summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCoprDistGit <infra@openeuler.org>2024-08-03 06:28:41 +0000
committerCoprDistGit <infra@openeuler.org>2024-08-03 06:28:41 +0000
commitd20db0561a6a36f914fde030512503b114ef9a0c (patch)
treed4e5e3494d95c269a1cee6195f11bf3201bcadbf
parent016343d99b1b269d7246ef1e143d4b54914433d4 (diff)
-rw-r--r--.gitignore2
-rw-r--r--0001-add-base-files-for-libphtread-condition-family.patch2321
-rw-r--r--0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch1206
-rw-r--r--0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch312
-rw-r--r--0002-add-header-files-for-libphtread_2_17_so.patch2609
-rw-r--r--0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch1177
-rw-r--r--0002-elf-ld.so-keep-compatible-with-the-original-policy-o.patch34
-rw-r--r--0003-add-build-script-and-files-of-libpthread_2_17_so.patch135
-rw-r--r--0003-elf-ld.so-remove-_mmap_hole-when-ld.so-mmap-PT_LOAD-.patch84
-rw-r--r--0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch69
-rw-r--r--0004-add-two-header-files-with-some-deleted-macros.patch166
-rw-r--r--0005-add-pthread-functions_h.patch140
-rw-r--r--0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch587
-rw-r--r--0007-add-lowlevellock_2_17_c.patch68
-rw-r--r--0008-add-pause_nocancel_2_17.patch56
-rw-r--r--0009-add-unwind-with-longjmp.patch161
-rw-r--r--0009_nptl_2.17_adapt_for_bug_29029.patch248
-rw-r--r--1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch136
-rw-r--r--1_6-LoongArch-Optimize-string-functions-memcpy-memmove.patch693
-rw-r--r--2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch131
-rw-r--r--2_6-LoongArch-Optimize-string-functions-strchr-strchrnul.patch250
-rw-r--r--3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch80
-rw-r--r--3_6-LoongArch-Optimize-string-function-memset.patch190
-rw-r--r--4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch51
-rw-r--r--4_6-LoongArch-Optimize-string-functions-strcmp-strncmp.patch414
-rw-r--r--5-5-AArch64-Improve-A64FX-memset-medium-loops.patch96
-rw-r--r--5_6-LoongArch-Optimize-string-function-strcpy.patch195
-rw-r--r--6_6-LoongArch-Optimize-string-functions-strlen-strnlen.patch255
-rw-r--r--AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch55
-rw-r--r--AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch39
-rw-r--r--Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch216
-rw-r--r--Assume-only-FLAG_ELF_LIBC6-suport.patch658
-rw-r--r--Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch34
-rw-r--r--CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch125
-rw-r--r--CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch65
-rw-r--r--Check-the-validity-of-len-before-mmap.patch60
-rw-r--r--Disable-debuginfod-in-printer-tests-BZ-28757.patch57
-rw-r--r--Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch37
-rw-r--r--Fix-deadlock-when-pthread_atfork-handler-calls-pthre.patch754
-rw-r--r--Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch37
-rw-r--r--Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch399
-rw-r--r--Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch31
-rw-r--r--Fix-ununsed-fstatat64_time64_statx.patch41
-rw-r--r--Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch158
-rw-r--r--LanguageList196
-rw-r--r--LicenseList26
-rw-r--r--Linux-Avoid-closing-1-on-failure-in-__closefrom_fall.patch26
-rw-r--r--Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch53
-rw-r--r--Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch72
-rw-r--r--Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch498
-rw-r--r--Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch241
-rw-r--r--LoongArch-Add-missing-relocation-type-in-elf.h.patch71
-rw-r--r--LoongArch-Add-static-PIE-support.patch161
-rw-r--r--LoongArch-Fix-ptr-mangling-demangling-and-SHMLBA.patch158
-rw-r--r--LoongArch-Fix-the-condition-to-use-PC-relative-addre.patch179
-rw-r--r--LoongArch-Further-refine-the-condition-to-enable-sta.patch55
-rw-r--r--LoongArch-Port.patch11388
-rw-r--r--Remove-_dl_skip_args_internal-declaration.patch34
-rw-r--r--Remove-sysdeps-tls-macros.h.patch1810
-rw-r--r--Update-string-test-memmove.c-to-cover-16KB-copy.patch78
-rw-r--r--Use-__executable_start-as-the-lowest-address-for-pro.patch106
-rw-r--r--Use-support_open_dev_null_range-io-tst-closefrom-mis.patch212
-rw-r--r--aarch64-Make-elf_machine_-load_address-dynamic-robus.patch72
-rw-r--r--aarch64-Move-ld.so-_start-to-separate-file-and-drop-.patch188
-rw-r--r--add-GB18030-2022-charmap-BZ-30243.patch853
-rw-r--r--add-Wl-z-noseparate-code-for-so.patch29
-rw-r--r--add-pthread_cond_clockwait-GLIBC_2_28.patch66
-rw-r--r--arm-Simplify-elf_machine_-load_address-dynamic.patch82
-rw-r--r--backport-Add-TEST_COMPARE_STRING_WIDE-to-support-check.h.patch757
-rw-r--r--backport-Add-codepoint_collation-support-for-LC_COLLATE.patch994
-rw-r--r--backport-Avoid-use-of-atoi-in-some-places-in-libc.patch120
-rw-r--r--backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch146
-rw-r--r--backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch39
-rw-r--r--backport-CVE-2023-4806.patch149
-rw-r--r--backport-CVE-2023-4813.patch285
-rw-r--r--backport-CVE-2023-4911.patch158
-rw-r--r--backport-CVE-2023-5156.patch29
-rw-r--r--backport-CVE-2024-33599-nscd-Stack-based-buffer-overflow-in-netgroup-cache.patch41
-rw-r--r--backport-CVE-2024-33600-nscd-Avoid-null-pointer-crash-after-not-found-response.patch63
-rw-r--r--backport-CVE-2024-33600-nscd-Do-not-send-missing-not-found-response.patch62
-rw-r--r--backport-CVE-2024-33601-CVE-2024-33602-nscd-Use-two-buffer-in-addgetnetgrentX.patch393
-rw-r--r--backport-Fix-OOB-read-in-stdlib-thousand-grouping-parsing-BZ.patch62
-rw-r--r--backport-Fix-invalid-pointer-dereference-in-wcpcpy_chk.patch35
-rw-r--r--backport-Fix-invalid-pointer-dereference-in-wcscpy_chk.patch64
-rw-r--r--backport-Skip-unusable-entries-in-first-pass-in-prune_cache.patch93
-rw-r--r--backport-Use-errval-not-errno-to-guide-cache-update.patch49
-rw-r--r--backport-elf-Add-TLS-modid-reuse-test-for-bug-29039.patch209
-rw-r--r--backport-elf-Check-objname-before-calling-fatal_error.patch35
-rw-r--r--backport-elf-Do-not-completely-clear-reused-namespace-in-dlmo.patch98
-rw-r--r--backport-elf-Fix-TLS-modid-reuse-generation-assignment-BZ-290.patch54
-rw-r--r--backport-elf-Fix-_dl_debug_vdprintf-to-work-before-self-reloc.patch137
-rw-r--r--backport-elf-Fix-alloca-size-in-_dl_debug_vdprintf.patch43
-rw-r--r--backport-elf-Fix-use-after-free-in-ldconfig-BZ-26779.patch31
-rw-r--r--backport-elf-Handle-non-directory-name-in-search-path-BZ-3103.patch220
-rw-r--r--backport-elf-Make-more-functions-available-for-binding-during.patch236
-rw-r--r--backport-elf-Properly-align-PT_LOAD-segments-BZ-28676.patch135
-rw-r--r--backport-elf-Remove-allocate-use-on-_dl_debug_printf.patch90
-rw-r--r--backport-elf-fix-handling-of-negative-numbers-in-dl-printf.patch57
-rw-r--r--backport-elf-ldconfig-should-skip-temporary-files-created-by-.patch76
-rw-r--r--backport-elf-tlsdeschtab.h-Add-the-Malloc-return-value-check.patch32
-rw-r--r--backport-gmon-fix-memory-corruption-issues-BZ-30101.patch194
-rw-r--r--backport-gmon-improve-mcount-overflow-handling-BZ-27576.patch424
-rw-r--r--backport-ldconfig-Fixes-for-skipping-temporary-files.patch68
-rw-r--r--backport-localedata-Adjust-C.UTF-8-to-align-with-C-POSIX.patch702
-rw-r--r--backport-localedef-Fix-handling-of-empty-mon_decimal_point-Bu.patch74
-rw-r--r--backport-mktime-improve-heuristic-for-ca-1986-Indiana-DST.patch78
-rw-r--r--backport-nscd-Fix-netlink-cache-invalidation-if-epoll-is-used.patch48
-rw-r--r--backport-nss_dns-In-gaih_getanswer_slice-skip-strange-aliases-bug-12154.patch58
-rw-r--r--backport-posix-Fix-some-crashes-in-wordexp-BZ-18096.patch86
-rw-r--r--backport-posix-Fix-system-blocks-SIGCHLD-erroneously-BZ-30163.patch290
-rw-r--r--backport-resolv-fix-non-existing-second-DNS-response-error.patch197
-rw-r--r--backport-resolv_conf-release-lock-on-allocation-failure-bug-30527.patch31
-rw-r--r--backport-rtld-properly-handle-root-directory-in-load-path-bug-30435.patch31
-rw-r--r--backport-stdlib-Undo-post-review-change-to-16adc58e73f3-BZ-27.patch140
-rw-r--r--backport-stdlib-fix-grouping-verification-with-multi-byte-tho.patch131
-rw-r--r--backport-string-strerror-must-not-return-NULL-bug-30555.patch141
-rw-r--r--backport-sunrpc-Suppress-GCC-Os-warning-on-user2netname.patch63
-rw-r--r--backport-x86-Fix-wcsnlen-avx2-page-cross-length-comparison-BZ.patch136
-rw-r--r--bench.mk77
-rw-r--r--copy_and_spawn_sgid-Avoid-double-calls-to-close.patch28
-rw-r--r--delete-check-installed-headers-c-and-check-installed.patch60
-rw-r--r--delete-no-hard-link-to-avoid-all_language-package-to.patch26
-rw-r--r--dlfcn-Do-not-use-rtld_active-to-determine-ld.so-stat.patch400
-rw-r--r--dlfcn-Pass-caller-pointer-to-static-dlopen-implement.patch31
-rw-r--r--elf-Add-a-comment-after-trailing-backslashes.patch49
-rw-r--r--elf-Add-a-way-to-check-if-tunable-is-set-BZ-27069.patch202
-rw-r--r--elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch482
-rw-r--r--elf-Call-__libc_early_init-for-reused-namespaces-bug.patch221
-rw-r--r--elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch543
-rw-r--r--elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch73
-rw-r--r--elf-Fix-DNDEBUG-warning-in-_dl_start_args_adjust.patch30
-rw-r--r--elf-Fix-compile-error-with-Werror-and-DNDEBUG.patch36
-rw-r--r--elf-Fix-hwcaps-string-size-overestimation.patch62
-rw-r--r--elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch313
-rw-r--r--elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch27
-rw-r--r--elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch544
-rw-r--r--elf-Replace-nsid-with-args.nsid-BZ-27609.patch50
-rw-r--r--elf-Restore-ldconfig-libc6-implicit-soname-logic-BZ-.patch214
-rw-r--r--elf-Sort-tests-and-modules-names.patch546
-rw-r--r--elf-Unconditionally-use-__ehdr_start.patch177
-rw-r--r--elf-ld.so-Consider-maybe-existing-hole-between-PT_LO.patch47
-rw-r--r--elf-ld.so-add-MAP_NORESERVE-flag-for-the-first-mmap-2MB-contig.patch33
-rw-r--r--elf-ld.so-prohibit-multiple-i-options-and-do-not-allow-i-speci.patch54
-rw-r--r--fix-CVE-2019-1010023.patch66
-rw-r--r--fix-Segmentation-fault-in-nss-module.patch40
-rw-r--r--fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch55
-rw-r--r--fix_nss_database_check_reload_and_get_memleak.patch38
-rw-r--r--gaiconf_init-Avoid-double-free-in-label-and-preceden.patch36
-rw-r--r--gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch185
-rw-r--r--gconv_parseconfdir-Fix-memory-leak.patch37
-rw-r--r--getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch355
-rw-r--r--gethosts-Remove-unused-argument-_type.patch44
-rw-r--r--glibc-1070416.patch38
-rw-r--r--glibc-bench-compare153
-rw-r--r--glibc.spec2284
-rw-r--r--gmon-Fix-allocated-buffer-overflow-bug-29444.patch79
-rw-r--r--i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch463
-rw-r--r--iconv-ISO-2022-CN-EXT-fix-out-of-bound-writes-when-w.patch214
-rw-r--r--iconv_charmap-Close-output-file-when-done.patch26
-rw-r--r--iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch123
-rw-r--r--inet-fix-warn-unused-result.patch41
-rw-r--r--intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch42
-rw-r--r--io-Do-not-implement-fstat-with-fstatat.patch165
-rw-r--r--io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch210
-rw-r--r--io-Fix-use-after-free-in-ftw-BZ-26779.patch29
-rw-r--r--ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch37
-rw-r--r--ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch124
-rw-r--r--ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch515
-rw-r--r--ldconfig-avoid-leak-on-empty-paths-in-config-file.patch30
-rw-r--r--libio-Ensure-output-buffer-for-wchars-bug-28828.patch110
-rw-r--r--libio-Flush-only-_IO_str_overflow-must-not-return-EO.patch54
-rw-r--r--linux-Add-a-getauxval-test-BZ-23293.patch114
-rw-r--r--linux-Fix-__closefrom_fallback-iterates-until-max-in.patch58
-rw-r--r--linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch457
-rw-r--r--linux-Fix-fchmodat-with-AT_SYMLINK_NOFOLLOW-for-64-b.patch139
-rw-r--r--linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch37
-rw-r--r--linux-Fix-mq_timereceive-check-for-32-bit-fallback-c.patch31
-rw-r--r--linux-Fix-posix_spawn-return-code-if-clone-fails-BZ-.patch28
-rw-r--r--linux-Only-build-fstatat-fallback-if-required.patch52
-rw-r--r--linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch206
-rw-r--r--linux-Simplify-get_nprocs.patch216
-rw-r--r--linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch102
-rw-r--r--linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch30
-rw-r--r--linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch212
-rw-r--r--linux-use-statx-for-fstat-if-neither-newfstatat-nor-.patch36
-rw-r--r--localedef-Handle-symbolic-links-when-generating-loca.patch33
-rw-r--r--login-Add-back-libutil-as-an-empty-library.patch42
-rw-r--r--malloc-Fix-Wuse-after-free-warning-in-tst-mallocalig.patch89
-rw-r--r--malloc-Fix-malloc-debug-for-2.35-onwards.patch57
-rw-r--r--malloc-Fix-transposed-arguments-in-sysmalloc_mmap_fa.patch37
-rw-r--r--malloc-Improve-MAP_HUGETLB-with-glibc.malloc.hugetlb.patch50
-rw-r--r--malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch532
-rw-r--r--malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch111
-rw-r--r--malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch205
-rw-r--r--malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch476
-rw-r--r--malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch338
-rw-r--r--malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch119
-rw-r--r--malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch86
-rw-r--r--malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch25
-rw-r--r--math-Fix-asin-and-acos-invalid-exception-with-old-gc.patch64
-rw-r--r--misc-Add-__get_nprocs_sched.patch110
-rw-r--r--mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch77
-rw-r--r--mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch61
-rw-r--r--nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch46
-rw-r--r--nptl-Add-one-more-barrier-to-nptl-tst-create1.patch67
-rw-r--r--nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch137
-rw-r--r--nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch111
-rw-r--r--nptl-Fix-___pthread_unregister_cancel_restore-asynch.patch29
-rw-r--r--nptl-Fix-pthread_cancel-cancelhandling-atomic-operat.patch38
-rw-r--r--nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch424
-rw-r--r--nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch37
-rw-r--r--nptl-Handle-spurious-EINTR-when-thread-cancellation-.patch869
-rw-r--r--nptl-pthread_kill-must-send-signals-to-a-specific-th.patch162
-rw-r--r--nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch142
-rw-r--r--nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch292
-rw-r--r--nscd.conf1
-rw-r--r--nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch81
-rw-r--r--nsswitch.conf56
-rw-r--r--posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch50
-rw-r--r--posix-glob.c-update-from-gnulib.patch195
-rw-r--r--pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch41
-rw-r--r--realpath-Avoid-overwriting-preexisting-error-CVE-2021-3998.patch33
-rw-r--r--realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch138
-rw-r--r--replace_same_file_to_hard_link.py98
-rw-r--r--riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch60
-rw-r--r--riscv-align-stack-in-clone-BZ-28702.patch35
-rw-r--r--rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch197
-rw-r--r--rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch48
-rw-r--r--rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch300
-rw-r--r--rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch692
-rw-r--r--rseq-nptl-Add-rseq-registration.patch1165
-rw-r--r--rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch141
-rw-r--r--rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch56
-rw-r--r--rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch935
-rw-r--r--rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch44
-rw-r--r--rt-Set-the-correct-message-queue-for-tst-mqueue10.patch35
-rw-r--r--rtld-Remove-DL_ARGV_NOT_RELRO-and-make-_dl_skip_args.patch299
-rw-r--r--rtld-Use-generic-argv-adjustment-in-ld.so-BZ-23293.patch305
-rw-r--r--rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch28
-rw-r--r--socket-Add-the-__sockaddr_un_set-function.patch174
-rw-r--r--socket-Do-not-use-AF_NETLINK-in-__opensock.patch40
-rw-r--r--socket-Fix-mistyped-define-statement-in-socket-sys-s.patch26
-rw-r--r--sources2
-rw-r--r--stdlib-Fix-formatting-of-tests-list-in-Makefile.patch178
-rw-r--r--stdlib-Sort-tests-in-Makefile.patch126
-rw-r--r--stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch176
-rw-r--r--strcmp-delete-align-for-loop_aligned.patch32
-rw-r--r--sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch89
-rw-r--r--support-Add-check-for-TID-zero-in-support_wait_for_t.patch42
-rw-r--r--support-Add-helpers-to-create-paths-longer-than-PATH.patch282
-rw-r--r--support-Add-support_open_dev_null_range.patch363
-rw-r--r--support-Add-support_socket_so_timestamp_time64.patch103
-rw-r--r--support-Add-support_wait_for_thread_exit.patch124
-rw-r--r--support-Also-return-fd-when-it-is-0.patch45
-rw-r--r--testsuite_whitelist138
-rw-r--r--time-Fix-overflow-itimer-tests-on-32-bit-systems.patch90
-rw-r--r--time-Fix-use-after-free-in-getdate.patch48
-rw-r--r--time-strftime_l-Avoid-an-unbounded-alloca.patch75
-rw-r--r--timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch45
-rw-r--r--timezone-handle-truncated-timezones-from-tzcode-2021.patch57
-rw-r--r--timezone-test-case-for-BZ-28707.patch138
-rw-r--r--tst-realpath-toolong-Fix-hurd-build.patch31
-rw-r--r--tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch29
-rw-r--r--turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch29
-rw-r--r--use-region-to-instead-of-country-for-extract-timezon.patch152
-rw-r--r--x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch267
-rw-r--r--x86-64-Use-testl-to-check-__x86_string_control.patch38
-rw-r--r--x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch67
-rw-r--r--x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch132
-rw-r--r--x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch37
-rw-r--r--x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch40
-rw-r--r--x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch40
-rw-r--r--x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch147
-rw-r--r--x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch29
-rw-r--r--x86-fix-Autoconf-caching-of-instruction-support-chec.patch178
-rw-r--r--x86-use-default-cache-size-if-it-cannot-be-determine.patch61
-rw-r--r--x86-use-total-l3cache-for-non_temporal_threshold.patch74
-rw-r--r--x86_64-Simplify-elf_machine_-load_address-dynamic.patch55
278 files changed, 64504 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
index e69de29..19cad26 100644
--- a/.gitignore
+++ b/.gitignore
@@ -0,0 +1,2 @@
+/backport-Add-generic-C.UTF-8-locale-Bug-17318.patch
+/glibc-2.34.tar.xz
diff --git a/0001-add-base-files-for-libphtread-condition-family.patch b/0001-add-base-files-for-libphtread-condition-family.patch
new file mode 100644
index 0000000..9ca2225
--- /dev/null
+++ b/0001-add-base-files-for-libphtread-condition-family.patch
@@ -0,0 +1,2321 @@
+From 76a50749f7af5935ba3739e815aa6a16ae4440d1 Mon Sep 17 00:00:00 2001
+From: Ulrich Drepper <drepper@redhat.com>
+Date: Tue Nov 26 22:50:54 2002 +0000
+Subject: [PATCH 1/9] 0001
+
+since https://sourceware.org/git/?p=glibc.git;a=commit;h=ed19993b5b0d05d62cc883571519a67dae481a14
+delete pthread_condtion function.However, using these interfaces has better performance.
+Therefore, we add a subpacket to use these interfaces.
+you can use it by adding LD_PRELOAD=./libpthreadcond.so in front of your program (eg:
+LD_PRELOAD=./libpthreadcond.so ./test). use with-compat_2_17 to compile it.
+WARNING:2.17 version does not meet the posix standard, you should pay attention when using it.
+add pthread_cond_clockwait to prevent process hang up when libpthread-2.17 and libpthread-2.28 are used together.
+use pthread_cond_common to implement the public functions of pthread_cond_clockwait,pthread_cond_clockwait and pthread_cond_timedwait.
+
+Add some base files for the libpthread_condition family.
+Including but not limited to the following submission:
+6efd481484e
+a88c9263686
+76a50749f7a
+69431c9a21f
+5bd8a24966d
+
+---
+ nptl_2_17/cancellation_2_17.c | 60 ++
+ nptl_2_17/cleanup_compat_2_17.c | 50 ++
+ nptl_2_17/pthread_cond_broadcast_2_17.c | 101 +++
+ nptl_2_17/pthread_cond_destroy_2_17.c | 86 +++
+ nptl_2_17/pthread_cond_init_2_17.c | 49 ++
+ nptl_2_17/pthread_cond_signal_2_17.c | 84 +++
+ nptl_2_17/pthread_cond_wait_2_17.c | 329 ++++++++++
+ nptl_2_17/pthread_condattr_getclock_2_17.c | 28 +
+ nptl_2_17/pthread_condattr_getpshared_2_17.c | 28 +
+ nptl_2_17/pthread_condattr_init_2_17.c | 33 +
+ nptl_2_17/pthread_condattr_setclock_2_17.c | 45 ++
+ nptl_2_17/pthread_mutex_cond_lock_2_17.c | 21 +
+ nptl_2_17/pthread_mutex_lock_2_17.c | 652 +++++++++++++++++++
+ nptl_2_17/pthread_mutex_unlock_2_17.c | 361 ++++++++++
+ nptl_2_17/tpp_2_17.c | 195 ++++++
+ nptl_2_17/vars_2_17.c | 43 ++
+ 16 files changed, 2165 insertions(+)
+ create mode 100644 nptl_2_17/cancellation_2_17.c
+ create mode 100644 nptl_2_17/cleanup_compat_2_17.c
+ create mode 100644 nptl_2_17/pthread_cond_broadcast_2_17.c
+ create mode 100644 nptl_2_17/pthread_cond_destroy_2_17.c
+ create mode 100644 nptl_2_17/pthread_cond_init_2_17.c
+ create mode 100644 nptl_2_17/pthread_cond_signal_2_17.c
+ create mode 100644 nptl_2_17/pthread_cond_wait_2_17.c
+ create mode 100644 nptl_2_17/pthread_condattr_getclock_2_17.c
+ create mode 100644 nptl_2_17/pthread_condattr_getpshared_2_17.c
+ create mode 100644 nptl_2_17/pthread_condattr_init_2_17.c
+ create mode 100644 nptl_2_17/pthread_condattr_setclock_2_17.c
+ create mode 100644 nptl_2_17/pthread_mutex_cond_lock_2_17.c
+ create mode 100644 nptl_2_17/pthread_mutex_lock_2_17.c
+ create mode 100644 nptl_2_17/pthread_mutex_unlock_2_17.c
+ create mode 100644 nptl_2_17/tpp_2_17.c
+ create mode 100644 nptl_2_17/vars_2_17.c
+
+diff --git a/nptl_2_17/cancellation_2_17.c b/nptl_2_17/cancellation_2_17.c
+new file mode 100644
+index 00000000..5c9ce572
+--- /dev/null
++++ b/nptl_2_17/cancellation_2_17.c
+@@ -0,0 +1,60 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <setjmp.h>
++#include <stdlib.h>
++#include <futex-internal.h>
++
++int
++__pthread_enable_asynccancel (void)
++{
++ struct pthread *self = THREAD_SELF;
++
++ int oldval = THREAD_GETMEM (self, canceltype);
++ THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS);
++
++ int ch = THREAD_GETMEM (self, cancelhandling);
++
++ if (self->cancelstate == PTHREAD_CANCEL_ENABLE
++ && (ch & CANCELED_BITMASK)
++ && !(ch & EXITING_BITMASK)
++ && !(ch & TERMINATED_BITMASK))
++ {
++ THREAD_SETMEM (self, result, PTHREAD_CANCELED);
++ __do_cancel ();
++ }
++
++ return oldval;
++}
++libc_hidden_def (__pthread_enable_asynccancel)
++
++/* See the comment for __pthread_enable_asynccancel regarding
++ the AS-safety of this function. */
++void
++__pthread_disable_asynccancel (int oldtype)
++{
++ /* If asynchronous cancellation was enabled before we do not have
++ anything to do. */
++ if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS)
++ return;
++
++ struct pthread *self = THREAD_SELF;
++ self->canceltype = PTHREAD_CANCEL_DEFERRED;
++}
++libc_hidden_def (__pthread_disable_asynccancel)
+diff --git a/nptl_2_17/cleanup_compat_2_17.c b/nptl_2_17/cleanup_compat_2_17.c
+new file mode 100644
+index 00000000..53cf903d
+--- /dev/null
++++ b/nptl_2_17/cleanup_compat_2_17.c
+@@ -0,0 +1,50 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <stdlib.h>
++
++
++void
++_pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg)
++{
++ struct pthread *self = THREAD_SELF;
++
++ buffer->__routine = routine;
++ buffer->__arg = arg;
++ buffer->__prev = THREAD_GETMEM (self, cleanup);
++
++ THREAD_SETMEM (self, cleanup, buffer);
++}
++strong_alias (_pthread_cleanup_push, __pthread_cleanup_push)
++
++
++void
++_pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer, int execute)
++{
++ struct pthread *self __attribute ((unused)) = THREAD_SELF;
++
++ THREAD_SETMEM (self, cleanup, buffer->__prev);
++
++ /* If necessary call the cleanup routine after we removed the
++ current cleanup block from the list. */
++ if (execute)
++ buffer->__routine (buffer->__arg);
++}
++strong_alias (_pthread_cleanup_pop, __pthread_cleanup_pop)
+diff --git a/nptl_2_17/pthread_cond_broadcast_2_17.c b/nptl_2_17/pthread_cond_broadcast_2_17.c
+new file mode 100644
+index 00000000..df39c99b
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_broadcast_2_17.c
+@@ -0,0 +1,101 @@
++/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "kernel-features_2_17.h"
++#include "pthread_2_17.h"
++#include "pthreadP_2_17.h"
++
++#include <endian.h>
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++#include <stap-probe.h>
++#include <atomic.h>
++
++#include <shlib-compat.h>
++
++#include <old_macros_2_17.h>
++
++/* We do the following steps from __pthread_cond_signal in one critical
++ section: (1) signal all waiters in G1, (2) close G1 so that it can become
++ the new G2 and make G2 the new G1, and (3) signal all waiters in the new
++ G1. We don't need to do all these steps if there are no waiters in G1
++ and/or G2. See __pthread_cond_signal for further details. */
++int
++__pthread_cond_broadcast (pthread_cond_t *cond)
++{
++ LIBC_PROBE (cond_broadcast, 1, cond);
++
++ int pshared = (cond->__data.__mutex == (void *) ~0l)
++ ? LLL_SHARED : LLL_PRIVATE;
++ /* Make sure we are alone. */
++ lll_lock (cond->__data.__lock, pshared);
++
++ /* Are there any waiters to be woken? */
++ if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
++
++ {
++ /* Yes. Mark them all as woken. */
++ cond->__data.__wakeup_seq = cond->__data.__total_seq;
++ cond->__data.__woken_seq = cond->__data.__total_seq;
++ cond->__data.__futex = (unsigned int) cond->__data.__total_seq * 2;
++ int futex_val = cond->__data.__futex;
++ /* Signal that a broadcast happened. */
++ ++cond->__data.__broadcast_seq;
++
++ /* We are done. */
++ lll_unlock (cond->__data.__lock, pshared);
++
++ /* Wake everybody. */
++ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
++
++ /* Do not use requeue for pshared condvars. */
++ if (mut == (void *) ~0l
++ || PTHREAD_MUTEX_PSHARED (mut) & PTHREAD_MUTEX_PSHARED_BIT)
++ goto wake_all;
++
++#if (defined lll_futex_cmp_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++ if (USE_REQUEUE_PI (mut))
++ {
++ if (lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, INT_MAX,
++ &mut->__data.__lock, futex_val,
++ LLL_PRIVATE) == 0)
++ return 0;
++ }
++ else
++#endif
++ /* lll_futex_requeue returns 0 for success and non-zero
++ for errors. */
++ if (!__builtin_expect (lll_futex_requeue (&cond->__data.__futex, 1,
++ INT_MAX, &mut->__data.__lock,
++ futex_val, LLL_PRIVATE), 0))
++ return 0;
++
++wake_all:
++ lll_futex_wake (&cond->__data.__futex, INT_MAX, pshared);
++ return 0;
++ }
++ /* We are done. */
++ lll_unlock (cond->__data.__lock, pshared);
++
++ return 0;
++}
++
++versioned_symbol (libpthread, __pthread_cond_broadcast, pthread_cond_broadcast,
++ GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_destroy_2_17.c b/nptl_2_17/pthread_cond_destroy_2_17.c
+new file mode 100644
+index 00000000..6342f471
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_destroy_2_17.c
+@@ -0,0 +1,86 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <errno.h>
++#include <shlib-compat.h>
++#include <stap-probe.h>
++#include <old_macros_2_17.h>
++int
++__pthread_cond_destroy (pthread_cond_t *cond)
++{
++ int pshared = (cond->__data.__mutex == (void *) ~0l)
++ ? LLL_SHARED : LLL_PRIVATE;
++
++ LIBC_PROBE (cond_destroy, 1, cond);
++
++ /* Make sure we are alone. */
++ lll_lock (cond->__data.__lock, pshared);
++
++ if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
++ {
++ /* If there are still some waiters which have not been
++ woken up, this is an application bug. */
++ lll_unlock (cond->__data.__lock, pshared);
++ return EBUSY;
++ }
++
++ /* Tell pthread_cond_*wait that this condvar is being destroyed. */
++ cond->__data.__total_seq = -1ULL;
++
++ /* If there are waiters which have been already signalled or
++ broadcasted, but still are using the pthread_cond_t structure,
++ pthread_cond_destroy needs to wait for them. */
++ unsigned int nwaiters = cond->__data.__nwaiters;
++
++ if (nwaiters >= (1 << COND_NWAITERS_SHIFT))
++
++ {
++ /* Wake everybody on the associated mutex in case there are
++ threads that have been requeued to it.
++ Without this, pthread_cond_destroy could block potentially
++ for a long time or forever, as it would depend on other
++ thread's using the mutex.
++ When all threads waiting on the mutex are woken up, pthread_cond_wait
++ only waits for threads to acquire and release the internal
++ condvar lock. */
++ if (cond->__data.__mutex != NULL
++ && cond->__data.__mutex != (void *) ~0l)
++ {
++ pthread_mutex_t *mut = (pthread_mutex_t *) cond->__data.__mutex;
++ lll_futex_wake (&mut->__data.__lock, INT_MAX,
++ PTHREAD_MUTEX_PSHARED (mut));
++ }
++
++ do
++ {
++ lll_unlock (cond->__data.__lock, pshared);
++
++ lll_futex_wait (&cond->__data.__nwaiters, nwaiters, pshared);
++
++ lll_lock (cond->__data.__lock, pshared);
++
++ nwaiters = cond->__data.__nwaiters;
++ }
++ while (nwaiters >= (1 << COND_NWAITERS_SHIFT));
++ }
++
++ return 0;
++}
++versioned_symbol (libpthread, __pthread_cond_destroy,
++ pthread_cond_destroy, GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_init_2_17.c b/nptl_2_17/pthread_cond_init_2_17.c
+new file mode 100644
+index 00000000..d590d1d0
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_init_2_17.c
+@@ -0,0 +1,49 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <shlib-compat.h>
++#include <stap-probe.h>
++
++
++int
++__pthread_cond_init (pthread_cond_t *cond, const pthread_condattr_t *cond_attr)
++{
++ ASSERT_TYPE_SIZE (pthread_cond_t, __SIZEOF_PTHREAD_COND_T);
++
++ struct pthread_condattr *icond_attr = (struct pthread_condattr *) cond_attr;
++
++ cond->__data.__lock = LLL_LOCK_INITIALIZER;
++ cond->__data.__futex = 0;
++ cond->__data.__nwaiters = (icond_attr != NULL
++ ? ((icond_attr->value >> 1) & ((1 << COND_NWAITERS_SHIFT) - 1))
++ : CLOCK_REALTIME);
++ cond->__data.__total_seq = 0;
++ cond->__data.__wakeup_seq = 0;
++ cond->__data.__woken_seq = 0;
++ cond->__data.__mutex = (icond_attr == NULL || (icond_attr->value & 1) == 0
++ ? NULL : (void *) ~0l);
++ cond->__data.__broadcast_seq = 0;
++
++
++ LIBC_PROBE (cond_init, 2, cond, cond_attr);
++
++ return 0;
++}
++versioned_symbol (libpthread, __pthread_cond_init,
++ pthread_cond_init, GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_signal_2_17.c b/nptl_2_17/pthread_cond_signal_2_17.c
+new file mode 100644
+index 00000000..e6f08ac8
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_signal_2_17.c
+@@ -0,0 +1,84 @@
++/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "kernel-features_2_17.h"
++#include "pthread_2_17.h"
++#include "pthreadP_2_17.h"
++
++#include <endian.h>
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++
++#include <shlib-compat.h>
++#include <stap-probe.h>
++
++#include <old_macros_2_17.h>
++
++int
++__pthread_cond_signal (pthread_cond_t *cond)
++{
++ int pshared = (cond->__data.__mutex == (void *) ~0l)
++ ? LLL_SHARED : LLL_PRIVATE;
++
++ LIBC_PROBE (cond_signal, 1, cond);
++
++ /* Make sure we are alone. */
++ lll_lock (cond->__data.__lock, pshared);
++
++ /* Are there any waiters to be woken? */
++ if (cond->__data.__total_seq > cond->__data.__wakeup_seq)
++ {
++ /* Yes. Mark one of them as woken. */
++ ++cond->__data.__wakeup_seq;
++ ++cond->__data.__futex;
++
++#if (defined lll_futex_cmp_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++ pthread_mutex_t *mut = cond->__data.__mutex;
++
++ if (USE_REQUEUE_PI (mut)
++ /* This can only really fail with a ENOSYS, since nobody can modify
++ futex while we have the cond_lock. */
++ && lll_futex_cmp_requeue_pi (&cond->__data.__futex, 1, 0,
++ &mut->__data.__lock,
++ cond->__data.__futex, pshared) == 0)
++ {
++ lll_unlock (cond->__data.__lock, pshared);
++ return 0;
++ }
++ else
++#endif
++ /* Wake one. */
++ if (! __builtin_expect (lll_futex_wake_unlock (&cond->__data.__futex,
++ 1, 1,
++ &cond->__data.__lock,
++ pshared), 0))
++ return 0;
++
++ /* Fallback if neither of them work. */
++ lll_futex_wake (&cond->__data.__futex, 1, pshared);
++ }
++/* We are done. */
++ lll_unlock (cond->__data.__lock, pshared);
++
++ return 0;
++}
++
++versioned_symbol (libpthread, __pthread_cond_signal, pthread_cond_signal,
++ GLIBC_2_3_2);
+diff --git a/nptl_2_17/pthread_cond_wait_2_17.c b/nptl_2_17/pthread_cond_wait_2_17.c
+new file mode 100644
+index 00000000..ff651a00
+--- /dev/null
++++ b/nptl_2_17/pthread_cond_wait_2_17.c
+@@ -0,0 +1,329 @@
++/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Martin Schwidefsky <schwidefsky@de.ibm.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "kernel-features_2_17.h"
++#include "pthread_2_17.h"
++#include "pthreadP_2_17.h"
++
++#include <endian.h>
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++#include <sys/time.h>
++#include <futex-internal.h>
++
++#include <shlib-compat.h>
++#include <stap-probe.h>
++
++#include <old_macros_2_17.h>
++
++struct _condvar_cleanup_buffer
++{
++ int oldtype;
++ pthread_cond_t *cond;
++ pthread_mutex_t *mutex;
++ unsigned int bc_seq;
++};
++
++void
++__attribute__ ((visibility ("hidden")))
++__condvar_cleanup (void *arg)
++{
++ struct _condvar_cleanup_buffer *cbuffer =
++ (struct _condvar_cleanup_buffer *) arg;
++ unsigned int destroying;
++ int pshared = (cbuffer->cond->__data.__mutex == (void *) ~0l)
++ ? LLL_SHARED : LLL_PRIVATE;
++
++ /* We are going to modify shared data. */
++ lll_lock (cbuffer->cond->__data.__lock, pshared);
++
++ if (cbuffer->bc_seq == cbuffer->cond->__data.__broadcast_seq)
++ {
++ /* This thread is not waiting anymore. Adjust the sequence counters
++ * appropriately. We do not increment WAKEUP_SEQ if this would
++ * bump it over the value of TOTAL_SEQ. This can happen if a thread
++ * was woken and then canceled. */
++ if (cbuffer->cond->__data.__wakeup_seq
++ < cbuffer->cond->__data.__total_seq)
++ {
++ ++cbuffer->cond->__data.__wakeup_seq;
++ ++cbuffer->cond->__data.__futex;
++ }
++ ++cbuffer->cond->__data.__woken_seq;
++ }
++
++ cbuffer->cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
++
++ /* If pthread_cond_destroy was called on this variable already,
++ notify the pthread_cond_destroy caller all waiters have left
++ and it can be successfully destroyed. */
++ destroying = 0;
++ if (cbuffer->cond->__data.__total_seq == -1ULL
++ && cbuffer->cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
++ {
++ lll_futex_wake (&cbuffer->cond->__data.__nwaiters, 1, pshared);
++ destroying = 1;
++ }
++
++ /* We are done. */
++ lll_unlock (cbuffer->cond->__data.__lock, pshared);
++
++ /* Wake everybody to make sure no condvar signal gets lost. */
++ if (! destroying)
++ lll_futex_wake (&cbuffer->cond->__data.__futex, INT_MAX, pshared);
++
++ /* Get the mutex before returning unless asynchronous cancellation
++ is in effect. We don't try to get the mutex if we already own it. */
++ if (!(USE_REQUEUE_PI (cbuffer->mutex))
++ || ((cbuffer->mutex->__data.__lock & FUTEX_TID_MASK)
++ != THREAD_GETMEM (THREAD_SELF, tid)))
++ {
++ __pthread_mutex_cond_lock (cbuffer->mutex);
++ }
++ else
++ __pthread_mutex_cond_lock_adjust (cbuffer->mutex);
++}
++
++static __always_inline int
++__pthread_cond_wait_common (pthread_cond_t *cond, pthread_mutex_t *mutex,
++ clockid_t clockid,
++ const struct timespec *abstime)
++{
++ struct _pthread_cleanup_buffer buffer;
++ struct _condvar_cleanup_buffer cbuffer;
++ int result = 0;
++
++ int pshared = (cond->__data.__mutex == (void *) ~0l)
++ ? LLL_SHARED : LLL_PRIVATE;
++
++ #if (defined lll_futex_wait_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++ int pi_flag = 0;
++#endif
++ LIBC_PROBE (cond_wait, 2, cond, mutex);
++ /* clockid will already have been checked by
++ __pthread_cond_clockwait or pthread_condattr_setclock, or we
++ don't use it if abstime is NULL, so we don't need to check it
++ here. */
++ /* Make sure we are alone. */
++ lll_lock (cond->__data.__lock, pshared);
++
++ /* Now we can release the mutex. */
++ int err = __pthread_mutex_unlock_usercnt (mutex, 0);
++ if (__glibc_unlikely (err))
++ {
++ lll_unlock (cond->__data.__lock, pshared);
++ return err;
++ }
++
++ /* We have one new user of the condvar. */
++ ++cond->__data.__total_seq;
++ ++cond->__data.__futex;
++ cond->__data.__nwaiters += 1 << COND_NWAITERS_SHIFT;
++
++ /* Work around the fact that the kernel rejects negative timeout values
++ despite them being valid. */
++ if (abstime != NULL && __glibc_unlikely (abstime->tv_sec < 0))
++ goto timeout;
++
++ /* Remember the mutex we are using here. If there is already a
++ different address store this is a bad user bug. Do not store
++ anything for pshared condvars. */
++ if (cond->__data.__mutex != (void *) ~0l)
++ cond->__data.__mutex = mutex;
++
++ /* Prepare structure passed to cancellation handler. */
++ cbuffer.cond = cond;
++ cbuffer.mutex = mutex;
++
++ /* Before we block we enable cancellation. Therefore we have to
++ install a cancellation handler. */
++ __pthread_cleanup_push (&buffer, __condvar_cleanup, &cbuffer);
++
++ /* The current values of the wakeup counter. The "woken" counter
++ must exceed this value. */
++ unsigned long long int val;
++ unsigned long long int seq;
++ val = seq = cond->__data.__wakeup_seq;
++ /* Remember the broadcast counter. */
++ cbuffer.bc_seq = cond->__data.__broadcast_seq;
++
++ while (1)
++ {
++ unsigned int futex_val = cond->__data.__futex;
++
++ /* Prepare to wait. Release the condvar futex. */
++ lll_unlock (cond->__data.__lock, pshared);
++
++ /* Enable asynchronous cancellation. Required by the standard. */
++ cbuffer.oldtype = __pthread_enable_asynccancel ();
++
++#if (defined lll_futex_wait_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++ /* If pi_flag remained 1 then it means that we had the lock and the mutex
++ but a spurious waker raced ahead of us. Give back the mutex before
++ going into wait again. */
++ if (pi_flag)
++ {
++ __pthread_mutex_cond_lock_adjust (mutex);
++ __pthread_mutex_unlock_usercnt (mutex, 0);
++ }
++ pi_flag = USE_REQUEUE_PI (mutex);
++
++ if (pi_flag)
++ {
++ if (abstime == NULL)
++ {
++ err = lll_futex_wait_requeue_pi (&cond->__data.__futex,
++ futex_val, &mutex->__data.__lock,
++ pshared);
++ }
++ else
++ {
++ unsigned int clockbit = (clockid == CLOCK_REALTIME)
++ ? FUTEX_CLOCK_REALTIME : 0;
++
++ err = lll_futex_timed_wait_requeue_pi (&cond->__data.__futex,
++ futex_val, abstime, clockbit,
++ &mutex->__data.__lock,
++ pshared);
++ }
++ pi_flag = (err == 0);
++ }
++ else
++#endif
++ /* Wait until woken by signal or broadcast. */
++ {
++ if (abstime == NULL)
++ {
++ lll_futex_wait (&cond->__data.__futex, futex_val, pshared);
++ }
++ else
++ {
++ err = lll_futex_clock_wait_bitset (&cond->__data.__futex, futex_val,
++ clockid, abstime, pshared);
++ }
++ }
++ /* Disable asynchronous cancellation. */
++ __pthread_disable_asynccancel (cbuffer.oldtype);
++
++ /* We are going to look at shared data again, so get the lock. */
++ lll_lock (cond->__data.__lock, pshared);
++
++ /* If a broadcast happened, we are done. */
++ if (cbuffer.bc_seq != cond->__data.__broadcast_seq)
++ goto bc_out;
++
++ /* Check whether we are eligible for wakeup. */
++ val = cond->__data.__wakeup_seq;
++ if (val != seq && cond->__data.__woken_seq != val)
++ break;
++
++ /* Not woken yet. Maybe the time expired? */
++ if (abstime != NULL && __glibc_unlikely (err == -ETIMEDOUT))
++ {
++ timeout:
++ /* Yep. Adjust the counters. */
++ ++cond->__data.__wakeup_seq;
++ ++cond->__data.__futex;
++
++ /* The error value. */
++ result = ETIMEDOUT;
++ break;
++ }
++ }
++
++ /* Another thread woken up. */
++ ++cond->__data.__woken_seq;
++
++bc_out:
++ cond->__data.__nwaiters -= 1 << COND_NWAITERS_SHIFT;
++
++ /* If pthread_cond_destroy was called on this variable already,
++ notify the pthread_cond_destroy caller all waiters have left
++ and it can be successfully destroyed. */
++ if (cond->__data.__total_seq == -1ULL
++ && cond->__data.__nwaiters < (1 << COND_NWAITERS_SHIFT))
++ lll_futex_wake (&cond->__data.__nwaiters, 1, pshared);
++
++ /* We are done with the condvar. */
++ lll_unlock (cond->__data.__lock, pshared);
++
++ /* The cancellation handling is back to normal, remove the handler. */
++ __pthread_cleanup_pop (&buffer, 0);
++
++ /* Get the mutex before returning. */
++#if (defined lll_futex_wait_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++ if (pi_flag)
++ {
++ __pthread_mutex_cond_lock_adjust (mutex);
++ err = 0;
++ }
++ else
++#endif
++ err = __pthread_mutex_cond_lock (mutex);
++ return err ?: result;
++}
++/* See __pthread_cond_wait_common. */
++int
++__pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex)
++{
++ /* clockid is unused when abstime is NULL. */
++ return __pthread_cond_wait_common (cond, mutex, 0, NULL);
++}
++
++/* See __pthread_cond_wait_common. */
++int
++__pthread_cond_timedwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
++ const struct timespec *abstime)
++{
++ /* Check parameter validity. This should also tell the compiler that
++ it can assume that abstime is not NULL. */
++ if (abstime == NULL || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
++ return EINVAL;
++
++ clockid_t clockid = cond->__data.__nwaiters & 1;
++
++ return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
++}
++
++/* See __pthread_cond_wait_common. */
++int
++__pthread_cond_clockwait (pthread_cond_t *cond, pthread_mutex_t *mutex,
++ clockid_t clockid,
++ const struct timespec *abstime)
++{
++ /* Check parameter validity. This should also tell the compiler that
++ it can assume that abstime is not NULL. */
++ if (abstime == NULL || abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
++ return EINVAL;
++
++ if (!futex_abstimed_supported_clockid (clockid))
++ return EINVAL;
++
++ return __pthread_cond_wait_common (cond, mutex, clockid, abstime);
++}
++
++versioned_symbol (libpthread, __pthread_cond_wait, pthread_cond_wait,
++ GLIBC_2_3_2);
++versioned_symbol (libpthread, __pthread_cond_timedwait, pthread_cond_timedwait,
++ GLIBC_2_3_2);
++versioned_symbol (libpthread, __pthread_cond_clockwait, pthread_cond_clockwait,
++ GLIBC_2_34);
+diff --git a/nptl_2_17/pthread_condattr_getclock_2_17.c b/nptl_2_17/pthread_condattr_getclock_2_17.c
+new file mode 100644
+index 00000000..414a6856
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_getclock_2_17.c
+@@ -0,0 +1,28 @@
++/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++
++
++int
++pthread_condattr_getclock (const pthread_condattr_t *attr, clockid_t *clock_id)
++{
++ *clock_id = (((((const struct pthread_condattr *) attr)->value) >> 1)
++ & ((1 << COND_NWAITERS_SHIFT) - 1));
++ return 0;
++}
+diff --git a/nptl_2_17/pthread_condattr_getpshared_2_17.c b/nptl_2_17/pthread_condattr_getpshared_2_17.c
+new file mode 100644
+index 00000000..2b85506f
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_getpshared_2_17.c
+@@ -0,0 +1,28 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++
++
++int
++pthread_condattr_getpshared (const pthread_condattr_t *attr, int *pshared)
++{
++ *pshared = ((const struct pthread_condattr *) attr)->value & 1;
++
++ return 0;
++}
+diff --git a/nptl_2_17/pthread_condattr_init_2_17.c b/nptl_2_17/pthread_condattr_init_2_17.c
+new file mode 100644
+index 00000000..c2765e96
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_init_2_17.c
+@@ -0,0 +1,33 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <string.h>
++
++
++int
++__pthread_condattr_init (pthread_condattr_t *attr)
++{
++ ASSERT_TYPE_SIZE (pthread_condattr_t, __SIZEOF_PTHREAD_CONDATTR_T);
++ ASSERT_PTHREAD_INTERNAL_SIZE (pthread_condattr_t,
++ struct pthread_condattr);
++
++ memset (attr, '\0', sizeof (*attr));
++ return 0;
++}
++strong_alias (__pthread_condattr_init, pthread_condattr_init)
+diff --git a/nptl_2_17/pthread_condattr_setclock_2_17.c b/nptl_2_17/pthread_condattr_setclock_2_17.c
+new file mode 100644
+index 00000000..69c64dcb
+--- /dev/null
++++ b/nptl_2_17/pthread_condattr_setclock_2_17.c
+@@ -0,0 +1,45 @@
++/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <assert.h>
++#include <errno.h>
++#include <stdbool.h>
++#include <time.h>
++#include <sysdep.h>
++
++
++int
++pthread_condattr_setclock (pthread_condattr_t *attr, clockid_t clock_id)
++{
++ /* Only a few clocks are allowed. */
++ if (clock_id != CLOCK_MONOTONIC && clock_id != CLOCK_REALTIME)
++ /* If more clocks are allowed some day the storing of the clock ID
++ in the pthread_cond_t structure needs to be adjusted. */
++ return EINVAL;
++
++ /* Make sure the value fits in the bits we reserved. */
++ assert (clock_id < (1 << COND_NWAITERS_SHIFT));
++
++ int *valuep = &((struct pthread_condattr *) attr)->value;
++
++ *valuep = ((*valuep & ~(((1 << COND_NWAITERS_SHIFT) - 1) << 1))
++ | (clock_id << 1));
++
++ return 0;
++}
+diff --git a/nptl_2_17/pthread_mutex_cond_lock_2_17.c b/nptl_2_17/pthread_mutex_cond_lock_2_17.c
+new file mode 100644
+index 00000000..87734543
+--- /dev/null
++++ b/nptl_2_17/pthread_mutex_cond_lock_2_17.c
+@@ -0,0 +1,21 @@
++#include <pthreadP_2_17.h>
++
++#define LLL_MUTEX_LOCK(mutex) \
++ lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex))
++
++/* Not actually elided so far. Needed? */
++#define LLL_MUTEX_LOCK_ELISION(mutex) \
++ ({ lll_cond_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex)); 0; })
++
++#define LLL_MUTEX_TRYLOCK(mutex) \
++ lll_cond_trylock ((mutex)->__data.__lock)
++#define LLL_MUTEX_TRYLOCK_ELISION(mutex) LLL_MUTEX_TRYLOCK(mutex)
++
++/* We need to assume that there are other threads blocked on the futex.
++ See __pthread_mutex_lock_full for further details. */
++#define LLL_ROBUST_MUTEX_LOCK_MODIFIER FUTEX_WAITERS
++#define __pthread_mutex_lock __pthread_mutex_cond_lock
++#define __pthread_mutex_lock_full __pthread_mutex_cond_lock_full
++#define NO_INCR
++
++#include <nptl_2_17/pthread_mutex_lock_2_17.c>
+diff --git a/nptl_2_17/pthread_mutex_lock_2_17.c b/nptl_2_17/pthread_mutex_lock_2_17.c
+new file mode 100644
+index 00000000..b08a2472
+--- /dev/null
++++ b/nptl_2_17/pthread_mutex_lock_2_17.c
+@@ -0,0 +1,652 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <assert.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <sys/param.h>
++#include <not-cancel.h>
++#include <atomic.h>
++#include <lowlevellock.h>
++#include <stap-probe.h>
++
++#include <old_macros_2_17.h>
++#ifndef lll_lock_elision
++#define lll_lock_elision(lock, try_lock, private) ({ \
++ lll_lock (lock, private); 0; })
++#endif
++
++#ifndef lll_trylock_elision
++#define lll_trylock_elision(a,t) lll_trylock(a)
++#endif
++
++/* Some of the following definitions differ when pthread_mutex_cond_lock.c
++ includes this file. */
++#ifndef LLL_MUTEX_LOCK
++/* lll_lock with single-thread optimization. */
++static inline void
++lll_mutex_lock_optimized (pthread_mutex_t *mutex)
++{
++ /* The single-threaded optimization is only valid for private
++ mutexes. For process-shared mutexes, the mutex could be in a
++ shared mapping, so synchronization with another process is needed
++ even without any threads. If the lock is already marked as
++ acquired, POSIX requires that pthread_mutex_lock deadlocks for
++ normal mutexes, so skip the optimization in that case as
++ well. */
++ int private = PTHREAD_MUTEX_PSHARED (mutex);
++ if (private == LLL_PRIVATE && SINGLE_THREAD_P && mutex->__data.__lock == 0)
++ mutex->__data.__lock = 1;
++ else
++ lll_lock (mutex->__data.__lock, private);
++}
++# define LLL_MUTEX_LOCK(mutex) \
++ lll_lock ((mutex)->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex))
++# define LLL_MUTEX_LOCK_OPTIMIZED(mutex) lll_mutex_lock_optimized (mutex)
++# define LLL_MUTEX_TRYLOCK(mutex) \
++ lll_trylock ((mutex)->__data.__lock)
++# define LLL_ROBUST_MUTEX_LOCK_MODIFIER 0
++# define LLL_MUTEX_LOCK_ELISION(mutex) \
++ lll_lock_elision ((mutex)->__data.__lock, (mutex)->__data.__elision, \
++ PTHREAD_MUTEX_PSHARED (mutex))
++# define LLL_MUTEX_TRYLOCK_ELISION(mutex) \
++ lll_trylock_elision((mutex)->__data.__lock, (mutex)->__data.__elision, \
++ PTHREAD_MUTEX_PSHARED (mutex))
++# define PTHREAD_MUTEX_LOCK ___pthread_mutex_lock
++# define PTHREAD_MUTEX_VERSIONS 1
++#endif
++
++static int __pthread_mutex_lock_full (pthread_mutex_t *mutex)
++ __attribute_noinline__;
++
++int
++__pthread_mutex_lock (pthread_mutex_t *mutex)
++{
++ /* See concurrency notes regarding mutex type which is loaded from __kind
++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
++ unsigned int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
++
++ LIBC_PROBE (mutex_entry, 1, mutex);
++
++ if (__builtin_expect (type & ~(PTHREAD_MUTEX_KIND_MASK_NP
++ | PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
++ return __pthread_mutex_lock_full (mutex);
++
++ if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_NP))
++ {
++ FORCE_ELISION (mutex, goto elision);
++ simple:
++ /* Normal mutex. */
++ LLL_MUTEX_LOCK (mutex);
++ assert (mutex->__data.__owner == 0);
++ }
++#ifdef ENABLE_ELISION_SUPPORT
++ else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
++ {
++ elision: __attribute__((unused))
++ /* This case can never happen on a system without elision,
++ as the mutex type initialization functions will not
++ allow to set the elision flags. */
++ /* Don't record owner or users for elision case. This is a
++ tail call. */
++ return LLL_MUTEX_LOCK_ELISION (mutex);
++ }
++#endif
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_RECURSIVE_NP, 1))
++ {
++ /* Recursive mutex. */
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++
++ /* Check whether we already hold the mutex. */
++ if (mutex->__data.__owner == id)
++ {
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++
++ /* We have to get the mutex. */
++ LLL_MUTEX_LOCK (mutex);
++
++ assert (mutex->__data.__owner == 0);
++ mutex->__data.__count = 1;
++ }
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_ADAPTIVE_NP, 1))
++ {
++ if (! __is_smp)
++ goto simple;
++
++ if (LLL_MUTEX_TRYLOCK (mutex) != 0)
++ {
++ int cnt = 0;
++ int max_cnt = MIN (MAX_ADAPTIVE_COUNT,
++ mutex->__data.__spins * 2 + 10);
++ do
++ {
++ if (cnt++ >= max_cnt)
++ {
++ LLL_MUTEX_LOCK (mutex);
++ break;
++ }
++ atomic_spin_nop ();
++ }
++ while (LLL_MUTEX_TRYLOCK (mutex) != 0);
++
++ mutex->__data.__spins += (cnt - mutex->__data.__spins) / 8;
++ }
++ assert (mutex->__data.__owner == 0);
++ }
++ else
++ {
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++ assert (PTHREAD_MUTEX_TYPE (mutex) == PTHREAD_MUTEX_ERRORCHECK_NP);
++ /* Check whether we already hold the mutex. */
++ if (__glibc_unlikely (mutex->__data.__owner == id))
++ return EDEADLK;
++ goto simple;
++ }
++
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++
++ /* Record the ownership. */
++ mutex->__data.__owner = id;
++#ifndef NO_INCR
++ ++mutex->__data.__nusers;
++#endif
++
++ LIBC_PROBE (mutex_acquired, 1, mutex);
++
++ return 0;
++}
++
++static int
++__pthread_mutex_lock_full (pthread_mutex_t *mutex)
++{
++ int oldval;
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++
++ switch (PTHREAD_MUTEX_TYPE (mutex))
++ {
++ case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
++ case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ &mutex->__data.__list.__next);
++ /* We need to set op_pending before starting the operation. Also
++ see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++
++ oldval = mutex->__data.__lock;
++ /* This is set to FUTEX_WAITERS iff we might have shared the
++ FUTEX_WAITERS flag with other threads, and therefore need to keep it
++ set to avoid lost wake-ups. We have the same requirement in the
++ simple mutex algorithm.
++ We start with value zero for a normal mutex, and FUTEX_WAITERS if we
++ are building the special case mutexes for use from within condition
++ variables. */
++ unsigned int assume_other_futex_waiters = LLL_ROBUST_MUTEX_LOCK_MODIFIER;
++ while (1)
++ {
++ /* Try to acquire the lock through a CAS from 0 (not acquired) to
++ our TID | assume_other_futex_waiters. */
++ if (__glibc_likely (oldval == 0))
++ {
++ oldval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ id | assume_other_futex_waiters, 0);
++ if (__glibc_likely (oldval == 0))
++ break;
++ }
++
++ if ((oldval & FUTEX_OWNER_DIED) != 0)
++ {
++ /* The previous owner died. Try locking the mutex. */
++ int newval = id;
++#ifdef NO_INCR
++ /* We are not taking assume_other_futex_waiters into accoount
++ here simply because we'll set FUTEX_WAITERS anyway. */
++ newval |= FUTEX_WAITERS;
++#else
++ newval |= (oldval & FUTEX_WAITERS) | assume_other_futex_waiters;
++#endif
++
++ newval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ newval, oldval);
++
++ if (newval != oldval)
++ {
++ oldval = newval;
++ continue;
++ }
++
++ /* We got the mutex. */
++ mutex->__data.__count = 1;
++ /* But it is inconsistent unless marked otherwise. */
++ mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
++
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++
++ /* Note that we deliberately exit here. If we fall
++ through to the end of the function __nusers would be
++ incremented which is not correct because the old
++ owner has to be discounted. If we are not supposed
++ to increment __nusers we actually have to decrement
++ it here. */
++#ifdef NO_INCR
++ --mutex->__data.__nusers;
++#endif
++
++ return EOWNERDEAD;
++ }
++
++ /* Check whether we already hold the mutex. */
++ if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
++ {
++ int kind = PTHREAD_MUTEX_TYPE (mutex);
++ if (kind == PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. Also see comments at ENQUEUE_MUTEX. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ NULL);
++ return EDEADLK;
++ }
++
++ if (kind == PTHREAD_MUTEX_ROBUST_RECURSIVE_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ NULL);
++
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++ }
++
++ /* We cannot acquire the mutex nor has its owner died. Thus, try
++ to block using futexes. Set FUTEX_WAITERS if necessary so that
++ other threads are aware that there are potentially threads
++ blocked on the futex. Restart if oldval changed in the
++ meantime. */
++ if ((oldval & FUTEX_WAITERS) == 0)
++ {
++ if (atomic_compare_and_exchange_bool_acq (&mutex->__data.__lock,
++ oldval | FUTEX_WAITERS,
++ oldval)
++ != 0)
++ {
++ oldval = mutex->__data.__lock;
++ continue;
++ }
++ oldval |= FUTEX_WAITERS;
++ }
++
++ /* It is now possible that we share the FUTEX_WAITERS flag with
++ another thread; therefore, update assume_other_futex_waiters so
++ that we do not forget about this when handling other cases
++ above and thus do not cause lost wake-ups. */
++ assume_other_futex_waiters |= FUTEX_WAITERS;
++
++ /* Block using the futex and reload current lock value. */
++ lll_futex_wait (&mutex->__data.__lock, oldval,
++ PTHREAD_ROBUST_MUTEX_PSHARED (mutex));
++ oldval = mutex->__data.__lock;
++ }
++
++ /* We have acquired the mutex; check if it is still consistent. */
++ if (__builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
++ {
++ /* This mutex is now not recoverable. */
++ mutex->__data.__count = 0;
++ int private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
++ lll_unlock (mutex->__data.__lock, private);
++ /* FIXME This violates the mutex destruction requirements. See
++ __pthread_mutex_unlock_full. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ return ENOTRECOVERABLE;
++ }
++
++ mutex->__data.__count = 1;
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ break;
++
++ /* The PI support requires the Linux futex system call. If that's not
++ available, pthread_mutex_init should never have allowed the type to
++ be set. So it will get the default case for an invalid type. */
++#ifdef __NR_futex
++ case PTHREAD_MUTEX_PI_RECURSIVE_NP:
++ case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
++ {
++ int kind, robust;
++ {
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
++ kind = mutex_kind & PTHREAD_MUTEX_KIND_MASK_NP;
++ robust = mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
++ }
++
++ if (robust)
++ {
++ /* Note: robust PI futexes are signaled by setting bit 0. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ (void *) (((uintptr_t) &mutex->__data.__list.__next)
++ | 1));
++ /* We need to set op_pending before starting the operation. Also
++ see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ }
++
++ oldval = mutex->__data.__lock;
++
++ /* Check whether we already hold the mutex. */
++ if (__glibc_unlikely ((oldval & FUTEX_TID_MASK) == id))
++ {
++ if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ return EDEADLK;
++ }
++
++ if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
++ {
++ /* We do not need to ensure ordering wrt another memory
++ access. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++ }
++
++ int newval = id;
++# ifdef NO_INCR
++ newval |= FUTEX_WAITERS;
++# endif
++ oldval = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ newval, 0);
++
++ if (oldval != 0)
++ {
++ /* The mutex is locked. The kernel will now take care of
++ everything. */
++ int private = (robust
++ ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
++ : PTHREAD_MUTEX_PSHARED (mutex));
++ INTERNAL_SYSCALL_DECL (__err);
++ int e = INTERNAL_SYSCALL (futex, 4, &mutex->__data.__lock,
++ __lll_private_flag (FUTEX_LOCK_PI,
++ private), 1, 0);
++
++ if (INTERNAL_SYSCALL_ERROR_P (e)
++ && (INTERNAL_SYSCALL_ERRNO (e) == ESRCH
++ || INTERNAL_SYSCALL_ERRNO (e) == EDEADLK))
++ {
++ assert (INTERNAL_SYSCALL_ERRNO (e) != EDEADLK
++ || (kind != PTHREAD_MUTEX_ERRORCHECK_NP
++ && kind != PTHREAD_MUTEX_RECURSIVE_NP));
++ /* ESRCH can happen only for non-robust PI mutexes where
++ the owner of the lock died. */
++ assert (INTERNAL_SYSCALL_ERRNO (e, __err) != ESRCH || !robust);
++
++ /* Delay the thread indefinitely. */
++ while (1)
++ __pause_nocancel ();
++ }
++
++ oldval = mutex->__data.__lock;
++
++ assert (robust || (oldval & FUTEX_OWNER_DIED) == 0);
++ }
++
++ if (__glibc_unlikely (oldval & FUTEX_OWNER_DIED))
++ {
++ atomic_and (&mutex->__data.__lock, ~FUTEX_OWNER_DIED);
++
++ /* We got the mutex. */
++ mutex->__data.__count = 1;
++ /* But it is inconsistent unless marked otherwise. */
++ mutex->__data.__owner = PTHREAD_MUTEX_INCONSISTENT;
++
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX_PI (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++
++ /* Note that we deliberately exit here. If we fall
++ through to the end of the function __nusers would be
++ incremented which is not correct because the old owner
++ has to be discounted. If we are not supposed to
++ increment __nusers we actually have to decrement it here. */
++# ifdef NO_INCR
++ --mutex->__data.__nusers;
++# endif
++
++ return EOWNERDEAD;
++ }
++
++ if (robust
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_NOTRECOVERABLE, 0))
++ {
++ /* This mutex is now not recoverable. */
++ mutex->__data.__count = 0;
++
++ INTERNAL_SYSCALL_DECL (__err);
++ INTERNAL_SYSCALL (futex, 4, &mutex->__data.__lock,
++ __lll_private_flag (FUTEX_UNLOCK_PI,
++ PTHREAD_ROBUST_MUTEX_PSHARED (mutex)),
++ 0, 0);
++
++ /* To the kernel, this will be visible after the kernel has
++ acquired the mutex in the syscall. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ return ENOTRECOVERABLE;
++ }
++
++ mutex->__data.__count = 1;
++ if (robust)
++ {
++ /* We must not enqueue the mutex before we have acquired it.
++ Also see comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ ENQUEUE_MUTEX_PI (mutex);
++ /* We need to clear op_pending after we enqueue the mutex. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ }
++ }
++ break;
++#endif /* __NR_futex. */
++
++ case PTHREAD_MUTEX_PP_RECURSIVE_NP:
++ case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PP_NORMAL_NP:
++ case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
++ {
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int kind = atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_KIND_MASK_NP;
++
++ oldval = mutex->__data.__lock;
++
++ /* Check whether we already hold the mutex. */
++ if (mutex->__data.__owner == id)
++ {
++ if (kind == PTHREAD_MUTEX_ERRORCHECK_NP)
++ return EDEADLK;
++
++ if (kind == PTHREAD_MUTEX_RECURSIVE_NP)
++ {
++ /* Just bump the counter. */
++ if (__glibc_unlikely (mutex->__data.__count + 1 == 0))
++ /* Overflow of the counter. */
++ return EAGAIN;
++
++ ++mutex->__data.__count;
++
++ return 0;
++ }
++ }
++
++ int oldprio = -1, ceilval;
++ do
++ {
++ int ceiling = (oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK)
++ >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
++
++ if (__pthread_current_priority () > ceiling)
++ {
++ if (oldprio != -1)
++ __pthread_tpp_change_priority (oldprio, -1);
++ return EINVAL;
++ }
++
++ int retval = __pthread_tpp_change_priority (oldprio, ceiling);
++ if (retval)
++ return retval;
++
++ ceilval = ceiling << PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
++ oldprio = ceiling;
++
++ oldval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++#ifdef NO_INCR
++ ceilval | 2,
++#else
++ ceilval | 1,
++#endif
++ ceilval);
++
++ if (oldval == ceilval)
++ break;
++
++ do
++ {
++ oldval
++ = atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ ceilval | 2,
++ ceilval | 1);
++
++ if ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval)
++ break;
++
++ if (oldval != ceilval)
++ lll_futex_wait (&mutex->__data.__lock, ceilval | 2,
++ PTHREAD_MUTEX_PSHARED (mutex));
++ }
++ while (atomic_compare_and_exchange_val_acq (&mutex->__data.__lock,
++ ceilval | 2, ceilval)
++ != ceilval);
++ }
++ while ((oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK) != ceilval);
++
++ assert (mutex->__data.__owner == 0);
++ mutex->__data.__count = 1;
++ }
++ break;
++
++ default:
++ /* Correct code cannot set any other type. */
++ return EINVAL;
++ }
++
++ /* Record the ownership. */
++ mutex->__data.__owner = id;
++#ifndef NO_INCR
++ ++mutex->__data.__nusers;
++#endif
++
++ LIBC_PROBE (mutex_acquired, 1, mutex);
++
++ return 0;
++}
++#ifndef __pthread_mutex_lock
++weak_alias (__pthread_mutex_lock, pthread_mutex_lock)
++hidden_def (__pthread_mutex_lock)
++#endif
++
++
++#ifdef NO_INCR
++void
++__pthread_mutex_cond_lock_adjust (pthread_mutex_t *mutex)
++{
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int mutex_kind = atomic_load_relaxed (&(mutex->__data.__kind));
++ assert ((mutex_kind & PTHREAD_MUTEX_PRIO_INHERIT_NP) != 0);
++ assert ((mutex_kind & PTHREAD_MUTEX_ROBUST_NORMAL_NP) == 0);
++ assert ((mutex_kind & PTHREAD_MUTEX_PSHARED_BIT) == 0);
++
++ /* Record the ownership. */
++ pid_t id = THREAD_GETMEM (THREAD_SELF, tid);
++ mutex->__data.__owner = id;
++
++ if (mutex_kind == PTHREAD_MUTEX_PI_RECURSIVE_NP)
++ ++mutex->__data.__count;
++}
++#endif
+diff --git a/nptl_2_17/pthread_mutex_unlock_2_17.c b/nptl_2_17/pthread_mutex_unlock_2_17.c
+new file mode 100644
+index 00000000..00729d32
+--- /dev/null
++++ b/nptl_2_17/pthread_mutex_unlock_2_17.c
+@@ -0,0 +1,361 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <assert.h>
++#include <errno.h>
++#include <stdlib.h>
++#include <lowlevellock.h>
++#include <stap-probe.h>
++
++#include <old_macros_2_17.h>
++
++#ifndef lll_unlock_elision
++#define lll_unlock_elision(a,b,c) ({ lll_unlock (a,c); 0; })
++#endif
++
++static int
++__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
++ __attribute_noinline__;
++
++int
++attribute_hidden
++__pthread_mutex_unlock_usercnt (pthread_mutex_t *mutex, int decr)
++{
++ /* See concurrency notes regarding mutex type which is loaded from __kind
++ in struct __pthread_mutex_s in sysdeps/nptl/bits/thread-shared-types.h. */
++ int type = PTHREAD_MUTEX_TYPE_ELISION (mutex);
++ if (__builtin_expect (type &
++ ~(PTHREAD_MUTEX_KIND_MASK_NP|PTHREAD_MUTEX_ELISION_FLAGS_NP), 0))
++ return __pthread_mutex_unlock_full (mutex, decr);
++
++ if (__builtin_expect (type, PTHREAD_MUTEX_TIMED_NP)
++ == PTHREAD_MUTEX_TIMED_NP)
++ {
++ /* Always reset the owner field. */
++ normal:
++ mutex->__data.__owner = 0;
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock. */
++ lll_unlock (mutex->__data.__lock, PTHREAD_MUTEX_PSHARED (mutex));
++
++ LIBC_PROBE (mutex_release, 1, mutex);
++
++ return 0;
++ }
++ else if (__glibc_likely (type == PTHREAD_MUTEX_TIMED_ELISION_NP))
++ {
++ /* Don't reset the owner/users fields for elision. */
++ return lll_unlock_elision (mutex->__data.__lock, mutex->__data.__elision,
++ PTHREAD_MUTEX_PSHARED (mutex));
++ }
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_RECURSIVE_NP, 1))
++ {
++ /* Recursive mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++ goto normal;
++ }
++ else if (__builtin_expect (PTHREAD_MUTEX_TYPE (mutex)
++ == PTHREAD_MUTEX_ADAPTIVE_NP, 1))
++ goto normal;
++ else
++ {
++ /* Error checking mutex. */
++ assert (type == PTHREAD_MUTEX_ERRORCHECK_NP);
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
++ || ! lll_islocked (mutex->__data.__lock))
++ return EPERM;
++ goto normal;
++ }
++}
++
++
++static int
++__pthread_mutex_unlock_full (pthread_mutex_t *mutex, int decr)
++{
++ int newowner = 0;
++ int private;
++
++ switch (PTHREAD_MUTEX_TYPE (mutex))
++ {
++ case PTHREAD_MUTEX_ROBUST_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ == THREAD_GETMEM (THREAD_SELF, tid)
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ {
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return ENOTRECOVERABLE;
++
++ goto notrecoverable;
++ }
++
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++
++ goto robust;
++
++ case PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP:
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ != THREAD_GETMEM (THREAD_SELF, tid)
++ || ! lll_islocked (mutex->__data.__lock))
++ return EPERM;
++
++ /* If the previous owner died and the caller did not succeed in
++ making the state consistent, mark the mutex as unrecoverable
++ and make all waiters. */
++ if (__builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ notrecoverable:
++ newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
++
++ robust:
++ /* Remove mutex from the list. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ &mutex->__data.__list.__next);
++ /* We must set op_pending before we dequeue the mutex. Also see
++ comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ DEQUEUE_MUTEX (mutex);
++
++ mutex->__data.__owner = newowner;
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock by setting the lock to 0 (not acquired); if the lock had
++ FUTEX_WAITERS set previously, then wake any waiters.
++ The unlock operation must be the last access to the mutex to not
++ violate the mutex destruction requirements (see __lll_unlock). */
++ private = PTHREAD_ROBUST_MUTEX_PSHARED (mutex);
++ if (__glibc_unlikely ((atomic_exchange_rel (&mutex->__data.__lock, 0)
++ & FUTEX_WAITERS) != 0))
++ lll_futex_wake (&mutex->__data.__lock, 1, private);
++
++ /* We must clear op_pending after we release the mutex.
++ FIXME However, this violates the mutex destruction requirements
++ because another thread could acquire the mutex, destroy it, and
++ reuse the memory for something else; then, if this thread crashes,
++ and the memory happens to have a value equal to the TID, the kernel
++ will believe it is still related to the mutex (which has been
++ destroyed already) and will modify some other random object. */
++ __asm ("" ::: "memory");
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ break;
++
++ /* The PI support requires the Linux futex system call. If that's not
++ available, pthread_mutex_init should never have allowed the type to
++ be set. So it will get the default case for an invalid type. */
++#ifdef __NR_futex
++ case PTHREAD_MUTEX_PI_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++ goto continue_pi_non_robust;
++
++ case PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ == THREAD_GETMEM (THREAD_SELF, tid)
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ {
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return ENOTRECOVERABLE;
++
++ goto pi_notrecoverable;
++ }
++
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++
++ goto continue_pi_robust;
++
++ case PTHREAD_MUTEX_PI_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ADAPTIVE_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP:
++ case PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP:
++ if ((mutex->__data.__lock & FUTEX_TID_MASK)
++ != THREAD_GETMEM (THREAD_SELF, tid)
++ || ! lll_islocked (mutex->__data.__lock))
++ return EPERM;
++
++ /* If the previous owner died and the caller did not succeed in
++ making the state consistent, mark the mutex as unrecoverable
++ and make all waiters. */
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ if ((atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0
++ && __builtin_expect (mutex->__data.__owner
++ == PTHREAD_MUTEX_INCONSISTENT, 0))
++ pi_notrecoverable:
++ newowner = PTHREAD_MUTEX_NOTRECOVERABLE;
++
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ if ((atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP) != 0)
++ {
++ continue_pi_robust:
++ /* Remove mutex from the list.
++ Note: robust PI futexes are signaled by setting bit 0. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending,
++ (void *) (((uintptr_t) &mutex->__data.__list.__next)
++ | 1));
++ /* We must set op_pending before we dequeue the mutex. Also see
++ comments at ENQUEUE_MUTEX. */
++ __asm ("" ::: "memory");
++ DEQUEUE_MUTEX (mutex);
++ }
++
++ continue_pi_non_robust:
++ mutex->__data.__owner = newowner;
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock. Load all necessary mutex data before releasing the mutex
++ to not violate the mutex destruction requirements (see
++ lll_unlock). */
++ /* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++ int robust = atomic_load_relaxed (&(mutex->__data.__kind))
++ & PTHREAD_MUTEX_ROBUST_NORMAL_NP;
++ private = (robust
++ ? PTHREAD_ROBUST_MUTEX_PSHARED (mutex)
++ : PTHREAD_MUTEX_PSHARED (mutex));
++ /* Unlock the mutex using a CAS unless there are futex waiters or our
++ TID is not the value of __lock anymore, in which case we let the
++ kernel take care of the situation. Use release MO in the CAS to
++ synchronize with acquire MO in lock acquisitions. */
++ int l = atomic_load_relaxed (&mutex->__data.__lock);
++ do
++ {
++ if (((l & FUTEX_WAITERS) != 0)
++ || (l != THREAD_GETMEM (THREAD_SELF, tid)))
++ {
++ INTERNAL_SYSCALL_DECL (__err);
++ INTERNAL_SYSCALL (futex, 2, &mutex->__data.__lock,
++ __lll_private_flag (FUTEX_UNLOCK_PI, private));
++ break;
++ }
++ }
++ while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
++ &l, 0));
++
++ /* This happens after the kernel releases the mutex but violates the
++ mutex destruction requirements; see comments in the code handling
++ PTHREAD_MUTEX_ROBUST_NORMAL_NP. */
++ THREAD_SETMEM (THREAD_SELF, robust_head.list_op_pending, NULL);
++ break;
++#endif /* __NR_futex. */
++
++ case PTHREAD_MUTEX_PP_RECURSIVE_NP:
++ /* Recursive mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid))
++ return EPERM;
++
++ if (--mutex->__data.__count != 0)
++ /* We still hold the mutex. */
++ return 0;
++ goto pp;
++
++ case PTHREAD_MUTEX_PP_ERRORCHECK_NP:
++ /* Error checking mutex. */
++ if (mutex->__data.__owner != THREAD_GETMEM (THREAD_SELF, tid)
++ || (mutex->__data.__lock & ~ PTHREAD_MUTEX_PRIO_CEILING_MASK) == 0)
++ return EPERM;
++ /* FALLTHROUGH */
++
++ case PTHREAD_MUTEX_PP_NORMAL_NP:
++ case PTHREAD_MUTEX_PP_ADAPTIVE_NP:
++ /* Always reset the owner field. */
++ pp:
++ mutex->__data.__owner = 0;
++
++ if (decr)
++ /* One less user. */
++ --mutex->__data.__nusers;
++
++ /* Unlock. Use release MO in the CAS to synchronize with acquire MO in
++ lock acquisitions. */
++ int newval;
++ int oldval = atomic_load_relaxed (&mutex->__data.__lock);
++ do
++ {
++ newval = oldval & PTHREAD_MUTEX_PRIO_CEILING_MASK;
++ }
++ while (!atomic_compare_exchange_weak_release (&mutex->__data.__lock,
++ &oldval, newval));
++
++ if ((oldval & ~PTHREAD_MUTEX_PRIO_CEILING_MASK) > 1)
++ lll_futex_wake (&mutex->__data.__lock, 1,
++ PTHREAD_MUTEX_PSHARED (mutex));
++
++ int oldprio = newval >> PTHREAD_MUTEX_PRIO_CEILING_SHIFT;
++
++ LIBC_PROBE (mutex_release, 1, mutex);
++
++ return __pthread_tpp_change_priority (oldprio, -1);
++
++ default:
++ /* Correct code cannot set any other type. */
++ return EINVAL;
++ }
++
++ LIBC_PROBE (mutex_release, 1, mutex);
++ return 0;
++}
++
++
++int
++__pthread_mutex_unlock (pthread_mutex_t *mutex)
++{
++ return __pthread_mutex_unlock_usercnt (mutex, 1);
++}
++weak_alias (__pthread_mutex_unlock, pthread_mutex_unlock)
++hidden_def (__pthread_mutex_unlock)
+diff --git a/nptl_2_17/tpp_2_17.c b/nptl_2_17/tpp_2_17.c
+new file mode 100644
+index 00000000..45fff81a
+--- /dev/null
++++ b/nptl_2_17/tpp_2_17.c
+@@ -0,0 +1,195 @@
++/* Thread Priority Protect helpers.
++ Copyright (C) 2006-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Jakub Jelinek <jakub@redhat.com>, 2006.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <assert.h>
++#include <atomic.h>
++#include <errno.h>
++#include <sched.h>
++#include <stdlib.h>
++#include <atomic.h>
++
++
++int __sched_fifo_min_prio = -1;
++int __sched_fifo_max_prio = -1;
++
++/* We only want to initialize __sched_fifo_min_prio and __sched_fifo_max_prio
++ once. The standard solution would be similar to pthread_once, but then
++ readers would need to use an acquire fence. In this specific case,
++ initialization is comprised of just idempotent writes to two variables
++ that have an initial value of -1. Therefore, we can treat each variable as
++ a separate, at-least-once initialized value. This enables using just
++ relaxed MO loads and stores, but requires that consumers check for
++ initialization of each value that is to be used; see
++ __pthread_tpp_change_priority for an example.
++ */
++void
++__init_sched_fifo_prio (void)
++{
++ atomic_store_relaxed (&__sched_fifo_max_prio,
++ __sched_get_priority_max (SCHED_FIFO));
++ atomic_store_relaxed (&__sched_fifo_min_prio,
++ __sched_get_priority_min (SCHED_FIFO));
++}
++
++int
++__pthread_tpp_change_priority (int previous_prio, int new_prio)
++{
++ struct pthread *self = THREAD_SELF;
++ struct priority_protection_data *tpp = THREAD_GETMEM (self, tpp);
++ int fifo_min_prio = atomic_load_relaxed (&__sched_fifo_min_prio);
++ int fifo_max_prio = atomic_load_relaxed (&__sched_fifo_max_prio);
++
++ if (tpp == NULL)
++ {
++ /* See __init_sched_fifo_prio. We need both the min and max prio,
++ so need to check both, and run initialization if either one is
++ not initialized. The memory model's write-read coherence rule
++ makes this work. */
++ if (fifo_min_prio == -1 || fifo_max_prio == -1)
++ {
++ __init_sched_fifo_prio ();
++ fifo_min_prio = atomic_load_relaxed (&__sched_fifo_min_prio);
++ fifo_max_prio = atomic_load_relaxed (&__sched_fifo_max_prio);
++ }
++
++ size_t size = sizeof *tpp;
++ size += (fifo_max_prio - fifo_min_prio + 1)
++ * sizeof (tpp->priomap[0]);
++ tpp = calloc (size, 1);
++ if (tpp == NULL)
++ return ENOMEM;
++ tpp->priomax = fifo_min_prio - 1;
++ THREAD_SETMEM (self, tpp, tpp);
++ }
++
++ assert (new_prio == -1
++ || (new_prio >= fifo_min_prio
++ && new_prio <= fifo_max_prio));
++ assert (previous_prio == -1
++ || (previous_prio >= fifo_min_prio
++ && previous_prio <= fifo_max_prio));
++
++ int priomax = tpp->priomax;
++ int newpriomax = priomax;
++ if (new_prio != -1)
++ {
++ if (tpp->priomap[new_prio - fifo_min_prio] + 1 == 0)
++ return EAGAIN;
++ ++tpp->priomap[new_prio - fifo_min_prio];
++ if (new_prio > priomax)
++ newpriomax = new_prio;
++ }
++
++ if (previous_prio != -1)
++ {
++ if (--tpp->priomap[previous_prio - fifo_min_prio] == 0
++ && priomax == previous_prio
++ && previous_prio > new_prio)
++ {
++ int i;
++ for (i = previous_prio - 1; i >= fifo_min_prio; --i)
++ if (tpp->priomap[i - fifo_min_prio])
++ break;
++ newpriomax = i;
++ }
++ }
++
++ if (priomax == newpriomax)
++ return 0;
++
++ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */
++ lll_lock (self->lock, LLL_PRIVATE);
++
++ tpp->priomax = newpriomax;
++
++ int result = 0;
++
++ if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
++ {
++ if (__sched_getparam (self->tid, &self->schedparam) != 0)
++ result = errno;
++ else
++ self->flags |= ATTR_FLAG_SCHED_SET;
++ }
++
++ if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
++ {
++ self->schedpolicy = __sched_getscheduler (self->tid);
++ if (self->schedpolicy == -1)
++ result = errno;
++ else
++ self->flags |= ATTR_FLAG_POLICY_SET;
++ }
++
++ if (result == 0)
++ {
++ struct sched_param sp = self->schedparam;
++ if (sp.sched_priority < newpriomax || sp.sched_priority < priomax)
++ {
++ if (sp.sched_priority < newpriomax)
++ sp.sched_priority = newpriomax;
++
++ if (__sched_setscheduler (self->tid, self->schedpolicy, &sp) < 0)
++ result = errno;
++ }
++ }
++
++ lll_unlock (self->lock, LLL_PRIVATE);
++
++ return result;
++}
++
++int
++__pthread_current_priority (void)
++{
++ struct pthread *self = THREAD_SELF;
++ if ((self->flags & (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
++ == (ATTR_FLAG_POLICY_SET | ATTR_FLAG_SCHED_SET))
++ return self->schedparam.sched_priority;
++
++ int result = 0;
++
++ /* See CREATE THREAD NOTES in nptl/pthread_create.c. */
++ lll_lock (self->lock, LLL_PRIVATE);
++
++ if ((self->flags & ATTR_FLAG_SCHED_SET) == 0)
++ {
++ if (__sched_getparam (self->tid, &self->schedparam) != 0)
++ result = -1;
++ else
++ self->flags |= ATTR_FLAG_SCHED_SET;
++ }
++
++ if ((self->flags & ATTR_FLAG_POLICY_SET) == 0)
++ {
++ self->schedpolicy = __sched_getscheduler (self->tid);
++ if (self->schedpolicy == -1)
++ result = -1;
++ else
++ self->flags |= ATTR_FLAG_POLICY_SET;
++ }
++
++ if (result != -1)
++ result = self->schedparam.sched_priority;
++
++ lll_unlock (self->lock, LLL_PRIVATE);
++
++ return result;
++}
+diff --git a/nptl_2_17/vars_2_17.c b/nptl_2_17/vars_2_17.c
+new file mode 100644
+index 00000000..ae60c0f8
+--- /dev/null
++++ b/nptl_2_17/vars_2_17.c
+@@ -0,0 +1,43 @@
++/* Copyright (C) 2004-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <stdlib.h>
++#include <tls.h>
++#include <unistd.h>
++
++/* Default thread attributes for the case when the user does not
++ provide any. */
++struct pthread_attr __default_pthread_attr attribute_hidden;
++
++/* Mutex protecting __default_pthread_attr. */
++int __default_pthread_attr_lock = LLL_LOCK_INITIALIZER;
++
++/* Flag whether the machine is SMP or not. */
++int __is_smp attribute_hidden;
++
++#ifndef TLS_MULTIPLE_THREADS_IN_TCB
++/* Variable set to a nonzero value either if more than one thread runs or ran,
++ or if a single-threaded process is trying to cancel itself. See
++ nptl/descr.h for more context on the single-threaded process case. */
++int __pthread_multiple_threads attribute_hidden;
++#endif
++
++/* Table of the key information. */
++struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX]
++ __attribute__ ((nocommon));
++hidden_data_def (__pthread_keys)
+--
+2.30.0
+
diff --git a/0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch b/0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch
new file mode 100644
index 0000000..fdbdead
--- /dev/null
+++ b/0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch
@@ -0,0 +1,1206 @@
+From d3a58c218f2c1605499be11a4b3a21f8ef133180 Mon Sep 17 00:00:00 2001
+From: Lv Ying <lvying6@huawei.com>
+Date: Mon, 7 Mar 2022 03:28:33 +0000
+Subject: [PATCH] elf: dynamic linker load shared object use hugepage as much
+ as possible
+
+This patch provides environment variables HUGEPAGE_PROBE and LD_HUGEPAGE_LIB
+to enable load shared object use hugepage.
+
+When load shared object, ld.so first to map text PT_LOAD segment into 2MB
+hugepage area. And then, load the neighbor PT_LOAD segment use 2MB hugepage
+as much as possible. This means:
+* PT_LOAD segment's mapstart_va is 2MB aligned, howerver its maplenth is
+ less than 2MB, fallback to 4KB page
+* PT_LOAD segment's mapstart_va is 2MB aligned, and its maplenth is larger
+ than 2MB, the first 2MB aligned area use 2MB hugepage, the end area (if it exists) use 4KB area
+* PT_LOAD segment's mapstart_va is not 2MB aligned, alignup this address
+ to 2MB aligned address mapstart_align, if its maplenth is less than
+ mapstart_align - mapstart_va, or maplenth - (mapstart_align - mapstart_va), fallback to 4KB hugepage
+* PT_LOAD segment's mapstart_va is not 2MB aligned, maplenth - (mapstart_align - mapstart_va)
+ is still larger than 2MB, first map (mapstart_align - mapstart_va) as 4KB page
+ then map 2MB aligned area as hugepage, the end area (if it exists) use 4KB area
+---
+ config.h.in | 2 +
+ configure | 20 ++
+ configure.ac | 11 +
+ elf/Makefile | 8 +
+ elf/dl-environ.c | 11 +
+ elf/dl-load.c | 38 +++
+ elf/dl-load.h | 16 +
+ elf/dl-map-segments-hugepage.h | 593 +++++++++++++++++++++++++++++++++
+ elf/dl-support.c | 4 +
+ elf/elf.h | 2 +
+ elf/hugepageedit.c | 169 ++++++++++
+ elf/rtld.c | 63 ++++
+ sysdeps/generic/ldsodefs.h | 11 +-
+ 13 files changed, 947 insertions(+), 1 deletion(-)
+ create mode 100644 elf/dl-map-segments-hugepage.h
+ create mode 100644 elf/hugepageedit.c
+
+diff --git a/config.h.in b/config.h.in
+index db6402cd..13101496 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -277,6 +277,8 @@
+ /* Define if static PIE is supported. */
+ #undef SUPPORT_STATIC_PIE
+
++#undef HUGEPAGE_SHARED_LIB
++
+ /* Define if static PIE is enabled. */
+ #define ENABLE_STATIC_PIE 0
+
+diff --git a/configure b/configure
+index 7272fbf6..43993923 100755
+--- a/configure
++++ b/configure
+@@ -670,6 +670,7 @@ stack_protector
+ libc_cv_ssp
+ libc_cv_with_fp
+ base_machine
++enable_hugepage_shared_library
+ have_tunables
+ build_pt_chown
+ build_nscd
+@@ -791,6 +792,7 @@ enable_pt_chown
+ enable_tunables
+ enable_mathvec
+ enable_cet
++enable_hugepage_shared_library
+ enable_scv
+ with_cpu
+ '
+@@ -1464,6 +1466,9 @@ Optional Features:
+ depends on architecture]
+ --enable-cet enable Intel Control-flow Enforcement Technology
+ (CET), x86 only
++ --enable-hugepage-shared-library
++ enable shared library use huge page to decrease TLB
++ miss, x86_64 aarch64 only
+ --disable-scv syscalls will not use scv instruction, even if the
+ kernel supports it, powerpc only
+
+@@ -3830,6 +3835,21 @@ if test "$use_scv" != "no"; then :
+
+ fi
+
++# Check whether --enable-hugepage-shared-library was given.
++if test "${enable_hugepage_shared_library+set}" = set; then :
++ enableval=$enable_hugepage_shared_library; enable_hugepage_shared_library=$enableval
++else
++ enable_hugepage_shared_library=no
++fi
++
++
++config_vars="$config_vars
++enable-hugepage-shared-library = $enable_hugepage_shared_library"
++if test "$enable_hugepage_shared_library" = yes; then
++ $as_echo "#define HUGEPAGE_SHARED_LIB 1" >>confdefs.h
++
++fi
++
+ # We keep the original values in `$config_*' and never modify them, so we
+ # can write them unchanged into config.make. Everything else uses
+ # $machine, $vendor, and $os, and changes them whenever convenient.
+diff --git a/configure.ac b/configure.ac
+index af47cd51..27a48338 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -478,6 +478,17 @@ AC_ARG_ENABLE([scv],
+
+ AS_IF([[test "$use_scv" != "no"]],[AC_DEFINE(USE_PPC_SCV)])
+
++AC_ARG_ENABLE([hugepage-shared-library],
++ AC_HELP_STRING([--enable-hugepage-shared-library],
++ [enable shared library use huge page to decrease TLB miss, x86_64 aarch64 only]),
++ [enable_hugepage_shared_library=$enableval],
++ [enable_hugepage_shared_library=no])
++
++LIBC_CONFIG_VAR([enable-hugepage-shared-library], [$enable_hugepage_shared_library])
++if test "$enable_hugepage_shared_library" = yes; then
++ AC_DEFINE(HUGEPAGE_SHARED_LIB)
++fi
++
+ # We keep the original values in `$config_*' and never modify them, so we
+ # can write them unchanged into config.make. Everything else uses
+ # $machine, $vendor, and $os, and changes them whenever convenient.
+diff --git a/elf/Makefile b/elf/Makefile
+index 6fd515ba..32aba7ac 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -207,6 +207,14 @@ others-extras = $(ldconfig-modules)
+ endif
+ endif
+
++ifeq (yes,$(enable-hugepage-shared-library))
++others += hugepageedit
++others-pie += hugepageedit
++install-bin += hugepageedit
++
++$(objpfx)hugepageedit: $(objpfx)hugepageedit.o
++endif
++
+ # To find xmalloc.c and xstrdup.c
+ vpath %.c ../locale/programs
+
+diff --git a/elf/dl-environ.c b/elf/dl-environ.c
+index 31c1c09f..ac70c9ab 100644
+--- a/elf/dl-environ.c
++++ b/elf/dl-environ.c
+@@ -31,6 +31,17 @@ _dl_next_ld_env_entry (char ***position)
+
+ while (*current != NULL)
+ {
++#ifdef HUGEPAGE_SHARED_LIB
++ #define LEN_HUGEPAGE_PROBE (sizeof("HUGEPAGE_PROBE") - 1)
++ if (memcmp (*current, "HUGEPAGE_PROBE", LEN_HUGEPAGE_PROBE) == 0)
++ {
++ result = *current;
++
++ /* Save current position for next visit. */
++ *position = ++current;
++ break;
++ }
++#endif
+ if (__builtin_expect ((*current)[0] == 'L', 0)
+ && (*current)[1] == 'D' && (*current)[2] == '_')
+ {
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index 0976977f..f4b5c4a7 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -73,6 +73,9 @@ struct filebuf
+ #include <dl-sysdep-open.h>
+ #include <dl-prop.h>
+ #include <not-cancel.h>
++#ifdef HUGEPAGE_SHARED_LIB
++#include <dl-map-segments-hugepage.h>
++#endif
+
+ #include <endian.h>
+ #if BYTE_ORDER == BIG_ENDIAN
+@@ -1131,6 +1134,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ size_t nloadcmds = 0;
+ bool has_holes = false;
+ bool empty_dynamic = false;
++#ifdef HUGEPAGE_SHARED_LIB
++ bool use_hugepage = false;
++#endif
+
+ /* The struct is initialized to zero so this is not necessary:
+ l->l_ld = 0;
+@@ -1188,6 +1194,11 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ if (nloadcmds > 1 && c[-1].mapend != c->mapstart)
+ has_holes = true;
+
++#ifdef HUGEPAGE_SHARED_LIB
++ if (ph->p_flags & PF_HUGEPAGE)
++ use_hugepage = true;
++#endif
++
+ /* Optimize a common case. */
+ #if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
+ c->prot = (PF_TO_PROT
+@@ -1278,12 +1289,39 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ /* Length of the sections to be loaded. */
+ maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart;
+
++#ifdef HUGEPAGE_SHARED_LIB
++#define ERRSTRING_BUF_LEN 1024
++ int hp_errcode = 0;
++ char hp_buf[ERRSTRING_BUF_LEN];
++ if ((GLRO(dl_hugepage_mask) & DL_HUGEPAGE_LIB_LARGE_IN_FLAG) ||
++ ((GLRO(dl_hugepage_mask) & DL_HUGEPAGE_PROBE_FLAG) && use_hugepage))
++ {
++ errstring = _dl_map_segments_largein (l, fd, header, type, loadcmds, nloadcmds,
++ maplength, has_holes);
++ if (__glibc_unlikely (errstring != NULL))
++ {
++ hp_errcode = errno;
++ /* __strerror_r will set hp_buf last character '\0', hp_buf will not overflow */
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf ("_dl_map_segments_largein: %s, %s\n", errstring,
++ hp_errcode ? __strerror_r (hp_errcode, hp_buf, sizeof hp_buf) : "");
++ goto fallback;
++ }
++ }
++ else
++ {
++ fallback:
++ errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds,
++ maplength, has_holes, loader);
++ }
++#else
+ /* Now process the load commands and map segments into memory.
+ This is responsible for filling in:
+ l_map_start, l_map_end, l_addr, l_contiguous, l_text_end, l_phdr
+ */
+ errstring = _dl_map_segments (l, fd, header, type, loadcmds, nloadcmds,
+ maplength, has_holes, loader);
++#endif
+ if (__glibc_unlikely (errstring != NULL))
+ {
+ /* Mappings can be in an inconsistent state: avoid unmap. */
+diff --git a/elf/dl-load.h b/elf/dl-load.h
+index e329d49a..d3f69466 100644
+--- a/elf/dl-load.h
++++ b/elf/dl-load.h
+@@ -131,5 +131,21 @@ static const char *_dl_map_segments (struct link_map *l, int fd,
+ #define DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL \
+ N_("cannot map zero-fill pages")
+
++#ifdef HUGEPAGE_SHARED_LIB
++#define DL_MAP_SEGMENTS_ERROR_TYPE \
++ N_("cannot map Non shared object file in hugepage")
++#define DL_MAP_SEGMENTS_ERROR_READ_SEGMENT \
++ N_("failed to read shared object file")
++#define DL_MAP_SEGMENTS_ERROR_ARRANGE \
++ N_("shared object's PT_LOAD segment in wrong arrange")
++#define DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL \
++ N_("failed to mmap shared object's hole part of PT_LOAD")
++#define DL_MAP_RESERVED_HUGEPAGE_AREA_ERROR \
++ N_("failed to map reserved 2MB contiguous hugepage va space")
++#define DL_FIND_EXEC_SEGMENT_ERROR \
++ N_("fail to find exec prot segment")
++#define DL_MAP_SEGMENT_ERROR_EXTRA_SIZE \
++ N_("wrong segment extra size")
++#endif
+
+ #endif /* dl-load.h */
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+new file mode 100644
+index 00000000..cd7b6d79
+--- /dev/null
++++ b/elf/dl-map-segments-hugepage.h
+@@ -0,0 +1,593 @@
++/* Map a shared object's segments into hugepage. Generic version.
++ Copyright (C) 1995-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <dl-load.h>
++
++#define SHFIT_2MB 21
++#define SIZE_2MB 0x200000
++#define MASK_2MB 0x1FFFFF
++#define THRESHOLD 16
++
++/*
++ * Find the first PT_LOAD segment with execute permission
++ */
++static __always_inline const struct loadcmd *
++_find_exec_segment(const struct loadcmd loadcmds[], size_t nloadcmds)
++{
++ const struct loadcmd *c = loadcmds;
++
++ while (c < &loadcmds[nloadcmds])
++ {
++ if (c->prot & PROT_EXEC)
++ return c;
++ c++;
++ }
++ return NULL;
++}
++
++static __always_inline void *
++__mmap_reserved_area(const struct loadcmd loadcmds[], size_t nloadcmds,
++ size_t *maparealen)
++{
++ const struct loadcmd * c = loadcmds;
++ *maparealen = 0;
++
++ while (c < &loadcmds[nloadcmds])
++ {
++ *maparealen += ALIGN_UP((c->mapend > c->allocend ? c->mapend : c->allocend), SIZE_2MB) -
++ ALIGN_DOWN(c->mapstart, SIZE_2MB);
++ c++;
++ }
++
++ /*
++ * Get 2MB aligned contiguous va space
++ * This va space can not be munmap in case of multi thread dlopen concurrently
++ */
++ void *map_area_start = __mmap(0, *maparealen, PROT_NONE,
++ MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT), -1, 0);
++ if (__glibc_unlikely (map_area_start == MAP_FAILED))
++ return MAP_FAILED;
++
++ /*
++ * Remap 2MB aligned contiguous va space into 4KB contiguous va space
++ * to avoid the tedious work of splitting hugepage into 4KB page
++ */
++ if (__glibc_unlikely(__mmap(map_area_start, *maparealen, PROT_NONE,
++ MAP_PRIVATE|MAP_ANONYMOUS|MAP_FIXED, -1, 0)
++ == MAP_FAILED))
++ {
++ goto unmap_reserved_area;
++ }
++ return map_area_start;
++
++unmap_reserved_area:
++ __munmap(map_area_start, *maparealen);
++ return MAP_FAILED;
++}
++
++static __always_inline size_t
++_get_relro_len(struct link_map *l, const struct loadcmd *c)
++{
++ size_t relro_len = 0;
++ if (c->mapstart == ALIGN_DOWN (l->l_relro_addr, GLRO(dl_pagesize)))
++ {
++ relro_len = ALIGN_DOWN(l->l_relro_addr + l->l_relro_size, GLRO(dl_pagesize)) -
++ ALIGN_DOWN(l->l_relro_addr, GLRO(dl_pagesize));
++ }
++ return relro_len;
++}
++
++/*
++ * the alignment stands for the size of page which is to be cleared to zero
++ */
++static __always_inline const char *
++_zero_tail_page(const struct loadcmd *c, ElfW(Addr) zero, ElfW(Addr) zeropage,
++ size_t alignment)
++{
++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
++ {
++ /* Dag nab it. */
++ if (__mprotect ((caddr_t) ALIGN_DOWN(zero, alignment), alignment,
++ c->prot|PROT_WRITE) < 0)
++ return DL_MAP_SEGMENTS_ERROR_MPROTECT;
++ }
++ memset ((void *) zero, '\0', zeropage - zero);
++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
++ __mprotect ((caddr_t) ALIGN_DOWN(zero, alignment), alignment, c->prot);
++ return NULL;
++}
++
++static __always_inline const char *
++_mmap_remain_zero_page(ElfW(Addr) zeropage, ElfW(Addr) zeroend, int prot)
++{
++ ElfW(Addr) hp_start = ALIGN_UP(zeropage, SIZE_2MB);
++ size_t len = 0, mod = 0;
++ caddr_t mapat;
++
++ if (zeroend > hp_start && zeroend - hp_start >= SIZE_2MB)
++ {
++ len = zeroend - hp_start;
++ mod = len % SIZE_2MB;
++ }
++ else
++ hp_start = 0;
++
++ if (hp_start == 0)
++ {
++ mapat = __mmap((caddr_t) zeropage, zeroend - zeropage, prot,
++ MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
++ if (__glibc_unlikely (mapat == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
++ return NULL;
++ }
++
++ if (hp_start - zeropage > 0)
++ {
++ mapat = __mmap((caddr_t) zeropage, hp_start - zeropage,
++ prot, MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
++ if (__glibc_unlikely (mapat == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
++ }
++
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\t\t=> mmap anonymous hugepage: [%lx-%lx)\n", hp_start, hp_start + len - mod);
++ mapat = __mmap((caddr_t) hp_start, len - mod, prot,
++ MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT),
++ -1, 0);
++ if (__glibc_unlikely (mapat == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
++
++ if (mod > 0)
++ {
++ mapat =__mmap((caddr_t)(hp_start + len - mod), mod, prot,
++ MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0);
++ if (__glibc_unlikely (mapat == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
++ }
++
++ return NULL;
++}
++
++/*
++ * memsz_len records the remain memsiz part
++ */
++static __always_inline const char *
++_mmap_segment_memsz(struct link_map *l, const struct loadcmd * c,
++ ElfW(Addr) mapstart, size_t extra_len, size_t *memsz_len)
++{
++ const char * errstring = NULL;
++
++ /* Extra zero pages should appear at the end of this segment,
++ after the data mapped from the file. */
++ ElfW(Addr) zero, zeroend, zeropage;
++
++ zero = mapstart + c->dataend - c->mapstart;
++ zeroend = mapstart + c->allocend - c->mapstart;
++ zeropage = ALIGN_UP(zero, GLRO(dl_pagesize));
++ size_t alignment = GLRO(dl_pagesize);
++ *memsz_len = 0;
++
++ /*
++ * no matter what the extra space consists of:
++ * 1. all the extra space is initialized data area (MemSiz > FileSiz)
++ * 2. initialized data area and hole
++ * 3. all the extra space is hole (MemSiz == FileSiz)
++ *
++ * the extra space just needs to be set zero, for the initialized data area, it's
++ * initialized to zero; for the hole area, it's initialized to invalid instruction
++ */
++ if (extra_len > 0)
++ {
++ if (__glibc_unlikely(zeropage == ALIGN_UP(zero, SIZE_2MB) ||
++ zeropage + extra_len != ALIGN_UP(zero, SIZE_2MB)))
++ return DL_MAP_SEGMENT_ERROR_EXTRA_SIZE;
++
++ zeropage = ALIGN_UP(zero, SIZE_2MB);
++ alignment = SIZE_2MB;
++ }
++ else
++ {
++ /*
++ * extra_len = 0, _mmap_segment_filesz just mmap segment's FileSiz part,
++ * here, it needs to zero tail page [FileSiz end, tail page end) part
++ */
++ if (c->allocend <= c->dataend)
++ return NULL;
++
++ if (ALIGN_UP(zero, GLRO(dl_pagesize)) == ALIGN_UP(zero, SIZE_2MB) &&
++ (zeropage - (mapstart + _get_relro_len(l, c)) >= SIZE_2MB))
++ {
++ alignment = SIZE_2MB;
++ }
++
++ if (zeroend < zeropage)
++ zeropage = zeroend;
++ }
++
++ if (zeropage > zero)
++ {
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tzero tail page [%lx-%lx) which contains hole area length: 0x%lx\n",
++ zero, zeropage, zeropage > ALIGN_UP(zero, GLRO(dl_pagesize)) ?
++ zeropage - ALIGN_UP(zero, GLRO(dl_pagesize)) : 0);
++ errstring = _zero_tail_page(c, zero, zeropage, alignment);
++ if (errstring != NULL)
++ return errstring;
++ }
++
++ if (zeroend > zeropage)
++ {
++ *memsz_len = ALIGN_UP(zeroend, GLRO(dl_pagesize)) - zeropage;
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tzero remain page [%lx-%lx)\n", zeropage, zeroend);
++ errstring = _mmap_remain_zero_page(zeropage, zeroend, c->prot);
++ }
++ return errstring;
++}
++
++/*
++ * mmap as fixed addr, if the middle part is 2MB aligned,
++ * this part should be mmaped in 2MB aligned, else in 4KB aligned
++ * 2MB hugepage area should be set with correct permissions, no need to remap
++ */
++static __always_inline const char *
++_mmap_segment_filesz(struct link_map *l, const struct loadcmd *c, ElfW(Addr) mapstart,
++ size_t extra_len, int fd)
++{
++ void *map_addr = 0;
++
++ size_t relro_len = _get_relro_len(l, c);
++ if (relro_len > 0)
++ {
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tmmap relro: [%lx-%lx)\n", mapstart, mapstart + relro_len);
++ /*
++ * relro part must be mapped as normal page size to avoid
++ * _dl_protect_relro failure
++ */
++ map_addr = __mmap((void *)mapstart, relro_len, c->prot,
++ MAP_PRIVATE|MAP_FIXED|MAP_FILE,
++ fd, c->mapoff);
++ if (__glibc_unlikely (map_addr == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++
++ mapstart += relro_len;
++ }
++
++ size_t prev_map_len = ALIGN_UP(mapstart, SIZE_2MB) - mapstart;
++ size_t len = (c->mapend + extra_len) - (c->mapstart + relro_len);
++ if (len <= prev_map_len || len - prev_map_len < SIZE_2MB)
++ {
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tmmap all: [%lx-%lx), which includes prev_map_len(0x%lx)\n",
++ mapstart, mapstart + len, prev_map_len);
++ mapstart = (ElfW(Addr))__mmap((void *)mapstart, len, c->prot,
++ MAP_PRIVATE|MAP_FIXED|MAP_FILE,
++ fd, c->mapoff + relro_len);
++ if (__glibc_unlikely ((void *)mapstart == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++ return NULL;
++ }
++
++ if (prev_map_len > 0)
++ {
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tmmap prev_map_len: [%lx-%lx)\n",
++ mapstart, mapstart + prev_map_len);
++ mapstart = (ElfW(Addr))__mmap((void *)mapstart, prev_map_len, c->prot,
++ MAP_PRIVATE|MAP_FIXED|MAP_FILE,
++ fd, c->mapoff + relro_len);
++ if (__glibc_unlikely ((void *)mapstart == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++
++ map_addr = map_addr == 0 ? (void *)mapstart : map_addr;
++ mapstart += prev_map_len;
++ len -= prev_map_len;
++ }
++
++ size_t mod = len % SIZE_2MB;
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tmmap hugepage: [%lx-%lx)\n", mapstart, mapstart + len - mod);
++ mapstart = (ElfW(Addr))__mmap((void *)mapstart, len - mod, c->prot,
++ MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT),
++ -1, 0);
++ if (__glibc_unlikely ((void *)mapstart == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++
++ if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot | PROT_WRITE) < 0)
++ {
++ return DL_MAP_SEGMENTS_ERROR_MPROTECT;
++ }
++
++ /* Read the segment contents from the file. */
++ size_t file_len = (size_t)(c->dataend - c->mapstart) <= prev_map_len + relro_len ? 0 :
++ (size_t)(c->dataend - c->mapstart) - prev_map_len - relro_len;
++ if (file_len > 0)
++ {
++ lseek(fd, c->mapoff + relro_len + prev_map_len, SEEK_SET);
++ if ( __read(fd, (void *)mapstart, file_len < len - mod ? file_len : len - mod) < 0)
++ return DL_MAP_SEGMENTS_ERROR_READ_SEGMENT;
++ }
++
++ if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot) < 0)
++ {
++ return DL_MAP_SEGMENTS_ERROR_MPROTECT;
++ }
++
++ map_addr = map_addr == 0 ? (void *)mapstart : map_addr;
++ mapstart += len - mod;
++
++ if (__glibc_unlikely (extra_len > 0 && mod > 0))
++ return DL_MAP_SEGMENT_ERROR_EXTRA_SIZE;
++
++ if (mod > 0 && __glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tmmap tail part: [%lx-%lx)\n", mapstart, mapstart + mod);
++ if (mod > 0 && __mmap((void *)mapstart, mod, c->prot,
++ MAP_PRIVATE|MAP_FIXED|MAP_FILE,
++ fd, c->mapoff + relro_len + prev_map_len + len - mod)
++ == MAP_FAILED)
++ {
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++ }
++ return NULL;
++}
++
++/*
++ * mmap segment filesz tail part only covers the very first part of hugepage,
++ * if the size of this tail part reach the threshold, map the tail part in hugepage
++ *
++ * The tail part must be calculated by mapend, because this is file mmaping,
++ * if tail part is calculated by allocend, it will mmap invalid data in file
++ * s: mapstart mp: mapend ac: allocend
++ * 1. [s, mp) can not cover the tail hugepage start, mp, s, ac are all in same hugepage, no extra space
++ * s mp ac
++ * | | |
++ * |--------|--------|
++ *
++ * 2. [s, mp) can not cover the tail hugepage start, ac is in the behind hugepage, no extra space
++ * s mp ac
++ * | | |
++ * |--------|--------|--------|
++ *
++ * 3. [s, mp) covers the tail hugepage start, mp and the ac in the same hugepage,
++ * if (ac - ALIGN_DOWN(mp, SIZE_2MB) < threshold, no extra space; else extra space
++ * [mp, ALIGN_UP(mp, SIZE_2MB) which contains initialized data area and hole
++ * if ac == mp, the extra space only contains hole
++ * s1 s2 mp ac
++ * | | | |
++ * |--------|--------|--------|
++ *
++ * 4. [s, mp) covers the tail hugepage start, ac is in the behind hugepage,
++ * the extra space is [mp, ALIGN_UP(mp, SIZE_2MB) which only contains initialized data area
++ * s1 s2 mp ac
++ * | | | |
++ * |--------|--------|--------|--------|--------|
++ *
++ * 5. if mp is 2MB aligned, no matter [s, mp) covers the tail hugepage start or not,
++ * no extra area
++ * s1 s2 s3 mp ac
++ * | | | | |
++ * |--------|--------|--------|--------|--------|
++ *
++ * there are a few points to note:
++ * 1. the extra part shold not overlap with the next segment
++ * 2. PT_LOAD segment which contains relro section should update mapstart
++ */
++static __always_inline size_t
++_extra_mmap(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmds,
++ const struct loadcmd *c, ElfW(Addr) mapstart)
++{
++ ElfW(Addr) mapend = mapstart + (c->mapend - c->mapstart);
++ ElfW(Addr) hugepage = ALIGN_DOWN(mapend, SIZE_2MB);
++ size_t relro_len = _get_relro_len(l, c);
++ mapstart += relro_len;
++
++ /*
++ * 1. mapend is 2MB aligned
++ * 2. [mapstart, mapend) does not cover the tail hugepage start
++ */
++ if (mapend == ALIGN_UP(mapend, SIZE_2MB) || mapstart > hugepage)
++ return 0;
++
++ /* the initialized data area end in the tail hugepage */
++ ElfW(Addr) end = (mapstart - relro_len) + ALIGN_UP(c->allocend - c->mapstart, GLRO(dl_pagesize)) >=
++ ALIGN_UP(mapend, SIZE_2MB) ? ALIGN_UP(mapend, SIZE_2MB) :
++ (mapstart - relro_len) + ALIGN_UP(c->allocend - c->mapstart, GLRO(dl_pagesize));
++
++ size_t extra_len = ALIGN_UP(mapend, SIZE_2MB) - mapend;
++ if ((end - hugepage < THRESHOLD * GLRO(dl_pagesize)) || ((c < loadcmds + (nloadcmds - 1)) &&
++ (ALIGN_UP(mapend, SIZE_2MB) > (mapstart - relro_len) + c[1].mapstart - c->mapstart)))
++ {
++ extra_len = 0;
++ }
++
++ return extra_len;
++}
++
++/*
++ * PT_LOAD segment is described by p_filesz and p_memsz.
++ * The bytes from the file are mapped to the beginning of the memory segment.
++ * If the segment’s memory size (p_memsz) is larger than the file size (p_filesz),
++ * the extra bytes are defined to hold the value 0 and to follow the segment’s
++ * initialized area
++ */
++static __always_inline const char *
++_mmap_segment(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmds,
++ const struct loadcmd *c, ElfW(Addr) mapstart, int fd, size_t *mapseglen)
++{
++ const char * errstring = NULL;
++ size_t extra_len = _extra_mmap(l, loadcmds, nloadcmds, c, mapstart);
++ size_t memsz_len = 0;
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t%s(0x%lx): extra_len = 0x%lx\n\t{\n", __func__,
++ (unsigned long)c, extra_len);
++
++ errstring = _mmap_segment_filesz(l, c, mapstart, extra_len, fd);
++ if (__glibc_unlikely (errstring != NULL))
++ return errstring;
++ errstring = _mmap_segment_memsz(l, c, mapstart, extra_len, &memsz_len);
++ if (__glibc_unlikely (errstring != NULL))
++ return errstring;
++
++ *mapseglen = c->mapend - c->mapstart + extra_len + memsz_len;
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t} => mapseglen = 0x%lx, memsz_len = 0x%lx\n", *mapseglen, memsz_len);
++ return NULL;
++}
++
++static __always_inline void *
++_mmap_hole(const struct loadcmd *current, const struct loadcmd *next,
++ ElfW(Addr) mapstart, size_t mapseglen, int fd)
++{
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\tmmap hole area:[%lx-%lx)\n", mapstart + mapseglen,
++ mapstart + (next->mapstart - current->mapstart));
++ return __mmap((void *)(mapstart + mapseglen),
++ next->mapstart - (current->mapstart + mapseglen),
++ PROT_NONE, MAP_FILE|MAP_PRIVATE|MAP_FIXED,
++ fd, current->mapoff + mapseglen);
++}
++
++static __always_inline const char *
++_dl_map_segments_largein (struct link_map *l, int fd,
++ const ElfW(Ehdr) *header, int type,
++ const struct loadcmd loadcmds[], size_t nloadcmds,
++ const size_t maplength, bool has_holes)
++{
++ if (__glibc_unlikely (type != ET_DYN))
++ return DL_MAP_SEGMENTS_ERROR_TYPE;
++
++ const char *errstring = NULL;
++ const struct loadcmd *text = _find_exec_segment(loadcmds, nloadcmds);
++ if (__glibc_unlikely (text == NULL))
++ return DL_FIND_EXEC_SEGMENT_ERROR;
++
++ size_t maparealen;
++ void *map_area_start = __mmap_reserved_area(loadcmds, nloadcmds, &maparealen);
++ if (__glibc_unlikely (map_area_start == MAP_FAILED))
++ return DL_MAP_RESERVED_HUGEPAGE_AREA_ERROR;
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("reserved area:[%lx-%lx)\n",
++ (unsigned long)map_area_start, (unsigned long)map_area_start + maparealen);
++
++ /* First to mmap text segment */
++ const struct loadcmd * c = loadcmds;
++ ElfW(Addr) text_addr = ALIGN_UP((ElfW(Addr))map_area_start + (text->mapstart - c->mapstart), SIZE_2MB);
++ size_t mapseglen;
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, text, text_addr, fd, &mapseglen);
++ if (__glibc_unlikely(errstring != NULL))
++ goto unmap_reserved_area;
++
++ const struct loadcmd *prev = text;
++ c = text + 1;
++ ElfW(Addr) map_addr = text_addr;
++ while (c < &loadcmds[nloadcmds])
++ {
++ if (prev->mapstart + mapseglen > c->mapstart || c->mapstart < prev->mapstart)
++ {
++ errstring = DL_MAP_SEGMENTS_ERROR_ARRANGE;
++ goto unmap_reserved_area;
++ }
++
++ if (prev->mapstart + mapseglen < c->mapstart &&
++ _mmap_hole(prev, c, map_addr, mapseglen, fd) == MAP_FAILED)
++ {
++ errstring = DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL;
++ goto unmap_reserved_area;
++ }
++
++ map_addr += c->mapstart - prev->mapstart;
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen);
++ if (__glibc_unlikely(errstring != NULL))
++ goto unmap_reserved_area;
++ prev = c;
++ ++c;
++ }
++ ElfW(Addr) l_map_end = map_addr + mapseglen;
++
++ /* search for the first segment */
++ prev = text;
++ c = text - 1;
++ map_addr = text_addr;
++ while (c >= loadcmds)
++ {
++ if (prev->mapstart < c->mapstart)
++ {
++ errstring = DL_MAP_SEGMENTS_ERROR_ARRANGE;
++ goto unmap_reserved_area;
++ }
++
++ map_addr -= prev->mapstart - c->mapstart;
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen);
++ if (__glibc_unlikely(errstring != NULL))
++ goto unmap_reserved_area;
++
++ if (c->mapstart + mapseglen > prev->mapstart)
++ {
++ errstring = DL_MAP_SEGMENTS_ERROR_ARRANGE;
++ goto unmap_reserved_area;
++ }
++
++ if (c->mapstart + mapseglen < prev->mapstart &&
++ _mmap_hole(c, prev, map_addr, mapseglen, fd) == MAP_FAILED)
++ {
++ errstring = DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL;
++ goto unmap_reserved_area;
++ }
++ prev = c;
++ --c;
++ }
++
++ ++c;
++ l->l_map_start = map_addr;
++ l->l_map_end = l->l_map_start + maplength;
++ l->l_addr = l->l_map_start - c->mapstart;
++ l->l_contiguous = 1;
++
++ c = loadcmds;
++ while (c < &loadcmds[nloadcmds])
++ {
++ _dl_postprocess_loadcmd (l, header, c);
++ ++c;
++ }
++
++ if (l->l_map_start > (ElfW(Addr))map_area_start)
++ {
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("__munmap [%lx-%lx)\n", (ElfW(Addr))map_area_start, l->l_map_start);
++ __munmap(map_area_start, l->l_map_start - (ElfW(Addr))map_area_start);
++ }
++
++ /*
++ * l->l_map_end is caculated by maplength, l_map_end may end with extra space
++ * use l->l_map_end may munmap extra space part
++ */
++ if ((ElfW(Addr))map_area_start + maparealen > l_map_end)
++ {
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("__munmap [%lx-%lx)\n", l_map_end, (ElfW(Addr))map_area_start + maparealen);
++ __munmap((void *)l_map_end, (ElfW(Addr))map_area_start + maparealen - l_map_end);
++ }
++
++ return NULL;
++
++unmap_reserved_area:
++ __munmap(map_area_start, maparealen);
++
++ return errstring;
++}
+diff --git a/elf/dl-support.c b/elf/dl-support.c
+index d8c06ba7..f6ab2627 100644
+--- a/elf/dl-support.c
++++ b/elf/dl-support.c
+@@ -166,6 +166,10 @@ size_t _dl_phnum;
+ uint64_t _dl_hwcap;
+ uint64_t _dl_hwcap2;
+
++#ifdef HUGEPAGE_SHARED_LIB
++int _dl_hugepage_mask;
++#endif
++
+ /* The value of the FPU control word the kernel will preset in hardware. */
+ fpu_control_t _dl_fpu_control = _FPU_DEFAULT;
+
+diff --git a/elf/elf.h b/elf/elf.h
+index 4738dfa2..c5315d1b 100644
+--- a/elf/elf.h
++++ b/elf/elf.h
+@@ -730,6 +730,8 @@ typedef struct
+
+ /* Legal values for p_flags (segment flags). */
+
++/* libhugetlbfs's hugeedit use 0x00100000, here use another */
++#define PF_HUGEPAGE (0x01000000)
+ #define PF_X (1 << 0) /* Segment is executable */
+ #define PF_W (1 << 1) /* Segment is writable */
+ #define PF_R (1 << 2) /* Segment is readable */
+diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c
+new file mode 100644
+index 00000000..14a91a4b
+--- /dev/null
++++ b/elf/hugepageedit.c
+@@ -0,0 +1,169 @@
++/* Mark ELF object ELF header hugepage flag Generic version.
++ Copyright (C) 2021-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++#include <stdio.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <string.h>
++#include <unistd.h>
++#include <elf.h>
++#include <link.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++#include <sys/types.h>
++
++/* reference kernel load_elf_phdrs program header table size constraint */
++#define ELF_MIN_ALIGN 4096
++#define TOOL_NAME "hugepageedit"
++
++int check_ptr(void *ptr, void *start, size_t len)
++{
++ if (ptr < start || ptr > start + len)
++ return -1;
++ return 0;
++}
++
++void print_usage(void)
++{
++ fprintf(stderr, "%s [-x] [-d] <ELF file>\n" \
++ "\tdefault mark all PT_LOAD segment PF_HUGEPAGE flag\n" \
++ "\t-x option only mark executable PT_LOAD segment PF_HUGEPAGE flag\n" \
++ "\t-d option delete all the PT_LOAD segment PF_HUGEPAGE flag\n", TOOL_NAME);
++}
++
++int main(int argc, char *argv[])
++{
++ int exit_status = -1;
++ int i, opt, delete = 0, exec_only = 0;
++ while ((opt = getopt(argc, argv, "dx")) != -1)
++ {
++ switch (opt)
++ {
++ case 'd':
++ delete = 1;
++ break;
++ case 'x':
++ exec_only = 1;
++ break;
++ default:
++ print_usage();
++ return 0;
++ }
++ }
++
++ if (delete && exec_only)
++ {
++ fprintf(stderr, "can not specify -x and -d option at the same time\n");
++ return -1;
++ }
++
++ if (optind >= argc)
++ {
++ fprintf(stderr, "Expected argument after options\n");
++ return -1;
++ }
++
++ int fd = open(argv[optind], O_RDWR);
++ if (fd < 0)
++ {
++ perror("open");
++ return -1;
++ }
++
++ struct stat statbuf;
++ if (fstat(fd, &statbuf) != 0)
++ {
++ perror("fstat");
++ goto close_fd;
++ }
++
++ /* this ensures file is large enough to hold ELF header */
++ if (statbuf.st_size < sizeof (ElfW(Ehdr)))
++ {
++ fprintf(stderr, "file is not large enough to hold ELF header\n");
++ goto close_fd;
++ }
++
++ void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
++ if (ehdr == MAP_FAILED)
++ {
++ perror("mmap");
++ goto close_fd;
++ }
++
++ if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0)
++ {
++ fprintf(stderr, "file is not ELF format\n");
++ goto unmap;
++ }
++
++ if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr)))
++ {
++ fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n");
++ goto unmap;
++ }
++
++ unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr));
++ if (size == 0 || size > ELF_MIN_ALIGN)
++ {
++ fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size);
++ goto unmap;
++ }
++
++ void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff;
++ void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size;
++
++ if (check_ptr(ephdr_s, ehdr, statbuf.st_size) ||
++ check_ptr(ephdr_e, ehdr, statbuf.st_size))
++ {
++ fprintf(stderr, "ELF porgram header table is not fully mmaped\n");
++ goto unmap;
++ }
++
++ ElfW(Phdr) *phdr = (ElfW(Phdr) *)ephdr_s;
++ /*
++ * Here, mark hugepage flag in ELF header e_ident padding bytes won't work.
++ * elf/dl-load.c open_verify will check if shared object ELF header e_ident
++ * padding bytes match expected[EI_NIDENT] byte array which padding bytes
++ * should be zero. If it mismatches, ld.so will exit abnormally
++ */
++ for (i = 0; i < ((ElfW(Ehdr) *)ehdr)->e_phnum; i++)
++ {
++ if (phdr[i].p_type == PT_LOAD)
++ {
++ if (delete)
++ {
++ phdr[i].p_flags &= ~PF_HUGEPAGE;
++ }
++ else
++ {
++ if (exec_only && !(phdr[i].p_flags & PF_X))
++ continue;
++ phdr[i].p_flags |= PF_HUGEPAGE;
++ }
++ }
++ }
++ exit_status = 0;
++
++unmap:
++ munmap(ehdr, statbuf.st_size);
++
++close_fd:
++ close(fd);
++
++ return exit_status;
++}
+diff --git a/elf/rtld.c b/elf/rtld.c
+index a8ae8b31..85596ee4 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -2543,6 +2543,40 @@ dl_main (const ElfW(Phdr) *phdr,
+ /* Once we return, _dl_sysdep_start will invoke
+ the DT_INIT functions and then *USER_ENTRY. */
+ }
++
++#ifdef HUGEPAGE_SHARED_LIB
++/* prase the hugepage use strategy of loading shared object */
++static void
++process_dl_hugepage (const char *dl_hugepage)
++{
++ static const struct
++ {
++ uint64_t option;
++ int flag;
++ } hpopts[] =
++ {
++ {DL_HUGEPAGE_LARGE_IN, DL_HUGEPAGE_LIB_LARGE_IN_FLAG},
++ };
++#define nhpopts (sizeof (hpopts) / sizeof (hpopts[0]))
++
++ if (dl_hugepage == NULL)
++ return;
++
++ char *endptr;
++ uint64_t val = _dl_strtoul (dl_hugepage, &endptr);
++ /* Invalid digit in input string */
++ if (*endptr != '\0')
++ return;
++
++ for (size_t cnt = 0; cnt < nhpopts; ++cnt)
++ if (val == hpopts[cnt].option)
++ {
++ GLRO(dl_hugepage_mask) |= hpopts[cnt].flag;
++ break;
++ }
++}
++#endif
++
+
+ /* This is a little helper function for resolving symbols while
+ tracing the binary. */
+@@ -2678,6 +2712,9 @@ process_envvars (struct dl_main_state *state)
+ char **runp = _environ;
+ char *envline;
+ char *debug_output = NULL;
++#ifdef HUGEPAGE_SHARED_LIB
++ bool hugepage_lib_env = false;
++#endif
+
+ /* This is the default place for profiling data file. */
+ GLRO(dl_profile_output)
+@@ -2790,6 +2827,15 @@ process_envvars (struct dl_main_state *state)
+ if (!__libc_enable_secure
+ && memcmp (envline, "DYNAMIC_WEAK", 12) == 0)
+ GLRO(dl_dynamic_weak) = 1;
++
++#ifdef HUGEPAGE_SHARED_LIB
++ if (memcmp (envline, "HUGEPAGE_LIB", 12) == 0 && envline[13] != '\0')
++ {
++ hugepage_lib_env = true;
++ process_dl_hugepage(&envline[13]);
++ }
++#endif
++
+ break;
+
+ case 13:
+@@ -2812,6 +2858,13 @@ process_envvars (struct dl_main_state *state)
+ && memcmp (envline, "PROFILE_OUTPUT", 14) == 0
+ && envline[15] != '\0')
+ GLRO(dl_profile_output) = &envline[15];
++
++#ifdef HUGEPAGE_SHARED_LIB
++ if (memcmp (envline, "HUGEPAGE_PROBE", 14) == 0 &&
++ envline[15] != '\0')
++ GLRO(dl_hugepage_mask) |= DL_HUGEPAGE_PROBE_FLAG;
++#endif
++
+ break;
+
+ case 16:
+@@ -2841,6 +2894,16 @@ process_envvars (struct dl_main_state *state)
+ }
+ }
+
++#ifdef HUGEPAGE_SHARED_LIB
++ /* LIB_HUGEPAGE_LIB and HUGEPAGE_PROBE are both set. use LIB_HUGEPAGE_LIB */
++ if ((GLRO(dl_hugepage_mask) & DL_HUGEPAGE_PROBE_FLAG) && hugepage_lib_env)
++ {
++ GLRO(dl_hugepage_mask) &= ~DL_HUGEPAGE_PROBE_FLAG;
++ }
++ /* unsetenv LD_HUGEPAGE_LIB, child process should not get this env */
++ unsetenv("LD_HUGEPAGE_LIB");
++#endif
++
+ /* Extra security for SUID binaries. Remove all dangerous environment
+ variables. */
+ if (__builtin_expect (__libc_enable_secure, 0))
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index a1d70ce7..a9fffd66 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -549,7 +549,11 @@ struct rtld_global_ro
+ /* These two are used only internally. */
+ #define DL_DEBUG_HELP (1 << 10)
+ #define DL_DEBUG_PRELINK (1 << 11)
+-
++#ifdef HUGEPAGE_SHARED_LIB
++#define DL_HUGEPAGE_PROBE_FLAG (1 << 31)
++#define DL_HUGEPAGE_LIB_LARGE_IN_FLAG (1 << 30)
++#define DL_HUGEPAGE_LARGE_IN 1
++#endif
+ /* OS version. */
+ EXTERN unsigned int _dl_osversion;
+ /* Platform name. */
+@@ -672,6 +676,11 @@ struct rtld_global_ro
+ platforms. */
+ EXTERN uint64_t _dl_hwcap2;
+
++#ifdef HUGEPAGE_SHARED_LIB
++ /* Mask for how to use hugepage */
++ EXTERN int _dl_hugepage_mask;
++#endif
++
+ #ifdef SHARED
+ /* We add a function table to _rtld_global which is then used to
+ call the function instead of going through the PLT. The result
+--
+2.37.3
+
diff --git a/0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch b/0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch
new file mode 100644
index 0000000..8d899e5
--- /dev/null
+++ b/0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch
@@ -0,0 +1,312 @@
+From 7adf5ee832d2649fa85f8f104523932dab64f12e Mon Sep 17 00:00:00 2001
+From: Lv Ying <lvying6@huawei.com>
+Date: Tue, 7 Feb 2023 19:29:11 +0800
+Subject: [PATCH 1/3] ld.so: support ld.so mmap hugetlb hugepage according to
+ PT_LOAD segment granularity
+
+Only attempt to use hugepage to load PT_LOAD segments marked with PF_HUGEPAGE flag.
+Even if the segment is marked with the PF_HUGEPAGE flag, the segment does not
+necessarily use the hugetlb huge page, either because the segment is too small,
+or because the segment is in an address space that is not suitable for using
+a huge page. Also we add added the -i option to hugepageedit to mark any
+PT_LOAD segment with the PF_HUGEPAGE flag.
+
+Signed-off-by: Lv Ying <lvying6@huawei.com>
+---
+ elf/dl-load.c | 15 ++++---
+ elf/dl-map-segments-hugepage.h | 72 ++++++++++++++++++++++++++++++----
+ elf/elf.h | 2 +
+ elf/hugepageedit.c | 58 ++++++++++++++++++++++++---
+ 4 files changed, 128 insertions(+), 19 deletions(-)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index f4b5c4a7..e0d4fa2e 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1136,6 +1136,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ bool empty_dynamic = false;
+ #ifdef HUGEPAGE_SHARED_LIB
+ bool use_hugepage = false;
++ char hp_bitmap[l->l_phnum];
+ #endif
+
+ /* The struct is initialized to zero so this is not necessary:
+@@ -1182,6 +1183,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ goto lose;
+ }
+
++#ifdef HUGEPAGE_SHARED_LIB
++ if (ph->p_flags & PF_HUGEPAGE) {
++ hp_bitmap[nloadcmds] = 1;
++ use_hugepage = true;
++ } else
++ hp_bitmap[nloadcmds] = 0;
++#endif
+ struct loadcmd *c = &loadcmds[nloadcmds++];
+ c->mapstart = ALIGN_DOWN (ph->p_vaddr, GLRO(dl_pagesize));
+ c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
+@@ -1194,11 +1202,6 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ if (nloadcmds > 1 && c[-1].mapend != c->mapstart)
+ has_holes = true;
+
+-#ifdef HUGEPAGE_SHARED_LIB
+- if (ph->p_flags & PF_HUGEPAGE)
+- use_hugepage = true;
+-#endif
+-
+ /* Optimize a common case. */
+ #if (PF_R | PF_W | PF_X) == 7 && (PROT_READ | PROT_WRITE | PROT_EXEC) == 7
+ c->prot = (PF_TO_PROT
+@@ -1297,7 +1300,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ ((GLRO(dl_hugepage_mask) & DL_HUGEPAGE_PROBE_FLAG) && use_hugepage))
+ {
+ errstring = _dl_map_segments_largein (l, fd, header, type, loadcmds, nloadcmds,
+- maplength, has_holes);
++ maplength, hp_bitmap);
+ if (__glibc_unlikely (errstring != NULL))
+ {
+ hp_errcode = errno;
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+index 37788ef9..e7202131 100644
+--- a/elf/dl-map-segments-hugepage.h
++++ b/elf/dl-map-segments-hugepage.h
+@@ -400,6 +400,55 @@ _extra_mmap(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmd
+ return extra_len;
+ }
+
++static __always_inline const char *
++__mmap_segment_normalsz(const struct loadcmd *c, ElfW(Addr) mapstart, int fd,
++ size_t *mapseglen)
++{
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\tuse normal page mmap segment:[%lx-%lx)\n", mapstart,
++ mapstart + (c->allocend - c->mapstart));
++
++ if (c->mapend > c->mapstart &&
++ (__mmap((void *)mapstart, c->mapend - c->mapstart, c->prot,
++ MAP_FILE|MAP_PRIVATE|MAP_FIXED, fd, c->mapoff) == MAP_FAILED))
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++
++ if (c->allocend > c->dataend) {
++ ElfW(Addr) zero, zeroend, zeropage;
++
++ zero = mapstart + c->dataend - c->mapstart;
++ zeroend = mapstart + c->allocend - c->mapstart;
++ zeropage = ((zero + GLRO(dl_pagesize) - 1)
++ & ~(GLRO(dl_pagesize) - 1));
++
++ if (zeroend < zeropage)
++ zeropage = zeroend;
++
++ if (zeropage > zero) {
++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0)) {
++ if (__mprotect ((caddr_t) (zero & ~(GLRO(dl_pagesize) - 1)),
++ GLRO(dl_pagesize), c->prot|PROT_WRITE) < 0)
++ return DL_MAP_SEGMENTS_ERROR_MPROTECT;
++ }
++
++ memset ((void *) zero, '\0', zeropage - zero);
++
++ if (__glibc_unlikely ((c->prot & PROT_WRITE) == 0))
++ __mprotect ((caddr_t) (zero & ~(GLRO(dl_pagesize) - 1)),
++ GLRO(dl_pagesize), c->prot);
++ }
++
++ if (zeroend > zeropage) {
++ if (__mmap ((caddr_t) zeropage, zeroend - zeropage, c->prot,
++ MAP_ANON|MAP_PRIVATE|MAP_FIXED, -1, 0) == MAP_FAILED)
++ return DL_MAP_SEGMENTS_ERROR_MAP_ZERO_FILL;
++ }
++ }
++
++ *mapseglen = c->allocend - c->mapstart;
++ return NULL;
++}
++
+ /*
+ * PT_LOAD segment is described by p_filesz and p_memsz.
+ * The bytes from the file are mapped to the beginning of the memory segment.
+@@ -409,11 +458,17 @@ _extra_mmap(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmd
+ */
+ static __always_inline const char *
+ _mmap_segment(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadcmds,
+- const struct loadcmd *c, ElfW(Addr) mapstart, int fd, size_t *mapseglen)
++ const struct loadcmd *c, ElfW(Addr) mapstart, int fd,
++ size_t *mapseglen, const char hp_bitmap[])
+ {
+ const char * errstring = NULL;
+- size_t extra_len = _extra_mmap(l, loadcmds, nloadcmds, c, mapstart);
+- size_t memsz_len = 0;
++ size_t extra_len, memsz_len = 0;
++
++ if (!hp_bitmap[((void *)c - (void *)loadcmds) / sizeof(struct loadcmd)]) {
++ return __mmap_segment_normalsz(c, mapstart, fd, mapseglen);
++ }
++
++ extra_len = _extra_mmap(l, loadcmds, nloadcmds, c, mapstart);
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+ _dl_debug_printf("\t%s(0x%lx): extra_len = 0x%lx\n\t{\n", __func__,
+ (unsigned long)c, extra_len);
+@@ -448,7 +503,7 @@ static __always_inline const char *
+ _dl_map_segments_largein (struct link_map *l, int fd,
+ const ElfW(Ehdr) *header, int type,
+ const struct loadcmd loadcmds[], size_t nloadcmds,
+- const size_t maplength, bool has_holes)
++ const size_t maplength, const char hp_bitmap[])
+ {
+ if (__glibc_unlikely (type != ET_DYN))
+ return DL_MAP_SEGMENTS_ERROR_TYPE;
+@@ -470,7 +525,8 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ const struct loadcmd * c = loadcmds;
+ ElfW(Addr) text_addr = ALIGN_UP((ElfW(Addr))map_area_start + (text->mapstart - c->mapstart), SIZE_2MB);
+ size_t mapseglen;
+- errstring = _mmap_segment(l, loadcmds, nloadcmds, text, text_addr, fd, &mapseglen);
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, text, text_addr, fd,
++ &mapseglen, hp_bitmap);
+ if (__glibc_unlikely(errstring != NULL))
+ goto unmap_reserved_area;
+
+@@ -493,7 +549,8 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ }
+
+ map_addr += c->mapstart - prev->mapstart;
+- errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen);
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd,
++ &mapseglen, hp_bitmap);
+ if (__glibc_unlikely(errstring != NULL))
+ goto unmap_reserved_area;
+ prev = c;
+@@ -514,7 +571,8 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ }
+
+ map_addr -= prev->mapstart - c->mapstart;
+- errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd, &mapseglen);
++ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd,
++ &mapseglen, hp_bitmap);
+ if (__glibc_unlikely(errstring != NULL))
+ goto unmap_reserved_area;
+
+diff --git a/elf/elf.h b/elf/elf.h
+index c5315d1b..a64576bb 100644
+--- a/elf/elf.h
++++ b/elf/elf.h
+@@ -730,8 +730,10 @@ typedef struct
+
+ /* Legal values for p_flags (segment flags). */
+
++#ifdef HUGEPAGE_SHARED_LIB
+ /* libhugetlbfs's hugeedit use 0x00100000, here use another */
+ #define PF_HUGEPAGE (0x01000000)
++#endif
+ #define PF_X (1 << 0) /* Segment is executable */
+ #define PF_W (1 << 1) /* Segment is writable */
+ #define PF_R (1 << 2) /* Segment is readable */
+diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c
+index ab4247ad..0a44ece6 100644
+--- a/elf/hugepageedit.c
++++ b/elf/hugepageedit.c
+@@ -31,18 +31,52 @@
+
+ void print_usage(void)
+ {
+- fprintf(stderr, "%s [-x] [-d] <ELF file>\n" \
++ fprintf(stderr, "%s [-x] [-d] [-i index] <ELF file>\n" \
+ "\tdefault mark all PT_LOAD segment PF_HUGEPAGE flag\n" \
+ "\t-x option only mark executable PT_LOAD segment PF_HUGEPAGE flag\n" \
++ "\t-i [index(start from 0)] option specifies the index that marks the PT_LOAD segment PF_HUGEPAGE flag\n" \
+ "\t-d option delete all the PT_LOAD segment PF_HUGEPAGE flag\n", TOOL_NAME);
+ }
+
++
++static long parse_index(char *str)
++{
++ char *endptr;
++
++ errno = 0;
++ long val = strtol(str, &endptr, 10);
++
++ if (errno != 0) {
++ perror("strtol");
++ return -1;
++ }
++
++ if (endptr == str) {
++ fprintf(stderr, "No digits were found in -i option\n");
++ return -1;
++ }
++
++ if (*endptr != '\0') {
++ fprintf(stderr, "Invalid characters %s in -i %s option\n", endptr, str);
++ return -1;
++ }
++
++ if (val < 0) {
++ fprintf(stderr, "Negative index %ld in -i %s option\n", val, str);
++ return -1;
++ }
++
++ return val;
++}
++
++
+ int main(int argc, char *argv[])
+ {
+ size_t length;
+ int exit_status = -1;
+- int i, opt, delete = 0, exec_only = 0;
+- while ((opt = getopt(argc, argv, "dx")) != -1)
++ int i, opt, delete = 0, exec_only = 0, index_set = 0;
++ long index = -1;
++ while ((opt = getopt(argc, argv, "dxi:")) != -1)
+ {
+ switch (opt)
+ {
+@@ -52,15 +86,21 @@ int main(int argc, char *argv[])
+ case 'x':
+ exec_only = 1;
+ break;
++ case 'i':
++ index = parse_index(optarg);
++ index_set = 1;
++ if (index < 0)
++ return -1;
++ break;
+ default:
+ print_usage();
+ return 0;
+ }
+ }
+
+- if (delete && exec_only)
++ if (delete + exec_only + index_set > 1)
+ {
+- fprintf(stderr, "can not specify -x and -d option at the same time\n");
++ fprintf(stderr, "can not specify -x, -d and -i option at the same time\n");
+ return -1;
+ }
+
+@@ -81,6 +121,12 @@ int main(int argc, char *argv[])
+ if (ehdr == NULL)
+ goto close_fd;
+
++ if (index_set && index >= ((ElfW(Ehdr) *)ehdr)->e_phnum) {
++ fprintf(stderr, "Index %ld in -i %s option out of PT_LOAD segment range\n",
++ index, argv[optind]);
++ goto close_fd;
++ }
++
+ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length);
+ if (phdr == NULL)
+ goto unmap;
+@@ -100,7 +146,7 @@ int main(int argc, char *argv[])
+ }
+ else
+ {
+- if (exec_only && !(phdr[i].p_flags & PF_X))
++ if ((exec_only && !(phdr[i].p_flags & PF_X)) || (index_set && index != i))
+ continue;
+ phdr[i].p_flags |= PF_HUGEPAGE;
+ }
+--
+2.38.1
+
diff --git a/0002-add-header-files-for-libphtread_2_17_so.patch b/0002-add-header-files-for-libphtread_2_17_so.patch
new file mode 100644
index 0000000..98db0ff
--- /dev/null
+++ b/0002-add-header-files-for-libphtread_2_17_so.patch
@@ -0,0 +1,2609 @@
+From 76a50749f7af5935ba3739e815aa6a16ae4440d1 Mon Sep 17 00:00:00 2001
+From: Ulrich Drepper <drepper@redhat.com>
+Date: Tue Nov 26 22:50:54 2002 +0000
+Subject: [PATCH 2/9] build extra lipthreadcond so
+
+To successfully build some header files that reference glibc-2.17
+
+Including but not limited to the following submission:
+76a50749f7a
+d5efd131d4e
+eab380d8ec9
+
+---
+ nptl_2_17/bits/pthreadtypes_2_17.h | 127 +++
+ nptl_2_17/bits/thread-shared-types_2_17.h | 186 ++++
+ nptl_2_17/internaltypes_2_17.h | 179 ++++
+ nptl_2_17/kernel-features_2_17.h | 162 +++
+ nptl_2_17/pthreadP_2_17.h | 714 +++++++++++++
+ nptl_2_17/pthread_2_17.h | 1175 +++++++++++++++++++++
+ 6 files changed, 2543 insertions(+)
+ create mode 100644 nptl_2_17/bits/pthreadtypes_2_17.h
+ create mode 100644 nptl_2_17/bits/thread-shared-types_2_17.h
+ create mode 100644 nptl_2_17/internaltypes_2_17.h
+ create mode 100644 nptl_2_17/kernel-features_2_17.h
+ create mode 100644 nptl_2_17/pthreadP_2_17.h
+ create mode 100644 nptl_2_17/pthread_2_17.h
+
+diff --git a/nptl_2_17/bits/pthreadtypes_2_17.h b/nptl_2_17/bits/pthreadtypes_2_17.h
+new file mode 100644
+index 00000000..da5521c1
+--- /dev/null
++++ b/nptl_2_17/bits/pthreadtypes_2_17.h
+@@ -0,0 +1,127 @@
++/* Declaration of common pthread types for all architectures.
++ Copyright (C) 2017-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#ifndef _BITS_PTHREADTYPES_COMMON_H
++# define _BITS_PTHREADTYPES_COMMON_H 1
++
++/* For internal mutex and condition variable definitions. */
++#include "thread-shared-types_2_17.h"
++
++/* Thread identifiers. The structure of the attribute type is not
++ exposed on purpose. */
++typedef unsigned long int pthread_t;
++
++
++/* Data structures for mutex handling. The structure of the attribute
++ type is not exposed on purpose. */
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_MUTEXATTR_T];
++ int __align;
++} pthread_mutexattr_t;
++
++
++/* Data structure for condition variable handling. The structure of
++ the attribute type is not exposed on purpose. */
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_CONDATTR_T];
++ int __align;
++} pthread_condattr_t;
++
++
++/* Keys for thread-specific data */
++typedef unsigned int pthread_key_t;
++
++
++/* Once-only execution */
++typedef int __ONCE_ALIGNMENT pthread_once_t;
++
++
++union pthread_attr_t
++{
++ char __size[__SIZEOF_PTHREAD_ATTR_T];
++ long int __align;
++};
++#ifndef __have_pthread_attr_t
++typedef union pthread_attr_t pthread_attr_t;
++# define __have_pthread_attr_t 1
++#endif
++
++
++typedef union
++{
++ struct __pthread_mutex_s __data;
++ char __size[__SIZEOF_PTHREAD_MUTEX_T];
++ long int __align;
++} pthread_mutex_t;
++
++
++typedef union
++{
++struct
++{
++ int __lock;
++ unsigned int __futex;
++ __extension__ unsigned long long int __total_seq;
++ __extension__ unsigned long long int __wakeup_seq;
++ __extension__ unsigned long long int __woken_seq;
++ void *__mutex;
++ unsigned int __nwaiters;
++ unsigned int __broadcast_seq;
++}__data;
++ char __size[__SIZEOF_PTHREAD_COND_T];
++ long int __align;
++} pthread_cond_t;
++
++
++/* Data structure for reader-writer lock variable handling. The
++ structure of the attribute type is deliberately not exposed. */
++typedef union
++{
++ struct __pthread_rwlock_arch_t __data;
++ char __size[__SIZEOF_PTHREAD_RWLOCK_T];
++ long int __align;
++} pthread_rwlock_t;
++
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_RWLOCKATTR_T];
++ long int __align;
++} pthread_rwlockattr_t;
++
++
++/* POSIX spinlock data type. */
++typedef volatile int pthread_spinlock_t;
++
++
++/* POSIX barriers data type. The structure of the type is
++ deliberately not exposed. */
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_BARRIER_T];
++ long int __align;
++} pthread_barrier_t;
++
++typedef union
++{
++ char __size[__SIZEOF_PTHREAD_BARRIERATTR_T];
++ int __align;
++} pthread_barrierattr_t;
++
++#endif
+diff --git a/nptl_2_17/bits/thread-shared-types_2_17.h b/nptl_2_17/bits/thread-shared-types_2_17.h
+new file mode 100644
+index 00000000..c855d0d8
+--- /dev/null
++++ b/nptl_2_17/bits/thread-shared-types_2_17.h
+@@ -0,0 +1,186 @@
++/* Common threading primitives definitions for both POSIX and C11.
++ Copyright (C) 2017-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#ifndef _THREAD_SHARED_TYPES_H
++#define _THREAD_SHARED_TYPES_H 1
++
++#include <compat_pthread_2_17.h>
++/* Arch-specific definitions. Each architecture must define the following
++ macros to define the expected sizes of pthread data types:
++
++ __SIZEOF_PTHREAD_ATTR_T - size of pthread_attr_t.
++ __SIZEOF_PTHREAD_MUTEX_T - size of pthread_mutex_t.
++ __SIZEOF_PTHREAD_MUTEXATTR_T - size of pthread_mutexattr_t.
++ __SIZEOF_PTHREAD_COND_T - size of pthread_cond_t.
++ __SIZEOF_PTHREAD_CONDATTR_T - size of pthread_condattr_t.
++ __SIZEOF_PTHREAD_RWLOCK_T - size of pthread_rwlock_t.
++ __SIZEOF_PTHREAD_RWLOCKATTR_T - size of pthread_rwlockattr_t.
++ __SIZEOF_PTHREAD_BARRIER_T - size of pthread_barrier_t.
++ __SIZEOF_PTHREAD_BARRIERATTR_T - size of pthread_barrierattr_t.
++
++ Also, the following macros must be define for internal pthread_mutex_t
++ struct definitions (struct __pthread_mutex_s):
++
++ __PTHREAD_COMPAT_PADDING_MID - any additional members after 'kind'
++ and before '__spin' (for 64 bits) or
++ '__nusers' (for 32 bits).
++ __PTHREAD_COMPAT_PADDING_END - any additional members at the end of
++ the internal structure.
++ __PTHREAD_MUTEX_LOCK_ELISION - 1 if the architecture supports lock
++ elision or 0 otherwise.
++ __PTHREAD_MUTEX_NUSERS_AFTER_KIND - control where to put __nusers. The
++ preferred value for new architectures
++ is 0.
++ __PTHREAD_MUTEX_USE_UNION - control whether internal __spins and
++ __list will be place inside a union for
++ linuxthreads compatibility.
++ The preferred value for new architectures
++ is 0.
++
++ For a new port the preferred values for the required defines are:
++
++ #define __PTHREAD_COMPAT_PADDING_MID
++ #define __PTHREAD_COMPAT_PADDING_END
++ #define __PTHREAD_MUTEX_LOCK_ELISION 0
++ #define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0
++ #define __PTHREAD_MUTEX_USE_UNION 0
++
++ __PTHREAD_MUTEX_LOCK_ELISION can be set to 1 if the hardware plans to
++ eventually support lock elision using transactional memory.
++
++ The additional macro defines any constraint for the lock alignment
++ inside the thread structures:
++
++ __LOCK_ALIGNMENT - for internal lock/futex usage.
++
++ Same idea but for the once locking primitive:
++
++ __ONCE_ALIGNMENT - for pthread_once_t/once_flag definition.
++
++ And finally the internal pthread_rwlock_t (struct __pthread_rwlock_arch_t)
++ must be defined.
++ */
++#include <bits/pthreadtypes-arch.h>
++
++/* Common definition of pthread_mutex_t. */
++
++#if !__PTHREAD_MUTEX_USE_UNION
++typedef struct __pthread_internal_list
++{
++ struct __pthread_internal_list *__prev;
++ struct __pthread_internal_list *__next;
++} __pthread_list_t;
++#else
++typedef struct __pthread_internal_slist
++{
++ struct __pthread_internal_slist *__next;
++} __pthread_slist_t;
++#endif
++
++/* Lock elision support. */
++#if __PTHREAD_MUTEX_LOCK_ELISION
++# if !__PTHREAD_MUTEX_USE_UNION
++# define __PTHREAD_SPINS_DATA \
++ short __spins; \
++ short __elision
++# define __PTHREAD_SPINS 0, 0
++# else
++# define __PTHREAD_SPINS_DATA \
++ struct \
++ { \
++ short __espins; \
++ short __eelision; \
++ } __elision_data
++# define __PTHREAD_SPINS { 0, 0 }
++# define __spins __elision_data.__espins
++# define __elision __elision_data.__eelision
++# endif
++#else
++# define __PTHREAD_SPINS_DATA int __spins
++/* Mutex __spins initializer used by PTHREAD_MUTEX_INITIALIZER. */
++# define __PTHREAD_SPINS 0
++#endif
++
++struct __pthread_mutex_s
++{
++ int __lock __LOCK_ALIGNMENT;
++ unsigned int __count;
++ int __owner;
++#if !__PTHREAD_MUTEX_NUSERS_AFTER_KIND
++ unsigned int __nusers;
++#endif
++ /* KIND must stay at this position in the structure to maintain
++ binary compatibility with static initializers.
++
++ Concurrency notes:
++ The __kind of a mutex is initialized either by the static
++ PTHREAD_MUTEX_INITIALIZER or by a call to pthread_mutex_init.
++
++ After a mutex has been initialized, the __kind of a mutex is usually not
++ changed. BUT it can be set to -1 in pthread_mutex_destroy or elision can
++ be enabled. This is done concurrently in the pthread_mutex_*lock functions
++ by using the macro FORCE_ELISION. This macro is only defined for
++ architectures which supports lock elision.
++
++ For elision, there are the flags PTHREAD_MUTEX_ELISION_NP and
++ PTHREAD_MUTEX_NO_ELISION_NP which can be set in addition to the already set
++ type of a mutex.
++ Before a mutex is initialized, only PTHREAD_MUTEX_NO_ELISION_NP can be set
++ with pthread_mutexattr_settype.
++ After a mutex has been initialized, the functions pthread_mutex_*lock can
++ enable elision - if the mutex-type and the machine supports it - by setting
++ the flag PTHREAD_MUTEX_ELISION_NP. This is done concurrently. Afterwards
++ the lock / unlock functions are using specific elision code-paths. */
++ int __kind;
++ __PTHREAD_COMPAT_PADDING_MID
++#if __PTHREAD_MUTEX_NUSERS_AFTER_KIND
++ unsigned int __nusers;
++#endif
++#if !__PTHREAD_MUTEX_USE_UNION
++ __PTHREAD_SPINS_DATA;
++ __pthread_list_t __list;
++# define __PTHREAD_MUTEX_HAVE_PREV 1
++#else
++ __extension__ union
++ {
++ __PTHREAD_SPINS_DATA;
++ __pthread_slist_t __list;
++ };
++# define __PTHREAD_MUTEX_HAVE_PREV 0
++#endif
++ __PTHREAD_COMPAT_PADDING_END
++};
++
++
++/* Common definition of pthread_cond_t. */
++
++struct __pthread_cond_s
++{
++ int __lock;
++ unsigned int __futex;
++ __extension__ unsigned long long int __total_seq;
++ __extension__ unsigned long long int __wakeup_seq;
++ __extension__ unsigned long long int __woken_seq;
++ void *__mutex;
++ unsigned int __nwaiters;
++ unsigned int __broadcast_seq;
++
++long int __align;
++};
++
++#endif /* _THREAD_SHARED_TYPES_H */
+diff --git a/nptl_2_17/internaltypes_2_17.h b/nptl_2_17/internaltypes_2_17.h
+new file mode 100644
+index 00000000..603dc01c
+--- /dev/null
++++ b/nptl_2_17/internaltypes_2_17.h
+@@ -0,0 +1,179 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#ifndef _INTERNALTYPES_H
++#define _INTERNALTYPES_H 1
++
++#include <stdint.h>
++#include <atomic.h>
++#include <endian.h>
++
++
++struct pthread_attr
++{
++ /* Scheduler parameters and priority. */
++ struct sched_param schedparam;
++ int schedpolicy;
++ /* Various flags like detachstate, scope, etc. */
++ int flags;
++ /* Size of guard area. */
++ size_t guardsize;
++ /* Stack handling. */
++ void *stackaddr;
++ size_t stacksize;
++ /* Affinity map. */
++ cpu_set_t *cpuset;
++ size_t cpusetsize;
++};
++
++#define ATTR_FLAG_DETACHSTATE 0x0001
++#define ATTR_FLAG_NOTINHERITSCHED 0x0002
++#define ATTR_FLAG_SCOPEPROCESS 0x0004
++#define ATTR_FLAG_STACKADDR 0x0008
++#define ATTR_FLAG_OLDATTR 0x0010
++#define ATTR_FLAG_SCHED_SET 0x0020
++#define ATTR_FLAG_POLICY_SET 0x0040
++
++
++/* Mutex attribute data structure. */
++struct pthread_mutexattr
++{
++ /* Identifier for the kind of mutex.
++
++ Bit 31 is set if the mutex is to be shared between processes.
++
++ Bit 0 to 30 contain one of the PTHREAD_MUTEX_ values to identify
++ the type of the mutex. */
++ int mutexkind;
++};
++
++
++/* Conditional variable attribute data structure. */
++struct pthread_condattr
++{
++ /* Combination of values:
++
++ Bit 0 : flag whether conditional variable will be
++ sharable between processes.
++ Bit 1-COND_CLOCK_BITS: Clock ID. COND_CLOCK_BITS is the number of bits
++ needed to represent the ID of the clock. */
++ int value;
++};
++#define COND_CLOCK_BITS 1
++#define COND_NWAITERS_SHIFT 1
++
++/* Read-write lock variable attribute data structure. */
++struct pthread_rwlockattr
++{
++ int lockkind;
++ int pshared;
++};
++
++
++/* Barrier data structure. See pthread_barrier_wait for a description
++ of how these fields are used. */
++struct pthread_barrier
++{
++ unsigned int in;
++ unsigned int current_round;
++ unsigned int count;
++ int shared;
++ unsigned int out;
++};
++/* See pthread_barrier_wait for a description. */
++#define BARRIER_IN_THRESHOLD (UINT_MAX/2)
++
++
++/* Barrier variable attribute data structure. */
++struct pthread_barrierattr
++{
++ int pshared;
++};
++
++
++/* Thread-local data handling. */
++struct pthread_key_struct
++{
++ /* Sequence numbers. Even numbers indicated vacant entries. Note
++ that zero is even. We use uintptr_t to not require padding on
++ 32- and 64-bit machines. On 64-bit machines it helps to avoid
++ wrapping, too. */
++ uintptr_t seq;
++
++ /* Destructor for the data. */
++ void (*destr) (void *);
++};
++
++/* Check whether an entry is unused. */
++#define KEY_UNUSED(p) (((p) & 1) == 0)
++/* Check whether a key is usable. We cannot reuse an allocated key if
++ the sequence counter would overflow after the next destroy call.
++ This would mean that we potentially free memory for a key with the
++ same sequence. This is *very* unlikely to happen, A program would
++ have to create and destroy a key 2^31 times (on 32-bit platforms,
++ on 64-bit platforms that would be 2^63). If it should happen we
++ simply don't use this specific key anymore. */
++#define KEY_USABLE(p) (((uintptr_t) (p)) < ((uintptr_t) ((p) + 2)))
++
++
++/* Handling of read-write lock data. */
++// XXX For now there is only one flag. Maybe more in future.
++#define RWLOCK_RECURSIVE(rwlock) ((rwlock)->__data.__flags != 0)
++
++
++/* Semaphore variable structure. */
++struct new_sem
++{
++#if __HAVE_64B_ATOMICS
++ /* The data field holds both value (in the least-significant 32 bits) and
++ nwaiters. */
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++# define SEM_VALUE_OFFSET 0
++# elif __BYTE_ORDER == __BIG_ENDIAN
++# define SEM_VALUE_OFFSET 1
++# else
++# error Unsupported byte order.
++# endif
++# define SEM_NWAITERS_SHIFT 32
++# define SEM_VALUE_MASK (~(unsigned int)0)
++ uint64_t data;
++ int private;
++ int pad;
++#else
++# define SEM_VALUE_SHIFT 1
++# define SEM_NWAITERS_MASK ((unsigned int)1)
++ unsigned int value;
++ int private;
++ int pad;
++ unsigned int nwaiters;
++#endif
++};
++
++struct old_sem
++{
++ unsigned int value;
++};
++
++
++/* Compatibility type for old conditional variable interfaces. */
++typedef struct
++{
++ pthread_cond_t *cond;
++} pthread_cond_2_0_t;
++
++#endif /* internaltypes.h */
+diff --git a/nptl_2_17/kernel-features_2_17.h b/nptl_2_17/kernel-features_2_17.h
+new file mode 100644
+index 00000000..299ae0a1
+--- /dev/null
++++ b/nptl_2_17/kernel-features_2_17.h
+@@ -0,0 +1,162 @@
++/* Set flags signalling availability of kernel features based on given
++ kernel version number.
++ Copyright (C) 1999-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++/* This file must not contain any C code. At least it must be protected
++ to allow using the file also in assembler files. */
++
++#ifndef __LINUX_KERNEL_VERSION_2_17
++/* We assume the worst; all kernels should be supported. */
++# define __LINUX_KERNEL_VERSION_2_17 0
++#endif
++
++/* We assume for __LINUX_KERNEL_VERSION the same encoding used in
++ linux/version.h. I.e., the major, minor, and subminor all get a
++ byte with the major number being in the highest byte. This means
++ we can do numeric comparisons.
++
++ In the following we will define certain symbols depending on
++ whether the describes kernel feature is available in the kernel
++ version given by __LINUX_KERNEL_VERSION. We are not always exactly
++ recording the correct versions in which the features were
++ introduced. If somebody cares these values can afterwards be
++ corrected. */
++
++/* Some architectures use the socketcall multiplexer for some or all
++ socket-related operations instead of separate syscalls.
++ __ASSUME_SOCKETCALL is defined for such architectures. */
++
++/* The changed st_ino field appeared in 2.4.0-test6. However, SH is lame,
++ and still does not have a 64-bit inode field. */
++#define __ASSUME_ST_INO_64_BIT 1
++
++/* The statfs64 syscalls are available in 2.5.74 (but not for alpha). */
++#define __ASSUME_STATFS64 1
++
++/* pselect/ppoll were introduced just after 2.6.16-rc1. On x86_64 and
++ SH this appeared first in 2.6.19-rc1, on ia64 in 2.6.22-rc1. */
++#define __ASSUME_PSELECT 1
++
++/* The *at syscalls were introduced just after 2.6.16-rc1. On PPC
++ they were introduced in 2.6.17-rc1, on SH in 2.6.19-rc1. */
++#define __ASSUME_ATFCTS 1
++
++/* Support for inter-process robust mutexes was added in 2.6.17 (but
++ some architectures lack futex_atomic_cmpxchg_inatomic in some
++ configurations). */
++#define __ASSUME_SET_ROBUST_LIST 1
++
++/* Support for various CLOEXEC and NONBLOCK flags was added in
++ 2.6.27. */
++#define __ASSUME_IN_NONBLOCK 1
++
++/* Support for the FUTEX_CLOCK_REALTIME flag was added in 2.6.29. */
++#define __ASSUME_FUTEX_CLOCK_REALTIME 1
++
++/* Support for preadv and pwritev was added in 2.6.30. */
++#define __ASSUME_PREADV 1
++#define __ASSUME_PWRITEV 1
++
++
++/* Support for FUTEX_*_REQUEUE_PI was added in 2.6.31 (but some
++ * architectures lack futex_atomic_cmpxchg_inatomic in some
++ * configurations). */
++#define __ASSUME_REQUEUE_PI 1
++
++/* Support for sendmmsg functionality was added in 3.0. */
++#define __ASSUME_SENDMMSG 1
++
++/* On most architectures, most socket syscalls are supported for all
++ supported kernel versions, but on some socketcall architectures
++ separate syscalls were only added later. */
++#define __ASSUME_SENDMSG_SYSCALL 1
++#define __ASSUME_RECVMSG_SYSCALL 1
++#define __ASSUME_ACCEPT_SYSCALL 1
++#define __ASSUME_CONNECT_SYSCALL 1
++#define __ASSUME_RECVFROM_SYSCALL 1
++#define __ASSUME_SENDTO_SYSCALL 1
++#define __ASSUME_ACCEPT4_SYSCALL 1
++#define __ASSUME_RECVMMSG_SYSCALL 1
++#define __ASSUME_SENDMMSG_SYSCALL 1
++
++/* Support for SysV IPC through wired syscalls. All supported architectures
++ either support ipc syscall and/or all the ipc correspondent syscalls. */
++#define __ASSUME_DIRECT_SYSVIPC_SYSCALLS 1
++
++/* Support for p{read,write}v2 was added in 4.6. However Linux default
++ implementation does not assume the __ASSUME_* and instead use a fallback
++ implementation based on p{read,write}v and returning an error for
++ non supported flags. */
++
++/* Support for the renameat2 system call was added in kernel 3.15. */
++#if __LINUX_KERNEL_VERSION >= 0x030F00
++# define __ASSUME_RENAMEAT2
++#endif
++
++/* Support for the execveat syscall was added in 3.19. */
++#if __LINUX_KERNEL_VERSION >= 0x031300
++# define __ASSUME_EXECVEAT 1
++#endif
++
++#if __LINUX_KERNEL_VERSION >= 0x040400
++# define __ASSUME_MLOCK2 1
++#endif
++
++#if __LINUX_KERNEL_VERSION >= 0x040500
++# define __ASSUME_COPY_FILE_RANGE 1
++#endif
++
++/* Support for statx was added in kernel 4.11. */
++#if __LINUX_KERNEL_VERSION >= 0x040B00
++# define __ASSUME_STATX 1
++#endif
++
++/* Support for clone call used on fork. The signature varies across the
++ architectures with current 4 different variants:
++
++ 1. long int clone (unsigned long flags, unsigned long newsp,
++ int *parent_tidptr, unsigned long tls,
++ int *child_tidptr)
++
++ 2. long int clone (unsigned long newsp, unsigned long clone_flags,
++ int *parent_tidptr, int * child_tidptr,
++ unsigned long tls)
++
++ 3. long int clone (unsigned long flags, unsigned long newsp,
++ int stack_size, int *parent_tidptr,
++ int *child_tidptr, unsigned long tls)
++
++ 4. long int clone (unsigned long flags, unsigned long newsp,
++ int *parent_tidptr, int *child_tidptr,
++ unsigned long tls)
++
++ The fourth variant is intended to be used as the default for newer ports,
++ Also IA64 uses the third variant but with __NR_clone2 instead of
++ __NR_clone.
++
++ The macros names to define the variant used for the architecture is
++ similar to kernel:
++
++ - __ASSUME_CLONE_BACKWARDS: for variant 1.
++ - __ASSUME_CLONE_BACKWARDS2: for variant 2 (s390).
++ - __ASSUME_CLONE_BACKWARDS3: for variant 3 (microblaze).
++ - __ASSUME_CLONE_DEFAULT: for variant 4.
++ - __ASSUME_CLONE2: for clone2 with variant 3 (ia64).
++ */
++
++#define __ASSUME_CLONE_DEFAULT 1
+diff --git a/nptl_2_17/pthreadP_2_17.h b/nptl_2_17/pthreadP_2_17.h
+new file mode 100644
+index 00000000..3050fa54
+--- /dev/null
++++ b/nptl_2_17/pthreadP_2_17.h
+@@ -0,0 +1,714 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#ifndef _PTHREADP_H
++#define _PTHREADP_H 1
++
++
++#include <compat_pthread_2_17.h>
++#include "kernel-features_2_17.h"
++#include "pthread_2_17.h"
++#include "internaltypes_2_17.h"
++
++#include <setjmp.h>
++#include <stdbool.h>
++#include <sys/syscall.h>
++#include "descr.h"
++#include <tls.h>
++#include <lowlevellock.h>
++#include <stackinfo.h>
++#include <pthread-functions_2_17.h>
++#include <atomic.h>
++#include <errno.h>
++#include <internal-signals.h>
++
++/* Atomic operations on TLS memory. */
++#ifndef THREAD_ATOMIC_CMPXCHG_VAL
++# define THREAD_ATOMIC_CMPXCHG_VAL(descr, member, new, old) \
++ atomic_compare_and_exchange_val_acq (&(descr)->member, new, old)
++#endif
++
++#ifndef THREAD_ATOMIC_BIT_SET
++# define THREAD_ATOMIC_BIT_SET(descr, member, bit) \
++ atomic_bit_set (&(descr)->member, bit)
++#endif
++
++
++/* Adaptive mutex definitions. */
++#ifndef MAX_ADAPTIVE_COUNT
++# define MAX_ADAPTIVE_COUNT 100
++#endif
++
++
++/* Magic cookie representing robust mutex with dead owner. */
++#define PTHREAD_MUTEX_INCONSISTENT INT_MAX
++/* Magic cookie representing not recoverable robust mutex. */
++#define PTHREAD_MUTEX_NOTRECOVERABLE (INT_MAX - 1)
++
++
++/* Internal mutex type value. */
++enum
++{
++ PTHREAD_MUTEX_KIND_MASK_NP = 3,
++
++ PTHREAD_MUTEX_ELISION_NP = 256,
++ PTHREAD_MUTEX_NO_ELISION_NP = 512,
++
++ PTHREAD_MUTEX_ROBUST_NORMAL_NP = 16,
++ PTHREAD_MUTEX_ROBUST_RECURSIVE_NP
++ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP
++ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP
++ = PTHREAD_MUTEX_ROBUST_NORMAL_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
++ PTHREAD_MUTEX_PRIO_INHERIT_NP = 32,
++ PTHREAD_MUTEX_PI_NORMAL_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_NORMAL,
++ PTHREAD_MUTEX_PI_RECURSIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_PI_ERRORCHECK_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_PI_ADAPTIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
++ PTHREAD_MUTEX_PI_ROBUST_NORMAL_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP,
++ PTHREAD_MUTEX_PI_ROBUST_RECURSIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_RECURSIVE_NP,
++ PTHREAD_MUTEX_PI_ROBUST_ERRORCHECK_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ERRORCHECK_NP,
++ PTHREAD_MUTEX_PI_ROBUST_ADAPTIVE_NP
++ = PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_ADAPTIVE_NP,
++ PTHREAD_MUTEX_PRIO_PROTECT_NP = 64,
++ PTHREAD_MUTEX_PP_NORMAL_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_NORMAL,
++ PTHREAD_MUTEX_PP_RECURSIVE_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_PP_ERRORCHECK_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_PP_ADAPTIVE_NP
++ = PTHREAD_MUTEX_PRIO_PROTECT_NP | PTHREAD_MUTEX_ADAPTIVE_NP,
++ PTHREAD_MUTEX_ELISION_FLAGS_NP
++ = PTHREAD_MUTEX_ELISION_NP | PTHREAD_MUTEX_NO_ELISION_NP,
++
++ PTHREAD_MUTEX_TIMED_ELISION_NP =
++ PTHREAD_MUTEX_TIMED_NP | PTHREAD_MUTEX_ELISION_NP,
++ PTHREAD_MUTEX_TIMED_NO_ELISION_NP =
++ PTHREAD_MUTEX_TIMED_NP | PTHREAD_MUTEX_NO_ELISION_NP,
++};
++#define PTHREAD_MUTEX_PSHARED_BIT 128
++
++/* See concurrency notes regarding __kind in struct __pthread_mutex_s
++ in sysdeps/nptl/bits/thread-shared-types.h. */
++#define PTHREAD_MUTEX_TYPE(m) \
++ (atomic_load_relaxed (&((m)->__data.__kind)) & 127)
++/* Don't include NO_ELISION, as that type is always the same
++ as the underlying lock type. */
++#define PTHREAD_MUTEX_TYPE_ELISION(m) \
++ (atomic_load_relaxed (&((m)->__data.__kind)) \
++ & (127 | PTHREAD_MUTEX_ELISION_NP))
++
++#if LLL_PRIVATE == 0 && LLL_SHARED == 128
++# define PTHREAD_MUTEX_PSHARED(m) \
++ (atomic_load_relaxed (&((m)->__data.__kind)) & 128)
++#else
++# define PTHREAD_MUTEX_PSHARED(m) \
++ ((atomic_load_relaxed (&((m)->__data.__kind)) & 128) \
++ ? LLL_SHARED : LLL_PRIVATE)
++#endif
++
++/* The kernel when waking robust mutexes on exit never uses
++ FUTEX_PRIVATE_FLAG FUTEX_WAKE. */
++#define PTHREAD_ROBUST_MUTEX_PSHARED(m) LLL_SHARED
++
++/* Ceiling in __data.__lock. __data.__lock is signed, so don't
++ use the MSB bit in there, but in the mask also include that bit,
++ so that the compiler can optimize & PTHREAD_MUTEX_PRIO_CEILING_MASK
++ masking if the value is then shifted down by
++ PTHREAD_MUTEX_PRIO_CEILING_SHIFT. */
++#define PTHREAD_MUTEX_PRIO_CEILING_SHIFT 19
++#define PTHREAD_MUTEX_PRIO_CEILING_MASK 0xfff80000
++
++
++/* Flags in mutex attr. */
++#define PTHREAD_MUTEXATTR_PROTOCOL_SHIFT 28
++#define PTHREAD_MUTEXATTR_PROTOCOL_MASK 0x30000000
++#define PTHREAD_MUTEXATTR_PRIO_CEILING_SHIFT 12
++#define PTHREAD_MUTEXATTR_PRIO_CEILING_MASK 0x00fff000
++#define PTHREAD_MUTEXATTR_FLAG_ROBUST 0x40000000
++#define PTHREAD_MUTEXATTR_FLAG_PSHARED 0x80000000
++#define PTHREAD_MUTEXATTR_FLAG_BITS \
++ (PTHREAD_MUTEXATTR_FLAG_ROBUST | PTHREAD_MUTEXATTR_FLAG_PSHARED \
++ | PTHREAD_MUTEXATTR_PROTOCOL_MASK | PTHREAD_MUTEXATTR_PRIO_CEILING_MASK)
++
++
++/* For the following, see pthread_rwlock_common.c. */
++#define PTHREAD_RWLOCK_WRPHASE 1
++#define PTHREAD_RWLOCK_WRLOCKED 2
++#define PTHREAD_RWLOCK_RWAITING 4
++#define PTHREAD_RWLOCK_READER_SHIFT 3
++#define PTHREAD_RWLOCK_READER_OVERFLOW ((unsigned int) 1 \
++ << (sizeof (unsigned int) * 8 - 1))
++#define PTHREAD_RWLOCK_WRHANDOVER ((unsigned int) 1 \
++ << (sizeof (unsigned int) * 8 - 1))
++#define PTHREAD_RWLOCK_FUTEX_USED 2
++
++
++/* Bits used in robust mutex implementation. */
++#define FUTEX_WAITERS 0x80000000
++#define FUTEX_OWNER_DIED 0x40000000
++#define FUTEX_TID_MASK 0x3fffffff
++
++
++/* pthread_once definitions. See __pthread_once for how these are used. */
++#define __PTHREAD_ONCE_INPROGRESS 1
++#define __PTHREAD_ONCE_DONE 2
++#define __PTHREAD_ONCE_FORK_GEN_INCR 4
++
++/* Attribute to indicate thread creation was issued from C11 thrd_create. */
++#define ATTR_C11_THREAD ((void*)(uintptr_t)-1)
++
++#if 0
++/* Condition variable definitions. See __pthread_cond_wait_common.
++ Need to be defined here so there is one place from which
++ nptl_lock_constants can grab them. */
++#define __PTHREAD_COND_CLOCK_MONOTONIC_MASK 2
++#define __PTHREAD_COND_SHARED_MASK 1
++#endif
++
++/* Internal variables. */
++
++
++/* Default pthread attributes. */
++extern struct pthread_attr __default_pthread_attr attribute_hidden;
++extern int __default_pthread_attr_lock attribute_hidden;
++
++/* Size and alignment of static TLS block. */
++extern size_t __static_tls_size attribute_hidden;
++extern size_t __static_tls_align_m1 attribute_hidden;
++
++/* Flag whether the machine is SMP or not. */
++extern int __is_smp attribute_hidden;
++
++/* Thread descriptor handling. */
++extern list_t __stack_user;
++hidden_proto (__stack_user)
++
++/* Attribute handling. */
++extern struct pthread_attr *__attr_list attribute_hidden;
++extern int __attr_list_lock attribute_hidden;
++
++/* Concurrency handling. */
++extern int __concurrency_level attribute_hidden;
++
++/* Thread-local data key handling. */
++extern struct pthread_key_struct __pthread_keys[PTHREAD_KEYS_MAX];
++hidden_proto (__pthread_keys)
++
++/* Number of threads running. */
++extern unsigned int __nptl_nthreads attribute_hidden;
++
++#ifndef __ASSUME_SET_ROBUST_LIST
++/* Negative if we do not have the system call and we can use it. */
++extern int __set_robust_list_avail attribute_hidden;
++#endif
++
++/* Thread Priority Protection. */
++extern int __sched_fifo_min_prio attribute_hidden;
++extern int __sched_fifo_max_prio attribute_hidden;
++extern void __init_sched_fifo_prio (void) attribute_hidden;
++extern int __pthread_tpp_change_priority (int prev_prio, int new_prio)
++ attribute_hidden;
++extern int __pthread_current_priority (void) attribute_hidden;
++
++/* The library can run in debugging mode where it performs a lot more
++ tests. */
++extern int __pthread_debug attribute_hidden;
++/** For now disable debugging support. */
++#if 0
++# define DEBUGGING_P __builtin_expect (__pthread_debug, 0)
++# define INVALID_TD_P(pd) (DEBUGGING_P && __find_in_stack_list (pd) == NULL)
++# define INVALID_NOT_TERMINATED_TD_P(pd) INVALID_TD_P (pd)
++#else
++# define DEBUGGING_P 0
++/* Simplified test. This will not catch all invalid descriptors but
++ is better than nothing. And if the test triggers the thread
++ descriptor is guaranteed to be invalid. */
++# define INVALID_TD_P(pd) __builtin_expect ((pd)->tid <= 0, 0)
++# define INVALID_NOT_TERMINATED_TD_P(pd) __builtin_expect ((pd)->tid < 0, 0)
++#endif
++
++
++/* Cancellation test. */
++#define CANCELLATION_P(self) \
++ do { \
++ int cancelhandling = THREAD_GETMEM (self, cancelhandling); \
++ if (CANCEL_ENABLED_AND_CANCELED (cancelhandling)) \
++ { \
++ THREAD_SETMEM (self, result, PTHREAD_CANCELED); \
++ __do_cancel (); \
++ } \
++ } while (0)
++
++
++extern void __pthread_unwind (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute __attribute ((__noreturn__))
++ weak_function;
++extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute __attribute ((__noreturn__))
++ weak_function;
++extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++hidden_proto (__pthread_unwind)
++hidden_proto (__pthread_unwind_next)
++hidden_proto (__pthread_register_cancel)
++hidden_proto (__pthread_unregister_cancel)
++# ifdef SHARED
++extern void attribute_hidden pthread_cancel_init (void);
++# endif
++extern void __nptl_unwind_freeres (void) attribute_hidden;
++
++
++/* Called when a thread reacts on a cancellation request. */
++static inline void
++__attribute ((noreturn, always_inline))
++__do_cancel (void)
++{
++ struct pthread *self = THREAD_SELF;
++
++ /* Make sure we get no more cancellations. */
++ THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
++
++ __pthread_unwind ((__pthread_unwind_buf_t *)
++ THREAD_GETMEM (self, cleanup_jmp_buf));
++}
++
++
++/* Set cancellation mode to asynchronous. */
++#define CANCEL_ASYNC() \
++ __pthread_enable_asynccancel ()
++/* Reset to previous cancellation mode. */
++#define CANCEL_RESET(oldtype) \
++ __pthread_disable_asynccancel (oldtype)
++
++# undef LIBC_CANCEL_ASYNC
++# define LIBC_CANCEL_ASYNC() CANCEL_ASYNC ()
++
++# undef LIBC_CANCEL_RESET
++# define LIBC_CANCEL_RESET(val) CANCEL_RESET (val)
++
++# define LIBC_CANCEL_HANDLED() \
++ __asm (".globl " __SYMBOL_PREFIX "__pthread_enable_asynccancel"); \
++ __asm (".globl " __SYMBOL_PREFIX "__pthread_disable_asynccancel")
++
++
++/* Internal prototypes. */
++
++/* Thread list handling. */
++extern struct pthread *__find_in_stack_list (struct pthread *pd)
++ attribute_hidden;
++
++/* Deallocate a thread's stack after optionally making sure the thread
++ descriptor is still valid. */
++extern void __free_tcb (struct pthread *pd) attribute_hidden;
++
++/* Free allocated stack. */
++extern void __deallocate_stack (struct pthread *pd) attribute_hidden;
++
++/* Mark all the stacks except for the current one as available. This
++ function also re-initializes the lock for the stack cache. */
++extern void __reclaim_stacks (void) attribute_hidden;
++
++/* Make all threads's stacks executable. */
++extern int __make_stacks_executable (void **stack_endp) attribute_hidden;
++
++/* longjmp handling. */
++extern void __pthread_cleanup_upto (__jmp_buf target, char *targetframe);
++hidden_proto (__pthread_cleanup_upto)
++
++
++/* Functions with versioned interfaces. */
++extern int __pthread_create_2_1 (pthread_t *newthread,
++ const pthread_attr_t *attr,
++ void *(*start_routine) (void *), void *arg);
++extern int __pthread_create_2_0 (pthread_t *newthread,
++ const pthread_attr_t *attr,
++ void *(*start_routine) (void *), void *arg);
++extern int __pthread_attr_init_2_1 (pthread_attr_t *attr);
++extern int __pthread_attr_init_2_0 (pthread_attr_t *attr);
++
++
++/* Event handlers for libthread_db interface. */
++extern void __nptl_create_event (void);
++extern void __nptl_death_event (void);
++hidden_proto (__nptl_create_event)
++hidden_proto (__nptl_death_event)
++
++/* Register the generation counter in the libpthread with the libc. */
++#ifdef TLS_MULTIPLE_THREADS_IN_TCB
++extern void __libc_pthread_init (unsigned long int *ptr,
++ void (*reclaim) (void),
++ const struct pthread_functions *functions);
++#else
++extern int *__libc_pthread_init (unsigned long int *ptr,
++ void (*reclaim) (void),
++ const struct pthread_functions *functions);
++
++/* Variable set to a nonzero value either if more than one thread runs or ran,
++ or if a single-threaded process is trying to cancel itself. See
++ nptl/descr.h for more context on the single-threaded process case. */
++extern int __pthread_multiple_threads attribute_hidden;
++/* Pointer to the corresponding variable in libc. */
++extern int *__libc_multiple_threads_ptr attribute_hidden;
++#endif
++
++/* Find a thread given its TID. */
++extern struct pthread *__find_thread_by_id (pid_t tid) attribute_hidden
++#ifdef SHARED
++;
++#else
++weak_function;
++#define __find_thread_by_id(tid) \
++ (__find_thread_by_id ? (__find_thread_by_id) (tid) : (struct pthread *) NULL)
++#endif
++
++extern void __pthread_init_static_tls (struct link_map *) attribute_hidden;
++
++extern size_t __pthread_get_minstack (const pthread_attr_t *attr);
++
++/* Namespace save aliases. */
++extern int __pthread_getschedparam (pthread_t thread_id, int *policy,
++ struct sched_param *param);
++extern int __pthread_setschedparam (pthread_t thread_id, int policy,
++ const struct sched_param *param);
++extern int __pthread_setcancelstate (int state, int *oldstate);
++extern int __pthread_mutex_init (pthread_mutex_t *__mutex,
++ const pthread_mutexattr_t *__mutexattr);
++extern int __pthread_mutex_destroy (pthread_mutex_t *__mutex);
++extern int __pthread_mutex_trylock (pthread_mutex_t *_mutex);
++extern int __pthread_mutex_lock (pthread_mutex_t *__mutex);
++extern int __pthread_mutex_timedlock (pthread_mutex_t *__mutex,
++ const struct timespec *__abstime);
++extern int __pthread_mutex_cond_lock (pthread_mutex_t *__mutex)
++ attribute_hidden;
++extern void __pthread_mutex_cond_lock_adjust (pthread_mutex_t *__mutex)
++ attribute_hidden;
++extern int __pthread_mutex_unlock (pthread_mutex_t *__mutex);
++extern int __pthread_mutex_unlock_usercnt (pthread_mutex_t *__mutex,
++ int __decr) attribute_hidden;
++extern int __pthread_mutexattr_init (pthread_mutexattr_t *attr);
++extern int __pthread_mutexattr_destroy (pthread_mutexattr_t *attr);
++extern int __pthread_mutexattr_settype (pthread_mutexattr_t *attr, int kind);
++extern int __pthread_attr_destroy (pthread_attr_t *attr);
++extern int __pthread_attr_getdetachstate (const pthread_attr_t *attr,
++ int *detachstate);
++extern int __pthread_attr_setdetachstate (pthread_attr_t *attr,
++ int detachstate);
++extern int __pthread_attr_getinheritsched (const pthread_attr_t *attr,
++ int *inherit);
++extern int __pthread_attr_setinheritsched (pthread_attr_t *attr, int inherit);
++extern int __pthread_attr_getschedparam (const pthread_attr_t *attr,
++ struct sched_param *param);
++extern int __pthread_attr_setschedparam (pthread_attr_t *attr,
++ const struct sched_param *param);
++extern int __pthread_attr_getschedpolicy (const pthread_attr_t *attr,
++ int *policy);
++extern int __pthread_attr_setschedpolicy (pthread_attr_t *attr, int policy);
++extern int __pthread_attr_getscope (const pthread_attr_t *attr, int *scope);
++extern int __pthread_attr_setscope (pthread_attr_t *attr, int scope);
++extern int __pthread_attr_getstackaddr (const pthread_attr_t *__restrict
++ __attr, void **__restrict __stackaddr);
++extern int __pthread_attr_setstackaddr (pthread_attr_t *__attr,
++ void *__stackaddr);
++extern int __pthread_attr_getstacksize (const pthread_attr_t *__restrict
++ __attr,
++ size_t *__restrict __stacksize);
++extern int __pthread_attr_setstacksize (pthread_attr_t *__attr,
++ size_t __stacksize);
++extern int __pthread_attr_getstack (const pthread_attr_t *__restrict __attr,
++ void **__restrict __stackaddr,
++ size_t *__restrict __stacksize);
++extern int __pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
++ size_t __stacksize);
++extern int __pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
++ const pthread_rwlockattr_t *__restrict
++ __attr);
++extern int __pthread_rwlock_destroy (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_rwlock_unlock (pthread_rwlock_t *__rwlock);
++extern int __pthread_cond_broadcast (pthread_cond_t *cond);
++extern int __pthread_cond_destroy (pthread_cond_t *cond);
++extern int __pthread_cond_init (pthread_cond_t *cond,
++ const pthread_condattr_t *cond_attr);
++extern int __pthread_cond_signal (pthread_cond_t *cond);
++extern int __pthread_cond_wait (pthread_cond_t *cond, pthread_mutex_t *mutex);
++extern int __pthread_cond_timedwait (pthread_cond_t *cond,
++ pthread_mutex_t *mutex,
++ const struct timespec *abstime);
++extern int __pthread_cond_clockwait (pthread_cond_t *cond,
++ pthread_mutex_t *mutex,
++ clockid_t clockid,
++ const struct timespec *abstime)
++ __nonnull ((1, 2, 4));
++extern int __pthread_condattr_destroy (pthread_condattr_t *attr);
++extern int __pthread_condattr_init (pthread_condattr_t *attr);
++extern int __pthread_key_create (pthread_key_t *key, void (*destr) (void *));
++extern int __pthread_key_delete (pthread_key_t key);
++extern void *__pthread_getspecific (pthread_key_t key);
++extern int __pthread_setspecific (pthread_key_t key, const void *value);
++extern int __pthread_once (pthread_once_t *once_control,
++ void (*init_routine) (void));
++extern int __pthread_atfork (void (*prepare) (void), void (*parent) (void),
++ void (*child) (void));
++extern pthread_t __pthread_self (void);
++extern int __pthread_equal (pthread_t thread1, pthread_t thread2);
++extern int __pthread_detach (pthread_t th);
++extern int __pthread_cancel (pthread_t th);
++extern int __pthread_kill (pthread_t threadid, int signo);
++extern void __pthread_exit (void *value) __attribute__ ((__noreturn__));
++extern int __pthread_join (pthread_t threadid, void **thread_return);
++extern int __pthread_setcanceltype (int type, int *oldtype);
++extern int __pthread_enable_asynccancel (void) attribute_hidden;
++extern void __pthread_disable_asynccancel (int oldtype) attribute_hidden;
++extern void __pthread_testcancel (void);
++extern int __pthread_timedjoin_ex (pthread_t, void **, const struct timespec *,
++ bool);
++
++hidden_proto (__pthread_mutex_init)
++hidden_proto (__pthread_mutex_destroy)
++hidden_proto (__pthread_mutex_lock)
++hidden_proto (__pthread_mutex_trylock)
++hidden_proto (__pthread_mutex_unlock)
++hidden_proto (__pthread_rwlock_rdlock)
++hidden_proto (__pthread_rwlock_wrlock)
++hidden_proto (__pthread_rwlock_unlock)
++hidden_proto (__pthread_key_create)
++hidden_proto (__pthread_getspecific)
++hidden_proto (__pthread_setspecific)
++hidden_proto (__pthread_once)
++hidden_proto (__pthread_setcancelstate)
++hidden_proto (__pthread_testcancel)
++hidden_proto (__pthread_mutexattr_init)
++hidden_proto (__pthread_mutexattr_settype)
++hidden_proto (__pthread_timedjoin_ex)
++
++extern int __pthread_cond_broadcast_2_0 (pthread_cond_2_0_t *cond);
++extern int __pthread_cond_destroy_2_0 (pthread_cond_2_0_t *cond);
++extern int __pthread_cond_init_2_0 (pthread_cond_2_0_t *cond,
++ const pthread_condattr_t *cond_attr);
++extern int __pthread_cond_signal_2_0 (pthread_cond_2_0_t *cond);
++extern int __pthread_cond_timedwait_2_0 (pthread_cond_2_0_t *cond,
++ pthread_mutex_t *mutex,
++ const struct timespec *abstime);
++extern int __pthread_cond_wait_2_0 (pthread_cond_2_0_t *cond,
++ pthread_mutex_t *mutex);
++
++extern int __pthread_getaffinity_np (pthread_t th, size_t cpusetsize,
++ cpu_set_t *cpuset);
++
++/* The two functions are in libc.so and not exported. */
++extern int __libc_enable_asynccancel (void) attribute_hidden;
++extern void __libc_disable_asynccancel (int oldtype) attribute_hidden;
++
++
++/* The two functions are in librt.so and not exported. */
++extern int __librt_enable_asynccancel (void) attribute_hidden;
++extern void __librt_disable_asynccancel (int oldtype) attribute_hidden;
++
++/* Special versions which use non-exported functions. */
++extern void __pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg)
++ attribute_hidden;
++
++/* Replace cleanup macros defined in <pthread.h> with internal
++ versions that don't depend on unwind info and better support
++ cancellation. */
++# undef pthread_cleanup_push
++# define pthread_cleanup_push(routine,arg) \
++ { struct _pthread_cleanup_buffer _buffer; \
++ __pthread_cleanup_push (&_buffer, (routine), (arg));
++
++extern void __pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
++ int execute) attribute_hidden;
++# undef pthread_cleanup_pop
++# define pthread_cleanup_pop(execute) \
++ __pthread_cleanup_pop (&_buffer, (execute)); }
++
++# if defined __EXCEPTIONS && !defined __cplusplus
++/* Structure to hold the cleanup handler information. */
++struct __pthread_cleanup_combined_frame
++{
++ void (*__cancel_routine) (void *);
++ void *__cancel_arg;
++ int __do_it;
++ struct _pthread_cleanup_buffer __buffer;
++};
++
++/* Special cleanup macros which register cleanup both using
++ __pthread_cleanup_{push,pop} and using cleanup attribute. This is needed
++ for pthread_once, so that it supports both throwing exceptions from the
++ pthread_once callback (only cleanup attribute works there) and cancellation
++ of the thread running the callback if the callback or some routines it
++ calls don't have unwind information. */
++
++static __always_inline void
++__pthread_cleanup_combined_routine (struct __pthread_cleanup_combined_frame
++ *__frame)
++{
++ if (__frame->__do_it)
++ {
++ __frame->__cancel_routine (__frame->__cancel_arg);
++ __frame->__do_it = 0;
++ __pthread_cleanup_pop (&__frame->__buffer, 0);
++ }
++}
++
++static inline void
++__pthread_cleanup_combined_routine_voidptr (void *__arg)
++{
++ struct __pthread_cleanup_combined_frame *__frame
++ = (struct __pthread_cleanup_combined_frame *) __arg;
++ if (__frame->__do_it)
++ {
++ __frame->__cancel_routine (__frame->__cancel_arg);
++ __frame->__do_it = 0;
++ }
++}
++
++# define pthread_cleanup_combined_push(routine, arg) \
++ do { \
++ void (*__cancel_routine) (void *) = (routine); \
++ struct __pthread_cleanup_combined_frame __clframe \
++ __attribute__ ((__cleanup__ (__pthread_cleanup_combined_routine))) \
++ = { .__cancel_routine = __cancel_routine, .__cancel_arg = (arg), \
++ .__do_it = 1 }; \
++ __pthread_cleanup_push (&__clframe.__buffer, \
++ __pthread_cleanup_combined_routine_voidptr, \
++ &__clframe);
++
++# define pthread_cleanup_combined_pop(execute) \
++ __pthread_cleanup_pop (&__clframe.__buffer, 0); \
++ __clframe.__do_it = 0; \
++ if (execute) \
++ __cancel_routine (__clframe.__cancel_arg); \
++ } while (0)
++
++# endif
++
++extern void __pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg);
++extern void __pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
++ int execute);
++
++/* Old cleanup interfaces, still used in libc.so. */
++extern void _pthread_cleanup_push (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg);
++extern void _pthread_cleanup_pop (struct _pthread_cleanup_buffer *buffer,
++ int execute);
++extern void _pthread_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer,
++ void (*routine) (void *), void *arg);
++extern void _pthread_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer,
++ int execute);
++
++extern void __nptl_deallocate_tsd (void) attribute_hidden;
++
++extern void __nptl_setxid_error (struct xid_command *cmdp, int error)
++ attribute_hidden;
++extern int __nptl_setxid (struct xid_command *cmdp) attribute_hidden;
++#ifndef SHARED
++extern void __nptl_set_robust (struct pthread *self);
++#endif
++
++extern void __nptl_stacks_freeres (void) attribute_hidden;
++extern void __shm_directory_freeres (void) attribute_hidden;
++
++extern void __wait_lookup_done (void) attribute_hidden;
++
++#ifdef SHARED
++# define PTHREAD_STATIC_FN_REQUIRE(name)
++#else
++# define PTHREAD_STATIC_FN_REQUIRE(name) __asm (".globl " #name);
++#endif
++
++/* Test if the mutex is suitable for the FUTEX_WAIT_REQUEUE_PI operation. */
++#if (defined lll_futex_wait_requeue_pi \
++ && defined __ASSUME_REQUEUE_PI)
++# define USE_REQUEUE_PI(mut) \
++ ((mut) && (mut) != (void *) ~0l \
++ && (((mut)->__data.__kind \
++ & (PTHREAD_MUTEX_PRIO_INHERIT_NP | PTHREAD_MUTEX_ROBUST_NORMAL_NP)) \
++ == PTHREAD_MUTEX_PRIO_INHERIT_NP))
++#else
++# define USE_REQUEUE_PI(mut) 0
++#endif
++
++
++/* Returns 0 if POL is a valid scheduling policy. */
++static inline int
++check_sched_policy_attr (int pol)
++{
++ if (pol == SCHED_OTHER || pol == SCHED_FIFO || pol == SCHED_RR)
++ return 0;
++
++ return EINVAL;
++}
++
++/* Returns 0 if PR is within the accepted range of priority values for
++ the scheduling policy POL or EINVAL otherwise. */
++static inline int
++check_sched_priority_attr (int pr, int pol)
++{
++ int min = __sched_get_priority_min (pol);
++ int max = __sched_get_priority_max (pol);
++
++ if (min >= 0 && max >= 0 && pr >= min && pr <= max)
++ return 0;
++
++ return EINVAL;
++}
++
++/* Returns 0 if ST is a valid stack size for a thread stack and EINVAL
++ otherwise. */
++static inline int
++check_stacksize_attr (size_t st)
++{
++ if (st >= PTHREAD_STACK_MIN)
++ return 0;
++
++ return EINVAL;
++}
++
++#define ASSERT_TYPE_SIZE(type, size) \
++ _Static_assert (sizeof (type) == size, \
++ "sizeof (" #type ") != " #size)
++
++#define ASSERT_PTHREAD_INTERNAL_SIZE(type, internal) \
++ _Static_assert (sizeof ((type) { { 0 } }).__size >= sizeof (internal),\
++ "sizeof (" #type ".__size) < sizeof (" #internal ")")
++
++#define ASSERT_PTHREAD_STRING(x) __STRING (x)
++#define ASSERT_PTHREAD_INTERNAL_OFFSET(type, member, offset) \
++ _Static_assert (offsetof (type, member) == offset, \
++ "offset of " #member " field of " #type " != " \
++ ASSERT_PTHREAD_STRING (offset))
++
++#endif /* pthreadP.h */
+diff --git a/nptl_2_17/pthread_2_17.h b/nptl_2_17/pthread_2_17.h
+new file mode 100644
+index 00000000..3cb871a2
+--- /dev/null
++++ b/nptl_2_17/pthread_2_17.h
+@@ -0,0 +1,1175 @@
++/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#ifndef _PTHREAD_H
++#define _PTHREAD_H 1
++
++#include "bits/pthreadtypes_2_17.h"
++
++#include <features.h>
++#include <endian.h>
++#include <sched.h>
++#include <time.h>
++
++#include <bits/setjmp.h>
++#include <bits/wordsize.h>
++#include <bits/types/struct_timespec.h>
++
++
++/* Detach state. */
++enum
++{
++ PTHREAD_CREATE_JOINABLE,
++#define PTHREAD_CREATE_JOINABLE PTHREAD_CREATE_JOINABLE
++ PTHREAD_CREATE_DETACHED
++#define PTHREAD_CREATE_DETACHED PTHREAD_CREATE_DETACHED
++};
++
++
++/* Mutex types. */
++enum
++{
++ PTHREAD_MUTEX_TIMED_NP,
++ PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_ADAPTIVE_NP
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
++ ,
++ PTHREAD_MUTEX_NORMAL = PTHREAD_MUTEX_TIMED_NP,
++ PTHREAD_MUTEX_RECURSIVE = PTHREAD_MUTEX_RECURSIVE_NP,
++ PTHREAD_MUTEX_ERRORCHECK = PTHREAD_MUTEX_ERRORCHECK_NP,
++ PTHREAD_MUTEX_DEFAULT = PTHREAD_MUTEX_NORMAL
++#endif
++#ifdef __USE_GNU
++ /* For compatibility. */
++ , PTHREAD_MUTEX_FAST_NP = PTHREAD_MUTEX_TIMED_NP
++#endif
++};
++
++
++#ifdef __USE_XOPEN2K
++/* Robust mutex or not flags. */
++enum
++{
++ PTHREAD_MUTEX_STALLED,
++ PTHREAD_MUTEX_STALLED_NP = PTHREAD_MUTEX_STALLED,
++ PTHREAD_MUTEX_ROBUST,
++ PTHREAD_MUTEX_ROBUST_NP = PTHREAD_MUTEX_ROBUST
++};
++#endif
++
++
++#if defined __USE_POSIX199506 || defined __USE_UNIX98
++/* Mutex protocols. */
++enum
++{
++ PTHREAD_PRIO_NONE,
++ PTHREAD_PRIO_INHERIT,
++ PTHREAD_PRIO_PROTECT
++};
++#endif
++
++
++#if __PTHREAD_MUTEX_HAVE_PREV
++# define PTHREAD_MUTEX_INITIALIZER \
++ { { 0, 0, 0, 0, 0, __PTHREAD_SPINS, { 0, 0 } } }
++# ifdef __USE_GNU
++# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
++ { { 0, 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, __PTHREAD_SPINS, { 0, 0 } } }
++# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
++ { { 0, 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, __PTHREAD_SPINS, { 0, 0 } } }
++# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
++ { { 0, 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, __PTHREAD_SPINS, { 0, 0 } } }
++
++# endif
++#else
++# define PTHREAD_MUTEX_INITIALIZER \
++ { { 0, 0, 0, 0, 0, { __PTHREAD_SPINS } } }
++# ifdef __USE_GNU
++# define PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP \
++ { { 0, 0, 0, PTHREAD_MUTEX_RECURSIVE_NP, 0, { __PTHREAD_SPINS } } }
++# define PTHREAD_ERRORCHECK_MUTEX_INITIALIZER_NP \
++ { { 0, 0, 0, PTHREAD_MUTEX_ERRORCHECK_NP, 0, { __PTHREAD_SPINS } } }
++# define PTHREAD_ADAPTIVE_MUTEX_INITIALIZER_NP \
++ { { 0, 0, 0, PTHREAD_MUTEX_ADAPTIVE_NP, 0, { __PTHREAD_SPINS } } }
++
++# endif
++#endif
++
++
++/* Read-write lock types. */
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K
++enum
++{
++ PTHREAD_RWLOCK_PREFER_READER_NP,
++ PTHREAD_RWLOCK_PREFER_WRITER_NP,
++ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,
++ PTHREAD_RWLOCK_DEFAULT_NP = PTHREAD_RWLOCK_PREFER_READER_NP
++};
++
++/* Define __PTHREAD_RWLOCK_INT_FLAGS_SHARED to 1 if pthread_rwlock_t
++ has the shared field. All 64-bit architectures have the shared field
++ in pthread_rwlock_t. */
++#ifndef __PTHREAD_RWLOCK_INT_FLAGS_SHARED
++# if __WORDSIZE == 64
++# define __PTHREAD_RWLOCK_INT_FLAGS_SHARED 1
++# endif
++#endif
++
++/* Read-write lock initializers. */
++# define PTHREAD_RWLOCK_INITIALIZER \
++ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } }
++# ifdef __USE_GNU
++# ifdef __PTHREAD_RWLOCK_INT_FLAGS_SHARED
++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
++ { { 0, 0, 0, 0, 0, 0, 0, 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, \
++ PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP } }
++# else
++# if __BYTE_ORDER == __LITTLE_ENDIAN
++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
++ { { 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP, \
++ 0, __PTHREAD_RWLOCK_ELISION_EXTRA, 0, 0 } }
++# else
++# define PTHREAD_RWLOCK_WRITER_NONRECURSIVE_INITIALIZER_NP \
++ { { 0, 0, 0, 0, 0, 0, 0, 0, 0, PTHREAD_RWLOCK_PREFER_WRITER_NONRECURSIVE_NP,\
++ 0 } }
++# endif
++# endif
++# endif
++#endif /* Unix98 or XOpen2K */
++
++
++/* Scheduler inheritance. */
++enum
++{
++ PTHREAD_INHERIT_SCHED,
++#define PTHREAD_INHERIT_SCHED PTHREAD_INHERIT_SCHED
++ PTHREAD_EXPLICIT_SCHED
++#define PTHREAD_EXPLICIT_SCHED PTHREAD_EXPLICIT_SCHED
++};
++
++
++/* Scope handling. */
++enum
++{
++ PTHREAD_SCOPE_SYSTEM,
++#define PTHREAD_SCOPE_SYSTEM PTHREAD_SCOPE_SYSTEM
++ PTHREAD_SCOPE_PROCESS
++#define PTHREAD_SCOPE_PROCESS PTHREAD_SCOPE_PROCESS
++};
++
++
++/* Process shared or private flag. */
++enum
++{
++ PTHREAD_PROCESS_PRIVATE,
++#define PTHREAD_PROCESS_PRIVATE PTHREAD_PROCESS_PRIVATE
++ PTHREAD_PROCESS_SHARED
++#define PTHREAD_PROCESS_SHARED PTHREAD_PROCESS_SHARED
++};
++
++
++
++/* Conditional variable handling. */
++#define PTHREAD_COND_INITIALIZER { { 0, 0, 0, 0, 0, (void *) 0, 0, 0 } }
++
++/* Cleanup buffers */
++struct _pthread_cleanup_buffer
++{
++ void (*__routine) (void *); /* Function to call. */
++ void *__arg; /* Its argument. */
++ int __canceltype; /* Saved cancellation type. */
++ struct _pthread_cleanup_buffer *__prev; /* Chaining of cleanup functions. */
++};
++
++/* Cancellation */
++enum
++{
++ PTHREAD_CANCEL_ENABLE,
++#define PTHREAD_CANCEL_ENABLE PTHREAD_CANCEL_ENABLE
++ PTHREAD_CANCEL_DISABLE
++#define PTHREAD_CANCEL_DISABLE PTHREAD_CANCEL_DISABLE
++};
++enum
++{
++ PTHREAD_CANCEL_DEFERRED,
++#define PTHREAD_CANCEL_DEFERRED PTHREAD_CANCEL_DEFERRED
++ PTHREAD_CANCEL_ASYNCHRONOUS
++#define PTHREAD_CANCEL_ASYNCHRONOUS PTHREAD_CANCEL_ASYNCHRONOUS
++};
++#define PTHREAD_CANCELED ((void *) -1)
++
++
++/* Single execution handling. */
++#define PTHREAD_ONCE_INIT 0
++
++
++#ifdef __USE_XOPEN2K
++/* Value returned by 'pthread_barrier_wait' for one of the threads after
++ the required number of threads have called this function.
++ -1 is distinct from 0 and all errno constants */
++# define PTHREAD_BARRIER_SERIAL_THREAD -1
++#endif
++
++
++__BEGIN_DECLS
++
++/* Create a new thread, starting with execution of START-ROUTINE
++ getting passed ARG. Creation attributed come from ATTR. The new
++ handle is stored in *NEWTHREAD. */
++extern int pthread_create (pthread_t *__restrict __newthread,
++ const pthread_attr_t *__restrict __attr,
++ void *(*__start_routine) (void *),
++ void *__restrict __arg) __THROWNL __nonnull ((1, 3));
++
++/* Terminate calling thread.
++
++ The registered cleanup handlers are called via exception handling
++ so we cannot mark this function with __THROW.*/
++extern void pthread_exit (void *__retval) __attribute__ ((__noreturn__));
++
++/* Make calling thread wait for termination of the thread TH. The
++ exit status of the thread is stored in *THREAD_RETURN, if THREAD_RETURN
++ is not NULL.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_join (pthread_t __th, void **__thread_return);
++
++#ifdef __USE_GNU
++/* Check whether thread TH has terminated. If yes return the status of
++ the thread in *THREAD_RETURN, if THREAD_RETURN is not NULL. */
++extern int pthread_tryjoin_np (pthread_t __th, void **__thread_return) __THROW;
++
++/* Make calling thread wait for termination of the thread TH, but only
++ until TIMEOUT. The exit status of the thread is stored in
++ *THREAD_RETURN, if THREAD_RETURN is not NULL.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_timedjoin_np (pthread_t __th, void **__thread_return,
++ const struct timespec *__abstime);
++#endif
++
++/* Indicate that the thread TH is never to be joined with PTHREAD_JOIN.
++ The resources of TH will therefore be freed immediately when it
++ terminates, instead of waiting for another thread to perform PTHREAD_JOIN
++ on it. */
++extern int pthread_detach (pthread_t __th) __THROW;
++
++
++/* Obtain the identifier of the current thread. */
++extern pthread_t pthread_self (void) __THROW __attribute__ ((__const__));
++
++/* Compare two thread identifiers. */
++extern int pthread_equal (pthread_t __thread1, pthread_t __thread2)
++ __THROW __attribute__ ((__const__));
++
++
++/* Thread attribute handling. */
++
++/* Initialize thread attribute *ATTR with default attributes
++ (detachstate is PTHREAD_JOINABLE, scheduling policy is SCHED_OTHER,
++ no user-provided stack). */
++extern int pthread_attr_init (pthread_attr_t *__attr) __THROW __nonnull ((1));
++
++/* Destroy thread attribute *ATTR. */
++extern int pthread_attr_destroy (pthread_attr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get detach state attribute. */
++extern int pthread_attr_getdetachstate (const pthread_attr_t *__attr,
++ int *__detachstate)
++ __THROW __nonnull ((1, 2));
++
++/* Set detach state attribute. */
++extern int pthread_attr_setdetachstate (pthread_attr_t *__attr,
++ int __detachstate)
++ __THROW __nonnull ((1));
++
++
++/* Get the size of the guard area created for stack overflow protection. */
++extern int pthread_attr_getguardsize (const pthread_attr_t *__attr,
++ size_t *__guardsize)
++ __THROW __nonnull ((1, 2));
++
++/* Set the size of the guard area created for stack overflow protection. */
++extern int pthread_attr_setguardsize (pthread_attr_t *__attr,
++ size_t __guardsize)
++ __THROW __nonnull ((1));
++
++
++/* Return in *PARAM the scheduling parameters of *ATTR. */
++extern int pthread_attr_getschedparam (const pthread_attr_t *__restrict __attr,
++ struct sched_param *__restrict __param)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling parameters (priority, etc) in *ATTR according to PARAM. */
++extern int pthread_attr_setschedparam (pthread_attr_t *__restrict __attr,
++ const struct sched_param *__restrict
++ __param) __THROW __nonnull ((1, 2));
++
++/* Return in *POLICY the scheduling policy of *ATTR. */
++extern int pthread_attr_getschedpolicy (const pthread_attr_t *__restrict
++ __attr, int *__restrict __policy)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling policy in *ATTR according to POLICY. */
++extern int pthread_attr_setschedpolicy (pthread_attr_t *__attr, int __policy)
++ __THROW __nonnull ((1));
++
++/* Return in *INHERIT the scheduling inheritance mode of *ATTR. */
++extern int pthread_attr_getinheritsched (const pthread_attr_t *__restrict
++ __attr, int *__restrict __inherit)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling inheritance mode in *ATTR according to INHERIT. */
++extern int pthread_attr_setinheritsched (pthread_attr_t *__attr,
++ int __inherit)
++ __THROW __nonnull ((1));
++
++
++/* Return in *SCOPE the scheduling contention scope of *ATTR. */
++extern int pthread_attr_getscope (const pthread_attr_t *__restrict __attr,
++ int *__restrict __scope)
++ __THROW __nonnull ((1, 2));
++
++/* Set scheduling contention scope in *ATTR according to SCOPE. */
++extern int pthread_attr_setscope (pthread_attr_t *__attr, int __scope)
++ __THROW __nonnull ((1));
++
++/* Return the previously set address for the stack. */
++extern int pthread_attr_getstackaddr (const pthread_attr_t *__restrict
++ __attr, void **__restrict __stackaddr)
++ __THROW __nonnull ((1, 2)) __attribute_deprecated__;
++
++/* Set the starting address of the stack of the thread to be created.
++ Depending on whether the stack grows up or down the value must either
++ be higher or lower than all the address in the memory block. The
++ minimal size of the block must be PTHREAD_STACK_MIN. */
++extern int pthread_attr_setstackaddr (pthread_attr_t *__attr,
++ void *__stackaddr)
++ __THROW __nonnull ((1)) __attribute_deprecated__;
++
++/* Return the currently used minimal stack size. */
++extern int pthread_attr_getstacksize (const pthread_attr_t *__restrict
++ __attr, size_t *__restrict __stacksize)
++ __THROW __nonnull ((1, 2));
++
++/* Add information about the minimum stack size needed for the thread
++ to be started. This size must never be less than PTHREAD_STACK_MIN
++ and must also not exceed the system limits. */
++extern int pthread_attr_setstacksize (pthread_attr_t *__attr,
++ size_t __stacksize)
++ __THROW __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Return the previously set address for the stack. */
++extern int pthread_attr_getstack (const pthread_attr_t *__restrict __attr,
++ void **__restrict __stackaddr,
++ size_t *__restrict __stacksize)
++ __THROW __nonnull ((1, 2, 3));
++
++/* The following two interfaces are intended to replace the last two. They
++ require setting the address as well as the size since only setting the
++ address will make the implementation on some architectures impossible. */
++extern int pthread_attr_setstack (pthread_attr_t *__attr, void *__stackaddr,
++ size_t __stacksize) __THROW __nonnull ((1));
++#endif
++
++#ifdef __USE_GNU
++/* Thread created with attribute ATTR will be limited to run only on
++ the processors represented in CPUSET. */
++extern int pthread_attr_setaffinity_np (pthread_attr_t *__attr,
++ size_t __cpusetsize,
++ const cpu_set_t *__cpuset)
++ __THROW __nonnull ((1, 3));
++
++/* Get bit set in CPUSET representing the processors threads created with
++ ATTR can run on. */
++extern int pthread_attr_getaffinity_np (const pthread_attr_t *__attr,
++ size_t __cpusetsize,
++ cpu_set_t *__cpuset)
++ __THROW __nonnull ((1, 3));
++
++/* Get the default attributes used by pthread_create in this process. */
++extern int pthread_getattr_default_np (pthread_attr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Set the default attributes to be used by pthread_create in this
++ process. */
++extern int pthread_setattr_default_np (const pthread_attr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Initialize thread attribute *ATTR with attributes corresponding to the
++ already running thread TH. It shall be called on uninitialized ATTR
++ and destroyed with pthread_attr_destroy when no longer needed. */
++extern int pthread_getattr_np (pthread_t __th, pthread_attr_t *__attr)
++ __THROW __nonnull ((2));
++#endif
++
++
++/* Functions for scheduling control. */
++
++/* Set the scheduling parameters for TARGET_THREAD according to POLICY
++ and *PARAM. */
++extern int pthread_setschedparam (pthread_t __target_thread, int __policy,
++ const struct sched_param *__param)
++ __THROW __nonnull ((3));
++
++/* Return in *POLICY and *PARAM the scheduling parameters for TARGET_THREAD. */
++extern int pthread_getschedparam (pthread_t __target_thread,
++ int *__restrict __policy,
++ struct sched_param *__restrict __param)
++ __THROW __nonnull ((2, 3));
++
++/* Set the scheduling priority for TARGET_THREAD. */
++extern int pthread_setschedprio (pthread_t __target_thread, int __prio)
++ __THROW;
++
++
++#ifdef __USE_GNU
++/* Get thread name visible in the kernel and its interfaces. */
++extern int pthread_getname_np (pthread_t __target_thread, char *__buf,
++ size_t __buflen)
++ __THROW __nonnull ((2));
++
++/* Set thread name visible in the kernel and its interfaces. */
++extern int pthread_setname_np (pthread_t __target_thread, const char *__name)
++ __THROW __nonnull ((2));
++#endif
++
++
++#ifdef __USE_UNIX98
++/* Determine level of concurrency. */
++extern int pthread_getconcurrency (void) __THROW;
++
++/* Set new concurrency level to LEVEL. */
++extern int pthread_setconcurrency (int __level) __THROW;
++#endif
++
++#ifdef __USE_GNU
++/* Yield the processor to another thread or process.
++ This function is similar to the POSIX `sched_yield' function but
++ might be differently implemented in the case of a m-on-n thread
++ implementation. */
++extern int pthread_yield (void) __THROW;
++
++
++/* Limit specified thread TH to run only on the processors represented
++ in CPUSET. */
++extern int pthread_setaffinity_np (pthread_t __th, size_t __cpusetsize,
++ const cpu_set_t *__cpuset)
++ __THROW __nonnull ((3));
++
++/* Get bit set in CPUSET representing the processors TH can run on. */
++extern int pthread_getaffinity_np (pthread_t __th, size_t __cpusetsize,
++ cpu_set_t *__cpuset)
++ __THROW __nonnull ((3));
++#endif
++
++
++/* Functions for handling initialization. */
++
++/* Guarantee that the initialization function INIT_ROUTINE will be called
++ only once, even if pthread_once is executed several times with the
++ same ONCE_CONTROL argument. ONCE_CONTROL must point to a static or
++ extern variable initialized to PTHREAD_ONCE_INIT.
++
++ The initialization functions might throw exception which is why
++ this function is not marked with __THROW. */
++extern int pthread_once (pthread_once_t *__once_control,
++ void (*__init_routine) (void)) __nonnull ((1, 2));
++
++
++/* Functions for handling cancellation.
++
++ Note that these functions are explicitly not marked to not throw an
++ exception in C++ code. If cancellation is implemented by unwinding
++ this is necessary to have the compiler generate the unwind information. */
++
++/* Set cancelability state of current thread to STATE, returning old
++ state in *OLDSTATE if OLDSTATE is not NULL. */
++extern int pthread_setcancelstate (int __state, int *__oldstate);
++
++/* Set cancellation state of current thread to TYPE, returning the old
++ type in *OLDTYPE if OLDTYPE is not NULL. */
++extern int pthread_setcanceltype (int __type, int *__oldtype);
++
++/* Cancel THREAD immediately or at the next possibility. */
++extern int pthread_cancel (pthread_t __th);
++
++/* Test for pending cancellation for the current thread and terminate
++ the thread as per pthread_exit(PTHREAD_CANCELED) if it has been
++ cancelled. */
++extern void pthread_testcancel (void);
++
++
++/* Cancellation handling with integration into exception handling. */
++
++typedef struct
++{
++ struct
++ {
++ __jmp_buf __cancel_jmp_buf;
++ int __mask_was_saved;
++ } __cancel_jmp_buf[1];
++ void *__pad[4];
++} __pthread_unwind_buf_t __attribute__ ((__aligned__));
++
++/* No special attributes by default. */
++#ifndef __cleanup_fct_attribute
++# define __cleanup_fct_attribute
++#endif
++
++
++/* Structure to hold the cleanup handler information. */
++struct __pthread_cleanup_frame
++{
++ void (*__cancel_routine) (void *);
++ void *__cancel_arg;
++ int __do_it;
++ int __cancel_type;
++};
++
++#if defined __GNUC__ && defined __EXCEPTIONS
++# ifdef __cplusplus
++/* Class to handle cancellation handler invocation. */
++class __pthread_cleanup_class
++{
++ void (*__cancel_routine) (void *);
++ void *__cancel_arg;
++ int __do_it;
++ int __cancel_type;
++
++ public:
++ __pthread_cleanup_class (void (*__fct) (void *), void *__arg)
++ : __cancel_routine (__fct), __cancel_arg (__arg), __do_it (1) { }
++ ~__pthread_cleanup_class () { if (__do_it) __cancel_routine (__cancel_arg); }
++ void __setdoit (int __newval) { __do_it = __newval; }
++ void __defer () { pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED,
++ &__cancel_type); }
++ void __restore () const { pthread_setcanceltype (__cancel_type, 0); }
++};
++
++/* Install a cleanup handler: ROUTINE will be called with arguments ARG
++ when the thread is canceled or calls pthread_exit. ROUTINE will also
++ be called with arguments ARG when the matching pthread_cleanup_pop
++ is executed with non-zero EXECUTE argument.
++
++ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
++ be used in matching pairs at the same nesting level of braces. */
++# define pthread_cleanup_push(routine, arg) \
++ do { \
++ __pthread_cleanup_class __clframe (routine, arg)
++
++/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
++ If EXECUTE is non-zero, the handler function is called. */
++# define pthread_cleanup_pop(execute) \
++ __clframe.__setdoit (execute); \
++ } while (0)
++
++# ifdef __USE_GNU
++/* Install a cleanup handler as pthread_cleanup_push does, but also
++ saves the current cancellation type and sets it to deferred
++ cancellation. */
++# define pthread_cleanup_push_defer_np(routine, arg) \
++ do { \
++ __pthread_cleanup_class __clframe (routine, arg); \
++ __clframe.__defer ()
++
++/* Remove a cleanup handler as pthread_cleanup_pop does, but also
++ restores the cancellation type that was in effect when the matching
++ pthread_cleanup_push_defer was called. */
++# define pthread_cleanup_pop_restore_np(execute) \
++ __clframe.__restore (); \
++ __clframe.__setdoit (execute); \
++ } while (0)
++# endif
++# else
++/* Function called to call the cleanup handler. As an extern inline
++ function the compiler is free to decide inlining the change when
++ needed or fall back on the copy which must exist somewhere
++ else. */
++__extern_inline void
++__pthread_cleanup_routine (struct __pthread_cleanup_frame *__frame)
++{
++ if (__frame->__do_it)
++ __frame->__cancel_routine (__frame->__cancel_arg);
++}
++
++/* Install a cleanup handler: ROUTINE will be called with arguments ARG
++ when the thread is canceled or calls pthread_exit. ROUTINE will also
++ be called with arguments ARG when the matching pthread_cleanup_pop
++ is executed with non-zero EXECUTE argument.
++
++ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
++ be used in matching pairs at the same nesting level of braces. */
++# define pthread_cleanup_push(routine, arg) \
++ do { \
++ struct __pthread_cleanup_frame __clframe \
++ __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
++ = { .__cancel_routine = (routine), .__cancel_arg = (arg), \
++ .__do_it = 1 };
++
++/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
++ If EXECUTE is non-zero, the handler function is called. */
++# define pthread_cleanup_pop(execute) \
++ __clframe.__do_it = (execute); \
++ } while (0)
++
++# ifdef __USE_GNU
++/* Install a cleanup handler as pthread_cleanup_push does, but also
++ saves the current cancellation type and sets it to deferred
++ cancellation. */
++# define pthread_cleanup_push_defer_np(routine, arg) \
++ do { \
++ struct __pthread_cleanup_frame __clframe \
++ __attribute__ ((__cleanup__ (__pthread_cleanup_routine))) \
++ = { .__cancel_routine = (routine), .__cancel_arg = (arg), \
++ .__do_it = 1 }; \
++ (void) pthread_setcanceltype (PTHREAD_CANCEL_DEFERRED, \
++ &__clframe.__cancel_type)
++
++/* Remove a cleanup handler as pthread_cleanup_pop does, but also
++ restores the cancellation type that was in effect when the matching
++ pthread_cleanup_push_defer was called. */
++# define pthread_cleanup_pop_restore_np(execute) \
++ (void) pthread_setcanceltype (__clframe.__cancel_type, NULL); \
++ __clframe.__do_it = (execute); \
++ } while (0)
++# endif
++# endif
++#else
++/* Install a cleanup handler: ROUTINE will be called with arguments ARG
++ when the thread is canceled or calls pthread_exit. ROUTINE will also
++ be called with arguments ARG when the matching pthread_cleanup_pop
++ is executed with non-zero EXECUTE argument.
++
++ pthread_cleanup_push and pthread_cleanup_pop are macros and must always
++ be used in matching pairs at the same nesting level of braces. */
++# define pthread_cleanup_push(routine, arg) \
++ do { \
++ __pthread_unwind_buf_t __cancel_buf; \
++ void (*__cancel_routine) (void *) = (routine); \
++ void *__cancel_arg = (arg); \
++ int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
++ __cancel_buf.__cancel_jmp_buf, 0); \
++ if (__glibc_unlikely (__not_first_call)) \
++ { \
++ __cancel_routine (__cancel_arg); \
++ __pthread_unwind_next (&__cancel_buf); \
++ /* NOTREACHED */ \
++ } \
++ \
++ __pthread_register_cancel (&__cancel_buf); \
++ do {
++extern void __pthread_register_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++
++/* Remove a cleanup handler installed by the matching pthread_cleanup_push.
++ If EXECUTE is non-zero, the handler function is called. */
++# define pthread_cleanup_pop(execute) \
++ do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\
++ } while (0); \
++ __pthread_unregister_cancel (&__cancel_buf); \
++ if (execute) \
++ __cancel_routine (__cancel_arg); \
++ } while (0)
++extern void __pthread_unregister_cancel (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++
++# ifdef __USE_GNU
++/* Install a cleanup handler as pthread_cleanup_push does, but also
++ saves the current cancellation type and sets it to deferred
++ cancellation. */
++# define pthread_cleanup_push_defer_np(routine, arg) \
++ do { \
++ __pthread_unwind_buf_t __cancel_buf; \
++ void (*__cancel_routine) (void *) = (routine); \
++ void *__cancel_arg = (arg); \
++ int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
++ __cancel_buf.__cancel_jmp_buf, 0); \
++ if (__glibc_unlikely (__not_first_call)) \
++ { \
++ __cancel_routine (__cancel_arg); \
++ __pthread_unwind_next (&__cancel_buf); \
++ /* NOTREACHED */ \
++ } \
++ \
++ __pthread_register_cancel_defer (&__cancel_buf); \
++ do {
++extern void __pthread_register_cancel_defer (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++
++/* Remove a cleanup handler as pthread_cleanup_pop does, but also
++ restores the cancellation type that was in effect when the matching
++ pthread_cleanup_push_defer was called. */
++# define pthread_cleanup_pop_restore_np(execute) \
++ do { } while (0);/* Empty to allow label before pthread_cleanup_pop. */\
++ } while (0); \
++ __pthread_unregister_cancel_restore (&__cancel_buf); \
++ if (execute) \
++ __cancel_routine (__cancel_arg); \
++ } while (0)
++extern void __pthread_unregister_cancel_restore (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute;
++# endif
++
++/* Internal interface to initiate cleanup. */
++extern void __pthread_unwind_next (__pthread_unwind_buf_t *__buf)
++ __cleanup_fct_attribute __attribute__ ((__noreturn__))
++# ifndef SHARED
++ __attribute__ ((__weak__))
++# endif
++ ;
++#endif
++
++/* Function used in the macros. */
++struct __jmp_buf_tag;
++extern int __sigsetjmp (struct __jmp_buf_tag *__env, int __savemask) __THROWNL;
++
++
++/* Mutex handling. */
++
++/* Initialize a mutex. */
++extern int pthread_mutex_init (pthread_mutex_t *__mutex,
++ const pthread_mutexattr_t *__mutexattr)
++ __THROW __nonnull ((1));
++
++/* Destroy a mutex. */
++extern int pthread_mutex_destroy (pthread_mutex_t *__mutex)
++ __THROW __nonnull ((1));
++
++/* Try locking a mutex. */
++extern int pthread_mutex_trylock (pthread_mutex_t *__mutex)
++ __THROWNL __nonnull ((1));
++
++/* Lock a mutex. */
++extern int pthread_mutex_lock (pthread_mutex_t *__mutex)
++ __THROWNL __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Wait until lock becomes available, or specified time passes. */
++extern int pthread_mutex_timedlock (pthread_mutex_t *__restrict __mutex,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 2));
++#endif
++
++/* Unlock a mutex. */
++extern int pthread_mutex_unlock (pthread_mutex_t *__mutex)
++ __THROWNL __nonnull ((1));
++
++
++/* Get the priority ceiling of MUTEX. */
++extern int pthread_mutex_getprioceiling (const pthread_mutex_t *
++ __restrict __mutex,
++ int *__restrict __prioceiling)
++ __THROW __nonnull ((1, 2));
++
++/* Set the priority ceiling of MUTEX to PRIOCEILING, return old
++ priority ceiling value in *OLD_CEILING. */
++extern int pthread_mutex_setprioceiling (pthread_mutex_t *__restrict __mutex,
++ int __prioceiling,
++ int *__restrict __old_ceiling)
++ __THROW __nonnull ((1, 3));
++
++
++#ifdef __USE_XOPEN2K8
++/* Declare the state protected by MUTEX as consistent. */
++extern int pthread_mutex_consistent (pthread_mutex_t *__mutex)
++ __THROW __nonnull ((1));
++# ifdef __USE_GNU
++extern int pthread_mutex_consistent_np (pthread_mutex_t *__mutex)
++ __THROW __nonnull ((1));
++# endif
++#endif
++
++
++/* Functions for handling mutex attributes. */
++
++/* Initialize mutex attribute object ATTR with default attributes
++ (kind is PTHREAD_MUTEX_TIMED_NP). */
++extern int pthread_mutexattr_init (pthread_mutexattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy mutex attribute object ATTR. */
++extern int pthread_mutexattr_destroy (pthread_mutexattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get the process-shared flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_getpshared (const pthread_mutexattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set the process-shared flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_setpshared (pthread_mutexattr_t *__attr,
++ int __pshared)
++ __THROW __nonnull ((1));
++
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K8
++/* Return in *KIND the mutex kind attribute in *ATTR. */
++extern int pthread_mutexattr_gettype (const pthread_mutexattr_t *__restrict
++ __attr, int *__restrict __kind)
++ __THROW __nonnull ((1, 2));
++
++/* Set the mutex kind attribute in *ATTR to KIND (either PTHREAD_MUTEX_NORMAL,
++ PTHREAD_MUTEX_RECURSIVE, PTHREAD_MUTEX_ERRORCHECK, or
++ PTHREAD_MUTEX_DEFAULT). */
++extern int pthread_mutexattr_settype (pthread_mutexattr_t *__attr, int __kind)
++ __THROW __nonnull ((1));
++#endif
++
++/* Return in *PROTOCOL the mutex protocol attribute in *ATTR. */
++extern int pthread_mutexattr_getprotocol (const pthread_mutexattr_t *
++ __restrict __attr,
++ int *__restrict __protocol)
++ __THROW __nonnull ((1, 2));
++
++/* Set the mutex protocol attribute in *ATTR to PROTOCOL (either
++ PTHREAD_PRIO_NONE, PTHREAD_PRIO_INHERIT, or PTHREAD_PRIO_PROTECT). */
++extern int pthread_mutexattr_setprotocol (pthread_mutexattr_t *__attr,
++ int __protocol)
++ __THROW __nonnull ((1));
++
++/* Return in *PRIOCEILING the mutex prioceiling attribute in *ATTR. */
++extern int pthread_mutexattr_getprioceiling (const pthread_mutexattr_t *
++ __restrict __attr,
++ int *__restrict __prioceiling)
++ __THROW __nonnull ((1, 2));
++
++/* Set the mutex prioceiling attribute in *ATTR to PRIOCEILING. */
++extern int pthread_mutexattr_setprioceiling (pthread_mutexattr_t *__attr,
++ int __prioceiling)
++ __THROW __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Get the robustness flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr,
++ int *__robustness)
++ __THROW __nonnull ((1, 2));
++# ifdef __USE_GNU
++extern int pthread_mutexattr_getrobust_np (const pthread_mutexattr_t *__attr,
++ int *__robustness)
++ __THROW __nonnull ((1, 2));
++# endif
++
++/* Set the robustness flag of the mutex attribute ATTR. */
++extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr,
++ int __robustness)
++ __THROW __nonnull ((1));
++# ifdef __USE_GNU
++extern int pthread_mutexattr_setrobust_np (pthread_mutexattr_t *__attr,
++ int __robustness)
++ __THROW __nonnull ((1));
++# endif
++#endif
++
++
++#if defined __USE_UNIX98 || defined __USE_XOPEN2K
++/* Functions for handling read-write locks. */
++
++/* Initialize read-write lock RWLOCK using attributes ATTR, or use
++ the default values if later is NULL. */
++extern int pthread_rwlock_init (pthread_rwlock_t *__restrict __rwlock,
++ const pthread_rwlockattr_t *__restrict
++ __attr) __THROW __nonnull ((1));
++
++/* Destroy read-write lock RWLOCK. */
++extern int pthread_rwlock_destroy (pthread_rwlock_t *__rwlock)
++ __THROW __nonnull ((1));
++
++/* Acquire read lock for RWLOCK. */
++extern int pthread_rwlock_rdlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++/* Try to acquire read lock for RWLOCK. */
++extern int pthread_rwlock_tryrdlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++# ifdef __USE_XOPEN2K
++/* Try to acquire read lock for RWLOCK or return after specfied time. */
++extern int pthread_rwlock_timedrdlock (pthread_rwlock_t *__restrict __rwlock,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 2));
++# endif
++
++/* Acquire write lock for RWLOCK. */
++extern int pthread_rwlock_wrlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++/* Try to acquire write lock for RWLOCK. */
++extern int pthread_rwlock_trywrlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++# ifdef __USE_XOPEN2K
++/* Try to acquire write lock for RWLOCK or return after specfied time. */
++extern int pthread_rwlock_timedwrlock (pthread_rwlock_t *__restrict __rwlock,
++ const struct timespec *__restrict
++ __abstime) __THROWNL __nonnull ((1, 2));
++# endif
++
++/* Unlock RWLOCK. */
++extern int pthread_rwlock_unlock (pthread_rwlock_t *__rwlock)
++ __THROWNL __nonnull ((1));
++
++
++/* Functions for handling read-write lock attributes. */
++
++/* Initialize attribute object ATTR with default values. */
++extern int pthread_rwlockattr_init (pthread_rwlockattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy attribute object ATTR. */
++extern int pthread_rwlockattr_destroy (pthread_rwlockattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Return current setting of process-shared attribute of ATTR in PSHARED. */
++extern int pthread_rwlockattr_getpshared (const pthread_rwlockattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set process-shared attribute of ATTR to PSHARED. */
++extern int pthread_rwlockattr_setpshared (pthread_rwlockattr_t *__attr,
++ int __pshared)
++ __THROW __nonnull ((1));
++
++/* Return current setting of reader/writer preference. */
++extern int pthread_rwlockattr_getkind_np (const pthread_rwlockattr_t *
++ __restrict __attr,
++ int *__restrict __pref)
++ __THROW __nonnull ((1, 2));
++
++/* Set reader/write preference. */
++extern int pthread_rwlockattr_setkind_np (pthread_rwlockattr_t *__attr,
++ int __pref) __THROW __nonnull ((1));
++#endif
++
++
++/* Functions for handling conditional variables. */
++
++/* Initialize condition variable COND using attributes ATTR, or use
++ the default values if later is NULL. */
++extern int pthread_cond_init (pthread_cond_t *__restrict __cond,
++ const pthread_condattr_t *__restrict __cond_attr)
++ __THROW __nonnull ((1));
++
++/* Destroy condition variable COND. */
++extern int pthread_cond_destroy (pthread_cond_t *__cond)
++ __THROW __nonnull ((1));
++
++/* Wake up one thread waiting for condition variable COND. */
++extern int pthread_cond_signal (pthread_cond_t *__cond)
++ __THROWNL __nonnull ((1));
++
++/* Wake up all threads waiting for condition variables COND. */
++extern int pthread_cond_broadcast (pthread_cond_t *__cond)
++ __THROWNL __nonnull ((1));
++
++/* Wait for condition variable COND to be signaled or broadcast.
++ MUTEX is assumed to be locked before.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_cond_wait (pthread_cond_t *__restrict __cond,
++ pthread_mutex_t *__restrict __mutex)
++ __nonnull ((1, 2));
++
++/* Wait for condition variable COND to be signaled or broadcast until
++ ABSTIME. MUTEX is assumed to be locked before. ABSTIME is an
++ absolute time specification; zero is the beginning of the epoch
++ (00:00:00 GMT, January 1, 1970).
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_cond_timedwait (pthread_cond_t *__restrict __cond,
++ pthread_mutex_t *__restrict __mutex,
++ const struct timespec *__restrict __abstime)
++ __nonnull ((1, 2, 3));
++
++/* Wait for condition variable COND to be signaled or broadcast until
++ ABSTIME measured by the specified clock. MUTEX is assumed to be
++ locked before. CLOCK is the clock to use. ABSTIME is an absolute
++ time specification against CLOCK's epoch.
++
++ This function is a cancellation point and therefore not marked with
++ __THROW. */
++extern int pthread_cond_clockwait (pthread_cond_t *__restrict __cond,
++ pthread_mutex_t *__restrict __mutex,
++ __clockid_t __clock_id,
++ const struct timespec *__restrict __abstime)
++ __nonnull ((1, 2, 4));
++
++/* Functions for handling condition variable attributes. */
++
++/* Initialize condition variable attribute ATTR. */
++extern int pthread_condattr_init (pthread_condattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy condition variable attribute ATTR. */
++extern int pthread_condattr_destroy (pthread_condattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get the process-shared flag of the condition variable attribute ATTR. */
++extern int pthread_condattr_getpshared (const pthread_condattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set the process-shared flag of the condition variable attribute ATTR. */
++extern int pthread_condattr_setpshared (pthread_condattr_t *__attr,
++ int __pshared) __THROW __nonnull ((1));
++
++#ifdef __USE_XOPEN2K
++/* Get the clock selected for the condition variable attribute ATTR. */
++extern int pthread_condattr_getclock (const pthread_condattr_t *
++ __restrict __attr,
++ __clockid_t *__restrict __clock_id)
++ __THROW __nonnull ((1, 2));
++
++/* Set the clock selected for the condition variable attribute ATTR. */
++extern int pthread_condattr_setclock (pthread_condattr_t *__attr,
++ __clockid_t __clock_id)
++ __THROW __nonnull ((1));
++#endif
++
++
++#ifdef __USE_XOPEN2K
++/* Functions to handle spinlocks. */
++
++/* Initialize the spinlock LOCK. If PSHARED is nonzero the spinlock can
++ be shared between different processes. */
++extern int pthread_spin_init (pthread_spinlock_t *__lock, int __pshared)
++ __THROW __nonnull ((1));
++
++/* Destroy the spinlock LOCK. */
++extern int pthread_spin_destroy (pthread_spinlock_t *__lock)
++ __THROW __nonnull ((1));
++
++/* Wait until spinlock LOCK is retrieved. */
++extern int pthread_spin_lock (pthread_spinlock_t *__lock)
++ __THROWNL __nonnull ((1));
++
++/* Try to lock spinlock LOCK. */
++extern int pthread_spin_trylock (pthread_spinlock_t *__lock)
++ __THROWNL __nonnull ((1));
++
++/* Release spinlock LOCK. */
++extern int pthread_spin_unlock (pthread_spinlock_t *__lock)
++ __THROWNL __nonnull ((1));
++
++
++/* Functions to handle barriers. */
++
++/* Initialize BARRIER with the attributes in ATTR. The barrier is
++ opened when COUNT waiters arrived. */
++extern int pthread_barrier_init (pthread_barrier_t *__restrict __barrier,
++ const pthread_barrierattr_t *__restrict
++ __attr, unsigned int __count)
++ __THROW __nonnull ((1));
++
++/* Destroy a previously dynamically initialized barrier BARRIER. */
++extern int pthread_barrier_destroy (pthread_barrier_t *__barrier)
++ __THROW __nonnull ((1));
++
++/* Wait on barrier BARRIER. */
++extern int pthread_barrier_wait (pthread_barrier_t *__barrier)
++ __THROWNL __nonnull ((1));
++
++
++/* Initialize barrier attribute ATTR. */
++extern int pthread_barrierattr_init (pthread_barrierattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Destroy previously dynamically initialized barrier attribute ATTR. */
++extern int pthread_barrierattr_destroy (pthread_barrierattr_t *__attr)
++ __THROW __nonnull ((1));
++
++/* Get the process-shared flag of the barrier attribute ATTR. */
++extern int pthread_barrierattr_getpshared (const pthread_barrierattr_t *
++ __restrict __attr,
++ int *__restrict __pshared)
++ __THROW __nonnull ((1, 2));
++
++/* Set the process-shared flag of the barrier attribute ATTR. */
++extern int pthread_barrierattr_setpshared (pthread_barrierattr_t *__attr,
++ int __pshared)
++ __THROW __nonnull ((1));
++#endif
++
++
++/* Functions for handling thread-specific data. */
++
++/* Create a key value identifying a location in the thread-specific
++ data area. Each thread maintains a distinct thread-specific data
++ area. DESTR_FUNCTION, if non-NULL, is called with the value
++ associated to that key when the key is destroyed.
++ DESTR_FUNCTION is not called if the value associated is NULL when
++ the key is destroyed. */
++extern int pthread_key_create (pthread_key_t *__key,
++ void (*__destr_function) (void *))
++ __THROW __nonnull ((1));
++
++/* Destroy KEY. */
++extern int pthread_key_delete (pthread_key_t __key) __THROW;
++
++/* Return current value of the thread-specific data slot identified by KEY. */
++extern void *pthread_getspecific (pthread_key_t __key) __THROW;
++
++/* Store POINTER in the thread-specific data slot identified by KEY. */
++extern int pthread_setspecific (pthread_key_t __key,
++ const void *__pointer) __THROW ;
++
++
++#ifdef __USE_XOPEN2K
++/* Get ID of CPU-time clock for thread THREAD_ID. */
++extern int pthread_getcpuclockid (pthread_t __thread_id,
++ __clockid_t *__clock_id)
++ __THROW __nonnull ((2));
++#endif
++
++
++/* Install handlers to be called when a new process is created with FORK.
++ The PREPARE handler is called in the parent process just before performing
++ FORK. The PARENT handler is called in the parent process just after FORK.
++ The CHILD handler is called in the child process. Each of the three
++ handlers can be NULL, meaning that no handler needs to be called at that
++ point.
++ PTHREAD_ATFORK can be called several times, in which case the PREPARE
++ handlers are called in LIFO order (last added with PTHREAD_ATFORK,
++ first called before FORK), and the PARENT and CHILD handlers are called
++ in FIFO (first added, first called). */
++
++extern int pthread_atfork (void (*__prepare) (void),
++ void (*__parent) (void),
++ void (*__child) (void)) __THROW;
++
++
++#ifdef __USE_EXTERN_INLINES
++/* Optimizations. */
++__extern_inline int
++__NTH (pthread_equal (pthread_t __thread1, pthread_t __thread2))
++{
++ return __thread1 == __thread2;
++}
++#endif
++
++__END_DECLS
++
++#endif /* pthread.h */
+--
+2.30.0
+
diff --git a/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch b/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch
new file mode 100644
index 0000000..9442241
--- /dev/null
+++ b/0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch
@@ -0,0 +1,1177 @@
+From 74c980c56a1ae533c3cd25f572f83c0c1def6a30 Mon Sep 17 00:00:00 2001
+From: Lv Ying <lvying6@huawei.com>
+Date: Tue, 25 Jan 2022 09:25:35 +0000
+Subject: [PATCH 2/3] elf/ld.so: add testcase for ld.so load shared object use
+ hugepage feature
+
+1. testcase for hugepageedit
+2. testcase for feature env
+3. testcase for feature fallback
+4. testcase for hugepage mmap consistency witch process occupancy
+5. testcase for dlopen use hugepage
+---
+ config.make.in | 1 +
+ configure | 24 ++++++-
+ configure.ac | 3 +
+ elf/Makefile | 61 +++++++++++++++++
+ elf/hugepageedit.c | 69 +++----------------
+ elf/tst-check-hugepage.sh | 72 ++++++++++++++++++++
+ elf/tst-dl-hugepage.sh | 70 +++++++++++++++++++
+ elf/tst-dl-use-hugepage.c | 54 +++++++++++++++
+ elf/tst-get-ephdr.h | 96 ++++++++++++++++++++++++++
+ elf/tst-hugepageedit1.sh | 85 +++++++++++++++++++++++
+ elf/tst-ld-hugepage-env.sh | 108 ++++++++++++++++++++++++++++++
+ elf/tst-ld-hugepage-fallback.sh | 66 ++++++++++++++++++
+ elf/tst-ld-hugepage-mmap-smaps.sh | 49 ++++++++++++++
+ elf/tst-ld-hugepage.h | 7 ++
+ elf/tst-ld-hugepagemod.c | 19 ++++++
+ elf/tst-update-ehdr.c | 58 ++++++++++++++++
+ elf/tst-update-phdr.c | 93 +++++++++++++++++++++++++
+ elf/tst-use-hugepage.c | 15 +++++
+ 18 files changed, 889 insertions(+), 61 deletions(-)
+ create mode 100644 elf/tst-check-hugepage.sh
+ create mode 100644 elf/tst-dl-hugepage.sh
+ create mode 100644 elf/tst-dl-use-hugepage.c
+ create mode 100644 elf/tst-get-ephdr.h
+ create mode 100644 elf/tst-hugepageedit1.sh
+ create mode 100644 elf/tst-ld-hugepage-env.sh
+ create mode 100644 elf/tst-ld-hugepage-fallback.sh
+ create mode 100644 elf/tst-ld-hugepage-mmap-smaps.sh
+ create mode 100644 elf/tst-ld-hugepage.h
+ create mode 100644 elf/tst-ld-hugepagemod.c
+ create mode 100644 elf/tst-update-ehdr.c
+ create mode 100644 elf/tst-update-phdr.c
+ create mode 100644 elf/tst-use-hugepage.c
+
+diff --git a/config.make.in b/config.make.in
+index cbf59114..0105cc8e 100644
+--- a/config.make.in
++++ b/config.make.in
+@@ -76,6 +76,7 @@ use-default-link = @use_default_link@
+ have-cxx-thread_local = @libc_cv_cxx_thread_local@
+ have-loop-to-function = @libc_cv_cc_loop_to_function@
+ have-textrel_ifunc = @libc_cv_textrel_ifunc@
++have-hugetlb-dir = @have_hugetlb_dir@
+
+ multi-arch = @multi_arch@
+
+diff --git a/configure b/configure
+index 43993923..be2277b1 100755
+--- a/configure
++++ b/configure
+@@ -670,7 +670,7 @@ stack_protector
+ libc_cv_ssp
+ libc_cv_with_fp
+ base_machine
+-enable_hugepage_shared_library
++have_hugetlb_dir
+ have_tunables
+ build_pt_chown
+ build_nscd
+@@ -3848,6 +3848,28 @@ enable-hugepage-shared-library = $enable_hugepage_shared_library"
+ if test "$enable_hugepage_shared_library" = yes; then
+ $as_echo "#define HUGEPAGE_SHARED_LIB 1" >>confdefs.h
+
++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for /sys/devices/system/node/node0/hugepages/hugepages-2048kB/" >&5
++$as_echo_n "checking for /sys/devices/system/node/node0/hugepages/hugepages-2048kB/... " >&6; }
++if ${ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_+:} false; then :
++ $as_echo_n "(cached) " >&6
++else
++ test "$cross_compiling" = yes &&
++ as_fn_error $? "cannot check for file existence when cross compiling" "$LINENO" 5
++if test -r "/sys/devices/system/node/node0/hugepages/hugepages-2048kB/"; then
++ ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_=yes
++else
++ ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_=no
++fi
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" >&5
++$as_echo "$ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" >&6; }
++if test "x$ac_cv_file__sys_devices_system_node_node0_hugepages_hugepages_2048kB_" = xyes; then :
++ have_hugetlb_dir=yes
++else
++ have_hugetlb_dir=no
++fi
++
++
+ fi
+
+ # We keep the original values in `$config_*' and never modify them, so we
+diff --git a/configure.ac b/configure.ac
+index 27a48338..fa34af26 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -487,6 +487,9 @@ AC_ARG_ENABLE([hugepage-shared-library],
+ LIBC_CONFIG_VAR([enable-hugepage-shared-library], [$enable_hugepage_shared_library])
+ if test "$enable_hugepage_shared_library" = yes; then
+ AC_DEFINE(HUGEPAGE_SHARED_LIB)
++ AC_CHECK_FILE(/sys/devices/system/node/node0/hugepages/hugepages-2048kB/,
++ have_hugetlb_dir=yes, have_hugetlb_dir=no)
++ AC_SUBST(have_hugetlb_dir)
+ fi
+
+ # We keep the original values in `$config_*' and never modify them, so we
+diff --git a/elf/Makefile b/elf/Makefile
+index 1574574d..0fb2be3b 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -213,6 +213,12 @@ others-pie += hugepageedit
+ install-bin += hugepageedit
+
+ $(objpfx)hugepageedit: $(objpfx)hugepageedit.o
++
++ifeq ($(run-built-tests),yes)
++tests-special += $(objpfx)tst-hugepageedit1.out $(objpfx)tst-ld-hugepage-env.out \
++ $(objpfx)tst-ld-hugepage-fallback.out $(objpfx)tst-ld-hugepage-mmap-smaps.out \
++ $(objpfx)tst-dl-hugepage.out
++endif
+ endif
+
+ # To find xmalloc.c and xstrdup.c
+@@ -788,6 +794,13 @@ $(objpfx)tst-gnu2-tls1: $(objpfx)tst-gnu2-tls1mod.so
+ tst-gnu2-tls1mod.so-no-z-defs = yes
+ CFLAGS-tst-gnu2-tls1mod.c += -mtls-dialect=gnu2
+ endif
++ifeq (yes,$(enable-hugepage-shared-library))
++ld-hugepagemod-suffixes = 1 2 3 4 5
++ld-hugepagemod-modules = $(addprefix tst-ld-hugepagemod, $(ld-hugepagemod-suffixes))
++tst-usehugepage = $(addprefix tst-use-hugepage, $(ld-hugepagemod-suffixes))
++modules-names += $(ld-hugepagemod-modules)
++test-srcs += tst-update-ehdr tst-update-phdr tst-dl-use-hugepage $(tst-usehugepage)
++endif
+ ifeq (yes,$(have-protected-data))
+ modules-names += tst-protected1moda tst-protected1modb
+ tests += tst-protected1a tst-protected1b
+@@ -2015,6 +2028,54 @@ $(objpfx)tst-ldconfig-X.out : tst-ldconfig-X.sh $(objpfx)ldconfig
+ '$(run-program-env)' > $@; \
+ $(evaluate-test)
+
++ifeq (yes,$(enable-hugepage-shared-library))
++CFLAGS-tst-ld-hugepagemod.c += -DOBJDIR=\"$(elf-objpfx)\"
++$(objpfx)tst-ld-hugepage-bin.o :
++ dd if=/dev/zero of=$@ count=4 bs=2MB
++$(patsubst %,$(objpfx)%.os,$(ld-hugepagemod-modules)): $(objpfx)tst-ld-hugepagemod%.os: tst-ld-hugepagemod.c $(objpfx)tst-ld-hugepage-bin.o
++ $(compile-command.c) -DN=$*
++$(patsubst %,$(objpfx)%.o,$(tst-usehugepage)): $(objpfx)tst-use-hugepage%.o: tst-use-hugepage.c
++ $(compile-command.c)
++$(patsubst tst-use-hugepage%,$(objpfx)tst-use-hugepage%,$(tst-usehugepage)): $(objpfx)tst-use-hugepage% : \
++ $(objpfx)tst-use-hugepage%.o $(objpfx)tst-ld-hugepagemod%.so $(objpfx)ld.so
++$(objpfx)tst-dl-use-hugepage: $(libdl)
++
++ifeq ($(have-hugetlb-dir),yes)
++$(objpfx)tst-hugepageedit1.out: tst-hugepageedit1.sh tst-check-hugepage.sh \
++ $(objpfx)tst-update-ehdr $(objpfx)tst-use-hugepage1 $(objpfx)tst-ld-hugepagemod1.so
++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
++ $(evaluate-test)
++
++$(objpfx)tst-ld-hugepage-env.out: tst-ld-hugepage-env.sh tst-check-hugepage.sh \
++ $(objpfx)tst-use-hugepage2 $(objpfx)tst-ld-hugepagemod2.so
++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
++ $(evaluate-test)
++
++$(objpfx)tst-ld-hugepage-fallback.out: tst-ld-hugepage-fallback.sh tst-check-hugepage.sh \
++ $(objpfx)tst-update-phdr $(objpfx)tst-use-hugepage3 $(objpfx)tst-ld-hugepagemod3.so
++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
++ $(evaluate-test)
++
++$(objpfx)tst-ld-hugepage-mmap-smaps.out: tst-ld-hugepage-mmap-smaps.sh tst-check-hugepage.sh \
++ $(objpfx)tst-use-hugepage4 $(objpfx)tst-ld-hugepagemod4.so
++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
++ $(evaluate-test)
++
++$(objpfx)tst-dl-hugepage.out: tst-dl-hugepage.sh tst-check-hugepage.sh \
++ $(objpfx)tst-dl-use-hugepage $(objpfx)tst-ld-hugepagemod5.so
++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper)' \
++ '$(test-wrapper-env)' $(CURDIR)/tst-check-hugepage.sh > $@; \
++ $(evaluate-test)
++else
++tests-unsupported += tst-hugepageedit1.out tst-ld-hugepage-env.out tst-ld-hugepage-fallback.out \
++ tst-ld-hugepage-mmap-smaps.out tst-dl-hugepage.out
++endif
++endif
++
+ # Test static linking of all the libraries we can possibly link
+ # together. Note that in some configurations this may be less than the
+ # complete list of libraries we build but we try to maxmimize this list.
+diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c
+index 14a91a4b..ab4247ad 100644
+--- a/elf/hugepageedit.c
++++ b/elf/hugepageedit.c
+@@ -25,18 +25,10 @@
+ #include <sys/stat.h>
+ #include <sys/mman.h>
+ #include <sys/types.h>
++#include "tst-get-ephdr.h"
+
+-/* reference kernel load_elf_phdrs program header table size constraint */
+-#define ELF_MIN_ALIGN 4096
+ #define TOOL_NAME "hugepageedit"
+
+-int check_ptr(void *ptr, void *start, size_t len)
+-{
+- if (ptr < start || ptr > start + len)
+- return -1;
+- return 0;
+-}
+-
+ void print_usage(void)
+ {
+ fprintf(stderr, "%s [-x] [-d] <ELF file>\n" \
+@@ -47,6 +39,7 @@ void print_usage(void)
+
+ int main(int argc, char *argv[])
+ {
++ size_t length;
+ int exit_status = -1;
+ int i, opt, delete = 0, exec_only = 0;
+ while ((opt = getopt(argc, argv, "dx")) != -1)
+@@ -84,57 +77,13 @@ int main(int argc, char *argv[])
+ return -1;
+ }
+
+- struct stat statbuf;
+- if (fstat(fd, &statbuf) != 0)
+- {
+- perror("fstat");
+- goto close_fd;
+- }
+-
+- /* this ensures file is large enough to hold ELF header */
+- if (statbuf.st_size < sizeof (ElfW(Ehdr)))
+- {
+- fprintf(stderr, "file is not large enough to hold ELF header\n");
+- goto close_fd;
+- }
+-
+- void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
+- if (ehdr == MAP_FAILED)
+- {
+- perror("mmap");
+- goto close_fd;
+- }
+-
+- if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0)
+- {
+- fprintf(stderr, "file is not ELF format\n");
+- goto unmap;
+- }
+-
+- if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr)))
+- {
+- fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n");
+- goto unmap;
+- }
+-
+- unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr));
+- if (size == 0 || size > ELF_MIN_ALIGN)
+- {
+- fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size);
+- goto unmap;
+- }
+-
+- void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff;
+- void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size;
+-
+- if (check_ptr(ephdr_s, ehdr, statbuf.st_size) ||
+- check_ptr(ephdr_e, ehdr, statbuf.st_size))
+- {
+- fprintf(stderr, "ELF porgram header table is not fully mmaped\n");
+- goto unmap;
+- }
++ void *ehdr = get_ehdr(fd, &length);
++ if (ehdr == NULL)
++ goto close_fd;
+
+- ElfW(Phdr) *phdr = (ElfW(Phdr) *)ephdr_s;
++ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length);
++ if (phdr == NULL)
++ goto unmap;
+ /*
+ * Here, mark hugepage flag in ELF header e_ident padding bytes won't work.
+ * elf/dl-load.c open_verify will check if shared object ELF header e_ident
+@@ -160,7 +109,7 @@ int main(int argc, char *argv[])
+ exit_status = 0;
+
+ unmap:
+- munmap(ehdr, statbuf.st_size);
++ munmap(ehdr, length);
+
+ close_fd:
+ close(fd);
+diff --git a/elf/tst-check-hugepage.sh b/elf/tst-check-hugepage.sh
+new file mode 100644
+index 00000000..0cdebe2a
+--- /dev/null
++++ b/elf/tst-check-hugepage.sh
+@@ -0,0 +1,72 @@
++#!/bin/sh
++# check whether ld.so use hugepage when loading shared object and whether
++# there are exceptions when using hugepage
++# Copyright (C) 2021-2021 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <http://www.gnu.org/licenses/>.
++
++check_hugepage_mmap () {
++ log=$1
++
++ cat $log | egrep "reserved area|_dl_map_segments_largein:" > /dev/null && return 0
++ return 1
++}
++
++check_hugepage_mmap_success () {
++ log=$1
++
++ # check whether the log contains fallback log
++ cat $log | grep "_dl_map_segments_largein:" > /dev/null && return 1
++ check_hugepage_mmap $log || return 1
++ left=$(cat $log | grep _mmap_segment | wc -l)
++ right=$(cat $log | grep "} => mapseglen" | wc -l)
++ if [ $left -eq $right ]; then
++ return 0
++ else
++ return 1
++ fi
++}
++
++check_hugepage_fallback () {
++ log=$1
++
++ cat $log | grep "_dl_map_segments_largein:" > /dev/null && return 0
++ return 1
++}
++
++# return 0: mmap hugepage correctly
++# return 1: Non-hugepage mmap
++# return 2: mmap hugepage wrongly
++check_hugepage_mmap_detail () {
++ log=$1
++
++ # check whether the log contains hugepage mmap
++ areas=$(cat $log | grep "mmap hugepage:" | awk '{print $4}' | cut -d '[' -f2 | cut -d ')' -f1)
++ if test -z "$areas"; then
++ return 1
++ else
++ for area in $areas; do
++ num=$(grep "mmap hugepage: \[$area)" $log | wc -l)
++ num=$(( $num * 2))
++ total_num=$(grep $area $log | wc -l)
++ if [ $num -ne $total_num ]; then
++ return 2
++ fi
++ grep -A21 $area $log | tail -22
++ done
++ return 0
++ fi
++}
+diff --git a/elf/tst-dl-hugepage.sh b/elf/tst-dl-hugepage.sh
+new file mode 100644
+index 00000000..f67e552f
+--- /dev/null
++++ b/elf/tst-dl-hugepage.sh
+@@ -0,0 +1,70 @@
++#!/bin/sh
++# Test that ld.so can handle dlopen call
++# Copyright (C) 2021-2021 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <http://www.gnu.org/licenses/>.
++
++set -ex
++echo "source $4"
++source $4
++
++common_objpfx=$1
++test_wrapper=$2
++test_wrapper_env=$3
++result=0
++
++excption_handle ()
++{
++ echo "ld.so hugepage feature is not behaving as expected, return $1"
++ result=1
++}
++
++check_global_var ()
++{
++ log=$1
++
++ for i in $(seq 1 2); do
++ cat $log | grep "In huge_func, huge_global = $i" > /dev/null|| return -1
++ done
++ return 0
++}
++
++testroot="${common_objpfx}elf/dl-hugepage-directory"
++
++rm -rf "$testroot"
++mkdir -p $testroot
++
++echo '# reseve 200 2MB hugepage'
++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
++
++echo '# Test LD_HUGEPAGE_LIB=1 whether ld.so mmap hugepage is consistent with the actual process occupancy'
++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-dl-use-hugepage ${common_objpfx}elf/tst-ld-hugepagemod5.so > ${testroot}/log1 2>&1
++check_hugepage_mmap_detail ${testroot}/log1 && rc=0 || rc=$?
++#check_global_var ${testroot}/log1 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle $rc
++
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod5.so || exit 1
++
++echo '# Test HUGEPAGE_PROBE=1 whether ld.so mmap hugepage is consistent with the actual process occupancy'
++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-dl-use-hugepage ${common_objpfx}elf/tst-ld-hugepagemod5.so > ${testroot}/log2 2>&1
++check_hugepage_mmap_detail ${testroot}/log2 && rc=0 || rc=$?
++#check_global_var ${testroot}/log2 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle $rc
++
++exit $result
+diff --git a/elf/tst-dl-use-hugepage.c b/elf/tst-dl-use-hugepage.c
+new file mode 100644
+index 00000000..cd7c6f29
+--- /dev/null
++++ b/elf/tst-dl-use-hugepage.c
+@@ -0,0 +1,54 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include <dlfcn.h>
++#include "tst-ld-hugepage.h"
++
++#define DL_ERR_HANDLE(s) \
++do { \
++ fprintf(stderr, "%s: %s\n", s, dlerror()); \
++ exit(EXIT_FAILURE); \
++} while(0)
++
++static void dl_flag_test(char *libname, int flags, int val)
++{
++ int *global;
++ char *error;
++ void (*funcp)(void);
++ char command[100];
++ sprintf(command, "cat /proc/%d/smaps", getpid());
++
++ void *handle = dlopen(libname, flags);
++ if (handle == NULL)
++ DL_ERR_HANDLE("dlopen");
++
++ (void) dlerror();
++
++ *(void **)(&global) = dlsym(handle, "huge_global");
++ error = dlerror();
++ if (error != NULL)
++ DL_ERR_HANDLE("dlsym");
++
++ (void) dlerror();
++ *(void **)(&funcp) = dlsym(handle, "huge_func");
++ error = dlerror();
++ if (error != NULL)
++ DL_ERR_HANDLE("dlsym");
++
++ *global = val;
++ (*funcp)();
++ system(command);
++ dlclose(handle);
++}
++
++int main(int argc, char *argv[])
++{
++ if (argc != 2)
++ {
++ fprintf(stderr, "shared object should be a parameter\n");
++ exit(EXIT_FAILURE);
++ }
++ dl_flag_test(argv[1], RTLD_LAZY, 1);
++ dl_flag_test(argv[1], RTLD_NOW, 2);
++ return 0;
++}
+diff --git a/elf/tst-get-ephdr.h b/elf/tst-get-ephdr.h
+new file mode 100644
+index 00000000..109af265
+--- /dev/null
++++ b/elf/tst-get-ephdr.h
+@@ -0,0 +1,96 @@
++/* mmap ELF file return ELF header and get mmap length
++ Copyright (C) 1995-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++#include <stdio.h>
++#include <elf.h>
++#include <link.h>
++#include <string.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++
++/* reference kernel load_elf_phdrs program header table size constraint */
++#define ELF_MIN_ALIGN 4096
++
++static __always_inline void *get_ehdr(int fd, size_t *len)
++{
++ struct stat statbuf;
++ *len = 0;
++ if (fstat(fd, &statbuf) != 0)
++ {
++ perror("fstat");
++ return NULL;
++ }
++
++ /* this ensures file is large enough to hold ELF header */
++ if (statbuf.st_size < sizeof (ElfW(Ehdr)))
++ {
++ fprintf(stderr, "file is not large enough to hold ELF header\n");
++ return NULL;
++ }
++
++ void *ehdr = mmap(NULL, statbuf.st_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
++ if (ehdr == MAP_FAILED)
++ {
++ perror("mmap");
++ return NULL;
++ }
++
++ if (memcmp(((ElfW(Ehdr) *) ehdr)->e_ident, ELFMAG, SELFMAG) != 0)
++ {
++ fprintf(stderr, "file is not ELF format\n");
++ munmap(ehdr, statbuf.st_size);
++ ehdr = NULL;
++ }
++
++ *len = statbuf.st_size;
++ return ehdr;
++}
++
++static __always_inline int check_ptr(void *ptr, void *start, size_t len)
++{
++ if (ptr < start || ptr > start + len)
++ return -1;
++ return 0;
++}
++
++static __always_inline void *get_phdr(void *ehdr, size_t length)
++{
++ if (((ElfW(Ehdr) *)ehdr)->e_phentsize != sizeof(ElfW(Phdr)))
++ {
++ fprintf(stderr, "ELF header's e_phentsize mismatch ElfW(Phdr) size\n");
++ return NULL;
++ }
++
++ unsigned int size = ((ElfW(Ehdr) *)ehdr)->e_phnum * sizeof(ElfW(Phdr));
++ if (size == 0 || size > ELF_MIN_ALIGN)
++ {
++ fprintf(stderr, "The program header table size specified by ELF header is abnormal: %u\n", size);
++ return NULL;
++ }
++
++ void *ephdr_s = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff;
++ void *ephdr_e = ehdr + ((ElfW(Ehdr) *)ehdr)->e_phoff + size;
++
++ if (check_ptr(ephdr_s, ehdr, length) ||
++ check_ptr(ephdr_e, ehdr, length))
++ {
++ fprintf(stderr, "ELF porgram header table is not fully mmaped\n");
++ return NULL;
++ }
++
++ return ephdr_s;
++}
+diff --git a/elf/tst-hugepageedit1.sh b/elf/tst-hugepageedit1.sh
+new file mode 100644
+index 00000000..ee43c279
+--- /dev/null
++++ b/elf/tst-hugepageedit1.sh
+@@ -0,0 +1,85 @@
++#!/bin/sh
++# Test that hugepageedit can handle abnormal files reasonably
++# Copyright (C) 2021-2021 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <http://www.gnu.org/licenses/>.
++
++set -ex
++echo "source $4"
++source $4
++
++common_objpfx=$1
++test_wrapper=$2
++test_wrapper_env=$3
++result=0
++
++excption_handle ()
++{
++ echo "hugepageedit and ls.so use hugepage feature is not beahving expected"
++ result=1
++}
++
++testroot="${common_objpfx}elf/hugepageedit-test-directory"
++
++rm -rf "$testroot"
++mkdir -p $testroot
++cp ${common_objpfx}elf/tst-use-hugepage1 $testroot/tst-use-hugepage1
++
++echo '# reseve 200 2MB hugepage'
++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
++
++echo '# Test no option hugepageedit'
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1
++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log1 2>&1
++check_hugepage_mmap_success ${testroot}/log1 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# Test hugepageedit -d option'
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1
++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log2 2>&1
++check_hugepage_mmap ${testroot}/log2 && rc=1 || rc=0
++test $rc -eq 0 || excption_handle
++
++echo '# Test hugepageedit -x option'
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit -x ${common_objpfx}elf/tst-ld-hugepagemod1.so || exit 1
++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage1 > ${testroot}/log3 2>&1
++check_hugepage_mmap_success ${testroot}/log3 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# Test Non-ELF file'
++dd if=/dev/urandom of=${testroot}/test.file count=1024 bs=1024
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/test.file 2>&1 && result=1
++
++echo '# Test ELF phnum is 0'
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/tst-update-ehdr ${testroot}/tst-use-hugepage1 0 2>&1 || result=1
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/tst-use-hugepage1 2>&1 && result=1
++
++echo '# Test ELF phnum is 0xFFFF'
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/tst-update-ehdr ${testroot}/tst-use-hugepage1 65535 2>&1 || result=1
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit ${testroot}/tst-use-hugepage1 2>&1 && result=1
++
++exit $result
+diff --git a/elf/tst-ld-hugepage-env.sh b/elf/tst-ld-hugepage-env.sh
+new file mode 100644
+index 00000000..e16ada67
+--- /dev/null
++++ b/elf/tst-ld-hugepage-env.sh
+@@ -0,0 +1,108 @@
++#!/bin/sh
++# Test that ld.so can handle different env input
++# Copyright (C) 2021-2021 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <http://www.gnu.org/licenses/>.
++
++set -ex
++echo "source $4"
++source $4
++
++common_objpfx=$1
++test_wrapper=$2
++test_wrapper_env=$3
++result=0
++
++excption_handle ()
++{
++ echo "ld.so hugepage feature is not behaving as expected"
++ result=1
++}
++
++testroot="${common_objpfx}elf/ld-hugepage-env-directory"
++
++rm -rf "$testroot"
++mkdir -p $testroot
++
++echo '# reseve 200 2MB hugepage'
++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
++
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod2.so || exit 1
++
++echo '# Test HUGEPAGE_PROBE env set 1 and shared object is not hugepageedited'
++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log1 2>&1
++check_hugepage_mmap ${testroot}/log1 && rc=1 || rc=0
++test $rc -eq 0 || excption_handle
++
++echo '# Test LD_HUGEPAGE_LIB env set 1 and shared object is not hugepageedited'
++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log2 2>&1
++check_hugepage_mmap_success ${testroot}/log2 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# Test LD_HUGEPAGE_LIB env set 100 and shared object is not hugepageedited'
++${test_wrapper_env} LD_HUGEPAGE_LIB=100 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log3 2>&1
++check_hugepage_mmap ${testroot}/log3 && rc=1 || rc=0
++test $rc -eq 0 || excption_handle
++
++echo '# Test LD_HUGEPAGE_LIB env set -8 and shared object is not hugepageedited'
++${test_wrapper_env} LD_HUGEPAGE_LIB=-8 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log4 2>&1
++check_hugepage_mmap ${testroot}/log4 && rc=1 || rc=0
++test $rc -eq 0 || excption_handle
++
++echo '# Test LD_HUGEPAGE_LIB env set aa#_bb and shared object is not hugepageedited'
++${test_wrapper_env} LD_HUGEPAGE_LIB=aa#_bb LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log5 2>&1
++check_hugepage_mmap ${testroot}/log5 && rc=1 || rc=0
++test $rc -eq 0 || excption_handle
++
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod2.so || exit 1
++echo '# Test HUGEPAGE_PROBE env set 2 and shared object is hugepageedited'
++${test_wrapper_env} HUGEPAGE_PROBE=2 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log6 2>&1
++check_hugepage_mmap_success ${testroot}/log6 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# Test HUGEPAGE_PROBE env set -2 and shared object is hugepageedited'
++${test_wrapper_env} HUGEPAGE_PROBE=-2 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log7 2>&1
++check_hugepage_mmap_success ${testroot}/log7 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# Test HUGEPAGE_PROBE env set 0 and shared object is hugepageedited'
++${test_wrapper_env} HUGEPAGE_PROBE=0 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log8 2>&1
++check_hugepage_mmap_success ${testroot}/log8 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# Test HUGEPAGE_PROBE env set 3.14 and shared object is hugepageedited'
++${test_wrapper_env} HUGEPAGE_PROBE=3.14 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log9 2>&1
++check_hugepage_mmap_success ${testroot}/log9 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# Test HUGEPAGE_PROBE env set #aabb and shared object is hugepageedited'
++${test_wrapper_env} HUGEPAGE_PROBE=#aabb LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage2 > ${testroot}/log10 2>&1
++check_hugepage_mmap_success ${testroot}/log10 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++exit $result
+diff --git a/elf/tst-ld-hugepage-fallback.sh b/elf/tst-ld-hugepage-fallback.sh
+new file mode 100644
+index 00000000..0c616633
+--- /dev/null
++++ b/elf/tst-ld-hugepage-fallback.sh
+@@ -0,0 +1,66 @@
++#!/bin/sh
++# Test that ld.so can fallback to original shared object load process when
++# exception happens
++# Copyright (C) 2021-2021 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <http://www.gnu.org/licenses/>.
++
++echo "source $4"
++source $4
++
++common_objpfx=$1
++test_wrapper=$2
++test_wrapper_env=$3
++result=0
++
++excption_handle ()
++{
++ echo "ld.so hugepage feature should fallback this time"
++ result=1
++}
++
++testroot="${common_objpfx}elf/ld-hugepage-fallback"
++
++rm -rf "$testroot"
++mkdir -p $testroot
++
++echo '# reseve 200 2MB hugepage'
++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
++
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit -d ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1
++
++echo '# tst-update-phdr make shared object previous PT_LOAD segment vma > next'
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/tst-update-phdr ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1
++
++echo '# Test LD_HUGEPAGE_LIB env set 1 and shared object is not hugepageedited'
++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage3 > ${testroot}/log1 2>&1
++check_hugepage_fallback ${testroot}/log1 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++echo '# hugepageedit shared object'
++${test_wrapper_env} \
++${test_wrapper} ${common_objpfx}elf/hugepageedit ${common_objpfx}elf/tst-ld-hugepagemod3.so || exit 1
++
++echo '# Test HUGEPAGE_PROBE env set 1 and shared object is hugepageedited'
++${test_wrapper_env} HUGEPAGE_PROBE=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage3 > ${testroot}/log2 2>&1
++check_hugepage_fallback ${testroot}/log2 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle
++
++exit $result
+diff --git a/elf/tst-ld-hugepage-mmap-smaps.sh b/elf/tst-ld-hugepage-mmap-smaps.sh
+new file mode 100644
+index 00000000..b817ab53
+--- /dev/null
++++ b/elf/tst-ld-hugepage-mmap-smaps.sh
+@@ -0,0 +1,49 @@
++#!/bin/sh
++# Test that ld.so mmapping hugepage is consistent with the actual process occupancy
++# Copyright (C) 2021-2021 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <http://www.gnu.org/licenses/>.
++
++set -ex
++echo "source $4"
++source $4
++
++common_objpfx=$1
++test_wrapper=$2
++test_wrapper_env=$3
++result=0
++
++excption_handle ()
++{
++ echo "ld.so mmap hugepage is not consistent with the actual process occupancy, return $1"
++ result=1
++}
++
++testroot="${common_objpfx}elf/ld-hugepage-mmap-smaps"
++
++rm -rf "$testroot"
++mkdir -p $testroot
++
++echo '# reseve 200 2MB hugepage'
++echo 200 > /sys/devices/system/node/node0/hugepages/hugepages-2048kB/nr_hugepages || exit 1
++
++echo '# Test LD_HUGEPAGE_LIB=1 whether ld.so mmap hugepage is consistent with the actual process occupancy'
++${test_wrapper_env} LD_HUGEPAGE_LIB=1 LD_DEBUG=files \
++${test_wrapper} ${common_objpfx}elf/tst-use-hugepage4 > ${testroot}/log1 2>&1
++check_hugepage_mmap_detail ${testroot}/log1 && rc=0 || rc=$?
++test $rc -eq 0 || excption_handle $rc
++
++exit $result
+diff --git a/elf/tst-ld-hugepage.h b/elf/tst-ld-hugepage.h
+new file mode 100644
+index 00000000..30e938da
+--- /dev/null
++++ b/elf/tst-ld-hugepage.h
+@@ -0,0 +1,7 @@
++#ifndef TST_HUGEPAGE_H
++#define TST_HUGEPAGE_H
++
++extern void huge_func(void);
++extern int huge_global;
++
++#endif
+diff --git a/elf/tst-ld-hugepagemod.c b/elf/tst-ld-hugepagemod.c
+new file mode 100644
+index 00000000..70c42e5a
+--- /dev/null
++++ b/elf/tst-ld-hugepagemod.c
+@@ -0,0 +1,19 @@
++#include <stdio.h>
++
++#define BIN_PATH OBJDIR"/tst-ld-hugepage-bin.o"
++
++int huge_global;
++
++asm (".section .rodata\n\t" \
++ ".globl vvvdso_start, vvvdso_end\n" \
++ ".balign 4096\n" \
++ "vvvdso_start:\n\t" \
++ ".incbin " "\""BIN_PATH"\"" "\n\t" \
++ ".balign 4096\n" \
++ "vvvdso_end:\n\t" \
++ ".previous");
++
++void huge_func(void)
++{
++ printf("In huge_func, huge_global = %d\n", huge_global);
++}
+diff --git a/elf/tst-update-ehdr.c b/elf/tst-update-ehdr.c
+new file mode 100644
+index 00000000..6d653aa0
+--- /dev/null
++++ b/elf/tst-update-ehdr.c
+@@ -0,0 +1,58 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <elf.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <errno.h>
++#include <unistd.h>
++#include <sys/stat.h>
++#include "tst-get-ephdr.h"
++
++#define TOOL_NAME "tst-update-ehdr"
++
++void print_usage(void)
++{
++ fprintf(stderr, "%s <ELF file> <phdr number>\n", TOOL_NAME);
++}
++
++int main(int argc, char **argv)
++{
++ size_t length;
++ int exit_status = EXIT_FAILURE;
++
++ if (argc != 3)
++ {
++ print_usage();
++ exit(EXIT_FAILURE);
++ }
++
++ int fd = open(argv[1], O_RDWR);
++ if (fd < 0)
++ {
++ perror("open");
++ exit(EXIT_FAILURE);
++ }
++
++ void *ehdr = get_ehdr(fd, &length);
++ if (ehdr == NULL)
++ goto close_fd;
++
++ char *endptr;
++ unsigned long val = strtoul(argv[2], &endptr, 10);
++ if ((errno == ERANGE && val == ULONG_MAX) || (errno != 0 && val == 0))
++ {
++ perror("strtoul");
++ goto unmap;
++ }
++
++ ((ElfW(Ehdr) *)ehdr)->e_phnum = val;
++ exit_status = EXIT_SUCCESS;
++
++unmap:
++ munmap(ehdr, length);
++
++close_fd:
++ close(fd);
++
++ exit(exit_status);
++}
+diff --git a/elf/tst-update-phdr.c b/elf/tst-update-phdr.c
+new file mode 100644
+index 00000000..bd3e30eb
+--- /dev/null
++++ b/elf/tst-update-phdr.c
+@@ -0,0 +1,93 @@
++/* construct exception PT_LOAD segment VMA
++ make previous PT_LOAD vma > next PT_LOAD vma
++ Copyright (C) 2021-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++#include <stdio.h>
++#include <stdlib.h>
++#include <fcntl.h>
++#include <string.h>
++#include <unistd.h>
++#include <elf.h>
++#include <link.h>
++#include <sys/stat.h>
++#include <sys/mman.h>
++#include <sys/types.h>
++#include "tst-get-ephdr.h"
++
++#define TOOL_NAME "tst-update-phdr"
++#define PAGE_SIZE 0x1000
++
++void print_usage(void)
++{
++ fprintf(stderr, "%s <ELF file>\n", TOOL_NAME);
++}
++
++int main(int argc, char **argv)
++{
++ size_t length;
++ int exit_status = EXIT_FAILURE;
++ int i;
++ if (argc != 2)
++ {
++ print_usage();
++ exit(EXIT_FAILURE);
++ }
++
++ int fd = open(argv[1], O_RDWR);
++ if (fd < 0)
++ {
++ perror("open");
++ exit(EXIT_FAILURE);
++ }
++
++ void *ehdr = get_ehdr(fd, &length);
++ if (ehdr == NULL)
++ goto close_fd;
++
++ ElfW(Phdr) *phdr = (ElfW(Phdr) *)get_phdr(ehdr, length);
++ if (phdr == NULL)
++ goto unmap;
++
++ ElfW(Phdr) *prev =NULL, *next = NULL;
++ for (i = 0; i < ((ElfW(Ehdr) *)ehdr)->e_phnum; i++)
++ {
++ if (prev != NULL && next != NULL)
++ break;
++ if (phdr[i].p_type == PT_LOAD)
++ {
++ if (prev == NULL)
++ prev = &phdr[i];
++ else
++ next = &phdr[i];
++ }
++ }
++ if (prev != NULL && next != NULL)
++ {
++ prev->p_vaddr = next->p_vaddr + PAGE_SIZE;
++ exit_status = EXIT_SUCCESS;
++ }
++ else
++ fprintf(stderr, "There are no PT_LOADs in %s\n", argv[1]);
++
++unmap:
++ munmap(ehdr, length);
++
++close_fd:
++ close(fd);
++
++ exit(exit_status);
++}
+diff --git a/elf/tst-use-hugepage.c b/elf/tst-use-hugepage.c
+new file mode 100644
+index 00000000..938e0afc
+--- /dev/null
++++ b/elf/tst-use-hugepage.c
+@@ -0,0 +1,15 @@
++#include <stdio.h>
++#include <stdlib.h>
++#include <unistd.h>
++#include "tst-ld-hugepage.h"
++
++int main(void)
++{
++ char command[100];
++ sprintf(command, "cat /proc/%d/smaps", getpid());
++ system(command);
++ huge_func();
++ huge_global = 1;
++ huge_func();
++ return 0;
++}
+--
+2.31.1
+
diff --git a/0002-elf-ld.so-keep-compatible-with-the-original-policy-o.patch b/0002-elf-ld.so-keep-compatible-with-the-original-policy-o.patch
new file mode 100644
index 0000000..ea95478
--- /dev/null
+++ b/0002-elf-ld.so-keep-compatible-with-the-original-policy-o.patch
@@ -0,0 +1,34 @@
+From 2ace2eddbd6a0cda2006e632444cd19a360d12d4 Mon Sep 17 00:00:00 2001
+From: Lv Ying <lvying6@huawei.com>
+Date: Fri, 24 Feb 2023 16:14:42 +0800
+Subject: [PATCH 2/3] elf/ld.so: keep compatible with the original policy of
+ the LD_HUGEPAGE_LIB env
+
+When we use new policy: ld.so load PT_LOAD segement use hugepage according to
+PF_HUGEPAGE flag. We should keep compatible with the original policy of
+the LD_HUGEPAGE_LIB env which loads all the PT_LOAD segment try to use
+hugepage.
+
+Signed-off-by: Lv Ying <lvying6@huawei.com>
+---
+ elf/dl-load.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index e0d4fa2e..e01bb448 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1184,7 +1184,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ }
+
+ #ifdef HUGEPAGE_SHARED_LIB
+- if (ph->p_flags & PF_HUGEPAGE) {
++ if (GLRO(dl_hugepage_mask) & DL_HUGEPAGE_LIB_LARGE_IN_FLAG) {
++ hp_bitmap[nloadcmds] = 1;
++ } else if (ph->p_flags & PF_HUGEPAGE) {
+ hp_bitmap[nloadcmds] = 1;
+ use_hugepage = true;
+ } else
+--
+2.38.1
+
diff --git a/0003-add-build-script-and-files-of-libpthread_2_17_so.patch b/0003-add-build-script-and-files-of-libpthread_2_17_so.patch
new file mode 100644
index 0000000..75ca704
--- /dev/null
+++ b/0003-add-build-script-and-files-of-libpthread_2_17_so.patch
@@ -0,0 +1,135 @@
+From 7cb15fbef45361db6ad718077a4f0a6d2dc845f2 Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Wed Nov 24 09:31:31 2021 +0800
+Subject: [PATCH 3/9] build extra lipthreadcond so
+
+Add the build script and file of libpthread-2.17.so
+
+---
+ nptl_2_17/Makefile | 52 +++++++++++++++++++++++++++
+ nptl_2_17/build_libpthread-2.17.so.sh | 10 ++++++
+ nptl_2_17/libpthread-2.17-aarch64.map | 14 ++++++++
+ nptl_2_17/libpthread-2.17-x86_64.map | 14 ++++++++
+ 4 files changed, 90 insertions(+)
+ create mode 100644 nptl_2_17/Makefile
+ create mode 100644 nptl_2_17/build_libpthread-2.17.so.sh
+ create mode 100644 nptl_2_17/libpthread-2.17-aarch64.map
+ create mode 100644 nptl_2_17/libpthread-2.17-x86_64.map
+
+diff --git a/nptl_2_17/Makefile b/nptl_2_17/Makefile
+new file mode 100644
+index 00000000..f248ce56
+--- /dev/null
++++ b/nptl_2_17/Makefile
+@@ -0,0 +1,52 @@
++include libpthread-2.17_config
++subdir=libpthread-2.17
++objdir=../$(build_dir)/
++
++
++ifdef subdir
++.. := ../
++endif
++
++objpfx := $(patsubst %//,%/,$(objdir)/$(subdir)/)
++common-objpfx = $(objdir)/
++common-objdir = $(objdir)
++
++sysdep_dir := $(..)sysdeps
++export sysdep_dir := $(sysdep_dir)
++
++include $(common-objpfx)soversions.mk
++include $(common-objpfx)config.make
++
++uses-callbacks = -fexceptions
++
++sysdirs := $(foreach D,$(config-sysdirs),$(firstword $(filter /%,$D) $(..)$D))
++
+++sysdep_dirs = $(sysdirs)
+++sysdep_dirs := $(objdir) $(+sysdep_dirs)
++
+++sysdep-includes := $(foreach dir,$(+sysdep_dirs), $(addprefix -I,$(wildcard $(dir)/include) $(dir)))
++
++compile_obj = pthread_cond_wait_2_17.os pthread_cond_signal_2_17.os pthread_cond_broadcast_2_17.os pthread_cond_init_2_17.os pthread_cond_destroy_2_17.os pthread_condattr_getclock_2_17.os pthread_condattr_getpshared_2_17.os pthread_condattr_init_2_17.os pthread_condattr_setclock_2_17.os cleanup_compat_2_17.os pthread_mutex_lock_2_17.os pthread_mutex_unlock_2_17.os tpp_2_17.os vars_2_17.os pause_nocancel_2_17.os lll_timedlock_wait_2_17.os pthread_mutex_cond_lock_2_17.os cancellation_2_17.os lowlevellock_2_17.os unwind_2_17.os
++
++ifeq (x86_64, $(arch))
++compile_obj += elision-timed_2_17.os elision-trylock_2_17.os elision-lock_2_17.os elision-unlock_2_17.os
++endif
++
++exist_obj_dir = $(foreach n,$(exist_obj),../$(build_dir)/nptl/$(n))
++
++compile_obj_dir = $(foreach n,$(compile_obj),../$(build_dir)/nptl/$(n))
++
++CFLAGS = -c -std=gnu11 -fgnu89-inline -fPIE -DNDEBUG -O2 -Wall -Werror -Wp,-D_GLIBCXX_ASSERTIONS -Wundef -Wwrite-strings -fasynchronous-unwind-tables -fmerge-all-constants -frounding-math -fstack-clash-protection -fstack-protector-strong -g -mtune=generic -Wstrict-prototypes -Wold-style-definition -fno-math-errno -fPIC -fexceptions -fasynchronous-unwind-tables -ftls-model=initial-exec -D_FORTIFY_SOURCE=2 -DSHARED -DTOP_NAMESPACE=glibc
++
++Headers = -I../include -I../$(build_dir)/nptl $(+sysdep-includes) -I../nptl_2_17 -I../nptl -I../libio -I../. -D_LIBC_REENTRANT -include ../$(build_dir)/libc-modules.h -include include/libc-symbols.h
++
++all: libpthread-2.17.so
++
++libpthread-2.17.so : $(compile_obj) libpthread-2.17_pic.a
++ gcc -shared -static-libgcc -Wl,-O1 -Wl,-z,defs -Wl,-dynamic-linker=/usr/local/lib/$(ld.so-version) -B../$(build_dir)/csu/ -Wl,--version-script=libpthread-2.17-$(arch).map -Wl,-soname=libpthread-2.17.so.0 -Wl,-z,noexecstack -Wtrampolines -Wl,-z,combreloc -Wl,-z,relro -Wl,--hash-style=both -Wl,-z,now -Wl,--enable-new-dtags,-z,nodelete,-z,initfirst -L../$(build_dir) -L../$(build_dir)/math -L../$(build_dir)/elf -L../$(build_dir)/dlfcn -L../$(build_dir)/nss -L../$(build_dir)/nis -L../$(build_dir)/rt -L../$(build_dir)/resolv -L../$(build_dir)/mathvec -L../$(build_dir)/support -L../$(build_dir)/crypt -L../$(build_dir)/nptl -Wl,-rpath-link=../$(build_dir):../$(build_dir)/math:../$(build_dir)/elf:../$(build_dir)/dlfcn:../$(build_dir)/nss:../$(build_dir)/nis:../$(build_dir)/rt:../$(build_dir)/resolv:../$(build_dir)/mathvec:../$(build_dir)/support:../$(build_dir)/crypt:../$(build_dir)/nptl -o ../$(build_dir)/nptl/libpthread-2.17.so ../$(build_dir)/csu/abi-note.o -Wl,--whole-archive ../$(build_dir)/nptl/libpthread-2.17_pic.a -Wl,--no-whole-archive -Wl,--start-group ../$(build_dir)/libc.so ../$(build_dir)/libc_nonshared.a -Wl,--as-needed ../$(build_dir)/elf/ld.so -Wl,--no-as-needed -Wl,--end-group
++
++libpthread-2.17_pic.a : $(compile_obj_dir) $(exist_obj_dir)
++ ar cruv ../$(build_dir)/nptl/$@ $^
++
++$(compile_obj) : %.os : %.c
++ gcc $< $(CFLAGS) $(Headers) -o ../$(build_dir)/nptl/$@ -MD -MP -MF ../$(build_dir)/nptl/$@.dt -MT ../$(build_dir)/nptl/$@
+diff --git a/nptl_2_17/build_libpthread-2.17.so.sh b/nptl_2_17/build_libpthread-2.17.so.sh
+new file mode 100644
+index 00000000..bdb97d0f
+--- /dev/null
++++ b/nptl_2_17/build_libpthread-2.17.so.sh
+@@ -0,0 +1,10 @@
++#!/bin/sh
++set -e
++build_arch=$1
++build_dir=$2
++config_dir=libpthread-2.17_config
++
++echo arch=${build_arch} > ${config_dir}
++echo build_dir=${build_dir} >> ${config_dir}
++make
++rm -rf ${config_dir}
+diff --git a/nptl_2_17/libpthread-2.17-aarch64.map b/nptl_2_17/libpthread-2.17-aarch64.map
+new file mode 100644
+index 00000000..2c49fe17
+--- /dev/null
++++ b/nptl_2_17/libpthread-2.17-aarch64.map
+@@ -0,0 +1,14 @@
++GLIBC_2.17 {
++ global:
++ pthread_cond_init; pthread_cond_destroy;
++ pthread_cond_signal; pthread_cond_broadcast;
++ pthread_cond_wait; pthread_cond_timedwait;
++ local:
++ *;
++};
++GLIBC_2.34 {
++ global:
++ pthread_cond_clockwait;
++ local:
++ *;
++};
+diff --git a/nptl_2_17/libpthread-2.17-x86_64.map b/nptl_2_17/libpthread-2.17-x86_64.map
+new file mode 100644
+index 00000000..b01e7d0d
+--- /dev/null
++++ b/nptl_2_17/libpthread-2.17-x86_64.map
+@@ -0,0 +1,14 @@
++GLIBC_2.3.2 {
++ global:
++ pthread_cond_init; pthread_cond_destroy;
++ pthread_cond_signal; pthread_cond_broadcast;
++ pthread_cond_wait; pthread_cond_timedwait;
++ local:
++ *;
++};
++GLIBC_2.34 {
++ global:
++ pthread_cond_clockwait;
++ local:
++ *;
++};
+--
+2.30.0
+
diff --git a/0003-elf-ld.so-remove-_mmap_hole-when-ld.so-mmap-PT_LOAD-.patch b/0003-elf-ld.so-remove-_mmap_hole-when-ld.so-mmap-PT_LOAD-.patch
new file mode 100644
index 0000000..a12f0fb
--- /dev/null
+++ b/0003-elf-ld.so-remove-_mmap_hole-when-ld.so-mmap-PT_LOAD-.patch
@@ -0,0 +1,84 @@
+From 117a913e7b1c380bb99796588b266547de959de9 Mon Sep 17 00:00:00 2001
+From: Lv Ying <lvying6@huawei.com>
+Date: Thu, 23 Feb 2023 22:15:06 +0800
+Subject: [PATCH 3/3] elf/ld.so: remove _mmap_hole when ld.so mmap PT_LOAD
+ segment try to use hugepage
+
+When ld.so mmap PT_LOAD segment try to use hugepage, it's unnecessary to
+remap hole area, becasue __mmap_reserved_area already mmap reserved area
+as PROT_NONE. Besides _mmap_hole may mmap hole area from 4KB page
+misaligned addresses which will cause mmap faiure(invalid argument).
+
+Signed-off-by: Lv Ying <lvying6@huawei.com>
+---
+ elf/dl-load.h | 2 --
+ elf/dl-map-segments-hugepage.h | 26 --------------------------
+ 2 files changed, 28 deletions(-)
+
+diff --git a/elf/dl-load.h b/elf/dl-load.h
+index fcf91a47..f2428165 100644
+--- a/elf/dl-load.h
++++ b/elf/dl-load.h
+@@ -136,8 +136,6 @@ static const char *_dl_map_segments (struct link_map *l, int fd,
+ N_("cannot map Non shared object file in hugepage")
+ #define DL_MAP_SEGMENTS_ERROR_ARRANGE \
+ N_("shared object's PT_LOAD segment in wrong arrange")
+-#define DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL \
+- N_("failed to mmap shared object's hole part of PT_LOAD")
+ #define DL_MAP_RESERVED_HUGEPAGE_AREA_ERROR \
+ N_("failed to map reserved 2MB contiguous hugepage va space")
+ #define DL_FIND_EXEC_SEGMENT_ERROR \
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+index e7202131..a352c903 100644
+--- a/elf/dl-map-segments-hugepage.h
++++ b/elf/dl-map-segments-hugepage.h
+@@ -486,19 +486,6 @@ _mmap_segment(struct link_map *l, const struct loadcmd loadcmds[], size_t nloadc
+ return NULL;
+ }
+
+-static __always_inline void *
+-_mmap_hole(const struct loadcmd *current, const struct loadcmd *next,
+- ElfW(Addr) mapstart, size_t mapseglen, int fd)
+-{
+- if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+- _dl_debug_printf("\tmmap hole area:[%lx-%lx)\n", mapstart + mapseglen,
+- mapstart + (next->mapstart - current->mapstart));
+- return __mmap((void *)(mapstart + mapseglen),
+- next->mapstart - (current->mapstart + mapseglen),
+- PROT_NONE, MAP_FILE|MAP_PRIVATE|MAP_FIXED,
+- fd, current->mapoff + mapseglen);
+-}
+-
+ static __always_inline const char *
+ _dl_map_segments_largein (struct link_map *l, int fd,
+ const ElfW(Ehdr) *header, int type,
+@@ -541,13 +528,6 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ goto unmap_reserved_area;
+ }
+
+- if (prev->mapstart + mapseglen < c->mapstart &&
+- _mmap_hole(prev, c, map_addr, mapseglen, fd) == MAP_FAILED)
+- {
+- errstring = DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL;
+- goto unmap_reserved_area;
+- }
+-
+ map_addr += c->mapstart - prev->mapstart;
+ errstring = _mmap_segment(l, loadcmds, nloadcmds, c, map_addr, fd,
+ &mapseglen, hp_bitmap);
+@@ -582,12 +562,6 @@ _dl_map_segments_largein (struct link_map *l, int fd,
+ goto unmap_reserved_area;
+ }
+
+- if (c->mapstart + mapseglen < prev->mapstart &&
+- _mmap_hole(c, prev, map_addr, mapseglen, fd) == MAP_FAILED)
+- {
+- errstring = DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL;
+- goto unmap_reserved_area;
+- }
+ prev = c;
+ --c;
+ }
+--
+2.38.1
+
diff --git a/0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch b/0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch
new file mode 100644
index 0000000..8b67e66
--- /dev/null
+++ b/0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch
@@ -0,0 +1,69 @@
+From 49986b3674d002c43fa09e6b777555bdc772018b Mon Sep 17 00:00:00 2001
+From: Lv Ying <lvying6@huawei.com>
+Date: Tue, 25 Jan 2022 09:29:32 +0000
+Subject: [PATCH 3/3] elf/ld.so: use special mmap for hugepage to get symbols
+
+use special mmap for hugepage to get symbols in hugepage area for debug
+purpose; kernel need to support file mmap hugepage;
+---
+ elf/dl-load.h | 2 --
+ elf/dl-map-segments-hugepage.h | 25 +++----------------------
+ 2 files changed, 3 insertions(+), 24 deletions(-)
+
+diff --git a/elf/dl-load.h b/elf/dl-load.h
+index d3f69466..fcf91a47 100644
+--- a/elf/dl-load.h
++++ b/elf/dl-load.h
+@@ -134,8 +134,6 @@ static const char *_dl_map_segments (struct link_map *l, int fd,
+ #ifdef HUGEPAGE_SHARED_LIB
+ #define DL_MAP_SEGMENTS_ERROR_TYPE \
+ N_("cannot map Non shared object file in hugepage")
+-#define DL_MAP_SEGMENTS_ERROR_READ_SEGMENT \
+- N_("failed to read shared object file")
+ #define DL_MAP_SEGMENTS_ERROR_ARRANGE \
+ N_("shared object's PT_LOAD segment in wrong arrange")
+ #define DL_MAP_SEGMENTS_ERROR_MAP_HOLE_FILL \
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+index cd7b6d79..37788ef9 100644
+--- a/elf/dl-map-segments-hugepage.h
++++ b/elf/dl-map-segments-hugepage.h
+@@ -302,33 +302,14 @@ _mmap_segment_filesz(struct link_map *l, const struct loadcmd *c, ElfW(Addr) map
+
+ size_t mod = len % SIZE_2MB;
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+- _dl_debug_printf("\t\tmmap hugepage: [%lx-%lx)\n", mapstart, mapstart + len - mod);
++ _dl_debug_printf("\t\tmmap hugepage: [%lx-%lx), mapoff = %lx\n", mapstart,
++ mapstart + len - mod, c->mapoff + relro_len + prev_map_len);
+ mapstart = (ElfW(Addr))__mmap((void *)mapstart, len - mod, c->prot,
+ MAP_FIXED|MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT),
+- -1, 0);
++ fd, c->mapoff + relro_len + prev_map_len);
+ if (__glibc_unlikely ((void *)mapstart == MAP_FAILED))
+ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+
+- if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot | PROT_WRITE) < 0)
+- {
+- return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+- }
+-
+- /* Read the segment contents from the file. */
+- size_t file_len = (size_t)(c->dataend - c->mapstart) <= prev_map_len + relro_len ? 0 :
+- (size_t)(c->dataend - c->mapstart) - prev_map_len - relro_len;
+- if (file_len > 0)
+- {
+- lseek(fd, c->mapoff + relro_len + prev_map_len, SEEK_SET);
+- if ( __read(fd, (void *)mapstart, file_len < len - mod ? file_len : len - mod) < 0)
+- return DL_MAP_SEGMENTS_ERROR_READ_SEGMENT;
+- }
+-
+- if ((c->prot & PROT_WRITE) == 0 && __mprotect((void *)mapstart, len - mod, c->prot) < 0)
+- {
+- return DL_MAP_SEGMENTS_ERROR_MPROTECT;
+- }
+-
+ map_addr = map_addr == 0 ? (void *)mapstart : map_addr;
+ mapstart += len - mod;
+
+--
+2.31.1
+
diff --git a/0004-add-two-header-files-with-some-deleted-macros.patch b/0004-add-two-header-files-with-some-deleted-macros.patch
new file mode 100644
index 0000000..7acb8e2
--- /dev/null
+++ b/0004-add-two-header-files-with-some-deleted-macros.patch
@@ -0,0 +1,166 @@
+From d6e6184b4f10ef2cbdec09eae60350ced71e3de7 Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Wed Nov 24 09:31:31 2021 +0800
+Subject: [PATCH 4/9] build extra lipthreadcond so
+
+For compatibility with glibc2.17, two header files are added with some
+deleted macros.
+
+---
+ nptl_2_17/compat_pthread_2_17.h | 61 +++++++++++++++++++++++++++
+ nptl_2_17/old_macros_2_17.h | 75 +++++++++++++++++++++++++++++++++
+ 2 files changed, 136 insertions(+)
+ create mode 100644 nptl_2_17/compat_pthread_2_17.h
+ create mode 100644 nptl_2_17/old_macros_2_17.h
+
+diff --git a/nptl_2_17/compat_pthread_2_17.h b/nptl_2_17/compat_pthread_2_17.h
+new file mode 100644
+index 00000000..d13051ba
+--- /dev/null
++++ b/nptl_2_17/compat_pthread_2_17.h
+@@ -0,0 +1,61 @@
++#ifndef _COMPAT_PTHREAD_2_17_H
++#define _COMPAT_PTHREAD_2_17_H 1
++
++#include <bits/struct_rwlock.h>
++#include <unistd.h>
++
++#ifdef __x86_64__
++#define __PTHREAD_COMPAT_PADDING_MID
++#define __PTHREAD_COMPAT_PADDING_END
++#define __PTHREAD_MUTEX_LOCK_ELISION 1
++# define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0
++# define __PTHREAD_MUTEX_USE_UNION 0
++//# define ENABLE_ELISION_SUPPORT 1
++#else
++#define __PTHREAD_COMPAT_PADDING_MID
++#define __PTHREAD_COMPAT_PADDING_END
++#define __PTHREAD_MUTEX_LOCK_ELISION 0
++#define __PTHREAD_MUTEX_NUSERS_AFTER_KIND 0
++#define __PTHREAD_MUTEX_USE_UNION 0
++#endif
++
++#define CANCELSTATE_BIT 0
++#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT)
++ /* Bit set if asynchronous cancellation mode is selected. */
++#define CANCELTYPE_BIT 1
++#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT)
++ /* Bit set if canceling has been initiated. */
++#define CANCELING_BIT 2
++#define CANCELING_BITMASK (0x01 << CANCELING_BIT)
++ /* Bit set if canceled. */
++#define CANCELED_BIT 3
++#define CANCELED_BITMASK (0x01 << CANCELED_BIT)
++ /* Bit set if thread is exiting. */
++#define EXITING_BIT 4
++#define EXITING_BITMASK (0x01 << EXITING_BIT)
++ /* Bit set if thread terminated and TCB is freed. */
++#define TERMINATED_BIT 5
++#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT)
++ /* Bit set if thread is supposed to change XID. */
++#define SETXID_BIT 6
++#define SETXID_BITMASK (0x01 << SETXID_BIT)
++ /* Mask for the rest. Helps the compiler to optimize. */
++#define CANCEL_RESTMASK 0xffffff80
++
++
++#define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \
++ (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \
++ | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \
++ == (CANCELTYPE_BITMASK | CANCELED_BITMASK))
++
++# define INTERNAL_SYSCALL_DECL(err) do { } while (0)
++
++/*
++ * __pause_nocancel delete by fbb4a3143724ef3f044a4f05351,add it
++ */
++
++__typeof (pause) __pause_nocancel;
++hidden_proto (__pause_nocancel)
++
++#endif
++
+diff --git a/nptl_2_17/old_macros_2_17.h b/nptl_2_17/old_macros_2_17.h
+new file mode 100644
+index 00000000..334b2ab1
+--- /dev/null
++++ b/nptl_2_17/old_macros_2_17.h
+@@ -0,0 +1,75 @@
++#ifndef _OLD_MACROS_2_17_H
++#define _OLD_MACROS_2_17_H 1
++
++/*
++ * Contains macros that have been defined in glibc2.34.
++ * Cancel the definition and use the old version.
++ * This header file needs to be included at the end.
++ */
++#undef __lll_unlock
++#define __lll_unlock(futex, private) \
++ ((void) \
++ ({ \
++ int *__futex = (futex); \
++ int __private = (private); \
++ int __oldval = atomic_exchange_rel (__futex, 0); \
++ if (__glibc_unlikely (__oldval > 1)) \
++ lll_futex_wake (__futex, 1, __private); \
++ }))
++
++#undef lll_unlock
++#define lll_unlock(futex, private) \
++ __lll_unlock (&(futex), private)
++
++extern int __lll_timedlock_wait (int *futex, const struct timespec *,
++ int private) attribute_hidden;
++
++
++/* As __lll_lock, but with a timeout. If the timeout occurs then return
++ ETIMEDOUT. If ABSTIME is invalid, return EINVAL. */
++#define __lll_timedlock(futex, abstime, private) \
++ ({ \
++ int *__futex = (futex); \
++ int __val = 0; \
++ \
++ if (__glibc_unlikely \
++ (atomic_compare_and_exchange_bool_acq (__futex, 1, 0))) \
++ __val = __lll_timedlock_wait (__futex, abstime, private); \
++ __val; \
++ })
++#define lll_timedlock(futex, abstime, private) \
++ __lll_timedlock (&(futex), abstime, private)
++
++/* Verify whether the supplied clockid is supported by
++ lll_futex_clock_wait_bitset. */
++#define lll_futex_supported_clockid(clockid) \
++ ((clockid) == CLOCK_REALTIME || (clockid) == CLOCK_MONOTONIC)
++
++/* The kernel currently only supports CLOCK_MONOTONIC or
++ CLOCK_REALTIME timeouts for FUTEX_WAIT_BITSET. We could attempt to
++ convert others here but currently do not. */
++#define lll_futex_clock_wait_bitset(futexp, val, clockid, timeout, private) \
++ ({ \
++ long int __ret; \
++ if (lll_futex_supported_clockid (clockid)) \
++ { \
++ const unsigned int clockbit = \
++ (clockid == CLOCK_REALTIME) ? FUTEX_CLOCK_REALTIME : 0; \
++ const int op = \
++ __lll_private_flag (FUTEX_WAIT_BITSET | clockbit, private); \
++ \
++ __ret = lll_futex_syscall (6, futexp, op, val, \
++ timeout, NULL /* Unused. */, \
++ FUTEX_BITSET_MATCH_ANY); \
++ } \
++ else \
++ __ret = -EINVAL; \
++ __ret; \
++ })
++
++# undef INTERNAL_VSYSCALL
++# define INTERNAL_VSYSCALL INTERNAL_SYSCALL
++# undef INLINE_VSYSCALL
++# define INLINE_VSYSCALL INLINE_SYSCALL
++
++#endif
+--
+2.30.0
+
diff --git a/0005-add-pthread-functions_h.patch b/0005-add-pthread-functions_h.patch
new file mode 100644
index 0000000..f169140
--- /dev/null
+++ b/0005-add-pthread-functions_h.patch
@@ -0,0 +1,140 @@
+From 463dc947b4f9bc4137c9919ee72b896403926474 Mon Sep 17 00:00:00 2001
+From: Roland McGrath <roland@hack.frob.com>
+Date: Thu Jun 12 13:48:47 2014 -0700
+Subject: [PATCH 5/9] build extra lipthreadcond so
+
+add pthread-functions.h which delete by 1d67cf9e8a0194588e66fb3b7afcbdc3bf836a
+
+---
+ nptl_2_17/pthread-functions_2_17.h | 119 +++++++++++++++++++++++++++++
+ 1 file changed, 119 insertions(+)
+ create mode 100644 nptl_2_17/pthread-functions_2_17.h
+
+diff --git a/nptl_2_17/pthread-functions_2_17.h b/nptl_2_17/pthread-functions_2_17.h
+new file mode 100644
+index 00000000..07ca8e7e
+--- /dev/null
++++ b/nptl_2_17/pthread-functions_2_17.h
+@@ -0,0 +1,119 @@
++/* Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#ifndef _PTHREAD_FUNCTIONS_H
++#define _PTHREAD_FUNCTIONS_H 1
++
++#include <pthread.h>
++#include <setjmp.h>
++#include <internaltypes.h>
++#include <sysdep.h>
++
++struct xid_command;
++
++/* Data type shared with libc. The libc uses it to pass on calls to
++ the thread functions. */
++struct pthread_functions
++{
++ int (*ptr_pthread_attr_destroy) (pthread_attr_t *);
++ int (*ptr___pthread_attr_init_2_0) (pthread_attr_t *);
++ int (*ptr___pthread_attr_init_2_1) (pthread_attr_t *);
++ int (*ptr_pthread_attr_getdetachstate) (const pthread_attr_t *, int *);
++ int (*ptr_pthread_attr_setdetachstate) (pthread_attr_t *, int);
++ int (*ptr_pthread_attr_getinheritsched) (const pthread_attr_t *, int *);
++ int (*ptr_pthread_attr_setinheritsched) (pthread_attr_t *, int);
++ int (*ptr_pthread_attr_getschedparam) (const pthread_attr_t *,
++ struct sched_param *);
++ int (*ptr_pthread_attr_setschedparam) (pthread_attr_t *,
++ const struct sched_param *);
++ int (*ptr_pthread_attr_getschedpolicy) (const pthread_attr_t *, int *);
++ int (*ptr_pthread_attr_setschedpolicy) (pthread_attr_t *, int);
++ int (*ptr_pthread_attr_getscope) (const pthread_attr_t *, int *);
++ int (*ptr_pthread_attr_setscope) (pthread_attr_t *, int);
++ int (*ptr_pthread_condattr_destroy) (pthread_condattr_t *);
++ int (*ptr_pthread_condattr_init) (pthread_condattr_t *);
++ int (*ptr___pthread_cond_broadcast) (pthread_cond_t *);
++ int (*ptr___pthread_cond_destroy) (pthread_cond_t *);
++ int (*ptr___pthread_cond_init) (pthread_cond_t *,
++ const pthread_condattr_t *);
++ int (*ptr___pthread_cond_signal) (pthread_cond_t *);
++ int (*ptr___pthread_cond_wait) (pthread_cond_t *, pthread_mutex_t *);
++ int (*ptr___pthread_cond_timedwait) (pthread_cond_t *, pthread_mutex_t *,
++ const struct timespec *);
++ int (*ptr___pthread_cond_clockwait) (pthread_cond_t *,
++ pthread_mutex_t *,
++ clockid_t,
++ const struct timespec *);
++ int (*ptr___pthread_cond_broadcast_2_0) (pthread_cond_2_0_t *);
++ int (*ptr___pthread_cond_destroy_2_0) (pthread_cond_2_0_t *);
++ int (*ptr___pthread_cond_init_2_0) (pthread_cond_2_0_t *,
++ const pthread_condattr_t *);
++ int (*ptr___pthread_cond_signal_2_0) (pthread_cond_2_0_t *);
++ int (*ptr___pthread_cond_wait_2_0) (pthread_cond_2_0_t *, pthread_mutex_t *);
++ int (*ptr___pthread_cond_timedwait_2_0) (pthread_cond_2_0_t *,
++ pthread_mutex_t *,
++ const struct timespec *);
++ int (*ptr_pthread_equal) (pthread_t, pthread_t);
++ void (*ptr___pthread_exit) (void *) __attribute__ ((__noreturn__));
++ int (*ptr_pthread_getschedparam) (pthread_t, int *, struct sched_param *);
++ int (*ptr_pthread_setschedparam) (pthread_t, int,
++ const struct sched_param *);
++ int (*ptr_pthread_mutex_destroy) (pthread_mutex_t *);
++ int (*ptr_pthread_mutex_init) (pthread_mutex_t *,
++ const pthread_mutexattr_t *);
++ int (*ptr_pthread_mutex_lock) (pthread_mutex_t *);
++ int (*ptr_pthread_mutex_unlock) (pthread_mutex_t *);
++ int (*ptr___pthread_setcancelstate) (int, int *);
++ int (*ptr_pthread_setcanceltype) (int, int *);
++ void (*ptr___pthread_cleanup_upto) (__jmp_buf, char *);
++ int (*ptr___pthread_once) (pthread_once_t *, void (*) (void));
++ int (*ptr___pthread_rwlock_rdlock) (pthread_rwlock_t *);
++ int (*ptr___pthread_rwlock_wrlock) (pthread_rwlock_t *);
++ int (*ptr___pthread_rwlock_unlock) (pthread_rwlock_t *);
++ int (*ptr___pthread_key_create) (pthread_key_t *, void (*) (void *));
++ void *(*ptr___pthread_getspecific) (pthread_key_t);
++ int (*ptr___pthread_setspecific) (pthread_key_t, const void *);
++ void (*ptr__pthread_cleanup_push_defer) (struct _pthread_cleanup_buffer *,
++ void (*) (void *), void *);
++ void (*ptr__pthread_cleanup_pop_restore) (struct _pthread_cleanup_buffer *,
++ int);
++#define HAVE_PTR_NTHREADS
++ unsigned int *ptr_nthreads;
++ void (*ptr___pthread_unwind) (__pthread_unwind_buf_t *)
++ __attribute ((noreturn)) __cleanup_fct_attribute;
++ void (*ptr__nptl_deallocate_tsd) (void);
++ int (*ptr__nptl_setxid) (struct xid_command *);
++ void (*ptr_set_robust) (struct pthread *);
++};
++
++/* Variable in libc.so. */
++extern struct pthread_functions __libc_pthread_functions attribute_hidden;
++extern int __libc_pthread_functions_init attribute_hidden;
++
++#ifdef PTR_DEMANGLE
++# define PTHFCT_CALL(fct, params) \
++ ({ __typeof (__libc_pthread_functions.fct) __p; \
++ __p = __libc_pthread_functions.fct; \
++ PTR_DEMANGLE (__p); \
++ __p params; })
++#else
++# define PTHFCT_CALL(fct, params) \
++ __libc_pthread_functions.fct params
++#endif
++
++#endif /* pthread-functions.h */
+--
+2.30.0
+
diff --git a/0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch b/0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch
new file mode 100644
index 0000000..e60fc08
--- /dev/null
+++ b/0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch
@@ -0,0 +1,587 @@
+From 1cdbe579482c07e9f4bb3baa4864da2d3e7eb837 Mon Sep 17 00:00:00 2001
+From: Andi Kleen <ak@linux.intel.com>
+Date: Sat, 10 Nov 2012 00:51:26 -0800i
+Subject: [PATCH 6/9] build extra lipthreadcond so
+
+add elsion functions which moved to libc in glibc-2.34.
+Some attributes are changed and cannot be directly referenced.
+
+
+---
+ nptl_2_17/lll_timedlock_wait_2_17.c | 59 +++++++++++++++++++++++++++++
+ nptl_2_17/elision-conf_2_17.c | 138 +++++++++++++++++++++++++++++++
+ nptl_2_17/elision-lock_2_17.c | 107 ++++++++++++++++++++++++
+ nptl_2_17/elision-timed_2_17.c | 27 ++++++
+ nptl_2_17/elision-trylock_2_17.c | 75 +++++++++++++++++
+ nptl_2_17/elision-unlock_2_17.c | 34 ++++++++
+ nptl_2_17/hle_2_17.h | 75 +++++++++++++++++
+ 6 files changed, 515
+ insertions(+)
+ create mode 100644 nptl_2_17/lll_timedlock_wait_2_17.c
+ create mode 100644 nptl_2_17/elision-conf_2_17.c
+ create mode 100644 nptl_2_17/elision-lock_2_17.c
+ create mode 100644 nptl_2_17/elision-timed_2_17.c
+ create mode 100644 nptl_2_17/elision-trylock_2_17.c
+ create mode 100644 nptl_2_17/elision-unlock_2_17.c
+ create mode 100644 nptl_2_17/hle_2_17.h
+
+diff --git a/nptl_2_17/lll_timedlock_wait_2_17.c b/nptl_2_17/lll_timedlock_wait_2_17.c
+new file mode 100644
+index 00000000..91bf9637
+--- /dev/null
++++ b/nptl_2_17/lll_timedlock_wait_2_17.c
+@@ -0,0 +1,59 @@
++/* Timed low level locking for pthread library. Generic futex-using version.
++ Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <atomic.h>
++#include <errno.h>
++#include <lowlevellock.h>
++#include <sys/time.h>
++
++
++int
++__lll_timedlock_wait (int *futex, const struct timespec *abstime, int private)
++{
++ /* Reject invalid timeouts. */
++ if (abstime->tv_nsec < 0 || abstime->tv_nsec >= 1000000000)
++ return EINVAL;
++
++ /* Try locking. */
++ while (atomic_exchange_acq (futex, 2) != 0)
++ {
++ struct timeval tv;
++
++ /* Get the current time. */
++ (void) __gettimeofday (&tv, NULL);
++
++ /* Compute relative timeout. */
++ struct timespec rt;
++ rt.tv_sec = abstime->tv_sec - tv.tv_sec;
++ rt.tv_nsec = abstime->tv_nsec - tv.tv_usec * 1000;
++ if (rt.tv_nsec < 0)
++ {
++ rt.tv_nsec += 1000000000;
++ --rt.tv_sec;
++ }
++
++ if (rt.tv_sec < 0)
++ return ETIMEDOUT;
++
++ /* If *futex == 2, wait until woken or timeout. */
++ lll_futex_timed_wait (futex, 2, &rt, private);
++ }
++
++ return 0;
++}
+diff --git a/nptl_2_17/elision-conf_2_17.c b/nptl_2_17/elision-conf_2_17.c
+new file mode 100644
+index 00000000..22af2944
+--- /dev/null
++++ b/nptl_2_17/elision-conf_2_17.c
+@@ -0,0 +1,138 @@
++/* elision-conf.c: Lock elision tunable parameters.
++ Copyright (C) 2013-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "config.h"
++#include <pthreadP.h>
++#include <init-arch.h>
++#include <elision-conf.h>
++#include <unistd.h>
++
++#if HAVE_TUNABLES
++# define TUNABLE_NAMESPACE elision
++#endif
++#include <elf/dl-tunables.h>
++
++/* Reasonable initial tuning values, may be revised in the future.
++ This is a conservative initial value. */
++
++struct elision_config __elision_aconf =
++ {
++ /* How often to not attempt to use elision if a transaction aborted
++ because the lock is already acquired. Expressed in number of lock
++ acquisition attempts. */
++ .skip_lock_busy = 3,
++ /* How often to not attempt to use elision if a transaction aborted due
++ to reasons other than other threads' memory accesses. Expressed in
++ number of lock acquisition attempts. */
++ .skip_lock_internal_abort = 3,
++ /* How often we retry using elision if there is chance for the transaction
++ to finish execution (e.g., it wasn't aborted due to the lock being
++ already acquired. */
++ .retry_try_xbegin = 3,
++ /* Same as SKIP_LOCK_INTERNAL_ABORT but for trylock. */
++ .skip_trylock_internal_abort = 3,
++ };
++
++/* Force elision for all new locks. This is used to decide whether existing
++ DEFAULT locks should be automatically upgraded to elision in
++ pthread_mutex_lock(). Disabled for suid programs. Only used when elision
++ is available. */
++
++int __pthread_force_elision attribute_hidden = 0;
++
++#if HAVE_TUNABLES
++static inline void
++__always_inline
++do_set_elision_enable (int32_t elision_enable)
++{
++ /* Enable elision if it's avaliable in hardware. It's not necessary to check
++ if __libc_enable_secure isn't enabled since elision_enable will be set
++ according to the default, which is disabled. */
++ if (elision_enable == 1)
++ __pthread_force_elision = HAS_CPU_FEATURE (RTM) ? 1 : 0;
++}
++
++/* The pthread->elision_enable tunable is 0 or 1 indicating that elision
++ should be disabled or enabled respectively. The feature will only be used
++ if it's supported by the hardware. */
++
++void
++TUNABLE_CALLBACK (set_elision_enable) (tunable_val_t *valp)
++{
++ int32_t elision_enable = (int32_t) valp->numval;
++ do_set_elision_enable (elision_enable);
++}
++
++#define TUNABLE_CALLBACK_FNDECL(__name, __type) \
++static inline void \
++__always_inline \
++do_set_elision_ ## __name (__type value) \
++{ \
++ __elision_aconf.__name = value; \
++} \
++void \
++TUNABLE_CALLBACK (set_elision_ ## __name) (tunable_val_t *valp) \
++{ \
++ __type value = (__type) (valp)->numval; \
++ do_set_elision_ ## __name (value); \
++}
++
++TUNABLE_CALLBACK_FNDECL (skip_lock_busy, int32_t);
++TUNABLE_CALLBACK_FNDECL (skip_lock_internal_abort, int32_t);
++TUNABLE_CALLBACK_FNDECL (retry_try_xbegin, int32_t);
++TUNABLE_CALLBACK_FNDECL (skip_trylock_internal_abort, int32_t);
++#endif
++
++/* Initialize elision. */
++
++static void
++elision_init (int argc __attribute__ ((unused)),
++ char **argv __attribute__ ((unused)),
++ char **environ)
++{
++#if HAVE_TUNABLES
++ /* Elision depends on tunables and must be explicitly turned on by setting
++ the appropriate tunable on a supported platform. */
++
++ TUNABLE_GET (enable, int32_t,
++ TUNABLE_CALLBACK (set_elision_enable));
++ TUNABLE_GET (skip_lock_busy, int32_t,
++ TUNABLE_CALLBACK (set_elision_skip_lock_busy));
++ TUNABLE_GET (skip_lock_internal_abort, int32_t,
++ TUNABLE_CALLBACK (set_elision_skip_lock_internal_abort));
++ TUNABLE_GET (tries, int32_t,
++ TUNABLE_CALLBACK (set_elision_retry_try_xbegin));
++ TUNABLE_GET (skip_trylock_internal_abort, int32_t,
++ TUNABLE_CALLBACK (set_elision_skip_trylock_internal_abort));
++#endif
++
++ if (!__pthread_force_elision)
++ __elision_aconf.retry_try_xbegin = 0; /* Disable elision on rwlocks. */
++}
++
++#ifdef SHARED
++# define INIT_SECTION ".init_array"
++#else
++# define INIT_SECTION ".preinit_array"
++#endif
++
++void (*const __pthread_init_array []) (int, char **, char **)
++ __attribute__ ((section (INIT_SECTION), aligned (sizeof (void *)))) =
++{
++ &elision_init
++};
+diff --git a/nptl_2_17/elision-lock_2_17.c b/nptl_2_17/elision-lock_2_17.c
+new file mode 100644
+index 00000000..e6dbbc21
+--- /dev/null
++++ b/nptl_2_17/elision-lock_2_17.c
+@@ -0,0 +1,107 @@
++/* elision-lock.c: Elided pthread mutex lock.
++ Copyright (C) 2011-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <pthread_2_17.h>
++#include "pthreadP_2_17.h"
++#include "lowlevellock.h"
++#include "hle_2_17.h"
++#include <elision-conf.h>
++
++#if !defined(LLL_LOCK) && !defined(EXTRAARG)
++/* Make sure the configuration code is always linked in for static
++ libraries. */
++#include "elision-conf_2_17.c"
++#endif
++
++#ifndef EXTRAARG
++#define EXTRAARG
++#endif
++#ifndef LLL_LOCK
++#define LLL_LOCK(a,b) lll_lock(a,b), 0
++#endif
++
++#define aconf __elision_aconf
++
++/* Adaptive lock using transactions.
++ By default the lock region is run as a transaction, and when it
++ aborts or the lock is busy the lock adapts itself. */
++
++int
++__lll_lock_elision (int *futex, short *adapt_count, EXTRAARG int private)
++{
++ /* adapt_count can be accessed concurrently; these accesses can be both
++ inside of transactions (if critical sections are nested and the outer
++ critical section uses lock elision) and outside of transactions. Thus,
++ we need to use atomic accesses to avoid data races. However, the
++ value of adapt_count is just a hint, so relaxed MO accesses are
++ sufficient. */
++ if (atomic_load_relaxed (adapt_count) <= 0)
++ {
++ unsigned status;
++ int try_xbegin;
++
++ for (try_xbegin = aconf.retry_try_xbegin;
++ try_xbegin > 0;
++ try_xbegin--)
++ {
++ if ((status = _xbegin()) == _XBEGIN_STARTED)
++ {
++ if (*futex == 0)
++ return 0;
++
++ /* Lock was busy. Fall back to normal locking.
++ Could also _xend here but xabort with 0xff code
++ is more visible in the profiler. */
++ _xabort (_ABORT_LOCK_BUSY);
++ }
++
++ if (!(status & _XABORT_RETRY))
++ {
++ if ((status & _XABORT_EXPLICIT)
++ && _XABORT_CODE (status) == _ABORT_LOCK_BUSY)
++ {
++ /* Right now we skip here. Better would be to wait a bit
++ and retry. This likely needs some spinning. See
++ above for why relaxed MO is sufficient. */
++ if (atomic_load_relaxed (adapt_count)
++ != aconf.skip_lock_busy)
++ atomic_store_relaxed (adapt_count, aconf.skip_lock_busy);
++ }
++ /* Internal abort. There is no chance for retry.
++ Use the normal locking and next time use lock.
++ Be careful to avoid writing to the lock. See above for why
++ relaxed MO is sufficient. */
++ else if (atomic_load_relaxed (adapt_count)
++ != aconf.skip_lock_internal_abort)
++ atomic_store_relaxed (adapt_count,
++ aconf.skip_lock_internal_abort);
++ break;
++ }
++ }
++ }
++ else
++ {
++ /* Use a normal lock until the threshold counter runs out.
++ Lost updates possible. */
++ atomic_store_relaxed (adapt_count,
++ atomic_load_relaxed (adapt_count) - 1);
++ }
++
++ /* Use a normal lock here. */
++ return LLL_LOCK ((*futex), private);
++}
+diff --git a/nptl_2_17/elision-timed_2_17.c b/nptl_2_17/elision-timed_2_17.c
+new file mode 100644
+index 00000000..5050f2d1
+--- /dev/null
++++ b/nptl_2_17/elision-timed_2_17.c
+@@ -0,0 +1,27 @@
++/* elision-timed.c: Lock elision timed lock.
++ Copyright (C) 2013-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <time.h>
++#include <elision-conf.h>
++#include "lowlevellock.h"
++#include <old_macros_2_17.h>
++#define __lll_lock_elision __lll_timedlock_elision
++#define EXTRAARG const struct timespec *t,
++#undef LLL_LOCK
++#define LLL_LOCK(a, b) lll_timedlock(a, t, b)
++#include "elision-lock_2_17.c"
+diff --git a/nptl_2_17/elision-trylock_2_17.c b/nptl_2_17/elision-trylock_2_17.c
+new file mode 100644
+index 00000000..70d8f8b9
+--- /dev/null
++++ b/nptl_2_17/elision-trylock_2_17.c
+@@ -0,0 +1,75 @@
++/* elision-trylock.c: Lock eliding trylock for pthreads.
++ Copyright (C) 2013-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <pthread_2_17.h>
++
++#include <lowlevellock.h>
++#include "hle_2_17.h"
++#include <elision-conf.h>
++
++#define aconf __elision_aconf
++
++/* Try to elide a futex trylock. FUTEX is the futex variable. ADAPT_COUNT is
++ the adaptation counter in the mutex. */
++
++int
++__lll_trylock_elision (int *futex, short *adapt_count)
++{
++ /* Implement POSIX semantics by forbiding nesting
++ trylock. Sorry. After the abort the code is re-executed
++ non transactional and if the lock was already locked
++ return an error. */
++ _xabort (_ABORT_NESTED_TRYLOCK);
++
++ /* Only try a transaction if it's worth it. See __lll_lock_elision for
++ why we need atomic accesses. Relaxed MO is sufficient because this is
++ just a hint. */
++ if (atomic_load_relaxed (adapt_count) <= 0)
++ {
++ unsigned status;
++
++ if ((status = _xbegin()) == _XBEGIN_STARTED)
++ {
++ if (*futex == 0)
++ return 0;
++
++ /* Lock was busy. Fall back to normal locking.
++ Could also _xend here but xabort with 0xff code
++ is more visible in the profiler. */
++ _xabort (_ABORT_LOCK_BUSY);
++ }
++
++ if (!(status & _XABORT_RETRY))
++ {
++ /* Internal abort. No chance for retry. For future
++ locks don't try speculation for some time. See above for MO. */
++ if (atomic_load_relaxed (adapt_count)
++ != aconf.skip_lock_internal_abort)
++ atomic_store_relaxed (adapt_count, aconf.skip_lock_internal_abort);
++ }
++ /* Could do some retries here. */
++ }
++ else
++ {
++ /* Lost updates are possible but harmless (see above). */
++ atomic_store_relaxed (adapt_count,
++ atomic_load_relaxed (adapt_count) - 1);
++ }
++
++ return lll_trylock (*futex);
++}
+diff --git a/nptl_2_17/elision-unlock_2_17.c b/nptl_2_17/elision-unlock_2_17.c
+new file mode 100644
+index 00000000..b5d38c5f
+--- /dev/null
++++ b/nptl_2_17/elision-unlock_2_17.c
+@@ -0,0 +1,34 @@
++/* elision-unlock.c: Commit an elided pthread lock.
++ Copyright (C) 2013-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include "lowlevellock.h"
++#include "hle_2_17.h"
++#include <old_macros_2_17.h>
++
++int
++__lll_unlock_elision(int *lock, int private)
++{
++ /* When the lock was free we're in a transaction.
++ When you crash here you unlocked a free lock. */
++ if (*lock == 0)
++ _xend();
++ else
++ lll_unlock ((*lock), private);
++ return 0;
++}
+diff --git a/nptl_2_17/hle_2_17.h b/nptl_2_17/hle_2_17.h
+new file mode 100644
+index 00000000..4a7b9e3b
+--- /dev/null
++++ b/nptl_2_17/hle_2_17.h
+@@ -0,0 +1,75 @@
++/* Shared RTM header. Emulate TSX intrinsics for compilers and assemblers
++ that do not support the intrinsics and instructions yet. */
++#ifndef _HLE_H
++#define _HLE_H 1
++
++#ifdef __ASSEMBLER__
++
++.macro XBEGIN target
++ .byte 0xc7,0xf8
++ .long \target-1f
++1:
++.endm
++
++.macro XEND
++ .byte 0x0f,0x01,0xd5
++.endm
++
++.macro XABORT code
++ .byte 0xc6,0xf8,\code
++.endm
++
++.macro XTEST
++ .byte 0x0f,0x01,0xd6
++.endm
++
++#endif
++
++/* Official RTM intrinsics interface matching gcc/icc, but works
++ on older gcc compatible compilers and binutils.
++ We should somehow detect if the compiler supports it, because
++ it may be able to generate slightly better code. */
++
++#define _XBEGIN_STARTED (~0u)
++#define _XABORT_EXPLICIT (1 << 0)
++#define _XABORT_RETRY (1 << 1)
++#define _XABORT_CONFLICT (1 << 2)
++#define _XABORT_CAPACITY (1 << 3)
++#define _XABORT_DEBUG (1 << 4)
++#define _XABORT_NESTED (1 << 5)
++#define _XABORT_CODE(x) (((x) >> 24) & 0xff)
++
++#define _ABORT_LOCK_BUSY 0xff
++#define _ABORT_LOCK_IS_LOCKED 0xfe
++#define _ABORT_NESTED_TRYLOCK 0xfd
++
++#ifndef __ASSEMBLER__
++
++#define __force_inline __attribute__((__always_inline__)) inline
++
++static __force_inline int _xbegin(void)
++{
++ int ret = _XBEGIN_STARTED;
++ asm volatile (".byte 0xc7,0xf8 ; .long 0" : "+a" (ret) :: "memory");
++ return ret;
++}
++
++static __force_inline void _xend(void)
++{
++ asm volatile (".byte 0x0f,0x01,0xd5" ::: "memory");
++}
++
++static __force_inline void _xabort(const unsigned int status)
++{
++ asm volatile (".byte 0xc6,0xf8,%P0" :: "i" (status) : "memory");
++}
++
++static __force_inline int _xtest(void)
++{
++ unsigned char out;
++ asm volatile (".byte 0x0f,0x01,0xd6 ; setnz %0" : "=r" (out) :: "memory");
++ return out;
++}
++
++#endif
++#endif
+--
+2.30.0
+
diff --git a/0007-add-lowlevellock_2_17_c.patch b/0007-add-lowlevellock_2_17_c.patch
new file mode 100644
index 0000000..b516e77
--- /dev/null
+++ b/0007-add-lowlevellock_2_17_c.patch
@@ -0,0 +1,68 @@
+From 3df6f22e5fde470a6e0242e582e58919493bdd54 Mon Sep 17 00:00:00 2001
+From: Roland McGrath <roland@hack.frob.com>
+Date: Tue, 15 Jul 2014 15:23:06 -0700
+Subject: [PATCH 7/9] build extra lipthreadcond so
+
+since 78fe624d44b8f6489b2d0de9bfdc09290a719a7, lowlevellock.c depends futex-internal.h which uses the private symbol __GI___libc_fatal of glibc.
+We can't reference it in libpthread-2.17.so. Therefore, recompile in libphtread-2.17.so
+
+---
+ nptl_2_17/lowlevellock_2_17.c | 46 ++++++++++++++++++++++
+ 2 files changed, 46 insertions(+)
+ create mode 100644 nptl_2_17/lowlevellock_2_17.c
+
+diff --git a/nptl_2_17/lowlevellock_2_17.c b/nptl_2_17/lowlevellock_2_17.c
+new file mode 100644
+index 00000000..bf1ca6b9
+--- /dev/null
++++ b/nptl_2_17/lowlevellock_2_17.c
+@@ -0,0 +1,46 @@
++/* low level locking for pthread library. Generic futex-using version.
++ Copyright (C) 2003-2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Paul Mackerras <paulus@au.ibm.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <sysdep.h>
++#include <lowlevellock.h>
++#include <sys/time.h>
++#include <atomic.h>
++
++void
++__lll_lock_wait_private (int *futex)
++{
++ if (*futex == 2)
++ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */
++
++ while (atomic_exchange_acq (futex, 2) != 0)
++ lll_futex_wait (futex, 2, LLL_PRIVATE); /* Wait if *futex == 2. */
++}
++
++
++/* This function doesn't get included in libc. */
++void
++__lll_lock_wait (int *futex, int private)
++{
++ if (*futex == 2)
++ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
++
++ while (atomic_exchange_acq (futex, 2) != 0)
++ lll_futex_wait (futex, 2, private); /* Wait if *futex == 2. */
++}
+--
+2.30.0
+
diff --git a/0008-add-pause_nocancel_2_17.patch b/0008-add-pause_nocancel_2_17.patch
new file mode 100644
index 0000000..8d7ec88
--- /dev/null
+++ b/0008-add-pause_nocancel_2_17.patch
@@ -0,0 +1,56 @@
+From 329ea513b451ae8322aa7a24ed84da13992af2dd Mon Sep 17 00:00:00 2001
+From: Zack Weinberg <zackw@panix.com>
+Date: Tue, 3 Apr 2018 18:26:44 -0400
+Subject: [PATCH 8/9] build extra lipthreadcond so
+
+since bb4a3143724ef3f044a4f05351fe041300ee382, Remove pause and nanosleep not cancel wrappers
+To build libtphread-2.17.so, we added it back.
+
+---
+ nptl_2_17/pause_nocancel_2_17.c | 34 +++++++++++++++++++++++++++++++++
+ 1 file changed, 34 insertions(+)
+ create mode 100644 nptl_2_17/pause_nocancel_2_17.c
+
+diff --git a/nptl_2_17/pause_nocancel_2_17.c b/nptl_2_17/pause_nocancel_2_17.c
+new file mode 100644
+index 00000000..ab8e78d2
+--- /dev/null
++++ b/nptl_2_17/pause_nocancel_2_17.c
+@@ -0,0 +1,34 @@
++/* Linux pause syscall implementation -- non-cancellable.
++ Copyright (C) 2018 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <compat_pthread_2_17.h>
++#include <signal.h>
++#include <unistd.h>
++#include <sysdep-cancel.h>
++#include <not-cancel.h>
++
++int
++__pause_nocancel (void)
++{
++#ifdef __NR_pause
++ return INLINE_SYSCALL_CALL (pause);
++#else
++ return INLINE_SYSCALL_CALL (ppoll, NULL, 0, NULL, NULL);
++#endif
++}
++hidden_def (__pause_nocancel)
+--
+2.30.0
+
diff --git a/0009-add-unwind-with-longjmp.patch b/0009-add-unwind-with-longjmp.patch
new file mode 100644
index 0000000..cfe1ecb
--- /dev/null
+++ b/0009-add-unwind-with-longjmp.patch
@@ -0,0 +1,161 @@
+From 09d65ff393e9183eecba1e5cb877e95dbdd3d4a4 Mon Sep 17 00:00:00 2001
+From: Ulrich Drepper <drepper@redhat.com>
+Date: Sat, 12 Apr 2003 00:58:26 +0000
+Subject: [PATCH 9/9] build extra lipthreadcond so
+
+since 6253bacdc00de132dec452ff7c6ce3ba7fa23d81, __libc_longjmp became a
+private interface.We can't quote directly.
+Change it to longjmp
+
+---
+ nptl_2_17/unwind_2_17.c | 138 ++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 138 insertions(+)
+ create mode 100644 nptl_2_17/unwind_2_17.c
+
+diff --git a/nptl_2_17/unwind_2_17.c b/nptl_2_17/unwind_2_17.c
+new file mode 100644
+index 00000000..ada8f74d
+--- /dev/null
++++ b/nptl_2_17/unwind_2_17.c
+@@ -0,0 +1,138 @@
++/* Copyright (C) 2003-2016 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++ Contributed by Ulrich Drepper <drepper@redhat.com>
++ and Richard Henderson <rth@redhat.com>, 2003.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include "pthreadP_2_17.h"
++#include <setjmp.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <jmpbuf-unwind.h>
++
++#ifdef _STACK_GROWS_DOWN
++# define FRAME_LEFT(frame, other, adj) \
++ ((uintptr_t) frame - adj >= (uintptr_t) other - adj)
++#elif _STACK_GROWS_UP
++# define FRAME_LEFT(frame, other, adj) \
++ ((uintptr_t) frame - adj <= (uintptr_t) other - adj)
++#else
++# error "Define either _STACK_GROWS_DOWN or _STACK_GROWS_UP"
++#endif
++
++static _Unwind_Reason_Code
++unwind_stop (int version, _Unwind_Action actions,
++ _Unwind_Exception_Class exc_class,
++ struct _Unwind_Exception *exc_obj,
++ struct _Unwind_Context *context, void *stop_parameter)
++{
++ struct pthread_unwind_buf *buf = stop_parameter;
++ struct pthread *self = THREAD_SELF;
++ struct _pthread_cleanup_buffer *curp = THREAD_GETMEM (self, cleanup);
++ int do_longjump = 0;
++
++ /* Adjust all pointers used in comparisons, so that top of thread's
++ stack is at the top of address space. Without that, things break
++ if stack is allocated above the main stack. */
++ uintptr_t adj = (uintptr_t) self->stackblock + self->stackblock_size;
++
++ /* Do longjmp if we're at "end of stack", aka "end of unwind data".
++ We assume there are only C frame without unwind data in between
++ here and the jmp_buf target. Otherwise simply note that the CFA
++ of a function is NOT within it's stack frame; it's the SP of the
++ previous frame. */
++ if ((actions & _UA_END_OF_STACK)
++ || ! _JMPBUF_CFA_UNWINDS_ADJ (buf->cancel_jmp_buf[0].jmp_buf, context,
++ adj))
++ do_longjump = 1;
++
++ if (__glibc_unlikely (curp != NULL))
++ {
++ /* Handle the compatibility stuff. Execute all handlers
++ registered with the old method which would be unwound by this
++ step. */
++ struct _pthread_cleanup_buffer *oldp = buf->priv.data.cleanup;
++ void *cfa = (void *) (_Unwind_Ptr) _Unwind_GetCFA (context);
++
++ if (curp != oldp && (do_longjump || FRAME_LEFT (cfa, curp, adj)))
++ {
++ do
++ {
++ /* Pointer to the next element. */
++ struct _pthread_cleanup_buffer *nextp = curp->__prev;
++
++ /* Call the handler. */
++ curp->__routine (curp->__arg);
++
++ /* To the next. */
++ curp = nextp;
++ }
++ while (curp != oldp
++ && (do_longjump || FRAME_LEFT (cfa, curp, adj)));
++
++ /* Mark the current element as handled. */
++ THREAD_SETMEM (self, cleanup, curp);
++ }
++ }
++
++ if (do_longjump)
++ longjmp ((struct __jmp_buf_tag *) buf->cancel_jmp_buf, 1);
++
++ return _URC_NO_REASON;
++}
++
++
++static void
++unwind_cleanup (_Unwind_Reason_Code reason, struct _Unwind_Exception *exc)
++{
++ /* When we get here a C++ catch block didn't rethrow the object. We
++ cannot handle this case and therefore abort. */
++ __libc_fatal ("FATAL: exception not rethrown\n");
++}
++
++
++void
++__cleanup_fct_attribute __attribute ((noreturn))
++__pthread_unwind (__pthread_unwind_buf_t *buf)
++{
++ struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
++ struct pthread *self = THREAD_SELF;
++
++ /* This is not a catchable exception, so don't provide any details about
++ the exception type. We do need to initialize the field though. */
++ THREAD_SETMEM (self, exc.exception_class, 0);
++ THREAD_SETMEM (self, exc.exception_cleanup, &unwind_cleanup);
++
++ _Unwind_ForcedUnwind (&self->exc, unwind_stop, ibuf);
++ /* NOTREACHED */
++
++ /* We better do not get here. */
++ abort ();
++}
++hidden_def (__pthread_unwind)
++
++
++void
++__cleanup_fct_attribute __attribute ((noreturn))
++__pthread_unwind_next (__pthread_unwind_buf_t *buf)
++{
++ struct pthread_unwind_buf *ibuf = (struct pthread_unwind_buf *) buf;
++
++ __pthread_unwind ((__pthread_unwind_buf_t *) ibuf->priv.data.prev);
++}
++hidden_def (__pthread_unwind_next)
+--
+2.30.0
+
diff --git a/0009_nptl_2.17_adapt_for_bug_29029.patch b/0009_nptl_2.17_adapt_for_bug_29029.patch
new file mode 100644
index 0000000..d028f92
--- /dev/null
+++ b/0009_nptl_2.17_adapt_for_bug_29029.patch
@@ -0,0 +1,248 @@
+From ffdf4f3f121f35834131396c52049745cca21a22 Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Mon, 18 Apr 2022 11:10:46 +0800
+Subject: [PATCH] nptl 2.17 adapt for bug 29029
+
+upstream bug 29029 has revert some struct and function,
+this commit is to adapt the change.
+
+---
+ nptl_2_17/cancellation.c | 91 +++++++++++++++++++++++++++++++++
+ nptl_2_17/cancellation_2_17.c | 60 ++++++++++++++++------
+ nptl_2_17/compat_pthread_2_17.h | 21 --------
+ 3 files changed, 136 insertions(+), 36 deletions(-)
+ create mode 100644 nptl_2_17/cancellation.c
+
+diff --git a/nptl_2_17/cancellation.c b/nptl_2_17/cancellation.c
+new file mode 100644
+index 00000000..f4b08902
+--- /dev/null
++++ b/nptl_2_17/cancellation.c
+@@ -0,0 +1,91 @@
++/* Copyright (C) 2002-2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <setjmp.h>
++#include <stdlib.h>
++#include "pthreadP.h"
++#include <futex-internal.h>
++
++
++/* The next two functions are similar to pthread_setcanceltype() but
++ more specialized for the use in the cancelable functions like write().
++ They do not need to check parameters etc. These functions must be
++ AS-safe, with the exception of the actual cancellation, because they
++ are called by wrappers around AS-safe functions like write().*/
++int
++__pthread_enable_asynccancel (void)
++{
++ struct pthread *self = THREAD_SELF;
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
++
++ while (1)
++ {
++ int newval = oldval | CANCELTYPE_BITMASK;
++
++ if (newval == oldval)
++ break;
++
++ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval))
++ {
++ if (cancel_enabled_and_canceled_and_async (newval))
++ {
++ self->result = PTHREAD_CANCELED;
++ __do_cancel ();
++ }
++
++ break;
++ }
++ }
++
++ return oldval;
++}
++libc_hidden_def (__pthread_enable_asynccancel)
++
++/* See the comment for __pthread_enable_asynccancel regarding
++ the AS-safety of this function. */
++void
++__pthread_disable_asynccancel (int oldtype)
++{
++ /* If asynchronous cancellation was enabled before we do not have
++ anything to do. */
++ if (oldtype & CANCELTYPE_BITMASK)
++ return;
++
++ struct pthread *self = THREAD_SELF;
++ int newval;
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
++ do
++ {
++ newval = oldval & ~CANCELTYPE_BITMASK;
++ }
++ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval));
++
++ /* We cannot return when we are being canceled. Upon return the
++ thread might be things which would have to be undone. The
++ following loop should loop until the cancellation signal is
++ delivered. */
++ while (__glibc_unlikely ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
++ == CANCELING_BITMASK))
++ {
++ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
++ FUTEX_PRIVATE);
++ newval = atomic_load_relaxed (&self->cancelhandling);
++ }
++}
++libc_hidden_def (__pthread_disable_asynccancel)
+diff --git a/nptl_2_17/cancellation_2_17.c b/nptl_2_17/cancellation_2_17.c
+index 5c9ce572..9bc199e7 100644
+--- a/nptl_2_17/cancellation_2_17.c
++++ b/nptl_2_17/cancellation_2_17.c
+@@ -1,6 +1,5 @@
+-/* Copyright (C) 2002-2018 Free Software Foundation, Inc.
++/* Copyright (C) 2002-2022 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+- Contributed by Ulrich Drepper <drepper@redhat.com>, 2002.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+@@ -14,30 +13,42 @@
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+- <http://www.gnu.org/licenses/>. */
++ <https://www.gnu.org/licenses/>. */
+
+ #include "pthreadP_2_17.h"
+ #include <setjmp.h>
+ #include <stdlib.h>
+ #include <futex-internal.h>
+
++/* The next two functions are similar to pthread_setcanceltype() but
++ more specialized for the use in the cancelable functions like write().
++ They do not need to check parameters etc. These functions must be
++ AS-safe, with the exception of the actual cancellation, because they
++ are called by wrappers around AS-safe functions like write().*/
+ int
+ __pthread_enable_asynccancel (void)
+ {
+ struct pthread *self = THREAD_SELF;
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
+
+- int oldval = THREAD_GETMEM (self, canceltype);
+- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS);
++ while (1)
++ {
++ int newval = oldval | CANCELTYPE_BITMASK;
+
+- int ch = THREAD_GETMEM (self, cancelhandling);
++ if (newval == oldval)
++ break;
+
+- if (self->cancelstate == PTHREAD_CANCEL_ENABLE
+- && (ch & CANCELED_BITMASK)
+- && !(ch & EXITING_BITMASK)
+- && !(ch & TERMINATED_BITMASK))
+- {
+- THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+- __do_cancel ();
++ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval))
++ {
++ if (cancel_enabled_and_canceled_and_async (newval))
++ {
++ self->result = PTHREAD_CANCELED;
++ __do_cancel ();
++ }
++
++ break;
++ }
+ }
+
+ return oldval;
+@@ -51,10 +62,29 @@ __pthread_disable_asynccancel (int oldtype)
+ {
+ /* If asynchronous cancellation was enabled before we do not have
+ anything to do. */
+- if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS)
++ if (oldtype & CANCELTYPE_BITMASK)
+ return;
+
+ struct pthread *self = THREAD_SELF;
+- self->canceltype = PTHREAD_CANCEL_DEFERRED;
++ int newval;
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
++ do
++ {
++ newval = oldval & ~CANCELTYPE_BITMASK;
++ }
++ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval));
++
++ /* We cannot return when we are being canceled. Upon return the
++ thread might be things which would have to be undone. The
++ following loop should loop until the cancellation signal is
++ delivered. */
++ while (__glibc_unlikely ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
++ == CANCELING_BITMASK))
++ {
++ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
++ FUTEX_PRIVATE);
++ newval = atomic_load_relaxed (&self->cancelhandling);
++ }
+ }
+ libc_hidden_def (__pthread_disable_asynccancel)
+diff --git a/nptl_2_17/compat_pthread_2_17.h b/nptl_2_17/compat_pthread_2_17.h
+index d13051ba..5109ebc3 100644
+--- a/nptl_2_17/compat_pthread_2_17.h
++++ b/nptl_2_17/compat_pthread_2_17.h
+@@ -19,30 +19,9 @@
+ #define __PTHREAD_MUTEX_USE_UNION 0
+ #endif
+
+-#define CANCELSTATE_BIT 0
+-#define CANCELSTATE_BITMASK (0x01 << CANCELSTATE_BIT)
+- /* Bit set if asynchronous cancellation mode is selected. */
+-#define CANCELTYPE_BIT 1
+-#define CANCELTYPE_BITMASK (0x01 << CANCELTYPE_BIT)
+- /* Bit set if canceling has been initiated. */
+-#define CANCELING_BIT 2
+-#define CANCELING_BITMASK (0x01 << CANCELING_BIT)
+- /* Bit set if canceled. */
+-#define CANCELED_BIT 3
+-#define CANCELED_BITMASK (0x01 << CANCELED_BIT)
+- /* Bit set if thread is exiting. */
+-#define EXITING_BIT 4
+-#define EXITING_BITMASK (0x01 << EXITING_BIT)
+- /* Bit set if thread terminated and TCB is freed. */
+-#define TERMINATED_BIT 5
+-#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT)
+- /* Bit set if thread is supposed to change XID. */
+-#define SETXID_BIT 6
+-#define SETXID_BITMASK (0x01 << SETXID_BIT)
+ /* Mask for the rest. Helps the compiler to optimize. */
+ #define CANCEL_RESTMASK 0xffffff80
+
+-
+ #define CANCEL_ENABLED_AND_CANCELED_AND_ASYNCHRONOUS(value) \
+ (((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK \
+ | EXITING_BITMASK | CANCEL_RESTMASK | TERMINATED_BITMASK)) \
+--
+2.33.0
+
diff --git a/1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch b/1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch
new file mode 100644
index 0000000..2db0045
--- /dev/null
+++ b/1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch
@@ -0,0 +1,136 @@
+From 07b427296b8d59f439144029d9a948f6c1ce0a31 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:30:27 +0100
+Subject: [PATCH] [1/5] AArch64: Improve A64FX memset for small sizes
+
+Improve performance of small memsets by reducing instruction counts and
+improving code alignment. Bench-memset shows 35-45% performance gain for
+small sizes.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 96 ++++++++++++--------------------
+ 1 file changed, 36 insertions(+), 60 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index ce54e54..cf3d402 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -51,78 +51,54 @@
+ .endm
+
+ .macro st1b_unroll first=0, last=7
+- st1b z0.b, p0, [dst, #\first, mul vl]
++ st1b z0.b, p0, [dst, \first, mul vl]
+ .if \last-\first
+ st1b_unroll "(\first+1)", \last
+ .endif
+ .endm
+
+- .macro shortcut_for_small_size exit
+- // if rest <= vector_length * 2
+- whilelo p0.b, xzr, count
+- whilelo p1.b, vector_length, count
+- b.last 1f
+- st1b z0.b, p0, [dstin, #0, mul vl]
+- st1b z0.b, p1, [dstin, #1, mul vl]
+- ret
+-1: // if rest > vector_length * 8
+- cmp count, vector_length, lsl 3 // vector_length * 8
+- b.hi \exit
+- // if rest <= vector_length * 4
+- lsl tmp1, vector_length, 1 // vector_length * 2
+- whilelo p2.b, tmp1, count
+- incb tmp1
+- whilelo p3.b, tmp1, count
+- b.last 1f
+- st1b z0.b, p0, [dstin, #0, mul vl]
+- st1b z0.b, p1, [dstin, #1, mul vl]
+- st1b z0.b, p2, [dstin, #2, mul vl]
+- st1b z0.b, p3, [dstin, #3, mul vl]
+- ret
+-1: // if rest <= vector_length * 8
+- lsl tmp1, vector_length, 2 // vector_length * 4
+- whilelo p4.b, tmp1, count
+- incb tmp1
+- whilelo p5.b, tmp1, count
+- b.last 1f
+- st1b z0.b, p0, [dstin, #0, mul vl]
+- st1b z0.b, p1, [dstin, #1, mul vl]
+- st1b z0.b, p2, [dstin, #2, mul vl]
+- st1b z0.b, p3, [dstin, #3, mul vl]
+- st1b z0.b, p4, [dstin, #4, mul vl]
+- st1b z0.b, p5, [dstin, #5, mul vl]
+- ret
+-1: lsl tmp1, vector_length, 2 // vector_length * 4
+- incb tmp1 // vector_length * 5
+- incb tmp1 // vector_length * 6
+- whilelo p6.b, tmp1, count
+- incb tmp1
+- whilelo p7.b, tmp1, count
+- st1b z0.b, p0, [dstin, #0, mul vl]
+- st1b z0.b, p1, [dstin, #1, mul vl]
+- st1b z0.b, p2, [dstin, #2, mul vl]
+- st1b z0.b, p3, [dstin, #3, mul vl]
+- st1b z0.b, p4, [dstin, #4, mul vl]
+- st1b z0.b, p5, [dstin, #5, mul vl]
+- st1b z0.b, p6, [dstin, #6, mul vl]
+- st1b z0.b, p7, [dstin, #7, mul vl]
+- ret
+- .endm
+
+-ENTRY (MEMSET)
++#undef BTI_C
++#define BTI_C
+
++ENTRY (MEMSET)
+ PTR_ARG (0)
+ SIZE_ARG (2)
+
+- cbnz count, 1f
+- ret
+-1: dup z0.b, valw
+ cntb vector_length
+- // shortcut for less than vector_length * 8
+- // gives a free ptrue to p0.b for n >= vector_length
+- shortcut_for_small_size L(vl_agnostic)
+- // end of shortcut
++ dup z0.b, valw
++ whilelo p0.b, vector_length, count
++ b.last 1f
++ whilelo p1.b, xzr, count
++ st1b z0.b, p1, [dstin, 0, mul vl]
++ st1b z0.b, p0, [dstin, 1, mul vl]
++ ret
++
++ // count >= vector_length * 2
++1: cmp count, vector_length, lsl 2
++ add dstend, dstin, count
++ b.hi 1f
++ st1b z0.b, p0, [dstin, 0, mul vl]
++ st1b z0.b, p0, [dstin, 1, mul vl]
++ st1b z0.b, p0, [dstend, -2, mul vl]
++ st1b z0.b, p0, [dstend, -1, mul vl]
++ ret
++
++ // count > vector_length * 4
++1: lsl tmp1, vector_length, 3
++ cmp count, tmp1
++ b.hi L(vl_agnostic)
++ st1b z0.b, p0, [dstin, 0, mul vl]
++ st1b z0.b, p0, [dstin, 1, mul vl]
++ st1b z0.b, p0, [dstin, 2, mul vl]
++ st1b z0.b, p0, [dstin, 3, mul vl]
++ st1b z0.b, p0, [dstend, -4, mul vl]
++ st1b z0.b, p0, [dstend, -3, mul vl]
++ st1b z0.b, p0, [dstend, -2, mul vl]
++ st1b z0.b, p0, [dstend, -1, mul vl]
++ ret
+
++ .p2align 4
+ L(vl_agnostic): // VL Agnostic
+ mov rest, count
+ mov dst, dstin
+--
+1.8.3.1
+
diff --git a/1_6-LoongArch-Optimize-string-functions-memcpy-memmove.patch b/1_6-LoongArch-Optimize-string-functions-memcpy-memmove.patch
new file mode 100644
index 0000000..5413394
--- /dev/null
+++ b/1_6-LoongArch-Optimize-string-functions-memcpy-memmove.patch
@@ -0,0 +1,693 @@
+From 939b5ed88b61d03bae6d20bf97ad0f77f9b110bb Mon Sep 17 00:00:00 2001
+From: Xue Liu <liuxue@loongson.cn>
+Date: Sun, 29 Jan 2023 10:20:26 +0800
+Subject: [PATCH 1/6] LoongArch: Optimize string functions memcpy, memmove.
+
+Change-Id: Ib0e78d062082a657d5bf572403f19bf5bfe0a28d
+---
+ sysdeps/loongarch/lp64/memcpy.S | 259 ++++++++++++++++++++
+ sysdeps/loongarch/lp64/memmove.S | 406 +++++++++++++++++++++++++++++++
+ 2 files changed, 665 insertions(+)
+ create mode 100644 sysdeps/loongarch/lp64/memcpy.S
+ create mode 100644 sysdeps/loongarch/lp64/memmove.S
+
+diff --git a/sysdeps/loongarch/lp64/memcpy.S b/sysdeps/loongarch/lp64/memcpy.S
+new file mode 100644
+index 00000000..5d850123
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/memcpy.S
+@@ -0,0 +1,259 @@
++/* Optimized memcpy implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++/* Allow the routine to be named something else if desired. */
++#ifndef MEMCPY_NAME
++#define MEMCPY_NAME memcpy
++#endif
++
++#define LD_64(reg, n) \
++ ld.d t0, reg, n; \
++ ld.d t1, reg, n+8; \
++ ld.d t2, reg, n+16; \
++ ld.d t3, reg, n+24; \
++ ld.d t4, reg, n+32; \
++ ld.d t5, reg, n+40; \
++ ld.d t6, reg, n+48; \
++ ld.d t7, reg, n+56;
++
++#define ST_64(reg, n) \
++ st.d t0, reg, n; \
++ st.d t1, reg, n+8; \
++ st.d t2, reg, n+16; \
++ st.d t3, reg, n+24; \
++ st.d t4, reg, n+32; \
++ st.d t5, reg, n+40; \
++ st.d t6, reg, n+48; \
++ st.d t7, reg, n+56;
++
++LEAF(MEMCPY_NAME)
++//1st var: dst ptr: void *a1 $r4 a0
++//2nd var: src ptr: void *a2 $r5 a1
++//3rd var: size_t len $r6 a2
++//t0~t9 registers as temp
++
++ add.d a4, a1, a2
++ add.d a3, a0, a2
++ li.w a6, 16
++ bge a6, a2, less_16bytes
++ li.w a6, 128
++ blt a6, a2, long_bytes
++ li.w a6, 64
++ blt a6, a2, more_64bytes
++ li.w a6, 32
++ blt a6, a2, more_32bytes
++
++ /* 17...32 */
++ ld.d t0, a1, 0
++ ld.d t1, a1, 8
++ ld.d t2, a4, -16
++ ld.d t3, a4, -8
++ st.d t0, a0, 0
++ st.d t1, a0, 8
++ st.d t2, a3, -16
++ st.d t3, a3, -8
++ jr ra
++
++more_64bytes:
++ srli.d t8, a0, 3
++ slli.d t8, t8, 3
++ addi.d t8, t8, 0x8
++ sub.d a7, a0, t8
++ ld.d t0, a1, 0
++ sub.d a1, a1, a7
++ st.d t0, a0, 0
++
++ add.d a7, a7, a2
++ addi.d a7, a7, -0x20
++loop_32:
++ ld.d t0, a1, 0
++ ld.d t1, a1, 8
++ ld.d t2, a1, 16
++ ld.d t3, a1, 24
++ st.d t0, t8, 0
++ st.d t1, t8, 8
++ st.d t2, t8, 16
++ st.d t3, t8, 24
++
++ addi.d t8, t8, 0x20
++ addi.d a1, a1, 0x20
++ addi.d a7, a7, -0x20
++ blt zero, a7, loop_32
++
++ ld.d t4, a4, -32
++ ld.d t5, a4, -24
++ ld.d t6, a4, -16
++ ld.d t7, a4, -8
++ st.d t4, a3, -32
++ st.d t5, a3, -24
++ st.d t6, a3, -16
++ st.d t7, a3, -8
++
++ jr ra
++
++more_32bytes:
++ /* 33...64 */
++ ld.d t0, a1, 0
++ ld.d t1, a1, 8
++ ld.d t2, a1, 16
++ ld.d t3, a1, 24
++ ld.d t4, a4, -32
++ ld.d t5, a4, -24
++ ld.d t6, a4, -16
++ ld.d t7, a4, -8
++ st.d t0, a0, 0
++ st.d t1, a0, 8
++ st.d t2, a0, 16
++ st.d t3, a0, 24
++ st.d t4, a3, -32
++ st.d t5, a3, -24
++ st.d t6, a3, -16
++ st.d t7, a3, -8
++ jr ra
++
++less_16bytes:
++ srai.d a6, a2, 3
++ beqz a6, less_8bytes
++
++ /* 8...16 */
++ ld.d t0, a1, 0
++ ld.d t1, a4, -8
++ st.d t0, a0, 0
++ st.d t1, a3, -8
++
++ jr ra
++
++less_8bytes:
++ srai.d a6, a2, 2
++ beqz a6, less_4bytes
++
++ /* 4...7 */
++ ld.w t0, a1, 0
++ ld.w t1, a4, -4
++ st.w t0, a0, 0
++ st.w t1, a3, -4
++ jr ra
++
++less_4bytes:
++ srai.d a6, a2, 1
++ beqz a6, less_2bytes
++
++ /* 2...3 */
++ ld.h t0, a1, 0
++ ld.h t1, a4, -2
++ st.h t0, a0, 0
++ st.h t1, a3, -2
++ jr ra
++
++less_2bytes:
++ beqz a2, less_1bytes
++
++ ld.b t0, a1, 0
++ st.b t0, a0, 0
++ jr ra
++
++less_1bytes:
++ jr ra
++
++long_bytes:
++ srli.d t8, a0, 3
++ slli.d t8, t8, 3
++ beq a0, t8, start
++
++ ld.d t0, a1, 0
++ addi.d t8, t8, 0x8
++ st.d t0, a0, 0
++ sub.d a7, a0, t8
++ sub.d a1, a1, a7
++
++start:
++ addi.d a5, a3, -0x80
++ blt a5, t8, align_end_proc
++
++loop_128:
++ LD_64(a1, 0)
++ ST_64(t8, 0)
++ LD_64(a1, 64)
++ addi.d a1, a1, 0x80
++ ST_64(t8, 64)
++ addi.d t8, t8, 0x80
++ bge a5, t8, loop_128
++
++align_end_proc:
++ sub.d a2, a3, t8
++
++ pcaddi t1, 34
++ andi t2, a2, 0x78
++ sub.d t1, t1, t2
++ jirl zero, t1, 0
++
++end_120_128_unalign:
++ ld.d t0, a1, 112
++ st.d t0, t8, 112
++end_112_120_unalign:
++ ld.d t0, a1, 104
++ st.d t0, t8, 104
++end_104_112_unalign:
++ ld.d t0, a1, 96
++ st.d t0, t8, 96
++end_96_104_unalign:
++ ld.d t0, a1, 88
++ st.d t0, t8, 88
++end_88_96_unalign:
++ ld.d t0, a1, 80
++ st.d t0, t8, 80
++end_80_88_unalign:
++ ld.d t0, a1, 72
++ st.d t0, t8, 72
++end_72_80_unalign:
++ ld.d t0, a1, 64
++ st.d t0, t8, 64
++end_64_72_unalign:
++ ld.d t0, a1, 56
++ st.d t0, t8, 56
++end_56_64_unalign:
++ ld.d t0, a1, 48
++ st.d t0, t8, 48
++end_48_56_unalign:
++ ld.d t0, a1, 40
++ st.d t0, t8, 40
++end_40_48_unalign:
++ ld.d t0, a1, 32
++ st.d t0, t8, 32
++end_32_40_unalign:
++ ld.d t0, a1, 24
++ st.d t0, t8, 24
++end_24_32_unalign:
++ ld.d t0, a1, 16
++ st.d t0, t8, 16
++end_16_24_unalign:
++ ld.d t0, a1, 8
++ st.d t0, t8, 8
++end_8_16_unalign:
++ ld.d t0, a1, 0
++ st.d t0, t8, 0
++end_0_8_unalign:
++ ld.d t0, a4, -8
++ st.d t0, a3, -8
++
++ jr ra
++
++END(MEMCPY_NAME)
++libc_hidden_builtin_def (MEMCPY_NAME)
+diff --git a/sysdeps/loongarch/lp64/memmove.S b/sysdeps/loongarch/lp64/memmove.S
+new file mode 100644
+index 00000000..edd9cf3d
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/memmove.S
+@@ -0,0 +1,406 @@
++/* Optimized memmove implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++/* Allow the routine to be named something else if desired. */
++#ifndef MEMMOVE_NAME
++#define MEMMOVE_NAME memmove
++#endif
++
++#define LD_64(reg, n) \
++ ld.d t0, reg, n; \
++ ld.d t1, reg, n+8; \
++ ld.d t2, reg, n+16; \
++ ld.d t3, reg, n+24; \
++ ld.d t4, reg, n+32; \
++ ld.d t5, reg, n+40; \
++ ld.d t6, reg, n+48; \
++ ld.d t7, reg, n+56;
++
++
++#define ST_64(reg, n) \
++ st.d t0, reg, n; \
++ st.d t1, reg, n+8; \
++ st.d t2, reg, n+16; \
++ st.d t3, reg, n+24; \
++ st.d t4, reg, n+32; \
++ st.d t5, reg, n+40; \
++ st.d t6, reg, n+48; \
++ st.d t7, reg, n+56;
++
++/* memmove (const void *dst, const void *src, size_t n) */
++LEAF(MEMMOVE_NAME)
++ add.d a4, a1, a2
++ add.d a3, a0, a2
++ beq a1, a0, less_1bytes
++ move t8, a0
++ srai.d a6, a2, 4 #num/16
++ beqz a6, less_16bytes #num<16
++ srai.d a6, a2, 6 #num/64
++ bnez a6, more_64bytes #num>64
++ srai.d a6, a2, 5
++ beqz a6, less_32bytes #num<32
++
++ ld.d t0, a1, 0 #32<num<64
++ ld.d t1, a1, 8
++ ld.d t2, a1, 16
++ ld.d t3, a1, 24
++ ld.d t4, a4, -32
++ ld.d t5, a4, -24
++ ld.d t6, a4, -16
++ ld.d t7, a4, -8
++ st.d t0, a0, 0
++ st.d t1, a0, 8
++ st.d t2, a0, 16
++ st.d t3, a0, 24
++ st.d t4, a3, -32
++ st.d t5, a3, -24
++ st.d t6, a3, -16
++ st.d t7, a3, -8
++
++ jr ra
++
++less_32bytes:
++ ld.d t0, a1, 0
++ ld.d t1, a1, 8
++ ld.d t2, a4, -16
++ ld.d t3, a4, -8
++ st.d t0, a0, 0
++ st.d t1, a0, 8
++ st.d t2, a3, -16
++ st.d t3, a3, -8
++
++ jr ra
++
++less_16bytes:
++ srai.d a6, a2, 3 #num/8
++ beqz a6, less_8bytes
++
++ ld.d t0, a1, 0
++ ld.d t1, a4, -8
++ st.d t0, a0, 0
++ st.d t1, a3, -8
++
++ jr ra
++
++less_8bytes:
++ srai.d a6, a2, 2
++ beqz a6, less_4bytes
++
++ ld.w t0, a1, 0
++ ld.w t1, a4, -4
++ st.w t0, a0, 0
++ st.w t1, a3, -4
++
++ jr ra
++
++less_4bytes:
++ srai.d a6, a2, 1
++ beqz a6, less_2bytes
++
++ ld.h t0, a1, 0
++ ld.h t1, a4, -2
++ st.h t0, a0, 0
++ st.h t1, a3, -2
++
++ jr ra
++
++less_2bytes:
++ beqz a2, less_1bytes
++
++ ld.b t0, a1, 0
++ st.b t0, a0, 0
++
++ jr ra
++
++less_1bytes:
++ jr ra
++
++more_64bytes:
++ sub.d a7, a0, a1
++ bltu a7, a2, copy_backward
++
++copy_forward:
++ srli.d a0, a0, 3
++ slli.d a0, a0, 3
++ beq a0, t8, all_align
++ addi.d a0, a0, 0x8
++ sub.d a7, t8, a0
++ sub.d a1, a1, a7
++ add.d a2, a7, a2
++
++start_unalign_proc:
++ pcaddi t1, 18
++ slli.d a6, a7, 3
++ add.d t1, t1, a6
++ jirl zero, t1, 0
++
++start_7_unalign:
++ ld.b t0, a1, -7
++ st.b t0, a0, -7
++start_6_unalign:
++ ld.b t0, a1, -6
++ st.b t0, a0, -6
++start_5_unalign:
++ ld.b t0, a1, -5
++ st.b t0, a0, -5
++start_4_unalign:
++ ld.b t0, a1, -4
++ st.b t0, a0, -4
++start_3_unalign:
++ ld.b t0, a1, -3
++ st.b t0, a0, -3
++start_2_unalign:
++ ld.b t0, a1, -2
++ st.b t0, a0, -2
++start_1_unalign:
++ ld.b t0, a1, -1
++ st.b t0, a0, -1
++start_over:
++
++ addi.d a2, a2, -0x80
++ blt a2, zero, end_unalign_proc
++
++loop_less:
++ LD_64(a1, 0)
++ ST_64(a0, 0)
++ LD_64(a1, 64)
++ ST_64(a0, 64)
++
++ addi.d a0, a0, 0x80
++ addi.d a1, a1, 0x80
++ addi.d a2, a2, -0x80
++ bge a2, zero, loop_less
++
++end_unalign_proc:
++ addi.d a2, a2, 0x80
++
++ pcaddi t1, 36
++ andi t2, a2, 0x78
++ add.d a1, a1, t2
++ add.d a0, a0, t2
++ sub.d t1, t1, t2
++ jirl zero, t1, 0
++
++end_120_128_unalign:
++ ld.d t0, a1, -120
++ st.d t0, a0, -120
++end_112_120_unalign:
++ ld.d t0, a1, -112
++ st.d t0, a0, -112
++end_104_112_unalign:
++ ld.d t0, a1, -104
++ st.d t0, a0, -104
++end_96_104_unalign:
++ ld.d t0, a1, -96
++ st.d t0, a0, -96
++end_88_96_unalign:
++ ld.d t0, a1, -88
++ st.d t0, a0, -88
++end_80_88_unalign:
++ ld.d t0, a1, -80
++ st.d t0, a0, -80
++end_72_80_unalign:
++ ld.d t0, a1, -72
++ st.d t0, a0, -72
++end_64_72_unalign:
++ ld.d t0, a1, -64
++ st.d t0, a0, -64
++end_56_64_unalign:
++ ld.d t0, a1, -56
++ st.d t0, a0, -56
++end_48_56_unalign:
++ ld.d t0, a1, -48
++ st.d t0, a0, -48
++end_40_48_unalign:
++ ld.d t0, a1, -40
++ st.d t0, a0, -40
++end_32_40_unalign:
++ ld.d t0, a1, -32
++ st.d t0, a0, -32
++end_24_32_unalign:
++ ld.d t0, a1, -24
++ st.d t0, a0, -24
++end_16_24_unalign:
++ ld.d t0, a1, -16
++ st.d t0, a0, -16
++end_8_16_unalign:
++ ld.d t0, a1, -8
++ st.d t0, a0, -8
++end_0_8_unalign:
++
++ andi a2, a2, 0x7
++ pcaddi t1, 18
++ slli.d a2, a2, 3
++ sub.d t1, t1, a2
++ jirl zero, t1, 0
++
++end_7_unalign:
++ ld.b t0, a4, -7
++ st.b t0, a3, -7
++end_6_unalign:
++ ld.b t0, a4, -6
++ st.b t0, a3, -6
++end_5_unalign:
++ ld.b t0, a4, -5
++ st.b t0, a3, -5
++end_4_unalign:
++ ld.b t0, a4, -4
++ st.b t0, a3, -4
++end_3_unalign:
++ ld.b t0, a4, -3
++ st.b t0, a3, -3
++end_2_unalign:
++ ld.b t0, a4, -2
++ st.b t0, a3, -2
++end_1_unalign:
++ ld.b t0, a4, -1
++ st.b t0, a3, -1
++end:
++
++ move v0, t8
++ jr ra
++
++all_align:
++ addi.d a1, a1, 0x8
++ addi.d a0, a0, 0x8
++ ld.d t0, a1, -8
++ st.d t0, a0, -8
++ addi.d a2, a2, -8
++ b start_over
++
++all_align_back:
++ addi.d a4, a4, -0x8
++ addi.d a3, a3, -0x8
++ ld.d t0, a4, 0
++ st.d t0, a3, 0
++ addi.d a2, a2, -8
++ b start_over_back
++
++copy_backward:
++ move a5, a3
++ srli.d a3, a3, 3
++ slli.d a3, a3, 3
++ beq a3, a5, all_align_back
++ sub.d a7, a3, a5
++ add.d a4, a4, a7
++ add.d a2, a7, a2
++
++ pcaddi t1, 18
++ slli.d a6, a7, 3
++ add.d t1, t1, a6
++ jirl zero, t1, 0
++
++ ld.b t0, a4, 6
++ st.b t0, a3, 6
++ ld.b t0, a4, 5
++ st.b t0, a3, 5
++ ld.b t0, a4, 4
++ st.b t0, a3, 4
++ ld.b t0, a4, 3
++ st.b t0, a3, 3
++ ld.b t0, a4, 2
++ st.b t0, a3, 2
++ ld.b t0, a4, 1
++ st.b t0, a3, 1
++ ld.b t0, a4, 0
++ st.b t0, a3, 0
++start_over_back:
++
++ addi.d a2, a2, -0x80
++ blt a2, zero, end_unalign_proc_back
++
++loop_less_back:
++ LD_64(a4, -64)
++ ST_64(a3, -64)
++ LD_64(a4, -128)
++ ST_64(a3, -128)
++
++ addi.d a4, a4, -0x80
++ addi.d a3, a3, -0x80
++ addi.d a2, a2, -0x80
++ bge a2, zero, loop_less_back
++
++end_unalign_proc_back:
++ addi.d a2, a2, 0x80
++
++ pcaddi t1, 36
++ andi t2, a2, 0x78
++ sub.d a4, a4, t2
++ sub.d a3, a3, t2
++ sub.d t1, t1, t2
++ jirl zero, t1, 0
++
++ ld.d t0, a4, 112
++ st.d t0, a3, 112
++ ld.d t0, a4, 104
++ st.d t0, a3, 104
++ ld.d t0, a4, 96
++ st.d t0, a3, 96
++ ld.d t0, a4, 88
++ st.d t0, a3, 88
++ ld.d t0, a4, 80
++ st.d t0, a3, 80
++ ld.d t0, a4, 72
++ st.d t0, a3, 72
++ ld.d t0, a4, 64
++ st.d t0, a3, 64
++ ld.d t0, a4, 56
++ st.d t0, a3, 56
++ ld.d t0, a4, 48
++ st.d t0, a3, 48
++ ld.d t0, a4, 40
++ st.d t0, a3, 40
++ ld.d t0, a4, 32
++ st.d t0, a3, 32
++ ld.d t0, a4, 24
++ st.d t0, a3, 24
++ ld.d t0, a4, 16
++ st.d t0, a3, 16
++ ld.d t0, a4, 8
++ st.d t0, a3, 8
++ ld.d t0, a4, 0
++ st.d t0, a3, 0
++
++ andi a2, a2, 0x7
++ pcaddi t1, 18
++ slli.d a2, a2, 3
++ sub.d t1, t1, a2
++ jirl zero, t1, 0
++
++ ld.b t0, a1, 6
++ st.b t0, a0, 6
++ ld.b t0, a1, 5
++ st.b t0, a0, 5
++ ld.b t0, a1, 4
++ st.b t0, a0, 4
++ ld.b t0, a1, 3
++ st.b t0, a0, 3
++ ld.b t0, a1, 2
++ st.b t0, a0, 2
++ ld.b t0, a1, 1
++ st.b t0, a0, 1
++ ld.b t0, a1, 0
++ st.b t0, a0, 0
++
++ move v0, t8
++ jr ra
++
++END(MEMMOVE_NAME)
++libc_hidden_builtin_def (MEMMOVE_NAME)
+--
+2.33.0
+
diff --git a/2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch b/2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch
new file mode 100644
index 0000000..81cdbe0
--- /dev/null
+++ b/2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch
@@ -0,0 +1,131 @@
+From 9bc2ed8f46d80859a5596789cc9e8cc2de84b0e7 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:39:37 +0100
+Subject: [PATCH] [2/5] AArch64: Improve A64FX memset for large sizes
+
+Improve performance of large memsets. Simplify alignment code. For zero memset
+use DC ZVA, which almost doubles performance. For non-zero memsets use the
+unroll8 loop which is about 10% faster.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 85 ++++++++++----------------------
+ 1 file changed, 25 insertions(+), 60 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index cf3d402..75cf43a 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -27,14 +27,11 @@
+ */
+
+ #define L1_SIZE (64*1024) // L1 64KB
+-#define L2_SIZE (8*1024*1024) // L2 8MB - 1MB
++#define L2_SIZE (8*1024*1024) // L2 8MB
+ #define CACHE_LINE_SIZE 256
+ #define PF_DIST_L1 (CACHE_LINE_SIZE * 16) // Prefetch distance L1
+-#define ZF_DIST (CACHE_LINE_SIZE * 21) // Zerofill distance
+-#define rest x8
++#define rest x2
+ #define vector_length x9
+-#define vl_remainder x10 // vector_length remainder
+-#define cl_remainder x11 // CACHE_LINE_SIZE remainder
+
+ #if HAVE_AARCH64_SVE_ASM
+ # if IS_IN (libc)
+@@ -42,14 +39,6 @@
+
+ .arch armv8.2-a+sve
+
+- .macro dc_zva times
+- dc zva, tmp1
+- add tmp1, tmp1, CACHE_LINE_SIZE
+- .if \times-1
+- dc_zva "(\times-1)"
+- .endif
+- .endm
+-
+ .macro st1b_unroll first=0, last=7
+ st1b z0.b, p0, [dst, \first, mul vl]
+ .if \last-\first
+@@ -188,54 +177,30 @@ L(L1_prefetch): // if rest >= L1_SIZE
+ cbnz rest, L(unroll32)
+ ret
+
+-L(L2):
+- // align dst address at vector_length byte boundary
+- sub tmp1, vector_length, 1
+- ands tmp2, dst, tmp1
+- // if vl_remainder == 0
+- b.eq 1f
+- sub vl_remainder, vector_length, tmp2
+- // process remainder until the first vector_length boundary
+- whilelt p2.b, xzr, vl_remainder
+- st1b z0.b, p2, [dst]
+- add dst, dst, vl_remainder
+- sub rest, rest, vl_remainder
+- // align dstin address at CACHE_LINE_SIZE byte boundary
+-1: mov tmp1, CACHE_LINE_SIZE
+- ands tmp2, dst, CACHE_LINE_SIZE - 1
+- // if cl_remainder == 0
+- b.eq L(L2_dc_zva)
+- sub cl_remainder, tmp1, tmp2
+- // process remainder until the first CACHE_LINE_SIZE boundary
+- mov tmp1, xzr // index
+-2: whilelt p2.b, tmp1, cl_remainder
+- st1b z0.b, p2, [dst, tmp1]
+- incb tmp1
+- cmp tmp1, cl_remainder
+- b.lo 2b
+- add dst, dst, cl_remainder
+- sub rest, rest, cl_remainder
+-
+-L(L2_dc_zva):
+- // zero fill
+- mov tmp1, dst
+- dc_zva (ZF_DIST / CACHE_LINE_SIZE) - 1
+- mov zva_len, ZF_DIST
+- add tmp1, zva_len, CACHE_LINE_SIZE * 2
+- // unroll
++ // count >= L2_SIZE
+ .p2align 3
+-1: st1b_unroll 0, 3
+- add tmp2, dst, zva_len
+- dc zva, tmp2
+- st1b_unroll 4, 7
+- add tmp2, tmp2, CACHE_LINE_SIZE
+- dc zva, tmp2
+- add dst, dst, CACHE_LINE_SIZE * 2
+- sub rest, rest, CACHE_LINE_SIZE * 2
+- cmp rest, tmp1 // ZF_DIST + CACHE_LINE_SIZE * 2
+- b.ge 1b
+- cbnz rest, L(unroll8)
+- ret
++L(L2):
++ tst valw, 255
++ b.ne L(unroll8)
++ // align dst to CACHE_LINE_SIZE byte boundary
++ and tmp2, dst, CACHE_LINE_SIZE - 1
++ st1b z0.b, p0, [dst, 0, mul vl]
++ st1b z0.b, p0, [dst, 1, mul vl]
++ st1b z0.b, p0, [dst, 2, mul vl]
++ st1b z0.b, p0, [dst, 3, mul vl]
++ sub dst, dst, tmp2
++ add count, count, tmp2
++
++ // clear cachelines using DC ZVA
++ sub count, count, CACHE_LINE_SIZE * 2
++ .p2align 4
++1: add dst, dst, CACHE_LINE_SIZE
++ dc zva, dst
++ subs count, count, CACHE_LINE_SIZE
++ b.hi 1b
++ add count, count, CACHE_LINE_SIZE
++ add dst, dst, CACHE_LINE_SIZE
++ b L(last)
+
+ END (MEMSET)
+ libc_hidden_builtin_def (MEMSET)
+--
+1.8.3.1
+
diff --git a/2_6-LoongArch-Optimize-string-functions-strchr-strchrnul.patch b/2_6-LoongArch-Optimize-string-functions-strchr-strchrnul.patch
new file mode 100644
index 0000000..af11456
--- /dev/null
+++ b/2_6-LoongArch-Optimize-string-functions-strchr-strchrnul.patch
@@ -0,0 +1,250 @@
+From dd99689b821162293506e0344f163b82349a9298 Mon Sep 17 00:00:00 2001
+From: Xue Liu <liuxue@loongson.cn>
+Date: Sun, 29 Jan 2023 10:22:01 +0800
+Subject: [PATCH 2/6] LoongArch: Optimize string functions strchr, strchrnull.
+
+Change-Id: I8b274972642b6a1926d8fc176404bfd83344bc51
+---
+ sysdeps/loongarch/lp64/strchr.S | 107 +++++++++++++++++++++++++++
+ sysdeps/loongarch/lp64/strchrnul.S | 115 +++++++++++++++++++++++++++++
+ 2 files changed, 222 insertions(+)
+ create mode 100644 sysdeps/loongarch/lp64/strchr.S
+ create mode 100644 sysdeps/loongarch/lp64/strchrnul.S
+
+diff --git a/sysdeps/loongarch/lp64/strchr.S b/sysdeps/loongarch/lp64/strchr.S
+new file mode 100644
+index 00000000..3d64c684
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/strchr.S
+@@ -0,0 +1,107 @@
++/* Optimized strchr implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++/* char * strchr (const char *s1, int c); */
++LEAF(strchr)
++ .align 6
++
++ li.w t4, 0x7
++ lu12i.w a2, 0x01010
++ bstrins.d a1, a1, 15, 8
++ andi t0, a0, 0x7
++
++ ori a2, a2, 0x101
++ andn t4, a0, t4
++ slli.w t1, t0, 3
++
++ ld.d t4, t4, 0
++
++ nor t8, zero, zero
++ bstrins.d a1, a1, 31, 16
++ srl.d t4, t4, t1
++
++ bstrins.d a1, a1, 63, 32
++ bstrins.d a2, a2, 63, 32
++ srl.d a7, t8, t1
++
++ li.w t1, 8
++ nor t8, a7, zero
++ slli.d a3, a2, 7
++ or t5, t8, t4
++ and t3, a7, a1
++
++ sub.w t1, t1, t0
++ nor a3, a3, zero
++ xor t2, t5, t3
++ sub.d a7, t5, a2
++ nor a6, t5, a3
++
++ sub.d a5, t2, a2
++ nor a4, t2, a3
++
++ and a6, a7, a6
++ and a5, a5, a4
++ or a7, a6, a5
++ bnez a7, L(_mc8_a)
++
++ add.d a0, a0, t1
++L(_aloop):
++ ld.d t4, a0, 0
++
++ xor t2, t4, a1
++ sub.d a7, t4, a2
++ nor a6, t4, a3
++ sub.d a5, t2, a2
++
++ nor a4, t2, a3
++ and a6, a7, a6
++ and a5, a5, a4
++ or a7, a6, a5
++ bnez a7, L(_mc8_a)
++
++ ld.d t4, a0, 8
++ addi.d a0, a0, 16
++ xor t2, t4, a1
++ sub.d a7, t4, a2
++ nor a6, t4, a3
++ sub.d a5, t2, a2
++
++ nor a4, t2, a3
++ and a6, a7, a6
++ and a5, a5, a4
++ or a7, a6, a5
++ beqz a7, L(_aloop)
++
++ addi.d a0, a0, -8
++L(_mc8_a):
++
++ ctz.d t0, a5
++ ctz.d t2, a6
++
++ srli.w t0, t0, 3
++ srli.w t2, t2, 3
++ sltu t1, t2, t0
++ add.d v0, a0, t0
++ masknez v0, v0, t1
++ jr ra
++END(strchr)
++
++libc_hidden_builtin_def (strchr)
++weak_alias (strchr, index)
+diff --git a/sysdeps/loongarch/lp64/strchrnul.S b/sysdeps/loongarch/lp64/strchrnul.S
+new file mode 100644
+index 00000000..58b8b372
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/strchrnul.S
+@@ -0,0 +1,115 @@
++/* Optimized strchrnul implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++#define MOVZ(rd,rs,rt) \
++ masknez t6, rs, rt;\
++ maskeqz rd, rd, rt;\
++ or rd, rd, t6
++
++/* char *strchrnul(const char *s, int c); */
++LEAF(__strchrnul)
++ .align 6
++
++ li.w t4, 0x7
++ lu12i.w a2, 0x01010
++ bstrins.d a1, a1, 15, 8
++ andi t0, a0, 0x7
++
++ ori a2, a2, 0x101
++ andn t4, a0, t4
++ slli.w t1, t0, 3
++ ld.d t4, t4, 0
++
++ nor t8, zero, zero
++ bstrins.d a1, a1, 31, 16
++ srl.d t4, t4, t1
++
++ preld 0, a0, 32
++ bstrins.d a1, a1, 63, 32
++ bstrins.d a2, a2, 63, 32
++ srl.d a7, t8, t1
++
++ nor t8, a7, zero
++ slli.d a3, a2, 7
++ or t5, t8, t4
++ and t3, a7, a1
++
++ nor a3, a3, zero
++ xor t2, t5, t3
++ sub.d a7, t5, a2
++ nor a6, t5, a3
++
++ li.w t1, 8
++ sub.d a5, t2, a2
++ nor a4, t2, a3
++
++ and a6, a7, a6
++ and a5, a5, a4
++ or a7, a6, a5
++ bnez a7, L(_mc8_a)
++
++ sub.w t1, t1, t0
++ add.d a0, a0, t1
++L(_aloop):
++ ld.d t4, a0, 0
++
++ xor t2, t4, a1
++ sub.d a7, t4, a2
++ nor a6, t4, a3
++ sub.d a5, t2, a2
++
++ nor a4, t2, a3
++ and a6, a7, a6
++ and a5, a5, a4
++
++ or a7, a6, a5
++ bnez a7, L(_mc8_a)
++
++ ld.d t4, a0, 8
++ addi.d a0, a0, 16
++
++ xor t2, t4, a1
++ sub.d a7, t4, a2
++ nor a6, t4, a3
++ sub.d a5, t2, a2
++
++ nor a4, t2, a3
++ and a6, a7, a6
++ and a5, a5, a4
++
++ or a7, a6, a5
++ beqz a7, L(_aloop)
++
++ addi.d a0, a0, -8
++L(_mc8_a):
++ ctz.d t0, a5
++ ctz.d t2, a6
++
++ srli.w t0, t0, 3
++ srli.w t2, t2, 3
++ slt t1, t0, t2
++
++ MOVZ(t0,t2,t1)
++
++ add.d v0, a0, t0
++ jr ra
++END(__strchrnul)
++
++weak_alias(__strchrnul, strchrnul)
+--
+2.33.0
+
diff --git a/3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch b/3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch
new file mode 100644
index 0000000..7ba3516
--- /dev/null
+++ b/3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch
@@ -0,0 +1,80 @@
+From 186092c6ba8825598ffdbf15dbf0823c771f560d Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:42:07 +0100
+Subject: [PATCH] [3/5] AArch64: Improve A64FX memset for remaining bytes
+
+Simplify handling of remaining bytes. Avoid lots of taken branches and complex
+whilelo computations, instead unconditionally write vectors from the end.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 46 +++++++++-----------------------
+ 1 file changed, 13 insertions(+), 33 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index 75cf43a..337c86b 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -130,38 +130,19 @@ L(unroll8):
+ b 1b
+
+ L(last):
+- whilelo p0.b, xzr, rest
+- whilelo p1.b, vector_length, rest
+- b.last 1f
+- st1b z0.b, p0, [dst, #0, mul vl]
+- st1b z0.b, p1, [dst, #1, mul vl]
+- ret
+-1: lsl tmp1, vector_length, 1 // vector_length * 2
+- whilelo p2.b, tmp1, rest
+- incb tmp1
+- whilelo p3.b, tmp1, rest
+- b.last 1f
+- st1b z0.b, p0, [dst, #0, mul vl]
+- st1b z0.b, p1, [dst, #1, mul vl]
+- st1b z0.b, p2, [dst, #2, mul vl]
+- st1b z0.b, p3, [dst, #3, mul vl]
+- ret
+-1: lsl tmp1, vector_length, 2 // vector_length * 4
+- whilelo p4.b, tmp1, rest
+- incb tmp1
+- whilelo p5.b, tmp1, rest
+- incb tmp1
+- whilelo p6.b, tmp1, rest
+- incb tmp1
+- whilelo p7.b, tmp1, rest
+- st1b z0.b, p0, [dst, #0, mul vl]
+- st1b z0.b, p1, [dst, #1, mul vl]
+- st1b z0.b, p2, [dst, #2, mul vl]
+- st1b z0.b, p3, [dst, #3, mul vl]
+- st1b z0.b, p4, [dst, #4, mul vl]
+- st1b z0.b, p5, [dst, #5, mul vl]
+- st1b z0.b, p6, [dst, #6, mul vl]
+- st1b z0.b, p7, [dst, #7, mul vl]
++ cmp count, vector_length, lsl 1
++ b.ls 2f
++ add tmp2, vector_length, vector_length, lsl 2
++ cmp count, tmp2
++ b.ls 5f
++ st1b z0.b, p0, [dstend, -8, mul vl]
++ st1b z0.b, p0, [dstend, -7, mul vl]
++ st1b z0.b, p0, [dstend, -6, mul vl]
++5: st1b z0.b, p0, [dstend, -5, mul vl]
++ st1b z0.b, p0, [dstend, -4, mul vl]
++ st1b z0.b, p0, [dstend, -3, mul vl]
++2: st1b z0.b, p0, [dstend, -2, mul vl]
++ st1b z0.b, p0, [dstend, -1, mul vl]
+ ret
+
+ L(L1_prefetch): // if rest >= L1_SIZE
+@@ -199,7 +180,6 @@ L(L2):
+ subs count, count, CACHE_LINE_SIZE
+ b.hi 1b
+ add count, count, CACHE_LINE_SIZE
+- add dst, dst, CACHE_LINE_SIZE
+ b L(last)
+
+ END (MEMSET)
+--
+1.8.3.1
+
diff --git a/3_6-LoongArch-Optimize-string-function-memset.patch b/3_6-LoongArch-Optimize-string-function-memset.patch
new file mode 100644
index 0000000..54b9a2b
--- /dev/null
+++ b/3_6-LoongArch-Optimize-string-function-memset.patch
@@ -0,0 +1,190 @@
+From 603aa93569ec4034aa1d5a310f59504b5d6aad4d Mon Sep 17 00:00:00 2001
+From: Xue Liu <liuxue@loongson.cn>
+Date: Sun, 29 Jan 2023 10:23:06 +0800
+Subject: [PATCH 3/6] LoongArch: Optimize string function memset.
+
+Change-Id: I04906c31a2eabd380b19bb3a4cab603128526cd1
+---
+ sysdeps/loongarch/lp64/memset.S | 170 ++++++++++++++++++++++++++++++++
+ 1 file changed, 170 insertions(+)
+ create mode 100644 sysdeps/loongarch/lp64/memset.S
+
+diff --git a/sysdeps/loongarch/lp64/memset.S b/sysdeps/loongarch/lp64/memset.S
+new file mode 100644
+index 00000000..261504b1
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/memset.S
+@@ -0,0 +1,170 @@
++/* Optimized memset implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++#define ST_128(n) \
++ st.d a1, a0, n; \
++ st.d a1, a0, n+8 ; \
++ st.d a1, a0, n+16 ; \
++ st.d a1, a0, n+24 ; \
++ st.d a1, a0, n+32 ; \
++ st.d a1, a0, n+40 ; \
++ st.d a1, a0, n+48 ; \
++ st.d a1, a0, n+56 ; \
++ st.d a1, a0, n+64 ; \
++ st.d a1, a0, n+72 ; \
++ st.d a1, a0, n+80 ; \
++ st.d a1, a0, n+88 ; \
++ st.d a1, a0, n+96 ; \
++ st.d a1, a0, n+104; \
++ st.d a1, a0, n+112; \
++ st.d a1, a0, n+120; \
++
++/* void *memset(void *s, int c, size_t n); */
++LEAF(memset)
++ .align 6
++
++ bstrins.d a1, a1, 15, 8
++ add.d t7, a0, a2
++ bstrins.d a1, a1, 31, 16
++ move t0, a0
++ bstrins.d a1, a1, 63, 32
++ srai.d t8, a2, 4 #num/16
++ beqz t8, less_16bytes #num<16
++ srai.d t8, a2, 6 #num/64
++ bnez t8, more_64bytes #num>64
++ srai.d t8, a2, 5 #num/32
++ beqz t8, less_32bytes #num<32
++ st.d a1, a0, 0 #32<num<64
++ st.d a1, a0, 8
++ st.d a1, a0, 16
++ st.d a1, a0, 24
++ st.d a1, t7, -32
++ st.d a1, t7, -24
++ st.d a1, t7, -16
++ st.d a1, t7, -8
++
++ jr ra
++
++less_32bytes:
++ st.d a1, a0, 0
++ st.d a1, a0, 8
++ st.d a1, t7, -16
++ st.d a1, t7, -8
++
++ jr ra
++
++less_16bytes:
++ srai.d t8, a2, 3 #num/8
++ beqz t8, less_8bytes
++ st.d a1, a0, 0
++ st.d a1, t7, -8
++
++ jr ra
++
++less_8bytes:
++ srai.d t8, a2, 2
++ beqz t8, less_4bytes
++ st.w a1, a0, 0
++ st.w a1, t7, -4
++
++ jr ra
++
++less_4bytes:
++ srai.d t8, a2, 1
++ beqz t8, less_2bytes
++ st.h a1, a0, 0
++ st.h a1, t7, -2
++
++ jr ra
++
++less_2bytes:
++ beqz a2, less_1bytes
++ st.b a1, a0, 0
++
++ jr ra
++
++less_1bytes:
++ jr ra
++
++more_64bytes:
++ srli.d a0, a0, 3
++ slli.d a0, a0, 3
++ addi.d a0, a0, 0x8
++ st.d a1, t0, 0
++ sub.d t2, t0, a0
++ add.d a2, t2, a2
++
++ addi.d a2, a2, -0x80
++ blt a2, zero, end_unalign_proc
++
++loop_less:
++ ST_128(0)
++ addi.d a0, a0, 0x80
++ addi.d a2, a2, -0x80
++ bge a2, zero, loop_less
++
++end_unalign_proc:
++ addi.d a2, a2, 0x80
++
++ pcaddi t1, 20
++ andi t5, a2, 0x78
++ srli.d t5, t5, 1
++ sub.d t1, t1, t5
++ jirl zero, t1, 0
++
++end_120_128_unalign:
++ st.d a1, a0, 112
++end_112_120_unalign:
++ st.d a1, a0, 104
++end_104_112_unalign:
++ st.d a1, a0, 96
++end_96_104_unalign:
++ st.d a1, a0, 88
++end_88_96_unalign:
++ st.d a1, a0, 80
++end_80_88_unalign:
++ st.d a1, a0, 72
++end_72_80_unalign:
++ st.d a1, a0, 64
++end_64_72_unalign:
++ st.d a1, a0, 56
++end_56_64_unalign:
++ st.d a1, a0, 48
++end_48_56_unalign:
++ st.d a1, a0, 40
++end_40_48_unalign:
++ st.d a1, a0, 32
++end_32_40_unalign:
++ st.d a1, a0, 24
++end_24_32_unalign:
++ st.d a1, a0, 16
++end_16_24_unalign:
++ st.d a1, a0, 8
++end_8_16_unalign:
++ st.d a1, a0, 0
++end_0_8_unalign:
++ st.d a1, t7, -8
++
++ move v0, t0
++ jr ra
++
++END(memset)
++
++libc_hidden_builtin_def (memset)
+--
+2.33.0
+
diff --git a/4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch b/4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch
new file mode 100644
index 0000000..fd17671
--- /dev/null
+++ b/4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch
@@ -0,0 +1,51 @@
+From e69d9981f858a38e19304e6ff5ebdf89f2cb0ba0 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:44:27 +0100
+Subject: [PATCH] [4/5] AArch64: Improve A64FX memset by removing unroll32
+
+Remove unroll32 code since it doesn't improve performance.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 18 +-----------------
+ 1 file changed, 1 insertion(+), 17 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index 337c86b..ef03156 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -102,22 +102,6 @@ L(vl_agnostic): // VL Agnostic
+ ccmp vector_length, tmp1, 0, cs
+ b.eq L(L1_prefetch)
+
+-L(unroll32):
+- lsl tmp1, vector_length, 3 // vector_length * 8
+- lsl tmp2, vector_length, 5 // vector_length * 32
+- .p2align 3
+-1: cmp rest, tmp2
+- b.cc L(unroll8)
+- st1b_unroll
+- add dst, dst, tmp1
+- st1b_unroll
+- add dst, dst, tmp1
+- st1b_unroll
+- add dst, dst, tmp1
+- st1b_unroll
+- add dst, dst, tmp1
+- sub rest, rest, tmp2
+- b 1b
+
+ L(unroll8):
+ lsl tmp1, vector_length, 3
+@@ -155,7 +139,7 @@ L(L1_prefetch): // if rest >= L1_SIZE
+ sub rest, rest, CACHE_LINE_SIZE * 2
+ cmp rest, L1_SIZE
+ b.ge 1b
+- cbnz rest, L(unroll32)
++ cbnz rest, L(unroll8)
+ ret
+
+ // count >= L2_SIZE
+--
+1.8.3.1
+
diff --git a/4_6-LoongArch-Optimize-string-functions-strcmp-strncmp.patch b/4_6-LoongArch-Optimize-string-functions-strcmp-strncmp.patch
new file mode 100644
index 0000000..5e0ce7d
--- /dev/null
+++ b/4_6-LoongArch-Optimize-string-functions-strcmp-strncmp.patch
@@ -0,0 +1,414 @@
+From 3f3b70e39a529369e4b2936f35034215a45436a3 Mon Sep 17 00:00:00 2001
+From: Xue Liu <liuxue@loongson.cn>
+Date: Sun, 29 Jan 2023 10:23:50 +0800
+Subject: [PATCH 4/6] LoongArch: Optimize string functions strcmp, strncmp.
+
+Change-Id: I436138a312e8ebb668223cafef84fd74dcde72fd
+---
+ sysdeps/loongarch/lp64/strcmp.S | 161 ++++++++++++++++++++++
+ sysdeps/loongarch/lp64/strncmp.S | 225 +++++++++++++++++++++++++++++++
+ 2 files changed, 386 insertions(+)
+ create mode 100644 sysdeps/loongarch/lp64/strcmp.S
+ create mode 100644 sysdeps/loongarch/lp64/strncmp.S
+
+diff --git a/sysdeps/loongarch/lp64/strcmp.S b/sysdeps/loongarch/lp64/strcmp.S
+new file mode 100644
+index 00000000..0f7a6d55
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/strcmp.S
+@@ -0,0 +1,161 @@
++/* Optimized strcmp implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sys/asm.h>
++
++/* Parameters and Results */
++#define src1 a0
++#define src2 a1
++#define result v0
++
++/* Internal variable */
++#define src1_off a2
++#define src2_off a3
++#define data1 t0
++#define data2 t1
++#define has_nul t2
++#define diff t3
++#define syndrome t4
++#define zeroones t5
++#define sevenf t6
++#define pos t7
++#define exchange t8
++#define tmp1 a4
++#define tmp2 a5
++#define tmp3 a6
++#define tmp4 a7
++
++/* rd <- if rc then ra else rb
++ tmp3 will be destroyed */
++#define CONDITIONSEL(rd, rc, ra, rb)\
++ masknez tmp3, rb, rc;\
++ maskeqz rd, ra, rc;\
++ or rd, rd, tmp3
++
++LEAF(strcmp)
++ .align 4
++
++ xor tmp1, src1, src2
++ lu12i.w zeroones, 0x01010
++ lu12i.w sevenf, 0x7f7f7
++ andi src1_off, src1, 0x7
++ ori zeroones, zeroones, 0x101
++ ori sevenf, sevenf, 0xf7f
++ andi tmp1, tmp1, 0x7
++ bstrins.d zeroones, zeroones, 63, 32
++ bstrins.d sevenf, sevenf, 63, 32
++ bnez tmp1, strcmp_misaligned8
++ bnez src1_off, strcmp_mutual_align
++strcmp_loop_aligned:
++ ld.d data1, src1, 0
++ addi.d src1, src1, 8
++ ld.d data2, src2, 0
++ addi.d src2, src2, 8
++strcmp_start_realigned:
++ sub.d tmp1, data1, zeroones
++ or tmp2, data1, sevenf
++ xor diff, data1, data2
++ andn has_nul, tmp1, tmp2
++ or syndrome, diff, has_nul
++ beqz syndrome, strcmp_loop_aligned
++
++strcmp_end:
++ ctz.d pos, syndrome
++ bstrins.d pos, zero, 2, 0
++ srl.d data1, data1, pos
++ srl.d data2, data2, pos
++ andi data1, data1, 0xff
++ andi data2, data2, 0xff
++ sub.d result, data1, data2
++ jr ra
++strcmp_mutual_align:
++ bstrins.d src1, zero, 2, 0
++ bstrins.d src2, zero, 2, 0
++ slli.d tmp1, src1_off, 0x3
++ ld.d data1, src1, 0
++ sub.d tmp1, zero, tmp1
++ ld.d data2, src2, 0
++ addi.d src1, src1, 8
++ addi.d src2, src2, 8
++ nor tmp2, zero, zero
++ srl.d tmp2, tmp2, tmp1
++ or data1, data1, tmp2
++ or data2, data2, tmp2
++ b strcmp_start_realigned
++
++strcmp_misaligned8:
++ /* check
++ if ((src1 != 0) && ((src2 == 0 ) || (src1 < src2)))
++ then exchange(src1,src2). */
++ andi src2_off, src2, 0x7
++ slt tmp2, src1_off, src2_off
++ CONDITIONSEL(tmp2, src2_off, tmp2, tmp1)
++ maskeqz exchange, tmp2, src1_off
++ xor tmp3, src1, src2
++ maskeqz tmp3, tmp3, exchange
++ xor src1, src1, tmp3
++ xor src2, src2, tmp3
++
++ andi src1_off, src1, 0x7
++ beqz src1_off, strcmp_loop_misaligned
++strcmp_do_misaligned:
++ ld.bu data1, src1, 0
++ ld.bu data2, src2, 0
++ xor tmp3, data1, data2
++ addi.d src1, src1, 1
++ masknez tmp3, data1, tmp3
++ addi.d src2, src2, 1
++ beqz tmp3, strcmp_done
++ andi src1_off, src1, 0x7
++ bnez src1_off, strcmp_do_misaligned
++
++strcmp_loop_misaligned:
++ andi tmp1, src2, 0xff8
++ xori tmp1, tmp1, 0xff8
++ beqz tmp1, strcmp_do_misaligned
++ ld.d data1, src1, 0
++ ld.d data2, src2, 0
++ addi.d src1, src1, 8
++ addi.d src2, src2, 8
++
++ sub.d tmp1, data1, zeroones
++ or tmp2, data1, sevenf
++ xor diff, data1, data2
++ andn has_nul, tmp1, tmp2
++ or syndrome, diff, has_nul
++ beqz syndrome, strcmp_loop_misaligned
++strcmp_misalign_end:
++ ctz.d pos, syndrome
++ bstrins.d pos, zero, 2, 0
++ srl.d data1, data1, pos
++ srl.d data2, data2, pos
++ andi data1, data1, 0xff
++ andi data2, data2, 0xff
++ sub.d tmp1, data1, data2
++ sub.d tmp2, data2, data1
++ CONDITIONSEL(result, exchange, tmp2, tmp1)
++ jr ra
++
++strcmp_done:
++ sub.d tmp1, data1, data2
++ sub.d tmp2, data2, data1
++ CONDITIONSEL(result, exchange, tmp2, tmp1)
++ jr ra
++END(strcmp)
++
++libc_hidden_builtin_def (strcmp)
+diff --git a/sysdeps/loongarch/lp64/strncmp.S b/sysdeps/loongarch/lp64/strncmp.S
+new file mode 100644
+index 00000000..979ea40a
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/strncmp.S
+@@ -0,0 +1,225 @@
++/* Optimized strncmp implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sys/asm.h>
++
++/* Parameters and Results */
++#define src1 a0
++#define src2 a1
++#define limit a2
++#define result v0
++
++
++/* Internal variable */
++#define data1 t0
++#define data2 t1
++#define has_nul t2
++#define diff t3
++#define syndrome t4
++#define zeroones t5
++#define sevenf t6
++#define pos t7
++#define exchange t8
++#define tmp1 a5
++#define tmp2 a6
++#define tmp3 a7
++#define src1_off a3
++#define limit_wd a4
++
++LEAF(strncmp)
++ .align 4
++ beqz limit, strncmp_ret0
++
++ xor tmp1, src1, src2
++ lu12i.w zeroones, 0x01010
++ lu12i.w sevenf, 0x7f7f7
++ andi src1_off, src1, 0x7
++ ori zeroones, zeroones, 0x101
++ andi tmp1, tmp1, 0x7
++ ori sevenf, sevenf, 0xf7f
++ bstrins.d zeroones, zeroones, 63, 32
++ bstrins.d sevenf, sevenf, 63, 32
++ bnez tmp1, strncmp_misaligned8
++ bnez src1_off, strncmp_mutual_align
++ addi.d limit_wd, limit, -1
++ srli.d limit_wd, limit_wd, 3
++
++strncmp_loop_aligned:
++ ld.d data1, src1, 0
++ addi.d src1, src1, 8
++ ld.d data2, src2, 0
++ addi.d src2, src2, 8
++strncmp_start_realigned:
++ addi.d limit_wd, limit_wd, -1
++ sub.d tmp1, data1, zeroones
++ or tmp2, data1, sevenf
++ xor diff, data1, data2
++ andn has_nul, tmp1, tmp2
++ srli.d tmp1, limit_wd, 63
++ or syndrome, diff, has_nul
++ or tmp2, syndrome, tmp1
++ beqz tmp2, strncmp_loop_aligned
++
++ /* if not reach limit */
++ bge limit_wd, zero, strncmp_not_limit
++ /* if reach limit */
++ andi limit, limit, 0x7
++ li.w tmp1, 0x8
++ sub.d limit, tmp1, limit
++ slli.d limit, limit, 0x3
++ li.d tmp1, -1
++ srl.d tmp1, tmp1, limit
++ and data1, data1, tmp1
++ and data2, data2, tmp1
++ orn syndrome, syndrome, tmp1
++
++
++strncmp_not_limit:
++ ctz.d pos, syndrome
++ bstrins.d pos, zero, 2, 0
++ srl.d data1, data1, pos
++ srl.d data2, data2, pos
++ andi data1, data1, 0xff
++ andi data2, data2, 0xff
++ sub.d result, data1, data2
++ jr ra
++
++
++
++strncmp_mutual_align:
++ bstrins.d src1, zero, 2, 0
++ bstrins.d src2, zero, 2, 0
++ slli.d tmp1, src1_off, 0x3
++ ld.d data1, src1, 0
++ ld.d data2, src2, 0
++ addi.d src2, src2, 8
++ addi.d src1, src1, 8
++
++ addi.d limit_wd, limit, -1
++ andi tmp3, limit_wd, 0x7
++ srli.d limit_wd, limit_wd, 3
++ add.d limit, limit, src1_off
++ add.d tmp3, tmp3, src1_off
++ srli.d tmp3, tmp3, 3
++ add.d limit_wd, limit_wd, tmp3
++
++ sub.d tmp1, zero, tmp1
++ nor tmp2, zero, zero
++ srl.d tmp2, tmp2, tmp1
++ or data1, data1, tmp2
++ or data2, data2, tmp2
++ b strncmp_start_realigned
++
++strncmp_misaligned8:
++
++ li.w tmp1, 0x10
++ bge limit, tmp1, strncmp_try_words
++strncmp_byte_loop:
++ ld.bu data1, src1, 0
++ ld.bu data2, src2, 0
++ addi.d limit, limit, -1
++ xor tmp1, data1, data2
++ masknez tmp1, data1, tmp1
++ maskeqz tmp1, limit, tmp1
++ beqz tmp1, strncmp_done
++
++ ld.bu data1, src1, 1
++ ld.bu data2, src2, 1
++ addi.d src1, src1, 2
++ addi.d src2, src2, 2
++ addi.d limit, limit, -1
++ xor tmp1, data1, data2
++ masknez tmp1, data1, tmp1
++ maskeqz tmp1, limit, tmp1
++ bnez tmp1, strncmp_byte_loop
++
++
++strncmp_done:
++ sub.d result, data1, data2
++ jr ra
++
++strncmp_try_words:
++ srli.d limit_wd, limit, 3
++ beqz src1_off, strncmp_do_misaligned
++
++ sub.d src1_off, zero, src1_off
++ andi src1_off, src1_off, 0x7
++ sub.d limit, limit, src1_off
++ srli.d limit_wd, limit, 0x3
++
++strncmp_page_end_loop:
++ ld.bu data1, src1, 0
++ ld.bu data2, src2, 0
++ addi.d src1, src1, 1
++ addi.d src2, src2, 1
++ xor tmp1, data1, data2
++ masknez tmp1, data1, tmp1
++ beqz tmp1, strncmp_done
++ andi tmp1, src1, 0x7
++ bnez tmp1, strncmp_page_end_loop
++strncmp_do_misaligned:
++ li.w src1_off, 0x8
++ addi.d limit_wd, limit_wd, -1
++ blt limit_wd, zero, strncmp_done_loop
++
++strncmp_loop_misaligned:
++ andi tmp2, src2, 0xff8
++ xori tmp2, tmp2, 0xff8
++ beqz tmp2, strncmp_page_end_loop
++
++ ld.d data1, src1, 0
++ ld.d data2, src2, 0
++ addi.d src1, src1, 8
++ addi.d src2, src2, 8
++ sub.d tmp1, data1, zeroones
++ or tmp2, data1, sevenf
++ xor diff, data1, data2
++ andn has_nul, tmp1, tmp2
++ or syndrome, diff, has_nul
++ bnez syndrome, strncmp_not_limit
++ addi.d limit_wd, limit_wd, -1
++ bge limit_wd, zero, strncmp_loop_misaligned
++
++strncmp_done_loop:
++ andi limit, limit, 0x7
++ beqz limit, strncmp_not_limit
++ /* Read the last double word
++ check if the final part is about to exceed the page */
++ andi tmp1, src2, 0x7
++ andi tmp2, src2, 0xff8
++ add.d tmp1, tmp1, limit
++ xori tmp2, tmp2, 0xff8
++ andi tmp1, tmp1, 0x8
++ masknez tmp1, tmp1, tmp2
++ bnez tmp1, strncmp_byte_loop
++ addi.d src1, src1, -8
++ addi.d src2, src2, -8
++ ldx.d data1, src1, limit
++ ldx.d data2, src2, limit
++ sub.d tmp1, data1, zeroones
++ or tmp2, data1, sevenf
++ xor diff, data1, data2
++ andn has_nul, tmp1, tmp2
++ or syndrome, diff, has_nul
++ bnez syndrome, strncmp_not_limit
++
++strncmp_ret0:
++ move result, zero
++ jr ra
++END(strncmp)
++libc_hidden_builtin_def (strncmp)
+--
+2.33.0
+
diff --git a/5-5-AArch64-Improve-A64FX-memset-medium-loops.patch b/5-5-AArch64-Improve-A64FX-memset-medium-loops.patch
new file mode 100644
index 0000000..f8bc03e
--- /dev/null
+++ b/5-5-AArch64-Improve-A64FX-memset-medium-loops.patch
@@ -0,0 +1,96 @@
+From a5db6a5cae6a92d1675c013e5c8d972768721576 Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Tue, 10 Aug 2021 13:46:20 +0100
+Subject: [PATCH] [5/5] AArch64: Improve A64FX memset medium loops
+
+Simplify the code for memsets smaller than L1. Improve the unroll8 and
+L1_prefetch loops.
+
+Reviewed-by: Naohiro Tamura <naohirot@fujitsu.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 45 ++++++++++++++------------------
+ 1 file changed, 19 insertions(+), 26 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index ef03156..7bf759b 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -30,7 +30,6 @@
+ #define L2_SIZE (8*1024*1024) // L2 8MB
+ #define CACHE_LINE_SIZE 256
+ #define PF_DIST_L1 (CACHE_LINE_SIZE * 16) // Prefetch distance L1
+-#define rest x2
+ #define vector_length x9
+
+ #if HAVE_AARCH64_SVE_ASM
+@@ -89,29 +88,19 @@ ENTRY (MEMSET)
+
+ .p2align 4
+ L(vl_agnostic): // VL Agnostic
+- mov rest, count
+ mov dst, dstin
+- add dstend, dstin, count
+- // if rest >= L2_SIZE && vector_length == 64 then L(L2)
+- mov tmp1, 64
+- cmp rest, L2_SIZE
+- ccmp vector_length, tmp1, 0, cs
+- b.eq L(L2)
+- // if rest >= L1_SIZE && vector_length == 64 then L(L1_prefetch)
+- cmp rest, L1_SIZE
+- ccmp vector_length, tmp1, 0, cs
+- b.eq L(L1_prefetch)
+-
++ cmp count, L1_SIZE
++ b.hi L(L1_prefetch)
+
++ // count >= 8 * vector_length
+ L(unroll8):
+- lsl tmp1, vector_length, 3
+- .p2align 3
+-1: cmp rest, tmp1
+- b.cc L(last)
+- st1b_unroll
++ sub count, count, tmp1
++ .p2align 4
++1: st1b_unroll 0, 7
+ add dst, dst, tmp1
+- sub rest, rest, tmp1
+- b 1b
++ subs count, count, tmp1
++ b.hi 1b
++ add count, count, tmp1
+
+ L(last):
+ cmp count, vector_length, lsl 1
+@@ -129,18 +118,22 @@ L(last):
+ st1b z0.b, p0, [dstend, -1, mul vl]
+ ret
+
+-L(L1_prefetch): // if rest >= L1_SIZE
++ // count >= L1_SIZE
+ .p2align 3
++L(L1_prefetch):
++ cmp count, L2_SIZE
++ b.hs L(L2)
++ cmp vector_length, 64
++ b.ne L(unroll8)
+ 1: st1b_unroll 0, 3
+ prfm pstl1keep, [dst, PF_DIST_L1]
+ st1b_unroll 4, 7
+ prfm pstl1keep, [dst, PF_DIST_L1 + CACHE_LINE_SIZE]
+ add dst, dst, CACHE_LINE_SIZE * 2
+- sub rest, rest, CACHE_LINE_SIZE * 2
+- cmp rest, L1_SIZE
+- b.ge 1b
+- cbnz rest, L(unroll8)
+- ret
++ sub count, count, CACHE_LINE_SIZE * 2
++ cmp count, PF_DIST_L1
++ b.hs 1b
++ b L(unroll8)
+
+ // count >= L2_SIZE
+ .p2align 3
+--
+1.8.3.1
+
diff --git a/5_6-LoongArch-Optimize-string-function-strcpy.patch b/5_6-LoongArch-Optimize-string-function-strcpy.patch
new file mode 100644
index 0000000..d2686d5
--- /dev/null
+++ b/5_6-LoongArch-Optimize-string-function-strcpy.patch
@@ -0,0 +1,195 @@
+From 379b627b88af8d91c1f87b323925119ec313b1b7 Mon Sep 17 00:00:00 2001
+From: Xue Liu <liuxue@loongson.cn>
+Date: Sun, 29 Jan 2023 10:25:18 +0800
+Subject: [PATCH 5/6] LoongArch: Optimize string function strcpy.
+
+Change-Id: Ic105e1f00cceb4937d5fd2127ca03025a18ff4be
+---
+ sysdeps/loongarch/lp64/strcpy.S | 175 ++++++++++++++++++++++++++++++++
+ 1 file changed, 175 insertions(+)
+ create mode 100644 sysdeps/loongarch/lp64/strcpy.S
+
+diff --git a/sysdeps/loongarch/lp64/strcpy.S b/sysdeps/loongarch/lp64/strcpy.S
+new file mode 100644
+index 00000000..03d9d361
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/strcpy.S
+@@ -0,0 +1,175 @@
++/* Optimized strcpy implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sys/asm.h>
++
++/* Parameters and Results */
++#define dest a0
++#define src a1
++#define result v0
++
++/* Internal variable */
++#define data t0
++#define data1 t1
++#define has_nul t2
++#define diff t3
++#define syndrome t4
++#define zeroones t5
++#define sevenf t6
++#define pos t7
++#define dest_backup t8
++#define tmp1 a4
++#define tmp2 a5
++#define tmp3 a6
++#define dest_off a2
++#define src_off a3
++#define tmp4 a7
++
++/* rd <- if rc then ra else rb
++ tmp3 will be destroyed. */
++#define CONDITIONSEL(rd, rc, ra, rb)\
++ masknez tmp3, rb, rc;\
++ maskeqz rd, ra, rc;\
++ or rd, rd, tmp3
++
++/* int strcpy (const char *s1, const char *s2); */
++LEAF(strcpy)
++ .align 4
++
++ move dest_backup, dest
++ lu12i.w zeroones, 0x01010
++ lu12i.w sevenf, 0x7f7f7
++ ori zeroones, zeroones, 0x101
++ ori sevenf, sevenf, 0xf7f
++ bstrins.d zeroones, zeroones, 63, 32
++ bstrins.d sevenf, sevenf, 63, 32
++ andi src_off, src, 0x7
++ beqz src_off, strcpy_loop_aligned_1
++ b strcpy_mutual_align
++strcpy_loop_aligned:
++ st.d data, dest, 0
++ addi.d dest, dest, 8
++strcpy_loop_aligned_1:
++ ld.d data, src, 0
++ addi.d src, src, 8
++strcpy_start_realigned:
++ sub.d tmp1, data, zeroones
++ or tmp2, data, sevenf
++ andn has_nul, tmp1, tmp2
++ beqz has_nul, strcpy_loop_aligned
++
++strcpy_end:
++
++ /* 8 4 2 1 */
++ ctz.d pos, has_nul
++ srli.d pos, pos, 3
++ addi.d pos, pos, 1
++ /* Do 8/4/2/1 strcpy based on pos value.
++ pos value is the number of bytes to be copied
++ the bytes include the final \0 so the max length is 8 and the min length is 1. */
++strcpy_end_8:
++ andi tmp1, pos, 0x8
++ beqz tmp1, strcpy_end_4
++ st.d data, dest, 0
++ move dest, dest_backup
++ jr ra
++strcpy_end_4:
++ andi tmp1, pos, 0x4
++ beqz tmp1, strcpy_end_2
++ st.w data, dest, 0
++ srli.d data, data, 32
++ addi.d dest, dest, 4
++strcpy_end_2:
++ andi tmp1, pos, 0x2
++ beqz tmp1, strcpy_end_1
++ st.h data, dest, 0
++ srli.d data, data, 16
++ addi.d dest, dest, 2
++strcpy_end_1:
++ andi tmp1, pos, 0x1
++ beqz tmp1, strcpy_end_ret
++ st.b data, dest, 0
++strcpy_end_ret:
++ move result, dest_backup
++ jr ra
++
++
++strcpy_mutual_align:
++ /* Check if around src page bound.
++ if not go to page cross ok.
++ if it is, do further check.
++ use tmp2 to accelerate. */
++
++ li.w tmp2, 0xff8
++ andi tmp1, src, 0xff8
++ beq tmp1, tmp2, strcpy_page_cross
++
++strcpy_page_cross_ok:
++ /* Load a misaligned double word and check if has \0
++ If no, do a misaligned double word paste.
++ If yes, calculate the number of avaliable bytes,
++ then jump to 4/2/1 end. */
++ ld.d data, src, 0
++ sub.d tmp1, data, zeroones
++ or tmp2, data, sevenf
++ andn has_nul, tmp1, tmp2
++ bnez has_nul, strcpy_end
++strcpy_mutual_align_finish:
++ /* Before jump back to align loop, make dest/src aligned.
++ This will cause a duplicated paste for several bytes between the first double word and the second double word,
++ but should not bring a problem. */
++ li.w tmp1, 8
++ st.d data, dest, 0
++ sub.d tmp1, tmp1, src_off
++ add.d src, src, tmp1
++ add.d dest, dest, tmp1
++
++ b strcpy_loop_aligned_1
++
++strcpy_page_cross:
++ /*
++ ld.d from aligned address(src & ~0x7).
++ check if high bytes have \0.
++ it not, go back to page cross ok,
++ since the string is supposed to cross the page bound in such situation.
++ if it is, do a srl for data to make it seems like a direct double word from src,
++ then go to 4/2/1 strcpy end.
++
++ tmp4 is 0xffff...ffff mask
++ tmp2 demonstrate the bytes to be masked
++ tmp2 = src_off << 3
++ data = data >> (src_off * 8) | -1 << (64 - src_off * 8)
++ and
++ -1 << (64 - src_off * 8) -> ~(-1 >> (src_off * 8)) */
++
++ li.w tmp1, 0x7
++ andn tmp3, src, tmp1
++ ld.d data, tmp3, 0
++ li.w tmp4, -1
++ slli.d tmp2, src_off, 3
++ srl.d tmp4, tmp4, tmp2
++ srl.d data, data, tmp2
++ nor tmp4, tmp4, zero
++ or data, data, tmp4
++ sub.d tmp1, data, zeroones
++ or tmp2, data, sevenf
++ andn has_nul, tmp1, tmp2
++ beqz has_nul, strcpy_page_cross_ok
++ b strcpy_end
++END(strcpy)
++libc_hidden_builtin_def (strcpy)
+--
+2.33.0
+
diff --git a/6_6-LoongArch-Optimize-string-functions-strlen-strnlen.patch b/6_6-LoongArch-Optimize-string-functions-strlen-strnlen.patch
new file mode 100644
index 0000000..0c1af11
--- /dev/null
+++ b/6_6-LoongArch-Optimize-string-functions-strlen-strnlen.patch
@@ -0,0 +1,255 @@
+From 86290dbec63a9688ab0e0085ab8ab686fa256f18 Mon Sep 17 00:00:00 2001
+From: Xue Liu <liuxue@loongson.cn>
+Date: Sun, 29 Jan 2023 10:25:47 +0800
+Subject: [PATCH 6/6] LoongArch: Optimize string functions strlen, strnlen.
+
+Change-Id: I5df3398f9dbd9ea72c3de14e1e5f7793f6dbd794
+---
+ sysdeps/loongarch/lp64/strlen.S | 102 +++++++++++++++++++++++++
+ sysdeps/loongarch/lp64/strnlen.S | 125 +++++++++++++++++++++++++++++++
+ 2 files changed, 227 insertions(+)
+ create mode 100644 sysdeps/loongarch/lp64/strlen.S
+ create mode 100644 sysdeps/loongarch/lp64/strnlen.S
+
+diff --git a/sysdeps/loongarch/lp64/strlen.S b/sysdeps/loongarch/lp64/strlen.S
+new file mode 100644
+index 00000000..3569598c
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/strlen.S
+@@ -0,0 +1,102 @@
++/* Optimized strlen implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++#include <sys/asm.h>
++
++/* size_t strlen (const char *s1); */
++LEAF(strlen)
++ .align 5
++
++ nor t4, zero, zero
++ lu12i.w a2, 0x01010
++ andi t5, a0, 0x7
++
++ li.w t7, 0x7
++ slli.d t6, t5, 0x3
++ andn t7, a0, t7
++ ld.d a1, t7, 0
++ sub.d t7, zero, t6
++ sll.d t4, t4, t7
++ maskeqz t4, t4, t6
++ srl.d a1, a1, t6
++ or a1, a1, t4
++
++
++ ori a2, a2, 0x101
++ nor t1, a1, zero
++ li.w a4, 8
++
++ bstrins.d a2, a2, 63, 32
++ sub.d a5, a4, t5
++ move t5, a0
++
++ sub.d t0, a1, a2
++ slli.d t4, a2, 7
++ nor a3, zero, t4
++ nor t1, a1, a3
++
++ and t0, t0, t1
++ bnez t0, strlen_count1
++ add.d a0, a0, a5
++strlen_loop:
++ ld.d a1, a0, 0
++ sub.d t0, a1, a2
++ and t1, t0, t4
++ bnez t1, strlen_count_pre
++ ld.d a1, a0, 8
++ sub.d t0, a1, a2
++ and t1, t0, t4
++ addi.d a0, a0, 16
++ beqz t1, strlen_loop
++strlen_count:
++ addi.d a0, a0, -8
++strlen_count_pre:
++ nor t1, a1, a3
++ and t0, t0, t1
++ beqz t0, strlen_noascii_start
++strlen_count1:
++ ctz.d t1, t0
++ sub.d v0, a0, t5
++ srli.w t1, t1, 3
++ add.d v0, v0, t1
++ jr ra
++strlen_noascii_start:
++ addi.d a0, a0, 8
++strlen_loop_noascii:
++ ld.d a1, a0, 0
++ sub.d t0, a1, a2
++ nor t1, a1, a3
++ and t0, t0, t1
++ bnez t0, strlen_count1
++ ld.d a1, a0, 8
++ sub.d t0, a1, a2
++ nor t1, a1, a3
++ and t0, t0, t1
++ addi.d a0, a0, 16
++ beqz t0, strlen_loop_noascii
++ addi.d a0, a0, -8
++ ctz.d t1, t0
++ sub.d v0, a0, t5
++ srli.w t1, t1, 3
++ add.d v0, v0, t1
++ jr ra
++END(strlen)
++
++libc_hidden_builtin_def (strlen)
++
+diff --git a/sysdeps/loongarch/lp64/strnlen.S b/sysdeps/loongarch/lp64/strnlen.S
+new file mode 100644
+index 00000000..8eaa60e2
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/strnlen.S
+@@ -0,0 +1,125 @@
++/* Optimized strlen implementation for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sys/asm.h>
++
++/* rd <- if rc then ra else rb
++ a5 will be destroyed. */
++#define CONDITIONSEL(rd, ra, rb, rc)\
++ masknez a5, rb, rc;\
++ maskeqz rd, ra, rc;\
++ or rd, rd, a5
++
++/* Parameters and Results */
++#define srcin a0
++#define limit a1
++#define len v0
++
++/* Internal variable */
++#define data1 t0
++#define data2 t1
++#define has_nul1 t2
++#define has_nul2 t3
++#define src t4
++#define zeroones t5
++#define sevenf t6
++#define data2a t7
++#define tmp6 t7
++#define pos t8
++#define tmp1 a2
++#define tmp2 a3
++#define tmp3 a4
++#define tmp4 a5
++#define tmp5 a6
++#define limit_wd a7
++
++/* size_t strnlen (const char *s1,size_t maxlen); */
++LEAF(__strnlen)
++ .align 4
++ beqz limit, _hit_limit
++ lu12i.w zeroones, 0x01010
++ lu12i.w sevenf, 0x7f7f7
++ ori zeroones, zeroones, 0x101
++ ori sevenf, sevenf, 0xf7f
++ bstrins.d zeroones, zeroones, 63, 32
++ bstrins.d sevenf, sevenf, 63, 32
++ andi tmp1, srcin, 15
++ sub.d src, srcin, tmp1
++ bnez tmp1, misaligned
++ addi.d limit_wd, limit, -1
++ srli.d limit_wd, limit_wd, 4
++_loop:
++ ld.d data1, src, 0
++ ld.d data2, src, 8
++ addi.d src, src, 16
++_realigned:
++ sub.d tmp1, data1, zeroones
++ or tmp2, data1, sevenf
++ sub.d tmp3, data2, zeroones
++ or tmp4, data2, sevenf
++ andn has_nul1, tmp1, tmp2
++ andn has_nul2, tmp3, tmp4
++ addi.d limit_wd, limit_wd, -1
++ srli.d tmp1, limit_wd, 63
++ or tmp2, has_nul1, has_nul2
++ or tmp3, tmp1, tmp2
++ beqz tmp3, _loop
++ beqz tmp2, _hit_limit
++ sub.d len, src, srcin
++ beqz has_nul1, _nul_in_data2
++ move has_nul2, has_nul1
++ addi.d len, len, -8
++_nul_in_data2:
++ ctz.d pos, has_nul2
++ srli.d pos, pos, 3
++ addi.d len, len, -8
++ add.d len, len, pos
++ sltu tmp1, len, limit
++ CONDITIONSEL(len, len, limit, tmp1)
++ jr ra
++
++misaligned:
++ addi.d limit_wd, limit, -1
++ sub.d tmp4, zero, tmp1
++ andi tmp3, limit_wd, 15
++ srli.d limit_wd, limit_wd, 4
++ li.d tmp5, -1
++ ld.d data1, src, 0
++ ld.d data2, src, 8
++ addi.d src, src, 16
++ slli.d tmp4, tmp4, 3
++ add.d tmp3, tmp3, tmp1
++ srl.d tmp2, tmp5, tmp4
++ srli.d tmp3, tmp3, 4
++ add.d limit_wd, limit_wd, tmp3
++ or data1, data1, tmp2
++ or data2a, data2, tmp2
++ li.w tmp3, 9
++ sltu tmp1, tmp1, tmp3
++ CONDITIONSEL(data1, data1, tmp5, tmp1)
++ CONDITIONSEL(data2, data2, data2a, tmp1)
++ b _realigned
++
++_hit_limit:
++ move len, limit
++ jr ra
++END(__strnlen)
++
++weak_alias (__strnlen, strnlen)
++libc_hidden_def (strnlen)
++libc_hidden_def (__strnlen)
+--
+2.33.0
+
diff --git a/AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch b/AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch
new file mode 100644
index 0000000..1c41ca3
--- /dev/null
+++ b/AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch
@@ -0,0 +1,55 @@
+From e5fa62b8db546f8792ec9e5c61e6419f4f8e3f4d Mon Sep 17 00:00:00 2001
+From: Wilco Dijkstra <wdijkstr@arm.com>
+Date: Thu, 6 Jan 2022 14:36:28 +0000
+Subject: [PATCH] AArch64: Check for SVE in ifuncs [BZ #28744]
+
+Add a check for SVE in the A64FX ifuncs for memcpy, memset and memmove.
+This fixes BZ #28744.
+---
+ sysdeps/aarch64/multiarch/memcpy.c | 2 +-
+ sysdeps/aarch64/multiarch/memmove.c | 2 +-
+ sysdeps/aarch64/multiarch/memset.c | 2 +-
+ 3 files changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c
+index 7dac7b7..a476dd5 100644
+--- a/sysdeps/aarch64/multiarch/memcpy.c
++++ b/sysdeps/aarch64/multiarch/memcpy.c
+@@ -48,7 +48,7 @@ libc_ifunc (__libc_memcpy,
+ || IS_NEOVERSE_V1 (midr)
+ ? __memcpy_simd
+ # if HAVE_AARCH64_SVE_ASM
+- : (IS_A64FX (midr)
++ : (IS_A64FX (midr) && sve
+ ? __memcpy_a64fx
+ : __memcpy_generic))))));
+ # else
+diff --git a/sysdeps/aarch64/multiarch/memmove.c b/sysdeps/aarch64/multiarch/memmove.c
+index 48f8e46..4f7d7ee 100644
+--- a/sysdeps/aarch64/multiarch/memmove.c
++++ b/sysdeps/aarch64/multiarch/memmove.c
+@@ -48,7 +48,7 @@ libc_ifunc (__libc_memmove,
+ || IS_NEOVERSE_V1 (midr)
+ ? __memmove_simd
+ # if HAVE_AARCH64_SVE_ASM
+- : (IS_A64FX (midr)
++ : (IS_A64FX (midr) && sve
+ ? __memmove_a64fx
+ : __memmove_generic))))));
+ # else
+diff --git a/sysdeps/aarch64/multiarch/memset.c b/sysdeps/aarch64/multiarch/memset.c
+index 3692b07..c4008f3 100644
+--- a/sysdeps/aarch64/multiarch/memset.c
++++ b/sysdeps/aarch64/multiarch/memset.c
+@@ -44,7 +44,7 @@ libc_ifunc (__libc_memset,
+ : (IS_EMAG (midr) && zva_size == 64
+ ? __memset_emag
+ # if HAVE_AARCH64_SVE_ASM
+- : (IS_A64FX (midr)
++ : (IS_A64FX (midr) && sve
+ ? __memset_a64fx
+ : __memset_generic))));
+ # else
+--
+1.8.3.1
+
diff --git a/AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch b/AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch
new file mode 100644
index 0000000..f7ce84d
--- /dev/null
+++ b/AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch
@@ -0,0 +1,39 @@
+From 23777232c23f80809613bdfa329f63aadf992922 Mon Sep 17 00:00:00 2001
+From: Naohiro Tamura via Libc-alpha <libc-alpha@sourceware.org>
+Date: Fri, 27 Aug 2021 05:03:04 +0000
+Subject: [PATCH] AArch64: Update A64FX memset not to degrade at 16KB
+
+This patch updates unroll8 code so as not to degrade at the peak
+performance 16KB for both FX1000 and FX700.
+
+Inserted 2 instructions at the beginning of the unroll8 loop,
+cmp and branch, are a workaround that is found heuristically.
+
+Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
+---
+ sysdeps/aarch64/multiarch/memset_a64fx.S | 9 ++++++++-
+ 1 file changed, 8 insertions(+), 1 deletion(-)
+
+diff --git a/sysdeps/aarch64/multiarch/memset_a64fx.S b/sysdeps/aarch64/multiarch/memset_a64fx.S
+index 7bf759b..f7dfdaa 100644
+--- a/sysdeps/aarch64/multiarch/memset_a64fx.S
++++ b/sysdeps/aarch64/multiarch/memset_a64fx.S
+@@ -96,7 +96,14 @@ L(vl_agnostic): // VL Agnostic
+ L(unroll8):
+ sub count, count, tmp1
+ .p2align 4
+-1: st1b_unroll 0, 7
++ // The 2 instructions at the beginning of the following loop,
++ // cmp and branch, are a workaround so as not to degrade at
++ // the peak performance 16KB.
++ // It is found heuristically and the branch condition, b.ne,
++ // is chosen intentionally never to jump.
++1: cmp xzr, xzr
++ b.ne 1b
++ st1b_unroll 0, 7
+ add dst, dst, tmp1
+ subs count, count, tmp1
+ b.hi 1b
+--
+1.8.3.1
+
diff --git a/Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch b/Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch
new file mode 100644
index 0000000..a11a56e
--- /dev/null
+++ b/Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch
@@ -0,0 +1,216 @@
+From 98149b16d645e9644a8e9b3d1f4b7932b9b193c5 Mon Sep 17 00:00:00 2001
+From: Joseph Myers <joseph@codesourcery.com>
+Date: Mon, 9 Aug 2021 16:51:38 +0000
+Subject: [PATCH] Add PTRACE_GET_RSEQ_CONFIGURATION from Linux 5.13 to
+ sys/ptrace.h
+
+Linux 5.13 adds a PTRACE_GET_RSEQ_CONFIGURATION constant, with an
+associated ptrace_rseq_configuration structure.
+
+Add this constant to the various sys/ptrace.h headers in glibc, with
+the structure in bits/ptrace-shared.h (named struct
+__ptrace_rseq_configuration in glibc, as with other such structures).
+
+Tested for x86_64, and with build-many-glibcs.py.
+
+---
+ sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h | 7 ++++++-
+ sysdeps/unix/sysv/linux/arm/sys/ptrace.h | 6 +++++-
+ sysdeps/unix/sysv/linux/bits/ptrace-shared.h | 10 ++++++++++
+ sysdeps/unix/sysv/linux/ia64/sys/ptrace.h | 6 +++++-
+ sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h | 7 ++++++-
+ sysdeps/unix/sysv/linux/s390/sys/ptrace.h | 5 +++++
+ sysdeps/unix/sysv/linux/sparc/sys/ptrace.h | 6 +++++-
+ sysdeps/unix/sysv/linux/sys/ptrace.h | 6 +++++-
+ sysdeps/unix/sysv/linux/x86/sys/ptrace.h | 6 +++++-
+ 9 files changed, 52 insertions(+), 7 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h
+index af8193cbe7b2..1fae1dce9c6a 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/aarch64/sys/ptrace.h
+@@ -58,6 +58,7 @@ __BEGIN_DECLS
+ #undef PTRACE_SECCOMP_GET_FILTER
+ #undef PTRACE_SECCOMP_GET_METADATA
+ #undef PTRACE_GET_SYSCALL_INFO
++#undef PTRACE_GET_RSEQ_CONFIGURATION
+
+ /* Type of the REQUEST argument to `ptrace.' */
+ enum __ptrace_request
+@@ -190,8 +191,12 @@ enum __ptrace_request
+ #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA
+
+ /* Get information about system call. */
+- PTRACE_GET_SYSCALL_INFO = 0x420e
++ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
++
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
+ };
+
+
+diff --git a/sysdeps/unix/sysv/linux/arm/sys/ptrace.h b/sysdeps/unix/sysv/linux/arm/sys/ptrace.h
+index cdb1f159a7c1..2e3843664855 100644
+--- a/sysdeps/unix/sysv/linux/arm/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/arm/sys/ptrace.h
+@@ -200,8 +200,12 @@ enum __ptrace_request
+ #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA
+
+ /* Get information about system call. */
+- PTRACE_GET_SYSCALL_INFO = 0x420e
++ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
++
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
+ };
+
+
+diff --git a/sysdeps/unix/sysv/linux/bits/ptrace-shared.h b/sysdeps/unix/sysv/linux/bits/ptrace-shared.h
+index 7d40634da55e..7e95ca7082e9 100644
+--- a/sysdeps/unix/sysv/linux/bits/ptrace-shared.h
++++ b/sysdeps/unix/sysv/linux/bits/ptrace-shared.h
+@@ -120,6 +120,16 @@ struct __ptrace_syscall_info
+ };
+ };
+
++/* Results of PTRACE_GET_RSEQ_CONFIGURATION. */
++struct __ptrace_rseq_configuration
++{
++ __uint64_t rseq_abi_pointer;
++ __uint32_t rseq_abi_size;
++ __uint32_t signature;
++ __uint32_t flags;
++ __uint32_t pad;
++};
++
+ /* Perform process tracing functions. REQUEST is one of the values
+ above, and determines the action to be taken.
+ For all requests except PTRACE_TRACEME, PID specifies the process to be
+diff --git a/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h b/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h
+index bea975bb9e3d..536a0cafbd1b 100644
+--- a/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/ia64/sys/ptrace.h
+@@ -153,8 +153,12 @@ enum __ptrace_request
+ #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA
+
+ /* Get information about system call. */
+- PTRACE_GET_SYSCALL_INFO = 0x420e
++ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
++
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
+ };
+
+
+diff --git a/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h b/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h
+index 032c91e81791..fb599af6da64 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/powerpc/sys/ptrace.h
+@@ -36,6 +36,7 @@ __BEGIN_DECLS
+ # undef PTRACE_GETREGS
+ # undef PTRACE_GETREGS64
+ # undef PTRACE_GETREGSET
++# undef PTRACE_GET_RSEQ_CONFIGURATION
+ # undef PTRACE_GETSIGINFO
+ # undef PTRACE_GETSIGMASK
+ # undef PTRACE_GET_SYSCALL_INFO
+@@ -260,8 +261,12 @@ enum __ptrace_request
+ #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA
+
+ /* Get information about system call. */
+- PTRACE_GET_SYSCALL_INFO = 0x420e
++ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
++
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
+ };
+
+
+diff --git a/sysdeps/unix/sysv/linux/s390/sys/ptrace.h b/sysdeps/unix/sysv/linux/s390/sys/ptrace.h
+index 4f3c65726f61..3ddd2e426789 100644
+--- a/sysdeps/unix/sysv/linux/s390/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/s390/sys/ptrace.h
+@@ -86,6 +86,7 @@ __BEGIN_DECLS
+ # undef PTRACE_SYSCALL_INFO_ENTRY
+ # undef PTRACE_SYSCALL_INFO_EXIT
+ # undef PTRACE_SYSCALL_INFO_SECCOMP
++# undef PTRACE_GET_RSEQ_CONFIGURATION
+ #endif
+ /* Type of the REQUEST argument to `ptrace.' */
+ enum __ptrace_request
+@@ -217,6 +218,10 @@ enum __ptrace_request
+ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
+
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f,
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
++
+ PTRACE_PEEKUSR_AREA = 0x5000,
+ #define PTRACE_PEEKUSR_AREA PTRACE_PEEKUSR_AREA
+
+diff --git a/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h b/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h
+index 3f6150028487..773b4379249c 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/sparc/sys/ptrace.h
+@@ -221,8 +221,12 @@ enum __ptrace_request
+ #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA
+
+ /* Get information about system call. */
+- PTRACE_GET_SYSCALL_INFO = 0x420e
++ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
++
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
+ };
+
+
+diff --git a/sysdeps/unix/sysv/linux/sys/ptrace.h b/sysdeps/unix/sysv/linux/sys/ptrace.h
+index dc76e97ea72a..404fc3ddb7b5 100644
+--- a/sysdeps/unix/sysv/linux/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/sys/ptrace.h
+@@ -170,8 +170,12 @@ enum __ptrace_request
+ #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA
+
+ /* Get information about system call. */
+- PTRACE_GET_SYSCALL_INFO = 0x420e
++ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
++
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
+ };
+
+
+diff --git a/sysdeps/unix/sysv/linux/x86/sys/ptrace.h b/sysdeps/unix/sysv/linux/x86/sys/ptrace.h
+index 8501cc22ed7b..7202a09eefd3 100644
+--- a/sysdeps/unix/sysv/linux/x86/sys/ptrace.h
++++ b/sysdeps/unix/sysv/linux/x86/sys/ptrace.h
+@@ -190,8 +190,12 @@ enum __ptrace_request
+ #define PTRACE_SECCOMP_GET_METADATA PTRACE_SECCOMP_GET_METADATA
+
+ /* Get information about system call. */
+- PTRACE_GET_SYSCALL_INFO = 0x420e
++ PTRACE_GET_SYSCALL_INFO = 0x420e,
+ #define PTRACE_GET_SYSCALL_INFO PTRACE_GET_SYSCALL_INFO
++
++ /* Get rseq configuration information. */
++ PTRACE_GET_RSEQ_CONFIGURATION = 0x420f
++#define PTRACE_GET_RSEQ_CONFIGURATION PTRACE_GET_RSEQ_CONFIGURATION
+ };
+
+
+--
+2.27.0
+
diff --git a/Assume-only-FLAG_ELF_LIBC6-suport.patch b/Assume-only-FLAG_ELF_LIBC6-suport.patch
new file mode 100644
index 0000000..dbc9199
--- /dev/null
+++ b/Assume-only-FLAG_ELF_LIBC6-suport.patch
@@ -0,0 +1,658 @@
+From 8ee878592c4a642937152c8308b8faef86bcfc40 Mon Sep 17 00:00:00 2001
+From: "Lucas A. M. Magalhaes" <lamm@linux.ibm.com>
+Date: Thu, 14 Jul 2022 14:37:22 -0300
+Subject: [PATCH] Assume only FLAG_ELF_LIBC6 suport
+
+The older libc versions are obsolete for over twenty years now.
+This patch removes the special flags for libc5 and libc4 and assumes
+that all libraries cached are libc6 compatible and use FLAG_ELF_LIBC6.
+
+Checked with a build for all affected architectures.
+
+Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ elf/cache.c | 6 +-
+ elf/ldconfig.c | 63 ++-----------------
+ elf/readelflib.c | 46 ++------------
+ elf/readlib.c | 25 +-------
+ sysdeps/unix/sysv/linux/aarch64/ldconfig.h | 30 ---------
+ sysdeps/unix/sysv/linux/arc/ldconfig.h | 27 --------
+ sysdeps/unix/sysv/linux/arm/ldconfig.h | 25 --------
+ sysdeps/unix/sysv/linux/csky/ldconfig.h | 34 ----------
+ sysdeps/unix/sysv/linux/i386/ldconfig.h | 6 --
+ sysdeps/unix/sysv/linux/ia64/ldconfig.h | 24 -------
+ sysdeps/unix/sysv/linux/m68k/ldconfig.h | 1 -
+ .../unix/sysv/linux/mips/mips64/ldconfig.h | 25 --------
+ sysdeps/unix/sysv/linux/powerpc/ldconfig.h | 27 --------
+ sysdeps/unix/sysv/linux/riscv/ldconfig.h | 36 -----------
+ sysdeps/unix/sysv/linux/s390/ldconfig.h | 7 ---
+ sysdeps/unix/sysv/linux/x86_64/ldconfig.h | 26 --------
+ 16 files changed, 14 insertions(+), 394 deletions(-)
+ delete mode 100644 sysdeps/unix/sysv/linux/aarch64/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/arc/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/arm/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/csky/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/ia64/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/m68k/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/mips/mips64/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/powerpc/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/riscv/ldconfig.h
+ delete mode 100644 sysdeps/unix/sysv/linux/x86_64/ldconfig.h
+
+diff --git a/elf/cache.c b/elf/cache.c
+index 3d7d3a67bf..f5f3ef8c4d 100644
+--- a/elf/cache.c
++++ b/elf/cache.c
+@@ -157,6 +157,7 @@ struct cache_entry
+ /* List of all cache entries. */
+ static struct cache_entry *entries;
+
++/* libc4, ELF and libc5 are unsupported. */
+ static const char *flag_descr[] =
+ { "libc4", "ELF", "libc5", "libc6"};
+
+@@ -168,14 +169,11 @@ print_entry (const char *lib, int flag, uint64_t hwcap,
+ printf ("\t%s (", lib);
+ switch (flag & FLAG_TYPE_MASK)
+ {
+- case FLAG_LIBC4:
+- case FLAG_ELF:
+- case FLAG_ELF_LIBC5:
+ case FLAG_ELF_LIBC6:
+ fputs (flag_descr[flag & FLAG_TYPE_MASK], stdout);
+ break;
+ default:
+- fputs (_("unknown"), stdout);
++ fputs (_("unknown or unsupported flag"), stdout);
+ break;
+ }
+ switch (flag & FLAG_REQUIRED_MASK)
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index 9394ac6438..6f37f38f35 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -65,19 +65,6 @@
+
+ #define PACKAGE _libc_intl_domainname
+
+-static const struct
+-{
+- const char *name;
+- int flag;
+-} lib_types[] =
+-{
+- {"libc4", FLAG_LIBC4},
+- {"libc5", FLAG_ELF_LIBC5},
+- {"libc6", FLAG_ELF_LIBC6},
+- {"glibc2", FLAG_ELF_LIBC6}
+-};
+-
+-
+ /* List of directories to handle. */
+ struct dir_entry
+ {
+@@ -469,27 +456,8 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
+ entry->from_file = strdup (from_file);
+ entry->from_line = from_line;
+
+- /* Search for an '=' sign. */
+ entry->path = xstrdup (line);
+- char *equal_sign = strchr (entry->path, '=');
+- if (equal_sign)
+- {
+- *equal_sign = '\0';
+- ++equal_sign;
+- entry->flag = FLAG_ANY;
+- for (i = 0; i < sizeof (lib_types) / sizeof (lib_types[0]); ++i)
+- if (strcmp (equal_sign, lib_types[i].name) == 0)
+- {
+- entry->flag = lib_types[i].flag;
+- break;
+- }
+- if (entry->flag == FLAG_ANY)
+- error (0, 0, _("%s is not a known library type"), equal_sign);
+- }
+- else
+- {
+- entry->flag = FLAG_ANY;
+- }
++ entry->flag = FLAG_ELF_LIBC6;
+
+ /* Canonify path: for now only remove leading and trailing
+ whitespace and the trailing slashes. */
+@@ -1054,23 +1022,11 @@ search_dir (const struct dir_entry *entry)
+ soname = xstrdup (direntry->d_name);
+ }
+
+- if (flag == FLAG_ELF
+- && (entry->flag == FLAG_ELF_LIBC5
+- || entry->flag == FLAG_ELF_LIBC6))
+- flag = entry->flag;
+-
+ /* Some sanity checks to print warnings. */
+ if (opt_verbose)
+ {
+- if (flag == FLAG_ELF_LIBC5 && entry->flag != FLAG_ELF_LIBC5
+- && entry->flag != FLAG_ANY)
+- error (0, 0, _("libc5 library %s in wrong directory"), file_name);
+- if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6
+- && entry->flag != FLAG_ANY)
++ if (flag == FLAG_ELF_LIBC6 && entry->flag != FLAG_ELF_LIBC6)
+ error (0, 0, _("libc6 library %s in wrong directory"), file_name);
+- if (flag == FLAG_LIBC4 && entry->flag != FLAG_LIBC4
+- && entry->flag != FLAG_ANY)
+- error (0, 0, _("libc4 library %s in wrong directory"), file_name);
+ }
+
+ /* Add library to list. */
+@@ -1089,19 +1045,8 @@ search_dir (const struct dir_entry *entry)
+ /* It's newer - add it. */
+ /* Flag should be the same - sanity check. */
+ if (dlib_ptr->flag != flag)
+- {
+- if (dlib_ptr->flag == FLAG_ELF
+- && (flag == FLAG_ELF_LIBC5 || flag == FLAG_ELF_LIBC6))
+- dlib_ptr->flag = flag;
+- else if ((dlib_ptr->flag == FLAG_ELF_LIBC5
+- || dlib_ptr->flag == FLAG_ELF_LIBC6)
+- && flag == FLAG_ELF)
+- dlib_ptr->flag = flag;
+- else
+- error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
+- dlib_ptr->name, direntry->d_name,
+- entry->path);
+- }
++ error (0, 0, _("libraries %s and %s in directory %s have same soname but different type."),
++ dlib_ptr->name, direntry->d_name, entry->path);
+ free (dlib_ptr->name);
+ dlib_ptr->name = xstrdup (direntry->d_name);
+ dlib_ptr->is_link = is_link;
+diff --git a/elf/readelflib.c b/elf/readelflib.c
+index 771182b5d0..5f43e0230d 100644
+--- a/elf/readelflib.c
++++ b/elf/readelflib.c
+@@ -44,7 +44,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
+ char **soname, void *file_contents, size_t file_length)
+ {
+ int i;
+- unsigned int j;
+ unsigned int dynamic_addr;
+ size_t dynamic_size;
+ char *program_interpreter;
+@@ -81,9 +80,8 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
+ elf_pheader = (ElfW(Phdr) *) (elf_header->e_phoff + file_contents);
+ check_ptr (elf_pheader);
+
+- /* The library is an elf library, now search for soname and
+- libc5/libc6. */
+- *flag = FLAG_ELF;
++ /* The library is an elf library. */
++ *flag = FLAG_ELF_LIBC6;
+
+ /* The default ISA level is 0. */
+ *isa_level = 0;
+@@ -110,16 +108,6 @@ process_elf_file (const char *file_name, const char *lib, int *flag,
+ program_interpreter = (char *) (file_contents + segment->p_offset);
+ check_ptr (program_interpreter);
+
+- /* Check if this is enough to classify the binary. */
+- for (j = 0; j < sizeof (interpreters) / sizeof (interpreters [0]);
+- ++j)
+- if (strcmp (program_interpreter, interpreters[j].soname) == 0)
+- {
+- *flag = interpreters[j].flag;
+- break;
+- }
+- break;
+-
+ case PT_NOTE:
+ if (!*osversion && segment->p_filesz >= 32 && segment->p_align >= 4)
+ {
+@@ -244,38 +232,16 @@ done:
+ if (dynamic_strings == NULL)
+ return 1;
+
+- /* Now read the DT_NEEDED and DT_SONAME entries. */
++ /* Now read the DT_SONAME entries. */
+ for (dyn_entry = dynamic_segment; dyn_entry->d_tag != DT_NULL;
+ ++dyn_entry)
+ {
+- if (dyn_entry->d_tag == DT_NEEDED || dyn_entry->d_tag == DT_SONAME)
++ if (dyn_entry->d_tag == DT_SONAME)
+ {
+ char *name = dynamic_strings + dyn_entry->d_un.d_val;
+ check_ptr (name);
+-
+- if (dyn_entry->d_tag == DT_NEEDED)
+- {
+-
+- if (*flag == FLAG_ELF)
+- {
+- /* Check if this is enough to classify the binary. */
+- for (j = 0;
+- j < sizeof (known_libs) / sizeof (known_libs [0]);
+- ++j)
+- if (strcmp (name, known_libs [j].soname) == 0)
+- {
+- *flag = known_libs [j].flag;
+- break;
+- }
+- }
+- }
+-
+- else if (dyn_entry->d_tag == DT_SONAME)
+- *soname = xstrdup (name);
+-
+- /* Do we have everything we need? */
+- if (*soname && *flag != FLAG_ELF)
+- return 0;
++ *soname = xstrdup (name);
++ return 0;
+ }
+ }
+
+diff --git a/elf/readlib.c b/elf/readlib.c
+index ed42fbd48e..be65e3d0e9 100644
+--- a/elf/readlib.c
++++ b/elf/readlib.c
+@@ -43,24 +43,6 @@ struct known_names
+ int flag;
+ };
+
+-static struct known_names interpreters[] =
+-{
+- { "/lib/" LD_SO, FLAG_ELF_LIBC6 },
+-#ifdef SYSDEP_KNOWN_INTERPRETER_NAMES
+- SYSDEP_KNOWN_INTERPRETER_NAMES
+-#endif
+-};
+-
+-static struct known_names known_libs[] =
+-{
+- { LIBC_SO, FLAG_ELF_LIBC6 },
+- { LIBM_SO, FLAG_ELF_LIBC6 },
+-#ifdef SYSDEP_KNOWN_LIBRARY_NAMES
+- SYSDEP_KNOWN_LIBRARY_NAMES
+-#endif
+-};
+-
+-
+ /* Check if string corresponds to a GDB Python file. */
+ static bool
+ is_gdb_python_file (const char *name)
+@@ -83,7 +65,8 @@ process_file (const char *real_file_name, const char *file_name,
+ struct exec *aout_header;
+
+ ret = 0;
+- *flag = FLAG_ANY;
++ /* Just set FLAG_ELF_LIBC6 as old formats are not supported anymore. */
++ *flag = FLAG_ELF_LIBC6;
+ *soname = NULL;
+
+ file = fopen (real_file_name, "rb");
+@@ -150,7 +133,6 @@ process_file (const char *real_file_name, const char *file_name,
+ *dot = '\0';
+ }
+ *soname = copy;
+- *flag = FLAG_LIBC4;
+ goto done;
+ }
+
+@@ -191,9 +173,6 @@ implicit_soname (const char *lib, int flag)
+ {
+ char *soname = xstrdup (lib);
+
+- if ((flag & FLAG_TYPE_MASK) != FLAG_LIBC4)
+- return soname;
+-
+ /* Aout files don't have a soname, just return the name
+ including the major number. */
+ char *major = strstr (soname, ".so.");
+diff --git a/sysdeps/unix/sysv/linux/aarch64/ldconfig.h b/sysdeps/unix/sysv/linux/aarch64/ldconfig.h
+deleted file mode 100644
+index 5cbfb32714..0000000000
+--- a/sysdeps/unix/sysv/linux/aarch64/ldconfig.h
++++ /dev/null
+@@ -1,30 +0,0 @@
+-/* Copyright (C) 2009-2021 Free Software Foundation, Inc.
+-
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public License as
+- published by the Free Software Foundation; either version 2.1 of the
+- License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld-linux-aarch64.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld-linux-aarch64_be.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld-linux-aarch64_ilp32.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld-linux-aarch64_be_ilp32.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld-linux.so.3", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld-linux-armhf.so.3", FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/arc/ldconfig.h b/sysdeps/unix/sysv/linux/arc/ldconfig.h
+deleted file mode 100644
+index f673170e59..0000000000
+--- a/sysdeps/unix/sysv/linux/arc/ldconfig.h
++++ /dev/null
+@@ -1,27 +0,0 @@
+-/* ldconfig default paths and libraries. Linux/RISC-V version.
+- Copyright (C) 2020-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld-linux-arc.so.2", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld-linux-arceb.so.2", FLAG_ELF_LIBC6 },
+-
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/arm/ldconfig.h b/sysdeps/unix/sysv/linux/arm/ldconfig.h
+deleted file mode 100644
+index d1253993ea..0000000000
+--- a/sysdeps/unix/sysv/linux/arm/ldconfig.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld-linux.so.3", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld-linux-armhf.so.3", FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/csky/ldconfig.h b/sysdeps/unix/sysv/linux/csky/ldconfig.h
+deleted file mode 100644
+index fbe17e3dc8..0000000000
+--- a/sysdeps/unix/sysv/linux/csky/ldconfig.h
++++ /dev/null
+@@ -1,34 +0,0 @@
+-/* ldconfig default paths and libraries. Linux/C-SKY version.
+- Copyright (C) 2018-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define LD_SO_PREFIX "/lib/ld-linux-"
+-#define LD_SO_SUFFIX ".so.1"
+-
+-#ifdef __CSKY_HARD_FLOAT__
+-# define LD_SO_ABI "cskyv2-hf"
+-#else
+-# define LD_SO_ABI "cskyv2"
+-#endif
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { LD_SO_PREFIX LD_SO_ABI LD_SO_SUFFIX, FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/i386/ldconfig.h b/sysdeps/unix/sysv/linux/i386/ldconfig.h
+index bafbec1231..9afda09cca 100644
+--- a/sysdeps/unix/sysv/linux/i386/ldconfig.h
++++ b/sysdeps/unix/sysv/linux/i386/ldconfig.h
+@@ -16,9 +16,3 @@
+ <https://www.gnu.org/licenses/>. */
+
+ #include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld-linux.so.1", FLAG_ELF_LIBC5 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.5", FLAG_ELF_LIBC5 }, \
+- { "libm.so.5", FLAG_ELF_LIBC5 },
+diff --git a/sysdeps/unix/sysv/linux/ia64/ldconfig.h b/sysdeps/unix/sysv/linux/ia64/ldconfig.h
+deleted file mode 100644
+index 4731419bf8..0000000000
+--- a/sysdeps/unix/sysv/linux/ia64/ldconfig.h
++++ /dev/null
+@@ -1,24 +0,0 @@
+-/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/m68k/ldconfig.h b/sysdeps/unix/sysv/linux/m68k/ldconfig.h
+deleted file mode 100644
+index 953f192bcd..0000000000
+--- a/sysdeps/unix/sysv/linux/m68k/ldconfig.h
++++ /dev/null
+@@ -1 +0,0 @@
+-#include <sysdeps/unix/sysv/linux/i386/ldconfig.h>
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/ldconfig.h b/sysdeps/unix/sysv/linux/mips/mips64/ldconfig.h
+deleted file mode 100644
+index ac82941aff..0000000000
+--- a/sysdeps/unix/sysv/linux/mips/mips64/ldconfig.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib32/ld.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib64/ld.so.1", FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/powerpc/ldconfig.h b/sysdeps/unix/sysv/linux/powerpc/ldconfig.h
+deleted file mode 100644
+index 1d70657838..0000000000
+--- a/sysdeps/unix/sysv/linux/powerpc/ldconfig.h
++++ /dev/null
+@@ -1,27 +0,0 @@
+-/* ldconfig default paths and libraries. Linux/PowerPC version.
+- Copyright (C) 2002-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib64/ld64.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib64/ld64.so.2", FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/riscv/ldconfig.h b/sysdeps/unix/sysv/linux/riscv/ldconfig.h
+deleted file mode 100644
+index e3847f116e..0000000000
+--- a/sysdeps/unix/sysv/linux/riscv/ldconfig.h
++++ /dev/null
+@@ -1,36 +0,0 @@
+-/* ldconfig default paths and libraries. Linux/RISC-V version.
+- Copyright (C) 2001-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define LD_SO_PREFIX "/lib/ld-linux-"
+-#define LD_SO_SUFFIX ".so.1"
+-
+-#if __riscv_xlen == 64
+-# define LD_SO_ABI "riscv64-lp64"
+-#else
+-# define LD_SO_ABI "riscv32-ilp32"
+-#endif
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { LD_SO_PREFIX LD_SO_ABI "d" LD_SO_SUFFIX, FLAG_ELF_LIBC6 }, \
+- { LD_SO_PREFIX LD_SO_ABI LD_SO_SUFFIX, FLAG_ELF_LIBC6 },
+-
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/s390/ldconfig.h b/sysdeps/unix/sysv/linux/s390/ldconfig.h
+index f564a6eaf6..9afda09cca 100644
+--- a/sysdeps/unix/sysv/linux/s390/ldconfig.h
++++ b/sysdeps/unix/sysv/linux/s390/ldconfig.h
+@@ -16,10 +16,3 @@
+ <https://www.gnu.org/licenses/>. */
+
+ #include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld.so.1", FLAG_ELF_LIBC6 }, \
+- { "/lib/ld64.so.1", FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/x86_64/ldconfig.h b/sysdeps/unix/sysv/linux/x86_64/ldconfig.h
+deleted file mode 100644
+index b67203e017..0000000000
+--- a/sysdeps/unix/sysv/linux/x86_64/ldconfig.h
++++ /dev/null
+@@ -1,26 +0,0 @@
+-/* Copyright (C) 2001-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <sysdeps/generic/ldconfig.h>
+-
+-#define SYSDEP_KNOWN_INTERPRETER_NAMES \
+- { "/lib/ld-linux.so.2", FLAG_ELF_LIBC6 }, \
+- { "/libx32/ld-linux-x32.so.2", FLAG_ELF_LIBC6 }, \
+- { "/lib64/ld-linux-x86-64.so.2", FLAG_ELF_LIBC6 },
+-#define SYSDEP_KNOWN_LIBRARY_NAMES \
+- { "libc.so.6", FLAG_ELF_LIBC6 }, \
+- { "libm.so.6", FLAG_ELF_LIBC6 },
+--
+2.39.2
+
diff --git a/Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch b/Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch
new file mode 100644
index 0000000..60576f4
--- /dev/null
+++ b/Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch
@@ -0,0 +1,34 @@
+From 15e6d6785ac2935bb963506b47a37b3d1f728952 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Fri, 24 Sep 2021 08:56:42 -0700
+Subject: [PATCH] Avoid warning: overriding recipe for
+ .../tst-ro-dynamic-mod.so
+
+Add tst-ro-dynamic-mod to modules-names-nobuild to avoid
+
+../Makerules:767: warning: ignoring old recipe for target '.../elf/tst-ro-dynamic-mod.so'
+
+This updates BZ #28340 fix.
+---
+ elf/Makefile | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 0cdccaa..26986c0 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -402,8 +402,9 @@ endif
+ modules-execstack-yes = tst-execstack-mod
+ extra-test-objs += $(addsuffix .os,$(strip $(modules-names)))
+
+-# filtmod1.so, tst-big-note-lib.so have special rules.
+-modules-names-nobuild := filtmod1 tst-big-note-lib
++# filtmod1.so, tst-big-note-lib.so, tst-ro-dynamic-mod.so have special
++# rules.
++modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod
+
+ tests += $(tests-static)
+
+--
+1.8.3.1
+
diff --git a/CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch b/CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch
new file mode 100644
index 0000000..401059d
--- /dev/null
+++ b/CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch
@@ -0,0 +1,125 @@
+From f545ad4928fa1f27a3075265182b38a4f939a5f7 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 17 Jan 2022 10:21:34 +0100
+Subject: [PATCH] CVE-2022-23218: Buffer overflow in sunrpc svcunix_create (bug
+ 28768)
+
+The sunrpc function svcunix_create suffers from a stack-based buffer
+overflow with overlong pathname arguments.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ NEWS | 3 +++
+ sunrpc/Makefile | 2 +-
+ sunrpc/svc_unix.c | 11 ++++-------
+ sunrpc/tst-bug28768.c | 42 ++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 50 insertions(+), 8 deletions(-)
+ create mode 100644 sunrpc/tst-bug28768.c
+
+diff --git a/NEWS b/NEWS
+index 38a9ddb..38802f0 100644
+--- a/NEWS
++++ b/NEWS
+@@ -14,6 +14,9 @@ Security related changes:
+ legacy function could result in a stack-based buffer overflow when
+ using the "unix" protocol. Reported by Martin Sebor.
+
++ CVE-2022-23218: Passing an overlong file name to the svcunix_create
++ legacy function could result in a stack-based buffer overflow.
++
+ The following bugs are resolved with this release:
+
+ [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix"
+diff --git a/sunrpc/Makefile b/sunrpc/Makefile
+index 183ef3d..a79a719 100644
+--- a/sunrpc/Makefile
++++ b/sunrpc/Makefile
+@@ -65,7 +65,7 @@ shared-only-routines = $(routines)
+ endif
+
+ tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \
+- tst-udp-nonblocking tst-bug22542
++ tst-udp-nonblocking tst-bug22542 tst-bug28768
+
+ xtests := tst-getmyaddr
+
+diff --git a/sunrpc/svc_unix.c b/sunrpc/svc_unix.c
+index f2280b4..67177a2 100644
+--- a/sunrpc/svc_unix.c
++++ b/sunrpc/svc_unix.c
+@@ -154,7 +154,10 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
+ SVCXPRT *xprt;
+ struct unix_rendezvous *r;
+ struct sockaddr_un addr;
+- socklen_t len = sizeof (struct sockaddr_in);
++ socklen_t len = sizeof (addr);
++
++ if (__sockaddr_un_set (&addr, path) < 0)
++ return NULL;
+
+ if (sock == RPC_ANYSOCK)
+ {
+@@ -165,12 +168,6 @@ svcunix_create (int sock, u_int sendsize, u_int recvsize, char *path)
+ }
+ madesock = TRUE;
+ }
+- memset (&addr, '\0', sizeof (addr));
+- addr.sun_family = AF_UNIX;
+- len = strlen (path) + 1;
+- memcpy (addr.sun_path, path, len);
+- len += sizeof (addr.sun_family);
+-
+ __bind (sock, (struct sockaddr *) &addr, len);
+
+ if (__getsockname (sock, (struct sockaddr *) &addr, &len) != 0
+diff --git a/sunrpc/tst-bug28768.c b/sunrpc/tst-bug28768.c
+new file mode 100644
+index 0000000..35a4b7b
+--- /dev/null
++++ b/sunrpc/tst-bug28768.c
+@@ -0,0 +1,42 @@
++/* Test to verify that long path is rejected by svcunix_create (bug 28768).
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <rpc/svc.h>
++#include <shlib-compat.h>
++#include <string.h>
++#include <support/check.h>
++
++/* svcunix_create does not have a default version in linkobj/libc.so. */
++compat_symbol_reference (libc, svcunix_create, svcunix_create, GLIBC_2_1);
++
++static int
++do_test (void)
++{
++ char pathname[109];
++ memset (pathname, 'x', sizeof (pathname));
++ pathname[sizeof (pathname) - 1] = '\0';
++
++ errno = 0;
++ TEST_VERIFY (svcunix_create (RPC_ANYSOCK, 4096, 4096, pathname) == NULL);
++ TEST_COMPARE (errno, EINVAL);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch b/CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch
new file mode 100644
index 0000000..f5b0488
--- /dev/null
+++ b/CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch
@@ -0,0 +1,65 @@
+From 226b46770c82899b555986583294b049c6ec9b40 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 17 Jan 2022 10:21:34 +0100
+Subject: [PATCH] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for
+ "unix" (bug 22542)
+
+Processing an overlong pathname in the sunrpc clnt_create function
+results in a stack-based buffer overflow.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+---
+ NEWS | 14 ++++++++++++++
+ sunrpc/clnt_gen.c | 10 +++++++---
+ 2 files changed, 21 insertions(+), 3 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 3c610744..dbe6f086 100644
+--- a/NEWS
++++ b/NEWS
+@@ -4,6 +4,20 @@ See the end for copying conditions.
+
+ Please send GNU C library bug reports via <https://sourceware.org/bugzilla/>
+ using `glibc' in the "product" field.
++
++^L
++Version 2.34.1
++
++Security related changes:
++
++ CVE-2022-23219: Passing an overlong file name to the clnt_create
++ legacy function could result in a stack-based buffer overflow when
++ using the "unix" protocol. Reported by Martin Sebor.
++
++The following bugs are resolved with this release:
++
++ [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix"
++
+
+ Version 2.34
+
+diff --git a/sunrpc/clnt_gen.c b/sunrpc/clnt_gen.c
+index 13ced899..b44357cd 100644
+--- a/sunrpc/clnt_gen.c
++++ b/sunrpc/clnt_gen.c
+@@ -57,9 +57,13 @@ clnt_create (const char *hostname, u_long prog, u_long vers,
+
+ if (strcmp (proto, "unix") == 0)
+ {
+- memset ((char *)&sun, 0, sizeof (sun));
+- sun.sun_family = AF_UNIX;
+- strcpy (sun.sun_path, hostname);
++ if (__sockaddr_un_set (&sun, hostname) < 0)
++ {
++ struct rpc_createerr *ce = &get_rpc_createerr ();
++ ce->cf_stat = RPC_SYSTEMERROR;
++ ce->cf_error.re_errno = errno;
++ return NULL;
++ }
+ sock = RPC_ANYSOCK;
+ client = clntunix_create (&sun, prog, vers, &sock, 0, 0);
+ if (client == NULL)
+--
+2.27.0
+
diff --git a/Check-the-validity-of-len-before-mmap.patch b/Check-the-validity-of-len-before-mmap.patch
new file mode 100644
index 0000000..bf3af02
--- /dev/null
+++ b/Check-the-validity-of-len-before-mmap.patch
@@ -0,0 +1,60 @@
+From a4efa699bfb5e03e6b7142729965caad36d1996d Mon Sep 17 00:00:00 2001
+From: shixuantong <shixuantong1@huawei.com>
+Date: Thu, 13 Jun 2024 16:29:38 +0800
+Subject: [PATCH] Check the validity of len before mmap
+
+Two cases:
+(1)If condition 'c->mapend + extra_len < c->mapstart + relro_len' is True, the result of "len" (size_t len = (c->mapend + extra_len) - (c->mapstart + relro_len)) will be a negative value. 'len' is of type size_t, so it overflows. later __mmap will fail, because 'len - mod' is a very large value at this point.
+
+(2)If the data segment is small, "len" may be equal to 0. In this case, __mmap also fails.
+
+In both cases, the mapping fails, the mapping is falled back, and hugepage feature of dynamic library becomes invalid. Case (1) is an exception, and the fallback is the expected. Case (2) should not be fallled back in its entirety. In this case, the code segment may continue to use huge page, and the data segment uses 4KB page.
+---
+ elf/dl-load.h | 2 ++
+ elf/dl-map-segments-hugepage.h | 9 +++++++++
+ 2 files changed, 11 insertions(+)
+
+diff --git a/elf/dl-load.h b/elf/dl-load.h
+index f2428165..cd0a5143 100644
+--- a/elf/dl-load.h
++++ b/elf/dl-load.h
+@@ -142,6 +142,8 @@ static const char *_dl_map_segments (struct link_map *l, int fd,
+ N_("fail to find exec prot segment")
+ #define DL_MAP_SEGMENT_ERROR_EXTRA_SIZE \
+ N_("wrong segment extra size")
++#define DL_MAP_SEGMENTS_GNU_RELRO \
++ N_("relro segment size is not expected")
+ #endif
+
+ #endif /* dl-load.h */
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+index 218e93a0..3b863288 100644
+--- a/elf/dl-map-segments-hugepage.h
++++ b/elf/dl-map-segments-hugepage.h
+@@ -260,6 +260,9 @@ _mmap_segment_filesz(struct link_map *l, const struct loadcmd *c, ElfW(Addr) map
+ void *map_addr = 0;
+
+ size_t relro_len = _get_relro_len(l, c);
++ if (c->mapend + extra_len < c->mapstart + relro_len)
++ return DL_MAP_SEGMENTS_GNU_RELRO;
++
+ if (relro_len > 0)
+ {
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+@@ -279,6 +282,12 @@ _mmap_segment_filesz(struct link_map *l, const struct loadcmd *c, ElfW(Addr) map
+
+ size_t prev_map_len = ALIGN_UP(mapstart, SIZE_2MB) - mapstart;
+ size_t len = (c->mapend + extra_len) - (c->mapstart + relro_len);
++ if (len == 0)
++ {
++ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
++ _dl_debug_printf("\t\tAfter mmapping relro len, remain filesz is zero\n");
++ return NULL;
++ }
+ if (len <= prev_map_len || len - prev_map_len < SIZE_2MB)
+ {
+ if (__glibc_unlikely (GLRO(dl_debug_mask) & DL_DEBUG_FILES))
+--
+2.33.0
+
+
diff --git a/Disable-debuginfod-in-printer-tests-BZ-28757.patch b/Disable-debuginfod-in-printer-tests-BZ-28757.patch
new file mode 100644
index 0000000..a701f43
--- /dev/null
+++ b/Disable-debuginfod-in-printer-tests-BZ-28757.patch
@@ -0,0 +1,57 @@
+From 7de501f9418bf099e7104b63b0e4423257981b14 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sun, 9 Jan 2022 09:06:15 -0800
+Subject: [PATCH] Disable debuginfod in printer tests [BZ #28757]
+
+With gdb-11.1-6.fc35.x86_64, I got
+
+FAIL: nptl/test-cond-printers
+FAIL: nptl/test-condattr-printers
+FAIL: nptl/test-mutex-printers
+FAIL: nptl/test-mutexattr-printers
+FAIL: nptl/test-rwlock-printers
+FAIL: nptl/test-rwlockattr-printers
+
+$ cat nptl/test-condattr-printers.out
+Error: Response does not match the expected pattern.
+Command: start
+Expected pattern: main
+Response: Temporary breakpoint 1 at 0x11d5: file test-condattr-printers.c, line 43.
+Starting program: /export/build/gnu/tools-build/glibc-cet-gitlab/build-x86_64-linux/nptl/test-condattr-printers
+
+This GDB supports auto-downloading debuginfo from the following URLs:
+https://debuginfod.fedoraproject.org/
+Enable debuginfod for this session? (y or [n])
+
+Disable debuginfod to avoid GDB messages. This fixes BZ #28757.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+---
+ scripts/test_printers_common.py | 11 +++++++++++
+ 1 file changed, 11 insertions(+)
+
+diff --git a/scripts/test_printers_common.py b/scripts/test_printers_common.py
+index 6406e3bac7..38121697bc 100644
+--- a/scripts/test_printers_common.py
++++ b/scripts/test_printers_common.py
+@@ -161,6 +161,17 @@ def init_test(test_bin, printer_files, printer_names):
+ printer files.
+ """
+
++ # Disable debuginfod to avoid GDB messages like:
++ #
++ # This GDB supports auto-downloading debuginfo from the following URLs:
++ # https://debuginfod.fedoraproject.org/
++ # Enable debuginfod for this session? (y or [n])
++ #
++ try:
++ test('set debuginfod enabled off')
++ except Exception:
++ pass
++
+ # Load all the pretty printer files. We're assuming these are safe.
+ for printer_file in printer_files:
+ test('source {0}'.format(printer_file))
+--
+2.27.0
+
diff --git a/Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch b/Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch
new file mode 100644
index 0000000..ce25968
--- /dev/null
+++ b/Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch
@@ -0,0 +1,37 @@
+From 79850e1025aabeccd3586c32ca259aa854607582 Mon Sep 17 00:00:00 2001
+From: Joseph Myers <joseph@codesourcery.com>
+Date: Wed, 29 Sep 2021 17:38:32 +0000
+Subject: [PATCH] Do not define tgmath.h fmaxmag, fminmag macros for C2X (bug
+ 28397)
+
+C2X does not include fmaxmag and fminmag. When I updated feature test
+macro handling accordingly (commit
+858045ad1c5ac1682288bbcb3676632b97a21ddf, "Update floating-point
+feature test macro handling for C2X", included in 2.34), I missed
+updating tgmath.h so it doesn't define the corresponding type-generic
+macros unless __STDC_WANT_IEC_60559_BFP_EXT__ is defined; I've now
+reported this as bug 28397. Adjust the conditionals in tgmath.h
+accordingly.
+
+Tested for x86_64.
+---
+ math/tgmath.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/math/tgmath.h b/math/tgmath.h
+index 9868353..3d7b099 100644
+--- a/math/tgmath.h
++++ b/math/tgmath.h
+@@ -921,7 +921,9 @@
+
+ /* Like ilogb, but returning long int. */
+ # define llogb(Val) __TGMATH_UNARY_REAL_RET_ONLY (Val, llogb)
++#endif
+
++#if __GLIBC_USE (IEC_60559_BFP_EXT)
+ /* Return value with maximum magnitude. */
+ # define fmaxmag(Val1, Val2) __TGMATH_BINARY_REAL_ONLY (Val1, Val2, fmaxmag)
+
+--
+1.8.3.1
+
diff --git a/Fix-deadlock-when-pthread_atfork-handler-calls-pthre.patch b/Fix-deadlock-when-pthread_atfork-handler-calls-pthre.patch
new file mode 100644
index 0000000..97927a9
--- /dev/null
+++ b/Fix-deadlock-when-pthread_atfork-handler-calls-pthre.patch
@@ -0,0 +1,754 @@
+From ff450cdbdee0b8cb6b9d653d6d2fa892de29be31 Mon Sep 17 00:00:00 2001
+From: Arjun Shankar <arjun@redhat.com>
+Date: Tue, 24 May 2022 17:57:36 +0200
+Subject: [PATCH] Fix deadlock when pthread_atfork handler calls pthread_atfork
+ or dlclose
+
+In multi-threaded programs, registering via pthread_atfork,
+de-registering implicitly via dlclose, or running pthread_atfork
+handlers during fork was protected by an internal lock. This meant
+that a pthread_atfork handler attempting to register another handler or
+dlclose a dynamically loaded library would lead to a deadlock.
+
+This commit fixes the deadlock in the following way:
+
+During the execution of handlers at fork time, the atfork lock is
+released prior to the execution of each handler and taken again upon its
+return. Any handler registrations or de-registrations that occurred
+during the execution of the handler are accounted for before proceeding
+with further handler execution.
+
+If a handler that hasn't been executed yet gets de-registered by another
+handler during fork, it will not be executed. If a handler gets
+registered by another handler during fork, it will not be executed
+during that particular fork.
+
+The possibility that handlers may now be registered or deregistered
+during handler execution means that identifying the next handler to be
+run after a given handler may register/de-register others requires some
+bookkeeping. The fork_handler struct has an additional field, 'id',
+which is assigned sequentially during registration. Thus, handlers are
+executed in ascending order of 'id' during 'prepare', and descending
+order of 'id' during parent/child handler execution after the fork.
+
+Two tests are included:
+
+* tst-atfork3: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+ This test exercises calling dlclose from prepare, parent, and child
+ handlers.
+
+* tst-atfork4: This test exercises calling pthread_atfork and dlclose
+ from the prepare handler.
+
+[BZ #24595, BZ #27054]
+
+Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+(cherry picked from commit 52a103e237329b9f88a28513fe7506ffc3bd8ced)
+---
+ include/register-atfork.h | 26 ++++----
+ posix/fork.c | 7 +-
+ posix/register-atfork.c | 140 ++++++++++++++++++++++++++++++---------
+ sysdeps/pthread/Makefile | 38 +++++++++--
+ sysdeps/pthread/tst-atfork3.c | 118 +++++++++++++++++++++++++++++++++
+ sysdeps/pthread/tst-atfork3mod.c | 44 ++++++++++++
+ sysdeps/pthread/tst-atfork4.c | 128 +++++++++++++++++++++++++++++++++++
+ sysdeps/pthread/tst-atfork4mod.c | 48 ++++++++++++++
+ 8 files changed, 499 insertions(+), 50 deletions(-)
+ create mode 100644 sysdeps/pthread/tst-atfork3.c
+ create mode 100644 sysdeps/pthread/tst-atfork3mod.c
+ create mode 100644 sysdeps/pthread/tst-atfork4.c
+ create mode 100644 sysdeps/pthread/tst-atfork4mod.c
+
+diff --git a/include/register-atfork.h b/include/register-atfork.h
+index fadde14..6d7bfd8 100644
+--- a/include/register-atfork.h
++++ b/include/register-atfork.h
+@@ -26,6 +26,7 @@ struct fork_handler
+ void (*parent_handler) (void);
+ void (*child_handler) (void);
+ void *dso_handle;
++ uint64_t id;
+ };
+
+ /* Function to call to unregister fork handlers. */
+@@ -39,19 +40,18 @@ enum __run_fork_handler_type
+ atfork_run_parent
+ };
+
+-/* Run the atfork handlers and lock/unlock the internal lock depending
+- of the WHO argument:
+-
+- - atfork_run_prepare: run all the PREPARE_HANDLER in reverse order of
+- insertion and locks the internal lock.
+- - atfork_run_child: run all the CHILD_HANDLER and unlocks the internal
+- lock.
+- - atfork_run_parent: run all the PARENT_HANDLER and unlocks the internal
+- lock.
+-
+- Perform locking only if DO_LOCKING. */
+-extern void __run_fork_handlers (enum __run_fork_handler_type who,
+- _Bool do_locking) attribute_hidden;
++/* Run the atfork prepare handlers in the reverse order of registration and
++ return the ID of the last registered handler. If DO_LOCKING is true, the
++ internal lock is held locked upon return. */
++extern uint64_t __run_prefork_handlers (_Bool do_locking) attribute_hidden;
++
++/* Given a handler type (parent or child), run all the atfork handlers in
++ the order of registration up to and including the handler with id equal
++ to LASTRUN. If DO_LOCKING is true, the internal lock is unlocked prior
++ to return. */
++extern void __run_postfork_handlers (enum __run_fork_handler_type who,
++ _Bool do_locking,
++ uint64_t lastrun) attribute_hidden;
+
+ /* C library side function to register new fork handlers. */
+ extern int __register_atfork (void (*__prepare) (void),
+diff --git a/posix/fork.c b/posix/fork.c
+index 021691b..890b806 100644
+--- a/posix/fork.c
++++ b/posix/fork.c
+@@ -46,8 +46,9 @@ __libc_fork (void)
+ best effort to make is async-signal-safe at least for single-thread
+ case. */
+ bool multiple_threads = __libc_single_threaded == 0;
++ uint64_t lastrun;
+
+- __run_fork_handlers (atfork_run_prepare, multiple_threads);
++ lastrun = __run_prefork_handlers (multiple_threads);
+
+ struct nss_database_data nss_database_data;
+
+@@ -105,7 +106,7 @@ __libc_fork (void)
+ reclaim_stacks ();
+
+ /* Run the handlers registered for the child. */
+- __run_fork_handlers (atfork_run_child, multiple_threads);
++ __run_postfork_handlers (atfork_run_child, multiple_threads, lastrun);
+ }
+ else
+ {
+@@ -123,7 +124,7 @@ __libc_fork (void)
+ }
+
+ /* Run the handlers registered for the parent. */
+- __run_fork_handlers (atfork_run_parent, multiple_threads);
++ __run_postfork_handlers (atfork_run_parent, multiple_threads, lastrun);
+
+ if (pid < 0)
+ __set_errno (save_errno);
+diff --git a/posix/register-atfork.c b/posix/register-atfork.c
+index 6fd9e4c..6370437 100644
+--- a/posix/register-atfork.c
++++ b/posix/register-atfork.c
+@@ -19,6 +19,8 @@
+ #include <libc-lock.h>
+ #include <stdbool.h>
+ #include <register-atfork.h>
++#include <intprops.h>
++#include <stdio.h>
+
+ #define DYNARRAY_ELEMENT struct fork_handler
+ #define DYNARRAY_STRUCT fork_handler_list
+@@ -27,7 +29,7 @@
+ #include <malloc/dynarray-skeleton.c>
+
+ static struct fork_handler_list fork_handlers;
+-static bool fork_handler_init = false;
++static uint64_t fork_handler_counter;
+
+ static int atfork_lock = LLL_LOCK_INITIALIZER;
+
+@@ -37,11 +39,8 @@ __register_atfork (void (*prepare) (void), void (*parent) (void),
+ {
+ lll_lock (atfork_lock, LLL_PRIVATE);
+
+- if (!fork_handler_init)
+- {
+- fork_handler_list_init (&fork_handlers);
+- fork_handler_init = true;
+- }
++ if (fork_handler_counter == 0)
++ fork_handler_list_init (&fork_handlers);
+
+ struct fork_handler *newp = fork_handler_list_emplace (&fork_handlers);
+ if (newp != NULL)
+@@ -50,6 +49,13 @@ __register_atfork (void (*prepare) (void), void (*parent) (void),
+ newp->parent_handler = parent;
+ newp->child_handler = child;
+ newp->dso_handle = dso_handle;
++
++ /* IDs assigned to handlers start at 1 and increment with handler
++ registration. Un-registering a handlers discards the corresponding
++ ID. It is not reused in future registrations. */
++ if (INT_ADD_OVERFLOW (fork_handler_counter, 1))
++ __libc_fatal ("fork handler counter overflow");
++ newp->id = ++fork_handler_counter;
+ }
+
+ /* Release the lock. */
+@@ -104,37 +110,111 @@ __unregister_atfork (void *dso_handle)
+ lll_unlock (atfork_lock, LLL_PRIVATE);
+ }
+
+-void
+-__run_fork_handlers (enum __run_fork_handler_type who, _Bool do_locking)
++uint64_t
++__run_prefork_handlers (_Bool do_locking)
+ {
+- struct fork_handler *runp;
++ uint64_t lastrun;
+
+- if (who == atfork_run_prepare)
++ if (do_locking)
++ lll_lock (atfork_lock, LLL_PRIVATE);
++
++ /* We run prepare handlers from last to first. After fork, only
++ handlers up to the last handler found here (pre-fork) will be run.
++ Handlers registered during __run_prefork_handlers or
++ __run_postfork_handlers will be positioned after this last handler, and
++ since their prepare handlers won't be run now, their parent/child
++ handlers should also be ignored. */
++ lastrun = fork_handler_counter;
++
++ size_t sl = fork_handler_list_size (&fork_handlers);
++ for (size_t i = sl; i > 0;)
+ {
+- if (do_locking)
+- lll_lock (atfork_lock, LLL_PRIVATE);
+- size_t sl = fork_handler_list_size (&fork_handlers);
+- for (size_t i = sl; i > 0; i--)
+- {
+- runp = fork_handler_list_at (&fork_handlers, i - 1);
+- if (runp->prepare_handler != NULL)
+- runp->prepare_handler ();
+- }
++ struct fork_handler *runp
++ = fork_handler_list_at (&fork_handlers, i - 1);
++
++ uint64_t id = runp->id;
++
++ if (runp->prepare_handler != NULL)
++ {
++ if (do_locking)
++ lll_unlock (atfork_lock, LLL_PRIVATE);
++
++ runp->prepare_handler ();
++
++ if (do_locking)
++ lll_lock (atfork_lock, LLL_PRIVATE);
++ }
++
++ /* We unlocked, ran the handler, and locked again. In the
++ meanwhile, one or more deregistrations could have occurred leading
++ to the current (just run) handler being moved up the list or even
++ removed from the list itself. Since handler IDs are guaranteed to
++ to be in increasing order, the next handler has to have: */
++
++ /* A. An earlier position than the current one has. */
++ i--;
++
++ /* B. A lower ID than the current one does. The code below skips
++ any newly added handlers with higher IDs. */
++ while (i > 0
++ && fork_handler_list_at (&fork_handlers, i - 1)->id >= id)
++ i--;
+ }
+- else
++
++ return lastrun;
++}
++
++void
++__run_postfork_handlers (enum __run_fork_handler_type who, _Bool do_locking,
++ uint64_t lastrun)
++{
++ size_t sl = fork_handler_list_size (&fork_handlers);
++ for (size_t i = 0; i < sl;)
+ {
+- size_t sl = fork_handler_list_size (&fork_handlers);
+- for (size_t i = 0; i < sl; i++)
+- {
+- runp = fork_handler_list_at (&fork_handlers, i);
+- if (who == atfork_run_child && runp->child_handler)
+- runp->child_handler ();
+- else if (who == atfork_run_parent && runp->parent_handler)
+- runp->parent_handler ();
+- }
++ struct fork_handler *runp = fork_handler_list_at (&fork_handlers, i);
++ uint64_t id = runp->id;
++
++ /* prepare handlers were not run for handlers with ID > LASTRUN.
++ Thus, parent/child handlers will also not be run. */
++ if (id > lastrun)
++ break;
++
+ if (do_locking)
+- lll_unlock (atfork_lock, LLL_PRIVATE);
++ lll_unlock (atfork_lock, LLL_PRIVATE);
++
++ if (who == atfork_run_child && runp->child_handler)
++ runp->child_handler ();
++ else if (who == atfork_run_parent && runp->parent_handler)
++ runp->parent_handler ();
++
++ if (do_locking)
++ lll_lock (atfork_lock, LLL_PRIVATE);
++
++ /* We unlocked, ran the handler, and locked again. In the meanwhile,
++ one or more [de]registrations could have occurred. Due to this,
++ the list size must be updated. */
++ sl = fork_handler_list_size (&fork_handlers);
++
++ /* The just-run handler could also have moved up the list. */
++
++ if (sl > i && fork_handler_list_at (&fork_handlers, i)->id == id)
++ /* The position of the recently run handler hasn't changed. The
++ next handler to be run is an easy increment away. */
++ i++;
++ else
++ {
++ /* The next handler to be run is the first handler in the list
++ to have an ID higher than the current one. */
++ for (i = 0; i < sl; i++)
++ {
++ if (fork_handler_list_at (&fork_handlers, i)->id > id)
++ break;
++ }
++ }
+ }
++
++ if (do_locking)
++ lll_unlock (atfork_lock, LLL_PRIVATE);
+ }
+
+
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index 00419c4..5147588 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -154,16 +154,36 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx6 tst-cancelx8 tst-cancelx9 \
+ tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
+
+ ifeq ($(build-shared),yes)
+-tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 tst-create1
++tests += \
++ tst-atfork2 \
++ tst-pt-tls4 \
++ tst-_res1 \
++ tst-fini1 \
++ tst-create1 \
++ tst-atfork3 \
++ tst-atfork4 \
++# tests
++
+ tests-nolibpthread += tst-fini1
+ endif
+
+-modules-names += tst-atfork2mod tst-tls4moda tst-tls4modb \
+- tst-_res1mod1 tst-_res1mod2 tst-fini1mod \
+- tst-create1mod
++modules-names += \
++ tst-atfork2mod \
++ tst-tls4moda \
++ tst-tls4modb \
++ tst-_res1mod1 \
++ tst-_res1mod2 \
++ tst-fini1mod \
++ tst-create1mod \
++ tst-atfork3mod \
++ tst-atfork4mod \
++# module-names
++
+ test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
+
+ tst-atfork2mod.so-no-z-defs = yes
++tst-atfork3mod.so-no-z-defs = yes
++tst-atfork4mod.so-no-z-defs = yes
+ tst-create1mod.so-no-z-defs = yes
+
+ ifeq ($(build-shared),yes)
+@@ -226,8 +246,18 @@ tst-atfork2-ENV = MALLOC_TRACE=$(objpfx)tst-atfork2.mtrace \
+ LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+ $(objpfx)tst-atfork2mod.so: $(shared-thread-library)
+
++$(objpfx)tst-atfork3: $(shared-thread-library)
++LDFLAGS-tst-atfork3 = -rdynamic
++$(objpfx)tst-atfork3mod.so: $(shared-thread-library)
++
++$(objpfx)tst-atfork4: $(shared-thread-library)
++LDFLAGS-tst-atfork4 = -rdynamic
++$(objpfx)tst-atfork4mod.so: $(shared-thread-library)
++
+ ifeq ($(build-shared),yes)
+ $(objpfx)tst-atfork2.out: $(objpfx)tst-atfork2mod.so
++$(objpfx)tst-atfork3.out: $(objpfx)tst-atfork3mod.so
++$(objpfx)tst-atfork4.out: $(objpfx)tst-atfork4mod.so
+ endif
+
+ ifeq ($(build-shared),yes)
+diff --git a/sysdeps/pthread/tst-atfork3.c b/sysdeps/pthread/tst-atfork3.c
+new file mode 100644
+index 0000000..bb2250e
+--- /dev/null
++++ b/sysdeps/pthread/tst-atfork3.c
+@@ -0,0 +1,118 @@
++/* Check if pthread_atfork handler can call dlclose (BZ#24595).
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++#include <pthread.h>
++#include <unistd.h>
++#include <stdlib.h>
++#include <stdbool.h>
++
++#include <support/check.h>
++#include <support/xthread.h>
++#include <support/capture_subprocess.h>
++#include <support/xdlfcn.h>
++
++/* Check if pthread_atfork handlers do not deadlock when calling a function
++ that might alter the internal fork handle list, such as dlclose.
++
++ The test registers a callback set with pthread_atfork(), dlopen() a shared
++ library (nptl/tst-atfork3mod.c), calls an exported symbol from the library
++ (which in turn also registers atfork handlers), and calls fork to trigger
++ the callbacks. */
++
++static void *handler;
++static bool run_dlclose_prepare;
++static bool run_dlclose_parent;
++static bool run_dlclose_child;
++
++static void
++prepare (void)
++{
++ if (run_dlclose_prepare)
++ xdlclose (handler);
++}
++
++static void
++parent (void)
++{
++ if (run_dlclose_parent)
++ xdlclose (handler);
++}
++
++static void
++child (void)
++{
++ if (run_dlclose_child)
++ xdlclose (handler);
++}
++
++static void
++proc_func (void *closure)
++{
++}
++
++static void
++do_test_generic (bool dlclose_prepare, bool dlclose_parent, bool dlclose_child)
++{
++ run_dlclose_prepare = dlclose_prepare;
++ run_dlclose_parent = dlclose_parent;
++ run_dlclose_child = dlclose_child;
++
++ handler = xdlopen ("tst-atfork3mod.so", RTLD_NOW);
++
++ int (*atfork3mod_func)(void);
++ atfork3mod_func = xdlsym (handler, "atfork3mod_func");
++
++ atfork3mod_func ();
++
++ struct support_capture_subprocess proc
++ = support_capture_subprocess (proc_func, NULL);
++ support_capture_subprocess_check (&proc, "tst-atfork3", 0, sc_allow_none);
++
++ handler = atfork3mod_func = NULL;
++
++ support_capture_subprocess_free (&proc);
++}
++
++static void *
++thread_func (void *closure)
++{
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ {
++ /* Make the process acts as multithread. */
++ pthread_attr_t attr;
++ xpthread_attr_init (&attr);
++ xpthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
++ xpthread_create (&attr, thread_func, NULL);
++ }
++
++ TEST_COMPARE (pthread_atfork (prepare, parent, child), 0);
++
++ do_test_generic (true /* prepare */, false /* parent */, false /* child */);
++ do_test_generic (false /* prepare */, true /* parent */, false /* child */);
++ do_test_generic (false /* prepare */, false /* parent */, true /* child */);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/pthread/tst-atfork3mod.c b/sysdeps/pthread/tst-atfork3mod.c
+new file mode 100644
+index 0000000..6d0658c
+--- /dev/null
++++ b/sysdeps/pthread/tst-atfork3mod.c
+@@ -0,0 +1,44 @@
++/* Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <unistd.h>
++#include <stdlib.h>
++#include <pthread.h>
++
++#include <support/check.h>
++
++static void
++mod_prepare (void)
++{
++}
++
++static void
++mod_parent (void)
++{
++}
++
++static void
++mod_child (void)
++{
++}
++
++int atfork3mod_func (void)
++{
++ TEST_COMPARE (pthread_atfork (mod_prepare, mod_parent, mod_child), 0);
++
++ return 0;
++}
+diff --git a/sysdeps/pthread/tst-atfork4.c b/sysdeps/pthread/tst-atfork4.c
+new file mode 100644
+index 0000000..52dc87e
+--- /dev/null
++++ b/sysdeps/pthread/tst-atfork4.c
+@@ -0,0 +1,128 @@
++/* pthread_atfork supports handlers that call pthread_atfork or dlclose.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <support/xdlfcn.h>
++#include <stdio.h>
++#include <support/xthread.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++#include <support/xunistd.h>
++#include <support/check.h>
++#include <stdlib.h>
++
++static void *
++thread_func (void *x)
++{
++ return NULL;
++}
++
++static unsigned int second_atfork_handler_runcount = 0;
++
++static void
++second_atfork_handler (void)
++{
++ second_atfork_handler_runcount++;
++}
++
++static void *h = NULL;
++
++static unsigned int atfork_handler_runcount = 0;
++
++static void
++prepare (void)
++{
++ /* These atfork handlers are registered while atfork handlers are being
++ executed and thus will not be executed during the corresponding
++ fork. */
++ TEST_VERIFY_EXIT (pthread_atfork (second_atfork_handler,
++ second_atfork_handler,
++ second_atfork_handler) == 0);
++
++ /* This will de-register the atfork handlers registered by the dlopen'd
++ library and so they will not be executed. */
++ if (h != NULL)
++ {
++ xdlclose (h);
++ h = NULL;
++ }
++
++ atfork_handler_runcount++;
++}
++
++static void
++after (void)
++{
++ atfork_handler_runcount++;
++}
++
++static int
++do_test (void)
++{
++ /* Make sure __libc_single_threaded is 0. */
++ pthread_attr_t attr;
++ xpthread_attr_init (&attr);
++ xpthread_attr_setdetachstate (&attr, PTHREAD_CREATE_DETACHED);
++ xpthread_create (&attr, thread_func, NULL);
++
++ void (*reg_atfork_handlers) (void);
++
++ h = xdlopen ("tst-atfork4mod.so", RTLD_LAZY);
++
++ reg_atfork_handlers = xdlsym (h, "reg_atfork_handlers");
++
++ reg_atfork_handlers ();
++
++ /* We register our atfork handlers *after* loading the module so that our
++ prepare handler is called first at fork, where we then dlclose the
++ module before its prepare handler has a chance to be called. */
++ TEST_VERIFY_EXIT (pthread_atfork (prepare, after, after) == 0);
++
++ pid_t pid = xfork ();
++
++ /* Both the parent and the child processes should observe this. */
++ TEST_VERIFY_EXIT (atfork_handler_runcount == 2);
++ TEST_VERIFY_EXIT (second_atfork_handler_runcount == 0);
++
++ if (pid > 0)
++ {
++ int childstat;
++
++ xwaitpid (-1, &childstat, 0);
++ TEST_VERIFY_EXIT (WIFEXITED (childstat)
++ && WEXITSTATUS (childstat) == 0);
++
++ /* This time, the second set of atfork handlers should also be called
++ since the handlers are already in place before fork is called. */
++
++ pid = xfork ();
++
++ TEST_VERIFY_EXIT (atfork_handler_runcount == 4);
++ TEST_VERIFY_EXIT (second_atfork_handler_runcount == 2);
++
++ if (pid > 0)
++ {
++ xwaitpid (-1, &childstat, 0);
++ TEST_VERIFY_EXIT (WIFEXITED (childstat)
++ && WEXITSTATUS (childstat) == 0);
++ }
++ }
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/pthread/tst-atfork4mod.c b/sysdeps/pthread/tst-atfork4mod.c
+new file mode 100644
+index 0000000..e111efe
+--- /dev/null
++++ b/sysdeps/pthread/tst-atfork4mod.c
+@@ -0,0 +1,48 @@
++/* pthread_atfork supports handlers that call pthread_atfork or dlclose.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <pthread.h>
++#include <stdlib.h>
++
++/* This dynamically loaded library simply registers its atfork handlers when
++ asked to. The atfork handlers should never be executed because the
++ library is unloaded before fork is called by the test program. */
++
++static void
++prepare (void)
++{
++ abort ();
++}
++
++static void
++parent (void)
++{
++ abort ();
++}
++
++static void
++child (void)
++{
++ abort ();
++}
++
++void
++reg_atfork_handlers (void)
++{
++ pthread_atfork (prepare, parent, child);
++}
+--
+1.8.3.1
+
diff --git a/Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch b/Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch
new file mode 100644
index 0000000..f9cb581
--- /dev/null
+++ b/Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch
@@ -0,0 +1,37 @@
+From ae925404a10bf0ea63d6e8d41e3821f68b4d776c Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 3 Sep 2021 00:28:14 +0200
+Subject: [PATCH] Fix failing nss/tst-nss-files-hosts-long with local resolver
+
+When a local resolver like unbound is listening on the IPv4 loopback
+address 127.0.0.1, the nss/tst-nss-files-hosts-long test fails. This is
+due to:
+- the default resolver in the absence of resolv.conf being 127.0.0.1
+- the default DNS NSS database configuration in the absence of
+ nsswitch.conf being 'hosts: dns [!UNAVAIL=return] file'
+
+This causes the requests for 'test4' and 'test6' to first be sent to the
+local resolver, which responds with NXDOMAIN in the likely case those
+records do no exist. In turn that causes the access to /etc/hosts to be
+skipped, which is the purpose of that test.
+
+Fix that by providing a simple nsswitch.conf file forcing access to
+/etc/hosts for that test. I have tested that the only changed result in
+the testsuite is that test.
+
+(cherry picked from commit 2738480a4b0866723fb8c633f36bdd34a8767581)
+---
+ nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf
+
+diff --git a/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf
+new file mode 100644
+index 0000000..5b0c6a4
+--- /dev/null
++++ b/nss/tst-nss-files-hosts-long.root/etc/nsswitch.conf
+@@ -0,0 +1 @@
++hosts: files
+--
+1.8.3.1
+
diff --git a/Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch b/Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch
new file mode 100644
index 0000000..bc38a37
--- /dev/null
+++ b/Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch
@@ -0,0 +1,399 @@
+From 948ebc098ed3cd928ea10997f990115e7770bda3 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 27 Jan 2022 16:03:58 +0100
+Subject: [PATCH] Fix glibc 2.34 ABI omission (missing GLIBC_2.34 in dynamic
+ loader)
+
+The glibc 2.34 release really should have added a GLIBC_2.34
+symbol to the dynamic loader. With it, we could move functions such
+as dlopen or pthread_key_create that work on process-global state
+into the dynamic loader (once we have fixed a longstanding issue
+with static linking). Without the GLIBC_2.34 symbol, yet another
+new symbol version would be needed because old glibc will fail to
+load binaries due to the missing symbol version in ld.so that newly
+linked programs will require.
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+(cherry picked from commit af121ae3e7cd12628c91ecfc46a9d65313a6e972)
+---
+ elf/Makefile | 1 +
+ elf/Versions | 3 ++
+ elf/dl-compat.c | 32 +++++++++++++++++++
+ sysdeps/mach/hurd/i386/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/aarch64/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/alpha/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/arc/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/arm/be/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/arm/le/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/csky/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/hppa/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/i386/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/ia64/ld.abilist | 1 +
+ .../unix/sysv/linux/m68k/coldfire/ld.abilist | 1 +
+ .../unix/sysv/linux/m68k/m680x0/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/microblaze/ld.abilist | 1 +
+ .../unix/sysv/linux/mips/mips32/ld.abilist | 1 +
+ .../sysv/linux/mips/mips64/n32/ld.abilist | 1 +
+ .../sysv/linux/mips/mips64/n64/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/nios2/ld.abilist | 1 +
+ .../sysv/linux/powerpc/powerpc32/ld.abilist | 1 +
+ .../linux/powerpc/powerpc64/be/ld.abilist | 1 +
+ .../linux/powerpc/powerpc64/le/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist | 1 +
+ .../unix/sysv/linux/s390/s390-32/ld.abilist | 1 +
+ .../unix/sysv/linux/s390/s390-64/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/sh/be/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/sh/le/ld.abilist | 1 +
+ .../unix/sysv/linux/sparc/sparc32/ld.abilist | 1 +
+ .../unix/sysv/linux/sparc/sparc64/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/x86_64/64/ld.abilist | 1 +
+ sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist | 1 +
+ 33 files changed, 66 insertions(+)
+ create mode 100644 elf/dl-compat.c
+
+diff --git a/elf/Makefile b/elf/Makefile
+index f930e04e27..af4ccb978c 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -115,6 +115,7 @@ elide-routines.os = \
+ # interpreter and operating independent of libc.
+ rtld-routines = \
+ $(all-dl-routines) \
++ dl-compat \
+ dl-conflict \
+ dl-diagnostics \
+ dl-diagnostics-cpu \
+diff --git a/elf/Versions b/elf/Versions
+index 775aab62af..2af210b8f7 100644
+--- a/elf/Versions
++++ b/elf/Versions
+@@ -48,6 +48,9 @@ ld {
+ # stack canary
+ __stack_chk_guard;
+ }
++ GLIBC_2.34 {
++ __rtld_version_placeholder;
++ }
+ GLIBC_PRIVATE {
+ # Those are in the dynamic linker, but used by libc.so.
+ __libc_enable_secure;
+diff --git a/elf/dl-compat.c b/elf/dl-compat.c
+new file mode 100644
+index 0000000000..cc560c5159
+--- /dev/null
++++ b/elf/dl-compat.c
+@@ -0,0 +1,32 @@
++/* Placeholder compatibility symbols.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <shlib-compat.h>
++#include <sys/cdefs.h>
++
++/* GLIBC_2.34 placeholder for future symbol moves. */
++
++void
++attribute_compat_text_section
++__attribute_used__
++__rtld_version_placeholder_1 (void)
++{
++}
++
++compat_symbol (ld, __rtld_version_placeholder_1,
++ __rtld_version_placeholder, GLIBC_2_34);
+diff --git a/sysdeps/mach/hurd/i386/ld.abilist b/sysdeps/mach/hurd/i386/ld.abilist
+index 7e20c5e7ce..ebba31f770 100644
+--- a/sysdeps/mach/hurd/i386/ld.abilist
++++ b/sysdeps/mach/hurd/i386/ld.abilist
+@@ -16,3 +16,4 @@ GLIBC_2.2.6 _r_debug D 0x14
+ GLIBC_2.2.6 abort F
+ GLIBC_2.3 ___tls_get_addr F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+index 80b2fe6725..b7196a80e2 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.17 __stack_chk_guard D 0x8
+ GLIBC_2.17 __tls_get_addr F
+ GLIBC_2.17 _dl_mcount F
+ GLIBC_2.17 _r_debug D 0x28
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist
+index 98a03f611f..13f7fc74af 100644
+--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist
++++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x28
+ GLIBC_2.1 __libc_stack_end D 0x8
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x8
+diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/ld.abilist
+index 048f17c848..7284383a6b 100644
+--- a/sysdeps/unix/sysv/linux/arc/ld.abilist
++++ b/sysdeps/unix/sysv/linux/arc/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.32 __stack_chk_guard D 0x4
+ GLIBC_2.32 __tls_get_addr F
+ GLIBC_2.32 _dl_mcount F
+ GLIBC_2.32 _r_debug D 0x14
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/arm/be/ld.abilist b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
+index cc8825c3bc..7987bbae11 100644
+--- a/sysdeps/unix/sysv/linux/arm/be/ld.abilist
++++ b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
+@@ -1,3 +1,4 @@
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __libc_stack_end D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+ GLIBC_2.4 __tls_get_addr F
+diff --git a/sysdeps/unix/sysv/linux/arm/le/ld.abilist b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
+index cc8825c3bc..7987bbae11 100644
+--- a/sysdeps/unix/sysv/linux/arm/le/ld.abilist
++++ b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
+@@ -1,3 +1,4 @@
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __libc_stack_end D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+ GLIBC_2.4 __tls_get_addr F
+diff --git a/sysdeps/unix/sysv/linux/csky/ld.abilist b/sysdeps/unix/sysv/linux/csky/ld.abilist
+index 564ac09737..4939b20631 100644
+--- a/sysdeps/unix/sysv/linux/csky/ld.abilist
++++ b/sysdeps/unix/sysv/linux/csky/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.29 __stack_chk_guard D 0x4
+ GLIBC_2.29 __tls_get_addr F
+ GLIBC_2.29 _dl_mcount F
+ GLIBC_2.29 _r_debug D 0x14
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist
+index d155a59843..7cc9ebd792 100644
+--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist
++++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.2 __libc_stack_end D 0x4
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x14
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
+index 0478e22071..e8d187b14d 100644
+--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
++++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.1 __libc_stack_end D 0x4
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 ___tls_get_addr F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist
+index 33f91199bf..be5122650a 100644
+--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist
+@@ -2,3 +2,4 @@ GLIBC_2.2 __libc_stack_end D 0x8
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
+index cc8825c3bc..7987bbae11 100644
+--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
+@@ -1,3 +1,4 @@
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __libc_stack_end D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+ GLIBC_2.4 __tls_get_addr F
+diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
+index 3ba474c27f..4f2854edf7 100644
+--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x14
+ GLIBC_2.1 __libc_stack_end D 0x4
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
+index a4933c3541..9f0fdeca38 100644
+--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist
++++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.18 __stack_chk_guard D 0x4
+ GLIBC_2.18 __tls_get_addr F
+ GLIBC_2.18 _dl_mcount F
+ GLIBC_2.18 _r_debug D 0x14
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
+index be09641a48..f750067d5c 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x14
+ GLIBC_2.2 __libc_stack_end D 0x4
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
+index be09641a48..f750067d5c 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x14
+ GLIBC_2.2 __libc_stack_end D 0x4
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+index 1ea36e13f2..2fba6a9b6e 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.0 _r_debug D 0x28
+ GLIBC_2.2 __libc_stack_end D 0x8
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x8
+diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist
+index 52178802dd..57dfad5a53 100644
+--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist
++++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.21 __stack_chk_guard D 0x4
+ GLIBC_2.21 __tls_get_addr F
+ GLIBC_2.21 _dl_mcount F
+ GLIBC_2.21 _r_debug D 0x14
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
+index 4bbfba7a61..e896607392 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
+@@ -4,3 +4,4 @@ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.22 __tls_get_addr_opt F
+ GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+index 283fb4510b..ce0bc63959 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+@@ -4,3 +4,4 @@ GLIBC_2.3 __libc_stack_end D 0x8
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.3 _dl_mcount F
+ GLIBC_2.3 _r_debug D 0x28
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+index b1f313c7cd..65b22674d2 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+@@ -4,3 +4,4 @@ GLIBC_2.17 _dl_mcount F
+ GLIBC_2.17 _r_debug D 0x28
+ GLIBC_2.22 __tls_get_addr_opt F
+ GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
+index 94ca64c43d..5ad4c81d12 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.33 __stack_chk_guard D 0x4
+ GLIBC_2.33 __tls_get_addr F
+ GLIBC_2.33 _dl_mcount F
+ GLIBC_2.33 _r_debug D 0x14
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+index 845f356c3c..479efdea9b 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+@@ -3,3 +3,4 @@ GLIBC_2.27 __stack_chk_guard D 0x8
+ GLIBC_2.27 __tls_get_addr F
+ GLIBC_2.27 _dl_mcount F
+ GLIBC_2.27 _r_debug D 0x28
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
+index b56f005beb..d5ecb636bb 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
+@@ -2,3 +2,4 @@ GLIBC_2.0 _r_debug D 0x14
+ GLIBC_2.1 __libc_stack_end D 0x4
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_offset F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+index 6f788a086d..62a5e1d99a 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+@@ -2,3 +2,4 @@ GLIBC_2.2 __libc_stack_end D 0x8
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_offset F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/sh/be/ld.abilist b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
+index d155a59843..7cc9ebd792 100644
+--- a/sysdeps/unix/sysv/linux/sh/be/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.2 __libc_stack_end D 0x4
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x14
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sh/le/ld.abilist b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
+index d155a59843..7cc9ebd792 100644
+--- a/sysdeps/unix/sysv/linux/sh/le/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
+@@ -2,4 +2,5 @@ GLIBC_2.2 __libc_stack_end D 0x4
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x14
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
+index 0c6610e3c2..2e60543498 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
+@@ -2,3 +2,4 @@ GLIBC_2.0 _r_debug D 0x14
+ GLIBC_2.1 __libc_stack_end D 0x4
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+index 33f91199bf..be5122650a 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+@@ -2,3 +2,4 @@ GLIBC_2.2 __libc_stack_end D 0x8
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+index d3cdf7611e..afddaec57c 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+@@ -2,3 +2,4 @@ GLIBC_2.2.5 __libc_stack_end D 0x8
+ GLIBC_2.2.5 _dl_mcount F
+ GLIBC_2.2.5 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
++GLIBC_2.34 __rtld_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+index c70bccf782..defc488d13 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+@@ -2,3 +2,4 @@ GLIBC_2.16 __libc_stack_end D 0x4
+ GLIBC_2.16 __tls_get_addr F
+ GLIBC_2.16 _dl_mcount F
+ GLIBC_2.16 _r_debug D 0x14
++GLIBC_2.34 __rtld_version_placeholder F
+--
+2.27.0
+
diff --git a/Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch b/Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch
new file mode 100644
index 0000000..3825b15
--- /dev/null
+++ b/Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch
@@ -0,0 +1,31 @@
+From 645277434a42efc547d2cac8bfede4da10b4049f Mon Sep 17 00:00:00 2001
+From: Paul Eggert <eggert@cs.ucla.edu>
+Date: Mon, 13 Sep 2021 22:49:45 -0700
+Subject: [PATCH] Fix subscript error with odd TZif file [BZ #28338]
+
+* time/tzfile.c (__tzfile_compute): Fix unlikely off-by-one bug
+that accessed before start of an array when an oddball-but-valid
+TZif file was queried with an unusual time_t value.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ time/tzfile.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/time/tzfile.c b/time/tzfile.c
+index 4377018..190a777 100644
+--- a/time/tzfile.c
++++ b/time/tzfile.c
+@@ -765,8 +765,7 @@ __tzfile_compute (__time64_t timer, int use_localtime,
+ *leap_correct = leaps[i].change;
+
+ if (timer == leaps[i].transition /* Exactly at the transition time. */
+- && ((i == 0 && leaps[i].change > 0)
+- || leaps[i].change > leaps[i - 1].change))
++ && (leaps[i].change > (i == 0 ? 0 : leaps[i - 1].change)))
+ {
+ *leap_hit = 1;
+ while (i > 0
+--
+1.8.3.1
+
diff --git a/Fix-ununsed-fstatat64_time64_statx.patch b/Fix-ununsed-fstatat64_time64_statx.patch
new file mode 100644
index 0000000..da7c7a2
--- /dev/null
+++ b/Fix-ununsed-fstatat64_time64_statx.patch
@@ -0,0 +1,41 @@
+From c7f05bd5342517f3f751e6ea8dec1916b80bee8a Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 9 Mar 2022 18:35:39 -0300
+Subject: [PATCH] Fix ununsed fstatat64_time64_statx
+
+It is only called for legacy ABIs.
+---
+ sysdeps/unix/sysv/linux/fstatat64.c | 10 +++++-----
+ 1 file changed, 5 insertions(+), 5 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
+index a82d3dd4df..2ab914380d 100644
+--- a/sysdeps/unix/sysv/linux/fstatat64.c
++++ b/sysdeps/unix/sysv/linux/fstatat64.c
+@@ -40,6 +40,11 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
+ "__blkcnt_t and __blkcnt64_t must match");
+ #endif
+
++#if (__WORDSIZE == 32 \
++ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
++ || defined STAT_HAS_TIME32
++# define FSTATAT_USE_STATX 1
++
+ static inline int
+ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
+ int flag)
+@@ -73,11 +78,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
+
+ return r;
+ }
+-
+-#if (__WORDSIZE == 32 \
+- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+- || defined STAT_HAS_TIME32
+-# define FSTATAT_USE_STATX 1
+ #else
+ # define FSTATAT_USE_STATX 0
+ #endif
+--
+2.33.0
+
diff --git a/Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch b/Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch
new file mode 100644
index 0000000..9115fc4
--- /dev/null
+++ b/Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch
@@ -0,0 +1,158 @@
+From 01bffc013cdad1e0c45db7aa57efb2bee61f3338 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Fri, 29 Oct 2021 14:53:55 +0530
+Subject: [PATCH] Handle NULL input to malloc_usable_size [BZ #28506]
+
+Hoist the NULL check for malloc_usable_size into its entry points in
+malloc-debug and malloc and assume non-NULL in all callees. This fixes
+BZ #28506
+
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+Reviewed-by: Richard W.M. Jones <rjones@redhat.com>
+(cherry picked from commit 88e316b06414ee7c944cd6f8b30b07a972b78499)
+---
+ malloc/malloc-debug.c | 13 +++++++------
+ malloc/malloc.c | 25 +++++++++----------------
+ malloc/tst-malloc-usable.c | 22 +++++++++-------------
+ 3 files changed, 25 insertions(+), 35 deletions(-)
+
+diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c
+index 9922ef5..3d7e6d4 100644
+--- a/malloc/malloc-debug.c
++++ b/malloc/malloc-debug.c
+@@ -1,5 +1,6 @@
+ /* Malloc debug DSO.
+ Copyright (C) 2021 Free Software Foundation, Inc.
++ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -399,17 +400,17 @@ strong_alias (__debug_calloc, calloc)
+ size_t
+ malloc_usable_size (void *mem)
+ {
++ if (mem == NULL)
++ return 0;
++
+ if (__is_malloc_debug_enabled (MALLOC_MCHECK_HOOK))
+ return mcheck_usable_size (mem);
+ if (__is_malloc_debug_enabled (MALLOC_CHECK_HOOK))
+ return malloc_check_get_size (mem);
+
+- if (mem != NULL)
+- {
+- mchunkptr p = mem2chunk (mem);
+- if (DUMPED_MAIN_ARENA_CHUNK (p))
+- return chunksize (p) - SIZE_SZ;
+- }
++ mchunkptr p = mem2chunk (mem);
++ if (DUMPED_MAIN_ARENA_CHUNK (p))
++ return chunksize (p) - SIZE_SZ;
+
+ return musable (mem);
+ }
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index e065785..7882c70 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -1,5 +1,6 @@
+ /* Malloc implementation for multiple threads without lock contention.
+ Copyright (C) 1996-2021 Free Software Foundation, Inc.
++ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+ Contributed by Wolfram Gloger <wg@malloc.de>
+ and Doug Lea <dl@cs.oswego.edu>, 2001.
+@@ -5009,20 +5010,13 @@ __malloc_trim (size_t s)
+ static size_t
+ musable (void *mem)
+ {
+- mchunkptr p;
+- if (mem != 0)
+- {
+- size_t result = 0;
+-
+- p = mem2chunk (mem);
++ mchunkptr p = mem2chunk (mem);
+
+- if (chunk_is_mmapped (p))
+- result = chunksize (p) - CHUNK_HDR_SZ;
+- else if (inuse (p))
+- result = memsize (p);
++ if (chunk_is_mmapped (p))
++ return chunksize (p) - CHUNK_HDR_SZ;
++ else if (inuse (p))
++ return memsize (p);
+
+- return result;
+- }
+ return 0;
+ }
+
+@@ -5030,10 +5024,9 @@ musable (void *mem)
+ size_t
+ __malloc_usable_size (void *m)
+ {
+- size_t result;
+-
+- result = musable (m);
+- return result;
++ if (m == NULL)
++ return 0;
++ return musable (m);
+ }
+ #endif
+
+diff --git a/malloc/tst-malloc-usable.c b/malloc/tst-malloc-usable.c
+index a1074b7..b0d702b 100644
+--- a/malloc/tst-malloc-usable.c
++++ b/malloc/tst-malloc-usable.c
+@@ -2,6 +2,7 @@
+ MALLOC_CHECK_ exported to a positive value.
+
+ Copyright (C) 2012-2021 Free Software Foundation, Inc.
++ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -21,29 +22,24 @@
+ #include <malloc.h>
+ #include <string.h>
+ #include <stdio.h>
++#include <support/support.h>
++#include <support/check.h>
+
+ static int
+ do_test (void)
+ {
+ size_t usable_size;
+ void *p = malloc (7);
+- if (!p)
+- {
+- printf ("memory allocation failed\n");
+- return 1;
+- }
+
++ TEST_VERIFY_EXIT (p != NULL);
+ usable_size = malloc_usable_size (p);
+- if (usable_size != 7)
+- {
+- printf ("malloc_usable_size: expected 7 but got %zu\n", usable_size);
+- return 1;
+- }
+-
++ TEST_COMPARE (usable_size, 7);
+ memset (p, 0, usable_size);
+ free (p);
++
++ TEST_COMPARE (malloc_usable_size (NULL), 0);
++
+ return 0;
+ }
+
+-#define TEST_FUNCTION do_test ()
+-#include "../test-skeleton.c"
++#include "support/test-driver.c"
+--
+1.8.3.1
+
diff --git a/LanguageList b/LanguageList
new file mode 100644
index 0000000..7ae6391
--- /dev/null
+++ b/LanguageList
@@ -0,0 +1,196 @@
+glibc-langpack-aa
+glibc-langpack-af
+glibc-langpack-agr
+glibc-langpack-ak
+glibc-langpack-am
+glibc-langpack-an
+glibc-langpack-anp
+glibc-langpack-ar
+glibc-langpack-as
+glibc-langpack-ast
+glibc-langpack-ayc
+glibc-langpack-az
+glibc-langpack-be
+glibc-langpack-bem
+glibc-langpack-ber
+glibc-langpack-bg
+glibc-langpack-bhb
+glibc-langpack-bho
+glibc-langpack-bi
+glibc-langpack-bn
+glibc-langpack-bo
+glibc-langpack-br
+glibc-langpack-brx
+glibc-langpack-bs
+glibc-langpack-byn
+glibc-langpack-ca
+glibc-langpack-ce
+glibc-langpack-chr
+glibc-langpack-cmn
+glibc-langpack-crh
+glibc-langpack-cs
+glibc-langpack-csb
+glibc-langpack-cv
+glibc-langpack-cy
+glibc-langpack-da
+glibc-langpack-de
+glibc-langpack-doi
+glibc-langpack-dsb
+glibc-langpack-dv
+glibc-langpack-dz
+glibc-langpack-el
+glibc-langpack-en
+glibc-langpack-eo
+glibc-langpack-es
+glibc-langpack-et
+glibc-langpack-eu
+glibc-langpack-fa
+glibc-langpack-ff
+glibc-langpack-fi
+glibc-langpack-fil
+glibc-langpack-fo
+glibc-langpack-fr
+glibc-langpack-fur
+glibc-langpack-fy
+glibc-langpack-ga
+glibc-langpack-gd
+glibc-langpack-gez
+glibc-langpack-gl
+glibc-langpack-gu
+glibc-langpack-gv
+glibc-langpack-ha
+glibc-langpack-hak
+glibc-langpack-he
+glibc-langpack-hi
+glibc-langpack-hif
+glibc-langpack-hne
+glibc-langpack-hr
+glibc-langpack-hsb
+glibc-langpack-ht
+glibc-langpack-hu
+glibc-langpack-hy
+glibc-langpack-ia
+glibc-langpack-id
+glibc-langpack-ig
+glibc-langpack-ik
+glibc-langpack-is
+glibc-langpack-it
+glibc-langpack-iu
+glibc-langpack-ja
+glibc-langpack-ka
+glibc-langpack-kab
+glibc-langpack-kk
+glibc-langpack-kl
+glibc-langpack-km
+glibc-langpack-kn
+glibc-langpack-ko
+glibc-langpack-kok
+glibc-langpack-ks
+glibc-langpack-ku
+glibc-langpack-kw
+glibc-langpack-ky
+glibc-langpack-lb
+glibc-langpack-lg
+glibc-langpack-li
+glibc-langpack-lij
+glibc-langpack-ln
+glibc-langpack-lo
+glibc-langpack-lt
+glibc-langpack-lv
+glibc-langpack-lzh
+glibc-langpack-mag
+glibc-langpack-mai
+glibc-langpack-mfe
+glibc-langpack-mg
+glibc-langpack-mhr
+glibc-langpack-mi
+glibc-langpack-miq
+glibc-langpack-mjw
+glibc-langpack-mk
+glibc-langpack-ml
+glibc-langpack-mn
+glibc-langpack-mni
+glibc-langpack-mr
+glibc-langpack-ms
+glibc-langpack-mt
+glibc-langpack-my
+glibc-langpack-nan
+glibc-langpack-nb
+glibc-langpack-nds
+glibc-langpack-ne
+glibc-langpack-nhn
+glibc-langpack-niu
+glibc-langpack-nl
+glibc-langpack-nn
+glibc-langpack-nr
+glibc-langpack-nso
+glibc-langpack-oc
+glibc-langpack-om
+glibc-langpack-or
+glibc-langpack-os
+glibc-langpack-pa
+glibc-langpack-pap
+glibc-langpack-pl
+glibc-langpack-ps
+glibc-langpack-pt
+glibc-langpack-quz
+glibc-langpack-raj
+glibc-langpack-ro
+glibc-langpack-ru
+glibc-langpack-rw
+glibc-langpack-sa
+glibc-langpack-sah
+glibc-langpack-sat
+glibc-langpack-sc
+glibc-langpack-sd
+glibc-langpack-se
+glibc-langpack-sgs
+glibc-langpack-shn
+glibc-langpack-shs
+glibc-langpack-si
+glibc-langpack-sid
+glibc-langpack-sk
+glibc-langpack-sl
+glibc-langpack-sm
+glibc-langpack-so
+glibc-langpack-sq
+glibc-langpack-sr
+glibc-langpack-ss
+glibc-langpack-st
+glibc-langpack-sv
+glibc-langpack-sw
+glibc-langpack-szl
+glibc-langpack-ta
+glibc-langpack-tcy
+glibc-langpack-te
+glibc-langpack-tg
+glibc-langpack-th
+glibc-langpack-the
+glibc-langpack-ti
+glibc-langpack-tig
+glibc-langpack-tk
+glibc-langpack-tl
+glibc-langpack-tn
+glibc-langpack-to
+glibc-langpack-tpi
+glibc-langpack-tr
+glibc-langpack-ts
+glibc-langpack-tt
+glibc-langpack-ug
+glibc-langpack-uk
+glibc-langpack-unm
+glibc-langpack-ur
+glibc-langpack-uz
+glibc-langpack-ve
+glibc-langpack-vi
+glibc-langpack-wa
+glibc-langpack-wae
+glibc-langpack-wal
+glibc-langpack-wo
+glibc-langpack-xh
+glibc-langpack-yi
+glibc-langpack-yo
+glibc-langpack-yue
+glibc-langpack-yuw
+glibc-langpack-zh
+glibc-langpack-zu
diff --git a/LicenseList b/LicenseList
new file mode 100644
index 0000000..bcffe7a
--- /dev/null
+++ b/LicenseList
@@ -0,0 +1,26 @@
+In general, GPLv2+ is used by programs, LGPLv2+ is used for
+libraries.
+
+LGPLv2+ with exceptions is used for things that are linked directly
+into dynamically linked programs and shared libraries (e.g. crt
+files, lib*_nonshared.a). Historically, this exception also applies
+to parts of libio.
+
+GPLv2+ with exceptions is used for parts of the Arm unwinder.
+
+GFDL is used for the documentation.
+
+Some other licenses are used in various places (BSD, Inner-Net,
+ISC, Public Domain).
+
+HSRL and FSFAP are only used in test cases, which currently do not
+ship in binary RPMs, so they are not listed here. MIT is used for
+scripts/install-sh, which does not ship, either.
+
+GPLv3+ is used by manual/texinfo.tex, which we do not use.
+
+LGPLv3+ is used by some Hurd code, which we do not build.
+
+LGPLv2 is used in one place (time/timespec_get.c, by mistake), but
+it is not actually compiled, so it does not matter for libraries.
+
diff --git a/Linux-Avoid-closing-1-on-failure-in-__closefrom_fall.patch b/Linux-Avoid-closing-1-on-failure-in-__closefrom_fall.patch
new file mode 100644
index 0000000..b7596e7
--- /dev/null
+++ b/Linux-Avoid-closing-1-on-failure-in-__closefrom_fall.patch
@@ -0,0 +1,26 @@
+From 5ad9d62c3b7438c70452d6a9b2c7810f9f28bf32 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 24 Sep 2021 19:51:41 +0200
+Subject: [PATCH] Linux: Avoid closing -1 on failure in __closefrom_fallback
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+---
+ sysdeps/unix/sysv/linux/closefrom_fallback.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/closefrom_fallback.c b/sysdeps/unix/sysv/linux/closefrom_fallback.c
+index 9cca556..f215fd2 100644
+--- a/sysdeps/unix/sysv/linux/closefrom_fallback.c
++++ b/sysdeps/unix/sysv/linux/closefrom_fallback.c
+@@ -48,7 +48,7 @@ __closefrom_fallback (int from, _Bool dirfd_fallback)
+ dirfd = __open_nocancel (FD_TO_FILENAME_PREFIX, O_RDONLY | O_DIRECTORY,
+ 0);
+ if (dirfd == -1)
+- goto err;
++ return false;
+ }
+
+ char buffer[1024];
+--
+1.8.3.1
+
diff --git a/Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch b/Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch
new file mode 100644
index 0000000..9ae3ffb
--- /dev/null
+++ b/Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch
@@ -0,0 +1,53 @@
+From 3438bbca90895d32825a52e31a77dc44d273c1c1 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 24 Jan 2022 18:14:24 +0100
+Subject: [PATCH] Linux: Detect user namespace support in
+ io/tst-getcwd-smallbuff
+
+Otherwise the test fails with certain container runtimes.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit 5b8e7980c5dabd9aaefeba4f0208baa8cf7653ee)
+---
+ sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
+index d460d6e..55362f6 100644
+--- a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
++++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
+@@ -34,6 +34,7 @@
+ #include <sys/un.h>
+ #include <support/check.h>
+ #include <support/temp_file.h>
++#include <support/test-driver.h>
+ #include <support/xsched.h>
+ #include <support/xunistd.h>
+
+@@ -188,6 +189,23 @@ do_test (void)
+ xmkdir (MOUNT_NAME, S_IRWXU);
+ atexit (do_cleanup);
+
++ /* Check whether user namespaces are supported. */
++ {
++ pid_t pid = xfork ();
++ if (pid == 0)
++ {
++ if (unshare (CLONE_NEWUSER | CLONE_NEWNS) != 0)
++ _exit (EXIT_UNSUPPORTED);
++ else
++ _exit (0);
++ }
++ int status;
++ xwaitpid (pid, &status, 0);
++ TEST_VERIFY_EXIT (WIFEXITED (status));
++ if (WEXITSTATUS (status) != 0)
++ return WEXITSTATUS (status);
++ }
++
+ TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0);
+ pid_t child_pid = xclone (child_func, NULL, child_stack,
+ sizeof (child_stack),
+--
+1.8.3.1
+
diff --git a/Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch b/Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch
new file mode 100644
index 0000000..b33981d
--- /dev/null
+++ b/Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch
@@ -0,0 +1,72 @@
+From c87fcacc50505d550f1bb038382bcc7ea73a5926 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 6 Aug 2021 09:51:38 +0200
+Subject: [PATCH] Linux: Fix fcntl, ioctl, prctl redirects for _TIME_BITS=64
+ (bug 28182)
+
+__REDIRECT and __THROW are not compatible with C++ due to the ordering of the
+__asm__ alias and the throw specifier. __REDIRECT_NTH has to be used
+instead.
+
+Fixes commit 8a40aff86ba5f64a3a84883e539cb67b ("io: Add time64 alias
+for fcntl"), commit 82c395d91ea4f69120d453aeec398e30 ("misc: Add
+time64 alias for ioctl"), commit b39ffab860cd743a82c91946619f1b8158
+("Linux: Add time64 alias for prctl").
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ io/fcntl.h | 8 ++++----
+ misc/sys/ioctl.h | 4 ++--
+ sysdeps/unix/sysv/linux/sys/prctl.h | 2 +-
+ 3 files changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/io/fcntl.h b/io/fcntl.h
+index 8917a73..1c96f98 100644
+--- a/io/fcntl.h
++++ b/io/fcntl.h
+@@ -187,10 +187,10 @@ extern int fcntl64 (int __fd, int __cmd, ...);
+ # endif
+ #else /* __USE_TIME_BITS64 */
+ # ifdef __REDIRECT
+-extern int __REDIRECT (fcntl, (int __fd, int __request, ...),
+- __fcntl_time64) __THROW;
+-extern int __REDIRECT (fcntl64, (int __fd, int __request, ...),
+- __fcntl_time64) __THROW;
++extern int __REDIRECT_NTH (fcntl, (int __fd, int __request, ...),
++ __fcntl_time64);
++extern int __REDIRECT_NTH (fcntl64, (int __fd, int __request, ...),
++ __fcntl_time64);
+ # else
+ extern int __fcntl_time64 (int __fd, int __request, ...) __THROW;
+ # define fcntl64 __fcntl_time64
+diff --git a/misc/sys/ioctl.h b/misc/sys/ioctl.h
+index 6884d99..9945c1e 100644
+--- a/misc/sys/ioctl.h
++++ b/misc/sys/ioctl.h
+@@ -42,8 +42,8 @@ __BEGIN_DECLS
+ extern int ioctl (int __fd, unsigned long int __request, ...) __THROW;
+ #else
+ # ifdef __REDIRECT
+-extern int __REDIRECT (ioctl, (int __fd, unsigned long int __request, ...),
+- __ioctl_time64) __THROW;
++extern int __REDIRECT_NTH (ioctl, (int __fd, unsigned long int __request, ...),
++ __ioctl_time64);
+ # else
+ extern int __ioctl_time64 (int __fd, unsigned long int __request, ...) __THROW;
+ # define ioctl __ioctl_time64
+diff --git a/sysdeps/unix/sysv/linux/sys/prctl.h b/sysdeps/unix/sysv/linux/sys/prctl.h
+index db88938..f0e0d2f 100644
+--- a/sysdeps/unix/sysv/linux/sys/prctl.h
++++ b/sysdeps/unix/sysv/linux/sys/prctl.h
+@@ -42,7 +42,7 @@ __BEGIN_DECLS
+ extern int prctl (int __option, ...) __THROW;
+ #else
+ # ifdef __REDIRECT
+-extern int __REDIRECT (prctl, (int __option, ...), __prctl_time64) __THROW;
++extern int __REDIRECT_NTH (prctl, (int __option, ...), __prctl_time64);
+ # else
+ extern int __prctl_time64 (int __option,d ...) __THROW;
+ # define ioctl __prctl_time64
+--
+1.8.3.1
+
diff --git a/Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch b/Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch
new file mode 100644
index 0000000..45655a6
--- /dev/null
+++ b/Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch
@@ -0,0 +1,498 @@
+From 489d0b8b32548bc569cd3067aebf98b030720753 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 27 Jan 2022 16:45:18 -0300
+Subject: [PATCH] Linux: Only generate 64 bit timestamps for 64 bit time_t
+ recvmsg/recvmmsg
+
+The timestamps created by __convert_scm_timestamps only make sense for
+64 bit time_t programs, 32 bit time_t programs will ignore 64 bit time_t
+timestamps since SO_TIMESTAMP will be defined to old values (either by
+glibc or kernel headers).
+
+Worse, if the buffer is not suffice MSG_CTRUNC is set to indicate it
+(which breaks some programs [1]).
+
+This patch makes only 64 bit time_t recvmsg and recvmmsg to call
+__convert_scm_timestamps. Also, the assumption to called it is changed
+from __ASSUME_TIME64_SYSCALLS to __TIMESIZE != 64 since the setsockopt
+might be called by libraries built without __TIME_BITS=64. The
+MSG_CTRUNC is only set for the 64 bit symbols, it should happen only
+if 64 bit time_t programs run older kernels.
+
+Checked on x86_64-linux-gnu and i686-linux-gnu.
+
+[1] https://github.com/systemd/systemd/pull/20567
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+(cherry picked from commit 948ce73b31fdb0860bcec4b8e62b14e88234f98a)
+---
+ include/sys/socket.h | 10 +-
+ sysdeps/unix/sysv/linux/Makefile | 10 +-
+ sysdeps/unix/sysv/linux/recvmmsg.c | 36 ++-
+ sysdeps/unix/sysv/linux/recvmsg.c | 34 ++-
+ .../tst-socket-timestamp-compat-time64.c | 1 +
+ .../sysv/linux/tst-socket-timestamp-compat.c | 265 ++++++++++++++++++
+ 6 files changed, 330 insertions(+), 26 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c
+ create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
+
+diff --git a/include/sys/socket.h b/include/sys/socket.h
+index a1d749f9fa..6e4cf5077f 100644
+--- a/include/sys/socket.h
++++ b/include/sys/socket.h
+@@ -98,15 +98,21 @@ extern int __sendmmsg (int __fd, struct mmsghdr *__vmessages,
+ libc_hidden_proto (__sendmmsg)
+ #endif
+
+-/* Receive a message as described by MESSAGE from socket FD.
+- Returns the number of bytes read or -1 for errors. */
+ extern ssize_t __libc_recvmsg (int __fd, struct msghdr *__message,
+ int __flags);
+ extern ssize_t __recvmsg (int __fd, struct msghdr *__message,
+ int __flags) attribute_hidden;
+ #if __TIMESIZE == 64
++# define __libc_recvmsg64 __libc_recvmsg
++# define __recvmsg64 __recvmsg
+ # define __recvmmsg64 __recvmmsg
+ #else
++extern ssize_t __libc_recvmsg64 (int __fd, struct msghdr *__message,
++ int __flags);
++extern ssize_t __recvmsg64 (int __fd, struct msghdr *__message,
++ int __flags);
++/* Receive a message as described by MESSAGE from socket FD.
++ Returns the number of bytes read or -1 for errors. */
+ extern int __recvmmsg64 (int __fd, struct mmsghdr *vmessages,
+ unsigned int vlen, int flags,
+ struct __timespec64 *timeout);
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index 964f641ef9..c34774806f 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -262,8 +262,14 @@ sysdep_routines += cmsg_nxthdr
+ CFLAGS-recvmmsg.c = -fexceptions -fasynchronous-unwind-tables
+ CFLAGS-sendmmsg.c = -fexceptions -fasynchronous-unwind-tables
+
+-tests += tst-socket-timestamp
+-tests-time64 += tst-socket-timestamp-time64
++tests += \
++ tst-socket-timestamp \
++ tst-socket-timestamp-compat \
++ # tests
++tests-time64 += \
++ tst-socket-timestamp-time64 \
++ tst-socket-timestamp-compat-time64
++ # tests-time64
+
+ tests-special += $(objpfx)tst-socket-consts.out
+ $(objpfx)tst-socket-consts.out: ../sysdeps/unix/sysv/linux/tst-socket-consts.py
+diff --git a/sysdeps/unix/sysv/linux/recvmmsg.c b/sysdeps/unix/sysv/linux/recvmmsg.c
+index 5cd107ffa9..fca9f6582d 100644
+--- a/sysdeps/unix/sysv/linux/recvmmsg.c
++++ b/sysdeps/unix/sysv/linux/recvmmsg.c
+@@ -20,9 +20,9 @@
+ #include <sysdep.h>
+ #include <socketcall.h>
+
+-int
+-__recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
+- struct __timespec64 *timeout)
++static int
++recvmmsg_syscall (int fd, struct mmsghdr *vmessages, unsigned int vlen,
++ int flags, struct __timespec64 *timeout)
+ {
+ #ifndef __NR_recvmmsg_time64
+ # define __NR_recvmmsg_time64 __NR_recvmmsg
+@@ -45,12 +45,6 @@ __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
+ pts32 = &ts32;
+ }
+
+- socklen_t csize[IOV_MAX];
+- if (vlen > IOV_MAX)
+- vlen = IOV_MAX;
+- for (int i = 0; i < vlen; i++)
+- csize[i] = vmessages[i].msg_hdr.msg_controllen;
+-
+ # ifdef __ASSUME_RECVMMSG_SYSCALL
+ r = SYSCALL_CANCEL (recvmmsg, fd, vmessages, vlen, flags, pts32);
+ # else
+@@ -60,11 +54,31 @@ __recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
+ {
+ if (timeout != NULL)
+ *timeout = valid_timespec_to_timespec64 (ts32);
++ }
++#endif
++ return r;
++}
++
++int
++__recvmmsg64 (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
++ struct __timespec64 *timeout)
++{
++#if __TIMESIZE != 64
++ socklen_t csize[IOV_MAX];
++ if (vlen > IOV_MAX)
++ vlen = IOV_MAX;
++ for (int i = 0; i < vlen; i++)
++ csize[i] = vmessages[i].msg_hdr.msg_controllen;
++#endif
+
++ int r = recvmmsg_syscall (fd, vmessages, vlen, flags, timeout);
++#if __TIMESIZE != 64
++ if (r > 0)
++ {
+ for (int i=0; i < r; i++)
+ __convert_scm_timestamps (&vmessages[i].msg_hdr, csize[i]);
+ }
+-#endif /* __ASSUME_TIME64_SYSCALLS */
++#endif
+ return r;
+ }
+ #if __TIMESIZE != 64
+@@ -80,7 +94,7 @@ __recvmmsg (int fd, struct mmsghdr *vmessages, unsigned int vlen, int flags,
+ ts64 = valid_timespec_to_timespec64 (*timeout);
+ pts64 = &ts64;
+ }
+- int r = __recvmmsg64 (fd, vmessages, vlen, flags, pts64);
++ int r = recvmmsg_syscall (fd, vmessages, vlen, flags, pts64);
+ if (r >= 0 && timeout != NULL)
+ /* The remanining timeout will be always less the input TIMEOUT. */
+ *timeout = valid_timespec64_to_timespec (ts64);
+diff --git a/sysdeps/unix/sysv/linux/recvmsg.c b/sysdeps/unix/sysv/linux/recvmsg.c
+index 07212f7c86..c4b4704fd6 100644
+--- a/sysdeps/unix/sysv/linux/recvmsg.c
++++ b/sysdeps/unix/sysv/linux/recvmsg.c
+@@ -20,29 +20,41 @@
+ #include <sysdep-cancel.h>
+ #include <socketcall.h>
+
++static int
++__recvmsg_syscall (int fd, struct msghdr *msg, int flags)
++{
++#ifdef __ASSUME_RECVMSG_SYSCALL
++ return SYSCALL_CANCEL (recvmsg, fd, msg, flags);
++#else
++ return SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
++#endif
++}
++
+ ssize_t
+-__libc_recvmsg (int fd, struct msghdr *msg, int flags)
++__libc_recvmsg64 (int fd, struct msghdr *msg, int flags)
+ {
+ ssize_t r;
+-#ifndef __ASSUME_TIME64_SYSCALLS
++#if __TIMESIZE != 64
+ socklen_t orig_controllen = msg != NULL ? msg->msg_controllen : 0;
+ #endif
+
+-#ifdef __ASSUME_RECVMSG_SYSCALL
+- r = SYSCALL_CANCEL (recvmsg, fd, msg, flags);
+-#else
+- r = SOCKETCALL_CANCEL (recvmsg, fd, msg, flags);
+-#endif
++ r = __recvmsg_syscall (fd, msg, flags);
+
+-#ifndef __ASSUME_TIME64_SYSCALLS
++#if __TIMESIZE != 64
+ if (r >= 0 && orig_controllen != 0)
+ __convert_scm_timestamps (msg, orig_controllen);
+ #endif
+
+ return r;
+ }
+-weak_alias (__libc_recvmsg, recvmsg)
+-weak_alias (__libc_recvmsg, __recvmsg)
+ #if __TIMESIZE != 64
+-weak_alias (__recvmsg, __recvmsg64)
++weak_alias (__libc_recvmsg64, __recvmsg64)
++
++ssize_t
++__libc_recvmsg (int fd, struct msghdr *msg, int flags)
++{
++ return __recvmsg_syscall (fd, msg, flags);
++}
+ #endif
++weak_alias (__libc_recvmsg, recvmsg)
++weak_alias (__libc_recvmsg, __recvmsg)
+diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c
+new file mode 100644
+index 0000000000..96a0bef0bf
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat-time64.c
+@@ -0,0 +1 @@
++#include "tst-socket-timestamp-compat.c"
+diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
+new file mode 100644
+index 0000000000..de261dae5a
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
+@@ -0,0 +1,265 @@
++/* Check recvmsg/recvmmsg 64-bit timestamp support.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <arpa/inet.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/xsocket.h>
++#include <support/xunistd.h>
++#include <stdbool.h>
++
++/* AF_INET socket and address used to receive data. */
++static int srv;
++static struct sockaddr_in srv_addr;
++
++static int
++do_sendto (const struct sockaddr_in *addr, int payload)
++{
++ int s = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
++ xconnect (s, (const struct sockaddr *) addr, sizeof (*addr));
++
++ xsendto (s, &payload, sizeof (payload), 0, (const struct sockaddr *) addr,
++ sizeof (*addr));
++
++ xclose (s);
++
++ return 0;
++}
++
++static void
++do_recvmsg_ancillary (bool use_multi_call, struct mmsghdr *mmhdr,
++ void *msgbuf, size_t msgbuflen, int exp_payload)
++{
++ int payload;
++ struct iovec iov =
++ {
++ .iov_base = &payload,
++ .iov_len = sizeof (payload)
++ };
++ mmhdr->msg_hdr.msg_name = NULL;
++ mmhdr->msg_hdr.msg_iov = &iov;
++ mmhdr->msg_hdr.msg_iovlen = 1;
++ mmhdr->msg_hdr.msg_control = msgbuf;
++ mmhdr->msg_hdr.msg_controllen = msgbuflen;
++
++ int r;
++ if (use_multi_call)
++ {
++ r = recvmmsg (srv, mmhdr, 1, 0, NULL);
++ if (r >= 0)
++ r = mmhdr->msg_len;
++ }
++ else
++ r = recvmsg (srv, &mmhdr->msg_hdr, 0);
++ TEST_COMPARE (r, sizeof (int));
++ TEST_COMPARE (payload, exp_payload);
++}
++
++/* Check if recvmsg create the additional 64 bit timestamp if only 32 bit
++ is enabled for 64 bit recvmsg symbol. */
++static void
++do_test_large_buffer (bool mc)
++{
++ struct mmsghdr mmhdr = { 0 };
++ /* It should be large enought for either timeval/timespec and the
++ 64 time type as well. */
++
++ union
++ {
++ struct cmsghdr cmsghdr;
++ char msgbuf[512];
++ } control;
++
++ /* Enable 32 bit timeval precision and check if no 64 bit timeval stamp
++ is created. */
++ {
++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP_OLD, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++
++ do_sendto (&srv_addr, 42);
++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
++
++ bool found_timestamp = false;
++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
++ cmsg != NULL;
++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
++ {
++ if (cmsg->cmsg_level != SOL_SOCKET)
++ continue;
++
++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMP_NEW)
++ found_timestamp = true;
++ else
++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMP_NEW);
++ }
++
++ TEST_COMPARE (found_timestamp, sizeof (time_t) > 4);
++ }
++
++ /* Same as before, but for timespec. */
++ {
++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS_OLD, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++
++ do_sendto (&srv_addr, 42);
++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
++
++ bool found_timestamp = false;
++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
++ cmsg != NULL;
++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
++ {
++ if (cmsg->cmsg_level != SOL_SOCKET)
++ continue;
++
++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMPNS_NEW)
++ found_timestamp = true;
++ else
++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMPNS_NEW);
++ }
++
++ TEST_COMPARE (found_timestamp, sizeof (time_t) > 4);
++ }
++}
++
++/* Check if recvmsg does not create the additional 64 bit timestamp if
++ only 32 bit timestamp is enabled if the ancillary buffer is not large
++ enought. Also checks if MSG_CTRUNC is set iff for 64 bit recvmsg
++ symbol. */
++static void
++do_test_small_buffer (bool mc)
++{
++ struct mmsghdr mmhdr = { 0 };
++
++ /* Enable 32 bit timeval precision and check if no 64 bit timeval stamp
++ is created. */
++ {
++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP_OLD, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++
++ union
++ {
++ struct cmsghdr cmsghdr;
++ char msgbuf[CMSG_SPACE (sizeof (struct timeval))];
++ } control;
++
++ do_sendto (&srv_addr, 42);
++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
++
++ bool found_timestamp = false;
++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
++ cmsg != NULL;
++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
++ {
++ if (cmsg->cmsg_level != SOL_SOCKET)
++ continue;
++
++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMP_NEW)
++ found_timestamp = true;
++ else
++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMP_NEW);
++ }
++
++ if (sizeof (time_t) > 4)
++ {
++ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC));
++ TEST_COMPARE (found_timestamp, 0);
++ }
++ else
++ {
++ TEST_VERIFY (!(mmhdr.msg_hdr.msg_flags & MSG_CTRUNC));
++ TEST_COMPARE (found_timestamp, 0);
++ }
++ }
++
++ /* Same as before, but for timespec. */
++ {
++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS_OLD, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++
++ union
++ {
++ struct cmsghdr cmsghdr;
++ char msgbuf[CMSG_SPACE (sizeof (struct timespec))];
++ } control;
++
++ do_sendto (&srv_addr, 42);
++ do_recvmsg_ancillary (mc, &mmhdr, &control, sizeof control, 42);
++
++ bool found_timestamp = false;
++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
++ cmsg != NULL;
++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
++ {
++ if (cmsg->cmsg_level != SOL_SOCKET)
++ continue;
++
++ if (sizeof (time_t) > 4 && cmsg->cmsg_type == SO_TIMESTAMPNS_NEW)
++ found_timestamp = true;
++ else
++ TEST_VERIFY (cmsg->cmsg_type != SO_TIMESTAMPNS_NEW);
++ }
++
++ if (sizeof (time_t) > 4)
++ {
++ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC));
++ TEST_COMPARE (found_timestamp, 0);
++ }
++ else
++ {
++ TEST_VERIFY ((mmhdr.msg_hdr.msg_flags & MSG_CTRUNC) == 0);
++ TEST_COMPARE (found_timestamp, 0);
++ }
++ }
++}
++
++static int
++do_test (void)
++{
++ /* This test only make sense for ABIs that support 32 bit time_t socket
++ timestampss. */
++ if (sizeof (time_t) > 4 && __WORDSIZE == 64)
++ return 0;
++
++ srv = xsocket (AF_INET, SOCK_DGRAM, 0);
++ srv_addr = (struct sockaddr_in) {
++ .sin_family = AF_INET,
++ .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK) },
++ };
++ xbind (srv, (struct sockaddr *) &srv_addr, sizeof (srv_addr));
++ {
++ socklen_t sa_len = sizeof (srv_addr);
++ xgetsockname (srv, (struct sockaddr *) &srv_addr, &sa_len);
++ TEST_VERIFY (sa_len == sizeof (srv_addr));
++ }
++
++ /* Check recvmsg; */
++ do_test_large_buffer (false);
++ do_test_small_buffer (false);
++ /* Check recvmmsg. */
++ do_test_large_buffer (true);
++ do_test_small_buffer (true);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.27.0
+
diff --git a/Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch b/Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch
new file mode 100644
index 0000000..b7cbeef
--- /dev/null
+++ b/Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch
@@ -0,0 +1,241 @@
+From 5bf07e1b3a74232bfb8332275110be1a5da50f83 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 28 Sep 2021 18:55:49 +0200
+Subject: [PATCH] Linux: Simplify __opensock and fix race condition [BZ #28353]
+
+AF_NETLINK support is not quite optional on modern Linux systems
+anymore, so it is likely that the first attempt will always succeed.
+Consequently, there is no need to cache the result. Keep AF_UNIX
+and the Internet address families as a fallback, for the rare case
+that AF_NETLINK is missing. The other address families previously
+probed are totally obsolete be now, so remove them.
+
+Use this simplified version as the generic implementation, disabling
+Netlink support as needed.
+---
+ socket/opensock.c | 65 +++++---------
+ sysdeps/unix/sysv/linux/opensock.c | 114 ------------------------
+ sysdeps/unix/sysv/linux/s390/opensock.c | 2 -
+ 3 files changed, 22 insertions(+), 159 deletions(-)
+ delete mode 100644 sysdeps/unix/sysv/linux/opensock.c
+ delete mode 100644 sysdeps/unix/sysv/linux/s390/opensock.c
+
+diff --git a/socket/opensock.c b/socket/opensock.c
+index 37148d4743..ff94d27a61 100644
+--- a/socket/opensock.c
++++ b/socket/opensock.c
+@@ -1,4 +1,5 @@
+-/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
++/* Create socket with an unspecified address family for use with ioctl.
++ Copyright (C) 1999-2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -15,56 +16,34 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+-#include <stdio.h>
++#include <errno.h>
+ #include <sys/socket.h>
+-#include <libc-lock.h>
+
+ /* Return a socket of any type. The socket can be used in subsequent
+ ioctl calls to talk to the kernel. */
+ int
+ __opensock (void)
+ {
+- /* Cache the last AF that worked, to avoid many redundant calls to
+- socket(). */
+- static int sock_af = -1;
+- int fd = -1;
+- __libc_lock_define_initialized (static, lock);
+-
+- if (sock_af != -1)
+- {
+- fd = __socket (sock_af, SOCK_DGRAM, 0);
+- if (fd != -1)
+- return fd;
+- }
+-
+- __libc_lock_lock (lock);
+-
+- if (sock_af != -1)
+- fd = __socket (sock_af, SOCK_DGRAM, 0);
+-
+- if (fd == -1)
+- {
+-#ifdef AF_INET
+- fd = __socket (sock_af = AF_INET, SOCK_DGRAM, 0);
+-#endif
+-#ifdef AF_INET6
+- if (fd < 0)
+- fd = __socket (sock_af = AF_INET6, SOCK_DGRAM, 0);
+-#endif
+-#ifdef AF_IPX
+- if (fd < 0)
+- fd = __socket (sock_af = AF_IPX, SOCK_DGRAM, 0);
+-#endif
+-#ifdef AF_AX25
+- if (fd < 0)
+- fd = __socket (sock_af = AF_AX25, SOCK_DGRAM, 0);
+-#endif
+-#ifdef AF_APPLETALK
+- if (fd < 0)
+- fd = __socket (sock_af = AF_APPLETALK, SOCK_DGRAM, 0);
++ /* SOCK_DGRAM is supported by all address families. (Netlink does
++ not support SOCK_STREAM.) */
++ int type = SOCK_DGRAM | SOCK_CLOEXEC;
++ int fd;
++
++#ifdef AF_NETLINK
++ fd = __socket (AF_NETLINK, type, 0);
++ if (fd >= 0)
++ return fd;
+ #endif
+- }
+
+- __libc_lock_unlock (lock);
++ fd = __socket (AF_UNIX, type, 0);
++ if (fd >= 0)
++ return fd;
++ fd = __socket (AF_INET, type, 0);
++ if (fd >= 0)
++ return fd;
++ fd = __socket (AF_INET6, type, 0);
++ if (fd >= 0)
++ return fd;
++ __set_errno (ENOENT);
+ return fd;
+ }
+diff --git a/sysdeps/unix/sysv/linux/opensock.c b/sysdeps/unix/sysv/linux/opensock.c
+deleted file mode 100644
+index e87d6e58b0..0000000000
+--- a/sysdeps/unix/sysv/linux/opensock.c
++++ /dev/null
+@@ -1,114 +0,0 @@
+-/* Copyright (C) 1999-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <assert.h>
+-#include <errno.h>
+-#include <stdio.h>
+-#include <string.h>
+-#include <unistd.h>
+-#include <sys/socket.h>
+-
+-/* Return a socket of any type. The socket can be used in subsequent
+- ioctl calls to talk to the kernel. */
+-int
+-__opensock (void)
+-{
+- static int last_family; /* Available socket family we will use. */
+- static int last_type;
+- static const struct
+- {
+- int family;
+- const char procname[15];
+- } afs[] =
+- {
+- { AF_UNIX, "net/unix" },
+- { AF_INET, "" },
+- { AF_INET6, "net/if_inet6" },
+- { AF_AX25, "net/ax25" },
+- { AF_NETROM, "net/nr" },
+- { AF_ROSE, "net/rose" },
+- { AF_IPX, "net/ipx" },
+- { AF_APPLETALK, "net/appletalk" },
+- { AF_ECONET, "sys/net/econet" },
+- { AF_ASH, "sys/net/ash" },
+- { AF_X25, "net/x25" },
+-#ifdef NEED_AF_IUCV
+- { AF_IUCV, "net/iucv" }
+-#endif
+- };
+-#define nafs (sizeof (afs) / sizeof (afs[0]))
+- char fname[sizeof "/proc/" + 14];
+- int result;
+- int has_proc;
+- size_t cnt;
+-
+- /* We already know which family to use from the last call. Use it
+- again. */
+- if (last_family != 0)
+- {
+- assert (last_type != 0);
+-
+- result = __socket (last_family, last_type | SOCK_CLOEXEC, 0);
+- if (result != -1 || errno != EAFNOSUPPORT)
+- /* Maybe the socket type isn't supported anymore (module is
+- unloaded). In this case again try to find the type. */
+- return result;
+-
+- /* Reset the values. They seem not valid anymore. */
+- last_family = 0;
+- last_type = 0;
+- }
+-
+- /* Check whether the /proc filesystem is available. */
+- has_proc = __access ("/proc/net", R_OK) != -1;
+- strcpy (fname, "/proc/");
+-
+- /* Iterate over the interface families and find one which is
+- available. */
+- for (cnt = 0; cnt < nafs; ++cnt)
+- {
+- int type = SOCK_DGRAM;
+-
+- if (has_proc && afs[cnt].procname[0] != '\0')
+- {
+- strcpy (fname + 6, afs[cnt].procname);
+- if (__access (fname, R_OK) == -1)
+- /* The /proc entry is not available. I.e., we cannot
+- create a socket of this type (without loading the
+- module). Don't look for it since this might trigger
+- loading the module. */
+- continue;
+- }
+-
+- if (afs[cnt].family == AF_NETROM || afs[cnt].family == AF_X25)
+- type = SOCK_SEQPACKET;
+-
+- result = __socket (afs[cnt].family, type | SOCK_CLOEXEC, 0);
+- if (result != -1)
+- {
+- /* Found an available family. */
+- last_type = type;
+- last_family = afs[cnt].family;
+- return result;
+- }
+- }
+-
+- /* None of the protocol families is available. It is unclear what kind
+- of error is returned. ENOENT seems like a reasonable choice. */
+- __set_errno (ENOENT);
+- return -1;
+-}
+diff --git a/sysdeps/unix/sysv/linux/s390/opensock.c b/sysdeps/unix/sysv/linux/s390/opensock.c
+deleted file mode 100644
+index f099d651ff..0000000000
+--- a/sysdeps/unix/sysv/linux/s390/opensock.c
++++ /dev/null
+@@ -1,2 +0,0 @@
+-#define NEED_AF_IUCV 1
+-#include "../opensock.c"
+--
+2.27.0
+
diff --git a/LoongArch-Add-missing-relocation-type-in-elf.h.patch b/LoongArch-Add-missing-relocation-type-in-elf.h.patch
new file mode 100644
index 0000000..eca7a8f
--- /dev/null
+++ b/LoongArch-Add-missing-relocation-type-in-elf.h.patch
@@ -0,0 +1,71 @@
+From 8bd40a8f4fcf8086f199d62381fe2ea2502038c7 Mon Sep 17 00:00:00 2001
+From: XingLi <lixing@loongson.cn>
+Date: Wed, 24 Apr 2024 08:50:12 +0800
+Subject: [PATCH] LoongArch: Add missing relocation type in elf.h
+
+---
+ elf/elf.h | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+diff --git a/elf/elf.h b/elf/elf.h
+index 4119f784..a10e59c8 100644
+--- a/elf/elf.h
++++ b/elf/elf.h
+@@ -4104,6 +4104,54 @@ enum
+ #define R_LARCH_GNU_VTINHERIT 57
+ #define R_LARCH_GNU_VTENTRY 58
+
++/* reserved 59-63 */
++
++#define R_LARCH_B16 64
++#define R_LARCH_B21 65
++#define R_LARCH_B26 66
++#define R_LARCH_ABS_HI20 67
++#define R_LARCH_ABS_LO12 68
++#define R_LARCH_ABS64_LO20 69
++#define R_LARCH_ABS64_HI12 70
++#define R_LARCH_PCALA_HI20 71
++#define R_LARCH_PCALA_LO12 72
++#define R_LARCH_PCALA64_LO20 73
++#define R_LARCH_PCALA64_HI12 74
++#define R_LARCH_GOT_PC_HI20 75
++#define R_LARCH_GOT_PC_LO12 76
++#define R_LARCH_GOT64_PC_LO20 77
++#define R_LARCH_GOT64_PC_HI12 78
++#define R_LARCH_GOT_HI20 79
++#define R_LARCH_GOT_LO12 80
++#define R_LARCH_GOT64_LO20 81
++#define R_LARCH_GOT64_HI12 82
++#define R_LARCH_TLS_LE_HI20 83
++#define R_LARCH_TLS_LE_LO12 84
++#define R_LARCH_TLS_LE64_LO20 85
++#define R_LARCH_TLS_LE64_HI12 86
++#define R_LARCH_TLS_IE_PC_HI20 87
++#define R_LARCH_TLS_IE_PC_LO12 88
++#define R_LARCH_TLS_IE64_PC_LO20 89
++#define R_LARCH_TLS_IE64_PC_HI12 90
++#define R_LARCH_TLS_IE_HI20 91
++#define R_LARCH_TLS_IE_LO12 92
++#define R_LARCH_TLS_IE64_LO20 93
++#define R_LARCH_TLS_IE64_HI12 94
++#define R_LARCH_TLS_LD_PC_HI20 95
++#define R_LARCH_TLS_LD_HI20 96
++#define R_LARCH_TLS_GD_PC_HI20 97
++#define R_LARCH_TLS_GD_HI20 98
++#define R_LARCH_32_PCREL 99
++#define R_LARCH_RELAX 100
++#define R_LARCH_DELETE 101
++#define R_LARCH_ALIGN 102
++#define R_LARCH_PCREL20_S2 103
++#define R_LARCH_CFA 104
++#define R_LARCH_ADD6 105
++#define R_LARCH_SUB6 106
++#define R_LARCH_ADD_ULEB128 107
++#define R_LARCH_SUB_ULEB128 108
++#define R_LARCH_64_PCREL 109
+
+ /* ARCompact/ARCv2 specific relocs. */
+ #define R_ARC_NONE 0x0
+--
+2.33.0
+
diff --git a/LoongArch-Add-static-PIE-support.patch b/LoongArch-Add-static-PIE-support.patch
new file mode 100644
index 0000000..79df004
--- /dev/null
+++ b/LoongArch-Add-static-PIE-support.patch
@@ -0,0 +1,161 @@
+From d12d80cdcafd2f84321d311d6ce3e291f0e7b9a9 Mon Sep 17 00:00:00 2001
+From: XingLi <lixing@loongson.cn>
+Date: Thu, 27 Jul 2023 09:25:19 +0800
+Subject: [PATCH 2/3] LoongArch: Add static PIE support
+
+If the compiler is new enough, enable static PIE support. In the static
+PIE version of _start (in rcrt1.o), use la.pcrel instead of la.got
+because in a static PIE we cannot use GOT entries until the dynamic
+relocations for GOT are resolved.
+
+From: Xi Ruoyao <xry111@xry111.site>
+Date: Sat, 24 Sep 2022 15:45:34 +0800
+---
+ sysdeps/loongarch/configure | 51 ++++++++++++++++++++++++++++++++++
+ sysdeps/loongarch/configure.ac | 38 ++++++++++++++++++++++++-
+ sysdeps/loongarch/start.S | 16 +++++++----
+ 3 files changed, 99 insertions(+), 6 deletions(-)
+
+diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure
+index 1e5abf81..db6341e8 100644
+--- a/sysdeps/loongarch/configure
++++ b/sysdeps/loongarch/configure
+@@ -2,3 +2,54 @@
+ # Local configure fragment for sysdeps/loongarch/elf.
+
+ #AC_DEFINE(PI_STATIC_AND_HIDDEN)
++$as_echo "#define HIDDEN_VAR_NEEDS_DYNAMIC_RELOC 1" >>confdefs.h
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if the toolchain is sufficient to build static PIE on LoongArch" >&5
++$as_echo_n "checking if the toolchain is sufficient to build static PIE on LoongArch... " >&6; }
++if ${libc_cv_static_pie_on_loongarch+:} false; then :
++ $as_echo_n "(cached) " >&6
++else
++
++ cat > conftest.S << EOF
++.global _start
++.type _start, @function
++_start:
++ li.w \$a7, 93
++ /* This ensures the assembler supports explicit reloc. */
++ pcalau12i \$a0, %pc_hi20(x)
++ ld.w \$a0, \$a0, %pc_lo12(x)
++ syscall 0
++
++.data
++x:
++ .word 0
++ /* This should produce an R_LARCH_RELATIVE in the static PIE. */
++ .dword _start
++EOF
++ libc_cv_static_pie_on_loongarch=no
++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest conftest.S'
++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; }; } \
++ && { ac_try='LC_ALL=C $READELF -Wr conftest | grep -q R_LARCH_RELATIVE'
++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; }; }
++ then
++ libc_cv_static_pie_on_loongarch=yes
++ fi
++ rm -rf conftest.*
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie_on_loongarch" >&5
++$as_echo "$libc_cv_static_pie_on_loongarch" >&6; }
++
++if test "$libc_cv_static_pie_on_loongarch" = yes; then
++ $as_echo "#define SUPPORT_STATIC_PIE 1" >>confdefs.h
++
++fi
++
+diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac
+index 67b46ce0..603085cd 100644
+--- a/sysdeps/loongarch/configure.ac
++++ b/sysdeps/loongarch/configure.ac
+@@ -3,4 +3,40 @@ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+
+ dnl It is always possible to access static and hidden symbols in an
+ dnl position independent way.
+-#AC_DEFINE(PI_STATIC_AND_HIDDEN)
++ AC_DEFINE(HIDDEN_VAR_NEEDS_DYNAMIC_RELOC)
++
++dnl Test if the toolchain is new enough for static PIE.
++dnl We need a GAS supporting explicit reloc (older GAS produces stack-based
++dnl reloc and triggers an internal error in the linker). And, we need GCC to
++dnl pass the correct linker flags for static PIE. GCC >= 13 and GAS >= 2.40
++dnl satisify the requirement, but a distro may backport static PIE support into
++dnl earlier GCC or Binutils releases as well.
++AC_CACHE_CHECK([if the toolchain is sufficient to build static PIE on LoongArch],
++libc_cv_static_pie_on_loongarch, [
++ cat > conftest.S << EOF
++.global _start
++.type _start, @function
++_start:
++ li.w \$a7, 93
++ /* This ensures the assembler supports explicit reloc. */
++ pcalau12i \$a0, %pc_hi20(x)
++ ld.w \$a0, \$a0, %pc_lo12(x)
++ syscall 0
++
++.data
++x:
++ .word 0
++ /* This should produce an R_LARCH_RELATIVE in the static PIE. */
++ .dword _start
++EOF
++ libc_cv_static_pie_on_loongarch=no
++ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest conftest.S]) \
++ && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest | grep -q R_LARCH_RELATIVE])
++ then
++ libc_cv_static_pie_on_loongarch=yes
++ fi
++ rm -rf conftest.*])
++
++if test "$libc_cv_static_pie_on_loongarch" = yes; then
++ AC_DEFINE(SUPPORT_STATIC_PIE)
++fi
+diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S
+index 0deda78a..1b15fc9c 100644
+--- a/sysdeps/loongarch/start.S
++++ b/sysdeps/loongarch/start.S
+@@ -44,9 +44,15 @@ ENTRY (ENTRY_POINT)
+ cfi_undefined (1)
+ or a5, a0, zero /* rtld_fini */
+
+-/* We must get symbol main through GOT table, since main may not be local.
+- For instance: googletest defines main in dynamic library. */
+- la.got a0, t0, main
++#if defined(PIC) && !defined(SHARED)
++/* For static PIE, the GOT cannot be used in _start because the GOT entries are
++ offsets instead of real addresses before __libc_start_main. */
++# define LA la.pcrel
++#else
++# define LA la.got
++#endif
++
++ LA a0, t0, main
+ #ifdef __loongarch_lp64
+ ld.d a1, sp, 0
+ addi.d a2, sp, SZREG
+@@ -61,9 +67,9 @@ ENTRY (ENTRY_POINT)
+ move a4, zero /* used to be fini */
+ or a6, sp, zero /* stack_end */
+
+- la.got ra, t0, __libc_start_main
++ LA ra, t0, __libc_start_main
+ jirl ra, ra, 0
+
+- la.got ra, t0, abort
++ LA ra, t0, abort
+ jirl ra, ra, 0
+ END (ENTRY_POINT)
+--
+2.33.0
+
diff --git a/LoongArch-Fix-ptr-mangling-demangling-and-SHMLBA.patch b/LoongArch-Fix-ptr-mangling-demangling-and-SHMLBA.patch
new file mode 100644
index 0000000..cc9b99a
--- /dev/null
+++ b/LoongArch-Fix-ptr-mangling-demangling-and-SHMLBA.patch
@@ -0,0 +1,158 @@
+From 6698be0ce3a7877d68468c56a9217c4d87f74e23 Mon Sep 17 00:00:00 2001
+From: XingLi <lixing@loongson.cn>
+Date: Fri, 10 Nov 2023 15:00:28 +0800
+Subject: [PATCH 1/3] LoongArch Fix ptr mangling demangling and SHMLBA
+
+---
+ sysdeps/loongarch/__longjmp.S | 7 +++
+ sysdeps/loongarch/setjmp.S | 7 +++
+ .../unix/sysv/linux/loongarch/bits/shmlba.h | 24 +++++++
+ sysdeps/unix/sysv/linux/loongarch/sysdep.h | 62 ++++++++++++++++++-
+ 4 files changed, 97 insertions(+), 3 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/shmlba.h
+
+diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S
+index 5cc1bc78..fa86f797 100644
+--- a/sysdeps/loongarch/__longjmp.S
++++ b/sysdeps/loongarch/__longjmp.S
+@@ -20,8 +20,15 @@
+ #include <sys/asm.h>
+
+ ENTRY (__longjmp)
++#ifdef PTR_MANGLE
++ REG_L t0, a0, 0*SZREG
++ PTR_DEMANGLE (ra, t0, t1)
++ REG_L t0, a0, 1*SZREG
++ PTR_DEMANGLE2 (sp, t0, t1)
++#else
+ REG_L ra, a0, 0*SZREG
+ REG_L sp, a0, 1*SZREG
++#endif
+ REG_L x, a0, 2*SZREG
+ REG_L fp, a0, 3*SZREG
+ REG_L s0, a0, 4*SZREG
+diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S
+index 00ea14b2..6201d0e6 100644
+--- a/sysdeps/loongarch/setjmp.S
++++ b/sysdeps/loongarch/setjmp.S
+@@ -29,8 +29,15 @@ ENTRY (setjmp)
+ END (setjmp)
+
+ ENTRY (__sigsetjmp)
++#ifdef PTR_MANGLE
++ PTR_MANGLE (t0, ra, t1)
++ REG_S t0, a0, 0*SZREG
++ PTR_MANGLE2 (t0, sp, t1)
++ REG_S t0, a0, 1*SZREG
++#else
+ REG_S ra, a0, 0*SZREG
+ REG_S sp, a0, 1*SZREG
++#endif
+ REG_S x, a0, 2*SZREG
+ REG_S fp, a0, 3*SZREG
+ REG_S s0, a0, 4*SZREG
+diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/shmlba.h b/sysdeps/unix/sysv/linux/loongarch/bits/shmlba.h
+new file mode 100644
+index 00000000..28ff9d5c
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/bits/shmlba.h
+@@ -0,0 +1,24 @@
++/* Define SHMLBA. LoongArch version.
++ Copyright (C) 2018-2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_SHM_H
++# error "Never use <bits/shmlba.h> directly; include <sys/shm.h> instead."
++#endif
++
++/* Segment low boundary address multiple. */
++#define SHMLBA 0x10000
+diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
+index b2587091..3f2d691b 100644
+--- a/sysdeps/unix/sysv/linux/loongarch/sysdep.h
++++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
+@@ -313,8 +313,64 @@ extern long int __syscall_error (long int neg_errno);
+
+ #endif /* ! __ASSEMBLER__ */
+
+-/* Pointer mangling is not supported. */
+-#define PTR_MANGLE(var) (void) (var)
+-#define PTR_DEMANGLE(var) (void) (var)
++/* Pointer mangling is supported for LoongArch. */
++
++/* Load a got-relative EXPR into G, using T.
++ Note G and T are register names. */
++#define LD_GLOBAL(G, EXPR) \
++ la.global G, EXPR; \
++ REG_L G, G, 0;
++
++/* Load a pc-relative EXPR into G, using T.
++ Note G and T are register names. */
++#define LD_PCREL(G, EXPR) \
++ la.pcrel G, EXPR; \
++ REG_L G, G, 0;
++
++#if (IS_IN (rtld) \
++ || (!defined SHARED && (IS_IN (libc) \
++ || IS_IN (libpthread))))
++
++#ifdef __ASSEMBLER__
++#define PTR_MANGLE(dst, src, guard) \
++ LD_PCREL (guard, __pointer_chk_guard_local); \
++ PTR_MANGLE2 (dst, src, guard);
++#define PTR_DEMANGLE(dst, src, guard) \
++ LD_PCREL (guard, __pointer_chk_guard_local); \
++ PTR_DEMANGLE2 (dst, src, guard);
++/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
++#define PTR_MANGLE2(dst, src, guard) \
++ xor dst, src, guard;
++#define PTR_DEMANGLE2(dst, src, guard) \
++ PTR_MANGLE2 (dst, src, guard);
++#else
++extern uintptr_t __pointer_chk_guard_local attribute_relro attribute_hidden;
++#define PTR_MANGLE(var) \
++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard_local)
++#define PTR_DEMANGLE(var) PTR_MANGLE (var)
++#endif
++
++#else
++
++#ifdef __ASSEMBLER__
++#define PTR_MANGLE(dst, src, guard) \
++ LD_GLOBAL (guard, __pointer_chk_guard); \
++ PTR_MANGLE2 (dst, src, guard);
++#define PTR_DEMANGLE(dst, src, guard) \
++ LD_GLOBAL (guard, __pointer_chk_guard); \
++ PTR_DEMANGLE2 (dst, src, guard);
++/* Use PTR_MANGLE2 for efficiency if guard is already loaded. */
++#define PTR_MANGLE2(dst, src, guard) \
++ xor dst, src, guard;
++#define PTR_DEMANGLE2(dst, src, guard) \
++ PTR_MANGLE2 (dst, src, guard);
++#else
++extern uintptr_t __pointer_chk_guard attribute_relro;
++#define PTR_MANGLE(var) \
++ (var) = (__typeof (var)) ((uintptr_t) (var) ^ __pointer_chk_guard)
++#define PTR_DEMANGLE(var) PTR_MANGLE (var)
++#endif
++
++#endif
+
+ #endif /* linux/loongarch/sysdep.h */
+--
+2.33.0
+
diff --git a/LoongArch-Fix-the-condition-to-use-PC-relative-addre.patch b/LoongArch-Fix-the-condition-to-use-PC-relative-addre.patch
new file mode 100644
index 0000000..f1aa4eb
--- /dev/null
+++ b/LoongArch-Fix-the-condition-to-use-PC-relative-addre.patch
@@ -0,0 +1,179 @@
+From dba920d34797ea8e44fca1d2cfc6a08dbe9bb759 Mon Sep 17 00:00:00 2001
+From: XingLi <lixing@loongson.cn>
+Date: Thu, 27 Jul 2023 09:32:21 +0800
+Subject: [PATCH 3/3] LoongArch: Fix the condition to use PC-relative
+ addressing in start.S
+
+A start.o compiled from start.S with -DPIC and no -DSHARED is used by
+both crt1.o and rcrt1.o. So the LoongArch static PIE patch
+unintentionally introduced PC-relative addressing for main and
+__libc_start_main into crt1.o.
+
+While the latest Binutils (trunk, which will be released as 2.40)
+supports the PC-relative relocs against an external function by creating
+a PLT entry, the 2.39 release branch doesn't (and won't) support this.
+An error is raised:
+
+ "PLT stub does not represent and symbol not defined."
+
+So, we need the following changes:
+
+1. Check if ld supports the PC-relative relocs against an external
+ function. If it's not supported, we deem static PIE unsupported.
+2. Change start.S. If static PIE is supported, use PC-relative
+ addressing for main and __libc_start_main and rely on the linker to
+ create PLT entries. Otherwise, restore the old behavior (using GOT
+ to address these functions).
+
+An alternative would be adding a new "static-pie-start.S", and some
+custom logic into Makefile to build rcrt1.o with it. And, restore
+start.S to the state before static PIE change so crt1.o won't contain
+PC-relative relocs against external symbols. But I can't see any
+benefit of this alternative, so I'd just keep it simple.
+
+Tested by building glibc with the following configurations:
+
+1. Binutils trunk + GCC trunk. Static PIE enabled. All tests
+ passed.
+2. Binutils 2.39 branch + GCC trunk. Static PIE disabled. Tests
+ related to ifunc failed (it's a known issue). All other tests
+ passed.
+3. Binutils 2.39 branch + GCC 12 branch, cross compilation with
+ build-many-glibcs.py from x86_64-linux-gnu. Static PIE disabled.
+ Build succeeded.
+
+From: Xi Ruoyao <xry111@xry111.site>
+Date: Sun, 2 Oct 2022 22:23:09 +0800
+---
+ sysdeps/loongarch/configure | 29 +++++++++++++++++++++++++----
+ sysdeps/loongarch/configure.ac | 18 ++++++++++++++----
+ sysdeps/loongarch/start.S | 9 +++++++--
+ 3 files changed, 46 insertions(+), 10 deletions(-)
+
+diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure
+index db6341e8..4f0ac252 100644
+--- a/sysdeps/loongarch/configure
++++ b/sysdeps/loongarch/configure
+@@ -11,7 +11,7 @@ if ${libc_cv_static_pie_on_loongarch+:} false; then :
+ $as_echo_n "(cached) " >&6
+ else
+
+- cat > conftest.S << EOF
++ cat > conftest1.S << EOF
+ .global _start
+ .type _start, @function
+ _start:
+@@ -27,14 +27,35 @@ x:
+ /* This should produce an R_LARCH_RELATIVE in the static PIE. */
+ .dword _start
+ EOF
++ cat > conftest2.S << EOF
++.global f
++.type f, @function
++f:
++ /* The linker should be able to handle this and produce a PLT entry. */
++ la.pcrel \$t0, \$t0, external_func
++ jirl \$zero, \$t0, 0
++EOF
++
+ libc_cv_static_pie_on_loongarch=no
+- if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest conftest.S'
++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest1 conftest1.S'
++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; }; } \
++ && { ac_try='LC_ALL=C $READELF -Wr conftest1 | grep -q R_LARCH_RELATIVE'
++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; }; } \
++ && { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -shared -fPIC -o conftest2.so conftest2.S'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } \
+- && { ac_try='LC_ALL=C $READELF -Wr conftest | grep -q R_LARCH_RELATIVE'
++ && { ac_try='LC_ALL=C $READELF -Wr conftest2.so | grep -q 'R_LARCH_JUMP_SLOT.*external_func''
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -43,7 +64,7 @@ EOF
+ then
+ libc_cv_static_pie_on_loongarch=yes
+ fi
+- rm -rf conftest.*
++ rm -rf conftest*
+ fi
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_static_pie_on_loongarch" >&5
+ $as_echo "$libc_cv_static_pie_on_loongarch" >&6; }
+diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac
+index 603085cd..bfe4e0f2 100644
+--- a/sysdeps/loongarch/configure.ac
++++ b/sysdeps/loongarch/configure.ac
+@@ -13,7 +13,7 @@ dnl satisify the requirement, but a distro may backport static PIE support into
+ dnl earlier GCC or Binutils releases as well.
+ AC_CACHE_CHECK([if the toolchain is sufficient to build static PIE on LoongArch],
+ libc_cv_static_pie_on_loongarch, [
+- cat > conftest.S << EOF
++ cat > conftest1.S << EOF
+ .global _start
+ .type _start, @function
+ _start:
+@@ -28,14 +28,24 @@ x:
+ .word 0
+ /* This should produce an R_LARCH_RELATIVE in the static PIE. */
+ .dword _start
++EOF
++ cat > conftest2.S << EOF
++.global f
++.type f, @function
++f:
++ /* The linker should be able to handle this and produce a PLT entry. */
++ la.pcrel \$t0, \$t0, external_func
++ jirl \$zero, \$t0, 0
+ EOF
+ libc_cv_static_pie_on_loongarch=no
+- if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest conftest.S]) \
+- && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest | grep -q R_LARCH_RELATIVE])
++ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest1 conftest1.S]) \
++ && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest1 | grep -q R_LARCH_RELATIVE]) \
++ && AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -shared -fPIC -o conftest2.so conftest2.S]) \
++ && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest2.so | grep -q 'R_LARCH_JUMP_SLOT.*external_func'])
+ then
+ libc_cv_static_pie_on_loongarch=yes
+ fi
+- rm -rf conftest.*])
++ rm -rf conftest* ])
+
+ if test "$libc_cv_static_pie_on_loongarch" = yes; then
+ AC_DEFINE(SUPPORT_STATIC_PIE)
+diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S
+index 1b15fc9c..87bb1d4e 100644
+--- a/sysdeps/loongarch/start.S
++++ b/sysdeps/loongarch/start.S
+@@ -44,11 +44,16 @@ ENTRY (ENTRY_POINT)
+ cfi_undefined (1)
+ or a5, a0, zero /* rtld_fini */
+
+-#if defined(PIC) && !defined(SHARED)
++#if ENABLE_STATIC_PIE
+ /* For static PIE, the GOT cannot be used in _start because the GOT entries are
+- offsets instead of real addresses before __libc_start_main. */
++ offsets instead of real addresses before __libc_start_main.
++ __libc_start_main and/or main may be not local, so we rely on the linker to
++ produce PLT entries for them. GNU ld >= 2.40 supports this. */
+ # define LA la.pcrel
+ #else
++/* Old GNU ld (< 2.40) cannot handle PC relative address against a non-local
++ function correctly. We deem these old linkers failing to support static PIE
++ and load the addresses from GOT. */
+ # define LA la.got
+ #endif
+
+--
+2.33.0
+
diff --git a/LoongArch-Further-refine-the-condition-to-enable-sta.patch b/LoongArch-Further-refine-the-condition-to-enable-sta.patch
new file mode 100644
index 0000000..03fa828
--- /dev/null
+++ b/LoongArch-Further-refine-the-condition-to-enable-sta.patch
@@ -0,0 +1,55 @@
+From 8e39b3ab56422fa2f5e65aa67fabd928f40c5e32 Mon Sep 17 00:00:00 2001
+From: XingLi <lixing@loongson.cn>
+Date: Thu, 27 Jul 2023 09:36:23 +0800
+Subject: [PATCH 3/3] LoongArch: Further refine the condition to enable static
+ PIE
+
+Before GCC r13-2728, it would produce a normal dynamic-linked executable
+with -static-pie. I mistakely believed it would produce a static-linked
+executable, so failed to detect the breakage. Then with Binutils 2.40
+and (vanilla) GCC 12, libc_cv_static_pie_on_loongarch is mistakenly
+enabled and cause a building failure with "undefined reference to
+_DYNAMIC".
+
+Fix the issue by disabling static PIE if -static-pie creates something
+with a INTERP header.
+
+From: Xi Ruoyao <xry111@xry111.site>
+Date: Mon, 27 Feb 2023 19:08:09 +0800
+---
+ sysdeps/loongarch/configure | 6 ++++++
+ sysdeps/loongarch/configure.ac | 1 +
+ 2 files changed, 7 insertions(+)
+
+diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure
+index 4f0ac252..9fec0a73 100644
+--- a/sysdeps/loongarch/configure
++++ b/sysdeps/loongarch/configure
+@@ -48,6 +48,12 @@ EOF
+ (eval $ac_try) 2>&5
+ ac_status=$?
+ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
++ test $ac_status = 0; }; } \
++ && ! { ac_try='LC_ALL=C $READELF -Wl conftest1 | grep -q INTERP'
++ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
++ (eval $ac_try) 2>&5
++ ac_status=$?
++ $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+ test $ac_status = 0; }; } \
+ && { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -shared -fPIC -o conftest2.so conftest2.S'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac
+index bfe4e0f2..6d0b4d0d 100644
+--- a/sysdeps/loongarch/configure.ac
++++ b/sysdeps/loongarch/configure.ac
+@@ -40,6 +40,7 @@ EOF
+ libc_cv_static_pie_on_loongarch=no
+ if AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -static-pie -nostdlib -fPIE -o conftest1 conftest1.S]) \
+ && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest1 | grep -q R_LARCH_RELATIVE]) \
++ && ! AC_TRY_COMMAND([LC_ALL=C $READELF -Wl conftest1 | grep -q INTERP]) \
+ && AC_TRY_COMMAND([${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS -shared -fPIC -o conftest2.so conftest2.S]) \
+ && AC_TRY_COMMAND([LC_ALL=C $READELF -Wr conftest2.so | grep -q 'R_LARCH_JUMP_SLOT.*external_func'])
+ then
+--
+2.27.0
+
diff --git a/LoongArch-Port.patch b/LoongArch-Port.patch
new file mode 100644
index 0000000..b7076c3
--- /dev/null
+++ b/LoongArch-Port.patch
@@ -0,0 +1,11388 @@
+From c79112989afeadee37d64698eb4a922290b4e436 Mon Sep 17 00:00:00 2001
+From: wanghongliang <wanghongliang@loongson.cn>
+Date: Wed, 21 Dec 2022 14:39:59 +0800
+Subject: [PATCH] LoongArch Port.
+
+Signed-off-by: wanghongliang <wanghongliang@loongson.cn>
+Change-Id: Ia618b0101a483a2e07b8ecd114130907eb8ca5db
+---
+ config.h.in | 6 +
+ elf/elf.h | 71 +-
+ scripts/config.guess | 3 +
+ scripts/config.sub | 1 +
+ sysdeps/loongarch/Implies | 3 +
+ sysdeps/loongarch/Makefile | 15 +
+ sysdeps/loongarch/__longjmp.S | 52 +
+ sysdeps/loongarch/abort-instr.h | 2 +
+ sysdeps/loongarch/bits/endianness.h | 11 +
+ sysdeps/loongarch/bits/fenv.h | 90 +
+ sysdeps/loongarch/bits/link.h | 58 +
+ sysdeps/loongarch/bits/setjmp.h | 42 +
+ sysdeps/loongarch/bits/wordsize.h | 25 +
+ sysdeps/loongarch/bsd-_setjmp.c | 1 +
+ sysdeps/loongarch/bsd-setjmp.c | 1 +
+ sysdeps/loongarch/configure | 4 +
+ sysdeps/loongarch/configure.ac | 6 +
+ sysdeps/loongarch/dl-irel.h | 48 +
+ sysdeps/loongarch/dl-machine.h | 305 +++
+ sysdeps/loongarch/dl-tls.h | 46 +
+ sysdeps/loongarch/dl-trampoline.S | 103 +
+ sysdeps/loongarch/e_sqrtl.c | 39 +
+ sysdeps/loongarch/fpu/fclrexcpt.c | 46 +
+ sysdeps/loongarch/fpu/fedisblxcpt.c | 39 +
+ sysdeps/loongarch/fpu/feenablxcpt.c | 39 +
+ sysdeps/loongarch/fpu/fegetenv.c | 31 +
+ sysdeps/loongarch/fpu/fegetexcept.c | 32 +
+ sysdeps/loongarch/fpu/fegetmode.c | 27 +
+ sysdeps/loongarch/fpu/fegetround.c | 33 +
+ sysdeps/loongarch/fpu/feholdexcpt.c | 40 +
+ sysdeps/loongarch/fpu/fenv_libc.h | 30 +
+ sysdeps/loongarch/fpu/fesetenv.c | 42 +
+ sysdeps/loongarch/fpu/fesetexcept.c | 32 +
+ sysdeps/loongarch/fpu/fesetmode.c | 38 +
+ sysdeps/loongarch/fpu/fesetround.c | 44 +
+ sysdeps/loongarch/fpu/feupdateenv.c | 43 +
+ sysdeps/loongarch/fpu/fgetexcptflg.c | 38 +
+ sysdeps/loongarch/fpu/fraiseexcpt.c | 75 +
+ sysdeps/loongarch/fpu/fsetexcptflg.c | 41 +
+ sysdeps/loongarch/fpu/ftestexcept.c | 32 +
+ .../loongarch/fpu/math-use-builtins-sqrt.h | 4 +
+ sysdeps/loongarch/fpu_control.h | 102 +
+ sysdeps/loongarch/gccframe.h | 21 +
+ sysdeps/loongarch/hp-timing.h | 42 +
+ sysdeps/loongarch/jmpbuf-offsets.h | 22 +
+ sysdeps/loongarch/jmpbuf-unwind.h | 45 +
+ sysdeps/loongarch/ldsodefs.h | 41 +
+ sysdeps/loongarch/libc-start.h | 25 +
+ sysdeps/loongarch/libc-tls.c | 32 +
+ sysdeps/loongarch/linkmap.h | 4 +
+ sysdeps/loongarch/lp64/Implies-after | 1 +
+ sysdeps/loongarch/lp64/libm-test-ulps | 1411 +++++++++++
+ sysdeps/loongarch/lp64/libm-test-ulps-name | 1 +
+ sysdeps/loongarch/machine-gmon.h | 37 +
+ sysdeps/loongarch/math_private.h | 248 ++
+ sysdeps/loongarch/memusage.h | 25 +
+ sysdeps/loongarch/nptl/Makefile | 21 +
+ .../loongarch/nptl/bits/pthreadtypes-arch.h | 41 +
+ sysdeps/loongarch/nptl/bits/semaphore.h | 32 +
+ sysdeps/loongarch/nptl/bits/struct_rwlock.h | 44 +
+ sysdeps/loongarch/nptl/pthread-offsets.h | 15 +
+ sysdeps/loongarch/nptl/pthreaddef.h | 34 +
+ sysdeps/loongarch/nptl/tcb-offsets.sym | 6 +
+ sysdeps/loongarch/nptl/tls.h | 138 ++
+ sysdeps/loongarch/preconfigure | 52 +
+ sysdeps/loongarch/setjmp.S | 66 +
+ sysdeps/loongarch/sfp-machine.h | 102 +
+ sysdeps/loongarch/sotruss-lib.c | 50 +
+ sysdeps/loongarch/stackinfo.h | 33 +
+ sysdeps/loongarch/start.S | 69 +
+ sysdeps/loongarch/sys/asm.h | 58 +
+ sysdeps/loongarch/sys/ifunc.h | 30 +
+ sysdeps/loongarch/sys/regdef.h | 98 +
+ sysdeps/loongarch/tininess.h | 1 +
+ sysdeps/loongarch/tls-macros.h | 49 +
+ sysdeps/loongarch/tst-audit.h | 23 +
+ sysdeps/unix/sysv/linux/loongarch/Implies | 1 +
+ sysdeps/unix/sysv/linux/loongarch/Makefile | 10 +
+ .../unix/sysv/linux/loongarch/arch-syscall.h | 292 +++
+ .../sysv/linux/loongarch/atomic-machine.h | 196 ++
+ .../unix/sysv/linux/loongarch/bits/fcntl.h | 61 +
+ sysdeps/unix/sysv/linux/loongarch/bits/mman.h | 42 +
+ .../unix/sysv/linux/loongarch/bits/procfs.h | 52 +
+ .../linux/loongarch/bits/pthread_stack_min.h | 20 +
+ .../unix/sysv/linux/loongarch/bits/sigstack.h | 32 +
+ sysdeps/unix/sysv/linux/loongarch/clone.S | 100 +
+ sysdeps/unix/sysv/linux/loongarch/clone3.S | 87 +
+ sysdeps/unix/sysv/linux/loongarch/configure | 199 ++
+ .../unix/sysv/linux/loongarch/configure.ac | 27 +
+ sysdeps/unix/sysv/linux/loongarch/dl-static.c | 80 +
+ .../unix/sysv/linux/loongarch/getcontext.S | 59 +
+ sysdeps/unix/sysv/linux/loongarch/ldconfig.h | 30 +
+ .../unix/sysv/linux/loongarch/ldd-rewrite.sed | 3 +
+ sysdeps/unix/sysv/linux/loongarch/ldsodefs.h | 33 +
+ .../unix/sysv/linux/loongarch/localplt.data | 12 +
+ .../unix/sysv/linux/loongarch/lp64/Implies | 3 +
+ .../sysv/linux/loongarch/lp64/c++-types.data | 67 +
+ .../linux/loongarch/lp64/fpu/jmp_buf-macros.h | 44 +
+ .../unix/sysv/linux/loongarch/lp64/ld.abilist | 9 +
+ .../loongarch/lp64/libBrokenLocale.abilist | 1 +
+ .../sysv/linux/loongarch/lp64/libanl.abilist | 1 +
+ .../sysv/linux/loongarch/lp64/libc.abilist | 2135 +++++++++++++++++
+ .../loongarch/lp64/libc_malloc_debug.abilist | 26 +
+ .../linux/loongarch/lp64/libcrypt.abilist | 2 +
+ .../sysv/linux/loongarch/lp64/libdl.abilist | 0
+ .../sysv/linux/loongarch/lp64/libm.abilist | 940 ++++++++
+ .../linux/loongarch/lp64/libpthread.abilist | 0
+ .../linux/loongarch/lp64/libresolv.abilist | 55 +
+ .../sysv/linux/loongarch/lp64/librt.abilist | 0
+ .../linux/loongarch/lp64/libthread_db.abilist | 40 +
+ .../loongarch/lp64/nofpu/jmp_buf-macros.h | 41 +
+ .../unix/sysv/linux/loongarch/makecontext.c | 81 +
+ .../unix/sysv/linux/loongarch/register-dump.h | 61 +
+ .../unix/sysv/linux/loongarch/setcontext.S | 100 +
+ .../unix/sysv/linux/loongarch/shlib-versions | 7 +
+ .../sysv/linux/loongarch/sigcontextinfo.h | 32 +
+ .../unix/sysv/linux/loongarch/swapcontext.S | 95 +
+ .../unix/sysv/linux/loongarch/sys/ucontext.h | 64 +
+ sysdeps/unix/sysv/linux/loongarch/sys/user.h | 42 +
+ sysdeps/unix/sysv/linux/loongarch/syscall.c | 35 +
+ sysdeps/unix/sysv/linux/loongarch/sysdep.S | 53 +
+ sysdeps/unix/sysv/linux/loongarch/sysdep.h | 320 +++
+ .../sysv/linux/loongarch/ucontext-macros.h | 32 +
+ .../unix/sysv/linux/loongarch/ucontext_i.sym | 31 +
+ sysdeps/unix/sysv/linux/loongarch/vfork.S | 50 +
+ 125 files changed, 10359 insertions(+), 1 deletion(-)
+ create mode 100644 sysdeps/loongarch/Implies
+ create mode 100644 sysdeps/loongarch/Makefile
+ create mode 100644 sysdeps/loongarch/__longjmp.S
+ create mode 100644 sysdeps/loongarch/abort-instr.h
+ create mode 100644 sysdeps/loongarch/bits/endianness.h
+ create mode 100644 sysdeps/loongarch/bits/fenv.h
+ create mode 100644 sysdeps/loongarch/bits/link.h
+ create mode 100644 sysdeps/loongarch/bits/setjmp.h
+ create mode 100644 sysdeps/loongarch/bits/wordsize.h
+ create mode 100644 sysdeps/loongarch/bsd-_setjmp.c
+ create mode 100644 sysdeps/loongarch/bsd-setjmp.c
+ create mode 100644 sysdeps/loongarch/configure
+ create mode 100644 sysdeps/loongarch/configure.ac
+ create mode 100644 sysdeps/loongarch/dl-irel.h
+ create mode 100644 sysdeps/loongarch/dl-machine.h
+ create mode 100644 sysdeps/loongarch/dl-tls.h
+ create mode 100644 sysdeps/loongarch/dl-trampoline.S
+ create mode 100644 sysdeps/loongarch/e_sqrtl.c
+ create mode 100644 sysdeps/loongarch/fpu/fclrexcpt.c
+ create mode 100644 sysdeps/loongarch/fpu/fedisblxcpt.c
+ create mode 100644 sysdeps/loongarch/fpu/feenablxcpt.c
+ create mode 100644 sysdeps/loongarch/fpu/fegetenv.c
+ create mode 100644 sysdeps/loongarch/fpu/fegetexcept.c
+ create mode 100644 sysdeps/loongarch/fpu/fegetmode.c
+ create mode 100644 sysdeps/loongarch/fpu/fegetround.c
+ create mode 100644 sysdeps/loongarch/fpu/feholdexcpt.c
+ create mode 100644 sysdeps/loongarch/fpu/fenv_libc.h
+ create mode 100644 sysdeps/loongarch/fpu/fesetenv.c
+ create mode 100644 sysdeps/loongarch/fpu/fesetexcept.c
+ create mode 100644 sysdeps/loongarch/fpu/fesetmode.c
+ create mode 100644 sysdeps/loongarch/fpu/fesetround.c
+ create mode 100644 sysdeps/loongarch/fpu/feupdateenv.c
+ create mode 100644 sysdeps/loongarch/fpu/fgetexcptflg.c
+ create mode 100644 sysdeps/loongarch/fpu/fraiseexcpt.c
+ create mode 100644 sysdeps/loongarch/fpu/fsetexcptflg.c
+ create mode 100644 sysdeps/loongarch/fpu/ftestexcept.c
+ create mode 100644 sysdeps/loongarch/fpu/math-use-builtins-sqrt.h
+ create mode 100644 sysdeps/loongarch/fpu_control.h
+ create mode 100644 sysdeps/loongarch/gccframe.h
+ create mode 100644 sysdeps/loongarch/hp-timing.h
+ create mode 100644 sysdeps/loongarch/jmpbuf-offsets.h
+ create mode 100644 sysdeps/loongarch/jmpbuf-unwind.h
+ create mode 100644 sysdeps/loongarch/ldsodefs.h
+ create mode 100644 sysdeps/loongarch/libc-start.h
+ create mode 100644 sysdeps/loongarch/libc-tls.c
+ create mode 100644 sysdeps/loongarch/linkmap.h
+ create mode 100644 sysdeps/loongarch/lp64/Implies-after
+ create mode 100644 sysdeps/loongarch/lp64/libm-test-ulps
+ create mode 100644 sysdeps/loongarch/lp64/libm-test-ulps-name
+ create mode 100644 sysdeps/loongarch/machine-gmon.h
+ create mode 100644 sysdeps/loongarch/math_private.h
+ create mode 100644 sysdeps/loongarch/memusage.h
+ create mode 100644 sysdeps/loongarch/nptl/Makefile
+ create mode 100644 sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h
+ create mode 100644 sysdeps/loongarch/nptl/bits/semaphore.h
+ create mode 100644 sysdeps/loongarch/nptl/bits/struct_rwlock.h
+ create mode 100644 sysdeps/loongarch/nptl/pthread-offsets.h
+ create mode 100644 sysdeps/loongarch/nptl/pthreaddef.h
+ create mode 100644 sysdeps/loongarch/nptl/tcb-offsets.sym
+ create mode 100644 sysdeps/loongarch/nptl/tls.h
+ create mode 100644 sysdeps/loongarch/preconfigure
+ create mode 100644 sysdeps/loongarch/setjmp.S
+ create mode 100644 sysdeps/loongarch/sfp-machine.h
+ create mode 100644 sysdeps/loongarch/sotruss-lib.c
+ create mode 100644 sysdeps/loongarch/stackinfo.h
+ create mode 100644 sysdeps/loongarch/start.S
+ create mode 100644 sysdeps/loongarch/sys/asm.h
+ create mode 100644 sysdeps/loongarch/sys/ifunc.h
+ create mode 100644 sysdeps/loongarch/sys/regdef.h
+ create mode 100644 sysdeps/loongarch/tininess.h
+ create mode 100644 sysdeps/loongarch/tls-macros.h
+ create mode 100644 sysdeps/loongarch/tst-audit.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/Makefile
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/arch-syscall.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/atomic-machine.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/mman.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/procfs.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/clone.S
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/clone3.S
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/configure
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/configure.ac
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/dl-static.c
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/getcontext.S
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldconfig.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/ldsodefs.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/localplt.data
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/Implies
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/fpu/jmp_buf-macros.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libc_malloc_debug.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libdl.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libpthread.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/librt.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/jmp_buf-macros.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/makecontext.c
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/register-dump.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/setcontext.S
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/shlib-versions
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/swapcontext.S
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/sys/user.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/syscall.c
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/sysdep.S
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/sysdep.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym
+ create mode 100644 sysdeps/unix/sysv/linux/loongarch/vfork.S
+
+diff --git a/config.h.in b/config.h.in
+index 13101496..89596a83 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -144,6 +144,12 @@
+ /* RISC-V floating-point ABI for ld.so. */
+ #undef RISCV_ABI_FLEN
+
++/* LOONGARCH integer ABI for ld.so. */
++#undef LOONGARCH_ABI_GRLEN
++
++/* LOONGARCH floating-point ABI for ld.so. */
++#undef LOONGARCH_ABI_FRLEN
++
+ /* Linux specific: minimum supported kernel version. */
+ #undef __LINUX_KERNEL_VERSION
+
+diff --git a/elf/elf.h b/elf/elf.h
+index a64576bb..088f9764 100644
+--- a/elf/elf.h
++++ b/elf/elf.h
+@@ -358,8 +358,9 @@ typedef struct
+
+ #define EM_BPF 247 /* Linux BPF -- in-kernel virtual machine */
+ #define EM_CSKY 252 /* C-SKY */
++#define EM_LOONGARCH 258 /* LoongArch */
+
+-#define EM_NUM 253
++#define EM_NUM 259
+
+ /* Old spellings/synonyms. */
+
+@@ -4038,6 +4039,74 @@ enum
+ #define R_NDS32_TLS_TPOFF 102
+ #define R_NDS32_TLS_DESC 119
+
++/* LoongArch ELF Flags */
++#define EF_LARCH_ABI_MODIFIER_MASK 0x07
++#define EF_LARCH_ABI_SOFT_FLOAT 0x01
++#define EF_LARCH_ABI_SINGLE_FLOAT 0x02
++#define EF_LARCH_ABI_DOUBLE_FLOAT 0x03
++#define EF_LARCH_OBJABI_V1 0x40
++
++/* LoongArch specific dynamic relocations */
++#define R_LARCH_NONE 0
++#define R_LARCH_32 1
++#define R_LARCH_64 2
++#define R_LARCH_RELATIVE 3
++#define R_LARCH_COPY 4
++#define R_LARCH_JUMP_SLOT 5
++#define R_LARCH_TLS_DTPMOD32 6
++#define R_LARCH_TLS_DTPMOD64 7
++#define R_LARCH_TLS_DTPREL32 8
++#define R_LARCH_TLS_DTPREL64 9
++#define R_LARCH_TLS_TPREL32 10
++#define R_LARCH_TLS_TPREL64 11
++#define R_LARCH_IRELATIVE 12
++
++/* Reserved for future relocs that the dynamic linker must understand. */
++
++/* used by the static linker for relocating .text. */
++#define R_LARCH_MARK_LA 20
++#define R_LARCH_MARK_PCREL 21
++#define R_LARCH_SOP_PUSH_PCREL 22
++#define R_LARCH_SOP_PUSH_ABSOLUTE 23
++#define R_LARCH_SOP_PUSH_DUP 24
++#define R_LARCH_SOP_PUSH_GPREL 25
++#define R_LARCH_SOP_PUSH_TLS_TPREL 26
++#define R_LARCH_SOP_PUSH_TLS_GOT 27
++#define R_LARCH_SOP_PUSH_TLS_GD 28
++#define R_LARCH_SOP_PUSH_PLT_PCREL 29
++#define R_LARCH_SOP_ASSERT 30
++#define R_LARCH_SOP_NOT 31
++#define R_LARCH_SOP_SUB 32
++#define R_LARCH_SOP_SL 33
++#define R_LARCH_SOP_SR 34
++#define R_LARCH_SOP_ADD 35
++#define R_LARCH_SOP_AND 36
++#define R_LARCH_SOP_IF_ELSE 37
++#define R_LARCH_SOP_POP_32_S_10_5 38
++#define R_LARCH_SOP_POP_32_U_10_12 39
++#define R_LARCH_SOP_POP_32_S_10_12 40
++#define R_LARCH_SOP_POP_32_S_10_16 41
++#define R_LARCH_SOP_POP_32_S_10_16_S2 42
++#define R_LARCH_SOP_POP_32_S_5_20 43
++#define R_LARCH_SOP_POP_32_S_0_5_10_16_S2 44
++#define R_LARCH_SOP_POP_32_S_0_10_10_16_S2 45
++#define R_LARCH_SOP_POP_32_U 46
++
++/* used by the static linker for relocating non .text. */
++#define R_LARCH_ADD8 47
++#define R_LARCH_ADD16 48
++#define R_LARCH_ADD24 49
++#define R_LARCH_ADD32 50
++#define R_LARCH_ADD64 51
++#define R_LARCH_SUB8 52
++#define R_LARCH_SUB16 53
++#define R_LARCH_SUB24 54
++#define R_LARCH_SUB32 55
++#define R_LARCH_SUB64 56
++#define R_LARCH_GNU_VTINHERIT 57
++#define R_LARCH_GNU_VTENTRY 58
++
++
+ /* ARCompact/ARCv2 specific relocs. */
+ #define R_ARC_NONE 0x0
+ #define R_ARC_8 0x1
+diff --git a/scripts/config.guess b/scripts/config.guess
+index 0f9b29c8..ddbb6095 100755
+--- a/scripts/config.guess
++++ b/scripts/config.guess
+@@ -977,6 +977,9 @@ EOF
+ k1om:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
++ loongarch32:Linux:*:* | loongarch64:Linux:*:* | loongarchx32:Linux:*:*)
++ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
++ exit ;;
+ m32r*:Linux:*:*)
+ echo "$UNAME_MACHINE"-unknown-linux-"$LIBC"
+ exit ;;
+diff --git a/scripts/config.sub b/scripts/config.sub
+index a8f3f7e7..15731891 100755
+--- a/scripts/config.sub
++++ b/scripts/config.sub
+@@ -1182,6 +1182,7 @@ case $cpu-$vendor in
+ | k1om \
+ | le32 | le64 \
+ | lm32 \
++ | loongarch32 | loongarch64 | loongarchx32 \
+ | m32c | m32r | m32rle \
+ | m5200 | m68000 | m680[012346]0 | m68360 | m683?2 | m68k | v70 | w65 \
+ | m6811 | m68hc11 | m6812 | m68hc12 | m68hcs12x | nvptx | picochip \
+diff --git a/sysdeps/loongarch/Implies b/sysdeps/loongarch/Implies
+new file mode 100644
+index 00000000..1945b1f4
+--- /dev/null
++++ b/sysdeps/loongarch/Implies
+@@ -0,0 +1,3 @@
++ieee754/ldbl-128
++ieee754/dbl-64
++ieee754/flt-32
+diff --git a/sysdeps/loongarch/Makefile b/sysdeps/loongarch/Makefile
+new file mode 100644
+index 00000000..41c34496
+--- /dev/null
++++ b/sysdeps/loongarch/Makefile
+@@ -0,0 +1,15 @@
++ifeq ($(subdir),misc)
++sysdep_headers += sys/asm.h
++endif
++
++# LoongArch's assembler also needs to know about PIC as it changes the
++# definition of some assembler macros.
++ASFLAGS-.os += $(pic-ccflag)
++
++abi-variants := lp64
++
++ifeq (,$(filter $(default-abi),$(abi-variants)))
++$(error Unknown ABI $(default-abi), must be one of $(abi-variants))
++endif
++
++abi-lp64-condition := defined __loongarch_lp64
+diff --git a/sysdeps/loongarch/__longjmp.S b/sysdeps/loongarch/__longjmp.S
+new file mode 100644
+index 00000000..5cc1bc78
+--- /dev/null
++++ b/sysdeps/loongarch/__longjmp.S
+@@ -0,0 +1,52 @@
++/* longjmp.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++#include <sys/asm.h>
++
++ENTRY (__longjmp)
++ REG_L ra, a0, 0*SZREG
++ REG_L sp, a0, 1*SZREG
++ REG_L x, a0, 2*SZREG
++ REG_L fp, a0, 3*SZREG
++ REG_L s0, a0, 4*SZREG
++ REG_L s1, a0, 5*SZREG
++ REG_L s2, a0, 6*SZREG
++ REG_L s3, a0, 7*SZREG
++ REG_L s4, a0, 8*SZREG
++ REG_L s5, a0, 9*SZREG
++ REG_L s6, a0, 10*SZREG
++ REG_L s7, a0, 11*SZREG
++ REG_L s8, a0, 12*SZREG
++
++#ifndef __loongarch_soft_float
++ FREG_L $f24, a0, 13*SZREG + 0*SZFREG
++ FREG_L $f25, a0, 13*SZREG + 1*SZFREG
++ FREG_L $f26, a0, 13*SZREG + 2*SZFREG
++ FREG_L $f27, a0, 13*SZREG + 3*SZFREG
++ FREG_L $f28, a0, 13*SZREG + 4*SZFREG
++ FREG_L $f29, a0, 13*SZREG + 5*SZFREG
++ FREG_L $f30, a0, 13*SZREG + 6*SZFREG
++ FREG_L $f31, a0, 13*SZREG + 7*SZFREG
++#endif
++
++ sltui a0,a1,1
++ add.d a0, a0, a1 # a0 = (a1 == 0) ? 1 : a1
++ jirl zero,ra,0
++
++END (__longjmp)
+diff --git a/sysdeps/loongarch/abort-instr.h b/sysdeps/loongarch/abort-instr.h
+new file mode 100644
+index 00000000..92e22edf
+--- /dev/null
++++ b/sysdeps/loongarch/abort-instr.h
+@@ -0,0 +1,2 @@
++/* An instruction which should crash any program is a breakpoint. */
++#define ABORT_INSTRUCTION asm("break 0")
+diff --git a/sysdeps/loongarch/bits/endianness.h b/sysdeps/loongarch/bits/endianness.h
+new file mode 100644
+index 00000000..7290be7b
+--- /dev/null
++++ b/sysdeps/loongarch/bits/endianness.h
+@@ -0,0 +1,11 @@
++#ifndef _BITS_ENDIANNESS_H
++#define _BITS_ENDIANNESS_H 1
++
++#ifndef _BITS_ENDIAN_H
++#error "Never use <bits/endianness.h> directly; include <endian.h> instead."
++#endif
++
++/* LoongArch is little-endian. */
++#define __BYTE_ORDER __LITTLE_ENDIAN
++
++#endif /* bits/endianness.h */
+diff --git a/sysdeps/loongarch/bits/fenv.h b/sysdeps/loongarch/bits/fenv.h
+new file mode 100644
+index 00000000..35433bec
+--- /dev/null
++++ b/sysdeps/loongarch/bits/fenv.h
+@@ -0,0 +1,90 @@
++/* Floating point environment.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _FENV_H
++#error "Never use <bits/fenv.h> directly; include <fenv.h> instead."
++#endif
++
++/* Define bits representing the exception. We use the bit positions
++ of the appropriate bits in the FPU control word. */
++enum
++{
++ FE_INEXACT =
++#define FE_INEXACT 0x010000
++ FE_INEXACT,
++ FE_UNDERFLOW =
++#define FE_UNDERFLOW 0x020000
++ FE_UNDERFLOW,
++ FE_OVERFLOW =
++#define FE_OVERFLOW 0x040000
++ FE_OVERFLOW,
++ FE_DIVBYZERO =
++#define FE_DIVBYZERO 0x080000
++ FE_DIVBYZERO,
++ FE_INVALID =
++#define FE_INVALID 0x100000
++ FE_INVALID,
++};
++
++#define FE_ALL_EXCEPT \
++ (FE_INEXACT | FE_DIVBYZERO | FE_UNDERFLOW | FE_OVERFLOW | FE_INVALID)
++
++/* The LoongArch FPU supports all of the four defined rounding modes. We
++ use again the bit positions in the FPU control word as the values
++ for the appropriate macros. */
++enum
++{
++ FE_TONEAREST =
++#define FE_TONEAREST 0x000
++ FE_TONEAREST,
++ FE_TOWARDZERO =
++#define FE_TOWARDZERO 0x100
++ FE_TOWARDZERO,
++ FE_UPWARD =
++#define FE_UPWARD 0x200
++ FE_UPWARD,
++ FE_DOWNWARD =
++#define FE_DOWNWARD 0x300
++ FE_DOWNWARD
++};
++
++/* Type representing exception flags. */
++typedef unsigned int fexcept_t;
++
++/* Type representing floating-point environment. This function corresponds
++ to the layout of the block written by the `fstenv'. */
++typedef struct
++{
++ unsigned int __fp_control_register;
++} fenv_t;
++
++/* If the default argument is used we use this value. */
++#define FE_DFL_ENV ((const fenv_t *) -1)
++
++#ifdef __USE_GNU
++/* Floating-point environment where none of the exception is masked. */
++#define FE_NOMASK_ENV ((const fenv_t *) -257)
++#endif
++
++#if __GLIBC_USE (IEC_60559_BFP_EXT_C2X)
++/* Type representing floating-point control modes. */
++typedef unsigned int femode_t;
++
++/* Default floating-point control modes. */
++#define FE_DFL_MODE ((const femode_t *) -1L)
++#endif
+diff --git a/sysdeps/loongarch/bits/link.h b/sysdeps/loongarch/bits/link.h
+new file mode 100644
+index 00000000..3f2834d3
+--- /dev/null
++++ b/sysdeps/loongarch/bits/link.h
+@@ -0,0 +1,58 @@
++/* Machine-specific declarations for dynamic linker interface.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LINK_H
++#error "Never include <bits/link.h> directly; use <link.h> instead."
++#endif
++
++typedef struct La_loongarch_regs
++{
++ unsigned long int lr_reg[8]; /* a0 - a7 */
++ double lr_fpreg[8]; /* fa0 - fa7 */
++ unsigned long int lr_ra;
++ unsigned long int lr_sp;
++} La_loongarch_regs;
++
++/* Return values for calls from PLT on LoongArch. */
++typedef struct La_loongarch_retval
++{
++ unsigned long int lrv_a0;
++ unsigned long int lrv_a1;
++ double lrv_fa0;
++ double lrv_fa1;
++} La_loongarch_retval;
++
++__BEGIN_DECLS
++
++extern ElfW (Addr) la_loongarch_gnu_pltenter (ElfW (Sym) * __sym,
++ unsigned int __ndx,
++ uintptr_t *__refcook,
++ uintptr_t *__defcook,
++ La_loongarch_regs *__regs,
++ unsigned int *__flags,
++ const char *__symname,
++ long int *__framesizep);
++extern unsigned int la_loongarch_gnu_pltexit (ElfW (Sym) * __sym,
++ unsigned int __ndx,
++ uintptr_t *__refcook,
++ uintptr_t *__defcook,
++ const La_loongarch_regs *__inregs,
++ La_loongarch_retval *__outregs,
++ const char *__symname);
++
++__END_DECLS
+diff --git a/sysdeps/loongarch/bits/setjmp.h b/sysdeps/loongarch/bits/setjmp.h
+new file mode 100644
+index 00000000..b098ac6f
+--- /dev/null
++++ b/sysdeps/loongarch/bits/setjmp.h
+@@ -0,0 +1,42 @@
++/* Define the machine-dependent type `jmp_buf'.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LOONGARCH_BITS_SETJMP_H
++#define _LOONGARCH_BITS_SETJMP_H
++
++typedef struct __jmp_buf_internal_tag
++{
++ /* Program counter. */
++ long int __pc;
++ /* Stack pointer. */
++ long int __sp;
++ /* Reserved */
++ long int __x;
++ /* Frame pointer. */
++ long int __fp;
++ /* Callee-saved registers. */
++ long int __regs[9];
++
++#ifndef __loongarch_soft_float
++ /* Callee-saved floating point registers. */
++ double __fpregs[8];
++#endif
++
++} __jmp_buf[1];
++
++#endif /* _LOONGARCH_BITS_SETJMP_H */
+diff --git a/sysdeps/loongarch/bits/wordsize.h b/sysdeps/loongarch/bits/wordsize.h
+new file mode 100644
+index 00000000..0a83454b
+--- /dev/null
++++ b/sysdeps/loongarch/bits/wordsize.h
+@@ -0,0 +1,25 @@
++/* Determine the wordsize from the preprocessor defines.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifdef __LP64__
++#define __WORDSIZE 64
++#else
++#define __WORDSIZE 32
++#endif
++
++#define __WORDSIZE_TIME64_COMPAT32 0
+diff --git a/sysdeps/loongarch/bsd-_setjmp.c b/sysdeps/loongarch/bsd-_setjmp.c
+new file mode 100644
+index 00000000..32f49441
+--- /dev/null
++++ b/sysdeps/loongarch/bsd-_setjmp.c
+@@ -0,0 +1 @@
++/* _setjmp is implemented in setjmp.S. */
+diff --git a/sysdeps/loongarch/bsd-setjmp.c b/sysdeps/loongarch/bsd-setjmp.c
+new file mode 100644
+index 00000000..45fd802a
+--- /dev/null
++++ b/sysdeps/loongarch/bsd-setjmp.c
+@@ -0,0 +1 @@
++/* setjmp is implemented in setjmp.S. */
+diff --git a/sysdeps/loongarch/configure b/sysdeps/loongarch/configure
+new file mode 100644
+index 00000000..1e5abf81
+--- /dev/null
++++ b/sysdeps/loongarch/configure
+@@ -0,0 +1,4 @@
++# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
++ # Local configure fragment for sysdeps/loongarch/elf.
++
++#AC_DEFINE(PI_STATIC_AND_HIDDEN)
+diff --git a/sysdeps/loongarch/configure.ac b/sysdeps/loongarch/configure.ac
+new file mode 100644
+index 00000000..67b46ce0
+--- /dev/null
++++ b/sysdeps/loongarch/configure.ac
+@@ -0,0 +1,6 @@
++GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
++# Local configure fragment for sysdeps/loongarch/elf.
++
++dnl It is always possible to access static and hidden symbols in an
++dnl position independent way.
++#AC_DEFINE(PI_STATIC_AND_HIDDEN)
+diff --git a/sysdeps/loongarch/dl-irel.h b/sysdeps/loongarch/dl-irel.h
+new file mode 100644
+index 00000000..9fd106a3
+--- /dev/null
++++ b/sysdeps/loongarch/dl-irel.h
+@@ -0,0 +1,48 @@
++/* Machine-dependent ELF indirect relocation inline functions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _DL_IREL_H
++#define _DL_IREL_H
++
++#include <stdio.h>
++#include <unistd.h>
++
++#define ELF_MACHINE_IRELA 1
++
++static inline ElfW (Addr) __attribute ((always_inline))
++elf_ifunc_invoke (ElfW (Addr) addr)
++{
++ return ((ElfW (Addr) (*) (void)) (addr)) ();
++}
++
++static inline void __attribute ((always_inline))
++elf_irela (const ElfW (Rela) * reloc)
++{
++ ElfW (Addr) *const reloc_addr = (void *) reloc->r_offset;
++ const unsigned long int r_type = ELFW (R_TYPE) (reloc->r_info);
++
++ if (__glibc_likely (r_type == R_LARCH_IRELATIVE))
++ {
++ ElfW (Addr) value = elf_ifunc_invoke (reloc->r_addend);
++ *reloc_addr = value;
++ }
++ else
++ __libc_fatal ("Unexpected reloc type in static binary.\n");
++}
++
++#endif /* dl-irel.h */
+diff --git a/sysdeps/loongarch/dl-machine.h b/sysdeps/loongarch/dl-machine.h
+new file mode 100644
+index 00000000..b6eac3ae
+--- /dev/null
++++ b/sysdeps/loongarch/dl-machine.h
+@@ -0,0 +1,305 @@
++/* Machine-dependent ELF dynamic relocation inline functions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef dl_machine_h
++#define dl_machine_h
++
++#define ELF_MACHINE_NAME "LoongArch"
++
++#include <entry.h>
++#include <elf/elf.h>
++#include <sys/asm.h>
++#include <dl-tls.h>
++
++#ifndef _RTLD_PROLOGUE
++# define _RTLD_PROLOGUE(entry) \
++ ".globl\t" __STRING (entry) "\n\t" \
++ ".type\t" __STRING (entry) ", @function\n\t" \
++ CFI_STARTPROC "\n" \
++ __STRING (entry) ":\n"
++#endif
++
++#ifndef _RTLD_EPILOGUE
++# define _RTLD_EPILOGUE(entry) \
++ CFI_ENDPROC "\n\t" \
++ ".size\t" __STRING (entry) ", . - " __STRING (entry) "\n"
++#endif
++
++#define ELF_MACHINE_JMP_SLOT R_LARCH_JUMP_SLOT
++#define ELF_MACHINE_IRELATIVE R_LARCH_IRELATIVE
++
++#define elf_machine_type_class(type) \
++ ((ELF_RTYPE_CLASS_PLT *((type) == ELF_MACHINE_JMP_SLOT)) \
++ | (ELF_RTYPE_CLASS_COPY *((type) == R_LARCH_COPY)))
++
++#define ELF_MACHINE_NO_REL 1
++#define ELF_MACHINE_NO_RELA 0
++
++/* Return nonzero iff ELF header is compatible with the running host. */
++static inline int __attribute_used__
++elf_machine_matches_host (const ElfW (Ehdr) * ehdr)
++{
++ /* We can only run LoongArch binaries. */
++ if (ehdr->e_machine != EM_LOONGARCH)
++ return 0;
++
++ return 1;
++}
++
++/* Return the run-time load address of the shared object. */
++static inline ElfW (Addr) elf_machine_load_address (void)
++{
++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
++ return (ElfW(Addr)) &__ehdr_start;
++}
++
++/* Return the link-time address of _DYNAMIC. */
++static inline ElfW (Addr) elf_machine_dynamic (void)
++{
++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
++}
++
++/* Initial entry point code for the dynamic linker.
++ The C function `_dl_start' is the real entry point;
++ its return value is the user program's entry point. */
++
++#define RTLD_START asm (\
++ ".text\n\
++ " _RTLD_PROLOGUE (ENTRY_POINT) "\
++ .cfi_label .Ldummy \n\
++ " CFI_UNDEFINED (1) " \n\
++ or $a0, $sp, $zero \n\
++ bl _dl_start \n\
++ # Stash user entry point in s0. \n\
++ or $s0, $a0, $zero \n\
++ # Load the original argument count. \n\
++ ld.d $a1, $sp, 0 \n\
++ # Call _dl_init (struct link_map *main_map, int argc, \
++ char **argv, char **env) \n\
++ la $a0, _rtld_local \n\
++ ld.d $a0, $a0, 0 \n\
++ addi.d $a2, $sp, 8 \n\
++ slli.d $a3, $a1, 3 \n\
++ add.d $a3, $a3, $a2 \n\
++ addi.d $a3, $a3, 8 \n\
++ # Stash the stack pointer in s1.\n\
++ or $s1, $sp, $zero \n\
++ # Adjust $sp for 16-aligned \n\
++ bstrins.d $sp, $zero, 3, 0 \n\
++ # Call the function to run the initializers. \n\
++ bl _dl_init \n\
++ # Restore the stack pointer for _start.\n\
++ or $sp, $s1, $zero \n\
++ # Pass our finalizer function to _start. \n\
++ la $a0, _dl_fini \n\
++ # Jump to the user entry point. \n\
++ jirl $zero, $s0, 0 \n\
++ " _RTLD_EPILOGUE (ENTRY_POINT) "\
++ .previous");
++
++/* Names of the architecture-specific auditing callback functions. */
++#define ARCH_LA_PLTENTER loongarch_gnu_pltenter
++#define ARCH_LA_PLTEXIT loongarch_gnu_pltexit
++
++/* Bias .got.plt entry by the offset requested by the PLT header. */
++#define elf_machine_plt_value(map, reloc, value) (value)
++
++static inline ElfW (Addr)
++ elf_machine_fixup_plt (struct link_map *map, lookup_t t,
++ const ElfW (Sym) * refsym, const ElfW (Sym) * sym,
++ const ElfW (Rela) * reloc, ElfW (Addr) * reloc_addr,
++ ElfW (Addr) value)
++{
++ return *reloc_addr = value;
++}
++
++#endif /* !dl_machine_h */
++
++#ifdef RESOLVE_MAP
++
++/* Perform a relocation described by R_INFO at the location pointed to
++ by RELOC_ADDR. SYM is the relocation symbol specified by R_INFO and
++ MAP is the object containing the reloc. */
++
++auto inline void __attribute__ ((always_inline))
++elf_machine_rela (struct link_map *map,
++ const ElfW (Rela) * reloc,
++ const ElfW (Sym) * sym,
++ const struct r_found_version *version,
++ void *const reloc_addr, int skip_ifunc)
++{
++ ElfW (Addr) r_info = reloc->r_info;
++ const unsigned long int r_type = ELFW (R_TYPE) (r_info);
++ ElfW (Addr) *addr_field = (ElfW (Addr) *) reloc_addr;
++ const ElfW (Sym) *const __attribute__ ((unused)) refsym = sym;
++ struct link_map *sym_map = RESOLVE_MAP (&sym, version, r_type);
++ ElfW (Addr) value = 0;
++ if (sym_map != NULL)
++ value = SYMBOL_ADDRESS (sym_map, sym, true) + reloc->r_addend;
++
++ if (sym != NULL
++ && __builtin_expect (ELFW (ST_TYPE) (sym->st_info) == STT_GNU_IFUNC, 0)
++ && __builtin_expect (sym->st_shndx != SHN_UNDEF, 1)
++ && __builtin_expect (!skip_ifunc, 1))
++ value = ((ElfW (Addr) (*) (int)) value) (GLRO (dl_hwcap));
++
++ switch (r_type)
++ {
++ case R_LARCH_JUMP_SLOT:
++ case __WORDSIZE == 64 ? R_LARCH_64 : R_LARCH_32:
++ *addr_field = value;
++ break;
++
++ case R_LARCH_NONE:
++ break;
++
++#ifndef RTLD_BOOTSTRAP
++ case __WORDSIZE == 64 ? R_LARCH_TLS_DTPMOD64:
++ R_LARCH_TLS_DTPMOD32:
++ if (sym_map)
++ *addr_field = sym_map->l_tls_modid;
++ break;
++
++ case __WORDSIZE == 64 ? R_LARCH_TLS_DTPREL64:
++ R_LARCH_TLS_DTPREL32:
++ if (sym != NULL)
++ *addr_field = TLS_DTPREL_VALUE (sym) + reloc->r_addend;
++ break;
++
++ case __WORDSIZE == 64 ? R_LARCH_TLS_TPREL64:
++ R_LARCH_TLS_TPREL32:
++ if (sym != NULL)
++ {
++ CHECK_STATIC_TLS (map, sym_map);
++ *addr_field = TLS_TPREL_VALUE (sym_map, sym) + reloc->r_addend;
++ }
++ break;
++
++ case R_LARCH_COPY:
++ {
++ if (__glibc_unlikely (sym == NULL))
++ /* This can happen in trace mode if an object could not be
++ found. */
++ break;
++
++ /* Handle TLS copy relocations. */
++ if (__glibc_unlikely (ELFW (ST_TYPE) (sym->st_info) == STT_TLS))
++ {
++ /* There's nothing to do if the symbol is in .tbss. */
++ if (__glibc_likely (sym->st_value
++ >= sym_map->l_tls_initimage_size))
++ break;
++ value += (ElfW (Addr)) sym_map->l_tls_initimage - sym_map->l_addr;
++ }
++
++ size_t size = sym->st_size;
++ if (__glibc_unlikely (sym->st_size != refsym->st_size))
++ {
++ const char *strtab = (const void *) D_PTR (map, l_info[DT_STRTAB]);
++ if (sym->st_size > refsym->st_size)
++ size = refsym->st_size;
++ if (sym->st_size > refsym->st_size || GLRO (dl_verbose))
++ _dl_error_printf ("\
++ %s: Symbol `%s' has different size in shared object, consider re-linking\n",
++ rtld_progname ?: "<program name unknown>",
++ strtab + refsym->st_name);
++ }
++
++ memcpy (reloc_addr, (void *) value, size);
++ break;
++ }
++ case R_LARCH_RELATIVE:
++ {
++ *addr_field = map->l_addr + reloc->r_addend;
++ break;
++ }
++
++ case R_LARCH_IRELATIVE:
++ value = map->l_addr + reloc->r_addend;
++ if (__glibc_likely (!skip_ifunc))
++ value = ((ElfW (Addr) (*) (void)) value) ();
++ *addr_field = value;
++ break;
++#endif
++
++ default:
++ _dl_reloc_bad_type (map, r_type, 0);
++ break;
++ }
++}
++
++auto inline void __attribute__ ((always_inline))
++elf_machine_rela_relative (ElfW (Addr) l_addr, const ElfW (Rela) * reloc,
++ void *const reloc_addr)
++{
++ *(ElfW (Addr) *) reloc_addr = l_addr + reloc->r_addend;
++}
++
++auto inline void __attribute__ ((always_inline))
++elf_machine_lazy_rel (struct link_map *map,
++ ElfW (Addr) l_addr,
++ const ElfW (Rela) * reloc, int skip_ifunc)
++{
++ ElfW (Addr) *const reloc_addr = (void *) (l_addr + reloc->r_offset);
++ const unsigned int r_type = ELFW (R_TYPE) (reloc->r_info);
++
++ /* Check for unexpected PLT reloc type. */
++ if (__glibc_likely (r_type == R_LARCH_JUMP_SLOT))
++ {
++ if (__glibc_unlikely (map->l_mach.plt == 0))
++ {
++ if (l_addr)
++ *reloc_addr += l_addr;
++ }
++ else
++ *reloc_addr = map->l_mach.plt;
++ }
++ else
++ _dl_reloc_bad_type (map, r_type, 1);
++}
++
++/* Set up the loaded object described by L so its stub function
++ will jump to the on-demand fixup code __dl_runtime_resolve. */
++
++auto inline int __attribute__ ((always_inline))
++elf_machine_runtime_setup (struct link_map *l,
++ int lazy, int profile)
++{
++#ifndef RTLD_BOOTSTRAP
++ /* If using PLTs, fill in the first two entries of .got.plt. */
++ if (l->l_info[DT_JMPREL])
++ {
++ extern void _dl_runtime_resolve (void)
++ __attribute__ ((visibility ("hidden")));
++ ElfW (Addr) *gotplt = (ElfW (Addr) *) D_PTR (l, l_info[DT_PLTGOT]);
++ /* If a library is prelinked but we have to relocate anyway,
++ we have to be able to undo the prelinking of .got.plt.
++ The prelinker saved the address of .plt for us here. */
++ if (gotplt[1])
++ l->l_mach.plt = gotplt[1] + l->l_addr;
++ gotplt[0] = (ElfW (Addr)) & _dl_runtime_resolve;
++ gotplt[1] = (ElfW (Addr)) l;
++ }
++#endif
++
++ return lazy;
++}
++
++#endif /* RESOLVE_MAP */
+diff --git a/sysdeps/loongarch/dl-tls.h b/sysdeps/loongarch/dl-tls.h
+new file mode 100644
+index 00000000..ee7d78a3
+--- /dev/null
++++ b/sysdeps/loongarch/dl-tls.h
+@@ -0,0 +1,46 @@
++/* Thread-local storage handling in the ELF dynamic linker.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Type used for the representation of TLS information in the GOT. */
++typedef struct
++{
++ unsigned long int ti_module;
++ unsigned long int ti_offset;
++} tls_index;
++
++/* The thread pointer points to the first static TLS block. */
++#define TLS_TP_OFFSET 0
++
++/* Dynamic thread vector pointers point to the start of each
++ TLS block. */
++#define TLS_DTV_OFFSET 0
++
++/* Compute the value for a GOTTPREL reloc. */
++#define TLS_TPREL_VALUE(sym_map, sym) \
++ ((sym_map)->l_tls_offset + (sym)->st_value - TLS_TP_OFFSET)
++
++/* Compute the value for a DTPREL reloc. */
++#define TLS_DTPREL_VALUE(sym) ((sym)->st_value - TLS_DTV_OFFSET)
++
++extern void *__tls_get_addr (tls_index *ti);
++
++#define GET_ADDR_OFFSET (ti->ti_offset + TLS_DTV_OFFSET)
++#define __TLS_GET_ADDR(__ti) (__tls_get_addr (__ti) - TLS_DTV_OFFSET)
++
++/* Value used for dtv entries for which the allocation is delayed. */
++#define TLS_DTV_UNALLOCATED ((void *) -1l)
+diff --git a/sysdeps/loongarch/dl-trampoline.S b/sysdeps/loongarch/dl-trampoline.S
+new file mode 100644
+index 00000000..84b1fa1f
+--- /dev/null
++++ b/sysdeps/loongarch/dl-trampoline.S
+@@ -0,0 +1,103 @@
++/* PLT trampolines.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++#include <sys/asm.h>
++
++/* Assembler veneer called from the PLT header code for lazy loading.
++ The PLT header passes its own args in t0-t2. */
++
++#ifdef __loongarch_soft_float
++# define FRAME_SIZE (-((-10 * SZREG) & ALMASK))
++#else
++# define FRAME_SIZE (-((-10 * SZREG - 8 * SZFREG) & ALMASK))
++#endif
++
++ENTRY (_dl_runtime_resolve)
++
++ /* Save arguments to stack. */
++#ifdef __loongarch_lp64
++ addi.d sp, sp, -FRAME_SIZE
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++ REG_S ra, sp, 9*SZREG
++ REG_S a0, sp, 1*SZREG
++ REG_S a1, sp, 2*SZREG
++ REG_S a2, sp, 3*SZREG
++ REG_S a3, sp, 4*SZREG
++ REG_S a4, sp, 5*SZREG
++ REG_S a5, sp, 6*SZREG
++ REG_S a6, sp, 7*SZREG
++ REG_S a7, sp, 8*SZREG
++
++#ifndef __loongarch_soft_float
++ FREG_S fa0, sp, 10*SZREG + 0*SZFREG
++ FREG_S fa1, sp, 10*SZREG + 1*SZFREG
++ FREG_S fa2, sp, 10*SZREG + 2*SZFREG
++ FREG_S fa3, sp, 10*SZREG + 3*SZFREG
++ FREG_S fa4, sp, 10*SZREG + 4*SZFREG
++ FREG_S fa5, sp, 10*SZREG + 5*SZFREG
++ FREG_S fa6, sp, 10*SZREG + 6*SZFREG
++ FREG_S fa7, sp, 10*SZREG + 7*SZFREG
++#endif
++
++ /* Update .got.plt and obtain runtime address of callee */
++#ifdef __loongarch_lp64
++ slli.d a1, t1, 1
++ or a0, t0, zero
++ add.d a1, a1, t1
++ la a2, _dl_fixup
++ jirl ra, a2, 0
++ or t1, v0, zero
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++ /* Restore arguments from stack. */
++ REG_L ra, sp, 9*SZREG
++ REG_L a0, sp, 1*SZREG
++ REG_L a1, sp, 2*SZREG
++ REG_L a2, sp, 3*SZREG
++ REG_L a3, sp, 4*SZREG
++ REG_L a4, sp, 5*SZREG
++ REG_L a5, sp, 6*SZREG
++ REG_L a6, sp, 7*SZREG
++ REG_L a7, sp, 8*SZREG
++
++#ifndef __loongarch_soft_float
++ FREG_L fa0, sp, 10*SZREG + 0*SZFREG
++ FREG_L fa1, sp, 10*SZREG + 1*SZFREG
++ FREG_L fa2, sp, 10*SZREG + 2*SZFREG
++ FREG_L fa3, sp, 10*SZREG + 3*SZFREG
++ FREG_L fa4, sp, 10*SZREG + 4*SZFREG
++ FREG_L fa5, sp, 10*SZREG + 5*SZFREG
++ FREG_L fa6, sp, 10*SZREG + 6*SZFREG
++ FREG_L fa7, sp, 10*SZREG + 7*SZFREG
++#endif
++
++#ifdef __loongarch_lp64
++ addi.d sp, sp, FRAME_SIZE
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++ /* Invoke the callee. */
++ jirl zero, t1, 0
++END (_dl_runtime_resolve)
+diff --git a/sysdeps/loongarch/e_sqrtl.c b/sysdeps/loongarch/e_sqrtl.c
+new file mode 100644
+index 00000000..801af70b
+--- /dev/null
++++ b/sysdeps/loongarch/e_sqrtl.c
+@@ -0,0 +1,39 @@
++/* long double square root in software floating-point emulation.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdlib.h>
++#include <soft-fp/soft-fp.h>
++#include <soft-fp/quad.h>
++#include <libm-alias-finite.h>
++
++long double
++__ieee754_sqrtl (const long double a)
++{
++ FP_DECL_EX;
++ FP_DECL_Q (A);
++ FP_DECL_Q (C);
++ long double c;
++
++ FP_INIT_ROUNDMODE;
++ FP_UNPACK_Q (A, a);
++ FP_SQRT_Q (C, A);
++ FP_PACK_Q (c, C);
++ FP_HANDLE_EXCEPTIONS;
++ return c;
++}
++libm_alias_finite (__ieee754_sqrtl, __sqrtl)
+diff --git a/sysdeps/loongarch/fpu/fclrexcpt.c b/sysdeps/loongarch/fpu/fclrexcpt.c
+new file mode 100644
+index 00000000..6f77e9a3
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fclrexcpt.c
+@@ -0,0 +1,46 @@
++/* Clear given exceptions in current floating-point environment.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fenv_libc.h>
++#include <fpu_control.h>
++
++int
++feclearexcept (int excepts)
++{
++ int cw;
++
++ /* Mask out unsupported bits/exceptions. */
++ excepts &= FE_ALL_EXCEPT;
++
++ /* Read the complete control word. */
++ _FPU_GETCW (cw);
++
++ /* Clear exception flag bits and cause bits. If the cause bit is not
++ cleared, the next CTC instruction (just below) will re-generate the
++ exception. */
++
++ cw &= ~(excepts | (excepts << CAUSE_SHIFT));
++
++ /* Put the new data in effect. */
++ _FPU_SETCW (cw);
++
++ /* Success. */
++ return 0;
++}
++libm_hidden_def (feclearexcept)
+diff --git a/sysdeps/loongarch/fpu/fedisblxcpt.c b/sysdeps/loongarch/fpu/fedisblxcpt.c
+new file mode 100644
+index 00000000..532274bc
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fedisblxcpt.c
+@@ -0,0 +1,39 @@
++/* Disable floating-point exceptions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fenv_libc.h>
++#include <fpu_control.h>
++
++int
++fedisableexcept (int excepts)
++{
++ unsigned int new_exc, old_exc;
++
++ /* Get the current control word. */
++ _FPU_GETCW (new_exc);
++
++ old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT;
++
++ excepts &= FE_ALL_EXCEPT;
++
++ new_exc &= ~(excepts >> ENABLE_SHIFT);
++ _FPU_SETCW (new_exc);
++
++ return old_exc;
++}
+diff --git a/sysdeps/loongarch/fpu/feenablxcpt.c b/sysdeps/loongarch/fpu/feenablxcpt.c
+new file mode 100644
+index 00000000..565ebd4d
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/feenablxcpt.c
+@@ -0,0 +1,39 @@
++/* Enable floating-point exceptions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fenv_libc.h>
++#include <fpu_control.h>
++
++int
++feenableexcept (int excepts)
++{
++ unsigned int new_exc, old_exc;
++
++ /* Get the current control word. */
++ _FPU_GETCW (new_exc);
++
++ old_exc = (new_exc & ENABLE_MASK) << ENABLE_SHIFT;
++
++ excepts &= FE_ALL_EXCEPT;
++
++ new_exc |= excepts >> ENABLE_SHIFT;
++ _FPU_SETCW (new_exc);
++
++ return old_exc;
++}
+diff --git a/sysdeps/loongarch/fpu/fegetenv.c b/sysdeps/loongarch/fpu/fegetenv.c
+new file mode 100644
+index 00000000..5e8c095f
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fegetenv.c
+@@ -0,0 +1,31 @@
++/* Store current floating-point environment.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++__fegetenv (fenv_t *envp)
++{
++ _FPU_GETCW (*envp);
++
++ /* Success. */
++ return 0;
++}
++libm_hidden_def (__fegetenv) weak_alias (__fegetenv, fegetenv)
++libm_hidden_weak (fegetenv)
+diff --git a/sysdeps/loongarch/fpu/fegetexcept.c b/sysdeps/loongarch/fpu/fegetexcept.c
+new file mode 100644
+index 00000000..782e9d80
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fegetexcept.c
+@@ -0,0 +1,32 @@
++/* Get enabled floating-point exceptions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fenv_libc.h>
++#include <fpu_control.h>
++
++int
++fegetexcept (void)
++{
++ unsigned int exc;
++
++ /* Get the current control word. */
++ _FPU_GETCW (exc);
++
++ return (exc & ENABLE_MASK) << ENABLE_SHIFT;
++}
+diff --git a/sysdeps/loongarch/fpu/fegetmode.c b/sysdeps/loongarch/fpu/fegetmode.c
+new file mode 100644
+index 00000000..f39c4c31
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fegetmode.c
+@@ -0,0 +1,27 @@
++/* Store current floating-point control modes.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++fegetmode (femode_t *modep)
++{
++ _FPU_GETCW (*modep);
++ return 0;
++}
+diff --git a/sysdeps/loongarch/fpu/fegetround.c b/sysdeps/loongarch/fpu/fegetround.c
+new file mode 100644
+index 00000000..61a793a8
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fegetround.c
+@@ -0,0 +1,33 @@
++/* Return current rounding direction.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++__fegetround (void)
++{
++ int cw;
++
++ /* Get control word. */
++ _FPU_GETCW (cw);
++
++ return cw & _FPU_RC_MASK;
++}
++libm_hidden_def (__fegetround) weak_alias (__fegetround, fegetround)
++libm_hidden_weak (fegetround)
+diff --git a/sysdeps/loongarch/fpu/feholdexcpt.c b/sysdeps/loongarch/fpu/feholdexcpt.c
+new file mode 100644
+index 00000000..59791ba9
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/feholdexcpt.c
+@@ -0,0 +1,40 @@
++/* Store current floating-point environment and clear exceptions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++__feholdexcept (fenv_t *envp)
++{
++ fpu_control_t cw;
++
++ /* Save the current state. */
++ _FPU_GETCW (cw);
++ envp->__fp_control_register = cw;
++
++ /* Clear all exception enable bits and flags. */
++ cw &= ~(_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O | _FPU_MASK_U | _FPU_MASK_I
++ | FE_ALL_EXCEPT);
++ _FPU_SETCW (cw);
++
++ return 0;
++}
++
++libm_hidden_def (__feholdexcept) weak_alias (__feholdexcept, feholdexcept)
++libm_hidden_weak (feholdexcept)
+diff --git a/sysdeps/loongarch/fpu/fenv_libc.h b/sysdeps/loongarch/fpu/fenv_libc.h
+new file mode 100644
+index 00000000..60eedc93
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fenv_libc.h
+@@ -0,0 +1,30 @@
++/* Internal libc stuff for floating point environment routines.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _FENV_LIBC_H
++#define _FENV_LIBC_H 1
++
++/* Mask for enabling exceptions and for the CAUSE bits. */
++#define ENABLE_MASK 0x0000001FU
++#define CAUSE_MASK 0x1F000000U
++
++/* Shift for FE_* flags to get up to the ENABLE bits and the CAUSE bits. */
++#define ENABLE_SHIFT 16
++#define CAUSE_SHIFT 8
++
++#endif /* _FENV_LIBC_H */
+diff --git a/sysdeps/loongarch/fpu/fesetenv.c b/sysdeps/loongarch/fpu/fesetenv.c
+new file mode 100644
+index 00000000..2a73a17d
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fesetenv.c
+@@ -0,0 +1,42 @@
++/* Install given floating-point environment.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++__fesetenv (const fenv_t *envp)
++{
++ fpu_control_t cw;
++
++ /* Read first current state to flush fpu pipeline. */
++ _FPU_GETCW (cw);
++
++ if (envp == FE_DFL_ENV)
++ _FPU_SETCW (_FPU_DEFAULT);
++ else if (envp == FE_NOMASK_ENV)
++ _FPU_SETCW (_FPU_IEEE);
++ else
++ _FPU_SETCW (envp->__fp_control_register);
++
++ /* Success. */
++ return 0;
++}
++
++libm_hidden_def (__fesetenv) weak_alias (__fesetenv, fesetenv)
++libm_hidden_weak (fesetenv)
+diff --git a/sysdeps/loongarch/fpu/fesetexcept.c b/sysdeps/loongarch/fpu/fesetexcept.c
+new file mode 100644
+index 00000000..63c65e8f
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fesetexcept.c
+@@ -0,0 +1,32 @@
++/* Set given exception flags.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++fesetexcept (int excepts)
++{
++ fpu_control_t temp;
++
++ _FPU_GETCW (temp);
++ temp |= excepts & FE_ALL_EXCEPT;
++ _FPU_SETCW (temp);
++
++ return 0;
++}
+diff --git a/sysdeps/loongarch/fpu/fesetmode.c b/sysdeps/loongarch/fpu/fesetmode.c
+new file mode 100644
+index 00000000..8948876a
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fesetmode.c
+@@ -0,0 +1,38 @@
++/* Install given floating-point control modes.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++#define FCSR_STATUS 0x1f1f0000
++
++int
++fesetmode (const femode_t *modep)
++{
++ fpu_control_t cw;
++
++ _FPU_GETCW (cw);
++ cw &= FCSR_STATUS;
++ if (modep == FE_DFL_MODE)
++ cw |= _FPU_DEFAULT;
++ else
++ cw |= *modep & ~FCSR_STATUS;
++ _FPU_SETCW (cw);
++
++ return 0;
++}
+diff --git a/sysdeps/loongarch/fpu/fesetround.c b/sysdeps/loongarch/fpu/fesetround.c
+new file mode 100644
+index 00000000..dddac1cc
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fesetround.c
+@@ -0,0 +1,44 @@
++/* Set current rounding direction.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++__fesetround (int round)
++{
++ fpu_control_t cw;
++
++ if ((round & ~_FPU_RC_MASK) != 0)
++ /* ROUND is no valid rounding mode. */
++ return 1;
++
++ /* Get current state. */
++ _FPU_GETCW (cw);
++
++ /* Set rounding bits. */
++ cw &= ~_FPU_RC_MASK;
++ cw |= round;
++ /* Set new state. */
++ _FPU_SETCW (cw);
++
++ return 0;
++}
++
++libm_hidden_def (__fesetround) weak_alias (__fesetround, fesetround)
++libm_hidden_weak (fesetround)
+diff --git a/sysdeps/loongarch/fpu/feupdateenv.c b/sysdeps/loongarch/fpu/feupdateenv.c
+new file mode 100644
+index 00000000..ad147cbd
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/feupdateenv.c
+@@ -0,0 +1,43 @@
++/* Install given floating-point environment and raise exceptions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++__feupdateenv (const fenv_t *envp)
++{
++ int temp;
++
++ /* Save current exceptions. */
++ _FPU_GETCW (temp);
++ temp &= FE_ALL_EXCEPT;
++
++ /* Install new environment. */
++ __fesetenv (envp);
++
++ /* Raise the safed exception. Incidently for us the implementation
++ defined format of the values in objects of type fexcept_t is the
++ same as the ones specified using the FE_* constants. */
++ __feraiseexcept (temp);
++
++ /* Success. */
++ return 0;
++}
++libm_hidden_def (__feupdateenv) weak_alias (__feupdateenv, feupdateenv)
++libm_hidden_weak (feupdateenv)
+diff --git a/sysdeps/loongarch/fpu/fgetexcptflg.c b/sysdeps/loongarch/fpu/fgetexcptflg.c
+new file mode 100644
+index 00000000..85733765
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fgetexcptflg.c
+@@ -0,0 +1,38 @@
++/* Store current representation for exceptions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++fegetexceptflag (fexcept_t *flagp, int excepts)
++{
++ fpu_control_t temp;
++
++ /* Get the current exceptions. */
++ _FPU_GETCW (temp);
++
++ /* We only save the relevant bits here. In particular, care has to be
++ taken with the CAUSE bits, as an inadvertent restore later on could
++ generate unexpected exceptions. */
++
++ *flagp = temp & excepts & FE_ALL_EXCEPT;
++
++ /* Success. */
++ return 0;
++}
+diff --git a/sysdeps/loongarch/fpu/fraiseexcpt.c b/sysdeps/loongarch/fpu/fraiseexcpt.c
+new file mode 100644
+index 00000000..ac01dc70
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fraiseexcpt.c
+@@ -0,0 +1,75 @@
++/* Raise given exceptions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++#include <float.h>
++
++int
++__feraiseexcept (int excepts)
++{
++ const float fp_zero = 0.0, fp_one = 1.0, fp_max = FLT_MAX, fp_min = FLT_MIN,
++ fp_1e32 = 1.0e32f, fp_two = 2.0, fp_three = 3.0;
++
++ /* Raise exceptions represented by EXPECTS. But we must raise only
++ one signal at a time. It is important that if the overflow/underflow
++ exception and the inexact exception are given at the same time,
++ the overflow/underflow exception follows the inexact exception. */
++
++ /* First: invalid exception. */
++ if (FE_INVALID & excepts)
++ __asm__ __volatile__("fdiv.s $f0,%0,%0\n\t"
++ :
++ : "f"(fp_zero)
++ : "$f0");
++
++ /* Next: division by zero. */
++ if (FE_DIVBYZERO & excepts)
++ __asm__ __volatile__("fdiv.s $f0,%0,%1\n\t"
++ :
++ : "f"(fp_one), "f"(fp_zero)
++ : "$f0");
++
++ /* Next: overflow. */
++ if (FE_OVERFLOW & excepts)
++ /* There's no way to raise overflow without also raising inexact. */
++ __asm__ __volatile__("fadd.s $f0,%0,%1\n\t"
++ :
++ : "f"(fp_max), "f"(fp_1e32)
++ : "$f0");
++
++ /* Next: underflow. */
++ if (FE_UNDERFLOW & excepts)
++ __asm__ __volatile__("fdiv.s $f0,%0,%1\n\t"
++ :
++ : "f"(fp_min), "f"(fp_three)
++ : "$f0");
++
++ /* Last: inexact. */
++ if (FE_INEXACT & excepts)
++ __asm__ __volatile__("fdiv.s $f0, %0, %1\n\t"
++ :
++ : "f"(fp_two), "f"(fp_three)
++ : "$f0");
++
++ /* Success. */
++ return 0;
++}
++
++libm_hidden_def (__feraiseexcept) weak_alias (__feraiseexcept, feraiseexcept)
++libm_hidden_weak (feraiseexcept)
+diff --git a/sysdeps/loongarch/fpu/fsetexcptflg.c b/sysdeps/loongarch/fpu/fsetexcptflg.c
+new file mode 100644
+index 00000000..eef2faa6
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/fsetexcptflg.c
+@@ -0,0 +1,41 @@
++/* Set floating-point environment exception handling.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++fesetexceptflag (const fexcept_t *flagp, int excepts)
++{
++ fpu_control_t temp;
++
++ /* Get the current exceptions. */
++ _FPU_GETCW (temp);
++
++ /* Make sure the flags we want restored are legal. */
++ excepts &= FE_ALL_EXCEPT;
++
++ /* Now clear the bits called for, and copy them in from flagp. Note that
++ we ignore all non-flag bits from *flagp, so they don't matter. */
++ temp = (temp & ~excepts) | (*flagp & excepts);
++
++ _FPU_SETCW (temp);
++
++ /* Success. */
++ return 0;
++}
+diff --git a/sysdeps/loongarch/fpu/ftestexcept.c b/sysdeps/loongarch/fpu/ftestexcept.c
+new file mode 100644
+index 00000000..3abd75ee
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/ftestexcept.c
+@@ -0,0 +1,32 @@
++/* Test exception in current environment.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++int
++fetestexcept (int excepts)
++{
++ int cw;
++
++ /* Get current control word. */
++ _FPU_GETCW (cw);
++
++ return cw & excepts & FE_ALL_EXCEPT;
++}
++libm_hidden_def (fetestexcept)
+diff --git a/sysdeps/loongarch/fpu/math-use-builtins-sqrt.h b/sysdeps/loongarch/fpu/math-use-builtins-sqrt.h
+new file mode 100644
+index 00000000..e94c915b
+--- /dev/null
++++ b/sysdeps/loongarch/fpu/math-use-builtins-sqrt.h
+@@ -0,0 +1,4 @@
++#define USE_SQRT_BUILTIN 1
++#define USE_SQRTF_BUILTIN 1
++#define USE_SQRTL_BUILTIN 0
++#define USE_SQRTF128_BUILTIN 0
+diff --git a/sysdeps/loongarch/fpu_control.h b/sysdeps/loongarch/fpu_control.h
+new file mode 100644
+index 00000000..d26e27ab
+--- /dev/null
++++ b/sysdeps/loongarch/fpu_control.h
+@@ -0,0 +1,102 @@
++/* FPU control word bits.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _FPU_CONTROL_H
++#define _FPU_CONTROL_H
++
++/* LoongArch FPU floating point control register bits.
++ *
++ * 31-29 -> reserved (read as 0, can not changed by software)
++ * 28 -> cause bit for invalid exception
++ * 27 -> cause bit for division by zero exception
++ * 26 -> cause bit for overflow exception
++ * 25 -> cause bit for underflow exception
++ * 24 -> cause bit for inexact exception
++ * 23-21 -> reserved (read as 0, can not changed by software)
++ * 20 -> flag invalid exception
++ * 19 -> flag division by zero exception
++ * 18 -> flag overflow exception
++ * 17 -> flag underflow exception
++ * 16 -> flag inexact exception
++ * 9-8 -> rounding control
++ * 7-5 -> reserved (read as 0, can not changed by software)
++ * 4 -> enable exception for invalid exception
++ * 3 -> enable exception for division by zero exception
++ * 2 -> enable exception for overflow exception
++ * 1 -> enable exception for underflow exception
++ * 0 -> enable exception for inexact exception
++ *
++ *
++ * Rounding Control:
++ * 00 - rounding ties to even (RNE)
++ * 01 - rounding toward zero (RZ)
++ * 10 - rounding (up) toward plus infinity (RP)
++ * 11 - rounding (down) toward minus infinity (RM)
++ */
++
++#include <features.h>
++
++#ifdef __loongarch_soft_float
++
++#define _FPU_RESERVED 0xffffffff
++#define _FPU_DEFAULT 0x00000000
++typedef unsigned int fpu_control_t;
++#define _FPU_GETCW(cw) (cw) = 0
++#define _FPU_SETCW(cw) (void) (cw)
++extern fpu_control_t __fpu_control;
++
++#else /* __loongarch_soft_float */
++
++/* Masks for interrupts. */
++#define _FPU_MASK_V 0x10 /* Invalid operation */
++#define _FPU_MASK_Z 0x08 /* Division by zero */
++#define _FPU_MASK_O 0x04 /* Overflow */
++#define _FPU_MASK_U 0x02 /* Underflow */
++#define _FPU_MASK_I 0x01 /* Inexact operation */
++
++/* Flush denormalized numbers to zero. */
++#define _FPU_FLUSH_TZ 0x1000000
++
++/* Rounding control. */
++#define _FPU_RC_NEAREST 0x000 /* RECOMMENDED */
++#define _FPU_RC_ZERO 0x100
++#define _FPU_RC_UP 0x200
++#define _FPU_RC_DOWN 0x300
++/* Mask for rounding control. */
++#define _FPU_RC_MASK 0x300
++
++#define _FPU_RESERVED 0x0
++
++#define _FPU_DEFAULT 0x0
++#define _FPU_IEEE 0x1F
++
++/* Type of the control word. */
++typedef unsigned int fpu_control_t __attribute__ ((__mode__ (__SI__)));
++
++/* Macros for accessing the hardware control word. */
++extern fpu_control_t __loongarch_fpu_getcw (void) __THROW;
++extern void __loongarch_fpu_setcw (fpu_control_t) __THROW;
++#define _FPU_GETCW(cw) __asm__ volatile("movfcsr2gr %0,$r0" : "=r"(cw))
++#define _FPU_SETCW(cw) __asm__ volatile("movgr2fcsr $r0,%0" : : "r"(cw))
++
++/* Default control word set at startup. */
++extern fpu_control_t __fpu_control;
++
++#endif /* __loongarch_soft_float */
++
++#endif /* fpu_control.h */
+diff --git a/sysdeps/loongarch/gccframe.h b/sysdeps/loongarch/gccframe.h
+new file mode 100644
+index 00000000..19996f3c
+--- /dev/null
++++ b/sysdeps/loongarch/gccframe.h
+@@ -0,0 +1,21 @@
++/* Definition of object in frame unwind info.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define FIRST_PSEUDO_REGISTER 74
++
++#include <sysdeps/generic/gccframe.h>
+diff --git a/sysdeps/loongarch/hp-timing.h b/sysdeps/loongarch/hp-timing.h
+new file mode 100644
+index 00000000..7b36a539
+--- /dev/null
++++ b/sysdeps/loongarch/hp-timing.h
+@@ -0,0 +1,42 @@
++/* High precision, low overhead timing functions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _HP_TIMING_H
++#define _HP_TIMING_H 1
++
++/* We always assume having the timestamp register. */
++#define HP_TIMING_AVAIL (1)
++#define HP_SMALL_TIMING_AVAIL (1)
++
++/* We indeed have inlined functions. */
++#define HP_TIMING_INLINE (1)
++
++/* We use 64bit values for the times. */
++typedef unsigned long long int hp_timing_t;
++
++/* Read the stable counter. */
++#define HP_TIMING_NOW(Var) \
++ ({ \
++ unsigned long long int _count; \
++ asm volatile("rdtime.d\t%0,$r0" : "=r"(_count)); \
++ (Var) = _count; \
++ })
++
++#include <hp-timing-common.h>
++
++#endif /* hp-timing.h */
+diff --git a/sysdeps/loongarch/jmpbuf-offsets.h b/sysdeps/loongarch/jmpbuf-offsets.h
+new file mode 100644
+index 00000000..4df42dfa
+--- /dev/null
++++ b/sysdeps/loongarch/jmpbuf-offsets.h
+@@ -0,0 +1,22 @@
++/* Private macros for accessing __jmp_buf contents.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public License as
++ published by the Free Software Foundation; either version 2.1 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <jmpbuf-unwind.h>
++
++/* Helper for generic ____longjmp_chk(). */
++#define JB_FRAME_ADDRESS(buf) ((void *) _jmpbuf_sp (buf))
+diff --git a/sysdeps/loongarch/jmpbuf-unwind.h b/sysdeps/loongarch/jmpbuf-unwind.h
+new file mode 100644
+index 00000000..a37bef1d
+--- /dev/null
++++ b/sysdeps/loongarch/jmpbuf-unwind.h
+@@ -0,0 +1,45 @@
++/* Examine __jmp_buf for unwinding frames.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <setjmp.h>
++#include <stdint.h>
++#include <unwind.h>
++#include <sysdep.h>
++
++/* Test if longjmp to JMPBUF would unwind the frame
++ containing a local variable at ADDRESS. */
++#define _JMPBUF_UNWINDS(jmpbuf, address, demangle) \
++ ((void *) (address) < (void *) demangle ((jmpbuf)[0].__sp))
++
++#define _JMPBUF_CFA_UNWINDS_ADJ(_jmpbuf, _context, _adj) \
++ _JMPBUF_UNWINDS_ADJ (_jmpbuf, (void *) _Unwind_GetCFA (_context), _adj)
++
++static inline uintptr_t __attribute__ ((unused)) _jmpbuf_sp (__jmp_buf regs)
++{
++ uintptr_t sp = regs[0].__sp;
++#ifdef PTR_DEMANGLE
++ PTR_DEMANGLE (sp);
++#endif
++ return sp;
++}
++
++#define _JMPBUF_UNWINDS_ADJ(_jmpbuf, _address, _adj) \
++ ((uintptr_t) (_address) - (_adj) < _jmpbuf_sp (_jmpbuf) - (_adj))
++
++/* We use the normal longjmp for unwinding. */
++#define __libc_unwind_longjmp(buf, val) __libc_longjmp (buf, val)
+diff --git a/sysdeps/loongarch/ldsodefs.h b/sysdeps/loongarch/ldsodefs.h
+new file mode 100644
+index 00000000..ec91f640
+--- /dev/null
++++ b/sysdeps/loongarch/ldsodefs.h
+@@ -0,0 +1,41 @@
++/* Run-time dynamic linker data structures for loaded ELF shared objects.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LOONGARCH_LDSODEFS_H
++#define _LOONGARCH_LDSODEFS_H 1
++
++#include <elf.h>
++
++struct La_loongarch_regs;
++struct La_loongarch_retval;
++
++#define ARCH_PLTENTER_MEMBERS \
++ ElfW (Addr) (*loongarch_gnu_pltenter) (ElfW (Sym) *, unsigned int, \
++ uintptr_t *, uintptr_t *, \
++ const struct La_loongarch_regs *, \
++ unsigned int *, const char *name, \
++ long int *framesizep);
++
++#define ARCH_PLTEXIT_MEMBERS \
++ unsigned int (*loongarch_gnu_pltexit) (ElfW (Sym) *, unsigned int, \
++ uintptr_t *, uintptr_t *, const struct La_loongarch_regs *, \
++ struct La_loongarch_retval *, const char *);
++
++#include_next <ldsodefs.h>
++
++#endif
+diff --git a/sysdeps/loongarch/libc-start.h b/sysdeps/loongarch/libc-start.h
+new file mode 100644
+index 00000000..961d0b4d
+--- /dev/null
++++ b/sysdeps/loongarch/libc-start.h
+@@ -0,0 +1,25 @@
++/* LoongArch definitions for libc main startup.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef SHARED
++#define ARCH_SETUP_IREL()
++#define ARCH_APPLY_IREL() apply_irel ()
++#ifndef ARCH_SETUP_TLS
++#define ARCH_SETUP_TLS() __libc_setup_tls ()
++#endif
++#endif /* !SHARED */
+diff --git a/sysdeps/loongarch/libc-tls.c b/sysdeps/loongarch/libc-tls.c
+new file mode 100644
+index 00000000..32e303ec
+--- /dev/null
++++ b/sysdeps/loongarch/libc-tls.c
+@@ -0,0 +1,32 @@
++/* Thread-local storage handling in the ELF dynamic linker.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <csu/libc-tls.c>
++#include <dl-tls.h>
++
++/* On LoongArch, linker optimizations are not required, so __tls_get_addr
++ can be called even in statically linked binaries. In this case module
++ must be always 1 and PT_TLS segment exist in the binary, otherwise it
++ would not link. */
++
++void *
++__tls_get_addr (tls_index *ti)
++{
++ dtv_t *dtv = THREAD_DTV ();
++ return (char *) dtv[1].pointer.val + GET_ADDR_OFFSET;
++}
+diff --git a/sysdeps/loongarch/linkmap.h b/sysdeps/loongarch/linkmap.h
+new file mode 100644
+index 00000000..f88ce501
+--- /dev/null
++++ b/sysdeps/loongarch/linkmap.h
+@@ -0,0 +1,4 @@
++struct link_map_machine
++{
++ ElfW (Addr) plt; /* Address of .plt. */
++};
+diff --git a/sysdeps/loongarch/lp64/Implies-after b/sysdeps/loongarch/lp64/Implies-after
+new file mode 100644
+index 00000000..a8cae95f
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/Implies-after
+@@ -0,0 +1 @@
++wordsize-64
+diff --git a/sysdeps/loongarch/lp64/libm-test-ulps b/sysdeps/loongarch/lp64/libm-test-ulps
+new file mode 100644
+index 00000000..d0dfd076
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/libm-test-ulps
+@@ -0,0 +1,1411 @@
++# Begin of automatic generation
++
++# Maximal error of functions:
++Function: "acos":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "acos_downward":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "acos_towardzero":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "acos_upward":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "acosh":
++double: 2
++float: 2
++ldouble: 4
++
++Function: "acosh_downward":
++double: 2
++float: 2
++ldouble: 3
++
++Function: "acosh_towardzero":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "acosh_upward":
++double: 2
++float: 2
++ldouble: 3
++
++Function: "asin":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "asin_downward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "asin_towardzero":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "asin_upward":
++double: 2
++float: 1
++ldouble: 2
++
++Function: "asinh":
++double: 2
++float: 2
++ldouble: 4
++
++Function: "asinh_downward":
++double: 3
++float: 3
++ldouble: 4
++
++Function: "asinh_towardzero":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "asinh_upward":
++double: 3
++float: 3
++ldouble: 4
++
++Function: "atan":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "atan2":
++float: 1
++ldouble: 2
++
++Function: "atan2_downward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: "atan2_towardzero":
++double: 1
++float: 2
++ldouble: 3
++
++Function: "atan2_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "atan_downward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: "atan_towardzero":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "atan_upward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: "atanh":
++double: 2
++float: 2
++ldouble: 4
++
++Function: "atanh_downward":
++double: 3
++float: 3
++ldouble: 4
++
++Function: "atanh_towardzero":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "atanh_upward":
++double: 3
++float: 3
++ldouble: 4
++
++Function: "cabs":
++double: 1
++ldouble: 1
++
++Function: "cabs_downward":
++double: 1
++ldouble: 1
++
++Function: "cabs_towardzero":
++double: 1
++ldouble: 1
++
++Function: "cabs_upward":
++double: 1
++ldouble: 1
++
++Function: Real part of "cacos":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "cacos":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "cacos_downward":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "cacos_downward":
++double: 5
++float: 3
++ldouble: 6
++
++Function: Real part of "cacos_towardzero":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "cacos_towardzero":
++double: 4
++float: 2
++ldouble: 5
++
++Function: Real part of "cacos_upward":
++double: 2
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "cacos_upward":
++double: 5
++float: 5
++ldouble: 7
++
++Function: Real part of "cacosh":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "cacosh":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Real part of "cacosh_downward":
++double: 4
++float: 2
++ldouble: 5
++
++Function: Imaginary part of "cacosh_downward":
++double: 3
++float: 3
++ldouble: 4
++
++Function: Real part of "cacosh_towardzero":
++double: 4
++float: 2
++ldouble: 5
++
++Function: Imaginary part of "cacosh_towardzero":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Real part of "cacosh_upward":
++double: 4
++float: 3
++ldouble: 6
++
++Function: Imaginary part of "cacosh_upward":
++double: 3
++float: 2
++ldouble: 4
++
++Function: "carg":
++float: 1
++ldouble: 2
++
++Function: "carg_downward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: "carg_towardzero":
++double: 1
++float: 2
++ldouble: 3
++
++Function: "carg_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: Real part of "casin":
++double: 1
++float: 1
++ldouble: 2
++
++Function: Imaginary part of "casin":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "casin_downward":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "casin_downward":
++double: 5
++float: 3
++ldouble: 6
++
++Function: Real part of "casin_towardzero":
++double: 3
++float: 1
++ldouble: 3
++
++Function: Imaginary part of "casin_towardzero":
++double: 4
++float: 2
++ldouble: 5
++
++Function: Real part of "casin_upward":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "casin_upward":
++double: 5
++float: 5
++ldouble: 7
++
++Function: Real part of "casinh":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "casinh":
++double: 1
++float: 1
++ldouble: 2
++
++Function: Real part of "casinh_downward":
++double: 5
++float: 3
++ldouble: 6
++
++Function: Imaginary part of "casinh_downward":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Real part of "casinh_towardzero":
++double: 4
++float: 2
++ldouble: 5
++
++Function: Imaginary part of "casinh_towardzero":
++double: 3
++float: 1
++ldouble: 3
++
++Function: Real part of "casinh_upward":
++double: 5
++float: 5
++ldouble: 7
++
++Function: Imaginary part of "casinh_upward":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Real part of "catan":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Imaginary part of "catan":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Real part of "catan_downward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "catan_downward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "catan_towardzero":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "catan_towardzero":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "catan_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: Imaginary part of "catan_upward":
++double: 2
++float: 2
++ldouble: 3
++
++Function: Real part of "catanh":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Imaginary part of "catanh":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Real part of "catanh_downward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "catanh_downward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Real part of "catanh_towardzero":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "catanh_towardzero":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Real part of "catanh_upward":
++double: 4
++float: 4
++ldouble: 4
++
++Function: Imaginary part of "catanh_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "cbrt":
++double: 4
++float: 1
++ldouble: 1
++
++Function: "cbrt_downward":
++double: 4
++float: 1
++ldouble: 1
++
++Function: "cbrt_towardzero":
++double: 3
++float: 1
++ldouble: 1
++
++Function: "cbrt_upward":
++double: 5
++float: 1
++ldouble: 1
++
++Function: Real part of "ccos":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Imaginary part of "ccos":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Real part of "ccos_downward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: Imaginary part of "ccos_downward":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "ccos_towardzero":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "ccos_towardzero":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "ccos_upward":
++double: 1
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "ccos_upward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "ccosh":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Imaginary part of "ccosh":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Real part of "ccosh_downward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "ccosh_downward":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "ccosh_towardzero":
++double: 2
++float: 3
++ldouble: 2
++
++Function: Imaginary part of "ccosh_towardzero":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "ccosh_upward":
++double: 1
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "ccosh_upward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "cexp":
++double: 2
++float: 1
++ldouble: 1
++
++Function: Imaginary part of "cexp":
++double: 1
++float: 2
++ldouble: 1
++
++Function: Real part of "cexp_downward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "cexp_downward":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "cexp_towardzero":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "cexp_towardzero":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "cexp_upward":
++double: 1
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "cexp_upward":
++double: 3
++float: 2
++ldouble: 3
++
++Function: Real part of "clog":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Imaginary part of "clog":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Real part of "clog10":
++double: 3
++float: 4
++ldouble: 2
++
++Function: Imaginary part of "clog10":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "clog10_downward":
++double: 5
++float: 5
++ldouble: 3
++
++Function: Imaginary part of "clog10_downward":
++double: 2
++float: 4
++ldouble: 3
++
++Function: Real part of "clog10_towardzero":
++double: 5
++float: 6
++ldouble: 4
++
++Function: Imaginary part of "clog10_towardzero":
++double: 2
++float: 4
++ldouble: 3
++
++Function: Real part of "clog10_upward":
++double: 6
++float: 5
++ldouble: 4
++
++Function: Imaginary part of "clog10_upward":
++double: 2
++float: 4
++ldouble: 3
++
++Function: Real part of "clog_downward":
++double: 4
++float: 3
++ldouble: 3
++
++Function: Imaginary part of "clog_downward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Real part of "clog_towardzero":
++double: 4
++float: 4
++ldouble: 3
++
++Function: Imaginary part of "clog_towardzero":
++double: 1
++float: 3
++ldouble: 2
++
++Function: Real part of "clog_upward":
++double: 4
++float: 3
++ldouble: 4
++
++Function: Imaginary part of "clog_upward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: "cos":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "cos_downward":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "cos_towardzero":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "cos_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "cosh":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "cosh_downward":
++double: 3
++float: 1
++ldouble: 3
++
++Function: "cosh_towardzero":
++double: 3
++float: 1
++ldouble: 3
++
++Function: "cosh_upward":
++double: 2
++float: 2
++ldouble: 3
++
++Function: Real part of "cpow":
++double: 2
++float: 5
++ldouble: 4
++
++Function: Imaginary part of "cpow":
++float: 2
++ldouble: 1
++
++Function: Real part of "cpow_downward":
++double: 5
++float: 8
++ldouble: 6
++
++Function: Imaginary part of "cpow_downward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Real part of "cpow_towardzero":
++double: 5
++float: 8
++ldouble: 6
++
++Function: Imaginary part of "cpow_towardzero":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Real part of "cpow_upward":
++double: 4
++float: 1
++ldouble: 3
++
++Function: Imaginary part of "cpow_upward":
++double: 1
++float: 2
++ldouble: 2
++
++Function: Real part of "csin":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Imaginary part of "csin":
++ldouble: 1
++
++Function: Real part of "csin_downward":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Imaginary part of "csin_downward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: Real part of "csin_towardzero":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Imaginary part of "csin_towardzero":
++double: 1
++float: 1
++ldouble: 2
++
++Function: Real part of "csin_upward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "csin_upward":
++double: 1
++float: 2
++ldouble: 3
++
++Function: Real part of "csinh":
++float: 1
++ldouble: 1
++
++Function: Imaginary part of "csinh":
++double: 1
++float: 1
++ldouble: 1
++
++Function: Real part of "csinh_downward":
++double: 2
++float: 1
++ldouble: 2
++
++Function: Imaginary part of "csinh_downward":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "csinh_towardzero":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "csinh_towardzero":
++double: 3
++float: 3
++ldouble: 2
++
++Function: Real part of "csinh_upward":
++double: 1
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "csinh_upward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "csqrt":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Imaginary part of "csqrt":
++double: 2
++float: 2
++ldouble: 2
++
++Function: Real part of "csqrt_downward":
++double: 5
++float: 4
++ldouble: 4
++
++Function: Imaginary part of "csqrt_downward":
++double: 4
++float: 3
++ldouble: 3
++
++Function: Real part of "csqrt_towardzero":
++double: 4
++float: 3
++ldouble: 3
++
++Function: Imaginary part of "csqrt_towardzero":
++double: 4
++float: 3
++ldouble: 3
++
++Function: Real part of "csqrt_upward":
++double: 5
++float: 4
++ldouble: 4
++
++Function: Imaginary part of "csqrt_upward":
++double: 3
++float: 3
++ldouble: 3
++
++Function: Real part of "ctan":
++double: 1
++float: 1
++ldouble: 3
++
++Function: Imaginary part of "ctan":
++double: 2
++float: 2
++ldouble: 3
++
++Function: Real part of "ctan_downward":
++double: 6
++float: 5
++ldouble: 4
++
++Function: Imaginary part of "ctan_downward":
++double: 2
++float: 2
++ldouble: 5
++
++Function: Real part of "ctan_towardzero":
++double: 5
++float: 2
++ldouble: 4
++
++Function: Imaginary part of "ctan_towardzero":
++double: 2
++float: 2
++ldouble: 5
++
++Function: Real part of "ctan_upward":
++double: 2
++float: 4
++ldouble: 5
++
++Function: Imaginary part of "ctan_upward":
++double: 2
++float: 2
++ldouble: 5
++
++Function: Real part of "ctanh":
++double: 2
++float: 2
++ldouble: 3
++
++Function: Imaginary part of "ctanh":
++double: 2
++float: 1
++ldouble: 3
++
++Function: Real part of "ctanh_downward":
++double: 4
++float: 2
++ldouble: 5
++
++Function: Imaginary part of "ctanh_downward":
++double: 6
++float: 5
++ldouble: 4
++
++Function: Real part of "ctanh_towardzero":
++double: 2
++float: 2
++ldouble: 5
++
++Function: Imaginary part of "ctanh_towardzero":
++double: 5
++float: 2
++ldouble: 3
++
++Function: Real part of "ctanh_upward":
++double: 2
++float: 2
++ldouble: 5
++
++Function: Imaginary part of "ctanh_upward":
++double: 2
++float: 3
++ldouble: 5
++
++Function: "erf":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "erf_downward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "erf_towardzero":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "erf_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "erfc":
++double: 2
++float: 2
++ldouble: 4
++
++Function: "erfc_downward":
++double: 4
++float: 4
++ldouble: 5
++
++Function: "erfc_towardzero":
++double: 3
++float: 3
++ldouble: 4
++
++Function: "erfc_upward":
++double: 4
++float: 4
++ldouble: 5
++
++Function: "exp":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "exp10":
++double: 2
++ldouble: 2
++
++Function: "exp10_downward":
++double: 3
++float: 1
++ldouble: 3
++
++Function: "exp10_towardzero":
++double: 3
++float: 1
++ldouble: 3
++
++Function: "exp10_upward":
++double: 2
++float: 1
++ldouble: 3
++
++Function: "exp2":
++double: 1
++ldouble: 1
++
++Function: "exp2_downward":
++double: 1
++ldouble: 1
++
++Function: "exp2_towardzero":
++double: 1
++ldouble: 1
++
++Function: "exp2_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "exp_downward":
++double: 1
++float: 1
++
++Function: "exp_towardzero":
++double: 1
++float: 1
++
++Function: "exp_upward":
++double: 1
++float: 1
++
++Function: "expm1":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "expm1_downward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "expm1_towardzero":
++double: 1
++float: 2
++ldouble: 4
++
++Function: "expm1_upward":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "gamma":
++double: 3
++float: 3
++ldouble: 5
++
++Function: "gamma_downward":
++double: 4
++float: 4
++ldouble: 8
++
++Function: "gamma_towardzero":
++double: 4
++float: 3
++ldouble: 5
++
++Function: "gamma_upward":
++double: 4
++float: 5
++ldouble: 8
++
++Function: "hypot":
++double: 1
++ldouble: 1
++
++Function: "hypot_downward":
++double: 1
++ldouble: 1
++
++Function: "hypot_towardzero":
++double: 1
++ldouble: 1
++
++Function: "hypot_upward":
++double: 1
++ldouble: 1
++
++Function: "j0":
++double: 3
++float: 9
++ldouble: 2
++
++Function: "j0_downward":
++double: 6
++float: 9
++ldouble: 9
++
++Function: "j0_towardzero":
++double: 7
++float: 9
++ldouble: 9
++
++Function: "j0_upward":
++double: 9
++float: 9
++ldouble: 7
++
++Function: "j1":
++double: 4
++float: 9
++ldouble: 4
++
++Function: "j1_downward":
++double: 3
++float: 8
++ldouble: 4
++
++Function: "j1_towardzero":
++double: 4
++float: 8
++ldouble: 4
++
++Function: "j1_upward":
++double: 9
++float: 9
++ldouble: 3
++
++Function: "jn":
++double: 4
++float: 4
++ldouble: 7
++
++Function: "jn_downward":
++double: 4
++float: 5
++ldouble: 8
++
++Function: "jn_towardzero":
++double: 4
++float: 5
++ldouble: 8
++
++Function: "jn_upward":
++double: 5
++float: 4
++ldouble: 7
++
++Function: "lgamma":
++double: 3
++float: 3
++ldouble: 5
++
++Function: "lgamma_downward":
++double: 4
++float: 4
++ldouble: 8
++
++Function: "lgamma_towardzero":
++double: 4
++float: 3
++ldouble: 5
++
++Function: "lgamma_upward":
++double: 4
++float: 5
++ldouble: 8
++
++Function: "log":
++double: 1
++ldouble: 1
++
++Function: "log10":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "log10_downward":
++double: 2
++float: 3
++ldouble: 1
++
++Function: "log10_towardzero":
++double: 2
++float: 1
++ldouble: 1
++
++Function: "log10_upward":
++double: 2
++float: 2
++ldouble: 1
++
++Function: "log1p":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "log1p_downward":
++double: 1
++float: 2
++ldouble: 3
++
++Function: "log1p_towardzero":
++double: 2
++float: 2
++ldouble: 3
++
++Function: "log1p_upward":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "log2":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "log2_downward":
++double: 3
++ldouble: 3
++
++Function: "log2_towardzero":
++double: 2
++ldouble: 1
++
++Function: "log2_upward":
++double: 3
++ldouble: 1
++
++Function: "log_downward":
++ldouble: 1
++
++Function: "log_towardzero":
++ldouble: 2
++
++Function: "log_upward":
++double: 1
++ldouble: 2
++
++Function: "pow":
++double: 1
++ldouble: 2
++
++Function: "pow_downward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "pow_towardzero":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "pow_upward":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "sin":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "sin_downward":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "sin_towardzero":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "sin_upward":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "sincos":
++double: 1
++ldouble: 1
++
++Function: "sincos_downward":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "sincos_towardzero":
++double: 1
++float: 1
++ldouble: 2
++
++Function: "sincos_upward":
++double: 1
++float: 1
++ldouble: 3
++
++Function: "sinh":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "sinh_downward":
++double: 3
++float: 3
++ldouble: 3
++
++Function: "sinh_towardzero":
++double: 3
++float: 2
++ldouble: 3
++
++Function: "sinh_upward":
++double: 3
++float: 3
++ldouble: 4
++
++Function: "tan":
++float: 1
++ldouble: 1
++
++Function: "tan_downward":
++double: 1
++float: 2
++ldouble: 1
++
++Function: "tan_towardzero":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "tan_upward":
++double: 1
++float: 1
++ldouble: 1
++
++Function: "tanh":
++double: 2
++float: 2
++ldouble: 2
++
++Function: "tanh_downward":
++double: 3
++float: 3
++ldouble: 4
++
++Function: "tanh_towardzero":
++double: 2
++float: 2
++ldouble: 3
++
++Function: "tanh_upward":
++double: 3
++float: 3
++ldouble: 3
++
++Function: "tgamma":
++double: 9
++float: 8
++ldouble: 4
++
++Function: "tgamma_downward":
++double: 9
++float: 7
++ldouble: 5
++
++Function: "tgamma_towardzero":
++double: 9
++float: 7
++ldouble: 5
++
++Function: "tgamma_upward":
++double: 9
++float: 8
++ldouble: 4
++
++Function: "y0":
++double: 2
++float: 8
++ldouble: 3
++
++Function: "y0_downward":
++double: 3
++float: 8
++ldouble: 7
++
++Function: "y0_towardzero":
++double: 3
++float: 8
++ldouble: 3
++
++Function: "y0_upward":
++double: 2
++float: 8
++ldouble: 4
++
++Function: "y1":
++double: 3
++float: 9
++ldouble: 5
++
++Function: "y1_downward":
++double: 6
++float: 8
++ldouble: 5
++
++Function: "y1_towardzero":
++double: 3
++float: 9
++ldouble: 2
++
++Function: "y1_upward":
++double: 6
++float: 9
++ldouble: 5
++
++Function: "yn":
++double: 3
++float: 3
++ldouble: 5
++
++Function: "yn_downward":
++double: 3
++float: 4
++ldouble: 5
++
++Function: "yn_towardzero":
++double: 3
++float: 3
++ldouble: 5
++
++Function: "yn_upward":
++double: 4
++float: 5
++ldouble: 5
++
++# end of automatic generation
+diff --git a/sysdeps/loongarch/lp64/libm-test-ulps-name b/sysdeps/loongarch/lp64/libm-test-ulps-name
+new file mode 100644
+index 00000000..ce02281e
+--- /dev/null
++++ b/sysdeps/loongarch/lp64/libm-test-ulps-name
+@@ -0,0 +1 @@
++LoongArch 64-bit
+diff --git a/sysdeps/loongarch/machine-gmon.h b/sysdeps/loongarch/machine-gmon.h
+new file mode 100644
+index 00000000..d330fd6e
+--- /dev/null
++++ b/sysdeps/loongarch/machine-gmon.h
+@@ -0,0 +1,37 @@
++/* LoongArch definitions for profiling support.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Accept 'frompc' address as argument from the function that calls
++ _mcount for profiling. Use __builtin_return_address (0)
++ for the 'selfpc' address. */
++
++#include <sysdep.h>
++
++static void mcount_internal (unsigned long int frompc,
++ unsigned long int selfpc);
++
++#define _MCOUNT_DECL(frompc, selfpc) \
++ static inline void mcount_internal (unsigned long int frompc, \
++ unsigned long int selfpc)
++
++#define MCOUNT \
++ void _mcount (void *frompc) \
++ { \
++ mcount_internal ((unsigned long int) frompc, \
++ (unsigned long int) RETURN_ADDRESS (0)); \
++ }
+diff --git a/sysdeps/loongarch/math_private.h b/sysdeps/loongarch/math_private.h
+new file mode 100644
+index 00000000..5665624b
+--- /dev/null
++++ b/sysdeps/loongarch/math_private.h
+@@ -0,0 +1,248 @@
++/* Internal math stuff.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef LOONGARCH_MATH_PRIVATE_H
++#define LOONGARCH_MATH_PRIVATE_H 1
++
++/* Inline functions to speed up the math library implementation. The
++ default versions of these routines are in generic/math_private.h
++ and call fesetround, feholdexcept, etc. These routines use inlined
++ code instead. */
++
++#ifdef __loongarch_hard_float
++
++#include <fenv.h>
++#include <fenv_libc.h>
++#include <fpu_control.h>
++
++#define _FPU_MASK_ALL \
++ (_FPU_MASK_V | _FPU_MASK_Z | _FPU_MASK_O | _FPU_MASK_U | _FPU_MASK_I \
++ | FE_ALL_EXCEPT)
++
++static __always_inline void
++libc_feholdexcept_loongarch (fenv_t *envp)
++{
++ fpu_control_t cw;
++
++ /* Save the current state. */
++ _FPU_GETCW (cw);
++ envp->__fp_control_register = cw;
++
++ /* Clear all exception enable bits and flags. */
++ cw &= ~(_FPU_MASK_ALL);
++ _FPU_SETCW (cw);
++}
++#define libc_feholdexcept libc_feholdexcept_loongarch
++#define libc_feholdexceptf libc_feholdexcept_loongarch
++#define libc_feholdexceptl libc_feholdexcept_loongarch
++
++static __always_inline void
++libc_fesetround_loongarch (int round)
++{
++ fpu_control_t cw;
++
++ /* Get current state. */
++ _FPU_GETCW (cw);
++
++ /* Set rounding bits. */
++ cw &= ~_FPU_RC_MASK;
++ cw |= round;
++
++ /* Set new state. */
++ _FPU_SETCW (cw);
++}
++#define libc_fesetround libc_fesetround_loongarch
++#define libc_fesetroundf libc_fesetround_loongarch
++#define libc_fesetroundl libc_fesetround_loongarch
++
++static __always_inline void
++libc_feholdexcept_setround_loongarch (fenv_t *envp, int round)
++{
++ fpu_control_t cw;
++
++ /* Save the current state. */
++ _FPU_GETCW (cw);
++ envp->__fp_control_register = cw;
++
++ /* Clear all exception enable bits and flags. */
++ cw &= ~(_FPU_MASK_ALL);
++
++ /* Set rounding bits. */
++ cw &= ~_FPU_RC_MASK;
++ cw |= round;
++
++ /* Set new state. */
++ _FPU_SETCW (cw);
++}
++#define libc_feholdexcept_setround libc_feholdexcept_setround_loongarch
++#define libc_feholdexcept_setroundf libc_feholdexcept_setround_loongarch
++#define libc_feholdexcept_setroundl libc_feholdexcept_setround_loongarch
++
++#define libc_feholdsetround libc_feholdexcept_setround_loongarch
++#define libc_feholdsetroundf libc_feholdexcept_setround_loongarch
++#define libc_feholdsetroundl libc_feholdexcept_setround_loongarch
++
++static __always_inline void
++libc_fesetenv_loongarch (fenv_t *envp)
++{
++ fpu_control_t cw __attribute__ ((unused));
++
++ /* Read current state to flush fpu pipeline. */
++ _FPU_GETCW (cw);
++
++ _FPU_SETCW (envp->__fp_control_register);
++}
++#define libc_fesetenv libc_fesetenv_loongarch
++#define libc_fesetenvf libc_fesetenv_loongarch
++#define libc_fesetenvl libc_fesetenv_loongarch
++
++static __always_inline int
++libc_feupdateenv_test_loongarch (fenv_t *envp, int excepts)
++{
++ /* int ret = fetestexcept (excepts); feupdateenv (envp); return ret; */
++ int cw, temp;
++
++ /* Get current control word. */
++ _FPU_GETCW (cw);
++
++ /* Set flag bits (which are accumulative), and *also* set the
++ cause bits. The setting of the cause bits is what actually causes
++ the hardware to generate the exception, if the corresponding enable
++ bit is set as well. */
++ temp = cw & FE_ALL_EXCEPT;
++ temp |= envp->__fp_control_register | (temp << CAUSE_SHIFT);
++
++ /* Set new state. */
++ _FPU_SETCW (temp);
++
++ return cw & excepts & FE_ALL_EXCEPT;
++}
++#define libc_feupdateenv_test libc_feupdateenv_test_loongarch
++#define libc_feupdateenv_testf libc_feupdateenv_test_loongarch
++#define libc_feupdateenv_testl libc_feupdateenv_test_loongarch
++
++static __always_inline void
++libc_feupdateenv_loongarch (fenv_t *envp)
++{
++ libc_feupdateenv_test_loongarch (envp, 0);
++}
++#define libc_feupdateenv libc_feupdateenv_loongarch
++#define libc_feupdateenvf libc_feupdateenv_loongarch
++#define libc_feupdateenvl libc_feupdateenv_loongarch
++
++#define libc_feresetround libc_feupdateenv_loongarch
++#define libc_feresetroundf libc_feupdateenv_loongarch
++#define libc_feresetroundl libc_feupdateenv_loongarch
++
++static __always_inline int
++libc_fetestexcept_loongarch (int excepts)
++{
++ int cw;
++
++ /* Get current control word. */
++ _FPU_GETCW (cw);
++
++ return cw & excepts & FE_ALL_EXCEPT;
++}
++#define libc_fetestexcept libc_fetestexcept_loongarch
++#define libc_fetestexceptf libc_fetestexcept_loongarch
++#define libc_fetestexceptl libc_fetestexcept_loongarch
++
++/* Enable support for rounding mode context. */
++#define HAVE_RM_CTX 1
++
++static __always_inline void
++libc_feholdexcept_setround_loongarch_ctx (struct rm_ctx *ctx, int round)
++{
++ fpu_control_t old, new;
++
++ /* Save the current state. */
++ _FPU_GETCW (old);
++ ctx->env.__fp_control_register = old;
++
++ /* Clear all exception enable bits and flags. */
++ new = old & ~(_FPU_MASK_ALL);
++
++ /* Set rounding bits. */
++ new = (new & ~_FPU_RC_MASK) | round;
++
++ if (__glibc_unlikely (new != old))
++ {
++ _FPU_SETCW (new);
++ ctx->updated_status = true;
++ }
++ else
++ ctx->updated_status = false;
++}
++#define libc_feholdexcept_setround_ctx libc_feholdexcept_setround_loongarch_ctx
++#define libc_feholdexcept_setroundf_ctx \
++ libc_feholdexcept_setround_loongarch_ctx
++#define libc_feholdexcept_setroundl_ctx \
++ libc_feholdexcept_setround_loongarch_ctx
++
++static __always_inline void
++libc_fesetenv_loongarch_ctx (struct rm_ctx *ctx)
++{
++ libc_fesetenv_loongarch (&ctx->env);
++}
++#define libc_fesetenv_ctx libc_fesetenv_loongarch_ctx
++#define libc_fesetenvf_ctx libc_fesetenv_loongarch_ctx
++#define libc_fesetenvl_ctx libc_fesetenv_loongarch_ctx
++
++static __always_inline void
++libc_feupdateenv_loongarch_ctx (struct rm_ctx *ctx)
++{
++ if (__glibc_unlikely (ctx->updated_status))
++ libc_feupdateenv_test_loongarch (&ctx->env, 0);
++}
++#define libc_feupdateenv_ctx libc_feupdateenv_loongarch_ctx
++#define libc_feupdateenvf_ctx libc_feupdateenv_loongarch_ctx
++#define libc_feupdateenvl_ctx libc_feupdateenv_loongarch_ctx
++#define libc_feresetround_ctx libc_feupdateenv_loongarch_ctx
++#define libc_feresetroundf_ctx libc_feupdateenv_loongarch_ctx
++#define libc_feresetroundl_ctx libc_feupdateenv_loongarch_ctx
++
++static __always_inline void
++libc_feholdsetround_loongarch_ctx (struct rm_ctx *ctx, int round)
++{
++ fpu_control_t old, new;
++
++ /* Save the current state. */
++ _FPU_GETCW (old);
++ ctx->env.__fp_control_register = old;
++
++ /* Set rounding bits. */
++ new = (old & ~_FPU_RC_MASK) | round;
++
++ if (__glibc_unlikely (new != old))
++ {
++ _FPU_SETCW (new);
++ ctx->updated_status = true;
++ }
++ else
++ ctx->updated_status = false;
++}
++#define libc_feholdsetround_ctx libc_feholdsetround_loongarch_ctx
++#define libc_feholdsetroundf_ctx libc_feholdsetround_loongarch_ctx
++#define libc_feholdsetroundl_ctx libc_feholdsetround_loongarch_ctx
++
++#endif
++
++#include_next <math_private.h>
++
++#endif
+diff --git a/sysdeps/loongarch/memusage.h b/sysdeps/loongarch/memusage.h
+new file mode 100644
+index 00000000..bdf24bb2
+--- /dev/null
++++ b/sysdeps/loongarch/memusage.h
+@@ -0,0 +1,25 @@
++/* Machine-specific definitions for memory usage profiling.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define GETSP() \
++ ({ \
++ register uintptr_t stack_ptr asm("$sp"); \
++ stack_ptr; \
++ })
++
++#include <sysdeps/generic/memusage.h>
+diff --git a/sysdeps/loongarch/nptl/Makefile b/sysdeps/loongarch/nptl/Makefile
+new file mode 100644
+index 00000000..86d57110
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/Makefile
+@@ -0,0 +1,21 @@
++# Makefile for sysdeps/loongarch/nptl.
++# Copyright (C) 2021 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++#
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++#
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++#
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <https://www.gnu.org/licenses/>.
++
++ifeq ($(subdir),csu)
++gen-as-const-headers += tcb-offsets.sym
++endif
+diff --git a/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h
+new file mode 100644
+index 00000000..e57f122a
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/bits/pthreadtypes-arch.h
+@@ -0,0 +1,41 @@
++/* Machine-specific pthread type layouts.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _BITS_PTHREADTYPES_ARCH_H
++#define _BITS_PTHREADTYPES_ARCH_H 1
++
++#include <bits/endian.h>
++
++#ifdef __loongarch_lp64
++#define __SIZEOF_PTHREAD_ATTR_T 56
++#define __SIZEOF_PTHREAD_MUTEX_T 40
++#define __SIZEOF_PTHREAD_MUTEXATTR_T 4
++#define __SIZEOF_PTHREAD_COND_T 48
++#define __SIZEOF_PTHREAD_CONDATTR_T 4
++#define __SIZEOF_PTHREAD_RWLOCK_T 56
++#define __SIZEOF_PTHREAD_RWLOCKATTR_T 8
++#define __SIZEOF_PTHREAD_BARRIER_T 32
++#define __SIZEOF_PTHREAD_BARRIERATTR_T 4
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++#define __LOCK_ALIGNMENT
++#define __ONCE_ALIGNMENT
++
++#endif /* bits/pthreadtypes.h */
+diff --git a/sysdeps/loongarch/nptl/bits/semaphore.h b/sysdeps/loongarch/nptl/bits/semaphore.h
+new file mode 100644
+index 00000000..510f3b0e
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/bits/semaphore.h
+@@ -0,0 +1,32 @@
++/* POSIX semaphore type layout
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SEMAPHORE_H
++#error "Never use <bits/semaphore.h> directly; include <semaphore.h> instead."
++#endif
++
++#define __SIZEOF_SEM_T (4 * __SIZEOF_POINTER__)
++
++/* Value returned if `sem_open' failed. */
++#define SEM_FAILED ((sem_t *) 0)
++
++typedef union
++{
++ char __size[__SIZEOF_SEM_T];
++ long int __align;
++} sem_t;
+diff --git a/sysdeps/loongarch/nptl/bits/struct_rwlock.h b/sysdeps/loongarch/nptl/bits/struct_rwlock.h
+new file mode 100644
+index 00000000..12b6a469
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/bits/struct_rwlock.h
+@@ -0,0 +1,44 @@
++/* LoongArch internal rwlock struct definitions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _RWLOCK_INTERNAL_H
++#define _RWLOCK_INTERNAL_H
++
++/* There is a lot of padding in this structure. While it's not strictly
++ necessary on LoongArch, we're going to leave it in to be on the safe side in
++ case it's needed in the future. Most other architectures have the padding,
++ so this gives us the same extensibility as everyone else has. */
++struct __pthread_rwlock_arch_t
++{
++ unsigned int __readers;
++ unsigned int __writers;
++ unsigned int __wrphase_futex;
++ unsigned int __writers_futex;
++ unsigned int __pad3;
++ unsigned int __pad4;
++ int __cur_writer;
++ int __shared;
++ unsigned long int __pad1;
++ unsigned long int __pad2;
++ unsigned int __flags;
++};
++
++#define __PTHREAD_RWLOCK_INITIALIZER(__flags) \
++ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, __flags
++
++#endif
+diff --git a/sysdeps/loongarch/nptl/pthread-offsets.h b/sysdeps/loongarch/nptl/pthread-offsets.h
+new file mode 100644
+index 00000000..415c3c11
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/pthread-offsets.h
+@@ -0,0 +1,15 @@
++#if __WORDSIZE == 64
++#define __PTHREAD_MUTEX_KIND_OFFSET 16
++#else
++#define __PTHREAD_MUTEX_KIND_OFFSET 12
++#endif
++
++#if __WORDSIZE == 64
++#define __PTHREAD_RWLOCK_FLAGS_OFFSET 48
++#else
++#if __BYTE_ORDER == __BIG_ENDIAN
++#define __PTHREAD_RWLOCK_FLAGS_OFFSET 27
++#else
++#define __PTHREAD_RWLOCK_FLAGS_OFFSET 24
++#endif
++#endif
+diff --git a/sysdeps/loongarch/nptl/pthreaddef.h b/sysdeps/loongarch/nptl/pthreaddef.h
+new file mode 100644
+index 00000000..674ba844
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/pthreaddef.h
+@@ -0,0 +1,34 @@
++/* pthread machine parameter definitions.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Default stack size. */
++#define ARCH_STACK_DEFAULT_SIZE (2 * 1024 * 1024)
++
++/* Minimum guard size. */
++#define ARCH_MIN_GUARD_SIZE 0
++
++/* Required stack pointer alignment at beginning. */
++#define STACK_ALIGN 16
++
++/* Minimal stack size after allocating thread descriptor and guard size. */
++#define MINIMAL_REST_STACK 2048
++
++#define TCB_ALIGNMENT 16
++
++/* Location of current stack frame. */
++#define CURRENT_STACK_FRAME __builtin_frame_address (0)
+diff --git a/sysdeps/loongarch/nptl/tcb-offsets.sym b/sysdeps/loongarch/nptl/tcb-offsets.sym
+new file mode 100644
+index 00000000..7d0c7596
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/tcb-offsets.sym
+@@ -0,0 +1,6 @@
++#include <sysdep.h>
++#include <tls.h>
++
++#define thread_offsetof(mem) (long)(offsetof (struct pthread, mem) - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
++
++MULTIPLE_THREADS_OFFSET thread_offsetof (header.multiple_threads)
+diff --git a/sysdeps/loongarch/nptl/tls.h b/sysdeps/loongarch/nptl/tls.h
+new file mode 100644
+index 00000000..3b17e0b7
+--- /dev/null
++++ b/sysdeps/loongarch/nptl/tls.h
+@@ -0,0 +1,138 @@
++/* Definition for thread-local data handling.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LOONGARCH_TLS_H
++#define _LOONGARCH_TLS_H 1
++
++#include <dl-sysdep.h>
++
++#ifndef __ASSEMBLER__
++#include <stdbool.h>
++#include <stddef.h>
++#include <stdint.h>
++#include <dl-dtv.h>
++
++register void *__thread_self asm("$tp"); /* FIXME */
++#define READ_THREAD_POINTER() ({ __thread_self; })
++
++/* Get system call information. */
++#include <sysdep.h>
++
++/* The TP points to the start of the thread blocks. */
++#define TLS_DTV_AT_TP 1
++#define TLS_TCB_AT_TP 0
++
++/* Get the thread descriptor definition. */
++#include <nptl/descr.h>
++
++typedef struct
++{
++ dtv_t *dtv;
++ void *private;
++} tcbhead_t;
++
++/* This is the size of the initial TCB. Because our TCB is before the thread
++ pointer, we don't need this. */
++#define TLS_INIT_TCB_SIZE 0
++
++/* Alignment requirements for the initial TCB. */
++#define TLS_INIT_TCB_ALIGN __alignof__(struct pthread)
++
++/* This is the size of the TCB. Because our TCB is before the thread
++ pointer, we don't need this. */
++#define TLS_TCB_SIZE 0
++
++/* Alignment requirements for the TCB. */
++#define TLS_TCB_ALIGN __alignof__(struct pthread)
++
++/* This is the size we need before TCB - actually, it includes the TCB. */
++#define TLS_PRE_TCB_SIZE \
++ (sizeof (struct pthread) \
++ + ((sizeof (tcbhead_t) + TLS_TCB_ALIGN - 1) & ~(TLS_TCB_ALIGN - 1)))
++
++/* The thread pointer tp points to the end of the TCB.
++ The pthread_descr structure is immediately in front of the TCB. */
++#define TLS_TCB_OFFSET 0
++
++/* Install the dtv pointer. The pointer passed is to the element with
++ index -1 which contain the length. */
++#define INSTALL_DTV(tcbp, dtvp) (((tcbhead_t *) (tcbp))[-1].dtv = (dtvp) + 1)
++
++/* Install new dtv for current thread. */
++#define INSTALL_NEW_DTV(dtv) (THREAD_DTV () = (dtv))
++
++/* Return dtv of given thread descriptor. */
++#define GET_DTV(tcbp) (((tcbhead_t *) (tcbp))[-1].dtv)
++
++/* Code to initially initialize the thread pointer. */
++#define TLS_INIT_TP(tcbp) \
++ ({ \
++ __thread_self = (char *) tcbp + TLS_TCB_OFFSET; \
++ NULL; \
++ })
++
++/* Return the address of the dtv for the current thread. */
++#define THREAD_DTV() \
++ (((tcbhead_t *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET))[-1].dtv)
++
++/* Return the thread descriptor for the current thread. */
++#define THREAD_SELF \
++ ((struct pthread *) (READ_THREAD_POINTER () - TLS_TCB_OFFSET \
++ - TLS_PRE_TCB_SIZE))
++
++/* Value passed to 'clone' for initialization of the thread register. */
++#define TLS_DEFINE_INIT_TP(tp, pd) \
++ void *tp = (void *) (pd) + TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE
++
++/* Informs libthread_db that the thread pointer is register 2, which is used
++ * to know how to do THREAD_SELF. */
++#define DB_THREAD_SELF \
++ REGISTER (64, 64, 2 * 8, -TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
++
++/* Access to data in the thread descriptor is easy. */
++# include <tcb-access.h>
++
++/* l_tls_offset == 0 is perfectly valid, so we have to use some different
++ value to mean unset l_tls_offset. */
++#define NO_TLS_OFFSET -1
++
++/* Get and set the global scope generation counter in struct pthread. */
++#define THREAD_GSCOPE_IN_TCB 1
++#define THREAD_GSCOPE_FLAG_UNUSED 0
++#define THREAD_GSCOPE_FLAG_USED 1
++#define THREAD_GSCOPE_FLAG_WAIT 2
++#define THREAD_GSCOPE_RESET_FLAG() \
++ do \
++ { \
++ int __res = atomic_exchange_rel (&THREAD_SELF->header.gscope_flag, \
++ THREAD_GSCOPE_FLAG_UNUSED); \
++ if (__res == THREAD_GSCOPE_FLAG_WAIT) \
++ lll_futex_wake (&THREAD_SELF->header.gscope_flag, 1, LLL_PRIVATE); \
++ } \
++ while (0)
++#define THREAD_GSCOPE_SET_FLAG() \
++ do \
++ { \
++ THREAD_SELF->header.gscope_flag = THREAD_GSCOPE_FLAG_USED; \
++ atomic_write_barrier (); \
++ } \
++ while (0)
++
++#endif /* __ASSEMBLER__ */
++
++#endif /* tls.h */
+diff --git a/sysdeps/loongarch/preconfigure b/sysdeps/loongarch/preconfigure
+new file mode 100644
+index 00000000..2e3abb9e
+--- /dev/null
++++ b/sysdeps/loongarch/preconfigure
+@@ -0,0 +1,52 @@
++# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
++# Local preconfigure fragment for sysdeps/loongarch
++
++case "$machine" in
++loongarch*)
++
++ abi=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __loongarch_\(lp64\|ilp32\).*/\1/p'`
++ float_abi=`$CC $CFLAGS $CPPFLAGS -E -dM -xc /dev/null | sed -n 's/^#define __loongarch_\(soft\|single\|double\)_float.*/\1/p'`
++
++ with_fp_cond="!defined __loongarch_soft_float"
++
++ case "$float_abi" in
++ soft)
++ abi_flen=0
++ as_fn_error 1 "loongarch does not yet support soft floating-point ABI!!" "$LINENO" 5
++ ;;
++ single)
++ as_fn_error 1 "glibc does not yet support the single floating-point ABI!!" "$LINENO" 5
++ ;;
++ double)
++ abi_flen=64
++ ;;
++ *)
++ as_fn_error 1 "Unable to determine floating-point ABI!!" "$LINENO" 5
++ ;;
++ esac
++
++ case "$abi" in
++ ilp32)
++ as_fn_error 1 "loongarch does not yet support ilp32 ABI!!" "$LINENO" 5
++ ;;
++ lp64)
++ grlen=64
++ machine=loongarch/lp64
++ ;;
++ *)
++ as_fn_error 1 "Unable to determine GRLEN!!" "$LINENO" 5
++ ;;
++ esac
++
++ cat >>confdefs.h <<_ACEOF
++#define LOONGARCH_ABI_GRLEN $grlen
++_ACEOF
++
++ cat >>confdefs.h <<_ACEOF
++#define LOONGARCH_ABI_FRLEN $abi_flen
++_ACEOF
++
++
++ base_machine=loongarch
++ ;;
++esac
+diff --git a/sysdeps/loongarch/setjmp.S b/sysdeps/loongarch/setjmp.S
+new file mode 100644
+index 00000000..00ea14b2
+--- /dev/null
++++ b/sysdeps/loongarch/setjmp.S
+@@ -0,0 +1,66 @@
++/* setjmp for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++#include <sys/asm.h>
++
++ENTRY (_setjmp)
++ li.w a1,0
++ b HIDDEN_JUMPTARGET (__sigsetjmp)
++END (_setjmp)
++
++ENTRY (setjmp)
++ li.w a1,1
++END (setjmp)
++
++ENTRY (__sigsetjmp)
++ REG_S ra, a0, 0*SZREG
++ REG_S sp, a0, 1*SZREG
++ REG_S x, a0, 2*SZREG
++ REG_S fp, a0, 3*SZREG
++ REG_S s0, a0, 4*SZREG
++ REG_S s1, a0, 5*SZREG
++ REG_S s2, a0, 6*SZREG
++ REG_S s3, a0, 7*SZREG
++ REG_S s4, a0, 8*SZREG
++ REG_S s5, a0, 9*SZREG
++ REG_S s6, a0, 10*SZREG
++ REG_S s7, a0, 11*SZREG
++ REG_S s8, a0, 12*SZREG
++
++#ifndef __loongarch_soft_float
++ FREG_S $f24, a0, 13*SZREG + 0*SZFREG
++ FREG_S $f25, a0, 13*SZREG + 1*SZFREG
++ FREG_S $f26, a0, 13*SZREG + 2*SZFREG
++ FREG_S $f27, a0, 13*SZREG + 3*SZFREG
++ FREG_S $f28, a0, 13*SZREG + 4*SZFREG
++ FREG_S $f29, a0, 13*SZREG + 5*SZFREG
++ FREG_S $f30, a0, 13*SZREG + 6*SZFREG
++ FREG_S $f31, a0, 13*SZREG + 7*SZFREG
++#endif
++
++#if !IS_IN (libc) && IS_IN(rtld)
++ li.w v0, 0
++ jirl zero,ra,0
++#else
++ b __sigjmp_save
++#endif
++END (__sigsetjmp)
++
++hidden_def (__sigsetjmp)
++weak_alias (_setjmp, __GI__setjmp)
+diff --git a/sysdeps/loongarch/sfp-machine.h b/sysdeps/loongarch/sfp-machine.h
+new file mode 100644
+index 00000000..61f11dd0
+--- /dev/null
++++ b/sysdeps/loongarch/sfp-machine.h
+@@ -0,0 +1,102 @@
++/* LoongArch softfloat definitions
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <fenv.h>
++#include <fpu_control.h>
++
++#define _FP_W_TYPE_SIZE 64
++#define _FP_W_TYPE unsigned long long
++#define _FP_WS_TYPE signed long long
++#define _FP_I_TYPE long long
++
++#define _FP_MUL_MEAT_S(R, X, Y) _FP_MUL_MEAT_1_imm (_FP_WFRACBITS_S, R, X, Y)
++#define _FP_MUL_MEAT_D(R, X, Y) \
++ _FP_MUL_MEAT_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
++#define _FP_MUL_MEAT_Q(R, X, Y) \
++ _FP_MUL_MEAT_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
++
++#define _FP_MUL_MEAT_DW_S(R, X, Y) \
++ _FP_MUL_MEAT_DW_1_imm (_FP_WFRACBITS_S, R, X, Y)
++#define _FP_MUL_MEAT_DW_D(R, X, Y) \
++ _FP_MUL_MEAT_DW_1_wide (_FP_WFRACBITS_D, R, X, Y, umul_ppmm)
++#define _FP_MUL_MEAT_DW_Q(R, X, Y) \
++ _FP_MUL_MEAT_DW_2_wide_3mul (_FP_WFRACBITS_Q, R, X, Y, umul_ppmm)
++
++#define _FP_DIV_MEAT_S(R, X, Y) \
++ _FP_DIV_MEAT_1_imm (S, R, X, Y, _FP_DIV_HELP_imm)
++#define _FP_DIV_MEAT_D(R, X, Y) _FP_DIV_MEAT_1_udiv_norm (D, R, X, Y)
++#define _FP_DIV_MEAT_Q(R, X, Y) _FP_DIV_MEAT_2_udiv (Q, R, X, Y)
++
++#define _FP_NANFRAC_S _FP_QNANBIT_S
++#define _FP_NANFRAC_D _FP_QNANBIT_D
++#define _FP_NANFRAC_Q _FP_QNANBIT_Q, 0
++
++#define _FP_NANSIGN_S 0
++#define _FP_NANSIGN_D 0
++#define _FP_NANSIGN_Q 0
++
++#define _FP_KEEPNANFRACP 1
++#define _FP_QNANNEGATEDP 0
++
++/* NaN payloads should be preserved for NAN2008. */
++#define _FP_CHOOSENAN(fs, wc, R, X, Y, OP) \
++ do \
++ { \
++ R##_s = X##_s; \
++ _FP_FRAC_COPY_##wc (R, X); \
++ R##_c = FP_CLS_NAN; \
++ } \
++ while (0)
++
++#define _FP_DECL_EX fpu_control_t _fcw
++
++#define FP_ROUNDMODE (_fcw & 0x300)
++
++#define FP_RND_NEAREST FE_TONEAREST
++#define FP_RND_ZERO FE_TOWARDZERO
++#define FP_RND_PINF FE_UPWARD
++#define FP_RND_MINF FE_DOWNWARD
++
++#define FP_EX_INVALID FE_INVALID
++#define FP_EX_OVERFLOW FE_OVERFLOW
++#define FP_EX_UNDERFLOW FE_UNDERFLOW
++#define FP_EX_DIVZERO FE_DIVBYZERO
++#define FP_EX_INEXACT FE_INEXACT
++
++#define _FP_TININESS_AFTER_ROUNDING 1
++
++#ifdef __loongarch_hard_float
++#define FP_INIT_ROUNDMODE \
++ do \
++ { \
++ _FPU_GETCW (_fcw); \
++ } \
++ while (0)
++
++#define FP_HANDLE_EXCEPTIONS \
++ do \
++ { \
++ if (__builtin_expect (_fex, 0)) \
++ _FPU_SETCW (_fcw | _fex | (_fex << 8)); \
++ } \
++ while (0)
++#define FP_TRAPPING_EXCEPTIONS ((_fcw << 16) & 0x1f0000)
++#else
++#define FP_INIT_ROUNDMODE _fcw = FP_RND_NEAREST
++#endif
+diff --git a/sysdeps/loongarch/sotruss-lib.c b/sysdeps/loongarch/sotruss-lib.c
+new file mode 100644
+index 00000000..8a7a438b
+--- /dev/null
++++ b/sysdeps/loongarch/sotruss-lib.c
+@@ -0,0 +1,50 @@
++/* Override generic sotruss-lib.c to define actual functions for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define HAVE_ARCH_PLTENTER
++#define HAVE_ARCH_PLTEXIT
++
++#include <elf/sotruss-lib.c>
++
++ElfW (Addr)
++la_loongarch_gnu_pltenter (ElfW (Sym) * sym __attribute__ ((unused)),
++ unsigned int ndx __attribute__ ((unused)),
++ uintptr_t *refcook, uintptr_t *defcook,
++ La_loongarch_regs *regs, unsigned int *flags,
++ const char *symname, long int *framesizep)
++{
++ print_enter (refcook, defcook, symname, regs->lr_reg[0], regs->lr_reg[1],
++ regs->lr_reg[2], *flags);
++
++ /* No need to copy anything, we will not need the parameters in any case. */
++ *framesizep = 0;
++
++ return sym->st_value;
++}
++
++unsigned int
++la_loongarch_gnu_pltexit (ElfW (Sym) * sym, unsigned int ndx,
++ uintptr_t *refcook, uintptr_t *defcook,
++ const struct La_loongarch_regs *inregs,
++ struct La_loongarch_retval *outregs,
++ const char *symname)
++{
++ print_exit (refcook, defcook, symname, outregs->lrv_a0);
++
++ return 0;
++}
+diff --git a/sysdeps/loongarch/stackinfo.h b/sysdeps/loongarch/stackinfo.h
+new file mode 100644
+index 00000000..a990a471
+--- /dev/null
++++ b/sysdeps/loongarch/stackinfo.h
+@@ -0,0 +1,33 @@
++/* Stack environment definitions for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* This file contains a bit of information about the stack allocation
++ of the processor. */
++
++#ifndef _STACKINFO_H
++#define _STACKINFO_H 1
++
++#include <elf.h>
++
++/* On LoongArch the stack grows down. */
++#define _STACK_GROWS_DOWN 1
++
++/* Default to a non-executable stack. */
++#define DEFAULT_STACK_PERMS (PF_R | PF_W)
++
++#endif /* stackinfo.h */
+diff --git a/sysdeps/loongarch/start.S b/sysdeps/loongarch/start.S
+new file mode 100644
+index 00000000..0deda78a
+--- /dev/null
++++ b/sysdeps/loongarch/start.S
+@@ -0,0 +1,69 @@
++/* Startup code compliant to the ELF LoongArch ABI.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define __ASSEMBLY__ 1
++#include <entry.h>
++#include <sys/asm.h>
++
++/* The entry point's job is to call __libc_start_main. Per the ABI,
++ a0 contains the address of a function to be passed to atexit.
++ __libc_start_main wants this in a5. */
++
++/*
++int
++__libc_start_main (int (*main) (int, char **, char **),
++ int argc,
++ char **argv,
++ __typeof (main) init,
++ void (*fini) (void),
++ void (*rtld_fini) (void),
++ void *stack_end);
++ */
++
++ENTRY (ENTRY_POINT)
++
++/* Terminate call stack by noting ra is undefined. Use a dummy
++ .cfi_label to force starting the FDE. */
++ .cfi_label .Ldummy
++ cfi_undefined (1)
++ or a5, a0, zero /* rtld_fini */
++
++/* We must get symbol main through GOT table, since main may not be local.
++ For instance: googletest defines main in dynamic library. */
++ la.got a0, t0, main
++#ifdef __loongarch_lp64
++ ld.d a1, sp, 0
++ addi.d a2, sp, SZREG
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++ /* Adjust $sp for 16-aligned */
++ srli.d sp, sp, 4
++ slli.d sp, sp, 4
++
++ move a3, zero /* used to be init */
++ move a4, zero /* used to be fini */
++ or a6, sp, zero /* stack_end */
++
++ la.got ra, t0, __libc_start_main
++ jirl ra, ra, 0
++
++ la.got ra, t0, abort
++ jirl ra, ra, 0
++END (ENTRY_POINT)
+diff --git a/sysdeps/loongarch/sys/asm.h b/sysdeps/loongarch/sys/asm.h
+new file mode 100644
+index 00000000..1133f761
+--- /dev/null
++++ b/sysdeps/loongarch/sys/asm.h
+@@ -0,0 +1,58 @@
++/* Miscellaneous macros.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_ASM_H
++#define _SYS_ASM_H
++
++#include <sys/regdef.h>
++#include <sysdeps/generic/sysdep.h>
++
++/* Macros to handle different pointer/register sizes for 32/64-bit code. */
++#ifdef __loongarch_lp64
++#define PTRLOG 3
++#define SZREG 8
++#define SZFREG 8
++#define REG_L ld.d
++#define REG_S st.d
++#define FREG_L fld.d
++#define FREG_S fst.d
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++/* Declare leaf routine. */
++#define LEAF(symbol) \
++ .text; \
++ .globl symbol; \
++ .align 3; \
++ cfi_startproc; \
++ .type symbol, @function; \
++ symbol:
++
++#define ENTRY(symbol) LEAF (symbol)
++
++/* Mark end of function. */
++#undef END
++#define END(function) \
++ cfi_endproc; \
++ .size function, .- function;
++
++/* Stack alignment. */
++#define ALMASK ~15
++
++#endif /* sys/asm.h */
+diff --git a/sysdeps/loongarch/sys/ifunc.h b/sysdeps/loongarch/sys/ifunc.h
+new file mode 100644
+index 00000000..461df20c
+--- /dev/null
++++ b/sysdeps/loongarch/sys/ifunc.h
+@@ -0,0 +1,30 @@
++/* Definitions used by LoongArch indirect function resolvers.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_IFUNC_H
++#define _SYS_IFUNC_H
++
++struct __ifunc_arg_t
++{
++ unsigned long _size; /* Size of the struct, so it can grow. */
++ unsigned long _hwcap;
++};
++
++typedef struct __ifunc_arg_t __ifunc_arg_t;
++
++#endif
+diff --git a/sysdeps/loongarch/sys/regdef.h b/sysdeps/loongarch/sys/regdef.h
+new file mode 100644
+index 00000000..f53447db
+--- /dev/null
++++ b/sysdeps/loongarch/sys/regdef.h
+@@ -0,0 +1,98 @@
++/* Register Macro definitions
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_REGDEF_H
++#define _SYS_REGDEF_H
++
++#ifdef __loongarch_lp64
++#define zero $r0
++#define ra $r1
++#define tp $r2
++#define sp $r3
++#define a0 $r4
++#define a1 $r5
++#define a2 $r6
++#define a3 $r7
++#define a4 $r8
++#define a5 $r9
++#define a6 $r10
++#define a7 $r11
++#define v0 $r4
++#define v1 $r5
++#define t0 $r12
++#define t1 $r13
++#define t2 $r14
++#define t3 $r15
++#define t4 $r16
++#define t5 $r17
++#define t6 $r18
++#define t7 $r19
++#define t8 $r20
++#define x $r21
++#define fp $r22
++#define s0 $r23
++#define s1 $r24
++#define s2 $r25
++#define s3 $r26
++#define s4 $r27
++#define s5 $r28
++#define s6 $r29
++#define s7 $r30
++#define s8 $r31
++
++#define fa0 $f0
++#define fa1 $f1
++#define fa2 $f2
++#define fa3 $f3
++#define fa4 $f4
++#define fa5 $f5
++#define fa6 $f6
++#define fa7 $f7
++#define fv0 $f0
++#define fv1 $f1
++#define ft0 $f8
++#define ft1 $f9
++#define ft2 $f10
++#define ft3 $f11
++#define ft4 $f12
++#define ft5 $f13
++#define ft6 $f14
++#define ft7 $f15
++#define ft8 $f16
++#define ft9 $f17
++#define ft10 $f18
++#define ft11 $f19
++#define ft12 $f20
++#define ft13 $f21
++#define ft14 $f22
++#define ft15 $f23
++#define fs0 $f24
++#define fs1 $f25
++#define fs2 $f26
++#define fs3 $f27
++#define fs4 $f28
++#define fs5 $f29
++#define fs6 $f30
++#define fs7 $f31
++
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++#endif /* _SYS_REGDEF_H */
+diff --git a/sysdeps/loongarch/tininess.h b/sysdeps/loongarch/tininess.h
+new file mode 100644
+index 00000000..90956c35
+--- /dev/null
++++ b/sysdeps/loongarch/tininess.h
+@@ -0,0 +1 @@
++#define TININESS_AFTER_ROUNDING 1
+diff --git a/sysdeps/loongarch/tls-macros.h b/sysdeps/loongarch/tls-macros.h
+new file mode 100644
+index 00000000..af5eb6b7
+--- /dev/null
++++ b/sysdeps/loongarch/tls-macros.h
+@@ -0,0 +1,49 @@
++/* Macros to support TLS testing in times of missing compiler support.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sys/cdefs.h>
++#include <sys/asm.h>
++#include <sysdep.h>
++#include "dl-tls.h"
++
++#define TLS_GD(x) \
++ ({ \
++ void *__result; \
++ asm("la.tls.gd %0, " #x "\n\t" : "=r"(__result)); \
++ __tls_get_addr (__result); \
++ })
++
++#define TLS_LD(x) TLS_GD (x)
++
++#define TLS_IE(x) \
++ ({ \
++ void *__result; \
++ asm("la.tls.ie %0, " #x "\n\t" \
++ "add.d %0, %0, $tp\n\t" \
++ : "=r"(__result)); \
++ __result; \
++ })
++
++#define TLS_LE(x) \
++ ({ \
++ void *__result; \
++ asm("la.tls.le %0, " #x "\n\t" \
++ "add.d %0, %0, $tp\n\t" \
++ : "=r"(__result)); \
++ __result; \
++ })
+diff --git a/sysdeps/loongarch/tst-audit.h b/sysdeps/loongarch/tst-audit.h
+new file mode 100644
+index 00000000..de120d8a
+--- /dev/null
++++ b/sysdeps/loongarch/tst-audit.h
+@@ -0,0 +1,23 @@
++/* Definitions for testing PLT entry/exit auditing.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define pltenter la_loongarch_gnu_pltenter
++#define pltexit la_loongarch_gnu_pltexit
++#define La_regs La_loongarch_regs
++#define La_retval La_loongarch_retval
++#define int_retval lrv_a0
+diff --git a/sysdeps/unix/sysv/linux/loongarch/Implies b/sysdeps/unix/sysv/linux/loongarch/Implies
+new file mode 100644
+index 00000000..e52b1ac3
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/Implies
+@@ -0,0 +1 @@
++loongarch/nptl
+diff --git a/sysdeps/unix/sysv/linux/loongarch/Makefile b/sysdeps/unix/sysv/linux/loongarch/Makefile
+new file mode 100644
+index 00000000..e205ce83
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/Makefile
+@@ -0,0 +1,10 @@
++ifeq ($(subdir),elf)
++ifeq ($(build-shared),yes)
++# This is needed for DSO loading from static binaries.
++sysdep-dl-routines += dl-static
++endif
++endif
++
++ifeq ($(subdir),stdlib)
++gen-as-const-headers += ucontext_i.sym
++endif
+diff --git a/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h b/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h
+new file mode 100644
+index 00000000..c1ff6cb6
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/arch-syscall.h
+@@ -0,0 +1,292 @@
++/* AUTOGENERATED by update-syscall-lists.py. */
++#define __NR_accept 202
++#define __NR_accept4 242
++#define __NR_acct 89
++#define __NR_add_key 217
++#define __NR_adjtimex 171
++#define __NR_bind 200
++#define __NR_bpf 280
++#define __NR_brk 214
++#define __NR_capget 90
++#define __NR_capset 91
++#define __NR_chdir 49
++#define __NR_chroot 51
++#define __NR_clock_adjtime 266
++#define __NR_clock_getres 114
++#define __NR_clock_gettime 113
++#define __NR_clock_nanosleep 115
++#define __NR_clock_settime 112
++#define __NR_clone 220
++#define __NR_clone3 435
++#define __NR_close 57
++#define __NR_close_range 436
++#define __NR_connect 203
++#define __NR_copy_file_range 285
++#define __NR_delete_module 106
++#define __NR_dup 23
++#define __NR_dup3 24
++#define __NR_epoll_create1 20
++#define __NR_epoll_ctl 21
++#define __NR_epoll_pwait 22
++#define __NR_eventfd2 19
++#define __NR_execve 221
++#define __NR_execveat 281
++#define __NR_exit 93
++#define __NR_exit_group 94
++#define __NR_faccessat 48
++#define __NR_faccessat2 439
++#define __NR_fadvise64 223
++#define __NR_fallocate 47
++#define __NR_fanotify_init 262
++#define __NR_fanotify_mark 263
++#define __NR_fchdir 50
++#define __NR_fchmod 52
++#define __NR_fchmodat 53
++#define __NR_fchown 55
++#define __NR_fchownat 54
++#define __NR_fcntl 25
++#define __NR_fdatasync 83
++#define __NR_fgetxattr 10
++#define __NR_finit_module 273
++#define __NR_flistxattr 13
++#define __NR_flock 32
++#define __NR_fremovexattr 16
++#define __NR_fsconfig 431
++#define __NR_fsetxattr 7
++#define __NR_fsmount 432
++#define __NR_fsopen 430
++#define __NR_fspick 433
++#define __NR_fstatfs 44
++#define __NR_fsync 82
++#define __NR_ftruncate 46
++#define __NR_futex 98
++#define __NR_get_mempolicy 236
++#define __NR_get_robust_list 100
++#define __NR_getcpu 168
++#define __NR_getcwd 17
++#define __NR_getdents64 61
++#define __NR_getegid 177
++#define __NR_geteuid 175
++#define __NR_getgid 176
++#define __NR_getgroups 158
++#define __NR_getitimer 102
++#define __NR_getpeername 205
++#define __NR_getpgid 155
++#define __NR_getpid 172
++#define __NR_getppid 173
++#define __NR_getpriority 141
++#define __NR_getrandom 278
++#define __NR_getresgid 150
++#define __NR_getresuid 148
++#define __NR_getrusage 165
++#define __NR_getsid 156
++#define __NR_getsockname 204
++#define __NR_getsockopt 209
++#define __NR_gettid 178
++#define __NR_gettimeofday 169
++#define __NR_getuid 174
++#define __NR_getxattr 8
++#define __NR_init_module 105
++#define __NR_inotify_add_watch 27
++#define __NR_inotify_init1 26
++#define __NR_inotify_rm_watch 28
++#define __NR_io_cancel 3
++#define __NR_io_destroy 1
++#define __NR_io_getevents 4
++#define __NR_io_pgetevents 292
++#define __NR_io_setup 0
++#define __NR_io_submit 2
++#define __NR_io_uring_enter 426
++#define __NR_io_uring_register 427
++#define __NR_io_uring_setup 425
++#define __NR_ioctl 29
++#define __NR_ioprio_get 31
++#define __NR_ioprio_set 30
++#define __NR_kcmp 272
++#define __NR_kexec_file_load 294
++#define __NR_kexec_load 104
++#define __NR_keyctl 219
++#define __NR_kill 129
++#define __NR_lgetxattr 9
++#define __NR_linkat 37
++#define __NR_listen 201
++#define __NR_listxattr 11
++#define __NR_llistxattr 12
++#define __NR_lookup_dcookie 18
++#define __NR_lremovexattr 15
++#define __NR_lseek 62
++#define __NR_lsetxattr 6
++#define __NR_madvise 233
++#define __NR_mbind 235
++#define __NR_membarrier 283
++#define __NR_memfd_create 279
++#define __NR_migrate_pages 238
++#define __NR_mincore 232
++#define __NR_mkdirat 34
++#define __NR_mknodat 33
++#define __NR_mlock 228
++#define __NR_mlock2 284
++#define __NR_mlockall 230
++#define __NR_mmap 222
++#define __NR_mount 40
++#define __NR_move_mount 429
++#define __NR_move_pages 239
++#define __NR_mprotect 226
++#define __NR_mq_getsetattr 185
++#define __NR_mq_notify 184
++#define __NR_mq_open 180
++#define __NR_mq_timedreceive 183
++#define __NR_mq_timedsend 182
++#define __NR_mq_unlink 181
++#define __NR_mremap 216
++#define __NR_msgctl 187
++#define __NR_msgget 186
++#define __NR_msgrcv 188
++#define __NR_msgsnd 189
++#define __NR_msync 227
++#define __NR_munlock 229
++#define __NR_munlockall 231
++#define __NR_munmap 215
++#define __NR_name_to_handle_at 264
++#define __NR_nanosleep 101
++#define __NR_nfsservctl 42
++#define __NR_open_by_handle_at 265
++#define __NR_open_tree 428
++#define __NR_openat 56
++#define __NR_openat2 437
++#define __NR_perf_event_open 241
++#define __NR_personality 92
++#define __NR_pidfd_getfd 438
++#define __NR_pidfd_open 434
++#define __NR_pidfd_send_signal 424
++#define __NR_pipe2 59
++#define __NR_pivot_root 41
++#define __NR_pkey_alloc 289
++#define __NR_pkey_free 290
++#define __NR_pkey_mprotect 288
++#define __NR_ppoll 73
++#define __NR_prctl 167
++#define __NR_pread64 67
++#define __NR_preadv 69
++#define __NR_preadv2 286
++#define __NR_prlimit64 261
++#define __NR_process_madvise 440
++#define __NR_process_vm_readv 270
++#define __NR_process_vm_writev 271
++#define __NR_pselect6 72
++#define __NR_ptrace 117
++#define __NR_pwrite64 68
++#define __NR_pwritev 70
++#define __NR_pwritev2 287
++#define __NR_quotactl 60
++#define __NR_read 63
++#define __NR_readahead 213
++#define __NR_readlinkat 78
++#define __NR_readv 65
++#define __NR_reboot 142
++#define __NR_recvfrom 207
++#define __NR_recvmmsg 243
++#define __NR_recvmsg 212
++#define __NR_remap_file_pages 234
++#define __NR_removexattr 14
++#define __NR_renameat2 276
++#define __NR_request_key 218
++#define __NR_restart_syscall 128
++#define __NR_rseq 293
++#define __NR_rt_sigaction 134
++#define __NR_rt_sigpending 136
++#define __NR_rt_sigprocmask 135
++#define __NR_rt_sigqueueinfo 138
++#define __NR_rt_sigreturn 139
++#define __NR_rt_sigsuspend 133
++#define __NR_rt_sigtimedwait 137
++#define __NR_rt_tgsigqueueinfo 240
++#define __NR_sched_get_priority_max 125
++#define __NR_sched_get_priority_min 126
++#define __NR_sched_getaffinity 123
++#define __NR_sched_getattr 275
++#define __NR_sched_getparam 121
++#define __NR_sched_getscheduler 120
++#define __NR_sched_rr_get_interval 127
++#define __NR_sched_setaffinity 122
++#define __NR_sched_setattr 274
++#define __NR_sched_setparam 118
++#define __NR_sched_setscheduler 119
++#define __NR_sched_yield 124
++#define __NR_seccomp 277
++#define __NR_semctl 191
++#define __NR_semget 190
++#define __NR_semop 193
++#define __NR_semtimedop 192
++#define __NR_sendfile 71
++#define __NR_sendmmsg 269
++#define __NR_sendmsg 211
++#define __NR_sendto 206
++#define __NR_set_mempolicy 237
++#define __NR_set_robust_list 99
++#define __NR_set_tid_address 96
++#define __NR_setdomainname 162
++#define __NR_setfsgid 152
++#define __NR_setfsuid 151
++#define __NR_setgid 144
++#define __NR_setgroups 159
++#define __NR_sethostname 161
++#define __NR_setitimer 103
++#define __NR_setns 268
++#define __NR_setpgid 154
++#define __NR_setpriority 140
++#define __NR_setregid 143
++#define __NR_setresgid 149
++#define __NR_setresuid 147
++#define __NR_setreuid 145
++#define __NR_setsid 157
++#define __NR_setsockopt 208
++#define __NR_settimeofday 170
++#define __NR_setuid 146
++#define __NR_setxattr 5
++#define __NR_shmat 196
++#define __NR_shmctl 195
++#define __NR_shmdt 197
++#define __NR_shmget 194
++#define __NR_shutdown 210
++#define __NR_sigaltstack 132
++#define __NR_signalfd4 74
++#define __NR_socket 198
++#define __NR_socketpair 199
++#define __NR_splice 76
++#define __NR_statfs 43
++#define __NR_statx 291
++#define __NR_swapoff 225
++#define __NR_swapon 224
++#define __NR_symlinkat 36
++#define __NR_sync 81
++#define __NR_sync_file_range 84
++#define __NR_syncfs 267
++#define __NR_sysinfo 179
++#define __NR_syslog 116
++#define __NR_tee 77
++#define __NR_tgkill 131
++#define __NR_timer_create 107
++#define __NR_timer_delete 111
++#define __NR_timer_getoverrun 109
++#define __NR_timer_gettime 108
++#define __NR_timer_settime 110
++#define __NR_timerfd_create 85
++#define __NR_timerfd_gettime 87
++#define __NR_timerfd_settime 86
++#define __NR_times 153
++#define __NR_tkill 130
++#define __NR_truncate 45
++#define __NR_umask 166
++#define __NR_umount2 39
++#define __NR_uname 160
++#define __NR_unlinkat 35
++#define __NR_unshare 97
++#define __NR_userfaultfd 282
++#define __NR_utimensat 88
++#define __NR_vhangup 58
++#define __NR_vmsplice 75
++#define __NR_wait4 260
++#define __NR_waitid 95
++#define __NR_write 64
++#define __NR_writev 66
+diff --git a/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h
+new file mode 100644
+index 00000000..dbae608e
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/atomic-machine.h
+@@ -0,0 +1,196 @@
++/* Atomic operations.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LINUX_LOONGARCH_BITS_ATOMIC_H
++#define _LINUX_LOONGARCH_BITS_ATOMIC_H 1
++
++#include <stdint.h>
++
++typedef int32_t atomic32_t;
++typedef uint32_t uatomic32_t;
++
++typedef int64_t atomic64_t;
++typedef uint64_t uatomic64_t;
++
++typedef intptr_t atomicptr_t;
++typedef uintptr_t uatomicptr_t;
++typedef intmax_t atomic_max_t;
++typedef uintmax_t uatomic_max_t;
++
++#define atomic_full_barrier() __sync_synchronize ()
++
++#ifdef __LP64__
++#define __HAVE_64B_ATOMICS 1
++#endif
++#define USE_ATOMIC_COMPILER_BUILTINS 1
++#define ATOMIC_EXCHANGE_USES_CAS 0
++
++/* Compare and exchange.
++ For all "bool" routines, we return FALSE if exchange succesful. */
++
++#define __arch_compare_and_exchange_bool_8_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ })
++
++#define __arch_compare_and_exchange_bool_16_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ })
++
++#define __arch_compare_and_exchange_bool_32_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ })
++
++#define __arch_compare_and_exchange_bool_64_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ !__atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ })
++
++#define __arch_compare_and_exchange_val_8_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ __oldval; \
++ })
++
++#define __arch_compare_and_exchange_val_16_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ __oldval; \
++ })
++
++#define __arch_compare_and_exchange_val_32_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ __oldval; \
++ })
++
++#define __arch_compare_and_exchange_val_64_int(mem, newval, oldval, model) \
++ ({ \
++ typeof (*mem) __oldval = (oldval); \
++ __atomic_compare_exchange_n (mem, (void *) &__oldval, newval, 0, model, \
++ __ATOMIC_RELAXED); \
++ __oldval; \
++ })
++
++/* Atomic compare and exchange. */
++
++#define atomic_compare_and_exchange_bool_acq(mem, new, old) \
++ __atomic_bool_bysize (__arch_compare_and_exchange_bool, int, mem, new, old, \
++ __ATOMIC_ACQUIRE)
++
++#define atomic_compare_and_exchange_val_acq(mem, new, old) \
++ __atomic_val_bysize (__arch_compare_and_exchange_val, int, mem, new, old, \
++ __ATOMIC_ACQUIRE)
++
++#define atomic_compare_and_exchange_val_rel(mem, new, old) \
++ __atomic_val_bysize (__arch_compare_and_exchange_val, int, mem, new, old, \
++ __ATOMIC_RELEASE)
++
++/* Atomic exchange (without compare). */
++
++#define __arch_exchange_8_int(mem, newval, model) \
++ __atomic_exchange_n (mem, newval, model)
++
++#define __arch_exchange_16_int(mem, newval, model) \
++ __atomic_exchange_n (mem, newval, model)
++
++#define __arch_exchange_32_int(mem, newval, model) \
++ __atomic_exchange_n (mem, newval, model)
++
++#define __arch_exchange_64_int(mem, newval, model) \
++ __atomic_exchange_n (mem, newval, model)
++
++#define atomic_exchange_acq(mem, value) \
++ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_ACQUIRE)
++
++#define atomic_exchange_rel(mem, value) \
++ __atomic_val_bysize (__arch_exchange, int, mem, value, __ATOMIC_RELEASE)
++
++/* Atomically add value and return the previous (unincremented) value. */
++
++#define __arch_exchange_and_add_8_int(mem, value, model) \
++ __atomic_fetch_add (mem, value, model)
++
++#define __arch_exchange_and_add_16_int(mem, value, model) \
++ __atomic_fetch_add (mem, value, model)
++
++#define __arch_exchange_and_add_32_int(mem, value, model) \
++ __atomic_fetch_add (mem, value, model)
++
++#define __arch_exchange_and_add_64_int(mem, value, model) \
++ __atomic_fetch_add (mem, value, model)
++
++#define atomic_exchange_and_add_acq(mem, value) \
++ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
++ __ATOMIC_ACQUIRE)
++
++#define atomic_exchange_and_add_rel(mem, value) \
++ __atomic_val_bysize (__arch_exchange_and_add, int, mem, value, \
++ __ATOMIC_RELEASE)
++
++/* Miscellaneous. */
++
++#define asm_amo(which, mem, value) \
++ ({ \
++ __atomic_check_size (mem); \
++ typeof (*mem) __tmp; \
++ if (sizeof (__tmp) == 4) \
++ asm volatile(which ".w" \
++ "\t%0, %z2, %1" \
++ : "=&r"(__tmp), "+ZB"(*(mem)) \
++ : "rJ"(value)); \
++ else if (sizeof (__tmp) == 8) \
++ asm volatile(which ".d" \
++ "\t%0, %z2, %1" \
++ : "=&r"(__tmp), "+ZB"(*(mem)) \
++ : "rJ"(value)); \
++ else \
++ abort (); \
++ __tmp; \
++ })
++
++#define atomic_max(mem, value) asm_amo ("ammax_db", mem, value)
++#define atomic_min(mem, value) asm_amo ("ammin_db", mem, value)
++
++#define atomic_bit_test_set(mem, bit) \
++ ({ \
++ typeof (*mem) __mask = (typeof (*mem)) 1 << (bit); \
++ asm_amo ("amor_db", mem, __mask) & __mask; \
++ })
++
++#define catomic_exchange_and_add(mem, value) \
++ atomic_exchange_and_add (mem, value)
++#define catomic_max(mem, value) atomic_max (mem, value)
++
++#endif /* bits/atomic.h */
+diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h b/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h
+new file mode 100644
+index 00000000..a39985e1
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/bits/fcntl.h
+@@ -0,0 +1,61 @@
++/* O_*, F_*, FD_* bit values for the generic Linux/LoongArch ABI.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _FCNTL_H
++#error "Never use <bits/fcntl.h> directly; include <fcntl.h> instead."
++#endif
++
++#include <bits/wordsize.h>
++
++/* In 64-bit ISA files are always with 64bit off_t and F_*LK64 are the same as
++ non-64-bit versions. It will need to be revised for 128-bit. */
++#if __WORDSIZE == 64
++#define __O_LARGEFILE 0
++
++#define F_GETLK64 5 /* Get record locking info. */
++#define F_SETLK64 6 /* Set record locking info (non-blocking). */
++#define F_SETLKW64 7 /* Set record locking info (blocking). */
++#endif
++
++struct flock
++{
++ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
++ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
++#ifndef __USE_FILE_OFFSET64
++ __off_t l_start; /* Offset where the lock begins. */
++ __off_t l_len; /* Size of the locked area; zero means until EOF. */
++#else
++ __off64_t l_start; /* Offset where the lock begins. */
++ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
++#endif
++ __pid_t l_pid; /* Process holding the lock. */
++};
++
++#ifdef __USE_LARGEFILE64
++struct flock64
++{
++ short int l_type; /* Type of lock: F_RDLCK, F_WRLCK, or F_UNLCK. */
++ short int l_whence; /* Where `l_start' is relative to (like `lseek'). */
++ __off64_t l_start; /* Offset where the lock begins. */
++ __off64_t l_len; /* Size of the locked area; zero means until EOF. */
++ __pid_t l_pid; /* Process holding the lock. */
++};
++#endif
++
++/* Include generic Linux declarations. */
++#include <bits/fcntl-linux.h>
+diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/mman.h b/sysdeps/unix/sysv/linux/loongarch/bits/mman.h
+new file mode 100644
+index 00000000..1f2f76fc
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/bits/mman.h
+@@ -0,0 +1,42 @@
++/* Definitions for POSIX memory map interface.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_MMAN_H
++#error "Never use <bits/mman.h> directly; include <sys/mman.h> instead."
++#endif
++
++#ifdef __USE_MISC
++#define MAP_GROWSDOWN 0x00100 /* Stack-like segment. */
++#define MAP_DENYWRITE 0x00800 /* ETXTBSY. */
++#define MAP_EXECUTABLE 0x01000 /* Mark it as an executable. */
++#define MAP_LOCKED 0x02000 /* Lock the mapping. */
++#define MAP_NORESERVE 0x04000 /* Don't check for reservations. */
++#define MAP_POPULATE 0x08000 /* Populate (prefault) pagetables. */
++#define MAP_NONBLOCK 0x10000 /* Do not block on IO. */
++#define MAP_STACK 0x20000 /* Allocation is for a stack. */
++#define MAP_HUGETLB 0x40000 /* Create huge page mapping. */
++#define MAP_SYNC \
++ 0x80000 /* Perform synchronous page \
++ faults for the mapping. */
++#define MAP_FIXED_NOREPLACE \
++ 0x100000 /* MAP_FIXED but do not unmap \
++ underlying mapping. */
++#endif
++
++/* Include generic Linux declarations. */
++#include <bits/mman-linux.h>
+diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/procfs.h b/sysdeps/unix/sysv/linux/loongarch/bits/procfs.h
+new file mode 100644
+index 00000000..2db777b3
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/bits/procfs.h
+@@ -0,0 +1,52 @@
++/* Types for registers for sys/procfs.h.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_PROCFS_H
++# error "Never include <bits/procfs.h> directly; use <sys/procfs.h> instead."
++#endif
++
++/* Type for a general-purpose register. */
++typedef __uint64_t elf_greg_t;
++
++/* And the whole bunch of them. We could have used `struct
++ pt_regs' directly in the typedef, but tradition says that
++ the register set is an array, which does have some peculiar
++ semantics, so leave it that way. */
++#define ELF_NGREG (sizeof (struct user_regs_struct) / sizeof (elf_greg_t))
++typedef elf_greg_t elf_gregset_t[ELF_NGREG];
++
++#define ELF_NFPREG 34 /* 32 FPRs + 8-byte byte-vec for fcc + 4-byte FCR */
++typedef union
++{
++ double d;
++ float f;
++} elf_fpreg_t;
++typedef elf_fpreg_t elf_fpregset_t[ELF_NFPREG];
++
++typedef union
++{
++ double d[2];
++ float f[4];
++} __attribute__ ((__aligned__ (16))) elf_lsxregset_t[32];
++
++typedef union
++{
++ double d[4];
++ float f[8];
++} __attribute__ ((__aligned__ (32))) elf_lasxregset_t[32];
+diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h b/sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h
+new file mode 100644
+index 00000000..ccab36ca
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/bits/pthread_stack_min.h
+@@ -0,0 +1,20 @@
++/* Definition of PTHREAD_STACK_MIN. LoongArch Linux version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public License as
++ published by the Free Software Foundation; either version 2.1 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Minimum size for a thread. At least two pages with 64k pages. */
++#define PTHREAD_STACK_MIN 131072
+diff --git a/sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h b/sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h
+new file mode 100644
+index 00000000..d59632de
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/bits/sigstack.h
+@@ -0,0 +1,32 @@
++/* sigstack, sigaltstack definitions.
++ Copyright (C) 1998-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _BITS_SIGSTACK_H
++#define _BITS_SIGSTACK_H 1
++
++#if !defined _SIGNAL_H && !defined _SYS_UCONTEXT_H
++# error "Never include this file directly. Use <signal.h> instead"
++#endif
++
++/* Minimum stack size for a signal handler. */
++#define MINSIGSTKSZ 4096
++
++/* System default stack size. */
++#define SIGSTKSZ 16384
++
++#endif /* bits/sigstack.h */
+diff --git a/sysdeps/unix/sysv/linux/loongarch/clone.S b/sysdeps/unix/sysv/linux/loongarch/clone.S
+new file mode 100644
+index 00000000..d2bed244
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/clone.S
+@@ -0,0 +1,100 @@
++/* The clone syscall wrapper.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* clone() is even more special than fork() as it mucks with stacks
++ and invokes a function in the right context after its all over. */
++
++#include <sys/asm.h>
++#include <sysdep.h>
++#define _ERRNO_H 1
++#include <bits/errno.h>
++#include <tls.h>
++#include "tcb-offsets.h"
++
++/* int clone(int (*fn)(void *arg), void *child_stack, int flags, void *arg,
++ void *parent_tidptr, void *tls, void *child_tidptr) */
++
++ENTRY (__clone)
++
++ /* Align stack to 16 or 8 bytes per the ABI. */
++#ifdef __loongarch_lp64
++ bstrins.d a1, zero, 3, 0
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++ /* Sanity check arguments. */
++ beqz a0, L (invalid) /* No NULL function pointers. */
++ beqz a1, L (invalid) /* No NULL stack pointers. */
++
++ addi.d a1, a1, -16 /* Reserve argument save space. */
++ st.d a0, a1, 0 /* Save function pointer. */
++ st.d a3, a1, SZREG /* Save argument pointer. */
++
++ /* The syscall expects the args to be in different slots. */
++ or a0, a2, zero
++ or a2, a4, zero
++ or a3, a6, zero
++ or a4, a5, zero
++
++ /* Do the system call. */
++ li.d a7,__NR_clone
++ syscall 0
++
++ blt a0, zero ,L (error)
++ beqz a0,L (thread_start)
++
++ /* Successful return from the parent. */
++ ret
++
++L (invalid):
++ li.d a0, -EINVAL
++
++ /* Something bad happened -- no child created. */
++L (error):
++ b __syscall_error
++
++END (__clone)
++
++/* Load up the arguments to the function. Put this block of code in
++ its own function so that we can terminate the stack trace with our
++ debug info. */
++ENTRY (__thread_start)
++L (thread_start):
++
++/* Terminate call stack by noting ra is undefined. Use a dummy
++ .cfi_label to force starting the FDE. */
++ .cfi_label .Ldummy
++ cfi_undefined (1)
++
++ /* Restore the arg for user's function. */
++ ld.d a1, sp, 0 /* Function pointer. */
++ ld.d a0, sp, SZREG /* Argument pointer. */
++
++ /* Call the user's function. */
++ jirl ra, a1, 0
++
++ /* Call exit with the function's return value. */
++ li.d a7, __NR_exit
++ syscall 0
++
++ END (__thread_start)
++
++libc_hidden_def (__clone)
++weak_alias (__clone, clone)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/clone3.S b/sysdeps/unix/sysv/linux/loongarch/clone3.S
+new file mode 100644
+index 00000000..5eaaa546
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/clone3.S
+@@ -0,0 +1,87 @@
++/* The clone3 syscall wrapper.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* clone3() is even more special than fork() as it mucks with stacks
++ and invokes a function in the right context after its all over. */
++
++#include <sys/asm.h>
++#include <sysdep.h>
++#define _ERRNO_H 1
++#include <bits/errno.h>
++#include <tls.h>
++#include "tcb-offsets.h"
++
++/* int clone3(struct clone_args *cl_args, size_t size,
++ int (*func)(void *arg), void *arg); */
++
++ENTRY (__clone3)
++
++ /* Sanity check arguments. */
++ beqz a0, L (invalid) /* No NULL cl_args pointer. */
++ beqz a2, L (invalid) /* No NULL function pointer. */
++
++ /* Do the system call. */
++ li.d a7, __NR_clone3
++ syscall 0
++
++ blt a0, zero ,L (error)
++ beqz a0, L (thread_start3)
++
++ /* Successful return from the parent. */
++ ret
++
++L (invalid):
++ li.d a0, -EINVAL
++
++ /* Something bad happened -- no child created. */
++L (error):
++ b __syscall_error
++
++END (__clone3)
++
++/* Load up the arguments to the function. Put this block of code in
++ its own function so that we can terminate the stack trace with our
++ debug info. */
++ENTRY (__thread_start3)
++L (thread_start3):
++
++/* Terminate call stack by noting ra is undefined. Use a dummy
++ .cfi_label to force starting the FDE. */
++ .cfi_label .Ldummy
++ cfi_undefined (1)
++
++ /* Align stack to 16 or 8 bytes per the ABI. */
++#ifdef __loongarch_lp64
++ bstrins.d sp, zero, 3, 0
++#else
++#error "32bit LoongArch systems are not supported"
++#endif
++
++ /* Set up arguments for the function call. */
++ move a0, a3 /* Argument. */
++ jirl ra, a2, 0 /* Call function. */
++
++ /* Call exit with the function's return value. */
++ li.d a7, __NR_exit
++ syscall 0
++
++ END (__thread_start3)
++
++libc_hidden_def (__clone3)
++weak_alias (__clone3, clone3)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/configure b/sysdeps/unix/sysv/linux/loongarch/configure
+new file mode 100644
+index 00000000..23b44a8c
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/configure
+@@ -0,0 +1,199 @@
++# This file is generated from configure.ac by Autoconf. DO NOT EDIT!
++ # Local configure fragment for sysdeps/unix/sysv/linux/loongarch.
++
++arch_minimum_kernel=5.10.0
++
++libc_cv_loongarch_int_abi=no
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for grep that handles long lines and -e" >&5
++$as_echo_n "checking for grep that handles long lines and -e... " >&6; }
++if ${ac_cv_path_GREP+:} false; then :
++ $as_echo_n "(cached) " >&6
++else
++ if test -z "$GREP"; then
++ ac_path_GREP_found=false
++ # Loop through the user's path and test for each of PROGNAME-LIST
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ for ac_prog in grep ggrep; do
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ ac_path_GREP="$as_dir/$ac_prog$ac_exec_ext"
++ as_fn_executable_p "$ac_path_GREP" || continue
++# Check for GNU ac_path_GREP and select it if it is found.
++ # Check for GNU $ac_path_GREP
++case `"$ac_path_GREP" --version 2>&1` in
++*GNU*)
++ ac_cv_path_GREP="$ac_path_GREP" ac_path_GREP_found=:;;
++*)
++ ac_count=0
++ $as_echo_n 0123456789 >"conftest.in"
++ while :
++ do
++ cat "conftest.in" "conftest.in" >"conftest.tmp"
++ mv "conftest.tmp" "conftest.in"
++ cp "conftest.in" "conftest.nl"
++ $as_echo 'GREP' >> "conftest.nl"
++ "$ac_path_GREP" -e 'GREP$' -e '-(cannot match)-' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++ as_fn_arith $ac_count + 1 && ac_count=$as_val
++ if test $ac_count -gt ${ac_path_GREP_max-0}; then
++ # Best one so far, save it but keep looking for a better one
++ ac_cv_path_GREP="$ac_path_GREP"
++ ac_path_GREP_max=$ac_count
++ fi
++ # 10*(2^10) chars as input seems more than enough
++ test $ac_count -gt 10 && break
++ done
++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++ $ac_path_GREP_found && break 3
++ done
++ done
++ done
++IFS=$as_save_IFS
++ if test -z "$ac_cv_path_GREP"; then
++ as_fn_error $? "no acceptable grep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++ fi
++else
++ ac_cv_path_GREP=$GREP
++fi
++
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_GREP" >&5
++$as_echo "$ac_cv_path_GREP" >&6; }
++ GREP="$ac_cv_path_GREP"
++
++
++{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for egrep" >&5
++$as_echo_n "checking for egrep... " >&6; }
++if ${ac_cv_path_EGREP+:} false; then :
++ $as_echo_n "(cached) " >&6
++else
++ if echo a | $GREP -E '(a|b)' >/dev/null 2>&1
++ then ac_cv_path_EGREP="$GREP -E"
++ else
++ if test -z "$EGREP"; then
++ ac_path_EGREP_found=false
++ # Loop through the user's path and test for each of PROGNAME-LIST
++ as_save_IFS=$IFS; IFS=$PATH_SEPARATOR
++for as_dir in $PATH$PATH_SEPARATOR/usr/xpg4/bin
++do
++ IFS=$as_save_IFS
++ test -z "$as_dir" && as_dir=.
++ for ac_prog in egrep; do
++ for ac_exec_ext in '' $ac_executable_extensions; do
++ ac_path_EGREP="$as_dir/$ac_prog$ac_exec_ext"
++ as_fn_executable_p "$ac_path_EGREP" || continue
++# Check for GNU ac_path_EGREP and select it if it is found.
++ # Check for GNU $ac_path_EGREP
++case `"$ac_path_EGREP" --version 2>&1` in
++*GNU*)
++ ac_cv_path_EGREP="$ac_path_EGREP" ac_path_EGREP_found=:;;
++*)
++ ac_count=0
++ $as_echo_n 0123456789 >"conftest.in"
++ while :
++ do
++ cat "conftest.in" "conftest.in" >"conftest.tmp"
++ mv "conftest.tmp" "conftest.in"
++ cp "conftest.in" "conftest.nl"
++ $as_echo 'EGREP' >> "conftest.nl"
++ "$ac_path_EGREP" 'EGREP$' < "conftest.nl" >"conftest.out" 2>/dev/null || break
++ diff "conftest.out" "conftest.nl" >/dev/null 2>&1 || break
++ as_fn_arith $ac_count + 1 && ac_count=$as_val
++ if test $ac_count -gt ${ac_path_EGREP_max-0}; then
++ # Best one so far, save it but keep looking for a better one
++ ac_cv_path_EGREP="$ac_path_EGREP"
++ ac_path_EGREP_max=$ac_count
++ fi
++ # 10*(2^10) chars as input seems more than enough
++ test $ac_count -gt 10 && break
++ done
++ rm -f conftest.in conftest.tmp conftest.nl conftest.out;;
++esac
++
++ $ac_path_EGREP_found && break 3
++ done
++ done
++ done
++IFS=$as_save_IFS
++ if test -z "$ac_cv_path_EGREP"; then
++ as_fn_error $? "no acceptable egrep could be found in $PATH$PATH_SEPARATOR/usr/xpg4/bin" "$LINENO" 5
++ fi
++else
++ ac_cv_path_EGREP=$EGREP
++fi
++
++ fi
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_path_EGREP" >&5
++$as_echo "$ac_cv_path_EGREP" >&6; }
++ EGREP="$ac_cv_path_EGREP"
++
++
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "4 4 4" >/dev/null 2>&1; then :
++ libc_cv_loongarch_int_abi=lp32
++fi
++rm -f conftest*
++
++cat confdefs.h - <<_ACEOF >conftest.$ac_ext
++/* end confdefs.h. */
++__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
++
++_ACEOF
++if (eval "$ac_cpp conftest.$ac_ext") 2>&5 |
++ $EGREP "4 8 8" >/dev/null 2>&1; then :
++ libc_cv_loongarch_int_abi=lp64
++fi
++rm -f conftest*
++
++if test $libc_cv_loongarch_int_abi = no; then
++ as_fn_error $? "Unable to determine integer ABI" "$LINENO" 5
++fi
++
++config_vars="$config_vars
++default-abi = $libc_cv_loongarch_int_abi"
++
++case $libc_cv_loongarch_int_abi in
++lp32)
++ test -n "$libc_cv_slibdir" ||
++case "$prefix" in
++/usr | /usr/)
++ libc_cv_slibdir='/lib32'
++ libc_cv_rtlddir='/lib32'
++ if test "$libdir" = '${exec_prefix}/lib'; then
++ libdir='${exec_prefix}/lib32';
++ # Locale data can be shared between 32-bit and 64-bit libraries.
++ libc_cv_complocaledir='${exec_prefix}/lib/locale'
++ fi
++ ;;
++esac
++ ;;
++lp64)
++ test -n "$libc_cv_slibdir" ||
++case "$prefix" in
++/usr | /usr/)
++ libc_cv_slibdir='/lib64'
++ libc_cv_rtlddir='/lib64'
++ if test "$libdir" = '${exec_prefix}/lib'; then
++ libdir='${exec_prefix}/lib64';
++ # Locale data can be shared between 32-bit and 64-bit libraries.
++ libc_cv_complocaledir='${exec_prefix}/lib/locale'
++ fi
++ ;;
++esac
++ ;;
++esac
++
++ldd_rewrite_script=sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
+diff --git a/sysdeps/unix/sysv/linux/loongarch/configure.ac b/sysdeps/unix/sysv/linux/loongarch/configure.ac
+new file mode 100644
+index 00000000..55ccb504
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/configure.ac
+@@ -0,0 +1,27 @@
++sinclude(./aclocal.m4)dnl Autoconf lossage
++GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
++# Local configure fragment for sysdeps/unix/sysv/linux/loongarch.
++
++arch_minimum_kernel=5.10.0
++
++libc_cv_loongarch_int_abi=no
++AC_EGREP_CPP(4 4 4, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
++ ], libc_cv_loongarch_int_abi=ilp32)
++AC_EGREP_CPP(4 8 8, [__SIZEOF_INT__ __SIZEOF_LONG__ __SIZEOF_POINTER__
++ ], libc_cv_loongarch_int_abi=lp64)
++if test $libc_cv_loongarch_int_abi = no; then
++ AC_MSG_ERROR([Unable to determine integer ABI])
++fi
++
++LIBC_CONFIG_VAR([default-abi], [$libc_cv_loongarch_int_abi])
++
++case $libc_cv_loongarch_int_abi in
++ilp32)
++ LIBC_SLIBDIR_RTLDDIR([lib32], [lib32])
++ ;;
++lp64)
++ LIBC_SLIBDIR_RTLDDIR([lib64], [lib64])
++ ;;
++esac
++
++ldd_rewrite_script=sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
+diff --git a/sysdeps/unix/sysv/linux/loongarch/dl-static.c b/sysdeps/unix/sysv/linux/loongarch/dl-static.c
+new file mode 100644
+index 00000000..b9a7b2a6
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/dl-static.c
+@@ -0,0 +1,80 @@
++/* dl_static_init for loongarch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <ldsodefs.h>
++
++#ifdef SHARED
++
++void
++_dl_var_init (void *array[])
++{
++ /* It has to match "variables" below. */
++ enum
++ {
++ DL_PAGESIZE = 0
++ };
++
++ GLRO (dl_pagesize) = *((size_t *) array[DL_PAGESIZE]);
++}
++
++#else
++
++static void *variables[] = {&GLRO (dl_pagesize)};
++
++static void _dl_unprotect_relro (struct link_map *l)
++{
++ ElfW (Addr) start = ((l->l_addr + l->l_relro_addr)
++ & ~(GLRO (dl_pagesize) - 1));
++ ElfW (Addr) end = ((l->l_addr + l->l_relro_addr + l->l_relro_size)
++ & ~(GLRO (dl_pagesize) - 1));
++
++ if (start != end)
++ __mprotect ((void *) start, end - start, PROT_READ | PROT_WRITE);
++}
++
++void dl_static_init (struct link_map *l)
++{
++ struct link_map *rtld_map = l;
++ struct r_scope_elem **scope;
++ const ElfW (Sym) *ref = NULL;
++ lookup_t loadbase;
++ void (*f) (void *[]);
++ size_t i;
++
++ loadbase = _dl_lookup_symbol_x ("_dl_var_init", l, &ref, l->l_local_scope,
++ NULL, 0, 1, NULL);
++
++ for (scope = l->l_local_scope; *scope != NULL; scope++)
++ for (i = 0; i < (*scope)->r_nlist; i++)
++ if ((*scope)->r_list[i] == loadbase)
++ {
++ rtld_map = (*scope)->r_list[i];
++ break;
++ }
++
++ if (ref != NULL)
++ {
++ f = (void (*) (void *[])) DL_SYMBOL_ADDRESS (loadbase, ref);
++ _dl_unprotect_relro (rtld_map);
++ f (variables);
++ _dl_protect_relro (rtld_map);
++ }
++}
++
++#endif
+diff --git a/sysdeps/unix/sysv/linux/loongarch/getcontext.S b/sysdeps/unix/sysv/linux/loongarch/getcontext.S
+new file mode 100644
+index 00000000..43b95e97
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/getcontext.S
+@@ -0,0 +1,59 @@
++/* Save current context.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include "ucontext-macros.h"
++
++/* int getcontext (ucontext_t *ucp) */
++
++ .text
++LEAF (__getcontext)
++ SAVE_INT_REG (ra, 1, a0)
++ SAVE_INT_REG (sp, 3, a0)
++ SAVE_INT_REG (zero, 4, a0) /* return 0 by overwriting a0. */
++ SAVE_INT_REG (x, 21, a0)
++ SAVE_INT_REG (fp, 22, a0)
++ SAVE_INT_REG (s0, 23, a0)
++ SAVE_INT_REG (s1, 24, a0)
++ SAVE_INT_REG (s2, 25, a0)
++ SAVE_INT_REG (s3, 26, a0)
++ SAVE_INT_REG (s4, 27, a0)
++ SAVE_INT_REG (s5, 28, a0)
++ SAVE_INT_REG (s6, 29, a0)
++ SAVE_INT_REG (s7, 30, a0)
++ SAVE_INT_REG (s8, 31, a0)
++ st.d ra, a0, MCONTEXT_PC
++
++/* rt_sigprocmask (SIG_BLOCK, NULL, &ucp->uc_sigmask, _NSIG8) */
++ li.d a3, _NSIG8
++ li.d a2, UCONTEXT_SIGMASK
++ add.d a2, a2, a0
++ ori a1, zero,0
++ li.d a0, SIG_BLOCK
++
++ li.d a7, SYS_ify (rt_sigprocmask)
++ syscall 0
++ blt a0, zero, 99f
++
++ jirl $r0, $r1, 0
++
++99:
++ b __syscall_error
++
++PSEUDO_END (__getcontext)
++
++weak_alias (__getcontext, getcontext)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/ldconfig.h b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
+new file mode 100644
+index 00000000..126f0860
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/ldconfig.h
+@@ -0,0 +1,30 @@
++/* ldconfig default paths and libraries.
++ Copyright (C) 2001-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <sysdeps/generic/ldconfig.h>
++
++#ifdef __loongarch_lp64
++#define SYSDEP_KNOWN_INTERPRETER_NAMES \
++ { "/lib64/ld-linux-loongarch-lp64d.so.1", FLAG_ELF_LIBC6 },
++#else
++#error cannot determine ABI
++#endif
++
++#define SYSDEP_KNOWN_LIBRARY_NAMES \
++ { "libc.so.6", FLAG_ELF_LIBC6 }, \
++ { "libm.so.6", FLAG_ELF_LIBC6 },
+diff --git a/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed b/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
+new file mode 100644
+index 00000000..d42a13e0
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/ldd-rewrite.sed
+@@ -0,0 +1,3 @@
++/LD_TRACE_LOADED_OBJECTS=1/a\
++add_env="$add_env LD_LIBRARY_VERSION=\\$verify_out"
++s_^\(RTLDLIST=\)\(.*lib\)\(\|64\|32\)\(/[^/]*\)\(-loongarch\)\(64\|32\)\(\.so\.[0-9.]*\)[[:blank:]]*$_\1"\2\4\7 \264\4-loongarch64\7 \232\4-loongarch32\7"_
+diff --git a/sysdeps/unix/sysv/linux/loongarch/ldsodefs.h b/sysdeps/unix/sysv/linux/loongarch/ldsodefs.h
+new file mode 100644
+index 00000000..680baf2e
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/ldsodefs.h
+@@ -0,0 +1,33 @@
++/* Run-time dynamic linker data structures for loaded ELF shared objects.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LDSODEFS_H
++
++/* Get the real definitions. */
++#include_next <ldsodefs.h>
++
++/* Now define our stuff. */
++
++/* We need special support to initialize DSO loaded for statically linked
++ binaries. */
++extern void _dl_static_init (struct link_map *map);
++#undef DL_STATIC_INIT
++#define DL_STATIC_INIT(map) _dl_static_init (map)
++
++#endif /* ldsodefs.h */
+diff --git a/sysdeps/unix/sysv/linux/loongarch/localplt.data b/sysdeps/unix/sysv/linux/loongarch/localplt.data
+new file mode 100644
+index 00000000..817ab265
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/localplt.data
+@@ -0,0 +1,12 @@
++# See scripts/check-localplt.awk for how this file is processed.
++# PLT use is required for the malloc family and for matherr because
++# users can define their own functions and have library internals call them.
++libc.so: calloc
++libc.so: free
++libc.so: malloc
++libc.so: realloc
++# The TLS-enabled version of these functions is interposed from libc.so.
++ld.so: _dl_signal_error
++ld.so: _dl_catch_error
++ld.so: _dl_signal_exception
++ld.so: _dl_catch_exception
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/Implies b/sysdeps/unix/sysv/linux/loongarch/lp64/Implies
+new file mode 100644
+index 00000000..117c2b8e
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/Implies
+@@ -0,0 +1,3 @@
++unix/sysv/linux/loongarch
++unix/sysv/linux/generic
++unix/sysv/linux/wordsize-64
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data b/sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data
+new file mode 100644
+index 00000000..ac925ccb
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/c++-types.data
+@@ -0,0 +1,67 @@
++blkcnt64_t:l
++blkcnt_t:l
++blksize_t:i
++caddr_t:Pc
++clockid_t:i
++clock_t:l
++daddr_t:i
++dev_t:m
++fd_mask:l
++fsblkcnt64_t:m
++fsblkcnt_t:m
++fsfilcnt64_t:m
++fsfilcnt_t:m
++fsid_t:8__fsid_t
++gid_t:j
++id_t:j
++ino64_t:m
++ino_t:m
++int16_t:s
++int32_t:i
++int64_t:l
++int8_t:a
++intptr_t:l
++key_t:i
++loff_t:l
++mode_t:j
++nlink_t:j
++off64_t:l
++off_t:l
++pid_t:i
++pthread_attr_t:14pthread_attr_t
++pthread_barrier_t:17pthread_barrier_t
++pthread_barrierattr_t:21pthread_barrierattr_t
++pthread_cond_t:14pthread_cond_t
++pthread_condattr_t:18pthread_condattr_t
++pthread_key_t:j
++pthread_mutex_t:15pthread_mutex_t
++pthread_mutexattr_t:19pthread_mutexattr_t
++pthread_once_t:i
++pthread_rwlock_t:16pthread_rwlock_t
++pthread_rwlockattr_t:20pthread_rwlockattr_t
++pthread_spinlock_t:i
++pthread_t:m
++quad_t:l
++register_t:l
++rlim64_t:m
++rlim_t:m
++sigset_t:10__sigset_t
++size_t:m
++socklen_t:j
++ssize_t:l
++suseconds_t:l
++time_t:l
++u_char:h
++uid_t:j
++uint:j
++u_int:j
++u_int16_t:t
++u_int32_t:j
++u_int64_t:m
++u_int8_t:h
++ulong:m
++u_long:m
++u_quad_t:m
++useconds_t:j
++ushort:t
++u_short:t
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/fpu/jmp_buf-macros.h b/sysdeps/unix/sysv/linux/loongarch/lp64/fpu/jmp_buf-macros.h
+new file mode 100644
+index 00000000..a02865b4
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/fpu/jmp_buf-macros.h
+@@ -0,0 +1,44 @@
++/* jump buffer constants for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Produced by this program:
++
++ #include <stdio.h>
++ #include <unistd.h>
++ #include <setjmp.h>
++ #include <stddef.h>
++
++ int main (int argc, char **argv)
++ {
++ printf ("#define JMP_BUF_SIZE %d\n", sizeof (jmp_buf));
++ printf ("#define JMP_BUF_ALIGN %d\n", __alignof__ (jmp_buf));
++ printf ("#define SIGJMP_BUF_SIZE %d\n", sizeof (sigjmp_buf));
++ printf ("#define SIGJMP_BUF_ALIGN %d\n", __alignof__ (sigjmp_buf));
++ printf ("#define MASK_WAS_SAVED_OFFSET %d\n",
++ offsetof (struct __jmp_buf_tag, __mask_was_saved));
++ printf ("#define SAVED_MASK_OFFSET %d\n",
++ offsetof (struct __jmp_buf_tag, __saved_mask));
++ } */
++
++#define JMP_BUF_SIZE 304
++#define JMP_BUF_ALIGN 8
++#define SIGJMP_BUF_SIZE 304
++#define SIGJMP_BUF_ALIGN 8
++#define MASK_WAS_SAVED_OFFSET 168
++#define SAVED_MASK_OFFSET 176
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist
+new file mode 100644
+index 00000000..a6a0faff
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/ld.abilist
+@@ -0,0 +1,9 @@
++GLIBC_2.36 __libc_stack_end D 0x8
++GLIBC_2.36 __rseq_flags D 0x4
++GLIBC_2.36 __rseq_offset D 0x8
++GLIBC_2.36 __rseq_size D 0x4
++GLIBC_2.36 __rtld_version_placeholder F
++GLIBC_2.36 __stack_chk_guard D 0x8
++GLIBC_2.36 __tls_get_addr F
++GLIBC_2.36 _dl_mcount F
++GLIBC_2.36 _r_debug D 0x28
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist
+new file mode 100644
+index 00000000..404afa36
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libBrokenLocale.abilist
+@@ -0,0 +1 @@
++GLIBC_2.36 __ctype_get_mb_cur_max F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist
+new file mode 100644
+index 00000000..377e03d4
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libanl.abilist
+@@ -0,0 +1 @@
++GLIBC_2.36 __libanl_version_placeholder F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+new file mode 100644
+index 00000000..e1640cd7
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc.abilist
+@@ -0,0 +1,2135 @@
++GLIBC_2.36 _Exit F
++GLIBC_2.36 _Fork F
++GLIBC_2.36 _IO_2_1_stderr_ D 0xe0
++GLIBC_2.36 _IO_2_1_stdin_ D 0xe0
++GLIBC_2.36 _IO_2_1_stdout_ D 0xe0
++GLIBC_2.36 _IO_adjust_column F
++GLIBC_2.36 _IO_adjust_wcolumn F
++GLIBC_2.36 _IO_default_doallocate F
++GLIBC_2.36 _IO_default_finish F
++GLIBC_2.36 _IO_default_pbackfail F
++GLIBC_2.36 _IO_default_uflow F
++GLIBC_2.36 _IO_default_xsgetn F
++GLIBC_2.36 _IO_default_xsputn F
++GLIBC_2.36 _IO_do_write F
++GLIBC_2.36 _IO_doallocbuf F
++GLIBC_2.36 _IO_fclose F
++GLIBC_2.36 _IO_fdopen F
++GLIBC_2.36 _IO_feof F
++GLIBC_2.36 _IO_ferror F
++GLIBC_2.36 _IO_fflush F
++GLIBC_2.36 _IO_fgetpos F
++GLIBC_2.36 _IO_fgetpos64 F
++GLIBC_2.36 _IO_fgets F
++GLIBC_2.36 _IO_file_attach F
++GLIBC_2.36 _IO_file_close F
++GLIBC_2.36 _IO_file_close_it F
++GLIBC_2.36 _IO_file_doallocate F
++GLIBC_2.36 _IO_file_finish F
++GLIBC_2.36 _IO_file_fopen F
++GLIBC_2.36 _IO_file_init F
++GLIBC_2.36 _IO_file_jumps D 0xa8
++GLIBC_2.36 _IO_file_open F
++GLIBC_2.36 _IO_file_overflow F
++GLIBC_2.36 _IO_file_read F
++GLIBC_2.36 _IO_file_seek F
++GLIBC_2.36 _IO_file_seekoff F
++GLIBC_2.36 _IO_file_setbuf F
++GLIBC_2.36 _IO_file_stat F
++GLIBC_2.36 _IO_file_sync F
++GLIBC_2.36 _IO_file_underflow F
++GLIBC_2.36 _IO_file_write F
++GLIBC_2.36 _IO_file_xsputn F
++GLIBC_2.36 _IO_flockfile F
++GLIBC_2.36 _IO_flush_all F
++GLIBC_2.36 _IO_flush_all_linebuffered F
++GLIBC_2.36 _IO_fopen F
++GLIBC_2.36 _IO_fprintf F
++GLIBC_2.36 _IO_fputs F
++GLIBC_2.36 _IO_fread F
++GLIBC_2.36 _IO_free_backup_area F
++GLIBC_2.36 _IO_free_wbackup_area F
++GLIBC_2.36 _IO_fsetpos F
++GLIBC_2.36 _IO_fsetpos64 F
++GLIBC_2.36 _IO_ftell F
++GLIBC_2.36 _IO_ftrylockfile F
++GLIBC_2.36 _IO_funlockfile F
++GLIBC_2.36 _IO_fwrite F
++GLIBC_2.36 _IO_getc F
++GLIBC_2.36 _IO_getline F
++GLIBC_2.36 _IO_getline_info F
++GLIBC_2.36 _IO_gets F
++GLIBC_2.36 _IO_init F
++GLIBC_2.36 _IO_init_marker F
++GLIBC_2.36 _IO_init_wmarker F
++GLIBC_2.36 _IO_iter_begin F
++GLIBC_2.36 _IO_iter_end F
++GLIBC_2.36 _IO_iter_file F
++GLIBC_2.36 _IO_iter_next F
++GLIBC_2.36 _IO_least_wmarker F
++GLIBC_2.36 _IO_link_in F
++GLIBC_2.36 _IO_list_all D 0x8
++GLIBC_2.36 _IO_list_lock F
++GLIBC_2.36 _IO_list_resetlock F
++GLIBC_2.36 _IO_list_unlock F
++GLIBC_2.36 _IO_marker_delta F
++GLIBC_2.36 _IO_marker_difference F
++GLIBC_2.36 _IO_padn F
++GLIBC_2.36 _IO_peekc_locked F
++GLIBC_2.36 _IO_popen F
++GLIBC_2.36 _IO_printf F
++GLIBC_2.36 _IO_proc_close F
++GLIBC_2.36 _IO_proc_open F
++GLIBC_2.36 _IO_putc F
++GLIBC_2.36 _IO_puts F
++GLIBC_2.36 _IO_remove_marker F
++GLIBC_2.36 _IO_seekmark F
++GLIBC_2.36 _IO_seekoff F
++GLIBC_2.36 _IO_seekpos F
++GLIBC_2.36 _IO_seekwmark F
++GLIBC_2.36 _IO_setb F
++GLIBC_2.36 _IO_setbuffer F
++GLIBC_2.36 _IO_setvbuf F
++GLIBC_2.36 _IO_sgetn F
++GLIBC_2.36 _IO_sprintf F
++GLIBC_2.36 _IO_sputbackc F
++GLIBC_2.36 _IO_sputbackwc F
++GLIBC_2.36 _IO_sscanf F
++GLIBC_2.36 _IO_str_init_readonly F
++GLIBC_2.36 _IO_str_init_static F
++GLIBC_2.36 _IO_str_overflow F
++GLIBC_2.36 _IO_str_pbackfail F
++GLIBC_2.36 _IO_str_seekoff F
++GLIBC_2.36 _IO_str_underflow F
++GLIBC_2.36 _IO_sungetc F
++GLIBC_2.36 _IO_sungetwc F
++GLIBC_2.36 _IO_switch_to_get_mode F
++GLIBC_2.36 _IO_switch_to_main_wget_area F
++GLIBC_2.36 _IO_switch_to_wbackup_area F
++GLIBC_2.36 _IO_switch_to_wget_mode F
++GLIBC_2.36 _IO_un_link F
++GLIBC_2.36 _IO_ungetc F
++GLIBC_2.36 _IO_unsave_markers F
++GLIBC_2.36 _IO_unsave_wmarkers F
++GLIBC_2.36 _IO_vfprintf F
++GLIBC_2.36 _IO_vsprintf F
++GLIBC_2.36 _IO_wdefault_doallocate F
++GLIBC_2.36 _IO_wdefault_finish F
++GLIBC_2.36 _IO_wdefault_pbackfail F
++GLIBC_2.36 _IO_wdefault_uflow F
++GLIBC_2.36 _IO_wdefault_xsgetn F
++GLIBC_2.36 _IO_wdefault_xsputn F
++GLIBC_2.36 _IO_wdo_write F
++GLIBC_2.36 _IO_wdoallocbuf F
++GLIBC_2.36 _IO_wfile_jumps D 0xa8
++GLIBC_2.36 _IO_wfile_overflow F
++GLIBC_2.36 _IO_wfile_seekoff F
++GLIBC_2.36 _IO_wfile_sync F
++GLIBC_2.36 _IO_wfile_underflow F
++GLIBC_2.36 _IO_wfile_xsputn F
++GLIBC_2.36 _IO_wmarker_delta F
++GLIBC_2.36 _IO_wsetb F
++GLIBC_2.36 __adjtimex F
++GLIBC_2.36 __argz_count F
++GLIBC_2.36 __argz_next F
++GLIBC_2.36 __argz_stringify F
++GLIBC_2.36 __asprintf F
++GLIBC_2.36 __asprintf_chk F
++GLIBC_2.36 __assert F
++GLIBC_2.36 __assert_fail F
++GLIBC_2.36 __assert_perror_fail F
++GLIBC_2.36 __backtrace F
++GLIBC_2.36 __backtrace_symbols F
++GLIBC_2.36 __backtrace_symbols_fd F
++GLIBC_2.36 __bsd_getpgrp F
++GLIBC_2.36 __bzero F
++GLIBC_2.36 __check_rhosts_file D 0x4
++GLIBC_2.36 __chk_fail F
++GLIBC_2.36 __clone F
++GLIBC_2.36 __close F
++GLIBC_2.36 __cmsg_nxthdr F
++GLIBC_2.36 __confstr_chk F
++GLIBC_2.36 __connect F
++GLIBC_2.36 __ctype_b_loc F
++GLIBC_2.36 __ctype_get_mb_cur_max F
++GLIBC_2.36 __ctype_tolower_loc F
++GLIBC_2.36 __ctype_toupper_loc F
++GLIBC_2.36 __curbrk D 0x8
++GLIBC_2.36 __cxa_at_quick_exit F
++GLIBC_2.36 __cxa_atexit F
++GLIBC_2.36 __cxa_finalize F
++GLIBC_2.36 __cxa_thread_atexit_impl F
++GLIBC_2.36 __cyg_profile_func_enter F
++GLIBC_2.36 __cyg_profile_func_exit F
++GLIBC_2.36 __daylight D 0x4
++GLIBC_2.36 __dcgettext F
++GLIBC_2.36 __dgettext F
++GLIBC_2.36 __dprintf_chk F
++GLIBC_2.36 __dup2 F
++GLIBC_2.36 __duplocale F
++GLIBC_2.36 __endmntent F
++GLIBC_2.36 __environ D 0x8
++GLIBC_2.36 __errno_location F
++GLIBC_2.36 __explicit_bzero_chk F
++GLIBC_2.36 __fbufsize F
++GLIBC_2.36 __fcntl F
++GLIBC_2.36 __fdelt_chk F
++GLIBC_2.36 __fdelt_warn F
++GLIBC_2.36 __ffs F
++GLIBC_2.36 __fgets_chk F
++GLIBC_2.36 __fgets_unlocked_chk F
++GLIBC_2.36 __fgetws_chk F
++GLIBC_2.36 __fgetws_unlocked_chk F
++GLIBC_2.36 __finite F
++GLIBC_2.36 __finitef F
++GLIBC_2.36 __finitel F
++GLIBC_2.36 __flbf F
++GLIBC_2.36 __fork F
++GLIBC_2.36 __fpending F
++GLIBC_2.36 __fprintf_chk F
++GLIBC_2.36 __fpu_control D 0x4
++GLIBC_2.36 __fpurge F
++GLIBC_2.36 __fread_chk F
++GLIBC_2.36 __fread_unlocked_chk F
++GLIBC_2.36 __freadable F
++GLIBC_2.36 __freading F
++GLIBC_2.36 __freelocale F
++GLIBC_2.36 __fsetlocking F
++GLIBC_2.36 __fwprintf_chk F
++GLIBC_2.36 __fwritable F
++GLIBC_2.36 __fwriting F
++GLIBC_2.36 __getauxval F
++GLIBC_2.36 __getcwd_chk F
++GLIBC_2.36 __getdelim F
++GLIBC_2.36 __getdomainname_chk F
++GLIBC_2.36 __getgroups_chk F
++GLIBC_2.36 __gethostname_chk F
++GLIBC_2.36 __getlogin_r_chk F
++GLIBC_2.36 __getmntent_r F
++GLIBC_2.36 __getpagesize F
++GLIBC_2.36 __getpgid F
++GLIBC_2.36 __getpid F
++GLIBC_2.36 __gets_chk F
++GLIBC_2.36 __gettimeofday F
++GLIBC_2.36 __getwd_chk F
++GLIBC_2.36 __gmtime_r F
++GLIBC_2.36 __h_errno_location F
++GLIBC_2.36 __isalnum_l F
++GLIBC_2.36 __isalpha_l F
++GLIBC_2.36 __isascii_l F
++GLIBC_2.36 __isblank_l F
++GLIBC_2.36 __iscntrl_l F
++GLIBC_2.36 __isctype F
++GLIBC_2.36 __isdigit_l F
++GLIBC_2.36 __isgraph_l F
++GLIBC_2.36 __isinf F
++GLIBC_2.36 __isinff F
++GLIBC_2.36 __isinfl F
++GLIBC_2.36 __islower_l F
++GLIBC_2.36 __isnan F
++GLIBC_2.36 __isnanf F
++GLIBC_2.36 __isnanl F
++GLIBC_2.36 __isoc99_fscanf F
++GLIBC_2.36 __isoc99_fwscanf F
++GLIBC_2.36 __isoc99_scanf F
++GLIBC_2.36 __isoc99_sscanf F
++GLIBC_2.36 __isoc99_swscanf F
++GLIBC_2.36 __isoc99_vfscanf F
++GLIBC_2.36 __isoc99_vfwscanf F
++GLIBC_2.36 __isoc99_vscanf F
++GLIBC_2.36 __isoc99_vsscanf F
++GLIBC_2.36 __isoc99_vswscanf F
++GLIBC_2.36 __isoc99_vwscanf F
++GLIBC_2.36 __isoc99_wscanf F
++GLIBC_2.36 __isprint_l F
++GLIBC_2.36 __ispunct_l F
++GLIBC_2.36 __isspace_l F
++GLIBC_2.36 __isupper_l F
++GLIBC_2.36 __iswalnum_l F
++GLIBC_2.36 __iswalpha_l F
++GLIBC_2.36 __iswblank_l F
++GLIBC_2.36 __iswcntrl_l F
++GLIBC_2.36 __iswctype F
++GLIBC_2.36 __iswctype_l F
++GLIBC_2.36 __iswdigit_l F
++GLIBC_2.36 __iswgraph_l F
++GLIBC_2.36 __iswlower_l F
++GLIBC_2.36 __iswprint_l F
++GLIBC_2.36 __iswpunct_l F
++GLIBC_2.36 __iswspace_l F
++GLIBC_2.36 __iswupper_l F
++GLIBC_2.36 __iswxdigit_l F
++GLIBC_2.36 __isxdigit_l F
++GLIBC_2.36 __ivaliduser F
++GLIBC_2.36 __libc_allocate_rtsig F
++GLIBC_2.36 __libc_calloc F
++GLIBC_2.36 __libc_current_sigrtmax F
++GLIBC_2.36 __libc_current_sigrtmin F
++GLIBC_2.36 __libc_free F
++GLIBC_2.36 __libc_freeres F
++GLIBC_2.36 __libc_init_first F
++GLIBC_2.36 __libc_mallinfo F
++GLIBC_2.36 __libc_malloc F
++GLIBC_2.36 __libc_mallopt F
++GLIBC_2.36 __libc_memalign F
++GLIBC_2.36 __libc_pvalloc F
++GLIBC_2.36 __libc_realloc F
++GLIBC_2.36 __libc_sa_len F
++GLIBC_2.36 __libc_single_threaded D 0x1
++GLIBC_2.36 __libc_start_main F
++GLIBC_2.36 __libc_valloc F
++GLIBC_2.36 __longjmp_chk F
++GLIBC_2.36 __lseek F
++GLIBC_2.36 __mbrlen F
++GLIBC_2.36 __mbrtowc F
++GLIBC_2.36 __mbsnrtowcs_chk F
++GLIBC_2.36 __mbsrtowcs_chk F
++GLIBC_2.36 __mbstowcs_chk F
++GLIBC_2.36 __memcpy_chk F
++GLIBC_2.36 __memmove_chk F
++GLIBC_2.36 __mempcpy F
++GLIBC_2.36 __mempcpy_chk F
++GLIBC_2.36 __memset_chk F
++GLIBC_2.36 __monstartup F
++GLIBC_2.36 __mq_open_2 F
++GLIBC_2.36 __nanosleep F
++GLIBC_2.36 __newlocale F
++GLIBC_2.36 __nl_langinfo_l F
++GLIBC_2.36 __nss_configure_lookup F
++GLIBC_2.36 __nss_hostname_digits_dots F
++GLIBC_2.36 __obstack_printf_chk F
++GLIBC_2.36 __obstack_vprintf_chk F
++GLIBC_2.36 __open F
++GLIBC_2.36 __open64 F
++GLIBC_2.36 __open64_2 F
++GLIBC_2.36 __open_2 F
++GLIBC_2.36 __openat64_2 F
++GLIBC_2.36 __openat_2 F
++GLIBC_2.36 __overflow F
++GLIBC_2.36 __pipe F
++GLIBC_2.36 __poll F
++GLIBC_2.36 __poll_chk F
++GLIBC_2.36 __posix_getopt F
++GLIBC_2.36 __ppoll_chk F
++GLIBC_2.36 __pread64 F
++GLIBC_2.36 __pread64_chk F
++GLIBC_2.36 __pread_chk F
++GLIBC_2.36 __printf_chk F
++GLIBC_2.36 __printf_fp F
++GLIBC_2.36 __profile_frequency F
++GLIBC_2.36 __progname D 0x8
++GLIBC_2.36 __progname_full D 0x8
++GLIBC_2.36 __pthread_cleanup_routine F
++GLIBC_2.36 __pthread_key_create F
++GLIBC_2.36 __pthread_register_cancel F
++GLIBC_2.36 __pthread_register_cancel_defer F
++GLIBC_2.36 __pthread_rwlock_unlock F
++GLIBC_2.36 __pthread_unregister_cancel F
++GLIBC_2.36 __pthread_unregister_cancel_restore F
++GLIBC_2.36 __pthread_unwind_next F
++GLIBC_2.36 __ptsname_r_chk F
++GLIBC_2.36 __pwrite64 F
++GLIBC_2.36 __rawmemchr F
++GLIBC_2.36 __rcmd_errstr D 0x8
++GLIBC_2.36 __read F
++GLIBC_2.36 __read_chk F
++GLIBC_2.36 __readlink_chk F
++GLIBC_2.36 __readlinkat_chk F
++GLIBC_2.36 __realpath_chk F
++GLIBC_2.36 __recv_chk F
++GLIBC_2.36 __recvfrom_chk F
++GLIBC_2.36 __register_atfork F
++GLIBC_2.36 __res_init F
++GLIBC_2.36 __res_nclose F
++GLIBC_2.36 __res_ninit F
++GLIBC_2.36 __res_randomid F
++GLIBC_2.36 __res_state F
++GLIBC_2.36 __sbrk F
++GLIBC_2.36 __sched_cpualloc F
++GLIBC_2.36 __sched_cpucount F
++GLIBC_2.36 __sched_cpufree F
++GLIBC_2.36 __sched_get_priority_max F
++GLIBC_2.36 __sched_get_priority_min F
++GLIBC_2.36 __sched_getparam F
++GLIBC_2.36 __sched_getscheduler F
++GLIBC_2.36 __sched_setscheduler F
++GLIBC_2.36 __sched_yield F
++GLIBC_2.36 __select F
++GLIBC_2.36 __send F
++GLIBC_2.36 __setmntent F
++GLIBC_2.36 __setpgid F
++GLIBC_2.36 __sigaction F
++GLIBC_2.36 __signbit F
++GLIBC_2.36 __signbitf F
++GLIBC_2.36 __signbitl F
++GLIBC_2.36 __sigpause F
++GLIBC_2.36 __sigsetjmp F
++GLIBC_2.36 __sigsuspend F
++GLIBC_2.36 __snprintf_chk F
++GLIBC_2.36 __sprintf_chk F
++GLIBC_2.36 __stack_chk_fail F
++GLIBC_2.36 __statfs F
++GLIBC_2.36 __stpcpy F
++GLIBC_2.36 __stpcpy_chk F
++GLIBC_2.36 __stpncpy F
++GLIBC_2.36 __stpncpy_chk F
++GLIBC_2.36 __strcasecmp F
++GLIBC_2.36 __strcasecmp_l F
++GLIBC_2.36 __strcasestr F
++GLIBC_2.36 __strcat_chk F
++GLIBC_2.36 __strcoll_l F
++GLIBC_2.36 __strcpy_chk F
++GLIBC_2.36 __strdup F
++GLIBC_2.36 __strerror_r F
++GLIBC_2.36 __strfmon_l F
++GLIBC_2.36 __strftime_l F
++GLIBC_2.36 __strncasecmp_l F
++GLIBC_2.36 __strncat_chk F
++GLIBC_2.36 __strncpy_chk F
++GLIBC_2.36 __strndup F
++GLIBC_2.36 __strsep_g F
++GLIBC_2.36 __strtod_internal F
++GLIBC_2.36 __strtod_l F
++GLIBC_2.36 __strtof_internal F
++GLIBC_2.36 __strtof_l F
++GLIBC_2.36 __strtok_r F
++GLIBC_2.36 __strtol_internal F
++GLIBC_2.36 __strtol_l F
++GLIBC_2.36 __strtold_internal F
++GLIBC_2.36 __strtold_l F
++GLIBC_2.36 __strtoll_internal F
++GLIBC_2.36 __strtoll_l F
++GLIBC_2.36 __strtoul_internal F
++GLIBC_2.36 __strtoul_l F
++GLIBC_2.36 __strtoull_internal F
++GLIBC_2.36 __strtoull_l F
++GLIBC_2.36 __strverscmp F
++GLIBC_2.36 __strxfrm_l F
++GLIBC_2.36 __swprintf_chk F
++GLIBC_2.36 __sysconf F
++GLIBC_2.36 __syslog_chk F
++GLIBC_2.36 __sysv_signal F
++GLIBC_2.36 __timezone D 0x8
++GLIBC_2.36 __toascii_l F
++GLIBC_2.36 __tolower_l F
++GLIBC_2.36 __toupper_l F
++GLIBC_2.36 __towctrans F
++GLIBC_2.36 __towctrans_l F
++GLIBC_2.36 __towlower_l F
++GLIBC_2.36 __towupper_l F
++GLIBC_2.36 __ttyname_r_chk F
++GLIBC_2.36 __tzname D 0x10
++GLIBC_2.36 __uflow F
++GLIBC_2.36 __underflow F
++GLIBC_2.36 __uselocale F
++GLIBC_2.36 __vasprintf_chk F
++GLIBC_2.36 __vdprintf_chk F
++GLIBC_2.36 __vfork F
++GLIBC_2.36 __vfprintf_chk F
++GLIBC_2.36 __vfscanf F
++GLIBC_2.36 __vfwprintf_chk F
++GLIBC_2.36 __vprintf_chk F
++GLIBC_2.36 __vsnprintf F
++GLIBC_2.36 __vsnprintf_chk F
++GLIBC_2.36 __vsprintf_chk F
++GLIBC_2.36 __vsscanf F
++GLIBC_2.36 __vswprintf_chk F
++GLIBC_2.36 __vsyslog_chk F
++GLIBC_2.36 __vwprintf_chk F
++GLIBC_2.36 __wait F
++GLIBC_2.36 __waitpid F
++GLIBC_2.36 __wcpcpy_chk F
++GLIBC_2.36 __wcpncpy_chk F
++GLIBC_2.36 __wcrtomb_chk F
++GLIBC_2.36 __wcscasecmp_l F
++GLIBC_2.36 __wcscat_chk F
++GLIBC_2.36 __wcscoll_l F
++GLIBC_2.36 __wcscpy_chk F
++GLIBC_2.36 __wcsftime_l F
++GLIBC_2.36 __wcsncasecmp_l F
++GLIBC_2.36 __wcsncat_chk F
++GLIBC_2.36 __wcsncpy_chk F
++GLIBC_2.36 __wcsnrtombs_chk F
++GLIBC_2.36 __wcsrtombs_chk F
++GLIBC_2.36 __wcstod_internal F
++GLIBC_2.36 __wcstod_l F
++GLIBC_2.36 __wcstof_internal F
++GLIBC_2.36 __wcstof_l F
++GLIBC_2.36 __wcstol_internal F
++GLIBC_2.36 __wcstol_l F
++GLIBC_2.36 __wcstold_internal F
++GLIBC_2.36 __wcstold_l F
++GLIBC_2.36 __wcstoll_internal F
++GLIBC_2.36 __wcstoll_l F
++GLIBC_2.36 __wcstombs_chk F
++GLIBC_2.36 __wcstoul_internal F
++GLIBC_2.36 __wcstoul_l F
++GLIBC_2.36 __wcstoull_internal F
++GLIBC_2.36 __wcstoull_l F
++GLIBC_2.36 __wcsxfrm_l F
++GLIBC_2.36 __wctomb_chk F
++GLIBC_2.36 __wctrans_l F
++GLIBC_2.36 __wctype_l F
++GLIBC_2.36 __wmemcpy_chk F
++GLIBC_2.36 __wmemmove_chk F
++GLIBC_2.36 __wmempcpy_chk F
++GLIBC_2.36 __wmemset_chk F
++GLIBC_2.36 __woverflow F
++GLIBC_2.36 __wprintf_chk F
++GLIBC_2.36 __write F
++GLIBC_2.36 __wuflow F
++GLIBC_2.36 __wunderflow F
++GLIBC_2.36 __xpg_basename F
++GLIBC_2.36 __xpg_sigpause F
++GLIBC_2.36 __xpg_strerror_r F
++GLIBC_2.36 _dl_mcount_wrapper F
++GLIBC_2.36 _dl_mcount_wrapper_check F
++GLIBC_2.36 _environ D 0x8
++GLIBC_2.36 _exit F
++GLIBC_2.36 _flushlbf F
++GLIBC_2.36 _libc_intl_domainname D 0x5
++GLIBC_2.36 _longjmp F
++GLIBC_2.36 _mcleanup F
++GLIBC_2.36 _mcount F
++GLIBC_2.36 _nl_default_dirname D 0x12
++GLIBC_2.36 _nl_domain_bindings D 0x8
++GLIBC_2.36 _nl_msg_cat_cntr D 0x4
++GLIBC_2.36 _obstack_allocated_p F
++GLIBC_2.36 _obstack_begin F
++GLIBC_2.36 _obstack_begin_1 F
++GLIBC_2.36 _obstack_free F
++GLIBC_2.36 _obstack_memory_used F
++GLIBC_2.36 _obstack_newchunk F
++GLIBC_2.36 _pthread_cleanup_pop F
++GLIBC_2.36 _pthread_cleanup_push F
++GLIBC_2.36 _res D 0x238
++GLIBC_2.36 _res_hconf D 0x48
++GLIBC_2.36 _setjmp F
++GLIBC_2.36 _tolower F
++GLIBC_2.36 _toupper F
++GLIBC_2.36 a64l F
++GLIBC_2.36 abort F
++GLIBC_2.36 abs F
++GLIBC_2.36 accept F
++GLIBC_2.36 accept4 F
++GLIBC_2.36 access F
++GLIBC_2.36 acct F
++GLIBC_2.36 addmntent F
++GLIBC_2.36 addseverity F
++GLIBC_2.36 adjtime F
++GLIBC_2.36 adjtimex F
++GLIBC_2.36 aio_cancel F
++GLIBC_2.36 aio_cancel64 F
++GLIBC_2.36 aio_error F
++GLIBC_2.36 aio_error64 F
++GLIBC_2.36 aio_fsync F
++GLIBC_2.36 aio_fsync64 F
++GLIBC_2.36 aio_init F
++GLIBC_2.36 aio_read F
++GLIBC_2.36 aio_read64 F
++GLIBC_2.36 aio_return F
++GLIBC_2.36 aio_return64 F
++GLIBC_2.36 aio_suspend F
++GLIBC_2.36 aio_suspend64 F
++GLIBC_2.36 aio_write F
++GLIBC_2.36 aio_write64 F
++GLIBC_2.36 alarm F
++GLIBC_2.36 aligned_alloc F
++GLIBC_2.36 alphasort F
++GLIBC_2.36 alphasort64 F
++GLIBC_2.36 argp_err_exit_status D 0x4
++GLIBC_2.36 argp_error F
++GLIBC_2.36 argp_failure F
++GLIBC_2.36 argp_help F
++GLIBC_2.36 argp_parse F
++GLIBC_2.36 argp_program_bug_address D 0x8
++GLIBC_2.36 argp_program_version D 0x8
++GLIBC_2.36 argp_program_version_hook D 0x8
++GLIBC_2.36 argp_state_help F
++GLIBC_2.36 argp_usage F
++GLIBC_2.36 argz_add F
++GLIBC_2.36 argz_add_sep F
++GLIBC_2.36 argz_append F
++GLIBC_2.36 argz_count F
++GLIBC_2.36 argz_create F
++GLIBC_2.36 argz_create_sep F
++GLIBC_2.36 argz_delete F
++GLIBC_2.36 argz_extract F
++GLIBC_2.36 argz_insert F
++GLIBC_2.36 argz_next F
++GLIBC_2.36 argz_replace F
++GLIBC_2.36 argz_stringify F
++GLIBC_2.36 asctime F
++GLIBC_2.36 asctime_r F
++GLIBC_2.36 asprintf F
++GLIBC_2.36 atof F
++GLIBC_2.36 atoi F
++GLIBC_2.36 atol F
++GLIBC_2.36 atoll F
++GLIBC_2.36 backtrace F
++GLIBC_2.36 backtrace_symbols F
++GLIBC_2.36 backtrace_symbols_fd F
++GLIBC_2.36 basename F
++GLIBC_2.36 bcmp F
++GLIBC_2.36 bcopy F
++GLIBC_2.36 bind F
++GLIBC_2.36 bind_textdomain_codeset F
++GLIBC_2.36 bindresvport F
++GLIBC_2.36 bindtextdomain F
++GLIBC_2.36 brk F
++GLIBC_2.36 bsd_signal F
++GLIBC_2.36 bsearch F
++GLIBC_2.36 btowc F
++GLIBC_2.36 bzero F
++GLIBC_2.36 c16rtomb F
++GLIBC_2.36 c32rtomb F
++GLIBC_2.36 call_once F
++GLIBC_2.36 calloc F
++GLIBC_2.36 canonicalize_file_name F
++GLIBC_2.36 capget F
++GLIBC_2.36 capset F
++GLIBC_2.36 catclose F
++GLIBC_2.36 catgets F
++GLIBC_2.36 catopen F
++GLIBC_2.36 cfgetispeed F
++GLIBC_2.36 cfgetospeed F
++GLIBC_2.36 cfmakeraw F
++GLIBC_2.36 cfsetispeed F
++GLIBC_2.36 cfsetospeed F
++GLIBC_2.36 cfsetspeed F
++GLIBC_2.36 chdir F
++GLIBC_2.36 chflags F
++GLIBC_2.36 chmod F
++GLIBC_2.36 chown F
++GLIBC_2.36 chroot F
++GLIBC_2.36 clearenv F
++GLIBC_2.36 clearerr F
++GLIBC_2.36 clearerr_unlocked F
++GLIBC_2.36 clock F
++GLIBC_2.36 clock_adjtime F
++GLIBC_2.36 clock_getcpuclockid F
++GLIBC_2.36 clock_getres F
++GLIBC_2.36 clock_gettime F
++GLIBC_2.36 clock_nanosleep F
++GLIBC_2.36 clock_settime F
++GLIBC_2.36 clone F
++GLIBC_2.36 close F
++GLIBC_2.36 close_range F
++GLIBC_2.36 closedir F
++GLIBC_2.36 closefrom F
++GLIBC_2.36 closelog F
++GLIBC_2.36 cnd_broadcast F
++GLIBC_2.36 cnd_destroy F
++GLIBC_2.36 cnd_init F
++GLIBC_2.36 cnd_signal F
++GLIBC_2.36 cnd_timedwait F
++GLIBC_2.36 cnd_wait F
++GLIBC_2.36 confstr F
++GLIBC_2.36 connect F
++GLIBC_2.36 copy_file_range F
++GLIBC_2.36 copysign F
++GLIBC_2.36 copysignf F
++GLIBC_2.36 copysignl F
++GLIBC_2.36 creat F
++GLIBC_2.36 creat64 F
++GLIBC_2.36 ctermid F
++GLIBC_2.36 ctime F
++GLIBC_2.36 ctime_r F
++GLIBC_2.36 cuserid F
++GLIBC_2.36 daemon F
++GLIBC_2.36 daylight D 0x4
++GLIBC_2.36 dcgettext F
++GLIBC_2.36 dcngettext F
++GLIBC_2.36 delete_module F
++GLIBC_2.36 dgettext F
++GLIBC_2.36 difftime F
++GLIBC_2.36 dirfd F
++GLIBC_2.36 dirname F
++GLIBC_2.36 div F
++GLIBC_2.36 dl_iterate_phdr F
++GLIBC_2.36 dladdr F
++GLIBC_2.36 dladdr1 F
++GLIBC_2.36 dlclose F
++GLIBC_2.36 dlerror F
++GLIBC_2.36 dlinfo F
++GLIBC_2.36 dlmopen F
++GLIBC_2.36 dlopen F
++GLIBC_2.36 dlsym F
++GLIBC_2.36 dlvsym F
++GLIBC_2.36 dn_comp F
++GLIBC_2.36 dn_expand F
++GLIBC_2.36 dn_skipname F
++GLIBC_2.36 dngettext F
++GLIBC_2.36 dprintf F
++GLIBC_2.36 drand48 F
++GLIBC_2.36 drand48_r F
++GLIBC_2.36 dup F
++GLIBC_2.36 dup2 F
++GLIBC_2.36 dup3 F
++GLIBC_2.36 duplocale F
++GLIBC_2.36 dysize F
++GLIBC_2.36 eaccess F
++GLIBC_2.36 ecvt F
++GLIBC_2.36 ecvt_r F
++GLIBC_2.36 endaliasent F
++GLIBC_2.36 endfsent F
++GLIBC_2.36 endgrent F
++GLIBC_2.36 endhostent F
++GLIBC_2.36 endmntent F
++GLIBC_2.36 endnetent F
++GLIBC_2.36 endnetgrent F
++GLIBC_2.36 endprotoent F
++GLIBC_2.36 endpwent F
++GLIBC_2.36 endrpcent F
++GLIBC_2.36 endservent F
++GLIBC_2.36 endsgent F
++GLIBC_2.36 endspent F
++GLIBC_2.36 endttyent F
++GLIBC_2.36 endusershell F
++GLIBC_2.36 endutent F
++GLIBC_2.36 endutxent F
++GLIBC_2.36 environ D 0x8
++GLIBC_2.36 envz_add F
++GLIBC_2.36 envz_entry F
++GLIBC_2.36 envz_get F
++GLIBC_2.36 envz_merge F
++GLIBC_2.36 envz_remove F
++GLIBC_2.36 envz_strip F
++GLIBC_2.36 epoll_create F
++GLIBC_2.36 epoll_create1 F
++GLIBC_2.36 epoll_ctl F
++GLIBC_2.36 epoll_pwait F
++GLIBC_2.36 epoll_wait F
++GLIBC_2.36 erand48 F
++GLIBC_2.36 erand48_r F
++GLIBC_2.36 err F
++GLIBC_2.36 error F
++GLIBC_2.36 error_at_line F
++GLIBC_2.36 error_message_count D 0x4
++GLIBC_2.36 error_one_per_line D 0x4
++GLIBC_2.36 error_print_progname D 0x8
++GLIBC_2.36 errx F
++GLIBC_2.36 ether_aton F
++GLIBC_2.36 ether_aton_r F
++GLIBC_2.36 ether_hostton F
++GLIBC_2.36 ether_line F
++GLIBC_2.36 ether_ntoa F
++GLIBC_2.36 ether_ntoa_r F
++GLIBC_2.36 ether_ntohost F
++GLIBC_2.36 euidaccess F
++GLIBC_2.36 eventfd F
++GLIBC_2.36 eventfd_read F
++GLIBC_2.36 eventfd_write F
++GLIBC_2.36 execl F
++GLIBC_2.36 execle F
++GLIBC_2.36 execlp F
++GLIBC_2.36 execv F
++GLIBC_2.36 execve F
++GLIBC_2.36 execveat F
++GLIBC_2.36 execvp F
++GLIBC_2.36 execvpe F
++GLIBC_2.36 exit F
++GLIBC_2.36 explicit_bzero F
++GLIBC_2.36 faccessat F
++GLIBC_2.36 fallocate F
++GLIBC_2.36 fallocate64 F
++GLIBC_2.36 fanotify_init F
++GLIBC_2.36 fanotify_mark F
++GLIBC_2.36 fchdir F
++GLIBC_2.36 fchflags F
++GLIBC_2.36 fchmod F
++GLIBC_2.36 fchmodat F
++GLIBC_2.36 fchown F
++GLIBC_2.36 fchownat F
++GLIBC_2.36 fclose F
++GLIBC_2.36 fcloseall F
++GLIBC_2.36 fcntl F
++GLIBC_2.36 fcntl64 F
++GLIBC_2.36 fcvt F
++GLIBC_2.36 fcvt_r F
++GLIBC_2.36 fdatasync F
++GLIBC_2.36 fdopen F
++GLIBC_2.36 fdopendir F
++GLIBC_2.36 feof F
++GLIBC_2.36 feof_unlocked F
++GLIBC_2.36 ferror F
++GLIBC_2.36 ferror_unlocked F
++GLIBC_2.36 fexecve F
++GLIBC_2.36 fflush F
++GLIBC_2.36 fflush_unlocked F
++GLIBC_2.36 ffs F
++GLIBC_2.36 ffsl F
++GLIBC_2.36 ffsll F
++GLIBC_2.36 fgetc F
++GLIBC_2.36 fgetc_unlocked F
++GLIBC_2.36 fgetgrent F
++GLIBC_2.36 fgetgrent_r F
++GLIBC_2.36 fgetpos F
++GLIBC_2.36 fgetpos64 F
++GLIBC_2.36 fgetpwent F
++GLIBC_2.36 fgetpwent_r F
++GLIBC_2.36 fgets F
++GLIBC_2.36 fgets_unlocked F
++GLIBC_2.36 fgetsgent F
++GLIBC_2.36 fgetsgent_r F
++GLIBC_2.36 fgetspent F
++GLIBC_2.36 fgetspent_r F
++GLIBC_2.36 fgetwc F
++GLIBC_2.36 fgetwc_unlocked F
++GLIBC_2.36 fgetws F
++GLIBC_2.36 fgetws_unlocked F
++GLIBC_2.36 fgetxattr F
++GLIBC_2.36 fileno F
++GLIBC_2.36 fileno_unlocked F
++GLIBC_2.36 finite F
++GLIBC_2.36 finitef F
++GLIBC_2.36 finitel F
++GLIBC_2.36 flistxattr F
++GLIBC_2.36 flock F
++GLIBC_2.36 flockfile F
++GLIBC_2.36 fmemopen F
++GLIBC_2.36 fmtmsg F
++GLIBC_2.36 fnmatch F
++GLIBC_2.36 fopen F
++GLIBC_2.36 fopen64 F
++GLIBC_2.36 fopencookie F
++GLIBC_2.36 fork F
++GLIBC_2.36 forkpty F
++GLIBC_2.36 fpathconf F
++GLIBC_2.36 fprintf F
++GLIBC_2.36 fputc F
++GLIBC_2.36 fputc_unlocked F
++GLIBC_2.36 fputs F
++GLIBC_2.36 fputs_unlocked F
++GLIBC_2.36 fputwc F
++GLIBC_2.36 fputwc_unlocked F
++GLIBC_2.36 fputws F
++GLIBC_2.36 fputws_unlocked F
++GLIBC_2.36 fread F
++GLIBC_2.36 fread_unlocked F
++GLIBC_2.36 free F
++GLIBC_2.36 freeaddrinfo F
++GLIBC_2.36 freeifaddrs F
++GLIBC_2.36 freelocale F
++GLIBC_2.36 fremovexattr F
++GLIBC_2.36 freopen F
++GLIBC_2.36 freopen64 F
++GLIBC_2.36 frexp F
++GLIBC_2.36 frexpf F
++GLIBC_2.36 frexpl F
++GLIBC_2.36 fscanf F
++GLIBC_2.36 fseek F
++GLIBC_2.36 fseeko F
++GLIBC_2.36 fseeko64 F
++GLIBC_2.36 fsetpos F
++GLIBC_2.36 fsetpos64 F
++GLIBC_2.36 fsetxattr F
++GLIBC_2.36 fstat F
++GLIBC_2.36 fstat64 F
++GLIBC_2.36 fstatat F
++GLIBC_2.36 fstatat64 F
++GLIBC_2.36 fstatfs F
++GLIBC_2.36 fstatfs64 F
++GLIBC_2.36 fstatvfs F
++GLIBC_2.36 fstatvfs64 F
++GLIBC_2.36 fsync F
++GLIBC_2.36 ftell F
++GLIBC_2.36 ftello F
++GLIBC_2.36 ftello64 F
++GLIBC_2.36 ftime F
++GLIBC_2.36 ftok F
++GLIBC_2.36 ftruncate F
++GLIBC_2.36 ftruncate64 F
++GLIBC_2.36 ftrylockfile F
++GLIBC_2.36 fts64_children F
++GLIBC_2.36 fts64_close F
++GLIBC_2.36 fts64_open F
++GLIBC_2.36 fts64_read F
++GLIBC_2.36 fts64_set F
++GLIBC_2.36 fts_children F
++GLIBC_2.36 fts_close F
++GLIBC_2.36 fts_open F
++GLIBC_2.36 fts_read F
++GLIBC_2.36 fts_set F
++GLIBC_2.36 ftw F
++GLIBC_2.36 ftw64 F
++GLIBC_2.36 funlockfile F
++GLIBC_2.36 futimens F
++GLIBC_2.36 futimes F
++GLIBC_2.36 futimesat F
++GLIBC_2.36 fwide F
++GLIBC_2.36 fwprintf F
++GLIBC_2.36 fwrite F
++GLIBC_2.36 fwrite_unlocked F
++GLIBC_2.36 fwscanf F
++GLIBC_2.36 gai_cancel F
++GLIBC_2.36 gai_error F
++GLIBC_2.36 gai_strerror F
++GLIBC_2.36 gai_suspend F
++GLIBC_2.36 gcvt F
++GLIBC_2.36 get_avphys_pages F
++GLIBC_2.36 get_current_dir_name F
++GLIBC_2.36 get_nprocs F
++GLIBC_2.36 get_nprocs_conf F
++GLIBC_2.36 get_phys_pages F
++GLIBC_2.36 getaddrinfo F
++GLIBC_2.36 getaddrinfo_a F
++GLIBC_2.36 getaliasbyname F
++GLIBC_2.36 getaliasbyname_r F
++GLIBC_2.36 getaliasent F
++GLIBC_2.36 getaliasent_r F
++GLIBC_2.36 getauxval F
++GLIBC_2.36 getc F
++GLIBC_2.36 getc_unlocked F
++GLIBC_2.36 getchar F
++GLIBC_2.36 getchar_unlocked F
++GLIBC_2.36 getcontext F
++GLIBC_2.36 getcpu F
++GLIBC_2.36 getcwd F
++GLIBC_2.36 getdate F
++GLIBC_2.36 getdate_err D 0x4
++GLIBC_2.36 getdate_r F
++GLIBC_2.36 getdelim F
++GLIBC_2.36 getdents64 F
++GLIBC_2.36 getdirentries F
++GLIBC_2.36 getdirentries64 F
++GLIBC_2.36 getdomainname F
++GLIBC_2.36 getdtablesize F
++GLIBC_2.36 getegid F
++GLIBC_2.36 getentropy F
++GLIBC_2.36 getenv F
++GLIBC_2.36 geteuid F
++GLIBC_2.36 getfsent F
++GLIBC_2.36 getfsfile F
++GLIBC_2.36 getfsspec F
++GLIBC_2.36 getgid F
++GLIBC_2.36 getgrent F
++GLIBC_2.36 getgrent_r F
++GLIBC_2.36 getgrgid F
++GLIBC_2.36 getgrgid_r F
++GLIBC_2.36 getgrnam F
++GLIBC_2.36 getgrnam_r F
++GLIBC_2.36 getgrouplist F
++GLIBC_2.36 getgroups F
++GLIBC_2.36 gethostbyaddr F
++GLIBC_2.36 gethostbyaddr_r F
++GLIBC_2.36 gethostbyname F
++GLIBC_2.36 gethostbyname2 F
++GLIBC_2.36 gethostbyname2_r F
++GLIBC_2.36 gethostbyname_r F
++GLIBC_2.36 gethostent F
++GLIBC_2.36 gethostent_r F
++GLIBC_2.36 gethostid F
++GLIBC_2.36 gethostname F
++GLIBC_2.36 getifaddrs F
++GLIBC_2.36 getipv4sourcefilter F
++GLIBC_2.36 getitimer F
++GLIBC_2.36 getline F
++GLIBC_2.36 getloadavg F
++GLIBC_2.36 getlogin F
++GLIBC_2.36 getlogin_r F
++GLIBC_2.36 getmntent F
++GLIBC_2.36 getmntent_r F
++GLIBC_2.36 getnameinfo F
++GLIBC_2.36 getnetbyaddr F
++GLIBC_2.36 getnetbyaddr_r F
++GLIBC_2.36 getnetbyname F
++GLIBC_2.36 getnetbyname_r F
++GLIBC_2.36 getnetent F
++GLIBC_2.36 getnetent_r F
++GLIBC_2.36 getnetgrent F
++GLIBC_2.36 getnetgrent_r F
++GLIBC_2.36 getopt F
++GLIBC_2.36 getopt_long F
++GLIBC_2.36 getopt_long_only F
++GLIBC_2.36 getpagesize F
++GLIBC_2.36 getpass F
++GLIBC_2.36 getpeername F
++GLIBC_2.36 getpgid F
++GLIBC_2.36 getpgrp F
++GLIBC_2.36 getpid F
++GLIBC_2.36 getppid F
++GLIBC_2.36 getpriority F
++GLIBC_2.36 getprotobyname F
++GLIBC_2.36 getprotobyname_r F
++GLIBC_2.36 getprotobynumber F
++GLIBC_2.36 getprotobynumber_r F
++GLIBC_2.36 getprotoent F
++GLIBC_2.36 getprotoent_r F
++GLIBC_2.36 getpt F
++GLIBC_2.36 getpw F
++GLIBC_2.36 getpwent F
++GLIBC_2.36 getpwent_r F
++GLIBC_2.36 getpwnam F
++GLIBC_2.36 getpwnam_r F
++GLIBC_2.36 getpwuid F
++GLIBC_2.36 getpwuid_r F
++GLIBC_2.36 getrandom F
++GLIBC_2.36 getresgid F
++GLIBC_2.36 getresuid F
++GLIBC_2.36 getrlimit F
++GLIBC_2.36 getrlimit64 F
++GLIBC_2.36 getrpcbyname F
++GLIBC_2.36 getrpcbyname_r F
++GLIBC_2.36 getrpcbynumber F
++GLIBC_2.36 getrpcbynumber_r F
++GLIBC_2.36 getrpcent F
++GLIBC_2.36 getrpcent_r F
++GLIBC_2.36 getrusage F
++GLIBC_2.36 gets F
++GLIBC_2.36 getservbyname F
++GLIBC_2.36 getservbyname_r F
++GLIBC_2.36 getservbyport F
++GLIBC_2.36 getservbyport_r F
++GLIBC_2.36 getservent F
++GLIBC_2.36 getservent_r F
++GLIBC_2.36 getsgent F
++GLIBC_2.36 getsgent_r F
++GLIBC_2.36 getsgnam F
++GLIBC_2.36 getsgnam_r F
++GLIBC_2.36 getsid F
++GLIBC_2.36 getsockname F
++GLIBC_2.36 getsockopt F
++GLIBC_2.36 getsourcefilter F
++GLIBC_2.36 getspent F
++GLIBC_2.36 getspent_r F
++GLIBC_2.36 getspnam F
++GLIBC_2.36 getspnam_r F
++GLIBC_2.36 getsubopt F
++GLIBC_2.36 gettext F
++GLIBC_2.36 gettid F
++GLIBC_2.36 gettimeofday F
++GLIBC_2.36 getttyent F
++GLIBC_2.36 getttynam F
++GLIBC_2.36 getuid F
++GLIBC_2.36 getusershell F
++GLIBC_2.36 getutent F
++GLIBC_2.36 getutent_r F
++GLIBC_2.36 getutid F
++GLIBC_2.36 getutid_r F
++GLIBC_2.36 getutline F
++GLIBC_2.36 getutline_r F
++GLIBC_2.36 getutmp F
++GLIBC_2.36 getutmpx F
++GLIBC_2.36 getutxent F
++GLIBC_2.36 getutxid F
++GLIBC_2.36 getutxline F
++GLIBC_2.36 getw F
++GLIBC_2.36 getwc F
++GLIBC_2.36 getwc_unlocked F
++GLIBC_2.36 getwchar F
++GLIBC_2.36 getwchar_unlocked F
++GLIBC_2.36 getwd F
++GLIBC_2.36 getxattr F
++GLIBC_2.36 glob F
++GLIBC_2.36 glob64 F
++GLIBC_2.36 glob_pattern_p F
++GLIBC_2.36 globfree F
++GLIBC_2.36 globfree64 F
++GLIBC_2.36 gmtime F
++GLIBC_2.36 gmtime_r F
++GLIBC_2.36 gnu_dev_major F
++GLIBC_2.36 gnu_dev_makedev F
++GLIBC_2.36 gnu_dev_minor F
++GLIBC_2.36 gnu_get_libc_release F
++GLIBC_2.36 gnu_get_libc_version F
++GLIBC_2.36 grantpt F
++GLIBC_2.36 group_member F
++GLIBC_2.36 gsignal F
++GLIBC_2.36 gtty F
++GLIBC_2.36 h_errlist D 0x28
++GLIBC_2.36 h_nerr D 0x4
++GLIBC_2.36 hasmntopt F
++GLIBC_2.36 hcreate F
++GLIBC_2.36 hcreate_r F
++GLIBC_2.36 hdestroy F
++GLIBC_2.36 hdestroy_r F
++GLIBC_2.36 herror F
++GLIBC_2.36 hsearch F
++GLIBC_2.36 hsearch_r F
++GLIBC_2.36 hstrerror F
++GLIBC_2.36 htonl F
++GLIBC_2.36 htons F
++GLIBC_2.36 iconv F
++GLIBC_2.36 iconv_close F
++GLIBC_2.36 iconv_open F
++GLIBC_2.36 if_freenameindex F
++GLIBC_2.36 if_indextoname F
++GLIBC_2.36 if_nameindex F
++GLIBC_2.36 if_nametoindex F
++GLIBC_2.36 imaxabs F
++GLIBC_2.36 imaxdiv F
++GLIBC_2.36 in6addr_any D 0x10
++GLIBC_2.36 in6addr_loopback D 0x10
++GLIBC_2.36 index F
++GLIBC_2.36 inet6_opt_append F
++GLIBC_2.36 inet6_opt_find F
++GLIBC_2.36 inet6_opt_finish F
++GLIBC_2.36 inet6_opt_get_val F
++GLIBC_2.36 inet6_opt_init F
++GLIBC_2.36 inet6_opt_next F
++GLIBC_2.36 inet6_opt_set_val F
++GLIBC_2.36 inet6_option_alloc F
++GLIBC_2.36 inet6_option_append F
++GLIBC_2.36 inet6_option_find F
++GLIBC_2.36 inet6_option_init F
++GLIBC_2.36 inet6_option_next F
++GLIBC_2.36 inet6_option_space F
++GLIBC_2.36 inet6_rth_add F
++GLIBC_2.36 inet6_rth_getaddr F
++GLIBC_2.36 inet6_rth_init F
++GLIBC_2.36 inet6_rth_reverse F
++GLIBC_2.36 inet6_rth_segments F
++GLIBC_2.36 inet6_rth_space F
++GLIBC_2.36 inet_addr F
++GLIBC_2.36 inet_aton F
++GLIBC_2.36 inet_lnaof F
++GLIBC_2.36 inet_makeaddr F
++GLIBC_2.36 inet_netof F
++GLIBC_2.36 inet_network F
++GLIBC_2.36 inet_nsap_addr F
++GLIBC_2.36 inet_nsap_ntoa F
++GLIBC_2.36 inet_ntoa F
++GLIBC_2.36 inet_ntop F
++GLIBC_2.36 inet_pton F
++GLIBC_2.36 init_module F
++GLIBC_2.36 initgroups F
++GLIBC_2.36 initstate F
++GLIBC_2.36 initstate_r F
++GLIBC_2.36 innetgr F
++GLIBC_2.36 inotify_add_watch F
++GLIBC_2.36 inotify_init F
++GLIBC_2.36 inotify_init1 F
++GLIBC_2.36 inotify_rm_watch F
++GLIBC_2.36 insque F
++GLIBC_2.36 ioctl F
++GLIBC_2.36 iruserok F
++GLIBC_2.36 iruserok_af F
++GLIBC_2.36 isalnum F
++GLIBC_2.36 isalnum_l F
++GLIBC_2.36 isalpha F
++GLIBC_2.36 isalpha_l F
++GLIBC_2.36 isascii F
++GLIBC_2.36 isatty F
++GLIBC_2.36 isblank F
++GLIBC_2.36 isblank_l F
++GLIBC_2.36 iscntrl F
++GLIBC_2.36 iscntrl_l F
++GLIBC_2.36 isctype F
++GLIBC_2.36 isdigit F
++GLIBC_2.36 isdigit_l F
++GLIBC_2.36 isfdtype F
++GLIBC_2.36 isgraph F
++GLIBC_2.36 isgraph_l F
++GLIBC_2.36 isinf F
++GLIBC_2.36 isinff F
++GLIBC_2.36 isinfl F
++GLIBC_2.36 islower F
++GLIBC_2.36 islower_l F
++GLIBC_2.36 isnan F
++GLIBC_2.36 isnanf F
++GLIBC_2.36 isnanl F
++GLIBC_2.36 isprint F
++GLIBC_2.36 isprint_l F
++GLIBC_2.36 ispunct F
++GLIBC_2.36 ispunct_l F
++GLIBC_2.36 isspace F
++GLIBC_2.36 isspace_l F
++GLIBC_2.36 isupper F
++GLIBC_2.36 isupper_l F
++GLIBC_2.36 iswalnum F
++GLIBC_2.36 iswalnum_l F
++GLIBC_2.36 iswalpha F
++GLIBC_2.36 iswalpha_l F
++GLIBC_2.36 iswblank F
++GLIBC_2.36 iswblank_l F
++GLIBC_2.36 iswcntrl F
++GLIBC_2.36 iswcntrl_l F
++GLIBC_2.36 iswctype F
++GLIBC_2.36 iswctype_l F
++GLIBC_2.36 iswdigit F
++GLIBC_2.36 iswdigit_l F
++GLIBC_2.36 iswgraph F
++GLIBC_2.36 iswgraph_l F
++GLIBC_2.36 iswlower F
++GLIBC_2.36 iswlower_l F
++GLIBC_2.36 iswprint F
++GLIBC_2.36 iswprint_l F
++GLIBC_2.36 iswpunct F
++GLIBC_2.36 iswpunct_l F
++GLIBC_2.36 iswspace F
++GLIBC_2.36 iswspace_l F
++GLIBC_2.36 iswupper F
++GLIBC_2.36 iswupper_l F
++GLIBC_2.36 iswxdigit F
++GLIBC_2.36 iswxdigit_l F
++GLIBC_2.36 isxdigit F
++GLIBC_2.36 isxdigit_l F
++GLIBC_2.36 jrand48 F
++GLIBC_2.36 jrand48_r F
++GLIBC_2.36 kill F
++GLIBC_2.36 killpg F
++GLIBC_2.36 klogctl F
++GLIBC_2.36 l64a F
++GLIBC_2.36 labs F
++GLIBC_2.36 lchmod F
++GLIBC_2.36 lchown F
++GLIBC_2.36 lckpwdf F
++GLIBC_2.36 lcong48 F
++GLIBC_2.36 lcong48_r F
++GLIBC_2.36 ldexp F
++GLIBC_2.36 ldexpf F
++GLIBC_2.36 ldexpl F
++GLIBC_2.36 ldiv F
++GLIBC_2.36 lfind F
++GLIBC_2.36 lgetxattr F
++GLIBC_2.36 link F
++GLIBC_2.36 linkat F
++GLIBC_2.36 lio_listio F
++GLIBC_2.36 lio_listio64 F
++GLIBC_2.36 listen F
++GLIBC_2.36 listxattr F
++GLIBC_2.36 llabs F
++GLIBC_2.36 lldiv F
++GLIBC_2.36 llistxattr F
++GLIBC_2.36 localeconv F
++GLIBC_2.36 localtime F
++GLIBC_2.36 localtime_r F
++GLIBC_2.36 lockf F
++GLIBC_2.36 lockf64 F
++GLIBC_2.36 login F
++GLIBC_2.36 login_tty F
++GLIBC_2.36 logout F
++GLIBC_2.36 logwtmp F
++GLIBC_2.36 longjmp F
++GLIBC_2.36 lrand48 F
++GLIBC_2.36 lrand48_r F
++GLIBC_2.36 lremovexattr F
++GLIBC_2.36 lsearch F
++GLIBC_2.36 lseek F
++GLIBC_2.36 lseek64 F
++GLIBC_2.36 lsetxattr F
++GLIBC_2.36 lstat F
++GLIBC_2.36 lstat64 F
++GLIBC_2.36 lutimes F
++GLIBC_2.36 madvise F
++GLIBC_2.36 makecontext F
++GLIBC_2.36 mallinfo F
++GLIBC_2.36 mallinfo2 F
++GLIBC_2.36 malloc F
++GLIBC_2.36 malloc_info F
++GLIBC_2.36 malloc_stats F
++GLIBC_2.36 malloc_trim F
++GLIBC_2.36 malloc_usable_size F
++GLIBC_2.36 mallopt F
++GLIBC_2.36 mblen F
++GLIBC_2.36 mbrlen F
++GLIBC_2.36 mbrtoc16 F
++GLIBC_2.36 mbrtoc32 F
++GLIBC_2.36 mbrtowc F
++GLIBC_2.36 mbsinit F
++GLIBC_2.36 mbsnrtowcs F
++GLIBC_2.36 mbsrtowcs F
++GLIBC_2.36 mbstowcs F
++GLIBC_2.36 mbtowc F
++GLIBC_2.36 mcheck F
++GLIBC_2.36 mcheck_check_all F
++GLIBC_2.36 mcheck_pedantic F
++GLIBC_2.36 memalign F
++GLIBC_2.36 memccpy F
++GLIBC_2.36 memchr F
++GLIBC_2.36 memcmp F
++GLIBC_2.36 memcpy F
++GLIBC_2.36 memfd_create F
++GLIBC_2.36 memfrob F
++GLIBC_2.36 memmem F
++GLIBC_2.36 memmove F
++GLIBC_2.36 mempcpy F
++GLIBC_2.36 memrchr F
++GLIBC_2.36 memset F
++GLIBC_2.36 mincore F
++GLIBC_2.36 mkdir F
++GLIBC_2.36 mkdirat F
++GLIBC_2.36 mkdtemp F
++GLIBC_2.36 mkfifo F
++GLIBC_2.36 mkfifoat F
++GLIBC_2.36 mknod F
++GLIBC_2.36 mknodat F
++GLIBC_2.36 mkostemp F
++GLIBC_2.36 mkostemp64 F
++GLIBC_2.36 mkostemps F
++GLIBC_2.36 mkostemps64 F
++GLIBC_2.36 mkstemp F
++GLIBC_2.36 mkstemp64 F
++GLIBC_2.36 mkstemps F
++GLIBC_2.36 mkstemps64 F
++GLIBC_2.36 mktemp F
++GLIBC_2.36 mktime F
++GLIBC_2.36 mlock F
++GLIBC_2.36 mlock2 F
++GLIBC_2.36 mlockall F
++GLIBC_2.36 mmap F
++GLIBC_2.36 mmap64 F
++GLIBC_2.36 modf F
++GLIBC_2.36 modff F
++GLIBC_2.36 modfl F
++GLIBC_2.36 moncontrol F
++GLIBC_2.36 monstartup F
++GLIBC_2.36 mount F
++GLIBC_2.36 mprobe F
++GLIBC_2.36 mprotect F
++GLIBC_2.36 mq_close F
++GLIBC_2.36 mq_getattr F
++GLIBC_2.36 mq_notify F
++GLIBC_2.36 mq_open F
++GLIBC_2.36 mq_receive F
++GLIBC_2.36 mq_send F
++GLIBC_2.36 mq_setattr F
++GLIBC_2.36 mq_timedreceive F
++GLIBC_2.36 mq_timedsend F
++GLIBC_2.36 mq_unlink F
++GLIBC_2.36 mrand48 F
++GLIBC_2.36 mrand48_r F
++GLIBC_2.36 mremap F
++GLIBC_2.36 msgctl F
++GLIBC_2.36 msgget F
++GLIBC_2.36 msgrcv F
++GLIBC_2.36 msgsnd F
++GLIBC_2.36 msync F
++GLIBC_2.36 mtrace F
++GLIBC_2.36 mtx_destroy F
++GLIBC_2.36 mtx_init F
++GLIBC_2.36 mtx_lock F
++GLIBC_2.36 mtx_timedlock F
++GLIBC_2.36 mtx_trylock F
++GLIBC_2.36 mtx_unlock F
++GLIBC_2.36 munlock F
++GLIBC_2.36 munlockall F
++GLIBC_2.36 munmap F
++GLIBC_2.36 muntrace F
++GLIBC_2.36 name_to_handle_at F
++GLIBC_2.36 nanosleep F
++GLIBC_2.36 newlocale F
++GLIBC_2.36 nftw F
++GLIBC_2.36 nftw64 F
++GLIBC_2.36 ngettext F
++GLIBC_2.36 nice F
++GLIBC_2.36 nl_langinfo F
++GLIBC_2.36 nl_langinfo_l F
++GLIBC_2.36 nrand48 F
++GLIBC_2.36 nrand48_r F
++GLIBC_2.36 ns_name_compress F
++GLIBC_2.36 ns_name_ntop F
++GLIBC_2.36 ns_name_pack F
++GLIBC_2.36 ns_name_pton F
++GLIBC_2.36 ns_name_skip F
++GLIBC_2.36 ns_name_uncompress F
++GLIBC_2.36 ns_name_unpack F
++GLIBC_2.36 ntohl F
++GLIBC_2.36 ntohs F
++GLIBC_2.36 ntp_adjtime F
++GLIBC_2.36 ntp_gettime F
++GLIBC_2.36 ntp_gettimex F
++GLIBC_2.36 obstack_alloc_failed_handler D 0x8
++GLIBC_2.36 obstack_exit_failure D 0x4
++GLIBC_2.36 obstack_free F
++GLIBC_2.36 obstack_printf F
++GLIBC_2.36 obstack_vprintf F
++GLIBC_2.36 on_exit F
++GLIBC_2.36 open F
++GLIBC_2.36 open64 F
++GLIBC_2.36 open_by_handle_at F
++GLIBC_2.36 open_memstream F
++GLIBC_2.36 open_wmemstream F
++GLIBC_2.36 openat F
++GLIBC_2.36 openat64 F
++GLIBC_2.36 opendir F
++GLIBC_2.36 openlog F
++GLIBC_2.36 openpty F
++GLIBC_2.36 optarg D 0x8
++GLIBC_2.36 opterr D 0x4
++GLIBC_2.36 optind D 0x4
++GLIBC_2.36 optopt D 0x4
++GLIBC_2.36 parse_printf_format F
++GLIBC_2.36 pathconf F
++GLIBC_2.36 pause F
++GLIBC_2.36 pclose F
++GLIBC_2.36 perror F
++GLIBC_2.36 personality F
++GLIBC_2.36 pipe F
++GLIBC_2.36 pipe2 F
++GLIBC_2.36 pivot_root F
++GLIBC_2.36 pkey_alloc F
++GLIBC_2.36 pkey_free F
++GLIBC_2.36 pkey_get F
++GLIBC_2.36 pkey_mprotect F
++GLIBC_2.36 pkey_set F
++GLIBC_2.36 poll F
++GLIBC_2.36 popen F
++GLIBC_2.36 posix_fadvise F
++GLIBC_2.36 posix_fadvise64 F
++GLIBC_2.36 posix_fallocate F
++GLIBC_2.36 posix_fallocate64 F
++GLIBC_2.36 posix_madvise F
++GLIBC_2.36 posix_memalign F
++GLIBC_2.36 posix_openpt F
++GLIBC_2.36 posix_spawn F
++GLIBC_2.36 posix_spawn_file_actions_addchdir_np F
++GLIBC_2.36 posix_spawn_file_actions_addclose F
++GLIBC_2.36 posix_spawn_file_actions_addclosefrom_np F
++GLIBC_2.36 posix_spawn_file_actions_adddup2 F
++GLIBC_2.36 posix_spawn_file_actions_addfchdir_np F
++GLIBC_2.36 posix_spawn_file_actions_addopen F
++GLIBC_2.36 posix_spawn_file_actions_destroy F
++GLIBC_2.36 posix_spawn_file_actions_init F
++GLIBC_2.36 posix_spawnattr_destroy F
++GLIBC_2.36 posix_spawnattr_getflags F
++GLIBC_2.36 posix_spawnattr_getpgroup F
++GLIBC_2.36 posix_spawnattr_getschedparam F
++GLIBC_2.36 posix_spawnattr_getschedpolicy F
++GLIBC_2.36 posix_spawnattr_getsigdefault F
++GLIBC_2.36 posix_spawnattr_getsigmask F
++GLIBC_2.36 posix_spawnattr_init F
++GLIBC_2.36 posix_spawnattr_setflags F
++GLIBC_2.36 posix_spawnattr_setpgroup F
++GLIBC_2.36 posix_spawnattr_setschedparam F
++GLIBC_2.36 posix_spawnattr_setschedpolicy F
++GLIBC_2.36 posix_spawnattr_setsigdefault F
++GLIBC_2.36 posix_spawnattr_setsigmask F
++GLIBC_2.36 posix_spawnp F
++GLIBC_2.36 ppoll F
++GLIBC_2.36 prctl F
++GLIBC_2.36 pread F
++GLIBC_2.36 pread64 F
++GLIBC_2.36 preadv F
++GLIBC_2.36 preadv2 F
++GLIBC_2.36 preadv64 F
++GLIBC_2.36 preadv64v2 F
++GLIBC_2.36 printf F
++GLIBC_2.36 printf_size F
++GLIBC_2.36 printf_size_info F
++GLIBC_2.36 prlimit F
++GLIBC_2.36 prlimit64 F
++GLIBC_2.36 process_vm_readv F
++GLIBC_2.36 process_vm_writev F
++GLIBC_2.36 profil F
++GLIBC_2.36 program_invocation_name D 0x8
++GLIBC_2.36 program_invocation_short_name D 0x8
++GLIBC_2.36 pselect F
++GLIBC_2.36 psiginfo F
++GLIBC_2.36 psignal F
++GLIBC_2.36 pthread_attr_destroy F
++GLIBC_2.36 pthread_attr_getaffinity_np F
++GLIBC_2.36 pthread_attr_getdetachstate F
++GLIBC_2.36 pthread_attr_getguardsize F
++GLIBC_2.36 pthread_attr_getinheritsched F
++GLIBC_2.36 pthread_attr_getschedparam F
++GLIBC_2.36 pthread_attr_getschedpolicy F
++GLIBC_2.36 pthread_attr_getscope F
++GLIBC_2.36 pthread_attr_getsigmask_np F
++GLIBC_2.36 pthread_attr_getstack F
++GLIBC_2.36 pthread_attr_getstackaddr F
++GLIBC_2.36 pthread_attr_getstacksize F
++GLIBC_2.36 pthread_attr_init F
++GLIBC_2.36 pthread_attr_setaffinity_np F
++GLIBC_2.36 pthread_attr_setdetachstate F
++GLIBC_2.36 pthread_attr_setguardsize F
++GLIBC_2.36 pthread_attr_setinheritsched F
++GLIBC_2.36 pthread_attr_setschedparam F
++GLIBC_2.36 pthread_attr_setschedpolicy F
++GLIBC_2.36 pthread_attr_setscope F
++GLIBC_2.36 pthread_attr_setsigmask_np F
++GLIBC_2.36 pthread_attr_setstack F
++GLIBC_2.36 pthread_attr_setstackaddr F
++GLIBC_2.36 pthread_attr_setstacksize F
++GLIBC_2.36 pthread_barrier_destroy F
++GLIBC_2.36 pthread_barrier_init F
++GLIBC_2.36 pthread_barrier_wait F
++GLIBC_2.36 pthread_barrierattr_destroy F
++GLIBC_2.36 pthread_barrierattr_getpshared F
++GLIBC_2.36 pthread_barrierattr_init F
++GLIBC_2.36 pthread_barrierattr_setpshared F
++GLIBC_2.36 pthread_cancel F
++GLIBC_2.36 pthread_clockjoin_np F
++GLIBC_2.36 pthread_cond_broadcast F
++GLIBC_2.36 pthread_cond_clockwait F
++GLIBC_2.36 pthread_cond_destroy F
++GLIBC_2.36 pthread_cond_init F
++GLIBC_2.36 pthread_cond_signal F
++GLIBC_2.36 pthread_cond_timedwait F
++GLIBC_2.36 pthread_cond_wait F
++GLIBC_2.36 pthread_condattr_destroy F
++GLIBC_2.36 pthread_condattr_getclock F
++GLIBC_2.36 pthread_condattr_getpshared F
++GLIBC_2.36 pthread_condattr_init F
++GLIBC_2.36 pthread_condattr_setclock F
++GLIBC_2.36 pthread_condattr_setpshared F
++GLIBC_2.36 pthread_create F
++GLIBC_2.36 pthread_detach F
++GLIBC_2.36 pthread_equal F
++GLIBC_2.36 pthread_exit F
++GLIBC_2.36 pthread_getaffinity_np F
++GLIBC_2.36 pthread_getattr_default_np F
++GLIBC_2.36 pthread_getattr_np F
++GLIBC_2.36 pthread_getconcurrency F
++GLIBC_2.36 pthread_getcpuclockid F
++GLIBC_2.36 pthread_getname_np F
++GLIBC_2.36 pthread_getschedparam F
++GLIBC_2.36 pthread_getspecific F
++GLIBC_2.36 pthread_join F
++GLIBC_2.36 pthread_key_create F
++GLIBC_2.36 pthread_key_delete F
++GLIBC_2.36 pthread_kill F
++GLIBC_2.36 pthread_mutex_clocklock F
++GLIBC_2.36 pthread_mutex_consistent F
++GLIBC_2.36 pthread_mutex_destroy F
++GLIBC_2.36 pthread_mutex_getprioceiling F
++GLIBC_2.36 pthread_mutex_init F
++GLIBC_2.36 pthread_mutex_lock F
++GLIBC_2.36 pthread_mutex_setprioceiling F
++GLIBC_2.36 pthread_mutex_timedlock F
++GLIBC_2.36 pthread_mutex_trylock F
++GLIBC_2.36 pthread_mutex_unlock F
++GLIBC_2.36 pthread_mutexattr_destroy F
++GLIBC_2.36 pthread_mutexattr_getprioceiling F
++GLIBC_2.36 pthread_mutexattr_getprotocol F
++GLIBC_2.36 pthread_mutexattr_getpshared F
++GLIBC_2.36 pthread_mutexattr_getrobust F
++GLIBC_2.36 pthread_mutexattr_gettype F
++GLIBC_2.36 pthread_mutexattr_init F
++GLIBC_2.36 pthread_mutexattr_setprioceiling F
++GLIBC_2.36 pthread_mutexattr_setprotocol F
++GLIBC_2.36 pthread_mutexattr_setpshared F
++GLIBC_2.36 pthread_mutexattr_setrobust F
++GLIBC_2.36 pthread_mutexattr_settype F
++GLIBC_2.36 pthread_once F
++GLIBC_2.36 pthread_rwlock_clockrdlock F
++GLIBC_2.36 pthread_rwlock_clockwrlock F
++GLIBC_2.36 pthread_rwlock_destroy F
++GLIBC_2.36 pthread_rwlock_init F
++GLIBC_2.36 pthread_rwlock_rdlock F
++GLIBC_2.36 pthread_rwlock_timedrdlock F
++GLIBC_2.36 pthread_rwlock_timedwrlock F
++GLIBC_2.36 pthread_rwlock_tryrdlock F
++GLIBC_2.36 pthread_rwlock_trywrlock F
++GLIBC_2.36 pthread_rwlock_unlock F
++GLIBC_2.36 pthread_rwlock_wrlock F
++GLIBC_2.36 pthread_rwlockattr_destroy F
++GLIBC_2.36 pthread_rwlockattr_getkind_np F
++GLIBC_2.36 pthread_rwlockattr_getpshared F
++GLIBC_2.36 pthread_rwlockattr_init F
++GLIBC_2.36 pthread_rwlockattr_setkind_np F
++GLIBC_2.36 pthread_rwlockattr_setpshared F
++GLIBC_2.36 pthread_self F
++GLIBC_2.36 pthread_setaffinity_np F
++GLIBC_2.36 pthread_setattr_default_np F
++GLIBC_2.36 pthread_setcancelstate F
++GLIBC_2.36 pthread_setcanceltype F
++GLIBC_2.36 pthread_setconcurrency F
++GLIBC_2.36 pthread_setname_np F
++GLIBC_2.36 pthread_setschedparam F
++GLIBC_2.36 pthread_setschedprio F
++GLIBC_2.36 pthread_setspecific F
++GLIBC_2.36 pthread_sigmask F
++GLIBC_2.36 pthread_sigqueue F
++GLIBC_2.36 pthread_spin_destroy F
++GLIBC_2.36 pthread_spin_init F
++GLIBC_2.36 pthread_spin_lock F
++GLIBC_2.36 pthread_spin_trylock F
++GLIBC_2.36 pthread_spin_unlock F
++GLIBC_2.36 pthread_testcancel F
++GLIBC_2.36 pthread_timedjoin_np F
++GLIBC_2.36 pthread_tryjoin_np F
++GLIBC_2.36 ptrace F
++GLIBC_2.36 ptsname F
++GLIBC_2.36 ptsname_r F
++GLIBC_2.36 putc F
++GLIBC_2.36 putc_unlocked F
++GLIBC_2.36 putchar F
++GLIBC_2.36 putchar_unlocked F
++GLIBC_2.36 putenv F
++GLIBC_2.36 putgrent F
++GLIBC_2.36 putpwent F
++GLIBC_2.36 puts F
++GLIBC_2.36 putsgent F
++GLIBC_2.36 putspent F
++GLIBC_2.36 pututline F
++GLIBC_2.36 pututxline F
++GLIBC_2.36 putw F
++GLIBC_2.36 putwc F
++GLIBC_2.36 putwc_unlocked F
++GLIBC_2.36 putwchar F
++GLIBC_2.36 putwchar_unlocked F
++GLIBC_2.36 pvalloc F
++GLIBC_2.36 pwrite F
++GLIBC_2.36 pwrite64 F
++GLIBC_2.36 pwritev F
++GLIBC_2.36 pwritev2 F
++GLIBC_2.36 pwritev64 F
++GLIBC_2.36 pwritev64v2 F
++GLIBC_2.36 qecvt F
++GLIBC_2.36 qecvt_r F
++GLIBC_2.36 qfcvt F
++GLIBC_2.36 qfcvt_r F
++GLIBC_2.36 qgcvt F
++GLIBC_2.36 qsort F
++GLIBC_2.36 qsort_r F
++GLIBC_2.36 quick_exit F
++GLIBC_2.36 quotactl F
++GLIBC_2.36 raise F
++GLIBC_2.36 rand F
++GLIBC_2.36 rand_r F
++GLIBC_2.36 random F
++GLIBC_2.36 random_r F
++GLIBC_2.36 rawmemchr F
++GLIBC_2.36 rcmd F
++GLIBC_2.36 rcmd_af F
++GLIBC_2.36 re_comp F
++GLIBC_2.36 re_compile_fastmap F
++GLIBC_2.36 re_compile_pattern F
++GLIBC_2.36 re_exec F
++GLIBC_2.36 re_match F
++GLIBC_2.36 re_match_2 F
++GLIBC_2.36 re_search F
++GLIBC_2.36 re_search_2 F
++GLIBC_2.36 re_set_registers F
++GLIBC_2.36 re_set_syntax F
++GLIBC_2.36 re_syntax_options D 0x8
++GLIBC_2.36 read F
++GLIBC_2.36 readahead F
++GLIBC_2.36 readdir F
++GLIBC_2.36 readdir64 F
++GLIBC_2.36 readdir64_r F
++GLIBC_2.36 readdir_r F
++GLIBC_2.36 readlink F
++GLIBC_2.36 readlinkat F
++GLIBC_2.36 readv F
++GLIBC_2.36 realloc F
++GLIBC_2.36 reallocarray F
++GLIBC_2.36 realpath F
++GLIBC_2.36 reboot F
++GLIBC_2.36 recv F
++GLIBC_2.36 recvfrom F
++GLIBC_2.36 recvmmsg F
++GLIBC_2.36 recvmsg F
++GLIBC_2.36 regcomp F
++GLIBC_2.36 regerror F
++GLIBC_2.36 regexec F
++GLIBC_2.36 regfree F
++GLIBC_2.36 register_printf_function F
++GLIBC_2.36 register_printf_modifier F
++GLIBC_2.36 register_printf_specifier F
++GLIBC_2.36 register_printf_type F
++GLIBC_2.36 remap_file_pages F
++GLIBC_2.36 remove F
++GLIBC_2.36 removexattr F
++GLIBC_2.36 remque F
++GLIBC_2.36 rename F
++GLIBC_2.36 renameat F
++GLIBC_2.36 renameat2 F
++GLIBC_2.36 res_dnok F
++GLIBC_2.36 res_hnok F
++GLIBC_2.36 res_mailok F
++GLIBC_2.36 res_mkquery F
++GLIBC_2.36 res_nmkquery F
++GLIBC_2.36 res_nquery F
++GLIBC_2.36 res_nquerydomain F
++GLIBC_2.36 res_nsearch F
++GLIBC_2.36 res_nsend F
++GLIBC_2.36 res_ownok F
++GLIBC_2.36 res_query F
++GLIBC_2.36 res_querydomain F
++GLIBC_2.36 res_search F
++GLIBC_2.36 res_send F
++GLIBC_2.36 revoke F
++GLIBC_2.36 rewind F
++GLIBC_2.36 rewinddir F
++GLIBC_2.36 rexec F
++GLIBC_2.36 rexec_af F
++GLIBC_2.36 rexecoptions D 0x4
++GLIBC_2.36 rindex F
++GLIBC_2.36 rmdir F
++GLIBC_2.36 rpmatch F
++GLIBC_2.36 rresvport F
++GLIBC_2.36 rresvport_af F
++GLIBC_2.36 ruserok F
++GLIBC_2.36 ruserok_af F
++GLIBC_2.36 ruserpass F
++GLIBC_2.36 sbrk F
++GLIBC_2.36 scalbn F
++GLIBC_2.36 scalbnf F
++GLIBC_2.36 scalbnl F
++GLIBC_2.36 scandir F
++GLIBC_2.36 scandir64 F
++GLIBC_2.36 scandirat F
++GLIBC_2.36 scandirat64 F
++GLIBC_2.36 scanf F
++GLIBC_2.36 sched_get_priority_max F
++GLIBC_2.36 sched_get_priority_min F
++GLIBC_2.36 sched_getaffinity F
++GLIBC_2.36 sched_getcpu F
++GLIBC_2.36 sched_getparam F
++GLIBC_2.36 sched_getscheduler F
++GLIBC_2.36 sched_rr_get_interval F
++GLIBC_2.36 sched_setaffinity F
++GLIBC_2.36 sched_setparam F
++GLIBC_2.36 sched_setscheduler F
++GLIBC_2.36 sched_yield F
++GLIBC_2.36 secure_getenv F
++GLIBC_2.36 seed48 F
++GLIBC_2.36 seed48_r F
++GLIBC_2.36 seekdir F
++GLIBC_2.36 select F
++GLIBC_2.36 sem_clockwait F
++GLIBC_2.36 sem_close F
++GLIBC_2.36 sem_destroy F
++GLIBC_2.36 sem_getvalue F
++GLIBC_2.36 sem_init F
++GLIBC_2.36 sem_open F
++GLIBC_2.36 sem_post F
++GLIBC_2.36 sem_timedwait F
++GLIBC_2.36 sem_trywait F
++GLIBC_2.36 sem_unlink F
++GLIBC_2.36 sem_wait F
++GLIBC_2.36 semctl F
++GLIBC_2.36 semget F
++GLIBC_2.36 semop F
++GLIBC_2.36 semtimedop F
++GLIBC_2.36 send F
++GLIBC_2.36 sendfile F
++GLIBC_2.36 sendfile64 F
++GLIBC_2.36 sendmmsg F
++GLIBC_2.36 sendmsg F
++GLIBC_2.36 sendto F
++GLIBC_2.36 setaliasent F
++GLIBC_2.36 setbuf F
++GLIBC_2.36 setbuffer F
++GLIBC_2.36 setcontext F
++GLIBC_2.36 setdomainname F
++GLIBC_2.36 setegid F
++GLIBC_2.36 setenv F
++GLIBC_2.36 seteuid F
++GLIBC_2.36 setfsent F
++GLIBC_2.36 setfsgid F
++GLIBC_2.36 setfsuid F
++GLIBC_2.36 setgid F
++GLIBC_2.36 setgrent F
++GLIBC_2.36 setgroups F
++GLIBC_2.36 sethostent F
++GLIBC_2.36 sethostid F
++GLIBC_2.36 sethostname F
++GLIBC_2.36 setipv4sourcefilter F
++GLIBC_2.36 setitimer F
++GLIBC_2.36 setjmp F
++GLIBC_2.36 setlinebuf F
++GLIBC_2.36 setlocale F
++GLIBC_2.36 setlogin F
++GLIBC_2.36 setlogmask F
++GLIBC_2.36 setmntent F
++GLIBC_2.36 setnetent F
++GLIBC_2.36 setnetgrent F
++GLIBC_2.36 setns F
++GLIBC_2.36 setpgid F
++GLIBC_2.36 setpgrp F
++GLIBC_2.36 setpriority F
++GLIBC_2.36 setprotoent F
++GLIBC_2.36 setpwent F
++GLIBC_2.36 setregid F
++GLIBC_2.36 setresgid F
++GLIBC_2.36 setresuid F
++GLIBC_2.36 setreuid F
++GLIBC_2.36 setrlimit F
++GLIBC_2.36 setrlimit64 F
++GLIBC_2.36 setrpcent F
++GLIBC_2.36 setservent F
++GLIBC_2.36 setsgent F
++GLIBC_2.36 setsid F
++GLIBC_2.36 setsockopt F
++GLIBC_2.36 setsourcefilter F
++GLIBC_2.36 setspent F
++GLIBC_2.36 setstate F
++GLIBC_2.36 setstate_r F
++GLIBC_2.36 settimeofday F
++GLIBC_2.36 setttyent F
++GLIBC_2.36 setuid F
++GLIBC_2.36 setusershell F
++GLIBC_2.36 setutent F
++GLIBC_2.36 setutxent F
++GLIBC_2.36 setvbuf F
++GLIBC_2.36 setxattr F
++GLIBC_2.36 sgetsgent F
++GLIBC_2.36 sgetsgent_r F
++GLIBC_2.36 sgetspent F
++GLIBC_2.36 sgetspent_r F
++GLIBC_2.36 shm_open F
++GLIBC_2.36 shm_unlink F
++GLIBC_2.36 shmat F
++GLIBC_2.36 shmctl F
++GLIBC_2.36 shmdt F
++GLIBC_2.36 shmget F
++GLIBC_2.36 shutdown F
++GLIBC_2.36 sigabbrev_np F
++GLIBC_2.36 sigaction F
++GLIBC_2.36 sigaddset F
++GLIBC_2.36 sigaltstack F
++GLIBC_2.36 sigandset F
++GLIBC_2.36 sigblock F
++GLIBC_2.36 sigdelset F
++GLIBC_2.36 sigdescr_np F
++GLIBC_2.36 sigemptyset F
++GLIBC_2.36 sigfillset F
++GLIBC_2.36 siggetmask F
++GLIBC_2.36 sighold F
++GLIBC_2.36 sigignore F
++GLIBC_2.36 siginterrupt F
++GLIBC_2.36 sigisemptyset F
++GLIBC_2.36 sigismember F
++GLIBC_2.36 siglongjmp F
++GLIBC_2.36 signal F
++GLIBC_2.36 signalfd F
++GLIBC_2.36 sigorset F
++GLIBC_2.36 sigpause F
++GLIBC_2.36 sigpending F
++GLIBC_2.36 sigprocmask F
++GLIBC_2.36 sigqueue F
++GLIBC_2.36 sigrelse F
++GLIBC_2.36 sigreturn F
++GLIBC_2.36 sigset F
++GLIBC_2.36 sigsetmask F
++GLIBC_2.36 sigstack F
++GLIBC_2.36 sigsuspend F
++GLIBC_2.36 sigtimedwait F
++GLIBC_2.36 sigwait F
++GLIBC_2.36 sigwaitinfo F
++GLIBC_2.36 sleep F
++GLIBC_2.36 snprintf F
++GLIBC_2.36 sockatmark F
++GLIBC_2.36 socket F
++GLIBC_2.36 socketpair F
++GLIBC_2.36 splice F
++GLIBC_2.36 sprintf F
++GLIBC_2.36 sprofil F
++GLIBC_2.36 srand F
++GLIBC_2.36 srand48 F
++GLIBC_2.36 srand48_r F
++GLIBC_2.36 srandom F
++GLIBC_2.36 srandom_r F
++GLIBC_2.36 sscanf F
++GLIBC_2.36 ssignal F
++GLIBC_2.36 stat F
++GLIBC_2.36 stat64 F
++GLIBC_2.36 statfs F
++GLIBC_2.36 statfs64 F
++GLIBC_2.36 statvfs F
++GLIBC_2.36 statvfs64 F
++GLIBC_2.36 statx F
++GLIBC_2.36 stderr D 0x8
++GLIBC_2.36 stdin D 0x8
++GLIBC_2.36 stdout D 0x8
++GLIBC_2.36 stpcpy F
++GLIBC_2.36 stpncpy F
++GLIBC_2.36 strcasecmp F
++GLIBC_2.36 strcasecmp_l F
++GLIBC_2.36 strcasestr F
++GLIBC_2.36 strcat F
++GLIBC_2.36 strchr F
++GLIBC_2.36 strchrnul F
++GLIBC_2.36 strcmp F
++GLIBC_2.36 strcoll F
++GLIBC_2.36 strcoll_l F
++GLIBC_2.36 strcpy F
++GLIBC_2.36 strcspn F
++GLIBC_2.36 strdup F
++GLIBC_2.36 strerror F
++GLIBC_2.36 strerror_l F
++GLIBC_2.36 strerror_r F
++GLIBC_2.36 strerrordesc_np F
++GLIBC_2.36 strerrorname_np F
++GLIBC_2.36 strfmon F
++GLIBC_2.36 strfmon_l F
++GLIBC_2.36 strfromd F
++GLIBC_2.36 strfromf F
++GLIBC_2.36 strfromf128 F
++GLIBC_2.36 strfromf32 F
++GLIBC_2.36 strfromf32x F
++GLIBC_2.36 strfromf64 F
++GLIBC_2.36 strfromf64x F
++GLIBC_2.36 strfroml F
++GLIBC_2.36 strfry F
++GLIBC_2.36 strftime F
++GLIBC_2.36 strftime_l F
++GLIBC_2.36 strlen F
++GLIBC_2.36 strncasecmp F
++GLIBC_2.36 strncasecmp_l F
++GLIBC_2.36 strncat F
++GLIBC_2.36 strncmp F
++GLIBC_2.36 strncpy F
++GLIBC_2.36 strndup F
++GLIBC_2.36 strnlen F
++GLIBC_2.36 strpbrk F
++GLIBC_2.36 strptime F
++GLIBC_2.36 strptime_l F
++GLIBC_2.36 strrchr F
++GLIBC_2.36 strsep F
++GLIBC_2.36 strsignal F
++GLIBC_2.36 strspn F
++GLIBC_2.36 strstr F
++GLIBC_2.36 strtod F
++GLIBC_2.36 strtod_l F
++GLIBC_2.36 strtof F
++GLIBC_2.36 strtof128 F
++GLIBC_2.36 strtof128_l F
++GLIBC_2.36 strtof32 F
++GLIBC_2.36 strtof32_l F
++GLIBC_2.36 strtof32x F
++GLIBC_2.36 strtof32x_l F
++GLIBC_2.36 strtof64 F
++GLIBC_2.36 strtof64_l F
++GLIBC_2.36 strtof64x F
++GLIBC_2.36 strtof64x_l F
++GLIBC_2.36 strtof_l F
++GLIBC_2.36 strtoimax F
++GLIBC_2.36 strtok F
++GLIBC_2.36 strtok_r F
++GLIBC_2.36 strtol F
++GLIBC_2.36 strtol_l F
++GLIBC_2.36 strtold F
++GLIBC_2.36 strtold_l F
++GLIBC_2.36 strtoll F
++GLIBC_2.36 strtoll_l F
++GLIBC_2.36 strtoq F
++GLIBC_2.36 strtoul F
++GLIBC_2.36 strtoul_l F
++GLIBC_2.36 strtoull F
++GLIBC_2.36 strtoull_l F
++GLIBC_2.36 strtoumax F
++GLIBC_2.36 strtouq F
++GLIBC_2.36 strverscmp F
++GLIBC_2.36 strxfrm F
++GLIBC_2.36 strxfrm_l F
++GLIBC_2.36 stty F
++GLIBC_2.36 swab F
++GLIBC_2.36 swapcontext F
++GLIBC_2.36 swapoff F
++GLIBC_2.36 swapon F
++GLIBC_2.36 swprintf F
++GLIBC_2.36 swscanf F
++GLIBC_2.36 symlink F
++GLIBC_2.36 symlinkat F
++GLIBC_2.36 sync F
++GLIBC_2.36 sync_file_range F
++GLIBC_2.36 syncfs F
++GLIBC_2.36 syscall F
++GLIBC_2.36 sysconf F
++GLIBC_2.36 sysinfo F
++GLIBC_2.36 syslog F
++GLIBC_2.36 system F
++GLIBC_2.36 sysv_signal F
++GLIBC_2.36 tcdrain F
++GLIBC_2.36 tcflow F
++GLIBC_2.36 tcflush F
++GLIBC_2.36 tcgetattr F
++GLIBC_2.36 tcgetpgrp F
++GLIBC_2.36 tcgetsid F
++GLIBC_2.36 tcsendbreak F
++GLIBC_2.36 tcsetattr F
++GLIBC_2.36 tcsetpgrp F
++GLIBC_2.36 tdelete F
++GLIBC_2.36 tdestroy F
++GLIBC_2.36 tee F
++GLIBC_2.36 telldir F
++GLIBC_2.36 tempnam F
++GLIBC_2.36 textdomain F
++GLIBC_2.36 tfind F
++GLIBC_2.36 tgkill F
++GLIBC_2.36 thrd_create F
++GLIBC_2.36 thrd_current F
++GLIBC_2.36 thrd_detach F
++GLIBC_2.36 thrd_equal F
++GLIBC_2.36 thrd_exit F
++GLIBC_2.36 thrd_join F
++GLIBC_2.36 thrd_sleep F
++GLIBC_2.36 thrd_yield F
++GLIBC_2.36 time F
++GLIBC_2.36 timegm F
++GLIBC_2.36 timelocal F
++GLIBC_2.36 timer_create F
++GLIBC_2.36 timer_delete F
++GLIBC_2.36 timer_getoverrun F
++GLIBC_2.36 timer_gettime F
++GLIBC_2.36 timer_settime F
++GLIBC_2.36 timerfd_create F
++GLIBC_2.36 timerfd_gettime F
++GLIBC_2.36 timerfd_settime F
++GLIBC_2.36 times F
++GLIBC_2.36 timespec_get F
++GLIBC_2.36 timespec_getres F
++GLIBC_2.36 timezone D 0x8
++GLIBC_2.36 tmpfile F
++GLIBC_2.36 tmpfile64 F
++GLIBC_2.36 tmpnam F
++GLIBC_2.36 tmpnam_r F
++GLIBC_2.36 toascii F
++GLIBC_2.36 tolower F
++GLIBC_2.36 tolower_l F
++GLIBC_2.36 toupper F
++GLIBC_2.36 toupper_l F
++GLIBC_2.36 towctrans F
++GLIBC_2.36 towctrans_l F
++GLIBC_2.36 towlower F
++GLIBC_2.36 towlower_l F
++GLIBC_2.36 towupper F
++GLIBC_2.36 towupper_l F
++GLIBC_2.36 truncate F
++GLIBC_2.36 truncate64 F
++GLIBC_2.36 tsearch F
++GLIBC_2.36 tss_create F
++GLIBC_2.36 tss_delete F
++GLIBC_2.36 tss_get F
++GLIBC_2.36 tss_set F
++GLIBC_2.36 ttyname F
++GLIBC_2.36 ttyname_r F
++GLIBC_2.36 ttyslot F
++GLIBC_2.36 twalk F
++GLIBC_2.36 twalk_r F
++GLIBC_2.36 tzname D 0x10
++GLIBC_2.36 tzset F
++GLIBC_2.36 ualarm F
++GLIBC_2.36 ulckpwdf F
++GLIBC_2.36 ulimit F
++GLIBC_2.36 umask F
++GLIBC_2.36 umount F
++GLIBC_2.36 umount2 F
++GLIBC_2.36 uname F
++GLIBC_2.36 ungetc F
++GLIBC_2.36 ungetwc F
++GLIBC_2.36 unlink F
++GLIBC_2.36 unlinkat F
++GLIBC_2.36 unlockpt F
++GLIBC_2.36 unsetenv F
++GLIBC_2.36 unshare F
++GLIBC_2.36 updwtmp F
++GLIBC_2.36 updwtmpx F
++GLIBC_2.36 uselocale F
++GLIBC_2.36 usleep F
++GLIBC_2.36 utime F
++GLIBC_2.36 utimensat F
++GLIBC_2.36 utimes F
++GLIBC_2.36 utmpname F
++GLIBC_2.36 utmpxname F
++GLIBC_2.36 valloc F
++GLIBC_2.36 vasprintf F
++GLIBC_2.36 vdprintf F
++GLIBC_2.36 verr F
++GLIBC_2.36 verrx F
++GLIBC_2.36 versionsort F
++GLIBC_2.36 versionsort64 F
++GLIBC_2.36 vfork F
++GLIBC_2.36 vfprintf F
++GLIBC_2.36 vfscanf F
++GLIBC_2.36 vfwprintf F
++GLIBC_2.36 vfwscanf F
++GLIBC_2.36 vhangup F
++GLIBC_2.36 vlimit F
++GLIBC_2.36 vmsplice F
++GLIBC_2.36 vprintf F
++GLIBC_2.36 vscanf F
++GLIBC_2.36 vsnprintf F
++GLIBC_2.36 vsprintf F
++GLIBC_2.36 vsscanf F
++GLIBC_2.36 vswprintf F
++GLIBC_2.36 vswscanf F
++GLIBC_2.36 vsyslog F
++GLIBC_2.36 vwarn F
++GLIBC_2.36 vwarnx F
++GLIBC_2.36 vwprintf F
++GLIBC_2.36 vwscanf F
++GLIBC_2.36 wait F
++GLIBC_2.36 wait3 F
++GLIBC_2.36 wait4 F
++GLIBC_2.36 waitid F
++GLIBC_2.36 waitpid F
++GLIBC_2.36 warn F
++GLIBC_2.36 warnx F
++GLIBC_2.36 wcpcpy F
++GLIBC_2.36 wcpncpy F
++GLIBC_2.36 wcrtomb F
++GLIBC_2.36 wcscasecmp F
++GLIBC_2.36 wcscasecmp_l F
++GLIBC_2.36 wcscat F
++GLIBC_2.36 wcschr F
++GLIBC_2.36 wcschrnul F
++GLIBC_2.36 wcscmp F
++GLIBC_2.36 wcscoll F
++GLIBC_2.36 wcscoll_l F
++GLIBC_2.36 wcscpy F
++GLIBC_2.36 wcscspn F
++GLIBC_2.36 wcsdup F
++GLIBC_2.36 wcsftime F
++GLIBC_2.36 wcsftime_l F
++GLIBC_2.36 wcslen F
++GLIBC_2.36 wcsncasecmp F
++GLIBC_2.36 wcsncasecmp_l F
++GLIBC_2.36 wcsncat F
++GLIBC_2.36 wcsncmp F
++GLIBC_2.36 wcsncpy F
++GLIBC_2.36 wcsnlen F
++GLIBC_2.36 wcsnrtombs F
++GLIBC_2.36 wcspbrk F
++GLIBC_2.36 wcsrchr F
++GLIBC_2.36 wcsrtombs F
++GLIBC_2.36 wcsspn F
++GLIBC_2.36 wcsstr F
++GLIBC_2.36 wcstod F
++GLIBC_2.36 wcstod_l F
++GLIBC_2.36 wcstof F
++GLIBC_2.36 wcstof128 F
++GLIBC_2.36 wcstof128_l F
++GLIBC_2.36 wcstof32 F
++GLIBC_2.36 wcstof32_l F
++GLIBC_2.36 wcstof32x F
++GLIBC_2.36 wcstof32x_l F
++GLIBC_2.36 wcstof64 F
++GLIBC_2.36 wcstof64_l F
++GLIBC_2.36 wcstof64x F
++GLIBC_2.36 wcstof64x_l F
++GLIBC_2.36 wcstof_l F
++GLIBC_2.36 wcstoimax F
++GLIBC_2.36 wcstok F
++GLIBC_2.36 wcstol F
++GLIBC_2.36 wcstol_l F
++GLIBC_2.36 wcstold F
++GLIBC_2.36 wcstold_l F
++GLIBC_2.36 wcstoll F
++GLIBC_2.36 wcstoll_l F
++GLIBC_2.36 wcstombs F
++GLIBC_2.36 wcstoq F
++GLIBC_2.36 wcstoul F
++GLIBC_2.36 wcstoul_l F
++GLIBC_2.36 wcstoull F
++GLIBC_2.36 wcstoull_l F
++GLIBC_2.36 wcstoumax F
++GLIBC_2.36 wcstouq F
++GLIBC_2.36 wcswcs F
++GLIBC_2.36 wcswidth F
++GLIBC_2.36 wcsxfrm F
++GLIBC_2.36 wcsxfrm_l F
++GLIBC_2.36 wctob F
++GLIBC_2.36 wctomb F
++GLIBC_2.36 wctrans F
++GLIBC_2.36 wctrans_l F
++GLIBC_2.36 wctype F
++GLIBC_2.36 wctype_l F
++GLIBC_2.36 wcwidth F
++GLIBC_2.36 wmemchr F
++GLIBC_2.36 wmemcmp F
++GLIBC_2.36 wmemcpy F
++GLIBC_2.36 wmemmove F
++GLIBC_2.36 wmempcpy F
++GLIBC_2.36 wmemset F
++GLIBC_2.36 wordexp F
++GLIBC_2.36 wordfree F
++GLIBC_2.36 wprintf F
++GLIBC_2.36 write F
++GLIBC_2.36 writev F
++GLIBC_2.36 wscanf F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libc_malloc_debug.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libc_malloc_debug.abilist
+new file mode 100644
+index 00000000..6ddfd162
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libc_malloc_debug.abilist
+@@ -0,0 +1,26 @@
++GLIBC_2.36 __free_hook D 0x8
++GLIBC_2.36 __malloc_hook D 0x8
++GLIBC_2.36 __memalign_hook D 0x8
++GLIBC_2.36 __realloc_hook D 0x8
++GLIBC_2.36 aligned_alloc F
++GLIBC_2.36 calloc F
++GLIBC_2.36 free F
++GLIBC_2.36 mallinfo F
++GLIBC_2.36 mallinfo2 F
++GLIBC_2.36 malloc F
++GLIBC_2.36 malloc_info F
++GLIBC_2.36 malloc_stats F
++GLIBC_2.36 malloc_trim F
++GLIBC_2.36 malloc_usable_size F
++GLIBC_2.36 mallopt F
++GLIBC_2.36 mcheck F
++GLIBC_2.36 mcheck_check_all F
++GLIBC_2.36 mcheck_pedantic F
++GLIBC_2.36 memalign F
++GLIBC_2.36 mprobe F
++GLIBC_2.36 mtrace F
++GLIBC_2.36 muntrace F
++GLIBC_2.36 posix_memalign F
++GLIBC_2.36 pvalloc F
++GLIBC_2.36 realloc F
++GLIBC_2.36 valloc F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist
+new file mode 100644
+index 00000000..4d4332da
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libcrypt.abilist
+@@ -0,0 +1,2 @@
++GLIBC_2.36 crypt F
++GLIBC_2.36 crypt_r F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libdl.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libdl.abilist
+new file mode 100644
+index 00000000..e69de29b
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist
+new file mode 100644
+index 00000000..b566624d
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libm.abilist
+@@ -0,0 +1,940 @@
++GLIBC_2.36 __clog10 F
++GLIBC_2.36 __clog10f F
++GLIBC_2.36 __clog10l F
++GLIBC_2.36 __finite F
++GLIBC_2.36 __finitef F
++GLIBC_2.36 __finitel F
++GLIBC_2.36 __fpclassify F
++GLIBC_2.36 __fpclassifyf F
++GLIBC_2.36 __fpclassifyl F
++GLIBC_2.36 __iseqsig F
++GLIBC_2.36 __iseqsigf F
++GLIBC_2.36 __iseqsigl F
++GLIBC_2.36 __issignaling F
++GLIBC_2.36 __issignalingf F
++GLIBC_2.36 __issignalingl F
++GLIBC_2.36 __signbit F
++GLIBC_2.36 __signbitf F
++GLIBC_2.36 __signbitl F
++GLIBC_2.36 __signgam D 0x4
++GLIBC_2.36 acos F
++GLIBC_2.36 acosf F
++GLIBC_2.36 acosf128 F
++GLIBC_2.36 acosf32 F
++GLIBC_2.36 acosf32x F
++GLIBC_2.36 acosf64 F
++GLIBC_2.36 acosf64x F
++GLIBC_2.36 acosh F
++GLIBC_2.36 acoshf F
++GLIBC_2.36 acoshf128 F
++GLIBC_2.36 acoshf32 F
++GLIBC_2.36 acoshf32x F
++GLIBC_2.36 acoshf64 F
++GLIBC_2.36 acoshf64x F
++GLIBC_2.36 acoshl F
++GLIBC_2.36 acosl F
++GLIBC_2.36 asin F
++GLIBC_2.36 asinf F
++GLIBC_2.36 asinf128 F
++GLIBC_2.36 asinf32 F
++GLIBC_2.36 asinf32x F
++GLIBC_2.36 asinf64 F
++GLIBC_2.36 asinf64x F
++GLIBC_2.36 asinh F
++GLIBC_2.36 asinhf F
++GLIBC_2.36 asinhf128 F
++GLIBC_2.36 asinhf32 F
++GLIBC_2.36 asinhf32x F
++GLIBC_2.36 asinhf64 F
++GLIBC_2.36 asinhf64x F
++GLIBC_2.36 asinhl F
++GLIBC_2.36 asinl F
++GLIBC_2.36 atan F
++GLIBC_2.36 atan2 F
++GLIBC_2.36 atan2f F
++GLIBC_2.36 atan2f128 F
++GLIBC_2.36 atan2f32 F
++GLIBC_2.36 atan2f32x F
++GLIBC_2.36 atan2f64 F
++GLIBC_2.36 atan2f64x F
++GLIBC_2.36 atan2l F
++GLIBC_2.36 atanf F
++GLIBC_2.36 atanf128 F
++GLIBC_2.36 atanf32 F
++GLIBC_2.36 atanf32x F
++GLIBC_2.36 atanf64 F
++GLIBC_2.36 atanf64x F
++GLIBC_2.36 atanh F
++GLIBC_2.36 atanhf F
++GLIBC_2.36 atanhf128 F
++GLIBC_2.36 atanhf32 F
++GLIBC_2.36 atanhf32x F
++GLIBC_2.36 atanhf64 F
++GLIBC_2.36 atanhf64x F
++GLIBC_2.36 atanhl F
++GLIBC_2.36 atanl F
++GLIBC_2.36 cabs F
++GLIBC_2.36 cabsf F
++GLIBC_2.36 cabsf128 F
++GLIBC_2.36 cabsf32 F
++GLIBC_2.36 cabsf32x F
++GLIBC_2.36 cabsf64 F
++GLIBC_2.36 cabsf64x F
++GLIBC_2.36 cabsl F
++GLIBC_2.36 cacos F
++GLIBC_2.36 cacosf F
++GLIBC_2.36 cacosf128 F
++GLIBC_2.36 cacosf32 F
++GLIBC_2.36 cacosf32x F
++GLIBC_2.36 cacosf64 F
++GLIBC_2.36 cacosf64x F
++GLIBC_2.36 cacosh F
++GLIBC_2.36 cacoshf F
++GLIBC_2.36 cacoshf128 F
++GLIBC_2.36 cacoshf32 F
++GLIBC_2.36 cacoshf32x F
++GLIBC_2.36 cacoshf64 F
++GLIBC_2.36 cacoshf64x F
++GLIBC_2.36 cacoshl F
++GLIBC_2.36 cacosl F
++GLIBC_2.36 canonicalize F
++GLIBC_2.36 canonicalizef F
++GLIBC_2.36 canonicalizef128 F
++GLIBC_2.36 canonicalizef32 F
++GLIBC_2.36 canonicalizef32x F
++GLIBC_2.36 canonicalizef64 F
++GLIBC_2.36 canonicalizef64x F
++GLIBC_2.36 canonicalizel F
++GLIBC_2.36 carg F
++GLIBC_2.36 cargf F
++GLIBC_2.36 cargf128 F
++GLIBC_2.36 cargf32 F
++GLIBC_2.36 cargf32x F
++GLIBC_2.36 cargf64 F
++GLIBC_2.36 cargf64x F
++GLIBC_2.36 cargl F
++GLIBC_2.36 casin F
++GLIBC_2.36 casinf F
++GLIBC_2.36 casinf128 F
++GLIBC_2.36 casinf32 F
++GLIBC_2.36 casinf32x F
++GLIBC_2.36 casinf64 F
++GLIBC_2.36 casinf64x F
++GLIBC_2.36 casinh F
++GLIBC_2.36 casinhf F
++GLIBC_2.36 casinhf128 F
++GLIBC_2.36 casinhf32 F
++GLIBC_2.36 casinhf32x F
++GLIBC_2.36 casinhf64 F
++GLIBC_2.36 casinhf64x F
++GLIBC_2.36 casinhl F
++GLIBC_2.36 casinl F
++GLIBC_2.36 catan F
++GLIBC_2.36 catanf F
++GLIBC_2.36 catanf128 F
++GLIBC_2.36 catanf32 F
++GLIBC_2.36 catanf32x F
++GLIBC_2.36 catanf64 F
++GLIBC_2.36 catanf64x F
++GLIBC_2.36 catanh F
++GLIBC_2.36 catanhf F
++GLIBC_2.36 catanhf128 F
++GLIBC_2.36 catanhf32 F
++GLIBC_2.36 catanhf32x F
++GLIBC_2.36 catanhf64 F
++GLIBC_2.36 catanhf64x F
++GLIBC_2.36 catanhl F
++GLIBC_2.36 catanl F
++GLIBC_2.36 cbrt F
++GLIBC_2.36 cbrtf F
++GLIBC_2.36 cbrtf128 F
++GLIBC_2.36 cbrtf32 F
++GLIBC_2.36 cbrtf32x F
++GLIBC_2.36 cbrtf64 F
++GLIBC_2.36 cbrtf64x F
++GLIBC_2.36 cbrtl F
++GLIBC_2.36 ccos F
++GLIBC_2.36 ccosf F
++GLIBC_2.36 ccosf128 F
++GLIBC_2.36 ccosf32 F
++GLIBC_2.36 ccosf32x F
++GLIBC_2.36 ccosf64 F
++GLIBC_2.36 ccosf64x F
++GLIBC_2.36 ccosh F
++GLIBC_2.36 ccoshf F
++GLIBC_2.36 ccoshf128 F
++GLIBC_2.36 ccoshf32 F
++GLIBC_2.36 ccoshf32x F
++GLIBC_2.36 ccoshf64 F
++GLIBC_2.36 ccoshf64x F
++GLIBC_2.36 ccoshl F
++GLIBC_2.36 ccosl F
++GLIBC_2.36 ceil F
++GLIBC_2.36 ceilf F
++GLIBC_2.36 ceilf128 F
++GLIBC_2.36 ceilf32 F
++GLIBC_2.36 ceilf32x F
++GLIBC_2.36 ceilf64 F
++GLIBC_2.36 ceilf64x F
++GLIBC_2.36 ceill F
++GLIBC_2.36 cexp F
++GLIBC_2.36 cexpf F
++GLIBC_2.36 cexpf128 F
++GLIBC_2.36 cexpf32 F
++GLIBC_2.36 cexpf32x F
++GLIBC_2.36 cexpf64 F
++GLIBC_2.36 cexpf64x F
++GLIBC_2.36 cexpl F
++GLIBC_2.36 cimag F
++GLIBC_2.36 cimagf F
++GLIBC_2.36 cimagf128 F
++GLIBC_2.36 cimagf32 F
++GLIBC_2.36 cimagf32x F
++GLIBC_2.36 cimagf64 F
++GLIBC_2.36 cimagf64x F
++GLIBC_2.36 cimagl F
++GLIBC_2.36 clog F
++GLIBC_2.36 clog10 F
++GLIBC_2.36 clog10f F
++GLIBC_2.36 clog10f128 F
++GLIBC_2.36 clog10f32 F
++GLIBC_2.36 clog10f32x F
++GLIBC_2.36 clog10f64 F
++GLIBC_2.36 clog10f64x F
++GLIBC_2.36 clog10l F
++GLIBC_2.36 clogf F
++GLIBC_2.36 clogf128 F
++GLIBC_2.36 clogf32 F
++GLIBC_2.36 clogf32x F
++GLIBC_2.36 clogf64 F
++GLIBC_2.36 clogf64x F
++GLIBC_2.36 clogl F
++GLIBC_2.36 conj F
++GLIBC_2.36 conjf F
++GLIBC_2.36 conjf128 F
++GLIBC_2.36 conjf32 F
++GLIBC_2.36 conjf32x F
++GLIBC_2.36 conjf64 F
++GLIBC_2.36 conjf64x F
++GLIBC_2.36 conjl F
++GLIBC_2.36 copysign F
++GLIBC_2.36 copysignf F
++GLIBC_2.36 copysignf128 F
++GLIBC_2.36 copysignf32 F
++GLIBC_2.36 copysignf32x F
++GLIBC_2.36 copysignf64 F
++GLIBC_2.36 copysignf64x F
++GLIBC_2.36 copysignl F
++GLIBC_2.36 cos F
++GLIBC_2.36 cosf F
++GLIBC_2.36 cosf128 F
++GLIBC_2.36 cosf32 F
++GLIBC_2.36 cosf32x F
++GLIBC_2.36 cosf64 F
++GLIBC_2.36 cosf64x F
++GLIBC_2.36 cosh F
++GLIBC_2.36 coshf F
++GLIBC_2.36 coshf128 F
++GLIBC_2.36 coshf32 F
++GLIBC_2.36 coshf32x F
++GLIBC_2.36 coshf64 F
++GLIBC_2.36 coshf64x F
++GLIBC_2.36 coshl F
++GLIBC_2.36 cosl F
++GLIBC_2.36 cpow F
++GLIBC_2.36 cpowf F
++GLIBC_2.36 cpowf128 F
++GLIBC_2.36 cpowf32 F
++GLIBC_2.36 cpowf32x F
++GLIBC_2.36 cpowf64 F
++GLIBC_2.36 cpowf64x F
++GLIBC_2.36 cpowl F
++GLIBC_2.36 cproj F
++GLIBC_2.36 cprojf F
++GLIBC_2.36 cprojf128 F
++GLIBC_2.36 cprojf32 F
++GLIBC_2.36 cprojf32x F
++GLIBC_2.36 cprojf64 F
++GLIBC_2.36 cprojf64x F
++GLIBC_2.36 cprojl F
++GLIBC_2.36 creal F
++GLIBC_2.36 crealf F
++GLIBC_2.36 crealf128 F
++GLIBC_2.36 crealf32 F
++GLIBC_2.36 crealf32x F
++GLIBC_2.36 crealf64 F
++GLIBC_2.36 crealf64x F
++GLIBC_2.36 creall F
++GLIBC_2.36 csin F
++GLIBC_2.36 csinf F
++GLIBC_2.36 csinf128 F
++GLIBC_2.36 csinf32 F
++GLIBC_2.36 csinf32x F
++GLIBC_2.36 csinf64 F
++GLIBC_2.36 csinf64x F
++GLIBC_2.36 csinh F
++GLIBC_2.36 csinhf F
++GLIBC_2.36 csinhf128 F
++GLIBC_2.36 csinhf32 F
++GLIBC_2.36 csinhf32x F
++GLIBC_2.36 csinhf64 F
++GLIBC_2.36 csinhf64x F
++GLIBC_2.36 csinhl F
++GLIBC_2.36 csinl F
++GLIBC_2.36 csqrt F
++GLIBC_2.36 csqrtf F
++GLIBC_2.36 csqrtf128 F
++GLIBC_2.36 csqrtf32 F
++GLIBC_2.36 csqrtf32x F
++GLIBC_2.36 csqrtf64 F
++GLIBC_2.36 csqrtf64x F
++GLIBC_2.36 csqrtl F
++GLIBC_2.36 ctan F
++GLIBC_2.36 ctanf F
++GLIBC_2.36 ctanf128 F
++GLIBC_2.36 ctanf32 F
++GLIBC_2.36 ctanf32x F
++GLIBC_2.36 ctanf64 F
++GLIBC_2.36 ctanf64x F
++GLIBC_2.36 ctanh F
++GLIBC_2.36 ctanhf F
++GLIBC_2.36 ctanhf128 F
++GLIBC_2.36 ctanhf32 F
++GLIBC_2.36 ctanhf32x F
++GLIBC_2.36 ctanhf64 F
++GLIBC_2.36 ctanhf64x F
++GLIBC_2.36 ctanhl F
++GLIBC_2.36 ctanl F
++GLIBC_2.36 daddl F
++GLIBC_2.36 ddivl F
++GLIBC_2.36 dmull F
++GLIBC_2.36 drem F
++GLIBC_2.36 dremf F
++GLIBC_2.36 dreml F
++GLIBC_2.36 dsubl F
++GLIBC_2.36 erf F
++GLIBC_2.36 erfc F
++GLIBC_2.36 erfcf F
++GLIBC_2.36 erfcf128 F
++GLIBC_2.36 erfcf32 F
++GLIBC_2.36 erfcf32x F
++GLIBC_2.36 erfcf64 F
++GLIBC_2.36 erfcf64x F
++GLIBC_2.36 erfcl F
++GLIBC_2.36 erff F
++GLIBC_2.36 erff128 F
++GLIBC_2.36 erff32 F
++GLIBC_2.36 erff32x F
++GLIBC_2.36 erff64 F
++GLIBC_2.36 erff64x F
++GLIBC_2.36 erfl F
++GLIBC_2.36 exp F
++GLIBC_2.36 exp10 F
++GLIBC_2.36 exp10f F
++GLIBC_2.36 exp10f128 F
++GLIBC_2.36 exp10f32 F
++GLIBC_2.36 exp10f32x F
++GLIBC_2.36 exp10f64 F
++GLIBC_2.36 exp10f64x F
++GLIBC_2.36 exp10l F
++GLIBC_2.36 exp2 F
++GLIBC_2.36 exp2f F
++GLIBC_2.36 exp2f128 F
++GLIBC_2.36 exp2f32 F
++GLIBC_2.36 exp2f32x F
++GLIBC_2.36 exp2f64 F
++GLIBC_2.36 exp2f64x F
++GLIBC_2.36 exp2l F
++GLIBC_2.36 expf F
++GLIBC_2.36 expf128 F
++GLIBC_2.36 expf32 F
++GLIBC_2.36 expf32x F
++GLIBC_2.36 expf64 F
++GLIBC_2.36 expf64x F
++GLIBC_2.36 expl F
++GLIBC_2.36 expm1 F
++GLIBC_2.36 expm1f F
++GLIBC_2.36 expm1f128 F
++GLIBC_2.36 expm1f32 F
++GLIBC_2.36 expm1f32x F
++GLIBC_2.36 expm1f64 F
++GLIBC_2.36 expm1f64x F
++GLIBC_2.36 expm1l F
++GLIBC_2.36 f32addf128 F
++GLIBC_2.36 f32addf32x F
++GLIBC_2.36 f32addf64 F
++GLIBC_2.36 f32addf64x F
++GLIBC_2.36 f32divf128 F
++GLIBC_2.36 f32divf32x F
++GLIBC_2.36 f32divf64 F
++GLIBC_2.36 f32divf64x F
++GLIBC_2.36 f32mulf128 F
++GLIBC_2.36 f32mulf32x F
++GLIBC_2.36 f32mulf64 F
++GLIBC_2.36 f32mulf64x F
++GLIBC_2.36 f32subf128 F
++GLIBC_2.36 f32subf32x F
++GLIBC_2.36 f32subf64 F
++GLIBC_2.36 f32subf64x F
++GLIBC_2.36 f32xaddf128 F
++GLIBC_2.36 f32xaddf64 F
++GLIBC_2.36 f32xaddf64x F
++GLIBC_2.36 f32xdivf128 F
++GLIBC_2.36 f32xdivf64 F
++GLIBC_2.36 f32xdivf64x F
++GLIBC_2.36 f32xmulf128 F
++GLIBC_2.36 f32xmulf64 F
++GLIBC_2.36 f32xmulf64x F
++GLIBC_2.36 f32xsubf128 F
++GLIBC_2.36 f32xsubf64 F
++GLIBC_2.36 f32xsubf64x F
++GLIBC_2.36 f64addf128 F
++GLIBC_2.36 f64addf64x F
++GLIBC_2.36 f64divf128 F
++GLIBC_2.36 f64divf64x F
++GLIBC_2.36 f64mulf128 F
++GLIBC_2.36 f64mulf64x F
++GLIBC_2.36 f64subf128 F
++GLIBC_2.36 f64subf64x F
++GLIBC_2.36 f64xaddf128 F
++GLIBC_2.36 f64xdivf128 F
++GLIBC_2.36 f64xmulf128 F
++GLIBC_2.36 f64xsubf128 F
++GLIBC_2.36 fabs F
++GLIBC_2.36 fabsf F
++GLIBC_2.36 fabsf128 F
++GLIBC_2.36 fabsf32 F
++GLIBC_2.36 fabsf32x F
++GLIBC_2.36 fabsf64 F
++GLIBC_2.36 fabsf64x F
++GLIBC_2.36 fabsl F
++GLIBC_2.36 fadd F
++GLIBC_2.36 faddl F
++GLIBC_2.36 fdim F
++GLIBC_2.36 fdimf F
++GLIBC_2.36 fdimf128 F
++GLIBC_2.36 fdimf32 F
++GLIBC_2.36 fdimf32x F
++GLIBC_2.36 fdimf64 F
++GLIBC_2.36 fdimf64x F
++GLIBC_2.36 fdiml F
++GLIBC_2.36 fdiv F
++GLIBC_2.36 fdivl F
++GLIBC_2.36 feclearexcept F
++GLIBC_2.36 fedisableexcept F
++GLIBC_2.36 feenableexcept F
++GLIBC_2.36 fegetenv F
++GLIBC_2.36 fegetexcept F
++GLIBC_2.36 fegetexceptflag F
++GLIBC_2.36 fegetmode F
++GLIBC_2.36 fegetround F
++GLIBC_2.36 feholdexcept F
++GLIBC_2.36 feraiseexcept F
++GLIBC_2.36 fesetenv F
++GLIBC_2.36 fesetexcept F
++GLIBC_2.36 fesetexceptflag F
++GLIBC_2.36 fesetmode F
++GLIBC_2.36 fesetround F
++GLIBC_2.36 fetestexcept F
++GLIBC_2.36 fetestexceptflag F
++GLIBC_2.36 feupdateenv F
++GLIBC_2.36 finite F
++GLIBC_2.36 finitef F
++GLIBC_2.36 finitel F
++GLIBC_2.36 floor F
++GLIBC_2.36 floorf F
++GLIBC_2.36 floorf128 F
++GLIBC_2.36 floorf32 F
++GLIBC_2.36 floorf32x F
++GLIBC_2.36 floorf64 F
++GLIBC_2.36 floorf64x F
++GLIBC_2.36 floorl F
++GLIBC_2.36 fma F
++GLIBC_2.36 fmaf F
++GLIBC_2.36 fmaf128 F
++GLIBC_2.36 fmaf32 F
++GLIBC_2.36 fmaf32x F
++GLIBC_2.36 fmaf64 F
++GLIBC_2.36 fmaf64x F
++GLIBC_2.36 fmal F
++GLIBC_2.36 fmax F
++GLIBC_2.36 fmaxf F
++GLIBC_2.36 fmaxf128 F
++GLIBC_2.36 fmaxf32 F
++GLIBC_2.36 fmaxf32x F
++GLIBC_2.36 fmaxf64 F
++GLIBC_2.36 fmaxf64x F
++GLIBC_2.36 fmaxl F
++GLIBC_2.36 fmaxmag F
++GLIBC_2.36 fmaxmagf F
++GLIBC_2.36 fmaxmagf128 F
++GLIBC_2.36 fmaxmagf32 F
++GLIBC_2.36 fmaxmagf32x F
++GLIBC_2.36 fmaxmagf64 F
++GLIBC_2.36 fmaxmagf64x F
++GLIBC_2.36 fmaxmagl F
++GLIBC_2.36 fmin F
++GLIBC_2.36 fminf F
++GLIBC_2.36 fminf128 F
++GLIBC_2.36 fminf32 F
++GLIBC_2.36 fminf32x F
++GLIBC_2.36 fminf64 F
++GLIBC_2.36 fminf64x F
++GLIBC_2.36 fminl F
++GLIBC_2.36 fminmag F
++GLIBC_2.36 fminmagf F
++GLIBC_2.36 fminmagf128 F
++GLIBC_2.36 fminmagf32 F
++GLIBC_2.36 fminmagf32x F
++GLIBC_2.36 fminmagf64 F
++GLIBC_2.36 fminmagf64x F
++GLIBC_2.36 fminmagl F
++GLIBC_2.36 fmod F
++GLIBC_2.36 fmodf F
++GLIBC_2.36 fmodf128 F
++GLIBC_2.36 fmodf32 F
++GLIBC_2.36 fmodf32x F
++GLIBC_2.36 fmodf64 F
++GLIBC_2.36 fmodf64x F
++GLIBC_2.36 fmodl F
++GLIBC_2.36 fmul F
++GLIBC_2.36 fmull F
++GLIBC_2.36 frexp F
++GLIBC_2.36 frexpf F
++GLIBC_2.36 frexpf128 F
++GLIBC_2.36 frexpf32 F
++GLIBC_2.36 frexpf32x F
++GLIBC_2.36 frexpf64 F
++GLIBC_2.36 frexpf64x F
++GLIBC_2.36 frexpl F
++GLIBC_2.36 fromfp F
++GLIBC_2.36 fromfpf F
++GLIBC_2.36 fromfpf128 F
++GLIBC_2.36 fromfpf32 F
++GLIBC_2.36 fromfpf32x F
++GLIBC_2.36 fromfpf64 F
++GLIBC_2.36 fromfpf64x F
++GLIBC_2.36 fromfpl F
++GLIBC_2.36 fromfpx F
++GLIBC_2.36 fromfpxf F
++GLIBC_2.36 fromfpxf128 F
++GLIBC_2.36 fromfpxf32 F
++GLIBC_2.36 fromfpxf32x F
++GLIBC_2.36 fromfpxf64 F
++GLIBC_2.36 fromfpxf64x F
++GLIBC_2.36 fromfpxl F
++GLIBC_2.36 fsub F
++GLIBC_2.36 fsubl F
++GLIBC_2.36 gamma F
++GLIBC_2.36 gammaf F
++GLIBC_2.36 gammal F
++GLIBC_2.36 getpayload F
++GLIBC_2.36 getpayloadf F
++GLIBC_2.36 getpayloadf128 F
++GLIBC_2.36 getpayloadf32 F
++GLIBC_2.36 getpayloadf32x F
++GLIBC_2.36 getpayloadf64 F
++GLIBC_2.36 getpayloadf64x F
++GLIBC_2.36 getpayloadl F
++GLIBC_2.36 hypot F
++GLIBC_2.36 hypotf F
++GLIBC_2.36 hypotf128 F
++GLIBC_2.36 hypotf32 F
++GLIBC_2.36 hypotf32x F
++GLIBC_2.36 hypotf64 F
++GLIBC_2.36 hypotf64x F
++GLIBC_2.36 hypotl F
++GLIBC_2.36 ilogb F
++GLIBC_2.36 ilogbf F
++GLIBC_2.36 ilogbf128 F
++GLIBC_2.36 ilogbf32 F
++GLIBC_2.36 ilogbf32x F
++GLIBC_2.36 ilogbf64 F
++GLIBC_2.36 ilogbf64x F
++GLIBC_2.36 ilogbl F
++GLIBC_2.36 j0 F
++GLIBC_2.36 j0f F
++GLIBC_2.36 j0f128 F
++GLIBC_2.36 j0f32 F
++GLIBC_2.36 j0f32x F
++GLIBC_2.36 j0f64 F
++GLIBC_2.36 j0f64x F
++GLIBC_2.36 j0l F
++GLIBC_2.36 j1 F
++GLIBC_2.36 j1f F
++GLIBC_2.36 j1f128 F
++GLIBC_2.36 j1f32 F
++GLIBC_2.36 j1f32x F
++GLIBC_2.36 j1f64 F
++GLIBC_2.36 j1f64x F
++GLIBC_2.36 j1l F
++GLIBC_2.36 jn F
++GLIBC_2.36 jnf F
++GLIBC_2.36 jnf128 F
++GLIBC_2.36 jnf32 F
++GLIBC_2.36 jnf32x F
++GLIBC_2.36 jnf64 F
++GLIBC_2.36 jnf64x F
++GLIBC_2.36 jnl F
++GLIBC_2.36 ldexp F
++GLIBC_2.36 ldexpf F
++GLIBC_2.36 ldexpf128 F
++GLIBC_2.36 ldexpf32 F
++GLIBC_2.36 ldexpf32x F
++GLIBC_2.36 ldexpf64 F
++GLIBC_2.36 ldexpf64x F
++GLIBC_2.36 ldexpl F
++GLIBC_2.36 lgamma F
++GLIBC_2.36 lgamma_r F
++GLIBC_2.36 lgammaf F
++GLIBC_2.36 lgammaf128 F
++GLIBC_2.36 lgammaf128_r F
++GLIBC_2.36 lgammaf32 F
++GLIBC_2.36 lgammaf32_r F
++GLIBC_2.36 lgammaf32x F
++GLIBC_2.36 lgammaf32x_r F
++GLIBC_2.36 lgammaf64 F
++GLIBC_2.36 lgammaf64_r F
++GLIBC_2.36 lgammaf64x F
++GLIBC_2.36 lgammaf64x_r F
++GLIBC_2.36 lgammaf_r F
++GLIBC_2.36 lgammal F
++GLIBC_2.36 lgammal_r F
++GLIBC_2.36 llogb F
++GLIBC_2.36 llogbf F
++GLIBC_2.36 llogbf128 F
++GLIBC_2.36 llogbf32 F
++GLIBC_2.36 llogbf32x F
++GLIBC_2.36 llogbf64 F
++GLIBC_2.36 llogbf64x F
++GLIBC_2.36 llogbl F
++GLIBC_2.36 llrint F
++GLIBC_2.36 llrintf F
++GLIBC_2.36 llrintf128 F
++GLIBC_2.36 llrintf32 F
++GLIBC_2.36 llrintf32x F
++GLIBC_2.36 llrintf64 F
++GLIBC_2.36 llrintf64x F
++GLIBC_2.36 llrintl F
++GLIBC_2.36 llround F
++GLIBC_2.36 llroundf F
++GLIBC_2.36 llroundf128 F
++GLIBC_2.36 llroundf32 F
++GLIBC_2.36 llroundf32x F
++GLIBC_2.36 llroundf64 F
++GLIBC_2.36 llroundf64x F
++GLIBC_2.36 llroundl F
++GLIBC_2.36 log F
++GLIBC_2.36 log10 F
++GLIBC_2.36 log10f F
++GLIBC_2.36 log10f128 F
++GLIBC_2.36 log10f32 F
++GLIBC_2.36 log10f32x F
++GLIBC_2.36 log10f64 F
++GLIBC_2.36 log10f64x F
++GLIBC_2.36 log10l F
++GLIBC_2.36 log1p F
++GLIBC_2.36 log1pf F
++GLIBC_2.36 log1pf128 F
++GLIBC_2.36 log1pf32 F
++GLIBC_2.36 log1pf32x F
++GLIBC_2.36 log1pf64 F
++GLIBC_2.36 log1pf64x F
++GLIBC_2.36 log1pl F
++GLIBC_2.36 log2 F
++GLIBC_2.36 log2f F
++GLIBC_2.36 log2f128 F
++GLIBC_2.36 log2f32 F
++GLIBC_2.36 log2f32x F
++GLIBC_2.36 log2f64 F
++GLIBC_2.36 log2f64x F
++GLIBC_2.36 log2l F
++GLIBC_2.36 logb F
++GLIBC_2.36 logbf F
++GLIBC_2.36 logbf128 F
++GLIBC_2.36 logbf32 F
++GLIBC_2.36 logbf32x F
++GLIBC_2.36 logbf64 F
++GLIBC_2.36 logbf64x F
++GLIBC_2.36 logbl F
++GLIBC_2.36 logf F
++GLIBC_2.36 logf128 F
++GLIBC_2.36 logf32 F
++GLIBC_2.36 logf32x F
++GLIBC_2.36 logf64 F
++GLIBC_2.36 logf64x F
++GLIBC_2.36 logl F
++GLIBC_2.36 lrint F
++GLIBC_2.36 lrintf F
++GLIBC_2.36 lrintf128 F
++GLIBC_2.36 lrintf32 F
++GLIBC_2.36 lrintf32x F
++GLIBC_2.36 lrintf64 F
++GLIBC_2.36 lrintf64x F
++GLIBC_2.36 lrintl F
++GLIBC_2.36 lround F
++GLIBC_2.36 lroundf F
++GLIBC_2.36 lroundf128 F
++GLIBC_2.36 lroundf32 F
++GLIBC_2.36 lroundf32x F
++GLIBC_2.36 lroundf64 F
++GLIBC_2.36 lroundf64x F
++GLIBC_2.36 lroundl F
++GLIBC_2.36 modf F
++GLIBC_2.36 modff F
++GLIBC_2.36 modff128 F
++GLIBC_2.36 modff32 F
++GLIBC_2.36 modff32x F
++GLIBC_2.36 modff64 F
++GLIBC_2.36 modff64x F
++GLIBC_2.36 modfl F
++GLIBC_2.36 nan F
++GLIBC_2.36 nanf F
++GLIBC_2.36 nanf128 F
++GLIBC_2.36 nanf32 F
++GLIBC_2.36 nanf32x F
++GLIBC_2.36 nanf64 F
++GLIBC_2.36 nanf64x F
++GLIBC_2.36 nanl F
++GLIBC_2.36 nearbyint F
++GLIBC_2.36 nearbyintf F
++GLIBC_2.36 nearbyintf128 F
++GLIBC_2.36 nearbyintf32 F
++GLIBC_2.36 nearbyintf32x F
++GLIBC_2.36 nearbyintf64 F
++GLIBC_2.36 nearbyintf64x F
++GLIBC_2.36 nearbyintl F
++GLIBC_2.36 nextafter F
++GLIBC_2.36 nextafterf F
++GLIBC_2.36 nextafterf128 F
++GLIBC_2.36 nextafterf32 F
++GLIBC_2.36 nextafterf32x F
++GLIBC_2.36 nextafterf64 F
++GLIBC_2.36 nextafterf64x F
++GLIBC_2.36 nextafterl F
++GLIBC_2.36 nextdown F
++GLIBC_2.36 nextdownf F
++GLIBC_2.36 nextdownf128 F
++GLIBC_2.36 nextdownf32 F
++GLIBC_2.36 nextdownf32x F
++GLIBC_2.36 nextdownf64 F
++GLIBC_2.36 nextdownf64x F
++GLIBC_2.36 nextdownl F
++GLIBC_2.36 nexttoward F
++GLIBC_2.36 nexttowardf F
++GLIBC_2.36 nexttowardl F
++GLIBC_2.36 nextup F
++GLIBC_2.36 nextupf F
++GLIBC_2.36 nextupf128 F
++GLIBC_2.36 nextupf32 F
++GLIBC_2.36 nextupf32x F
++GLIBC_2.36 nextupf64 F
++GLIBC_2.36 nextupf64x F
++GLIBC_2.36 nextupl F
++GLIBC_2.36 pow F
++GLIBC_2.36 powf F
++GLIBC_2.36 powf128 F
++GLIBC_2.36 powf32 F
++GLIBC_2.36 powf32x F
++GLIBC_2.36 powf64 F
++GLIBC_2.36 powf64x F
++GLIBC_2.36 powl F
++GLIBC_2.36 remainder F
++GLIBC_2.36 remainderf F
++GLIBC_2.36 remainderf128 F
++GLIBC_2.36 remainderf32 F
++GLIBC_2.36 remainderf32x F
++GLIBC_2.36 remainderf64 F
++GLIBC_2.36 remainderf64x F
++GLIBC_2.36 remainderl F
++GLIBC_2.36 remquo F
++GLIBC_2.36 remquof F
++GLIBC_2.36 remquof128 F
++GLIBC_2.36 remquof32 F
++GLIBC_2.36 remquof32x F
++GLIBC_2.36 remquof64 F
++GLIBC_2.36 remquof64x F
++GLIBC_2.36 remquol F
++GLIBC_2.36 rint F
++GLIBC_2.36 rintf F
++GLIBC_2.36 rintf128 F
++GLIBC_2.36 rintf32 F
++GLIBC_2.36 rintf32x F
++GLIBC_2.36 rintf64 F
++GLIBC_2.36 rintf64x F
++GLIBC_2.36 rintl F
++GLIBC_2.36 round F
++GLIBC_2.36 roundeven F
++GLIBC_2.36 roundevenf F
++GLIBC_2.36 roundevenf128 F
++GLIBC_2.36 roundevenf32 F
++GLIBC_2.36 roundevenf32x F
++GLIBC_2.36 roundevenf64 F
++GLIBC_2.36 roundevenf64x F
++GLIBC_2.36 roundevenl F
++GLIBC_2.36 roundf F
++GLIBC_2.36 roundf128 F
++GLIBC_2.36 roundf32 F
++GLIBC_2.36 roundf32x F
++GLIBC_2.36 roundf64 F
++GLIBC_2.36 roundf64x F
++GLIBC_2.36 roundl F
++GLIBC_2.36 scalb F
++GLIBC_2.36 scalbf F
++GLIBC_2.36 scalbl F
++GLIBC_2.36 scalbln F
++GLIBC_2.36 scalblnf F
++GLIBC_2.36 scalblnf128 F
++GLIBC_2.36 scalblnf32 F
++GLIBC_2.36 scalblnf32x F
++GLIBC_2.36 scalblnf64 F
++GLIBC_2.36 scalblnf64x F
++GLIBC_2.36 scalblnl F
++GLIBC_2.36 scalbn F
++GLIBC_2.36 scalbnf F
++GLIBC_2.36 scalbnf128 F
++GLIBC_2.36 scalbnf32 F
++GLIBC_2.36 scalbnf32x F
++GLIBC_2.36 scalbnf64 F
++GLIBC_2.36 scalbnf64x F
++GLIBC_2.36 scalbnl F
++GLIBC_2.36 setpayload F
++GLIBC_2.36 setpayloadf F
++GLIBC_2.36 setpayloadf128 F
++GLIBC_2.36 setpayloadf32 F
++GLIBC_2.36 setpayloadf32x F
++GLIBC_2.36 setpayloadf64 F
++GLIBC_2.36 setpayloadf64x F
++GLIBC_2.36 setpayloadl F
++GLIBC_2.36 setpayloadsig F
++GLIBC_2.36 setpayloadsigf F
++GLIBC_2.36 setpayloadsigf128 F
++GLIBC_2.36 setpayloadsigf32 F
++GLIBC_2.36 setpayloadsigf32x F
++GLIBC_2.36 setpayloadsigf64 F
++GLIBC_2.36 setpayloadsigf64x F
++GLIBC_2.36 setpayloadsigl F
++GLIBC_2.36 signgam D 0x4
++GLIBC_2.36 significand F
++GLIBC_2.36 significandf F
++GLIBC_2.36 significandl F
++GLIBC_2.36 sin F
++GLIBC_2.36 sincos F
++GLIBC_2.36 sincosf F
++GLIBC_2.36 sincosf128 F
++GLIBC_2.36 sincosf32 F
++GLIBC_2.36 sincosf32x F
++GLIBC_2.36 sincosf64 F
++GLIBC_2.36 sincosf64x F
++GLIBC_2.36 sincosl F
++GLIBC_2.36 sinf F
++GLIBC_2.36 sinf128 F
++GLIBC_2.36 sinf32 F
++GLIBC_2.36 sinf32x F
++GLIBC_2.36 sinf64 F
++GLIBC_2.36 sinf64x F
++GLIBC_2.36 sinh F
++GLIBC_2.36 sinhf F
++GLIBC_2.36 sinhf128 F
++GLIBC_2.36 sinhf32 F
++GLIBC_2.36 sinhf32x F
++GLIBC_2.36 sinhf64 F
++GLIBC_2.36 sinhf64x F
++GLIBC_2.36 sinhl F
++GLIBC_2.36 sinl F
++GLIBC_2.36 sqrt F
++GLIBC_2.36 sqrtf F
++GLIBC_2.36 sqrtf128 F
++GLIBC_2.36 sqrtf32 F
++GLIBC_2.36 sqrtf32x F
++GLIBC_2.36 sqrtf64 F
++GLIBC_2.36 sqrtf64x F
++GLIBC_2.36 sqrtl F
++GLIBC_2.36 tan F
++GLIBC_2.36 tanf F
++GLIBC_2.36 tanf128 F
++GLIBC_2.36 tanf32 F
++GLIBC_2.36 tanf32x F
++GLIBC_2.36 tanf64 F
++GLIBC_2.36 tanf64x F
++GLIBC_2.36 tanh F
++GLIBC_2.36 tanhf F
++GLIBC_2.36 tanhf128 F
++GLIBC_2.36 tanhf32 F
++GLIBC_2.36 tanhf32x F
++GLIBC_2.36 tanhf64 F
++GLIBC_2.36 tanhf64x F
++GLIBC_2.36 tanhl F
++GLIBC_2.36 tanl F
++GLIBC_2.36 tgamma F
++GLIBC_2.36 tgammaf F
++GLIBC_2.36 tgammaf128 F
++GLIBC_2.36 tgammaf32 F
++GLIBC_2.36 tgammaf32x F
++GLIBC_2.36 tgammaf64 F
++GLIBC_2.36 tgammaf64x F
++GLIBC_2.36 tgammal F
++GLIBC_2.36 totalorder F
++GLIBC_2.36 totalorderf F
++GLIBC_2.36 totalorderf128 F
++GLIBC_2.36 totalorderf32 F
++GLIBC_2.36 totalorderf32x F
++GLIBC_2.36 totalorderf64 F
++GLIBC_2.36 totalorderf64x F
++GLIBC_2.36 totalorderl F
++GLIBC_2.36 totalordermag F
++GLIBC_2.36 totalordermagf F
++GLIBC_2.36 totalordermagf128 F
++GLIBC_2.36 totalordermagf32 F
++GLIBC_2.36 totalordermagf32x F
++GLIBC_2.36 totalordermagf64 F
++GLIBC_2.36 totalordermagf64x F
++GLIBC_2.36 totalordermagl F
++GLIBC_2.36 trunc F
++GLIBC_2.36 truncf F
++GLIBC_2.36 truncf128 F
++GLIBC_2.36 truncf32 F
++GLIBC_2.36 truncf32x F
++GLIBC_2.36 truncf64 F
++GLIBC_2.36 truncf64x F
++GLIBC_2.36 truncl F
++GLIBC_2.36 ufromfp F
++GLIBC_2.36 ufromfpf F
++GLIBC_2.36 ufromfpf128 F
++GLIBC_2.36 ufromfpf32 F
++GLIBC_2.36 ufromfpf32x F
++GLIBC_2.36 ufromfpf64 F
++GLIBC_2.36 ufromfpf64x F
++GLIBC_2.36 ufromfpl F
++GLIBC_2.36 ufromfpx F
++GLIBC_2.36 ufromfpxf F
++GLIBC_2.36 ufromfpxf128 F
++GLIBC_2.36 ufromfpxf32 F
++GLIBC_2.36 ufromfpxf32x F
++GLIBC_2.36 ufromfpxf64 F
++GLIBC_2.36 ufromfpxf64x F
++GLIBC_2.36 ufromfpxl F
++GLIBC_2.36 y0 F
++GLIBC_2.36 y0f F
++GLIBC_2.36 y0f128 F
++GLIBC_2.36 y0f32 F
++GLIBC_2.36 y0f32x F
++GLIBC_2.36 y0f64 F
++GLIBC_2.36 y0f64x F
++GLIBC_2.36 y0l F
++GLIBC_2.36 y1 F
++GLIBC_2.36 y1f F
++GLIBC_2.36 y1f128 F
++GLIBC_2.36 y1f32 F
++GLIBC_2.36 y1f32x F
++GLIBC_2.36 y1f64 F
++GLIBC_2.36 y1f64x F
++GLIBC_2.36 y1l F
++GLIBC_2.36 yn F
++GLIBC_2.36 ynf F
++GLIBC_2.36 ynf128 F
++GLIBC_2.36 ynf32 F
++GLIBC_2.36 ynf32x F
++GLIBC_2.36 ynf64 F
++GLIBC_2.36 ynf64x F
++GLIBC_2.36 ynl F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libpthread.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libpthread.abilist
+new file mode 100644
+index 00000000..e69de29b
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist
+new file mode 100644
+index 00000000..c30f54c0
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libresolv.abilist
+@@ -0,0 +1,55 @@
++GLIBC_2.36 __b64_ntop F
++GLIBC_2.36 __b64_pton F
++GLIBC_2.36 __dn_count_labels F
++GLIBC_2.36 __fp_nquery F
++GLIBC_2.36 __fp_query F
++GLIBC_2.36 __fp_resstat F
++GLIBC_2.36 __hostalias F
++GLIBC_2.36 __loc_aton F
++GLIBC_2.36 __loc_ntoa F
++GLIBC_2.36 __p_cdname F
++GLIBC_2.36 __p_cdnname F
++GLIBC_2.36 __p_class F
++GLIBC_2.36 __p_class_syms D 0xa8
++GLIBC_2.36 __p_fqname F
++GLIBC_2.36 __p_fqnname F
++GLIBC_2.36 __p_option F
++GLIBC_2.36 __p_query F
++GLIBC_2.36 __p_rcode F
++GLIBC_2.36 __p_time F
++GLIBC_2.36 __p_type F
++GLIBC_2.36 __p_type_syms D 0x450
++GLIBC_2.36 __putlong F
++GLIBC_2.36 __putshort F
++GLIBC_2.36 __res_close F
++GLIBC_2.36 __res_hostalias F
++GLIBC_2.36 __res_isourserver F
++GLIBC_2.36 __res_nameinquery F
++GLIBC_2.36 __res_queriesmatch F
++GLIBC_2.36 __sym_ntop F
++GLIBC_2.36 __sym_ntos F
++GLIBC_2.36 __sym_ston F
++GLIBC_2.36 _getlong F
++GLIBC_2.36 _getshort F
++GLIBC_2.36 inet_net_ntop F
++GLIBC_2.36 inet_net_pton F
++GLIBC_2.36 inet_neta F
++GLIBC_2.36 ns_datetosecs F
++GLIBC_2.36 ns_format_ttl F
++GLIBC_2.36 ns_get16 F
++GLIBC_2.36 ns_get32 F
++GLIBC_2.36 ns_initparse F
++GLIBC_2.36 ns_makecanon F
++GLIBC_2.36 ns_msg_getflag F
++GLIBC_2.36 ns_name_ntol F
++GLIBC_2.36 ns_name_rollback F
++GLIBC_2.36 ns_parse_ttl F
++GLIBC_2.36 ns_parserr F
++GLIBC_2.36 ns_put16 F
++GLIBC_2.36 ns_put32 F
++GLIBC_2.36 ns_samedomain F
++GLIBC_2.36 ns_samename F
++GLIBC_2.36 ns_skiprr F
++GLIBC_2.36 ns_sprintrr F
++GLIBC_2.36 ns_sprintrrf F
++GLIBC_2.36 ns_subdomain F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/librt.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/librt.abilist
+new file mode 100644
+index 00000000..e69de29b
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist b/sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist
+new file mode 100644
+index 00000000..8658803d
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/libthread_db.abilist
+@@ -0,0 +1,40 @@
++GLIBC_2.36 td_init F
++GLIBC_2.36 td_log F
++GLIBC_2.36 td_symbol_list F
++GLIBC_2.36 td_ta_clear_event F
++GLIBC_2.36 td_ta_delete F
++GLIBC_2.36 td_ta_enable_stats F
++GLIBC_2.36 td_ta_event_addr F
++GLIBC_2.36 td_ta_event_getmsg F
++GLIBC_2.36 td_ta_get_nthreads F
++GLIBC_2.36 td_ta_get_ph F
++GLIBC_2.36 td_ta_get_stats F
++GLIBC_2.36 td_ta_map_id2thr F
++GLIBC_2.36 td_ta_map_lwp2thr F
++GLIBC_2.36 td_ta_new F
++GLIBC_2.36 td_ta_reset_stats F
++GLIBC_2.36 td_ta_set_event F
++GLIBC_2.36 td_ta_setconcurrency F
++GLIBC_2.36 td_ta_thr_iter F
++GLIBC_2.36 td_ta_tsd_iter F
++GLIBC_2.36 td_thr_clear_event F
++GLIBC_2.36 td_thr_dbresume F
++GLIBC_2.36 td_thr_dbsuspend F
++GLIBC_2.36 td_thr_event_enable F
++GLIBC_2.36 td_thr_event_getmsg F
++GLIBC_2.36 td_thr_get_info F
++GLIBC_2.36 td_thr_getfpregs F
++GLIBC_2.36 td_thr_getgregs F
++GLIBC_2.36 td_thr_getxregs F
++GLIBC_2.36 td_thr_getxregsize F
++GLIBC_2.36 td_thr_set_event F
++GLIBC_2.36 td_thr_setfpregs F
++GLIBC_2.36 td_thr_setgregs F
++GLIBC_2.36 td_thr_setprio F
++GLIBC_2.36 td_thr_setsigpending F
++GLIBC_2.36 td_thr_setxregs F
++GLIBC_2.36 td_thr_sigsetmask F
++GLIBC_2.36 td_thr_tls_get_addr F
++GLIBC_2.36 td_thr_tlsbase F
++GLIBC_2.36 td_thr_tsd F
++GLIBC_2.36 td_thr_validate F
+diff --git a/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/jmp_buf-macros.h b/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/jmp_buf-macros.h
+new file mode 100644
+index 00000000..835df05c
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/lp64/nofpu/jmp_buf-macros.h
+@@ -0,0 +1,41 @@
++/* Copyright (C) 2020-2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Produced by this program:
++
++ #include <stdio.h>
++ #include <unistd.h>
++ #include <setjmp.h>
++ #include <stddef.h>
++
++ int main (int argc, char **argv)
++ {
++ printf ("#define JMP_BUF_SIZE %d\n", sizeof (jmp_buf));
++ printf ("#define JMP_BUF_ALIGN %d\n", __alignof__ (jmp_buf));
++ printf ("#define SIGJMP_BUF_SIZE %d\n", sizeof (sigjmp_buf));
++ printf ("#define SIGJMP_BUF_ALIGN %d\n", __alignof__ (sigjmp_buf));
++ printf ("#define MASK_WAS_SAVED_OFFSET %d\n", offsetof (struct __jmp_buf_tag, __mask_was_saved));
++ printf ("#define SAVED_MASK_OFFSET %d\n", offsetof (struct __jmp_buf_tag, __saved_mask));
++ } */
++
++# define JMP_BUF_SIZE 240
++# define JMP_BUF_ALIGN 8
++# define SIGJMP_BUF_SIZE 240
++# define SIGJMP_BUF_ALIGN 8
++# define MASK_WAS_SAVED_OFFSET 104
++# define SAVED_MASK_OFFSET 112
+diff --git a/sysdeps/unix/sysv/linux/loongarch/makecontext.c b/sysdeps/unix/sysv/linux/loongarch/makecontext.c
+new file mode 100644
+index 00000000..94a45bf4
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/makecontext.c
+@@ -0,0 +1,81 @@
++/* Create new context.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++#include <sys/asm.h>
++#include <sys/ucontext.h>
++#include <stdarg.h>
++#include <assert.h>
++
++void
++__makecontext (ucontext_t *ucp, void (*func) (void), int argc, long int a0,
++ long int a1, long int a2, long int a3, long int a4, ...)
++{
++ extern void __start_context (void) attribute_hidden;
++ unsigned long int *sp;
++
++ _Static_assert(LARCH_REG_NARGS == 8,
++ "__makecontext assumes 8 argument registers");
++
++ /* Set up the stack. */
++ sp = (unsigned long int *)
++ (((uintptr_t) ucp->uc_stack.ss_sp + ucp->uc_stack.ss_size) & ALMASK);
++
++ /* Set up the register context.
++ ra = s0 = 0, terminating the stack for backtracing purposes.
++ s1 = the function we must call.
++ s2 = the subsequent context to run. */
++ ucp->uc_mcontext.__gregs[LARCH_REG_RA] = (uintptr_t) 0;
++ ucp->uc_mcontext.__gregs[LARCH_REG_S0] = (uintptr_t) 0;
++ ucp->uc_mcontext.__gregs[LARCH_REG_S1] = (uintptr_t) func;
++ ucp->uc_mcontext.__gregs[LARCH_REG_S2] = (uintptr_t) ucp->uc_link;
++ ucp->uc_mcontext.__gregs[LARCH_REG_SP] = (uintptr_t) sp;
++ ucp->uc_mcontext.__pc = (uintptr_t) &__start_context;
++
++ /* Put args in a0-a7, then put any remaining args on the stack. */
++ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 0] = (uintptr_t) a0;
++ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 1] = (uintptr_t) a1;
++ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 2] = (uintptr_t) a2;
++ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 3] = (uintptr_t) a3;
++ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + 4] = (uintptr_t) a4;
++
++ if (__glibc_unlikely (argc > 5))
++ {
++ va_list vl;
++ va_start (vl, a4);
++
++ long int reg_args = argc < LARCH_REG_NARGS ? argc : LARCH_REG_NARGS;
++ for (long int i = 5; i < reg_args; i++)
++ ucp->uc_mcontext.__gregs[LARCH_REG_A0 + i] = va_arg (vl, unsigned long int);
++
++ long int stack_args = argc - reg_args;
++ if (stack_args > 0)
++ {
++ sp = (unsigned long int *)
++ (((uintptr_t) sp - stack_args * sizeof (long int)) & ALMASK);
++ ucp->uc_mcontext.__gregs[LARCH_REG_SP] = (uintptr_t) sp;
++ for (long int i = 0; i < stack_args; i++)
++ sp[i] = va_arg (vl, unsigned long int);
++ }
++
++ va_end (vl);
++ }
++}
++
++weak_alias (__makecontext, makecontext)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/register-dump.h b/sysdeps/unix/sysv/linux/loongarch/register-dump.h
+new file mode 100644
+index 00000000..9000fc31
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/register-dump.h
+@@ -0,0 +1,61 @@
++/* Dump registers.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <unistd.h>
++#include <string.h>
++#include <_itoa.h>
++
++static void
++hexvalue (unsigned long int value, char *buf, size_t len)
++{
++ char *cp = _itoa_word (value, buf + len, 16, 0);
++ while (cp > buf)
++ *--cp = '0';
++}
++
++#define REGDUMP_NREGS 32
++#define REGDUMP_PER_LINE (80 / (__WORDSIZE / 4 + 4))
++
++static void
++register_dump (int fd, ucontext_t *ctx)
++{
++ int i;
++ char regvalue[__WORDSIZE / 4 + 1];
++ char str[82 * ((REGDUMP_NREGS + REGDUMP_PER_LINE - 1) / REGDUMP_PER_LINE)];
++
++ static const char names[REGDUMP_NREGS][4]
++ = {"pc", "ra", "tp", "sp", "a0", "a1", "a2", "a3", "a4", "a5", "a6",
++ "a7", "t0", "t1", "t2", "t3", "t4", "t5", "t6", "t7", "t8", "x",
++ "fp", "s0", "s1", "s2", "s3", "s4", "s5", "s6", "s7", "s8"};
++
++ str[0] = 0;
++ for (i = 0; i < REGDUMP_NREGS; i++)
++ {
++ strcat (str, names[i]);
++ strcat (str, " ");
++ hexvalue (ctx->uc_mcontext.__gregs[i], regvalue, __WORDSIZE / 4);
++ strcat (str, regvalue);
++
++ if ((i + 1) % REGDUMP_PER_LINE == 0)
++ strcat (str, "\n");
++ }
++
++ write (fd, str, strlen (str));
++}
++
++#define REGISTER_DUMP register_dump (fd, ctx)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/setcontext.S b/sysdeps/unix/sysv/linux/loongarch/setcontext.S
+new file mode 100644
+index 00000000..31d6de0f
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/setcontext.S
+@@ -0,0 +1,100 @@
++/* Set current context.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++#include "sys/regdef.h"
++#include "ucontext-macros.h"
++
++/* int __setcontext (const ucontext_t *ucp)
++
++ Restores the machine context in UCP and thereby resumes execution
++ in that context.
++
++ This implementation is intended to be used for *synchronous* context
++ switches only. Therefore, it does not have to restore anything
++ other than the PRESERVED state. */
++
++ .text
++LEAF (__setcontext)
++
++ addi.d sp, sp, -16
++ st.d a0, sp, 0 /* Save ucp to stack */
++
++/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, NULL, _NSIG8) */
++ li.d a3, _NSIG8
++ li.d a2, 0
++ li.d a1, UCONTEXT_SIGMASK
++ add.d a1, a1, a0
++ li.d a0, SIG_SETMASK
++
++ li.d a7, SYS_ify (rt_sigprocmask)
++ syscall 0
++
++ blt a0, $r0, 99f
++
++ ld.d t0, sp, 0 /* Load ucp to t0 */
++ cfi_def_cfa (12, 0)
++
++/* Note the contents of argument registers will be random
++ unless makecontext() has been called. */
++ RESTORE_INT_REG(ra, 1, t0)
++ RESTORE_INT_REG(sp, 3, t0)
++ RESTORE_INT_REG(a0, 4, t0)
++ RESTORE_INT_REG(a1, 5, t0)
++ RESTORE_INT_REG(a2, 6, t0)
++ RESTORE_INT_REG(a3, 7, t0)
++ RESTORE_INT_REG(a4, 8, t0)
++ RESTORE_INT_REG(a5, 9, t0)
++ RESTORE_INT_REG(a6, 10, t0)
++ RESTORE_INT_REG(a7, 11, t0)
++ RESTORE_INT_REG(x, 21, t0)
++ RESTORE_INT_REG(fp, 22, t0)
++ RESTORE_INT_REG(s0, 23, t0)
++ RESTORE_INT_REG(s1, 24, t0)
++ RESTORE_INT_REG(s2, 25, t0)
++ RESTORE_INT_REG(s3, 26, t0)
++ RESTORE_INT_REG(s4, 27, t0)
++ RESTORE_INT_REG(s5, 28, t0)
++ RESTORE_INT_REG(s6, 29, t0)
++ RESTORE_INT_REG(s7, 30, t0)
++ RESTORE_INT_REG(s8, 31, t0)
++
++ ld.d t1, t0, MCONTEXT_PC
++ jirl $r0,t1,0
++
++99:
++ addi.d sp, sp, 16
++ b __syscall_error
++
++PSEUDO_END (__setcontext)
++weak_alias (__setcontext, setcontext)
++
++LEAF (__start_context)
++
++ /* Terminate call stack by noting ra == 0. Happily, s0 == 0 here. */
++ cfi_register (1, 23)
++
++ /* Call the function passed to makecontext. */
++ jirl $r1,s1,0
++
++ /* Invoke subsequent context if present, else exit(0). */
++ ori a0, s2, 0
++ beqz s2, 1f
++ bl __setcontext
++1:
++ b HIDDEN_JUMPTARGET (exit)
++
++PSEUDO_END (__start_context)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/shlib-versions b/sysdeps/unix/sysv/linux/loongarch/shlib-versions
+new file mode 100644
+index 00000000..dc2220b4
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/shlib-versions
+@@ -0,0 +1,7 @@
++DEFAULT GLIBC_2.36
++
++%if LOONGARCH_ABI_GRLEN == 64 && LOONGARCH_ABI_FRLEN == 64
++ld=ld-linux-loongarch-lp64d.so.1
++%else
++%error cannot determine ABI
++%endif
+diff --git a/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h b/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h
+new file mode 100644
+index 00000000..5e202bc0
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/sigcontextinfo.h
+@@ -0,0 +1,32 @@
++/* LoongArch definitions for signal handling calling conventions.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SIGCONTEXTINFO_H
++#define _SIGCONTEXTINFO_H
++
++#include <stdint.h>
++#include <sys/ucontext.h>
++
++static inline uintptr_t
++sigcontext_get_pc (const ucontext_t *ctx)
++{
++ return ctx->uc_mcontext.__pc;
++}
++
++#endif
+diff --git a/sysdeps/unix/sysv/linux/loongarch/swapcontext.S b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S
+new file mode 100644
+index 00000000..bb22cd2f
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/swapcontext.S
+@@ -0,0 +1,95 @@
++/* Save and set current context.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include "ucontext-macros.h"
++
++/* int swapcontext (ucontext_t *oucp, const ucontext_t *ucp) */
++
++LEAF (__swapcontext)
++ ori a2, sp, 0 /* Save sp to a2 */
++ addi.d sp, sp, -16
++ st.d a1, sp, 0
++ ori t0, a1, 0
++
++ SAVE_INT_REG (ra, 1, a0)
++ SAVE_INT_REG (a2, 3, a0) /* Store sp */
++ SAVE_INT_REG (zero, 4, a0) /* return 0 by overwriting a0 */
++ SAVE_INT_REG (x, 21, a0)
++ SAVE_INT_REG (fp, 22, a0)
++ SAVE_INT_REG (s0, 23, a0)
++ SAVE_INT_REG (s1, 24, a0)
++ SAVE_INT_REG (s2, 25, a0)
++ SAVE_INT_REG (s3, 26, a0)
++ SAVE_INT_REG (s4, 27, a0)
++ SAVE_INT_REG (s5, 28, a0)
++ SAVE_INT_REG (s6, 29, a0)
++ SAVE_INT_REG (s7, 30, a0)
++ SAVE_INT_REG (s8, 31, a0)
++
++ st.d ra, a0, MCONTEXT_PC
++
++/* rt_sigprocmask (SIG_SETMASK, &ucp->uc_sigmask, &oucp->uc_sigmask, _NSIG8) */
++ li.d a3, _NSIG8
++ li.d a2, UCONTEXT_SIGMASK
++ add.d a2, a2, a0
++ li.d a1, UCONTEXT_SIGMASK
++ add.d a1, a1, t0
++ li.d a0, SIG_SETMASK
++
++ li.d a7, SYS_ify (rt_sigprocmask)
++ syscall 0
++
++ blt a0, zero, 99f
++
++ ld.d t0, sp, 0 /* Load a1 to t0 */
++
++/* Note the contents of argument registers will be random
++ unless makecontext() has been called. */
++ RESTORE_INT_REG (ra, 1, t0)
++ RESTORE_INT_REG (sp, 3, t0)
++ RESTORE_INT_REG (a0, 4, t0)
++ RESTORE_INT_REG (a1, 5, t0)
++ RESTORE_INT_REG (a2, 6, t0)
++ RESTORE_INT_REG (a3, 7, t0)
++ RESTORE_INT_REG (a4, 8, t0)
++ RESTORE_INT_REG (a5, 9, t0)
++ RESTORE_INT_REG (a6, 10, t0)
++ RESTORE_INT_REG (a7, 11, t0)
++ RESTORE_INT_REG (x, 21, t0)
++ RESTORE_INT_REG (fp, 22, t0)
++ RESTORE_INT_REG (s0, 23, t0)
++ RESTORE_INT_REG (s1, 24, t0)
++ RESTORE_INT_REG (s2, 25, t0)
++ RESTORE_INT_REG (s3, 26, t0)
++ RESTORE_INT_REG (s4, 27, t0)
++ RESTORE_INT_REG (s5, 28, t0)
++ RESTORE_INT_REG (s6, 29, t0)
++ RESTORE_INT_REG (s7, 30, t0)
++ RESTORE_INT_REG (s8, 31, t0)
++
++ ld.d t1, t0, MCONTEXT_PC
++ jirl $r0, t1, 0
++
++
++99:
++ addi.d sp, sp, 16
++ b __syscall_error
++
++PSEUDO_END (__swapcontext)
++
++weak_alias (__swapcontext, swapcontext)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h b/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h
+new file mode 100644
+index 00000000..db86380d
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/sys/ucontext.h
+@@ -0,0 +1,64 @@
++/* struct ucontext definition.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Don't rely on this, the interface is currently messed up and may need to
++ be broken to be fixed. */
++#ifndef _SYS_UCONTEXT_H
++#define _SYS_UCONTEXT_H 1
++
++#include <features.h>
++
++#include <bits/types/sigset_t.h>
++#include <bits/types/stack_t.h>
++
++#ifdef __USE_MISC
++#define LARCH_NGREG 32
++
++#define LARCH_REG_RA 1
++#define LARCH_REG_SP 3
++#define LARCH_REG_S0 23
++#define LARCH_REG_S1 24
++#define LARCH_REG_A0 4
++#define LARCH_REG_S2 25
++#define LARCH_REG_NARGS 8
++
++typedef unsigned long int greg_t;
++/* Container for all general registers. */
++typedef greg_t gregset_t[32];
++#endif
++
++typedef struct mcontext_t
++{
++ unsigned long long __pc;
++ unsigned long long __gregs[32];
++ unsigned int __flags;
++ unsigned long long __extcontext[0] __attribute__((__aligned__(16)));
++} mcontext_t;
++
++/* Userlevel context. */
++typedef struct ucontext_t
++{
++ unsigned long int __uc_flags;
++ struct ucontext_t *uc_link;
++ stack_t uc_stack;
++ sigset_t uc_sigmask;
++ mcontext_t uc_mcontext;
++} ucontext_t;
++
++#endif /* sys/ucontext.h */
+diff --git a/sysdeps/unix/sysv/linux/loongarch/sys/user.h b/sysdeps/unix/sysv/linux/loongarch/sys/user.h
+new file mode 100644
+index 00000000..640b9b33
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/sys/user.h
+@@ -0,0 +1,42 @@
++/* struct user_regs_struct definition for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_USER_H
++#define _SYS_USER_H 1
++
++#include <stdint.h>
++
++struct user_regs_struct
++{
++ /* Saved main processor registers. */
++ uint64_t regs[32];
++
++ /* Saved special registers. */
++ uint64_t orig_a0;
++ uint64_t csr_era;
++ uint64_t csr_badv;
++ uint64_t reserved[10];
++};
++
++struct user_fp_struct {
++ uint64_t fpr[32];
++ uint64_t fcc;
++ uint32_t fcsr;
++};
++
++#endif /* _SYS_USER_H */
+diff --git a/sysdeps/unix/sysv/linux/loongarch/syscall.c b/sysdeps/unix/sysv/linux/loongarch/syscall.c
+new file mode 100644
+index 00000000..d0067bc2
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/syscall.c
+@@ -0,0 +1,35 @@
++/* system call interface.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++long int
++syscall (long int syscall_number, long int arg1, long int arg2, long int arg3,
++ long int arg4, long int arg5, long int arg6, long int arg7)
++{
++ long int ret;
++
++ ret = INTERNAL_SYSCALL_NCS (syscall_number, 7, arg1, arg2, arg3, arg4, arg5,
++ arg6, arg7);
++
++ if (INTERNAL_SYSCALL_ERROR_P (ret))
++ return __syscall_error (ret);
++
++ return ret;
++}
+diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.S b/sysdeps/unix/sysv/linux/loongarch/sysdep.S
+new file mode 100644
+index 00000000..865de9b2
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.S
+@@ -0,0 +1,53 @@
++/* syscall error handlers
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++#if IS_IN (libc)
++# define errno __libc_errno
++#endif
++
++ENTRY (__syscall_error)
++/* Fall through to __syscall_set_errno */
++END (__syscall_error)
++
++/* Non-standard calling convention: argument in a0, return address in t0,
++ and clobber only t1.
++ */
++ENTRY (__syscall_set_errno)
++
++/* We got here because a0 < 0, but only codes in the range [-4095, -1]
++ represent errors. Otherwise, just return the result normally.
++ */
++ li.d t1, -4096
++ bgeu t1, a0, L (out)
++ sub.w a0, zero, a0
++#if RTLD_PRIVATE_ERRNO
++ la t1, rtld_errno
++#elif defined(__PIC__)
++ la.tls.ie t1, errno
++ add.d t1, tp, t1
++#else
++ la.tls.le t1, errno
++ add.d t1, tp, t1
++#endif
++ st.w a0, t1, 0
++ li.d a0, -1
++L (out):
++ ret
++END (__syscall_set_errno)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/sysdep.h b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
+new file mode 100644
+index 00000000..b2587091
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/sysdep.h
+@@ -0,0 +1,320 @@
++/* Assembly macros for LoongArch.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LINUX_LOONGARCH_SYSDEP_H
++#define _LINUX_LOONGARCH_SYSDEP_H 1
++
++#include <sysdeps/unix/sysv/linux/generic/sysdep.h>
++#include <tls.h>
++
++#ifdef __ASSEMBLER__
++
++#include <sys/asm.h>
++#define ret jirl zero, ra, 0
++#define L(label) .L##label
++
++/* Performs a system call, handling errors by setting errno. Linux indicates
++ errors by setting a0 to a value between -1 and -4095. */
++#undef PSEUDO
++#define PSEUDO(name, syscall_name, args) \
++ ENTRY (name); \
++ li.d a7, SYS_ify (syscall_name); \
++ syscall 0; \
++ li.d a7, -4096; \
++ bltu a7, a0, .Lsyscall_error##name;
++
++#undef PSEUDO_END
++#define PSEUDO_END(sym) \
++ SYSCALL_ERROR_HANDLER (sym); \
++ ret; \
++ END (sym);
++
++#if !IS_IN(libc)
++#if RTLD_PRIVATE_ERRNO
++
++#define SYSCALL_ERROR_HANDLER(name) \
++ .Lsyscall_error##name : la t0, rtld_errno; \
++ sub.w a0, zero, a0; \
++ st.w a0, t0, 0; \
++ li.d a0, -1;
++
++#else
++
++#define SYSCALL_ERROR_HANDLER(name) \
++ .Lsyscall_error##name : la.tls.ie t0, errno; \
++ add.d t0, tp, t0; \
++ sub.w a0, zero, a0; \
++ st.w a0, t0, 0; \
++ li.d a0, -1;
++
++#endif
++#else
++
++#define SYSCALL_ERROR_HANDLER(name) .Lsyscall_error##name : b __syscall_error;
++
++#endif
++
++/* Performs a system call, not setting errno. */
++#undef PSEUDO_NEORRNO
++#define PSEUDO_NOERRNO(name, syscall_name, args) \
++ ENTRY (name); \
++ li.d a7, SYS_ify (syscall_name); \
++ syscall 0;
++
++#undef PSEUDO_END_NOERRNO
++#define PSEUDO_END_NOERRNO(name) END (name);
++
++#undef ret_NOERRNO
++#define ret_NOERRNO ret
++
++/* Perfroms a system call, returning the error code. */
++#undef PSEUDO_ERRVAL
++#define PSEUDO_ERRVAL(name, syscall_name, args) \
++ PSEUDO_NOERRNO (name, syscall_name, args); \
++ slli.d a0, a0, 32; \
++ srai.d a0, a0, 32; /* sign_ext */ \
++ sub.d a0, zero, a0;
++
++#undef PSEUDO_END_ERRVAL
++#define PSEUDO_END_ERRVAL(name) END (name);
++
++#undef ret_ERRVAL
++#define ret_ERRVAL ret
++
++#endif /* __ASSEMBLER__ */
++
++/* In order to get __set_errno() definition in INLINE_SYSCALL. */
++#ifndef __ASSEMBLER__
++#include <errno.h>
++#endif
++
++#include <sysdeps/unix/sysdep.h>
++
++#undef SYS_ify
++#define SYS_ify(syscall_name) __NR_##syscall_name
++
++#ifndef __ASSEMBLER__
++
++#define VDSO_NAME "LINUX_5.10"
++#define VDSO_HASH 182947696
++
++/* List of system calls which are supported as vsyscalls. */
++#define HAVE_CLOCK_GETRES64_VSYSCALL "__vdso_clock_getres"
++#define HAVE_CLOCK_GETTIME64_VSYSCALL "__vdso_clock_gettime"
++#define HAVE_GETCPU_VSYSCALL "__vdso_getcpu"
++
++#define HAVE_CLONE3_WRAPPER 1
++
++#define INTERNAL_SYSCALL(name, nr, args...) \
++ internal_syscall##nr (SYS_ify (name), args)
++
++#define INTERNAL_SYSCALL_NCS(number, nr, args...) \
++ internal_syscall##nr (number, args)
++
++#define internal_syscall0(number, dummy...) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0"); \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "=r"(__a0) \
++ : "r"(__a7) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define internal_syscall1(number, arg0) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ long int _arg0 = (long int) (arg0); \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0") = _arg0; \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "+r"(__a0) \
++ : "r"(__a7) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define internal_syscall2(number, arg0, arg1) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ long int _arg0 = (long int) (arg0); \
++ long int _arg1 = (long int) (arg1); \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0") = _arg0; \
++ register long int __a1 asm ("$a1") = _arg1; \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "+r"(__a0) \
++ : "r"(__a7), "r"(__a1) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define internal_syscall3(number, arg0, arg1, arg2) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ long int _arg0 = (long int) (arg0); \
++ long int _arg1 = (long int) (arg1); \
++ long int _arg2 = (long int) (arg2); \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0") = _arg0; \
++ register long int __a1 asm ("$a1") = _arg1; \
++ register long int __a2 asm ("$a2") = _arg2; \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "+r"(__a0) \
++ : "r"(__a7), "r"(__a1), "r"(__a2) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define internal_syscall4(number, arg0, arg1, arg2, arg3) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ long int _arg0 = (long int) (arg0); \
++ long int _arg1 = (long int) (arg1); \
++ long int _arg2 = (long int) (arg2); \
++ long int _arg3 = (long int) (arg3); \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0") = _arg0; \
++ register long int __a1 asm ("$a1") = _arg1; \
++ register long int __a2 asm ("$a2") = _arg2; \
++ register long int __a3 asm ("$a3") = _arg3; \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "+r"(__a0) \
++ : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define internal_syscall5(number, arg0, arg1, arg2, arg3, arg4) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ long int _arg0 = (long int) (arg0); \
++ long int _arg1 = (long int) (arg1); \
++ long int _arg2 = (long int) (arg2); \
++ long int _arg3 = (long int) (arg3); \
++ long int _arg4 = (long int) (arg4); \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0") = _arg0; \
++ register long int __a1 asm ("$a1") = _arg1; \
++ register long int __a2 asm ("$a2") = _arg2; \
++ register long int __a3 asm ("$a3") = _arg3; \
++ register long int __a4 asm ("$a4") = _arg4; \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "+r"(__a0) \
++ : "r"(__a7), "r"(__a1), "r"(__a2), \
++ "r"(__a3), "r"(__a4) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define internal_syscall6(number, arg0, arg1, arg2, arg3, arg4, arg5) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ long int _arg0 = (long int) (arg0); \
++ long int _arg1 = (long int) (arg1); \
++ long int _arg2 = (long int) (arg2); \
++ long int _arg3 = (long int) (arg3); \
++ long int _arg4 = (long int) (arg4); \
++ long int _arg5 = (long int) (arg5); \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0") = _arg0; \
++ register long int __a1 asm ("$a1") = _arg1; \
++ register long int __a2 asm ("$a2") = _arg2; \
++ register long int __a3 asm ("$a3") = _arg3; \
++ register long int __a4 asm ("$a4") = _arg4; \
++ register long int __a5 asm ("$a5") = _arg5; \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "+r"(__a0) \
++ : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \
++ "r"(__a4), "r"(__a5) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define internal_syscall7(number, arg0, arg1, arg2, arg3, arg4, arg5, arg6) \
++ ({ \
++ long int _sys_result; \
++\
++ { \
++ long int _arg0 = (long int) (arg0); \
++ long int _arg1 = (long int) (arg1); \
++ long int _arg2 = (long int) (arg2); \
++ long int _arg3 = (long int) (arg3); \
++ long int _arg4 = (long int) (arg4); \
++ long int _arg5 = (long int) (arg5); \
++ long int _arg6 = (long int) (arg6); \
++ register long int __a7 asm ("$a7") = number; \
++ register long int __a0 asm ("$a0") = _arg0; \
++ register long int __a1 asm ("$a1") = _arg1; \
++ register long int __a2 asm ("$a2") = _arg2; \
++ register long int __a3 asm ("$a3") = _arg3; \
++ register long int __a4 asm ("$a4") = _arg4; \
++ register long int __a5 asm ("$a5") = _arg5; \
++ register long int __a6 asm ("$a6") = _arg6; \
++ __asm__ volatile ("syscall 0\n\t" \
++ : "+r"(__a0) \
++ : "r"(__a7), "r"(__a1), "r"(__a2), "r"(__a3), \
++ "r"(__a4), "r"(__a5), "r"(__a6) \
++ : __SYSCALL_CLOBBERS); \
++ _sys_result = __a0; \
++ } \
++ _sys_result; \
++ })
++
++#define __SYSCALL_CLOBBERS \
++ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", "memory"
++
++extern long int __syscall_error (long int neg_errno);
++
++#endif /* ! __ASSEMBLER__ */
++
++/* Pointer mangling is not supported. */
++#define PTR_MANGLE(var) (void) (var)
++#define PTR_DEMANGLE(var) (void) (var)
++
++#endif /* linux/loongarch/sysdep.h */
+diff --git a/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h
+new file mode 100644
+index 00000000..859eba46
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/ucontext-macros.h
+@@ -0,0 +1,32 @@
++/* Macros for ucontext routines.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _LINUX_LOONGARCH_UCONTEXT_MACROS_H
++#define _LINUX_LOONGARCH_UCONTEXT_MACROS_H
++
++#include <sysdep.h>
++#include <sys/asm.h>
++#include "ucontext_i.h"
++
++#define SAVE_INT_REG(name, num, base) \
++ REG_S name, base, ((num) *SZREG + MCONTEXT_GREGS)
++
++#define RESTORE_INT_REG(name, num, base) \
++ REG_L name, base, ((num) *SZREG + MCONTEXT_GREGS)
++
++#endif /* _LINUX_LOONGARCH_UCONTEXT_MACROS_H */
+diff --git a/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym b/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym
+new file mode 100644
+index 00000000..f27afad5
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/ucontext_i.sym
+@@ -0,0 +1,31 @@
++#include <inttypes.h>
++#include <signal.h>
++#include <stddef.h>
++#include <sys/ucontext.h>
++
++-- Constants used by the rt_sigprocmask call.
++
++SIG_BLOCK
++SIG_SETMASK
++
++_NSIG8 (_NSIG / 8)
++
++-- Offsets of the fields in the ucontext_t structure.
++#define ucontext(member) offsetof (ucontext_t, member)
++#define stack(member) ucontext (uc_stack.member)
++#define mcontext(member) ucontext (uc_mcontext.member)
++
++UCONTEXT_FLAGS ucontext (__uc_flags)
++UCONTEXT_LINK ucontext (uc_link)
++UCONTEXT_STACK ucontext (uc_stack)
++UCONTEXT_MCONTEXT ucontext (uc_mcontext)
++UCONTEXT_SIGMASK ucontext (uc_sigmask)
++
++STACK_SP stack (ss_sp)
++STACK_SIZE stack (ss_size)
++STACK_FLAGS stack (ss_flags)
++
++MCONTEXT_PC mcontext (__pc)
++MCONTEXT_GREGS mcontext (__gregs)
++
++UCONTEXT_SIZE sizeof (ucontext_t)
+diff --git a/sysdeps/unix/sysv/linux/loongarch/vfork.S b/sysdeps/unix/sysv/linux/loongarch/vfork.S
+new file mode 100644
+index 00000000..585f98ee
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/loongarch/vfork.S
+@@ -0,0 +1,50 @@
++/* vfork for Linux.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public License as
++ published by the Free Software Foundation; either version 2.1 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++#define _ERRNO_H 1
++#include <bits/errno.h>
++
++/* Clone the calling process, but without copying the whole address space.
++ The calling process is suspended until the new process exits or is
++ replaced by a call to `execve'. Return -1 for errors, 0 to the new process,
++ and the process ID of the new process to the old process. */
++
++ENTRY (__vfork)
++
++ li.d a0, 0x4111 /* CLONE_VM | CLONE_VFORK | SIGCHLD */
++ add.d a1, zero, sp
++
++ /* Do the system call. */
++ li.d a7, __NR_clone
++ syscall 0
++
++ blt a0, zero ,L (error)
++
++ ret
++
++L (error):
++ b __syscall_error
++
++END (__vfork)
++
++libc_hidden_def (__vfork)
++
++weak_alias (__vfork, vfork)
++strong_alias (__vfork, __libc_vfork)
+--
+2.33.0
+
diff --git a/Remove-_dl_skip_args_internal-declaration.patch b/Remove-_dl_skip_args_internal-declaration.patch
new file mode 100644
index 0000000..1970f11
--- /dev/null
+++ b/Remove-_dl_skip_args_internal-declaration.patch
@@ -0,0 +1,34 @@
+From 707efc2955a90299d8af8211756e2256fbc20c6e Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Wed, 6 Apr 2022 16:56:07 +0100
+Subject: [PATCH] Remove _dl_skip_args_internal declaration
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=707efc2955a90299d8af8211756e2256fbc20c6e
+
+It does not seem to be used.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+---
+ sysdeps/generic/ldsodefs.h | 5 -----
+ 1 file changed, 5 deletions(-)
+
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index 44750461a9..29f005499b 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -781,11 +781,6 @@ extern char **_dl_argv
+ rtld_hidden_proto (_dl_argv)
+ #if IS_IN (rtld)
+ extern unsigned int _dl_skip_args attribute_hidden
+-# ifndef DL_ARGV_NOT_RELRO
+- attribute_relro
+-# endif
+- ;
+-extern unsigned int _dl_skip_args_internal attribute_hidden
+ # ifndef DL_ARGV_NOT_RELRO
+ attribute_relro
+ # endif
+--
+2.27.0
+
diff --git a/Remove-sysdeps-tls-macros.h.patch b/Remove-sysdeps-tls-macros.h.patch
new file mode 100644
index 0000000..82561b7
--- /dev/null
+++ b/Remove-sysdeps-tls-macros.h.patch
@@ -0,0 +1,1810 @@
+From 710ba420fd417a4a82e0ad2e998e5f3b972cb503 Mon Sep 17 00:00:00 2001
+From: Fangrui Song <maskray@google.com>
+Date: Wed, 18 Aug 2021 09:15:20 -0700
+Subject: [PATCH] Remove sysdeps/*/tls-macros.h
+
+They provide TLS_GD/TLS_LD/TLS_IE/TLS_IE macros for TLS testing. Now
+that we have migrated to __thread and tls_model attributes, these macros
+are unused and the tls-macros.h files can retire.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ benchtests/strcoll-inputs/filelist#en_US.UTF-8 | 22 ----
+ sysdeps/aarch64/tls-macros.h | 51 ---------
+ sysdeps/alpha/tls-macros.h | 25 -----
+ sysdeps/arc/tls-macros.h | 47 --------
+ sysdeps/arm/tls-macros.h | 72 -------------
+ sysdeps/csky/abiv2/tls-macros.h | 55 ----------
+ sysdeps/generic/tls-macros.h | 12 ---
+ sysdeps/hppa/tls-macros.h | 114 --------------------
+ sysdeps/i386/tls-macros.h | 47 --------
+ sysdeps/ia64/tls-macros.h | 66 ------------
+ sysdeps/m68k/tls-macros.h | 68 ------------
+ sysdeps/microblaze/tls-macros.h | 46 --------
+ sysdeps/mips/tls-macros.h | 130 ----------------------
+ sysdeps/nios2/tls-macros.h | 46 --------
+ sysdeps/powerpc/powerpc32/tls-macros.h | 49 ---------
+ sysdeps/powerpc/powerpc64/tls-macros.h | 42 --------
+ sysdeps/powerpc/tls-macros.h | 3 -
+ sysdeps/riscv/tls-macros.h | 47 --------
+ sysdeps/s390/s390-32/tls-macros.h | 106 ------------------
+ sysdeps/s390/s390-64/tls-macros.h | 90 ----------------
+ sysdeps/sh/tls-macros.h | 143 -------------------------
+ sysdeps/sparc/sparc32/tls-macros.h | 66 ------------
+ sysdeps/sparc/sparc64/tls-macros.h | 65 -----------
+ sysdeps/x86_64/tls-macros.h | 39 -------
+ 24 files changed, 1451 deletions(-)
+ delete mode 100644 sysdeps/aarch64/tls-macros.h
+ delete mode 100644 sysdeps/alpha/tls-macros.h
+ delete mode 100644 sysdeps/arc/tls-macros.h
+ delete mode 100644 sysdeps/arm/tls-macros.h
+ delete mode 100644 sysdeps/csky/abiv2/tls-macros.h
+ delete mode 100644 sysdeps/generic/tls-macros.h
+ delete mode 100644 sysdeps/hppa/tls-macros.h
+ delete mode 100644 sysdeps/i386/tls-macros.h
+ delete mode 100644 sysdeps/ia64/tls-macros.h
+ delete mode 100644 sysdeps/m68k/tls-macros.h
+ delete mode 100644 sysdeps/microblaze/tls-macros.h
+ delete mode 100644 sysdeps/mips/tls-macros.h
+ delete mode 100644 sysdeps/nios2/tls-macros.h
+ delete mode 100644 sysdeps/powerpc/powerpc32/tls-macros.h
+ delete mode 100644 sysdeps/powerpc/powerpc64/tls-macros.h
+ delete mode 100644 sysdeps/powerpc/tls-macros.h
+ delete mode 100644 sysdeps/riscv/tls-macros.h
+ delete mode 100644 sysdeps/s390/s390-32/tls-macros.h
+ delete mode 100644 sysdeps/s390/s390-64/tls-macros.h
+ delete mode 100644 sysdeps/sh/tls-macros.h
+ delete mode 100644 sysdeps/sparc/sparc32/tls-macros.h
+ delete mode 100644 sysdeps/sparc/sparc64/tls-macros.h
+ delete mode 100644 sysdeps/x86_64/tls-macros.h
+
+diff --git a/benchtests/strcoll-inputs/filelist#en_US.UTF-8 b/benchtests/strcoll-inputs/filelist#en_US.UTF-8
+index 43eb9ef..197700e 100644
+--- a/benchtests/strcoll-inputs/filelist#en_US.UTF-8
++++ b/benchtests/strcoll-inputs/filelist#en_US.UTF-8
+@@ -3195,7 +3195,6 @@ Implies
+ submul_1.S
+ sysdep.h
+ add_n.S
+-tls-macros.h
+ libc-tls.c
+ sub_n.S
+ libgcc-compat.c
+@@ -3443,7 +3442,6 @@ libresolv.abilist
+ thread_state.h
+ pty-private.h
+ ldconfig.h
+-tls-macros.h
+ fd_to_filename.h
+ not-cancel.h
+ safe-fatal.h
+@@ -3605,7 +3603,6 @@ start.S
+ tst-mode-switch-3.c
+ addmul_1.S
+ add_n.S
+-tls-macros.h
+ libc-tls.c
+ sub_n.S
+ strcmp.S
+@@ -3921,7 +3918,6 @@ addmul_1.S
+ pthread_spin_trylock.S
+ add_n.S
+ e_sqrt.c
+-tls-macros.h
+ sub_n.S
+ strcmp.S
+ strlen.S
+@@ -4138,7 +4134,6 @@ addmul_1.S
+ pthread_spin_trylock.S
+ add_n.S
+ rtld-memset.c
+-tls-macros.h
+ sub_n.S
+ strcmp.S
+ strlen.S
+@@ -4651,7 +4646,6 @@ addmul_1.S
+ sysdep.h
+ strlen.c
+ add_n.S
+-tls-macros.h
+ sub_n.S
+ i786
+ Implies
+@@ -4712,7 +4706,6 @@ Makefile
+ start.S
+ libm-test-ulps
+ sysdep.h
+-tls-macros.h
+ libc-tls.c
+ tst-audit.h
+ dl-machine.h
+@@ -5071,7 +5064,6 @@ addmul_1.S
+ sysdep.h
+ add_n.S
+ wcschr.S
+-tls-macros.h
+ sub_n.S
+ tst-quad2.c
+ strcmp.S
+@@ -6337,7 +6329,6 @@ Makefile
+ start.S
+ libm-test-ulps
+ sysdep.h
+-tls-macros.h
+ libc-tls.c
+ strlen.S
+ tst-audit.h
+@@ -6447,7 +6438,6 @@ strstr.c
+ string-endian.h
+ memcmp.c
+ sysdep.h
+-tls-macros.h
+ tst-audit.h
+ dl-machine.h
+ dl-tls.h
+@@ -6581,7 +6571,6 @@ Makefile
+ start.S
+ libm-test-ulps
+ sysdep.h
+-tls-macros.h
+ libc-tls.c
+ strcmp.S
+ strrchr.S
+@@ -7004,7 +6993,6 @@ addmul_1.S
+ Implies
+ sysdep.h
+ rtld-memset.c
+-tls-macros.h
+ strcmp.S
+ strlen.S
+ tst-audit.h
+@@ -7124,7 +7112,6 @@ wcschr.c
+ Makefile
+ ffs.c
+ sysdep.h
+-tls-macros.h
+ test-arithf.c
+ nofpu
+ atomic-feupdateenv.c
+@@ -7386,7 +7373,6 @@ gprrest0.S
+ sysdep.h
+ add_n.S
+ rtld-memset.c
+-tls-macros.h
+ sub_n.S
+ strcmp.S
+ strlen.S
+@@ -7969,7 +7955,6 @@ memcmp.S
+ Makefile
+ start.S
+ sysdep.h
+-tls-macros.h
+ libc-tls.c
+ strcmp.S
+ sched_cpucount.c
+@@ -8197,7 +8182,6 @@ start.S
+ addmul_1.S
+ nscd-types.h
+ add_n.S
+-tls-macros.h
+ libc-tls.c
+ sub_n.S
+ divqu.S
+@@ -8318,7 +8302,6 @@ Makefile
+ ffs.c
+ start.S
+ sysdep.h
+-tls-macros.h
+ libc-tls.c
+ tst-audit.h
+ wcpcpy.c
+@@ -8628,7 +8611,6 @@ Makefile
+ start.S
+ sysdep.h
+ add_n.S
+-tls-macros.h
+ sub_n.S
+ strcmp.S
+ tst-audit.h
+@@ -8690,7 +8672,6 @@ start.S
+ addmul_1.S
+ sysdep.h
+ add_n.S
+-tls-macros.h
+ sub_n.S
+ strcmp.S
+ tst-audit.h
+@@ -8796,7 +8777,6 @@ ftestexcept.c
+ rt-aeabi_unwind_cpp_pr1.c
+ sysdep.h
+ add_n.S
+-tls-macros.h
+ libc-tls.c
+ sub_n.S
+ strlen.S
+@@ -8879,7 +8859,6 @@ Makefile
+ start.S
+ libm-test-ulps
+ sysdep.h
+-tls-macros.h
+ libc-tls.c
+ tst-audit.h
+ dl-machine.h
+@@ -12064,7 +12043,6 @@ nodelmod4.c
+ dl-fini.c
+ unload2dep.c
+ unload8.c
+-tls-macros.h
+ unload4.c
+ tst-array5.exp
+ unload4mod2.c
+diff --git a/sysdeps/aarch64/tls-macros.h b/sysdeps/aarch64/tls-macros.h
+deleted file mode 100644
+index 33883dc..0000000
+--- a/sysdeps/aarch64/tls-macros.h
++++ /dev/null
+@@ -1,51 +0,0 @@
+-/* Copyright (C) 2009-2021 Free Software Foundation, Inc.
+-
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public License as
+- published by the Free Software Foundation; either version 2.1 of the
+- License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#define TLS_LD(x) TLS_GD(x)
+-
+-#define TLS_GD(x) \
+- ({ register unsigned long __result asm ("x0"); \
+- asm ("adrp %0, :tlsgd:" #x "; " \
+- "add %0, %0, #:tlsgd_lo12:" #x "; " \
+- "bl __tls_get_addr;" \
+- "nop" \
+- : "=r" (__result) \
+- : \
+- : "x1", "x2", "x3", "x4", "x5", "x6", \
+- "x7", "x8", "x9", "x10", "x11", "x12", \
+- "x13", "x14", "x15", "x16", "x17", "x18", \
+- "x30", "memory", "cc"); \
+- (int *) (__result); })
+-
+-#define TLS_IE(x) \
+- ({ register unsigned long __result asm ("x0"); \
+- register unsigned long __t; \
+- asm ("mrs %1, tpidr_el0; " \
+- "adrp %0, :gottprel:" #x "; " \
+- "ldr %0, [%0, #:gottprel_lo12:" #x "]; " \
+- "add %0, %0, %1" \
+- : "=r" (__result), "=r" (__t)); \
+- (int *) (__result); })
+-
+-#define TLS_LE(x) \
+- ({ register unsigned long __result asm ("x0"); \
+- asm ("mrs %0, tpidr_el0; " \
+- "add %0, %0, :tprel_hi12:" #x "; " \
+- "add %0, %0, :tprel_lo12_nc:" #x \
+- : "=r" (__result)); \
+- (int *) (__result); })
+diff --git a/sysdeps/alpha/tls-macros.h b/sysdeps/alpha/tls-macros.h
+deleted file mode 100644
+index 00489c2..0000000
+--- a/sysdeps/alpha/tls-macros.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* Macros to support TLS testing in times of missing compiler support. */
+-
+-extern void *__tls_get_addr (void *);
+-
+-# define TLS_GD(x) \
+- ({ register void *__gp asm ("$29"); void *__result; \
+- asm ("lda %0, " #x "($gp) !tlsgd" : "=r" (__result) : "r"(__gp)); \
+- __tls_get_addr (__result); })
+-
+-# define TLS_LD(x) \
+- ({ register void *__gp asm ("$29"); void *__result; \
+- asm ("lda %0, " #x "($gp) !tlsldm" : "=r" (__result) : "r"(__gp)); \
+- __result = __tls_get_addr (__result); \
+- asm ("lda %0, " #x "(%0) !dtprel" : "+r" (__result)); \
+- __result; })
+-
+-# define TLS_IE(x) \
+- ({ register void *__gp asm ("$29"); long ofs; \
+- asm ("ldq %0, " #x "($gp) !gottprel" : "=r"(ofs) : "r"(__gp)); \
+- __builtin_thread_pointer () + ofs; })
+-
+-# define TLS_LE(x) \
+- ({ void *__result = __builtin_thread_pointer (); \
+- asm ("lda %0, " #x "(%0) !tprel" : "+r" (__result)); \
+- __result; })
+diff --git a/sysdeps/arc/tls-macros.h b/sysdeps/arc/tls-macros.h
+deleted file mode 100644
+index b0003d8..0000000
+--- a/sysdeps/arc/tls-macros.h
++++ /dev/null
+@@ -1,47 +0,0 @@
+-/* Macros to support TLS testing in times of missing compiler support. ARC version.
+- Copyright (C) 2020-2021 Free Software Foundation, Inc.
+-
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-
+-/* For now. */
+-#define TLS_LD(x) TLS_IE(x)
+-
+-#define TLS_GD(x) \
+- ({ void *__result; \
+- __asm__ ("add r0, pcl, @" #x "@tlsgd \n" \
+- ".tls_gd_ld " #x "`bl __tls_get_addr@plt \n" \
+- "mov %0, r0 \n" \
+- : "=&r" (__result) \
+- ::"r0","r1","r2","r3","r4","r5","r6","r7", \
+- "r8","r9","r10","r11","r12"); \
+- __result; })
+-
+-#define TLS_LE(x) \
+- ({ void *__result; \
+- void *tp = __builtin_thread_pointer (); \
+- __asm__ ("add %0, %1, @" #x "@tpoff \n" \
+- : "=r" (__result) : "r"(tp)); \
+- __result; })
+-
+-#define TLS_IE(x) \
+- ({ void *__result; \
+- void *tp = __builtin_thread_pointer (); \
+- __asm__ ("ld %0, [pcl, @" #x "@tlsie] \n" \
+- "add %0, %1, %0 \n" \
+- : "=&r" (__result) : "r" (tp)); \
+- __result; })
+diff --git a/sysdeps/arm/tls-macros.h b/sysdeps/arm/tls-macros.h
+deleted file mode 100644
+index 25cd849..0000000
+--- a/sysdeps/arm/tls-macros.h
++++ /dev/null
+@@ -1,72 +0,0 @@
+-#include <sysdep.h> /* For ARCH_HAS_T2. */
+-
+-#ifdef __thumb2__
+-# define ARM_PC_OFFSET "4"
+-#else
+-# define ARM_PC_OFFSET "8"
+-#endif
+-
+-/* Returns the address of data containing ".word SYMBOL(RELOC)". */
+-#if defined (ARCH_HAS_T2) && !defined (PIC)
+-# define GET_SPECIAL_RELOC(symbol, reloc) \
+- ({ \
+- int *__##symbol##_rodata; \
+- asm ("movw %0, #:lower16:1f\n" \
+- "movt %0, #:upper16:1f\n" \
+- ".pushsection .rodata.cst4, \"aM\", %%progbits, 4\n" \
+- ".balign 4\n" \
+- "1: .word " #symbol "(" #reloc ")\n" \
+- ".popsection" \
+- : "=r" (__##symbol##_rodata)); \
+- __##symbol##_rodata; \
+- })
+-#elif defined (ARCH_HAS_T2) && defined (PIC) && ARM_PCREL_MOVW_OK
+-# define GET_SPECIAL_RELOC(symbol, reloc) \
+- ({ \
+- int *__##symbol##_rodata; \
+- asm ("movw %0, #:lower16:1f - 2f - " ARM_PC_OFFSET "\n" \
+- "movt %0, #:upper16:1f - 2f - " ARM_PC_OFFSET "\n" \
+- ".pushsection .rodata.cst4, \"aM\", %%progbits, 4\n" \
+- ".balign 4\n" \
+- "1: .word " #symbol "(" #reloc ")\n" \
+- ".popsection\n" \
+- "2: add %0, %0, pc" \
+- : "=r" (__##symbol##_rodata)); \
+- __##symbol##_rodata; \
+- })
+-#else
+-# define GET_SPECIAL_RELOC(symbol, reloc) \
+- ({ \
+- int *__##symbol##_rodata; \
+- asm ("adr %0, 1f\n" \
+- "b 2f\n" \
+- ".balign 4\n" \
+- "1: .word " #symbol "(" #reloc ")\n" \
+- "2:" \
+- : "=r" (__##symbol##_rodata)); \
+- __##symbol##_rodata; \
+- })
+-#endif
+-
+-/* Returns the pointer value (SYMBOL(RELOC) + pc - PC_OFS). */
+-#define GET_SPECIAL_PCREL(symbol, reloc) \
+- ({ \
+- int *__##symbol##_rodata = GET_SPECIAL_RELOC (symbol, reloc); \
+- (void *) ((int) __##symbol##_rodata + *__##symbol##_rodata); \
+- })
+-
+-#define TLS_LE(x) \
+- (__builtin_thread_pointer () + *GET_SPECIAL_RELOC (x, tpoff))
+-
+-#define TLS_IE(x) \
+- ((int *) (__builtin_thread_pointer () \
+- + *(int *) GET_SPECIAL_PCREL (x, gottpoff)))
+-
+-extern void *__tls_get_addr (void *);
+-
+-#define TLS_LD(x) \
+- ((int *) (__tls_get_addr (GET_SPECIAL_PCREL (x, tlsldm)) \
+- + *GET_SPECIAL_RELOC (x, tlsldo)))
+-
+-#define TLS_GD(x) \
+- ((int *) __tls_get_addr (GET_SPECIAL_PCREL (x, tlsgd)))
+diff --git a/sysdeps/csky/abiv2/tls-macros.h b/sysdeps/csky/abiv2/tls-macros.h
+deleted file mode 100644
+index 57ed1e7..0000000
+--- a/sysdeps/csky/abiv2/tls-macros.h
++++ /dev/null
+@@ -1,55 +0,0 @@
+-/* Macros for accessing thread-local storage. C-SKY ABIV2 version.
+- Copyright (C) 2018-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-# define TLS_LE(x) \
+- ({ int *__result; \
+- __asm__ ("lrw %0, " #x "@TPOFF\n\t" \
+- "add %0, tls, %0" \
+- : "=&r" (__result)); \
+- __result; })
+-
+-# define TLS_IE(x) \
+- ({ int *__result; \
+- __asm__ ("grs a1, 1f\n" \
+- "1:\tlrw %0, " #x "@GOTTPOFF\n\t" \
+- "ldr.w %0, (a1, %0 << 0)\n\t" \
+- "add %0, tls, %0" \
+- : "=&r" (__result): : "a1"); \
+- __result; })
+-
+-# define TLS_LD(x) \
+- ({ char *__result; \
+- int __offset; \
+- extern void *__tls_get_addr (void *); \
+- __asm__ ("grs a1, 1f\n" \
+- "1:\tlrw %0, " #x "@TLSLDM32;\n\t" \
+- "add %0, a1, %0" \
+- : "=r" (__result) : : "a1"); \
+- __result = (char *)__tls_get_addr (__result); \
+- __asm__ ("lrw %0, " #x "@TLSLDO32" \
+- : "=r" (__offset)); \
+- (int *) (__result + __offset); })
+-
+-# define TLS_GD(x) \
+- ({ int *__result; \
+- extern void *__tls_get_addr (void *); \
+- __asm__ ("grs a1, 1f\n" \
+- "1:\tlrw %0, " #x "@TLSGD32\n\t" \
+- "add %0, a1, %0" \
+- : "=r" (__result) : : "a1"); \
+- (int *)__tls_get_addr (__result); })
+diff --git a/sysdeps/generic/tls-macros.h b/sysdeps/generic/tls-macros.h
+deleted file mode 100644
+index 0a08f7c..0000000
+--- a/sysdeps/generic/tls-macros.h
++++ /dev/null
+@@ -1,12 +0,0 @@
+-/* Macros to support TLS testing in times of missing compiler support.
+- Stub version.
+-
+- These macros should yield int * expressions for the TLS symbol X
+- accessed using the various TLS access models. Macros for some machines
+- are defined in elf/tls-macros.h, but ports can instead provide this file.
+-
+-#define TLS_LE(x)
+-#define TLS_IE(x)
+-#define TLS_LD(x)
+-#define TLS_GD(x)
+-*/
+diff --git a/sysdeps/hppa/tls-macros.h b/sysdeps/hppa/tls-macros.h
+deleted file mode 100644
+index 38edb1b..0000000
+--- a/sysdeps/hppa/tls-macros.h
++++ /dev/null
+@@ -1,114 +0,0 @@
+-/* TLS Access Macros for HP PARISC Linux */
+-
+-/* HPPA Local Exec TLS access. */
+-#define TLS_LE(x) \
+- ({ int * __result; \
+- unsigned long __tmp; \
+- asm ( \
+- " mfctl %%cr27, %1\n" \
+- " addil LR'" #x "-$tls_leoff$, %1\n" \
+- " ldo RR'" #x "-$tls_leoff$(%%r1), %0\n" \
+- : "=r" (__result), "=r" (__tmp) \
+- : \
+- : "r1" ); \
+- __result; \
+- })
+-
+-/* HPPA Initial Exec TLS access. */
+-#ifdef PIC
+-# define TLS_IE(x) \
+- ({ int * __result; \
+- unsigned long __tmp, __tmp2; \
+- asm ( \
+- " mfctl %%cr27, %1\n" \
+- " addil LT'" #x "-$tls_ieoff$, %%r19\n" \
+- " ldw RT'" #x "-$tls_ieoff$(%%r1), %2\n" \
+- " add %1, %2, %0\n" \
+- : "=r" (__result), "=r" (__tmp), "=r" (__tmp2) \
+- : \
+- : "r1" ); \
+- __result; \
+- })
+-#else
+-# define TLS_IE(x) \
+- ({ int * __result; \
+- unsigned long __tmp, __tmp2; \
+- asm ( \
+- " mfctl %%cr27, %1\n" \
+- " addil LR'" #x "-$tls_ieoff$, %%r27\n" \
+- " ldw RR'" #x "-$tls_ieoff$(%%r1), %2\n" \
+- " add %1, %2, %0\n" \
+- : "=r" (__result), "=r" (__tmp), "=r" (__tmp2) \
+- : \
+- : "r1" ); \
+- __result; \
+- })
+-#endif
+-
+-#ifdef PIC
+-/* HPPA Local Dynamic TLS access. */
+-# define TLS_LD(x) \
+- ({ int * __result; \
+- asm ( \
+- " copy %%r19, %%r4\n" \
+- " addil LT'" #x "-$tls_ldidx$, %%r19\n" \
+- " bl __tls_get_addr, %%r2\n" \
+- " ldo RT'" #x "-$tls_ldidx$(%%r1), %%r26\n" \
+- " addil LR'" #x "-$tls_dtpoff$, %%r28\n" \
+- " ldo RR'" #x "-$tls_dtpoff$(%%r1), %0\n" \
+- " copy %%r4, %%r19\n" \
+- : "=r" (__result) \
+- : \
+- : "r1", "r2", "r4", "r20", "r21", "r22", "r23", "r24", \
+- "r25", "r26", "r28", "r29", "r31" ); \
+- __result; \
+- })
+-#else
+-# define TLS_LD(x) \
+- ({ int * __result; \
+- asm ( \
+- " addil LR'" #x "-$tls_ldidx$, %%r27\n" \
+- " bl __tls_get_addr, %%r2\n" \
+- " ldo RR'" #x "-$tls_ldidx$(%%r1), %%r26\n" \
+- " addil LR'" #x "-$tls_dtpoff$, %%r28\n" \
+- " ldo RR'" #x "-$tls_dtpoff$(%%r1), %0\n" \
+- : "=r" (__result) \
+- : \
+- : "r1", "r2", "r20", "r21", "r22", "r23", "r24", \
+- "r25", "r26", "r28", "r29", "r31" ); \
+- __result; \
+- })
+-#endif
+-
+-/* HPPA General Dynamic TLS access. */
+-#ifdef PIC
+-# define TLS_GD(x) \
+- ({ int * __result; \
+- asm ( \
+- " copy %%r19, %%r4\n" \
+- " addil LT'" #x "-$tls_gdidx$, %%r19\n" \
+- " bl __tls_get_addr, %%r2\n" \
+- " ldo RT'" #x "-$tls_gdidx$(%%r1), %%r26\n" \
+- " copy %%r28, %0\n" \
+- " copy %%r4, %%r19\n" \
+- : "=r" (__result) \
+- : \
+- : "r1", "r2", "r4", "r20", "r21", "r22", "r23", "r24", \
+- "r25", "r26", "r28", "r29", "r31" ); \
+- __result; \
+- })
+-#else
+-# define TLS_GD(x) \
+- ({ int * __result; \
+- asm ( \
+- " addil LR'" #x "-$tls_gdidx$, %%r27\n" \
+- " bl __tls_get_addr, %%r2\n" \
+- " ldo RR'" #x "-$tls_gdidx$(%%r1), %%r26\n" \
+- " copy %%r28, %0\n" \
+- : "=r" (__result) \
+- : \
+- : "r1", "r2", "r20", "r21", "r22", "r23", "r24", \
+- "r25", "r26", "r28", "r29", "r31" ); \
+- __result; \
+- })
+-#endif
+diff --git a/sysdeps/i386/tls-macros.h b/sysdeps/i386/tls-macros.h
+deleted file mode 100644
+index 9c1303d..0000000
+--- a/sysdeps/i386/tls-macros.h
++++ /dev/null
+@@ -1,47 +0,0 @@
+-#define TLS_LE(x) \
+- ({ int *__l; \
+- asm ("movl %%gs:0,%0\n\t" \
+- "subl $" #x "@tpoff,%0" \
+- : "=r" (__l)); \
+- __l; })
+-
+-#define TLS_IE(x) \
+- ({ int *__l, __b; \
+- asm ("call 1f\n\t" \
+- ".subsection 1\n" \
+- "1:\tmovl (%%esp), %%ebx\n\t" \
+- "ret\n\t" \
+- ".previous\n\t" \
+- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \
+- "movl %%gs:0,%0\n\t" \
+- "subl " #x "@gottpoff(%%ebx),%0" \
+- : "=r" (__l), "=&b" (__b)); \
+- __l; })
+-
+-#define TLS_LD(x) \
+- ({ int *__l, __b, __c, __d; \
+- asm ("call 1f\n\t" \
+- ".subsection 1\n" \
+- "1:\tmovl (%%esp), %%ebx\n\t" \
+- "ret\n\t" \
+- ".previous\n\t" \
+- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \
+- "leal " #x "@tlsldm(%%ebx),%%eax\n\t" \
+- "call ___tls_get_addr@plt\n\t" \
+- "leal " #x "@dtpoff(%%eax), %%eax" \
+- : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d)); \
+- __l; })
+-
+-#define TLS_GD(x) \
+- ({ int *__l, __b, __c, __d; \
+- asm ("call 1f\n\t" \
+- ".subsection 1\n" \
+- "1:\tmovl (%%esp), %%ebx\n\t" \
+- "ret\n\t" \
+- ".previous\n\t" \
+- "addl $_GLOBAL_OFFSET_TABLE_, %%ebx\n\t" \
+- "leal " #x "@tlsgd(%%ebx),%%eax\n\t" \
+- "call ___tls_get_addr@plt\n\t" \
+- "nop" \
+- : "=a" (__l), "=&b" (__b), "=&c" (__c), "=&d" (__d)); \
+- __l; })
+diff --git a/sysdeps/ia64/tls-macros.h b/sysdeps/ia64/tls-macros.h
+deleted file mode 100644
+index 13b216d..0000000
+--- a/sysdeps/ia64/tls-macros.h
++++ /dev/null
+@@ -1,66 +0,0 @@
+-/* Macros to support TLS testing in times of missing compiler support. */
+-
+-extern void *__tls_get_addr (void *);
+-
+-# define TLS_LE(x) \
+- ({ void *__l; \
+- asm ("mov r2=r13\n\t" \
+- ";;\n\t" \
+- "addl %0=@tprel(" #x "),r2\n\t" \
+- : "=r" (__l) : : "r2" ); __l; })
+-
+-# define TLS_IE(x) \
+- ({ void *__l; \
+- register long __gp asm ("gp"); \
+- asm (";;\n\t" \
+- "addl r16=@ltoff(@tprel(" #x ")),gp\n\t" \
+- ";;\n\t" \
+- "ld8 r17=[r16]\n\t" \
+- ";;\n\t" \
+- "add %0=r13,r17\n\t" \
+- ";;\n\t" \
+- : "=r" (__l) : "r" (__gp) : "r16", "r17" ); __l; })
+-
+-# define __TLS_CALL_CLOBBERS \
+- "r2", "r3", "r8", "r9", "r10", "r11", "r14", "r15", "r16", "r17", \
+- "r18", "r19", "r20", "r21", "r22", "r23", "r24", "r25", "r26", \
+- "r27", "r28", "r29", "r30", "r31", \
+- "p6", "p7", "p8", "p9", "p10", "p11", "p12", "p13", "p14", "p15", \
+- "f6", "f7", "f8", "f9", "f10", "f11", "f12", "f13", "f14", "f15", \
+- "b6", "b7", \
+- "out0", "out1", "out2", "out3", "out4", "out5", "out6", "out7"
+-
+-# define TLS_LD(x) \
+- ({ void *__l; \
+- register long __gp asm ("gp"); \
+- asm (";;\n\t" \
+- "mov loc0=gp\n\t" \
+- "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \
+- "addl out1=@dtprel(" #x "),r0\n\t" \
+- ";;\n\t" \
+- "ld8 out0=[r16]\n\t" \
+- "br.call.sptk.many b0=__tls_get_addr" \
+- ";;\n\t" \
+- "mov gp=loc0\n\t" \
+- "mov %0=r8\n\t" \
+- ";;\n\t" \
+- : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \
+- __l; })
+-
+-# define TLS_GD(x) \
+- ({ void *__l; \
+- register long __gp asm ("gp"); \
+- asm (";;\n\t" \
+- "mov loc0=gp\n\t" \
+- "addl r16=@ltoff(@dtpmod(" #x ")),gp\n\t" \
+- "addl r17=@ltoff(@dtprel(" #x ")),gp\n\t" \
+- ";;\n\t" \
+- "ld8 out0=[r16]\n\t" \
+- "ld8 out1=[r17]\n\t" \
+- "br.call.sptk.many b0=__tls_get_addr" \
+- ";;\n\t" \
+- "mov gp=loc0\n\t" \
+- "mov %0=r8\n\t" \
+- ";;\n\t" \
+- : "=r" (__l) : "r" (__gp) : "loc0", __TLS_CALL_CLOBBERS); \
+- __l; })
+diff --git a/sysdeps/m68k/tls-macros.h b/sysdeps/m68k/tls-macros.h
+deleted file mode 100644
+index 5fe1735..0000000
+--- a/sysdeps/m68k/tls-macros.h
++++ /dev/null
+@@ -1,68 +0,0 @@
+-/* Macros for accessing thread-local storage. m68k version.
+- Copyright (C) 2010-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+- Contributed by Maxim Kuvyrkov <maxim@codesourcery.com>, 2010.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#define TLS_GD(x) \
+- ({ \
+- void *__result; \
+- extern void *__tls_get_addr (void *); \
+- \
+- asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \
+- "lea (-6, %%pc, %0), %0\n\t" \
+- "lea " #x "@TLSGD(%0), %0" \
+- : "=&a" (__result)); \
+- (int *) __tls_get_addr (__result); })
+-
+-#define TLS_LD(x) \
+- ({ \
+- char *__tp; \
+- int __offset; \
+- extern void *__tls_get_addr (void *); \
+- \
+- asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \
+- "lea (-6, %%pc, %0), %0\n\t" \
+- "lea " #x "@TLSLDM(%0), %0" \
+- : "=&a" (__tp)); \
+- __tp = (char *) __tls_get_addr (__tp); \
+- asm ("movel #" #x "@TLSLDO, %0" \
+- : "=a" (__offset)); \
+- (int *) (__tp + __offset); })
+-
+-#define TLS_IE(x) \
+- ({ \
+- char *__tp; \
+- int __offset; \
+- extern void * __m68k_read_tp (void); \
+- \
+- __tp = (char *) __m68k_read_tp (); \
+- asm ("movel #_GLOBAL_OFFSET_TABLE_@GOTPC, %0\n\t" \
+- "lea (-6, %%pc, %0), %0\n\t" \
+- "movel " #x "@TLSIE(%0), %0" \
+- : "=&a" (__offset)); \
+- (int *) (__tp + __offset); })
+-
+-#define TLS_LE(x) \
+- ({ \
+- char *__tp; \
+- int __offset; \
+- extern void * __m68k_read_tp (void); \
+- \
+- __tp = (char *) __m68k_read_tp (); \
+- asm ("movel #" #x "@TLSLE, %0" \
+- : "=a" (__offset)); \
+- (int *) (__tp + __offset); })
+diff --git a/sysdeps/microblaze/tls-macros.h b/sysdeps/microblaze/tls-macros.h
+deleted file mode 100644
+index f7cd59d..0000000
+--- a/sysdeps/microblaze/tls-macros.h
++++ /dev/null
+@@ -1,46 +0,0 @@
+-/* Copyright (C) 2009-2021 Free Software Foundation, Inc.
+-
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public License as
+- published by the Free Software Foundation; either version 2.1 of the
+- License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#define TLS_LD(x) \
+- ({ \
+- char *__result; \
+- int __offset; \
+- extern void *__tls_get_addr (void *); \
+- asm ("mfs r20,rpc \n" \
+- "addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n" \
+- "addik %0,r20," #x "@TLSLDM" \
+- : "=r" (__result)); \
+- __result = (char *) __tls_get_addr (__result); \
+- asm ("addik %0,r0,"#x"@TLSDTPREL" \
+- : "=r" (__offset)); \
+- (int *) (__result + __offset); })
+-
+-
+-#define TLS_GD(x) \
+- ({ \
+- int *__result; \
+- extern void *__tls_get_addr (void *); \
+- asm ("mfs r20,rpc\n" \
+- "addik r20,r20,_GLOBAL_OFFSET_TABLE_+8\n" \
+- "addik %0,r20," #x "@TLSGD" \
+- : "=r" (__result)); \
+- (int *) __tls_get_addr (__result); })
+-
+-#define TLS_LE(x) TLS_LD(x)
+-
+-#define TLS_IE(x) TLS_GD(x)
+diff --git a/sysdeps/mips/tls-macros.h b/sysdeps/mips/tls-macros.h
+deleted file mode 100644
+index a6fdfbc..0000000
+--- a/sysdeps/mips/tls-macros.h
++++ /dev/null
+@@ -1,130 +0,0 @@
+-/* Macros to support TLS testing in times of missing compiler support. */
+-
+-#include <sys/cdefs.h>
+-#include <sys/asm.h>
+-#include <sysdep.h>
+-
+-#define __STRING2(X) __STRING(X)
+-#define ADDU __STRING2(PTR_ADDU)
+-#define ADDIU __STRING2(PTR_ADDIU)
+-#define LW __STRING2(PTR_L)
+-
+-/* Load the GOT pointer, which may not be in $28 in a non-PIC
+- (abicalls pic0) function. */
+-#ifndef __PIC__
+-# if _MIPS_SIM != _ABI64
+-# ifndef __mips16
+-# define LOAD_GP "move %[tmp], $28\n\tla $28, __gnu_local_gp\n\t"
+-# else
+-# define LOAD_GP \
+- "li %[tmp], %%hi(__gnu_local_gp)\n\t" \
+- "sll %[tmp], 16\n\t" \
+- "addiu %[tmp], %%lo(__gnu_local_gp)\n\t"
+-# endif
+-# else
+-# define LOAD_GP "move %[tmp], $28\n\tdla $28, __gnu_local_gp\n\t"
+-# endif
+-# define UNLOAD_GP "\n\tmove $28, %[tmp]"
+-#else
+-/* MIPS16 (re)creates the GP value using PC-relative instructions. */
+-# ifdef __mips16
+-# define LOAD_GP \
+- "li %[tmp], %%hi(_gp_disp)\n\t" \
+- "addiu %0, $pc, %%lo(_gp_disp)\n\t" \
+- "sll %[tmp], 16\n\t" \
+- "addu %[tmp], %0\n\t"
+-# else
+-# define LOAD_GP
+-# endif
+-# define UNLOAD_GP
+-#endif
+-
+-# if __mips_isa_rev >= 2
+-# define TLS_RDHWR "rdhwr\t%0,$29"
+-# else
+-# define TLS_RDHWR \
+- ".set push\n\t.set mips32r2\n\t" \
+- "rdhwr\t%0,$29\n\t.set pop"
+-#endif
+-
+-#ifndef __mips16
+-# define TLS_GD(x) \
+- ({ void *__result, *__tmp; \
+- extern void *__tls_get_addr (void *); \
+- asm (LOAD_GP ADDIU " %0, $28, %%tlsgd(" #x ")" \
+- UNLOAD_GP \
+- : "=r" (__result), [tmp] "=&r" (__tmp)); \
+- (int *)__tls_get_addr (__result); })
+-# define TLS_LD(x) \
+- ({ void *__result, *__tmp; \
+- extern void *__tls_get_addr (void *); \
+- asm (LOAD_GP ADDIU " %0, $28, %%tlsldm(" #x ")" \
+- UNLOAD_GP \
+- : "=r" (__result), [tmp] "=&r" (__tmp)); \
+- __result = __tls_get_addr (__result); \
+- asm ("lui $3,%%dtprel_hi(" #x ")\n\t" \
+- "addiu $3,$3,%%dtprel_lo(" #x ")\n\t" \
+- ADDU " %0,%0,$3" \
+- : "+r" (__result) : : "$3"); \
+- __result; })
+-# define TLS_IE(x) \
+- ({ void *__result, *__tmp; \
+- asm (TLS_RDHWR \
+- : "=v" (__result)); \
+- asm (LOAD_GP LW " $3,%%gottprel(" #x ")($28)\n\t" \
+- ADDU " %0,%0,$3" \
+- UNLOAD_GP \
+- : "+r" (__result), [tmp] "=&r" (__tmp) \
+- : : "$3"); \
+- __result; })
+-# define TLS_LE(x) \
+- ({ void *__result; \
+- asm (TLS_RDHWR \
+- : "=v" (__result)); \
+- asm ("lui $3,%%tprel_hi(" #x ")\n\t" \
+- "addiu $3,$3,%%tprel_lo(" #x ")\n\t" \
+- ADDU " %0,%0,$3" \
+- : "+r" (__result) : : "$3"); \
+- __result; })
+-
+-#else /* __mips16 */
+-/* MIPS16 version. */
+-# define TLS_GD(x) \
+- ({ void *__result, *__tmp; \
+- extern void *__tls_get_addr (void *); \
+- asm (LOAD_GP ADDIU " %1, %%tlsgd(" #x ")" \
+- "\n\tmove %0, %1" \
+- : "=d" (__result), [tmp] "=&d" (__tmp)); \
+- (int *) __tls_get_addr (__result); })
+-# define TLS_LD(x) \
+- ({ void *__result, *__tmp; \
+- extern void *__tls_get_addr (void *); \
+- asm (LOAD_GP ADDIU " %1, %%tlsldm(" #x ")" \
+- "\n\tmove %0, %1" \
+- : "=d" (__result), [tmp] "=&d" (__tmp)); \
+- __result = __tls_get_addr (__result); \
+- asm ("li $3,%%dtprel_hi(" #x ")\n\t" \
+- "sll $3,16\n\t" \
+- "addiu $3,%%dtprel_lo(" #x ")\n\t" \
+- ADDU " %0,%0,$3" \
+- : "+d" (__result) : : "$3"); \
+- __result; })
+-# define TLS_IE(x) \
+- ({ void *__result, *__tmp, *__tp; \
+- __tp = __builtin_thread_pointer (); \
+- asm (LOAD_GP LW " $3,%%gottprel(" #x ")(%1)\n\t" \
+- ADDU " %0,%[tp],$3" \
+- : "=&d" (__result), [tmp] "=&d" (__tmp) \
+- : [tp] "d" (__tp) : "$3"); \
+- __result; })
+-# define TLS_LE(x) \
+- ({ void *__result, *__tp; \
+- __tp = __builtin_thread_pointer (); \
+- asm ("li $3,%%tprel_hi(" #x ")\n\t" \
+- "sll $3,16\n\t" \
+- "addiu $3,%%tprel_lo(" #x ")\n\t" \
+- ADDU " %0,%[tp],$3" \
+- : "=d" (__result) : [tp] "d" (__tp) : "$3"); \
+- __result; })
+-
+-#endif /* __mips16 */
+diff --git a/sysdeps/nios2/tls-macros.h b/sysdeps/nios2/tls-macros.h
+deleted file mode 100644
+index 7029530..0000000
+--- a/sysdeps/nios2/tls-macros.h
++++ /dev/null
+@@ -1,46 +0,0 @@
+-#define TLS_LE(x) \
+- ({ int *__result; \
+- asm ("addi %0, r23, %%tls_le(" #x ")" \
+- : "=r" (__result)); \
+- __result; })
+-
+-#define TLS_IE(x) \
+- ({ int *__result; \
+- int __tmp; \
+- asm ("nextpc %0 ; " \
+- "1: movhi %1, %%hiadj(_gp_got - 1b) ; " \
+- "addi %1, %1, %%lo(_gp_got - 1b) ; " \
+- "add %0, %0, %1 ; " \
+- "ldw %1, %%tls_ie(" #x ")(%0) ; " \
+- "add %1, r23, %1" \
+- : "=&r" (__tmp), "=&r" (__result)); \
+- __result; })
+-
+-#define TLS_LD(x) \
+- ({ char *__result; \
+- char *__result2; \
+- int *__result3; \
+- int __tmp; \
+- extern void *__tls_get_addr (void *); \
+- asm ("nextpc %0 ; " \
+- "1: movhi %1, %%hiadj(_gp_got - 1b) ; " \
+- "addi %1, %1, %%lo(_gp_got - 1b) ; " \
+- "add %0, %0, %1 ; " \
+- "addi %0, %0, %%tls_ldm(" #x ")" \
+- : "=r" (__result), "=r" (__tmp)); \
+- __result2 = (char *)__tls_get_addr (__result); \
+- asm ("addi %0, %1, %%tls_ldo(" #x ")" \
+- : "=r" (__result3) : "r" (__result2)); \
+- __result3; })
+-
+-#define TLS_GD(x) \
+- ({ int *__result; \
+- int __tmp; \
+- extern void *__tls_get_addr (void *); \
+- asm ("nextpc %0 ; " \
+- "1: movhi %1, %%hiadj(_gp_got - 1b) ; " \
+- "addi %1, %1, %%lo(_gp_got - 1b) ; " \
+- "add %0, %0, %1 ; " \
+- "addi %0, %0, %%tls_gd(" #x ")" \
+- : "=r" (__result), "=r" (__tmp)); \
+- (int *)__tls_get_addr (__result); })
+diff --git a/sysdeps/powerpc/powerpc32/tls-macros.h b/sysdeps/powerpc/powerpc32/tls-macros.h
+deleted file mode 100644
+index ee0eac4..0000000
+--- a/sysdeps/powerpc/powerpc32/tls-macros.h
++++ /dev/null
+@@ -1,49 +0,0 @@
+-/* Include sysdeps/powerpc/tls-macros.h for __TLS_CALL_CLOBBERS */
+-#include_next "tls-macros.h"
+-
+-/* PowerPC32 Local Exec TLS access. */
+-#define TLS_LE(x) \
+- ({ int *__result; \
+- asm ("addi %0,2," #x "@tprel" \
+- : "=r" (__result)); \
+- __result; })
+-
+-/* PowerPC32 Initial Exec TLS access. */
+-#define TLS_IE(x) \
+- ({ int *__result; \
+- asm ("bcl 20,31,1f\n1:\t" \
+- "mflr %0\n\t" \
+- "addis %0,%0,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \
+- "addi %0,%0,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \
+- "lwz %0," #x "@got@tprel(%0)\n\t" \
+- "add %0,%0," #x "@tls" \
+- : "=b" (__result) : \
+- : "lr"); \
+- __result; })
+-
+-/* PowerPC32 Local Dynamic TLS access. */
+-#define TLS_LD(x) \
+- ({ int *__result; \
+- asm ("bcl 20,31,1f\n1:\t" \
+- "mflr 3\n\t" \
+- "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \
+- "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \
+- "addi 3,3," #x "@got@tlsld\n\t" \
+- "bl __tls_get_addr@plt\n\t" \
+- "addi %0,3," #x "@dtprel" \
+- : "=r" (__result) : \
+- : "3", __TLS_CALL_CLOBBERS); \
+- __result; })
+-
+-/* PowerPC32 General Dynamic TLS access. */
+-#define TLS_GD(x) \
+- ({ register int *__result __asm__ ("r3"); \
+- asm ("bcl 20,31,1f\n1:\t" \
+- "mflr 3\n\t" \
+- "addis 3,3,_GLOBAL_OFFSET_TABLE_-1b@ha\n\t" \
+- "addi 3,3,_GLOBAL_OFFSET_TABLE_-1b@l\n\t" \
+- "addi 3,3," #x "@got@tlsgd\n\t" \
+- "bl __tls_get_addr@plt" \
+- : "=r" (__result) : \
+- : __TLS_CALL_CLOBBERS); \
+- __result; })
+diff --git a/sysdeps/powerpc/powerpc64/tls-macros.h b/sysdeps/powerpc/powerpc64/tls-macros.h
+deleted file mode 100644
+index 79a0b25..0000000
+--- a/sysdeps/powerpc/powerpc64/tls-macros.h
++++ /dev/null
+@@ -1,42 +0,0 @@
+-/* Include sysdeps/powerpc/tls-macros.h for __TLS_CALL_CLOBBERS */
+-#include_next "tls-macros.h"
+-
+-/* PowerPC64 Local Exec TLS access. */
+-#define TLS_LE(x) \
+- ({ int * __result; \
+- asm ("addis %0,13," #x "@tprel@ha\n\t" \
+- "addi %0,%0," #x "@tprel@l" \
+- : "=b" (__result) ); \
+- __result; \
+- })
+-/* PowerPC64 Initial Exec TLS access. */
+-#define TLS_IE(x) \
+- ({ int * __result; \
+- asm ("ld %0," #x "@got@tprel(2)\n\t" \
+- "add %0,%0," #x "@tls" \
+- : "=r" (__result) ); \
+- __result; \
+- })
+-
+-/* PowerPC64 Local Dynamic TLS access. */
+-#define TLS_LD(x) \
+- ({ int * __result; \
+- asm ("addi 3,2," #x "@got@tlsld\n\t" \
+- "bl __tls_get_addr\n\t" \
+- "nop \n\t" \
+- "addis %0,3," #x "@dtprel@ha\n\t" \
+- "addi %0,%0," #x "@dtprel@l" \
+- : "=b" (__result) : \
+- : "3", __TLS_CALL_CLOBBERS); \
+- __result; \
+- })
+-/* PowerPC64 General Dynamic TLS access. */
+-#define TLS_GD(x) \
+- ({ register int *__result __asm__ ("r3"); \
+- asm ("addi 3,2," #x "@got@tlsgd\n\t" \
+- "bl __tls_get_addr\n\t" \
+- "nop " \
+- : "=r" (__result) : \
+- : __TLS_CALL_CLOBBERS); \
+- __result; \
+- })
+diff --git a/sysdeps/powerpc/tls-macros.h b/sysdeps/powerpc/tls-macros.h
+deleted file mode 100644
+index 809ef5c..0000000
+--- a/sysdeps/powerpc/tls-macros.h
++++ /dev/null
+@@ -1,3 +0,0 @@
+-#define __TLS_CALL_CLOBBERS \
+- "0", "4", "5", "6", "7", "8", "9", "10", "11", "12", \
+- "lr", "ctr", "cr0", "cr1", "cr5", "cr6", "cr7"
+diff --git a/sysdeps/riscv/tls-macros.h b/sysdeps/riscv/tls-macros.h
+deleted file mode 100644
+index 90c496c..0000000
+--- a/sysdeps/riscv/tls-macros.h
++++ /dev/null
+@@ -1,47 +0,0 @@
+-/* Macros to support TLS testing in times of missing compiler support.
+- Copyright (C) 2017-2021 Free Software Foundation, Inc.
+-
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-
+-#include <sys/cdefs.h>
+-#include <sys/asm.h>
+-#include <sysdep.h>
+-#include "dl-tls.h"
+-
+-#define TLS_GD(x) \
+- ({ void *__result; \
+- asm ("la.tls.gd %0, " #x "\n\t" \
+- : "=r" (__result)); \
+- __tls_get_addr (__result); })
+-
+-#define TLS_LD(x) TLS_GD(x)
+-
+-#define TLS_IE(x) \
+- ({ void *__result; \
+- asm ("la.tls.ie %0, " #x "\n\t" \
+- "add %0, %0, tp\n\t" \
+- : "=r" (__result)); \
+- __result; })
+-
+-#define TLS_LE(x) \
+- ({ void *__result; \
+- asm ("lui %0, %%tprel_hi(" #x ")\n\t" \
+- "add %0, %0, tp, %%tprel_add(" #x ")\n\t" \
+- "addi %0, %0, %%tprel_lo(" #x ")\n\t" \
+- : "=r" (__result)); \
+- __result; })
+diff --git a/sysdeps/s390/s390-32/tls-macros.h b/sysdeps/s390/s390-32/tls-macros.h
+deleted file mode 100644
+index 153523a..0000000
+--- a/sysdeps/s390/s390-32/tls-macros.h
++++ /dev/null
+@@ -1,106 +0,0 @@
+-#define TLS_LE(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.long " #x "@ntpoff\n" \
+- "1:\tl %0,0(%0)" \
+- : "=a" (__offset) : : "cc" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-
+-#ifdef PIC
+-# define TLS_IE(x) \
+- ({ unsigned long __offset, __save12; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \
+- ".long " #x "@gotntpoff\n" \
+- "1:\tlr %1,%%r12\n\t" \
+- "l %%r12,0(%0)\n\t" \
+- "la %%r12,0(%0,%%r12)\n\t" \
+- "l %0,4(%0)\n\t" \
+- "l %0,0(%0,%%r12):tls_load:" #x "\n\t" \
+- "lr %%r12,%1\n" \
+- : "=&a" (__offset), "=&a" (__save12) : : "cc" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#else
+-# define TLS_IE(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.long " #x "@indntpoff\n" \
+- "1:\t l %0,0(%0)\n\t" \
+- "l %0,0(%0):tls_load:" #x \
+- : "=&a" (__offset) : : "cc" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#endif
+-
+-#ifdef PIC
+-# define TLS_LD(x) \
+- ({ unsigned long __offset, __save12; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \
+- ".long __tls_get_offset@plt-0b\n\t" \
+- ".long " #x "@tlsldm\n\t" \
+- ".long " #x "@dtpoff\n" \
+- "1:\tlr %1,%%r12\n\t" \
+- "l %%r12,0(%0)\n\t" \
+- "la %%r12,0(%%r12,%0)\n\t" \
+- "l %%r1,4(%0)\n\t" \
+- "l %%r2,8(%0)\n\t" \
+- "bas %%r14,0(%%r1,%0):tls_ldcall:" #x "\n\t" \
+- "l %0,12(%0)\n\t" \
+- "alr %0,%%r2\n\t" \
+- "lr %%r12,%1" \
+- : "=&a" (__offset), "=&a" (__save12) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "14"); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#else
+-# define TLS_LD(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \
+- ".long __tls_get_offset@plt\n\t" \
+- ".long " #x "@tlsldm\n\t" \
+- ".long " #x "@dtpoff\n" \
+- "1:\tl %%r12,0(%0)\n\t" \
+- "l %%r1,4(%0)\n\t" \
+- "l %%r2,8(%0)\n\t" \
+- "bas %%r14,0(%%r1):tls_ldcall:" #x "\n\t" \
+- "l %0,12(%0)\n\t" \
+- "alr %0,%%r2" \
+- : "=&a" (__offset) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14"); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#endif
+-
+-#ifdef PIC
+-# define TLS_GD(x) \
+- ({ unsigned long __offset, __save12; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.long _GLOBAL_OFFSET_TABLE_-0b\n\t" \
+- ".long __tls_get_offset@plt-0b\n\t" \
+- ".long " #x "@tlsgd\n" \
+- "1:\tlr %1,%%r12\n\t" \
+- "l %%r12,0(%0)\n\t" \
+- "la %%r12,0(%%r12,%0)\n\t" \
+- "l %%r1,4(%0)\n\t" \
+- "l %%r2,8(%0)\n\t" \
+- "bas %%r14,0(%%r1,%0):tls_gdcall:" #x "\n\t" \
+- "lr %0,%%r2\n\t" \
+- "lr %%r12,%1" \
+- : "=&a" (__offset), "=&a" (__save12) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "14"); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#else
+-# define TLS_GD(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.long _GLOBAL_OFFSET_TABLE_\n\t" \
+- ".long __tls_get_offset@plt\n\t" \
+- ".long " #x "@tlsgd\n" \
+- "1:\tl %%r12,0(%0)\n\t" \
+- "l %%r1,4(%0)\n\t" \
+- "l %%r2,8(%0)\n\t" \
+- "bas %%r14,0(%%r1):tls_gdcall:" #x "\n\t" \
+- "lr %0,%%r2" \
+- : "=&a" (__offset) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14"); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#endif
+diff --git a/sysdeps/s390/s390-64/tls-macros.h b/sysdeps/s390/s390-64/tls-macros.h
+deleted file mode 100644
+index 449a843..0000000
+--- a/sysdeps/s390/s390-64/tls-macros.h
++++ /dev/null
+@@ -1,90 +0,0 @@
+-#define TLS_LE(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.quad " #x "@ntpoff\n" \
+- "1:\tlg %0,0(%0)" \
+- : "=a" (__offset) : : "cc" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-
+-#ifdef PIC
+-# define TLS_IE(x) \
+- ({ unsigned long __offset, __save12; \
+- __asm__ ("bras %0,0f\n\t" \
+- ".quad " #x "@gotntpoff\n" \
+- "0:\tlgr %1,%%r12\n\t" \
+- "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
+- "lg %0,0(%0)\n\t" \
+- "lg %0,0(%0,%%r12):tls_load:" #x "\n\t" \
+- "lgr %%r12,%1\n" \
+- : "=&a" (__offset), "=&a" (__save12) : : "cc" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#else
+-# define TLS_IE(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.quad " #x "@indntpoff\n" \
+- "1:\t lg %0,0(%0)\n\t" \
+- "lg %0,0(%0):tls_load:" #x \
+- : "=&a" (__offset) : : "cc" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#endif
+-
+-#ifdef PIC
+-# define TLS_LD(x) \
+- ({ unsigned long __offset, __save12; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.quad " #x "@tlsldm\n\t" \
+- ".quad " #x "@dtpoff\n" \
+- "1:\tlgr %1,%%r12\n\t" \
+- "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
+- "lg %%r2,0(%0)\n\t" \
+- "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \
+- "lg %0,8(%0)\n\t" \
+- "algr %0,%%r2\n\t" \
+- "lgr %%r12,%1" \
+- : "=&a" (__offset), "=&a" (__save12) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#else
+-# define TLS_LD(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.quad " #x "@tlsldm\n\t" \
+- ".quad " #x "@dtpoff\n" \
+- "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
+- "lg %%r2,0(%0)\n\t" \
+- "brasl %%r14,__tls_get_offset@plt:tls_ldcall:" #x "\n\t" \
+- "lg %0,8(%0)\n\t" \
+- "algr %0,%%r2" \
+- : "=&a" (__offset) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#endif
+-
+-#ifdef PIC
+-# define TLS_GD(x) \
+- ({ unsigned long __offset, __save12; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.quad " #x "@tlsgd\n" \
+- "1:\tlgr %1,%%r12\n\t" \
+- "larl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
+- "lg %%r2,0(%0)\n\t" \
+- "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \
+- "lgr %0,%%r2\n\t" \
+- "lgr %%r12,%1" \
+- : "=&a" (__offset), "=&a" (__save12) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "14" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#else
+-# define TLS_GD(x) \
+- ({ unsigned long __offset; \
+- __asm__ ("bras %0,1f\n" \
+- "0:\t.quad " #x "@tlsgd\n" \
+- "1:\tlarl %%r12,_GLOBAL_OFFSET_TABLE_\n\t" \
+- "lg %%r2,0(%0)\n\t" \
+- "brasl %%r14,__tls_get_offset@plt:tls_gdcall:" #x "\n\t" \
+- "lgr %0,%%r2" \
+- : "=&a" (__offset) \
+- : : "cc", "0", "1", "2", "3", "4", "5", "12", "14" ); \
+- (int *) (__builtin_thread_pointer() + __offset); })
+-#endif
+diff --git a/sysdeps/sh/tls-macros.h b/sysdeps/sh/tls-macros.h
+deleted file mode 100644
+index aa56b0a..0000000
+--- a/sysdeps/sh/tls-macros.h
++++ /dev/null
+@@ -1,143 +0,0 @@
+-#define TLS_LE(x) \
+- ({ int *__l; void *__tp; \
+- asm ("stc gbr,%1\n\t" \
+- "mov.l 1f,%0\n\t" \
+- "bra 2f\n\t" \
+- " add %1,%0\n\t" \
+- ".align 2\n\t" \
+- "1: .long " #x "@tpoff\n\t" \
+- "2:" \
+- : "=r" (__l), "=r" (__tp)); \
+- __l; })
+-
+-#ifdef PIC
+-# define TLS_IE(x) \
+- ({ int *__l; void *__tp; \
+- register void *__gp __asm__("r12"); \
+- asm ("mov.l 1f,r0\n\t" \
+- "stc gbr,%1\n\t" \
+- "mov.l @(r0,r12),%0\n\t" \
+- "bra 2f\n\t" \
+- " add %1,%0\n\t" \
+- ".align 2\n\t" \
+- "1: .long " #x "@gottpoff\n\t" \
+- "2:" \
+- : "=r" (__l), "=r" (__tp) : "r" (__gp) : "r0"); \
+- __l; })
+-#else
+-# define TLS_IE(x) \
+- ({ int *__l; void *__tp; \
+- asm ("mov.l r12,@-r15\n\t" \
+- "mova 0f,r0\n\t" \
+- "mov.l 0f,r12\n\t" \
+- "add r0,r12\n\t" \
+- "mov.l 1f,r0\n\t" \
+- "stc gbr,%1\n\t" \
+- "mov.l @(r0,r12),%0\n\t" \
+- "bra 2f\n\t" \
+- " add %1,%0\n\t" \
+- ".align 2\n\t" \
+- "1: .long " #x "@gottpoff\n\t" \
+- "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \
+- "2: mov.l @r15+,r12" \
+- : "=r" (__l), "=r" (__tp) : : "r0"); \
+- __l; })
+-#endif
+-
+-#ifdef PIC
+-# define TLS_LD(x) \
+- ({ int *__l; \
+- register void *__gp __asm__("r12"); \
+- asm ("mov.l 1f,r4\n\t" \
+- "mova 2f,r0\n\t" \
+- "mov.l 2f,r1\n\t" \
+- "add r0,r1\n\t" \
+- "jsr @r1\n\t" \
+- " add r12,r4\n\t" \
+- "bra 4f\n\t" \
+- " nop\n\t" \
+- ".align 2\n\t" \
+- "1: .long " #x "@tlsldm\n\t" \
+- "2: .long __tls_get_addr@plt\n\t" \
+- "4: mov.l 3f,%0\n\t" \
+- "bra 5f\n\t" \
+- " add r0,%0\n\t" \
+- ".align 2\n\t" \
+- "3: .long " #x "@dtpoff\n\t" \
+- "5:" \
+- : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \
+- "r6", "r7", "pr", "t"); \
+- __l; })
+-#else
+-# define TLS_LD(x) \
+- ({ int *__l; \
+- asm ("mov.l r12,@-r15\n\t" \
+- "mova 0f,r0\n\t" \
+- "mov.l 0f,r12\n\t" \
+- "add r0,r12\n\t" \
+- "mov.l 1f,r4\n\t" \
+- "mova 2f,r0\n\t" \
+- "mov.l 2f,r1\n\t" \
+- "add r0,r1\n\t" \
+- "jsr @r1\n\t" \
+- " add r12,r4\n\t" \
+- "bra 4f\n\t" \
+- " nop\n\t" \
+- ".align 2\n\t" \
+- "1: .long " #x "@tlsldm\n\t" \
+- "2: .long __tls_get_addr@plt\n\t" \
+- "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \
+- "4: mov.l 3f,%0\n\t" \
+- "bra 5f\n\t" \
+- " add r0,%0\n\t" \
+- ".align 2\n\t" \
+- "3: .long " #x "@dtpoff\n\t" \
+- "5: mov.l @r15+,r12" \
+- : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+- "pr", "t"); \
+- __l; })
+-#endif
+-
+-#ifdef PIC
+-# define TLS_GD(x) \
+- ({ int *__l; \
+- register void *__gp __asm__("r12"); \
+- asm ("mov.l 1f,r4\n\t" \
+- "mova 2f,r0\n\t" \
+- "mov.l 2f,r1\n\t" \
+- "add r0,r1\n\t" \
+- "jsr @r1\n\t" \
+- " add r12,r4\n\t" \
+- "bra 3f\n\t" \
+- " mov r0,%0\n\t" \
+- ".align 2\n\t" \
+- "1: .long " #x "@tlsgd\n\t" \
+- "2: .long __tls_get_addr@plt\n\t" \
+- "3:" \
+- : "=r" (__l) : "r" (__gp) : "r0", "r1", "r2", "r3", "r4", "r5", \
+- "r6", "r7", "pr", "t"); \
+- __l; })
+-#else
+-# define TLS_GD(x) \
+- ({ int *__l; \
+- asm ("mov.l r12,@-r15\n\t" \
+- "mova 0f,r0\n\t" \
+- "mov.l 0f,r12\n\t" \
+- "add r0,r12\n\t" \
+- "mov.l 1f,r4\n\t" \
+- "mova 2f,r0\n\t" \
+- "mov.l 2f,r1\n\t" \
+- "add r0,r1\n\t" \
+- "jsr @r1\n\t" \
+- " add r12,r4\n\t" \
+- "bra 3f\n\t" \
+- " mov r0,%0\n\t" \
+- ".align 2\n\t" \
+- "1: .long " #x "@tlsgd\n\t" \
+- "2: .long __tls_get_addr@plt\n\t" \
+- "0: .long _GLOBAL_OFFSET_TABLE_\n\t" \
+- "3: mov.l @r15+,r12" \
+- : "=r" (__l) : : "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7", \
+- "pr", "t"); \
+- __l; })
+-#endif
+diff --git a/sysdeps/sparc/sparc32/tls-macros.h b/sysdeps/sparc/sparc32/tls-macros.h
+deleted file mode 100644
+index 152216e..0000000
+--- a/sysdeps/sparc/sparc32/tls-macros.h
++++ /dev/null
+@@ -1,66 +0,0 @@
+-#define TLS_LE(x) \
+- ({ int *__l; \
+- asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \
+- asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \
+- __l; })
+-
+-#ifdef __PIC__
+-# define TLS_LOAD_PIC \
+- ({ register long pc __asm__ ("%o7"); \
+- long got; \
+- asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \
+- "call .+8\n\t" \
+- "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \
+- "add %1, %0, %1\n\t" \
+- : "=r" (pc), "=r" (got)); \
+- got; })
+-#else
+-# define TLS_LOAD_PIC \
+- ({ long got; \
+- asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \
+- "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \
+- "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \
+- : "=r" (got)); \
+- got; })
+-#endif
+-
+-#define TLS_IE(x) \
+- ({ int *__l; \
+- asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \
+- asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("ld [%1 + %2], %0, %%tie_ld(" #x ")" \
+- : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \
+- asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \
+- __l; })
+-
+-#define TLS_LD(x) \
+- ({ int *__l; register void *__o0 asm ("%o0"); \
+- long __o; \
+- asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \
+- asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("add %1, %2, %0, %%tldm_add(" #x ")" \
+- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \
+- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \
+- " nop" \
+- : "=r" (__o0) : "0" (__o0) \
+- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \
+- "o5", "o7", "cc"); \
+- asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \
+- asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \
+- asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \
+- : "r" (__o0), "r" (__o)); \
+- __l; })
+-
+-#define TLS_GD(x) \
+- ({ int *__l; register void *__o0 asm ("%o0"); \
+- asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \
+- asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("add %1, %2, %0, %%tgd_add(" #x ")" \
+- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \
+- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \
+- " nop" \
+- : "=r" (__o0) : "0" (__o0) \
+- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \
+- "o5", "o7", "cc"); \
+- __o0; })
+diff --git a/sysdeps/sparc/sparc64/tls-macros.h b/sysdeps/sparc/sparc64/tls-macros.h
+deleted file mode 100644
+index bb0d803..0000000
+--- a/sysdeps/sparc/sparc64/tls-macros.h
++++ /dev/null
+@@ -1,65 +0,0 @@
+-#define TLS_LE(x) \
+- ({ int *__l; \
+- asm ("sethi %%tle_hix22(" #x "), %0" : "=r" (__l)); \
+- asm ("xor %1, %%tle_lox10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("add %%g7, %1, %0" : "=r" (__l) : "r" (__l)); \
+- __l; })
+-
+-#ifdef __PIC__
+-# define TLS_LOAD_PIC \
+- ({ long pc, got; \
+- asm ("sethi %%hi(_GLOBAL_OFFSET_TABLE_-4), %1\n\t" \
+- "rd %%pc, %0\n\t" \
+- "add %1, %%lo(_GLOBAL_OFFSET_TABLE_+4), %1\n\t" \
+- "add %1, %0, %1\n\t" \
+- : "=r" (pc), "=r" (got)); \
+- got; })
+-#else
+-# define TLS_LOAD_PIC \
+- ({ long got; \
+- asm (".hidden _GLOBAL_OFFSET_TABLE_\n\t" \
+- "sethi %%hi(_GLOBAL_OFFSET_TABLE_), %0\n\t" \
+- "or %0, %%lo(_GLOBAL_OFFSET_TABLE_), %0" \
+- : "=r" (got)); \
+- got; })
+-#endif
+-
+-#define TLS_IE(x) \
+- ({ int *__l; \
+- asm ("sethi %%tie_hi22(" #x "), %0" : "=r" (__l)); \
+- asm ("add %1, %%tie_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("ldx [%1 + %2], %0, %%tie_ldx(" #x ")" \
+- : "=r" (__l) : "r" (TLS_LOAD_PIC), "r" (__l)); \
+- asm ("add %%g7, %1, %0, %%tie_add(" #x ")" : "=r" (__l) : "r" (__l)); \
+- __l; })
+-
+-#define TLS_LD(x) \
+- ({ int *__l; register void *__o0 asm ("%o0"); \
+- long __o; \
+- asm ("sethi %%tldm_hi22(" #x "), %0" : "=r" (__l)); \
+- asm ("add %1, %%tldm_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("add %1, %2, %0, %%tldm_add(" #x ")" \
+- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \
+- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \
+- " nop" \
+- : "=r" (__o0) : "0" (__o0) \
+- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \
+- "o5", "o7", "cc"); \
+- asm ("sethi %%tldo_hix22(" #x "), %0" : "=r" (__o)); \
+- asm ("xor %1, %%tldo_lox10(" #x "), %0" : "=r" (__o) : "r" (__o)); \
+- asm ("add %1, %2, %0, %%tldo_add(" #x ")" : "=r" (__l) \
+- : "r" (__o0), "r" (__o)); \
+- __l; })
+-
+-#define TLS_GD(x) \
+- ({ int *__l; register void *__o0 asm ("%o0"); \
+- asm ("sethi %%tgd_hi22(" #x "), %0" : "=r" (__l)); \
+- asm ("add %1, %%tgd_lo10(" #x "), %0" : "=r" (__l) : "r" (__l)); \
+- asm ("add %1, %2, %0, %%tgd_add(" #x ")" \
+- : "=r" (__o0) : "r" (TLS_LOAD_PIC), "r" (__l)); \
+- asm ("call __tls_get_addr, %%tgd_call(" #x ")\n\t" \
+- " nop" \
+- : "=r" (__o0) : "0" (__o0) \
+- : "g1", "g2", "g3", "g4", "g5", "g6", "o1", "o2", "o3", "o4", \
+- "o5", "o7", "cc"); \
+- __o0; })
+diff --git a/sysdeps/x86_64/tls-macros.h b/sysdeps/x86_64/tls-macros.h
+deleted file mode 100644
+index 22d2a4b..0000000
+--- a/sysdeps/x86_64/tls-macros.h
++++ /dev/null
+@@ -1,39 +0,0 @@
+-#define TLS_LE(x) \
+- ({ int *__l; \
+- asm ("mov %%fs:0,%0\n\t" \
+- "lea " #x "@tpoff(%0), %0" \
+- : "=r" (__l)); \
+- __l; })
+-
+-#define TLS_IE(x) \
+- ({ int *__l; \
+- asm ("mov %%fs:0,%0\n\t" \
+- "add " #x "@gottpoff(%%rip),%0" \
+- : "=r" (__l)); \
+- __l; })
+-
+-#define TLS_LD(x) \
+- ({ int *__l, __c, __d; \
+- asm ("leaq " #x "@tlsld(%%rip),%%rdi\n\t" \
+- "call __tls_get_addr@plt\n\t" \
+- "leaq " #x "@dtpoff(%%rax), %%rax" \
+- : "=a" (__l), "=&c" (__c), "=&d" (__d) \
+- : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \
+- __l; })
+-
+-#ifdef __ILP32__
+-# define TLS_GD_PREFIX
+-#else
+-# define TLS_GD_PREFIX ".byte 0x66\n\t"
+-#endif
+-
+-#define TLS_GD(x) \
+- ({ int *__l, __c, __d; \
+- asm (TLS_GD_PREFIX \
+- "leaq " #x "@tlsgd(%%rip),%%rdi\n\t" \
+- ".word 0x6666\n\t" \
+- "rex64\n\t" \
+- "call __tls_get_addr@plt" \
+- : "=a" (__l), "=&c" (__c), "=&d" (__d) \
+- : : "rdi", "rsi", "r8", "r9", "r10", "r11"); \
+- __l; })
+--
+1.8.3.1
+
diff --git a/Update-string-test-memmove.c-to-cover-16KB-copy.patch b/Update-string-test-memmove.c-to-cover-16KB-copy.patch
new file mode 100644
index 0000000..894833e
--- /dev/null
+++ b/Update-string-test-memmove.c-to-cover-16KB-copy.patch
@@ -0,0 +1,78 @@
+From c333dcf8d8f9e6e46475d9eff24bd5394b5d3d9e Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 1 Feb 2021 17:23:12 -0800
+Subject: [PATCH] Update string/test-memmove.c to cover 16KB copy
+
+---
+ string/test-memmove.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 48 insertions(+)
+
+diff --git a/string/test-memmove.c b/string/test-memmove.c
+index b271248..670094c 100644
+--- a/string/test-memmove.c
++++ b/string/test-memmove.c
+@@ -312,6 +312,50 @@ do_test2 (size_t offset)
+ munmap ((void *) large_buf, size);
+ }
+
++static void
++do_test3 (size_t bytes_move, size_t offset)
++{
++ size_t size = bytes_move * 3;
++ uint32_t *buf;
++
++ buf = mmap (NULL, size, PROT_READ | PROT_WRITE,
++ MAP_PRIVATE | MAP_ANON, -1, 0);
++
++ if (buf == MAP_FAILED)
++ error (EXIT_UNSUPPORTED, errno, "mmap failed");
++
++ size_t arr_size = bytes_move / sizeof (uint32_t);
++ size_t i;
++
++ FOR_EACH_IMPL (impl, 0)
++ {
++ for (i = 0; i < arr_size; i++)
++ buf[i] = (uint32_t) i;
++
++ uint32_t *dst = &buf[arr_size + offset];
++
++#ifdef TEST_BCOPY
++ CALL (impl, (char *) buf, (char *) dst, bytes_move);
++#else
++ CALL (impl, (char *) dst, (char *) buf, bytes_move);
++#endif
++
++ for (i = 0; i < arr_size; i++)
++ {
++ if (dst[i] != (uint32_t) i)
++ {
++ error (0, 0,
++ "Wrong result in function %s dst \"%p\" src \"%p\" offset \"%zd\"",
++ impl->name, dst, buf, i);
++ ret = 1;
++ break;
++ }
++ }
++ }
++
++ munmap ((void *) buf, size);
++}
++
+ int
+ test_main (void)
+ {
+@@ -356,6 +400,10 @@ test_main (void)
+ do_test2 (0x200000);
+ do_test2 (0x4000000 - 1);
+ do_test2 (0x4000000);
++
++ /* Copy 16KB data. */
++ do_test3 (16384, 3);
++
+ return ret;
+ }
+
+--
+1.8.3.1
+
diff --git a/Use-__executable_start-as-the-lowest-address-for-pro.patch b/Use-__executable_start-as-the-lowest-address-for-pro.patch
new file mode 100644
index 0000000..06ddfb1
--- /dev/null
+++ b/Use-__executable_start-as-the-lowest-address-for-pro.patch
@@ -0,0 +1,106 @@
+From 84a7eb1f87c1d01b58ad887a0ab5d87abbc1c772 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Fri, 30 Jul 2021 19:07:30 -0700
+Subject: [PATCH] Use __executable_start as the lowest address for profiling
+ [BZ #28153]
+
+Glibc assumes that ENTRY_POINT is the lowest address for which we need
+to keep profiling records and BFD linker uses a linker script to place
+the input sections.
+
+Starting from GCC 4.6, the main function is placed in .text.startup
+section and starting from binutils 2.22, BFD linker with
+
+commit add44f8d5c5c05e08b11e033127a744d61c26aee
+Author: Alan Modra <amodra@gmail.com>
+Date: Thu Nov 25 03:03:02 2010 +0000
+
+ * scripttempl/elf.sc: Group .text.exit, text.startup and .text.hot
+ sections.
+
+places .text.startup section before .text section, which leave the main
+function out of profiling records.
+
+Starting from binutils 2.15, linker provides __executable_start to mark
+the lowest address of the executable. Use __executable_start as the
+lowest address to keep the main function in profiling records. This fixes
+[BZ #28153].
+
+Tested on Linux/x86-64, Linux/x32 and Linux/i686 as well as with
+build-many-glibcs.py.
+---
+ csu/gmon-start.c | 10 +++++++++-
+ gmon/tst-gmon-gprof.sh | 2 ++
+ gmon/tst-gmon-static-gprof.sh | 2 ++
+ 3 files changed, 13 insertions(+), 1 deletion(-)
+
+diff --git a/csu/gmon-start.c b/csu/gmon-start.c
+index b343288..344606a 100644
+--- a/csu/gmon-start.c
++++ b/csu/gmon-start.c
+@@ -52,6 +52,11 @@ extern char ENTRY_POINT[];
+ #endif
+ extern char etext[];
+
++/* Use __executable_start as the lowest address to keep profiling records
++ if it provided by the linker. */
++extern const char executable_start[] asm ("__executable_start")
++ __attribute__ ((weak, visibility ("hidden")));
++
+ #ifndef TEXT_START
+ # ifdef ENTRY_POINT_DECL
+ # define TEXT_START ENTRY_POINT
+@@ -92,7 +97,10 @@ __gmon_start__ (void)
+ called = 1;
+
+ /* Start keeping profiling records. */
+- __monstartup ((u_long) TEXT_START, (u_long) &etext);
++ if (&executable_start != NULL)
++ __monstartup ((u_long) &executable_start, (u_long) &etext);
++ else
++ __monstartup ((u_long) TEXT_START, (u_long) &etext);
+
+ /* Call _mcleanup before exiting; it will write out gmon.out from the
+ collected data. */
+diff --git a/gmon/tst-gmon-gprof.sh b/gmon/tst-gmon-gprof.sh
+index 9d37158..dc0be02 100644
+--- a/gmon/tst-gmon-gprof.sh
++++ b/gmon/tst-gmon-gprof.sh
+@@ -39,12 +39,14 @@ trap cleanup 0
+ cat > "$expected" <<EOF
+ f1 2000
+ f2 1000
++f3 1
+ EOF
+
+ # Special version for powerpc with function descriptors.
+ cat > "$expected_dot" <<EOF
+ .f1 2000
+ .f2 1000
++.f3 1
+ EOF
+
+ "$GPROF" -C "$program" "$data" \
+diff --git a/gmon/tst-gmon-static-gprof.sh b/gmon/tst-gmon-static-gprof.sh
+index 79218df..4cc99c8 100644
+--- a/gmon/tst-gmon-static-gprof.sh
++++ b/gmon/tst-gmon-static-gprof.sh
+@@ -39,6 +39,7 @@ trap cleanup 0
+ cat > "$expected" <<EOF
+ f1 2000
+ f2 1000
++f3 1
+ main 1
+ EOF
+
+@@ -46,6 +47,7 @@ EOF
+ cat > "$expected_dot" <<EOF
+ .f1 2000
+ .f2 1000
++.f3 1
+ .main 1
+ EOF
+
+--
+1.8.3.1
+
diff --git a/Use-support_open_dev_null_range-io-tst-closefrom-mis.patch b/Use-support_open_dev_null_range-io-tst-closefrom-mis.patch
new file mode 100644
index 0000000..bd7da16
--- /dev/null
+++ b/Use-support_open_dev_null_range-io-tst-closefrom-mis.patch
@@ -0,0 +1,212 @@
+From 772e33411bc730f832f415f93eb3e7c67e4d5488 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Tue, 24 Aug 2021 16:15:50 -0300
+Subject: [PATCH] Use support_open_dev_null_range io/tst-closefrom,
+ misc/tst-close_range, and posix/tst-spawn5 (BZ #28260)
+
+It ensures a continuous range of file descriptor and avoid hitting
+the RLIMIT_NOFILE.
+
+Checked on x86_64-linux-gnu.
+
+(cherry picked from commit 6b20880b22d1d0fce7e9f506baa6fe2d5c7fcfdc)
+---
+ io/tst-closefrom.c | 21 ++++++---------------
+ posix/tst-spawn5.c | 13 +------------
+ sysdeps/unix/sysv/linux/tst-close_range.c | 31 ++++++++++---------------------
+ 3 files changed, 17 insertions(+), 48 deletions(-)
+
+diff --git a/io/tst-closefrom.c b/io/tst-closefrom.c
+index d4c1870..395ec0d 100644
+--- a/io/tst-closefrom.c
++++ b/io/tst-closefrom.c
+@@ -24,31 +24,22 @@
+ #include <support/check.h>
+ #include <support/descriptors.h>
+ #include <support/xunistd.h>
++#include <support/support.h>
+
+ #include <array_length.h>
+
+ #define NFDS 100
+
+ static int
+-open_multiple_temp_files (void)
+-{
+- /* Check if the temporary file descriptor has no no gaps. */
+- int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
+- for (int i = 1; i <= NFDS; i++)
+- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600), lowfd + i);
+- return lowfd;
+-}
+-
+-static int
+ closefrom_test (void)
+ {
+ struct support_descriptors *descrs = support_descriptors_list ();
+
+- int lowfd = open_multiple_temp_files ();
++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
+
+- const int maximum_fd = lowfd + NFDS;
++ const int maximum_fd = lowfd + NFDS - 1;
+ const int half_fd = lowfd + NFDS / 2;
+- const int gap = maximum_fd / 4;
++ const int gap = lowfd + NFDS / 4;
+
+ /* Close half of the descriptors and check result. */
+ closefrom (half_fd);
+@@ -58,7 +49,7 @@ closefrom_test (void)
+ TEST_COMPARE (fcntl (i, F_GETFL), -1);
+ TEST_COMPARE (errno, EBADF);
+ }
+- for (int i = 0; i < half_fd; i++)
++ for (int i = lowfd; i < half_fd; i++)
+ TEST_VERIFY (fcntl (i, F_GETFL) > -1);
+
+ /* Create some gaps, close up to a threshold, and check result. */
+@@ -74,7 +65,7 @@ closefrom_test (void)
+ TEST_COMPARE (fcntl (i, F_GETFL), -1);
+ TEST_COMPARE (errno, EBADF);
+ }
+- for (int i = 0; i < gap; i++)
++ for (int i = lowfd; i < gap; i++)
+ TEST_VERIFY (fcntl (i, F_GETFL) > -1);
+
+ /* Close the remmaining but the last one. */
+diff --git a/posix/tst-spawn5.c b/posix/tst-spawn5.c
+index ac66738..a95199a 100644
+--- a/posix/tst-spawn5.c
++++ b/posix/tst-spawn5.c
+@@ -48,17 +48,6 @@ static int initial_argv_count;
+ #define NFDS 100
+
+ static int
+-open_multiple_temp_files (void)
+-{
+- /* Check if the temporary file descriptor has no no gaps. */
+- int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
+- for (int i = 1; i <= NFDS; i++)
+- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600),
+- lowfd + i);
+- return lowfd;
+-}
+-
+-static int
+ parse_fd (const char *str)
+ {
+ char *endptr;
+@@ -185,7 +174,7 @@ spawn_closefrom_test (posix_spawn_file_actions_t *fa, int lowfd, int highfd,
+ static void
+ do_test_closefrom (void)
+ {
+- int lowfd = open_multiple_temp_files ();
++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
+ const int half_fd = lowfd + NFDS / 2;
+
+ /* Close half of the descriptors and check result. */
+diff --git a/sysdeps/unix/sysv/linux/tst-close_range.c b/sysdeps/unix/sysv/linux/tst-close_range.c
+index dccb618..f5069d1 100644
+--- a/sysdeps/unix/sysv/linux/tst-close_range.c
++++ b/sysdeps/unix/sysv/linux/tst-close_range.c
+@@ -36,23 +36,12 @@
+
+ #define NFDS 100
+
+-static int
+-open_multiple_temp_files (void)
+-{
+- /* Check if the temporary file descriptor has no no gaps. */
+- int lowfd = xopen ("/dev/null", O_RDONLY, 0600);
+- for (int i = 1; i <= NFDS; i++)
+- TEST_COMPARE (xopen ("/dev/null", O_RDONLY, 0600),
+- lowfd + i);
+- return lowfd;
+-}
+-
+ static void
+ close_range_test_max_upper_limit (void)
+ {
+ struct support_descriptors *descrs = support_descriptors_list ();
+
+- int lowfd = open_multiple_temp_files ();
++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
+
+ {
+ int r = close_range (lowfd, ~0U, 0);
+@@ -68,7 +57,7 @@ close_range_test_max_upper_limit (void)
+ static void
+ close_range_test_common (int lowfd, unsigned int flags)
+ {
+- const int maximum_fd = lowfd + NFDS;
++ const int maximum_fd = lowfd + NFDS - 1;
+ const int half_fd = lowfd + NFDS / 2;
+ const int gap_1 = maximum_fd - 8;
+
+@@ -121,7 +110,7 @@ close_range_test (void)
+ struct support_descriptors *descrs = support_descriptors_list ();
+
+ /* Check if the temporary file descriptor has no no gaps. */
+- int lowfd = open_multiple_temp_files ();
++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
+
+ close_range_test_common (lowfd, 0);
+
+@@ -146,7 +135,7 @@ close_range_test_subprocess (void)
+ struct support_descriptors *descrs = support_descriptors_list ();
+
+ /* Check if the temporary file descriptor has no no gaps. */
+- int lowfd = open_multiple_temp_files ();
++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
+
+ struct support_stack stack = support_stack_alloc (4096);
+
+@@ -184,7 +173,7 @@ close_range_unshare_test (void)
+ struct support_descriptors *descrs1 = support_descriptors_list ();
+
+ /* Check if the temporary file descriptor has no no gaps. */
+- int lowfd = open_multiple_temp_files ();
++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
+
+ struct support_descriptors *descrs2 = support_descriptors_list ();
+
+@@ -200,7 +189,7 @@ close_range_unshare_test (void)
+
+ support_stack_free (&stack);
+
+- for (int i = 0; i < NFDS; i++)
++ for (int i = lowfd; i < lowfd + NFDS; i++)
+ TEST_VERIFY (fcntl (i, F_GETFL) > -1);
+
+ support_descriptors_check (descrs2);
+@@ -226,9 +215,9 @@ static void
+ close_range_cloexec_test (void)
+ {
+ /* Check if the temporary file descriptor has no no gaps. */
+- const int lowfd = open_multiple_temp_files ();
++ int lowfd = support_open_dev_null_range (NFDS, O_RDONLY, 0600);
+
+- const int maximum_fd = lowfd + NFDS;
++ const int maximum_fd = lowfd + NFDS - 1;
+ const int half_fd = lowfd + NFDS / 2;
+ const int gap_1 = maximum_fd - 8;
+
+@@ -251,13 +240,13 @@ close_range_cloexec_test (void)
+ /* Create some gaps, close up to a threshold, and check result. */
+ static int gap_close[] = { 57, 78, 81, 82, 84, 90 };
+ for (int i = 0; i < array_length (gap_close); i++)
+- xclose (gap_close[i]);
++ xclose (lowfd + gap_close[i]);
+
+ TEST_COMPARE (close_range (half_fd + 1, gap_1, CLOSE_RANGE_CLOEXEC), 0);
+ for (int i = half_fd + 1; i < gap_1; i++)
+ {
+ int flags = fcntl (i, F_GETFD);
+- if (is_in_array (gap_close, array_length (gap_close), i))
++ if (is_in_array (gap_close, array_length (gap_close), i - lowfd))
+ TEST_COMPARE (flags, -1);
+ else
+ {
+--
+1.8.3.1
+
diff --git a/aarch64-Make-elf_machine_-load_address-dynamic-robus.patch b/aarch64-Make-elf_machine_-load_address-dynamic-robus.patch
new file mode 100644
index 0000000..b178499
--- /dev/null
+++ b/aarch64-Make-elf_machine_-load_address-dynamic-robus.patch
@@ -0,0 +1,72 @@
+From 43d06ed218fc8be58987bdfd00e21e5720f0b862 Mon Sep 17 00:00:00 2001
+From: Fangrui Song <maskray@google.com>
+Date: Wed, 11 Aug 2021 09:00:37 -0700
+Subject: [PATCH] aarch64: Make elf_machine_{load_address,dynamic} robust [BZ
+ #28203]
+
+The AArch64 ABI is largely platform agnostic and does not specify
+_GLOBAL_OFFSET_TABLE_[0] ([1]). glibc ld.so turns out to be probably the
+only user of _GLOBAL_OFFSET_TABLE_[0] and GNU ld defines the value
+to the link-time address _DYNAMIC. [2]
+
+In 2012, __ehdr_start was implemented in GNU ld and gold in binutils
+2.23. Using adrp+add / (-mcmodel=tiny) adr to access
+__ehdr_start/_DYNAMIC gives us a robust way to get the load address and
+the link-time address of _DYNAMIC.
+
+[1]: From a psABI maintainer, https://bugs.llvm.org/show_bug.cgi?id=49672#c2
+[2]: LLD's aarch64 port does not set _GLOBAL_OFFSET_TABLE_[0] to the
+link-time address _DYNAMIC.
+LLD is widely used on aarch64 Android and ChromeOS devices. Software
+just works without the need for _GLOBAL_OFFSET_TABLE_[0].
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/aarch64/dl-machine.h | 24 +++++++++---------------
+ 1 file changed, 9 insertions(+), 15 deletions(-)
+
+diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
+index d29d827..3e10cb4 100644
+--- a/sysdeps/aarch64/dl-machine.h
++++ b/sysdeps/aarch64/dl-machine.h
+@@ -37,28 +37,22 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
+ return ehdr->e_machine == EM_AARCH64;
+ }
+
+-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+- first element of the GOT. */
+-static inline ElfW(Addr) __attribute__ ((unused))
+-elf_machine_dynamic (void)
+-{
+- extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
+- return _GLOBAL_OFFSET_TABLE_[0];
+-}
+-
+ /* Return the run-time load address of the shared object. */
+
+ static inline ElfW(Addr) __attribute__ ((unused))
+ elf_machine_load_address (void)
+ {
+- /* To figure out the load address we use the definition that for any symbol:
+- dynamic_addr(symbol) = static_addr(symbol) + load_addr
++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
++ return (ElfW(Addr)) &__ehdr_start;
++}
+
+- _DYNAMIC sysmbol is used here as its link-time address stored in
+- the special unrelocated first GOT entry. */
++/* Return the link-time address of _DYNAMIC. */
+
+- extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+- return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
++static inline ElfW(Addr) __attribute__ ((unused))
++elf_machine_dynamic (void)
++{
++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
+ }
+
+ /* Set up the loaded object described by L so its unrelocated PLT
+--
+1.8.3.1
+
diff --git a/aarch64-Move-ld.so-_start-to-separate-file-and-drop-.patch b/aarch64-Move-ld.so-_start-to-separate-file-and-drop-.patch
new file mode 100644
index 0000000..15738b9
--- /dev/null
+++ b/aarch64-Move-ld.so-_start-to-separate-file-and-drop-.patch
@@ -0,0 +1,188 @@
+From 1da064c015dce624cb19fcdc0bace7af2bd8caec Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Thu, 30 Dec 2021 17:08:36 +0000
+Subject: [PATCH 4/4] aarch64: Move ld.so _start to separate file and drop
+ _dl_skip_args
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=1da064c015dce624cb19fcdc0bace7af2bd8caec
+
+A separate asm file is easier to maintain than a macro that expands to
+inline asm.
+
+The RTLD_START macro is only needed now because _dl_start is local in
+rtld.c, but _start has to call it, if _dl_start was made hidden then it
+could be empty.
+
+_dl_skip_args is no longer needed.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ sysdeps/aarch64/Makefile | 1 +
+ sysdeps/aarch64/dl-machine.h | 77 +-----------------------------------
+ sysdeps/aarch64/dl-start.S | 53 +++++++++++++++++++++++++
+ 3 files changed, 56 insertions(+), 75 deletions(-)
+ create mode 100644 sysdeps/aarch64/dl-start.S
+
+diff --git a/sysdeps/aarch64/Makefile b/sysdeps/aarch64/Makefile
+index 7183895d04..17fb1c5b72 100644
+--- a/sysdeps/aarch64/Makefile
++++ b/sysdeps/aarch64/Makefile
+@@ -33,6 +33,7 @@ tst-audit27-ENV = LD_AUDIT=$(objpfx)tst-auditmod27.so
+ endif
+
+ ifeq ($(subdir),elf)
++sysdep-rtld-routines += dl-start
+ sysdep-dl-routines += tlsdesc dl-tlsdesc
+ gen-as-const-headers += dl-link.sym
+
+diff --git a/sysdeps/aarch64/dl-machine.h b/sysdeps/aarch64/dl-machine.h
+index b40050a981..fe120bb507 100644
+--- a/sysdeps/aarch64/dl-machine.h
++++ b/sysdeps/aarch64/dl-machine.h
+@@ -105,81 +105,8 @@ elf_machine_runtime_setup (struct link_map *l, struct r_scope_elem *scope[],
+ return lazy;
+ }
+
+-/* Initial entry point for the dynamic linker. The C function
+- _dl_start is the real entry point, its return value is the user
+- program's entry point */
+-#ifdef __LP64__
+-# define RTLD_START RTLD_START_1 ("x", "3", "sp")
+-#else
+-# define RTLD_START RTLD_START_1 ("w", "2", "wsp")
+-#endif
+-
+-
+-#define RTLD_START_1(PTR, PTR_SIZE_LOG, PTR_SP) asm ("\
+-.text \n\
+-.globl _start \n\
+-.type _start, %function \n\
+-.globl _dl_start_user \n\
+-.type _dl_start_user, %function \n\
+-_start: \n\
+- // bti c \n\
+- hint 34 \n\
+- mov " PTR "0, " PTR_SP " \n\
+- bl _dl_start \n\
+- // returns user entry point in x0 \n\
+- mov x21, x0 \n\
+-_dl_start_user: \n\
+- // get the original arg count \n\
+- ldr " PTR "1, [sp] \n\
+- // get the argv address \n\
+- add " PTR "2, " PTR_SP ", #(1<<" PTR_SIZE_LOG ") \n\
+- // get _dl_skip_args to see if we were \n\
+- // invoked as an executable \n\
+- adrp x4, _dl_skip_args \n\
+- ldr w4, [x4, #:lo12:_dl_skip_args] \n\
+- // do we need to adjust argc/argv \n\
+- cmp w4, 0 \n\
+- beq .L_done_stack_adjust \n\
+- // subtract _dl_skip_args from original arg count \n\
+- sub " PTR "1, " PTR "1, " PTR "4 \n\
+- // store adjusted argc back to stack \n\
+- str " PTR "1, [sp] \n\
+- // find the first unskipped argument \n\
+- mov " PTR "3, " PTR "2 \n\
+- add " PTR "4, " PTR "2, " PTR "4, lsl #" PTR_SIZE_LOG " \n\
+- // shuffle argv down \n\
+-1: ldr " PTR "5, [x4], #(1<<" PTR_SIZE_LOG ") \n\
+- str " PTR "5, [x3], #(1<<" PTR_SIZE_LOG ") \n\
+- cmp " PTR "5, #0 \n\
+- bne 1b \n\
+- // shuffle envp down \n\
+-1: ldr " PTR "5, [x4], #(1<<" PTR_SIZE_LOG ") \n\
+- str " PTR "5, [x3], #(1<<" PTR_SIZE_LOG ") \n\
+- cmp " PTR "5, #0 \n\
+- bne 1b \n\
+- // shuffle auxv down \n\
+-1: ldp " PTR "0, " PTR "5, [x4, #(2<<" PTR_SIZE_LOG ")]! \n\
+- stp " PTR "0, " PTR "5, [x3], #(2<<" PTR_SIZE_LOG ") \n\
+- cmp " PTR "0, #0 \n\
+- bne 1b \n\
+- // Update _dl_argv \n\
+- adrp x3, __GI__dl_argv \n\
+- str " PTR "2, [x3, #:lo12:__GI__dl_argv] \n\
+-.L_done_stack_adjust: \n\
+- // compute envp \n\
+- add " PTR "3, " PTR "2, " PTR "1, lsl #" PTR_SIZE_LOG " \n\
+- add " PTR "3, " PTR "3, #(1<<" PTR_SIZE_LOG ") \n\
+- adrp x16, _rtld_local \n\
+- add " PTR "16, " PTR "16, #:lo12:_rtld_local \n\
+- ldr " PTR "0, [x16] \n\
+- bl _dl_init \n\
+- // load the finalizer function \n\
+- adrp x0, _dl_fini \n\
+- add " PTR "0, " PTR "0, #:lo12:_dl_fini \n\
+- // jump to the user_s entry point \n\
+- mov x16, x21 \n\
+- br x16 \n\
+-");
++/* In elf/rtld.c _dl_start should be global so dl-start.S can reference it. */
++#define RTLD_START asm (".globl _dl_start");
+
+ #define elf_machine_type_class(type) \
+ ((((type) == AARCH64_R(JUMP_SLOT) \
+diff --git a/sysdeps/aarch64/dl-start.S b/sysdeps/aarch64/dl-start.S
+new file mode 100644
+index 0000000000..a3a57bd5a1
+--- /dev/null
++++ b/sysdeps/aarch64/dl-start.S
+@@ -0,0 +1,53 @@
++/* ld.so _start code.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++
++ENTRY (_start)
++ /* Create an initial frame with 0 LR and FP */
++ cfi_undefined (x30)
++ mov x29, #0
++ mov x30, #0
++
++ mov x0, sp
++ PTR_ARG (0)
++ bl _dl_start
++ /* Returns user entry point in x0. */
++ mov PTR_REG (21), PTR_REG (0)
++.globl _dl_start_user
++.type _dl_start_user, %function
++_dl_start_user:
++ /* Get argc. */
++ ldr PTR_REG (1), [sp]
++ /* Get argv. */
++ add x2, sp, PTR_SIZE
++ /* Compute envp. */
++ add PTR_REG (3), PTR_REG (2), PTR_REG (1), lsl PTR_LOG_SIZE
++ add PTR_REG (3), PTR_REG (3), PTR_SIZE
++ adrp x16, _rtld_local
++ add PTR_REG (16), PTR_REG (16), :lo12:_rtld_local
++ ldr PTR_REG (0), [x16]
++ bl _dl_init
++ /* Load the finalizer function. */
++ adrp x0, _dl_fini
++ add PTR_REG (0), PTR_REG (0), :lo12:_dl_fini
++ /* Jump to the user's entry point. */
++ mov x16, x21
++ br x16
++END (_start)
+--
+2.27.0
+
diff --git a/add-GB18030-2022-charmap-BZ-30243.patch b/add-GB18030-2022-charmap-BZ-30243.patch
new file mode 100644
index 0000000..0c15b24
--- /dev/null
+++ b/add-GB18030-2022-charmap-BZ-30243.patch
@@ -0,0 +1,853 @@
+From 1dc4a7192a27142bf3b916287c9cd37a361784f5 Mon Sep 17 00:00:00 2001
+From: lijianglin <lijianglin2@huawei.com>
+Date: Thu, 15 Jun 2023 16:50:13 +0800
+Subject: [PATCH v3] add GB18030-2022 charmap and test the entire GB18030 charmap [BZ #30243]
+
+support GB18030-2022 after add and change some transcoding relationship
+of GB18030-2022.Details are as follows:
+add 25 transcoding relationship
+ UE81E 0x82359037
+ UE826 0x82359038
+ UE82B 0x82359039
+ UE82C 0x82359130
+ UE832 0x82359131
+ UE843 0x82359132
+ UE854 0x82359133
+ UE864 0x82359134
+ UE78D 0x84318236
+ UE78F 0x84318237
+ UE78E 0x84318238
+ UE790 0x84318239
+ UE791 0x84318330
+ UE792 0x84318331
+ UE793 0x84318332
+ UE794 0x84318333
+ UE795 0x84318334
+ UE796 0x84318335
+ UE816 0xfe51
+ UE817 0xfe52
+ UE818 0xfe53
+ UE831 0xfe6c
+ UE83B 0xfe76
+ UE855 0xfe91
+change 6 transcoding relationship
+ U20087 0x95329031
+ U20089 0x95329033
+ U200CC 0x95329730
+ U215D7 0x9536b937
+ U2298F 0x9630ba35
+ U241FE 0x9635b630
+Test the entire GB18030 charmap, not only the Unicode BMP part.
+
+Co-authored-by: yangyanchao <yangyanchao6@huawei.com>
+Co-authored-by: liqingqing <liqingqing3@huawei.com>
+Co-authored-by: Bruno Haible <bruno@clisp.org>
+Reviewed-by: Andreas Schwab <schwab@suse.de>
+---
+ iconvdata/gb18030.c | 423 +++++++++++++++++++-----------------
+ iconvdata/tst-table-from.c | 5 +-
+ iconvdata/tst-table-to.c | 12 +-
+ iconvdata/tst-table.sh | 50 +++--
+ localedata/charmaps/GB18030 | 91 +++-----
+ 5 files changed, 292 insertions(+), 289 deletions(-)
+
+diff --git a/iconvdata/gb18030.c b/iconvdata/gb18030.c
+index 0b03b9bb..ca383dc0 100644
+--- a/iconvdata/gb18030.c
++++ b/iconvdata/gb18030.c
+@@ -6020,49 +6020,50 @@ static const uint16_t __twobyte_to_ucs[] =
+ [0x5dc2] = 0xfa0e, [0x5dc3] = 0xfa0f, [0x5dc4] = 0xfa11, [0x5dc5] = 0xfa13,
+ [0x5dc6] = 0xfa14, [0x5dc7] = 0xfa18, [0x5dc8] = 0xfa1f, [0x5dc9] = 0xfa20,
+ [0x5dca] = 0xfa21, [0x5dcb] = 0xfa23, [0x5dcc] = 0xfa24, [0x5dcd] = 0xfa27,
+- [0x5dce] = 0xfa28, [0x5dcf] = 0xfa29, [0x5dd0] = 0x2e81, [0x5dd4] = 0x2e84,
+- [0x5dd5] = 0x3473, [0x5dd6] = 0x3447, [0x5dd7] = 0x2e88, [0x5dd8] = 0x2e8b,
+- [0x5dd9] = 0x9fb4, [0x5dda] = 0x359e, [0x5ddb] = 0x361a, [0x5ddc] = 0x360e,
+- [0x5ddd] = 0x2e8c, [0x5dde] = 0x2e97, [0x5ddf] = 0x396e, [0x5de0] = 0x3918,
+- [0x5de1] = 0x9fb5, [0x5de2] = 0x39cf, [0x5de3] = 0x39df, [0x5de4] = 0x3a73,
+- [0x5de5] = 0x39d0, [0x5de6] = 0x9fb6, [0x5de7] = 0x9fb7, [0x5de8] = 0x3b4e,
+- [0x5de9] = 0x3c6e, [0x5dea] = 0x3ce0, [0x5deb] = 0x2ea7, [0x5ded] = 0x9fb8,
++ [0x5dce] = 0xfa28, [0x5dcf] = 0xfa29, [0x5dd0] = 0x2e81, [0x5dd1] = 0xe816,
++ [0x5dd2] = 0xe817, [0x5dd3] = 0xe818, [0x5dd4] = 0x2e84, [0x5dd5] = 0x3473,
++ [0x5dd6] = 0x3447, [0x5dd7] = 0x2e88, [0x5dd8] = 0x2e8b, [0x5dd9] = 0x9fb4,
++ [0x5dda] = 0x359e, [0x5ddb] = 0x361a, [0x5ddc] = 0x360e, [0x5ddd] = 0x2e8c,
++ [0x5dde] = 0x2e97, [0x5ddf] = 0x396e, [0x5de0] = 0x3918, [0x5de1] = 0x9fb5,
++ [0x5de2] = 0x39cf, [0x5de3] = 0x39df, [0x5de4] = 0x3a73, [0x5de5] = 0x39d0,
++ [0x5de6] = 0x9fb6, [0x5de7] = 0x9fb7, [0x5de8] = 0x3b4e, [0x5de9] = 0x3c6e,
++ [0x5dea] = 0x3ce0, [0x5deb] = 0x2ea7, [0x5dec] = 0xe831, [0x5ded] = 0x9fb8,
+ [0x5dee] = 0x2eaa, [0x5def] = 0x4056, [0x5df0] = 0x415f, [0x5df1] = 0x2eae,
+ [0x5df2] = 0x4337, [0x5df3] = 0x2eb3, [0x5df4] = 0x2eb6, [0x5df5] = 0x2eb7,
+- [0x5df7] = 0x43b1, [0x5df8] = 0x43ac, [0x5df9] = 0x2ebb, [0x5dfa] = 0x43dd,
+- [0x5dfb] = 0x44d6, [0x5dfc] = 0x4661, [0x5dfd] = 0x464c, [0x5dfe] = 0x9fb9,
+- [0x5e00] = 0x4723, [0x5e01] = 0x4729, [0x5e02] = 0x477c, [0x5e03] = 0x478d,
+- [0x5e04] = 0x2eca, [0x5e05] = 0x4947, [0x5e06] = 0x497a, [0x5e07] = 0x497d,
+- [0x5e08] = 0x4982, [0x5e09] = 0x4983, [0x5e0a] = 0x4985, [0x5e0b] = 0x4986,
+- [0x5e0c] = 0x499f, [0x5e0d] = 0x499b, [0x5e0e] = 0x49b7, [0x5e0f] = 0x49b6,
+- [0x5e10] = 0x9fba, [0x5e12] = 0x4ca3, [0x5e13] = 0x4c9f, [0x5e14] = 0x4ca0,
+- [0x5e15] = 0x4ca1, [0x5e16] = 0x4c77, [0x5e17] = 0x4ca2, [0x5e18] = 0x4d13,
+- [0x5e19] = 0x4d14, [0x5e1a] = 0x4d15, [0x5e1b] = 0x4d16, [0x5e1c] = 0x4d17,
+- [0x5e1d] = 0x4d18, [0x5e1e] = 0x4d19, [0x5e1f] = 0x4dae, [0x5e20] = 0x9fbb,
+- [0x5e21] = 0xe468, [0x5e22] = 0xe469, [0x5e23] = 0xe46a, [0x5e24] = 0xe46b,
+- [0x5e25] = 0xe46c, [0x5e26] = 0xe46d, [0x5e27] = 0xe46e, [0x5e28] = 0xe46f,
+- [0x5e29] = 0xe470, [0x5e2a] = 0xe471, [0x5e2b] = 0xe472, [0x5e2c] = 0xe473,
+- [0x5e2d] = 0xe474, [0x5e2e] = 0xe475, [0x5e2f] = 0xe476, [0x5e30] = 0xe477,
+- [0x5e31] = 0xe478, [0x5e32] = 0xe479, [0x5e33] = 0xe47a, [0x5e34] = 0xe47b,
+- [0x5e35] = 0xe47c, [0x5e36] = 0xe47d, [0x5e37] = 0xe47e, [0x5e38] = 0xe47f,
+- [0x5e39] = 0xe480, [0x5e3a] = 0xe481, [0x5e3b] = 0xe482, [0x5e3c] = 0xe483,
+- [0x5e3d] = 0xe484, [0x5e3e] = 0xe485, [0x5e3f] = 0xe486, [0x5e40] = 0xe487,
+- [0x5e41] = 0xe488, [0x5e42] = 0xe489, [0x5e43] = 0xe48a, [0x5e44] = 0xe48b,
+- [0x5e45] = 0xe48c, [0x5e46] = 0xe48d, [0x5e47] = 0xe48e, [0x5e48] = 0xe48f,
+- [0x5e49] = 0xe490, [0x5e4a] = 0xe491, [0x5e4b] = 0xe492, [0x5e4c] = 0xe493,
+- [0x5e4d] = 0xe494, [0x5e4e] = 0xe495, [0x5e4f] = 0xe496, [0x5e50] = 0xe497,
+- [0x5e51] = 0xe498, [0x5e52] = 0xe499, [0x5e53] = 0xe49a, [0x5e54] = 0xe49b,
+- [0x5e55] = 0xe49c, [0x5e56] = 0xe49d, [0x5e57] = 0xe49e, [0x5e58] = 0xe49f,
+- [0x5e59] = 0xe4a0, [0x5e5a] = 0xe4a1, [0x5e5b] = 0xe4a2, [0x5e5c] = 0xe4a3,
+- [0x5e5d] = 0xe4a4, [0x5e5e] = 0xe4a5, [0x5e5f] = 0xe4a6, [0x5e60] = 0xe4a7,
+- [0x5e61] = 0xe4a8, [0x5e62] = 0xe4a9, [0x5e63] = 0xe4aa, [0x5e64] = 0xe4ab,
+- [0x5e65] = 0xe4ac, [0x5e66] = 0xe4ad, [0x5e67] = 0xe4ae, [0x5e68] = 0xe4af,
+- [0x5e69] = 0xe4b0, [0x5e6a] = 0xe4b1, [0x5e6b] = 0xe4b2, [0x5e6c] = 0xe4b3,
+- [0x5e6d] = 0xe4b4, [0x5e6e] = 0xe4b5, [0x5e6f] = 0xe4b6, [0x5e70] = 0xe4b7,
+- [0x5e71] = 0xe4b8, [0x5e72] = 0xe4b9, [0x5e73] = 0xe4ba, [0x5e74] = 0xe4bb,
+- [0x5e75] = 0xe4bc, [0x5e76] = 0xe4bd, [0x5e77] = 0xe4be, [0x5e78] = 0xe4bf,
+- [0x5e79] = 0xe4c0, [0x5e7a] = 0xe4c1, [0x5e7b] = 0xe4c2, [0x5e7c] = 0xe4c3,
+- [0x5e7d] = 0xe4c4, [0x5e7e] = 0xe4c5,
++ [0x5df6] = 0xe83b, [0x5df7] = 0x43b1, [0x5df8] = 0x43ac, [0x5df9] = 0x2ebb,
++ [0x5dfa] = 0x43dd, [0x5dfb] = 0x44d6, [0x5dfc] = 0x4661, [0x5dfd] = 0x464c,
++ [0x5dfe] = 0x9fb9, [0x5e00] = 0x4723, [0x5e01] = 0x4729, [0x5e02] = 0x477c,
++ [0x5e03] = 0x478d, [0x5e04] = 0x2eca, [0x5e05] = 0x4947, [0x5e06] = 0x497a,
++ [0x5e07] = 0x497d, [0x5e08] = 0x4982, [0x5e09] = 0x4983, [0x5e0a] = 0x4985,
++ [0x5e0b] = 0x4986, [0x5e0c] = 0x499f, [0x5e0d] = 0x499b, [0x5e0e] = 0x49b7,
++ [0x5e0f] = 0x49b6, [0x5e10] = 0x9fba, [0x5e11] = 0xe855, [0x5e12] = 0x4ca3,
++ [0x5e13] = 0x4c9f, [0x5e14] = 0x4ca0, [0x5e15] = 0x4ca1, [0x5e16] = 0x4c77,
++ [0x5e17] = 0x4ca2, [0x5e18] = 0x4d13, [0x5e19] = 0x4d14, [0x5e1a] = 0x4d15,
++ [0x5e1b] = 0x4d16, [0x5e1c] = 0x4d17, [0x5e1d] = 0x4d18, [0x5e1e] = 0x4d19,
++ [0x5e1f] = 0x4dae, [0x5e20] = 0x9fbb, [0x5e21] = 0xe468, [0x5e22] = 0xe469,
++ [0x5e23] = 0xe46a, [0x5e24] = 0xe46b, [0x5e25] = 0xe46c, [0x5e26] = 0xe46d,
++ [0x5e27] = 0xe46e, [0x5e28] = 0xe46f, [0x5e29] = 0xe470, [0x5e2a] = 0xe471,
++ [0x5e2b] = 0xe472, [0x5e2c] = 0xe473, [0x5e2d] = 0xe474, [0x5e2e] = 0xe475,
++ [0x5e2f] = 0xe476, [0x5e30] = 0xe477, [0x5e31] = 0xe478, [0x5e32] = 0xe479,
++ [0x5e33] = 0xe47a, [0x5e34] = 0xe47b, [0x5e35] = 0xe47c, [0x5e36] = 0xe47d,
++ [0x5e37] = 0xe47e, [0x5e38] = 0xe47f, [0x5e39] = 0xe480, [0x5e3a] = 0xe481,
++ [0x5e3b] = 0xe482, [0x5e3c] = 0xe483, [0x5e3d] = 0xe484, [0x5e3e] = 0xe485,
++ [0x5e3f] = 0xe486, [0x5e40] = 0xe487, [0x5e41] = 0xe488, [0x5e42] = 0xe489,
++ [0x5e43] = 0xe48a, [0x5e44] = 0xe48b, [0x5e45] = 0xe48c, [0x5e46] = 0xe48d,
++ [0x5e47] = 0xe48e, [0x5e48] = 0xe48f, [0x5e49] = 0xe490, [0x5e4a] = 0xe491,
++ [0x5e4b] = 0xe492, [0x5e4c] = 0xe493, [0x5e4d] = 0xe494, [0x5e4e] = 0xe495,
++ [0x5e4f] = 0xe496, [0x5e50] = 0xe497, [0x5e51] = 0xe498, [0x5e52] = 0xe499,
++ [0x5e53] = 0xe49a, [0x5e54] = 0xe49b, [0x5e55] = 0xe49c, [0x5e56] = 0xe49d,
++ [0x5e57] = 0xe49e, [0x5e58] = 0xe49f, [0x5e59] = 0xe4a0, [0x5e5a] = 0xe4a1,
++ [0x5e5b] = 0xe4a2, [0x5e5c] = 0xe4a3, [0x5e5d] = 0xe4a4, [0x5e5e] = 0xe4a5,
++ [0x5e5f] = 0xe4a6, [0x5e60] = 0xe4a7, [0x5e61] = 0xe4a8, [0x5e62] = 0xe4a9,
++ [0x5e63] = 0xe4aa, [0x5e64] = 0xe4ab, [0x5e65] = 0xe4ac, [0x5e66] = 0xe4ad,
++ [0x5e67] = 0xe4ae, [0x5e68] = 0xe4af, [0x5e69] = 0xe4b0, [0x5e6a] = 0xe4b1,
++ [0x5e6b] = 0xe4b2, [0x5e6c] = 0xe4b3, [0x5e6d] = 0xe4b4, [0x5e6e] = 0xe4b5,
++ [0x5e6f] = 0xe4b6, [0x5e70] = 0xe4b7, [0x5e71] = 0xe4b8, [0x5e72] = 0xe4b9,
++ [0x5e73] = 0xe4ba, [0x5e74] = 0xe4bb, [0x5e75] = 0xe4bc, [0x5e76] = 0xe4bd,
++ [0x5e77] = 0xe4be, [0x5e78] = 0xe4bf, [0x5e79] = 0xe4c0, [0x5e7a] = 0xe4c1,
++ [0x5e7b] = 0xe4c2, [0x5e7c] = 0xe4c3, [0x5e7d] = 0xe4c4, [0x5e7e] = 0xe4c5,
+ };
+
+ /* Table for GB18030 -> UCS-4, containing the four-byte characters only,
+@@ -8691,7 +8692,9 @@ static const uint16_t __fourbyte_to_ucs[0x99e2 - 6637 - 2110 - 14404 - 4295] =
+ [0x2838] = 0x9fa6, [0x2839] = 0x9fa7, [0x283a] = 0x9fa8, [0x283b] = 0x9fa9,
+ [0x283c] = 0x9faa, [0x283d] = 0x9fab, [0x283e] = 0x9fac, [0x283f] = 0x9fad,
+ [0x2840] = 0x9fae, [0x2841] = 0x9faf, [0x2842] = 0x9fb0, [0x2843] = 0x9fb1,
+- [0x2844] = 0x9fb2, [0x2845] = 0x9fb3, [0x284e] = 0xe76c, [0x284f] = 0xe7c8,
++ [0x2844] = 0x9fb2, [0x2845] = 0x9fb3, [0x2846] = 0xe81e, [0x2847] = 0xe826,
++ [0x2848] = 0xe82b, [0x2849] = 0xe82c, [0x284a] = 0xe832, [0x284b] = 0xe843,
++ [0x284c] = 0xe854, [0x284d] = 0xe864, [0x284e] = 0xe76c, [0x284f] = 0xe7c8,
+ [0x2850] = 0xe7e7, [0x2851] = 0xe7e8, [0x2852] = 0xe7e9, [0x2853] = 0xe7ea,
+ [0x2854] = 0xe7eb, [0x2855] = 0xe7ec, [0x2856] = 0xe7ed, [0x2857] = 0xe7ee,
+ [0x2858] = 0xe7ef, [0x2859] = 0xe7f0, [0x285a] = 0xe7f1, [0x285b] = 0xe7f2,
+@@ -9019,84 +9022,86 @@ static const uint16_t __fourbyte_to_ucs[0x99e2 - 6637 - 2110 - 14404 - 4295] =
+ [0x2d60] = 0xfe02, [0x2d61] = 0xfe03, [0x2d62] = 0xfe04, [0x2d63] = 0xfe05,
+ [0x2d64] = 0xfe06, [0x2d65] = 0xfe07, [0x2d66] = 0xfe08, [0x2d67] = 0xfe09,
+ [0x2d68] = 0xfe0a, [0x2d69] = 0xfe0b, [0x2d6a] = 0xfe0c, [0x2d6b] = 0xfe0d,
+- [0x2d6c] = 0xfe0e, [0x2d6d] = 0xfe0f, [0x2d78] = 0xfe1a, [0x2d79] = 0xfe1b,
+- [0x2d7a] = 0xfe1c, [0x2d7b] = 0xfe1d, [0x2d7c] = 0xfe1e, [0x2d7d] = 0xfe1f,
+- [0x2d7e] = 0xfe20, [0x2d7f] = 0xfe21, [0x2d80] = 0xfe22, [0x2d81] = 0xfe23,
+- [0x2d82] = 0xfe24, [0x2d83] = 0xfe25, [0x2d84] = 0xfe26, [0x2d85] = 0xfe27,
+- [0x2d86] = 0xfe28, [0x2d87] = 0xfe29, [0x2d88] = 0xfe2a, [0x2d89] = 0xfe2b,
+- [0x2d8a] = 0xfe2c, [0x2d8b] = 0xfe2d, [0x2d8c] = 0xfe2e, [0x2d8d] = 0xfe2f,
+- [0x2d8e] = 0xfe32, [0x2d8f] = 0xfe45, [0x2d90] = 0xfe46, [0x2d91] = 0xfe47,
+- [0x2d92] = 0xfe48, [0x2d93] = 0xfe53, [0x2d94] = 0xfe58, [0x2d95] = 0xfe67,
+- [0x2d96] = 0xfe6c, [0x2d97] = 0xfe6d, [0x2d98] = 0xfe6e, [0x2d99] = 0xfe6f,
+- [0x2d9a] = 0xfe70, [0x2d9b] = 0xfe71, [0x2d9c] = 0xfe72, [0x2d9d] = 0xfe73,
+- [0x2d9e] = 0xfe74, [0x2d9f] = 0xfe75, [0x2da0] = 0xfe76, [0x2da1] = 0xfe77,
+- [0x2da2] = 0xfe78, [0x2da3] = 0xfe79, [0x2da4] = 0xfe7a, [0x2da5] = 0xfe7b,
+- [0x2da6] = 0xfe7c, [0x2da7] = 0xfe7d, [0x2da8] = 0xfe7e, [0x2da9] = 0xfe7f,
+- [0x2daa] = 0xfe80, [0x2dab] = 0xfe81, [0x2dac] = 0xfe82, [0x2dad] = 0xfe83,
+- [0x2dae] = 0xfe84, [0x2daf] = 0xfe85, [0x2db0] = 0xfe86, [0x2db1] = 0xfe87,
+- [0x2db2] = 0xfe88, [0x2db3] = 0xfe89, [0x2db4] = 0xfe8a, [0x2db5] = 0xfe8b,
+- [0x2db6] = 0xfe8c, [0x2db7] = 0xfe8d, [0x2db8] = 0xfe8e, [0x2db9] = 0xfe8f,
+- [0x2dba] = 0xfe90, [0x2dbb] = 0xfe91, [0x2dbc] = 0xfe92, [0x2dbd] = 0xfe93,
+- [0x2dbe] = 0xfe94, [0x2dbf] = 0xfe95, [0x2dc0] = 0xfe96, [0x2dc1] = 0xfe97,
+- [0x2dc2] = 0xfe98, [0x2dc3] = 0xfe99, [0x2dc4] = 0xfe9a, [0x2dc5] = 0xfe9b,
+- [0x2dc6] = 0xfe9c, [0x2dc7] = 0xfe9d, [0x2dc8] = 0xfe9e, [0x2dc9] = 0xfe9f,
+- [0x2dca] = 0xfea0, [0x2dcb] = 0xfea1, [0x2dcc] = 0xfea2, [0x2dcd] = 0xfea3,
+- [0x2dce] = 0xfea4, [0x2dcf] = 0xfea5, [0x2dd0] = 0xfea6, [0x2dd1] = 0xfea7,
+- [0x2dd2] = 0xfea8, [0x2dd3] = 0xfea9, [0x2dd4] = 0xfeaa, [0x2dd5] = 0xfeab,
+- [0x2dd6] = 0xfeac, [0x2dd7] = 0xfead, [0x2dd8] = 0xfeae, [0x2dd9] = 0xfeaf,
+- [0x2dda] = 0xfeb0, [0x2ddb] = 0xfeb1, [0x2ddc] = 0xfeb2, [0x2ddd] = 0xfeb3,
+- [0x2dde] = 0xfeb4, [0x2ddf] = 0xfeb5, [0x2de0] = 0xfeb6, [0x2de1] = 0xfeb7,
+- [0x2de2] = 0xfeb8, [0x2de3] = 0xfeb9, [0x2de4] = 0xfeba, [0x2de5] = 0xfebb,
+- [0x2de6] = 0xfebc, [0x2de7] = 0xfebd, [0x2de8] = 0xfebe, [0x2de9] = 0xfebf,
+- [0x2dea] = 0xfec0, [0x2deb] = 0xfec1, [0x2dec] = 0xfec2, [0x2ded] = 0xfec3,
+- [0x2dee] = 0xfec4, [0x2def] = 0xfec5, [0x2df0] = 0xfec6, [0x2df1] = 0xfec7,
+- [0x2df2] = 0xfec8, [0x2df3] = 0xfec9, [0x2df4] = 0xfeca, [0x2df5] = 0xfecb,
+- [0x2df6] = 0xfecc, [0x2df7] = 0xfecd, [0x2df8] = 0xfece, [0x2df9] = 0xfecf,
+- [0x2dfa] = 0xfed0, [0x2dfb] = 0xfed1, [0x2dfc] = 0xfed2, [0x2dfd] = 0xfed3,
+- [0x2dfe] = 0xfed4, [0x2dff] = 0xfed5, [0x2e00] = 0xfed6, [0x2e01] = 0xfed7,
+- [0x2e02] = 0xfed8, [0x2e03] = 0xfed9, [0x2e04] = 0xfeda, [0x2e05] = 0xfedb,
+- [0x2e06] = 0xfedc, [0x2e07] = 0xfedd, [0x2e08] = 0xfede, [0x2e09] = 0xfedf,
+- [0x2e0a] = 0xfee0, [0x2e0b] = 0xfee1, [0x2e0c] = 0xfee2, [0x2e0d] = 0xfee3,
+- [0x2e0e] = 0xfee4, [0x2e0f] = 0xfee5, [0x2e10] = 0xfee6, [0x2e11] = 0xfee7,
+- [0x2e12] = 0xfee8, [0x2e13] = 0xfee9, [0x2e14] = 0xfeea, [0x2e15] = 0xfeeb,
+- [0x2e16] = 0xfeec, [0x2e17] = 0xfeed, [0x2e18] = 0xfeee, [0x2e19] = 0xfeef,
+- [0x2e1a] = 0xfef0, [0x2e1b] = 0xfef1, [0x2e1c] = 0xfef2, [0x2e1d] = 0xfef3,
+- [0x2e1e] = 0xfef4, [0x2e1f] = 0xfef5, [0x2e20] = 0xfef6, [0x2e21] = 0xfef7,
+- [0x2e22] = 0xfef8, [0x2e23] = 0xfef9, [0x2e24] = 0xfefa, [0x2e25] = 0xfefb,
+- [0x2e26] = 0xfefc, [0x2e27] = 0xfefd, [0x2e28] = 0xfefe, [0x2e29] = 0xfeff,
+- [0x2e2a] = 0xff00, [0x2e2b] = 0xff5f, [0x2e2c] = 0xff60, [0x2e2d] = 0xff61,
+- [0x2e2e] = 0xff62, [0x2e2f] = 0xff63, [0x2e30] = 0xff64, [0x2e31] = 0xff65,
+- [0x2e32] = 0xff66, [0x2e33] = 0xff67, [0x2e34] = 0xff68, [0x2e35] = 0xff69,
+- [0x2e36] = 0xff6a, [0x2e37] = 0xff6b, [0x2e38] = 0xff6c, [0x2e39] = 0xff6d,
+- [0x2e3a] = 0xff6e, [0x2e3b] = 0xff6f, [0x2e3c] = 0xff70, [0x2e3d] = 0xff71,
+- [0x2e3e] = 0xff72, [0x2e3f] = 0xff73, [0x2e40] = 0xff74, [0x2e41] = 0xff75,
+- [0x2e42] = 0xff76, [0x2e43] = 0xff77, [0x2e44] = 0xff78, [0x2e45] = 0xff79,
+- [0x2e46] = 0xff7a, [0x2e47] = 0xff7b, [0x2e48] = 0xff7c, [0x2e49] = 0xff7d,
+- [0x2e4a] = 0xff7e, [0x2e4b] = 0xff7f, [0x2e4c] = 0xff80, [0x2e4d] = 0xff81,
+- [0x2e4e] = 0xff82, [0x2e4f] = 0xff83, [0x2e50] = 0xff84, [0x2e51] = 0xff85,
+- [0x2e52] = 0xff86, [0x2e53] = 0xff87, [0x2e54] = 0xff88, [0x2e55] = 0xff89,
+- [0x2e56] = 0xff8a, [0x2e57] = 0xff8b, [0x2e58] = 0xff8c, [0x2e59] = 0xff8d,
+- [0x2e5a] = 0xff8e, [0x2e5b] = 0xff8f, [0x2e5c] = 0xff90, [0x2e5d] = 0xff91,
+- [0x2e5e] = 0xff92, [0x2e5f] = 0xff93, [0x2e60] = 0xff94, [0x2e61] = 0xff95,
+- [0x2e62] = 0xff96, [0x2e63] = 0xff97, [0x2e64] = 0xff98, [0x2e65] = 0xff99,
+- [0x2e66] = 0xff9a, [0x2e67] = 0xff9b, [0x2e68] = 0xff9c, [0x2e69] = 0xff9d,
+- [0x2e6a] = 0xff9e, [0x2e6b] = 0xff9f, [0x2e6c] = 0xffa0, [0x2e6d] = 0xffa1,
+- [0x2e6e] = 0xffa2, [0x2e6f] = 0xffa3, [0x2e70] = 0xffa4, [0x2e71] = 0xffa5,
+- [0x2e72] = 0xffa6, [0x2e73] = 0xffa7, [0x2e74] = 0xffa8, [0x2e75] = 0xffa9,
+- [0x2e76] = 0xffaa, [0x2e77] = 0xffab, [0x2e78] = 0xffac, [0x2e79] = 0xffad,
+- [0x2e7a] = 0xffae, [0x2e7b] = 0xffaf, [0x2e7c] = 0xffb0, [0x2e7d] = 0xffb1,
+- [0x2e7e] = 0xffb2, [0x2e7f] = 0xffb3, [0x2e80] = 0xffb4, [0x2e81] = 0xffb5,
+- [0x2e82] = 0xffb6, [0x2e83] = 0xffb7, [0x2e84] = 0xffb8, [0x2e85] = 0xffb9,
+- [0x2e86] = 0xffba, [0x2e87] = 0xffbb, [0x2e88] = 0xffbc, [0x2e89] = 0xffbd,
+- [0x2e8a] = 0xffbe, [0x2e8b] = 0xffbf, [0x2e8c] = 0xffc0, [0x2e8d] = 0xffc1,
+- [0x2e8e] = 0xffc2, [0x2e8f] = 0xffc3, [0x2e90] = 0xffc4, [0x2e91] = 0xffc5,
+- [0x2e92] = 0xffc6, [0x2e93] = 0xffc7, [0x2e94] = 0xffc8, [0x2e95] = 0xffc9,
+- [0x2e96] = 0xffca, [0x2e97] = 0xffcb, [0x2e98] = 0xffcc, [0x2e99] = 0xffcd,
+- [0x2e9a] = 0xffce, [0x2e9b] = 0xffcf, [0x2e9c] = 0xffd0, [0x2e9d] = 0xffd1,
+- [0x2e9e] = 0xffd2, [0x2e9f] = 0xffd3, [0x2ea0] = 0xffd4, [0x2ea1] = 0xffd5,
+- [0x2ea2] = 0xffd6, [0x2ea3] = 0xffd7, [0x2ea4] = 0xffd8, [0x2ea5] = 0xffd9,
+- [0x2ea6] = 0xffda, [0x2ea7] = 0xffdb, [0x2ea8] = 0xffdc, [0x2ea9] = 0xffdd,
+- [0x2eaa] = 0xffde, [0x2eab] = 0xffdf,
++ [0x2d6c] = 0xfe0e, [0x2d6d] = 0xfe0f, [0x2d6e] = 0xe78d, [0x2d6f] = 0xe78f,
++ [0x2d70] = 0xe78e, [0x2d71] = 0xe790, [0x2d72] = 0xe791, [0x2d73] = 0xe792,
++ [0x2d74] = 0xe793, [0x2d75] = 0xe794, [0x2d76] = 0xe795, [0x2d77] = 0xe796,
++ [0x2d78] = 0xfe1a, [0x2d79] = 0xfe1b, [0x2d7a] = 0xfe1c, [0x2d7b] = 0xfe1d,
++ [0x2d7c] = 0xfe1e, [0x2d7d] = 0xfe1f, [0x2d7e] = 0xfe20, [0x2d7f] = 0xfe21,
++ [0x2d80] = 0xfe22, [0x2d81] = 0xfe23, [0x2d82] = 0xfe24, [0x2d83] = 0xfe25,
++ [0x2d84] = 0xfe26, [0x2d85] = 0xfe27, [0x2d86] = 0xfe28, [0x2d87] = 0xfe29,
++ [0x2d88] = 0xfe2a, [0x2d89] = 0xfe2b, [0x2d8a] = 0xfe2c, [0x2d8b] = 0xfe2d,
++ [0x2d8c] = 0xfe2e, [0x2d8d] = 0xfe2f, [0x2d8e] = 0xfe32, [0x2d8f] = 0xfe45,
++ [0x2d90] = 0xfe46, [0x2d91] = 0xfe47, [0x2d92] = 0xfe48, [0x2d93] = 0xfe53,
++ [0x2d94] = 0xfe58, [0x2d95] = 0xfe67, [0x2d96] = 0xfe6c, [0x2d97] = 0xfe6d,
++ [0x2d98] = 0xfe6e, [0x2d99] = 0xfe6f, [0x2d9a] = 0xfe70, [0x2d9b] = 0xfe71,
++ [0x2d9c] = 0xfe72, [0x2d9d] = 0xfe73, [0x2d9e] = 0xfe74, [0x2d9f] = 0xfe75,
++ [0x2da0] = 0xfe76, [0x2da1] = 0xfe77, [0x2da2] = 0xfe78, [0x2da3] = 0xfe79,
++ [0x2da4] = 0xfe7a, [0x2da5] = 0xfe7b, [0x2da6] = 0xfe7c, [0x2da7] = 0xfe7d,
++ [0x2da8] = 0xfe7e, [0x2da9] = 0xfe7f, [0x2daa] = 0xfe80, [0x2dab] = 0xfe81,
++ [0x2dac] = 0xfe82, [0x2dad] = 0xfe83, [0x2dae] = 0xfe84, [0x2daf] = 0xfe85,
++ [0x2db0] = 0xfe86, [0x2db1] = 0xfe87, [0x2db2] = 0xfe88, [0x2db3] = 0xfe89,
++ [0x2db4] = 0xfe8a, [0x2db5] = 0xfe8b, [0x2db6] = 0xfe8c, [0x2db7] = 0xfe8d,
++ [0x2db8] = 0xfe8e, [0x2db9] = 0xfe8f, [0x2dba] = 0xfe90, [0x2dbb] = 0xfe91,
++ [0x2dbc] = 0xfe92, [0x2dbd] = 0xfe93, [0x2dbe] = 0xfe94, [0x2dbf] = 0xfe95,
++ [0x2dc0] = 0xfe96, [0x2dc1] = 0xfe97, [0x2dc2] = 0xfe98, [0x2dc3] = 0xfe99,
++ [0x2dc4] = 0xfe9a, [0x2dc5] = 0xfe9b, [0x2dc6] = 0xfe9c, [0x2dc7] = 0xfe9d,
++ [0x2dc8] = 0xfe9e, [0x2dc9] = 0xfe9f, [0x2dca] = 0xfea0, [0x2dcb] = 0xfea1,
++ [0x2dcc] = 0xfea2, [0x2dcd] = 0xfea3, [0x2dce] = 0xfea4, [0x2dcf] = 0xfea5,
++ [0x2dd0] = 0xfea6, [0x2dd1] = 0xfea7, [0x2dd2] = 0xfea8, [0x2dd3] = 0xfea9,
++ [0x2dd4] = 0xfeaa, [0x2dd5] = 0xfeab, [0x2dd6] = 0xfeac, [0x2dd7] = 0xfead,
++ [0x2dd8] = 0xfeae, [0x2dd9] = 0xfeaf, [0x2dda] = 0xfeb0, [0x2ddb] = 0xfeb1,
++ [0x2ddc] = 0xfeb2, [0x2ddd] = 0xfeb3, [0x2dde] = 0xfeb4, [0x2ddf] = 0xfeb5,
++ [0x2de0] = 0xfeb6, [0x2de1] = 0xfeb7, [0x2de2] = 0xfeb8, [0x2de3] = 0xfeb9,
++ [0x2de4] = 0xfeba, [0x2de5] = 0xfebb, [0x2de6] = 0xfebc, [0x2de7] = 0xfebd,
++ [0x2de8] = 0xfebe, [0x2de9] = 0xfebf, [0x2dea] = 0xfec0, [0x2deb] = 0xfec1,
++ [0x2dec] = 0xfec2, [0x2ded] = 0xfec3, [0x2dee] = 0xfec4, [0x2def] = 0xfec5,
++ [0x2df0] = 0xfec6, [0x2df1] = 0xfec7, [0x2df2] = 0xfec8, [0x2df3] = 0xfec9,
++ [0x2df4] = 0xfeca, [0x2df5] = 0xfecb, [0x2df6] = 0xfecc, [0x2df7] = 0xfecd,
++ [0x2df8] = 0xfece, [0x2df9] = 0xfecf, [0x2dfa] = 0xfed0, [0x2dfb] = 0xfed1,
++ [0x2dfc] = 0xfed2, [0x2dfd] = 0xfed3, [0x2dfe] = 0xfed4, [0x2dff] = 0xfed5,
++ [0x2e00] = 0xfed6, [0x2e01] = 0xfed7, [0x2e02] = 0xfed8, [0x2e03] = 0xfed9,
++ [0x2e04] = 0xfeda, [0x2e05] = 0xfedb, [0x2e06] = 0xfedc, [0x2e07] = 0xfedd,
++ [0x2e08] = 0xfede, [0x2e09] = 0xfedf, [0x2e0a] = 0xfee0, [0x2e0b] = 0xfee1,
++ [0x2e0c] = 0xfee2, [0x2e0d] = 0xfee3, [0x2e0e] = 0xfee4, [0x2e0f] = 0xfee5,
++ [0x2e10] = 0xfee6, [0x2e11] = 0xfee7, [0x2e12] = 0xfee8, [0x2e13] = 0xfee9,
++ [0x2e14] = 0xfeea, [0x2e15] = 0xfeeb, [0x2e16] = 0xfeec, [0x2e17] = 0xfeed,
++ [0x2e18] = 0xfeee, [0x2e19] = 0xfeef, [0x2e1a] = 0xfef0, [0x2e1b] = 0xfef1,
++ [0x2e1c] = 0xfef2, [0x2e1d] = 0xfef3, [0x2e1e] = 0xfef4, [0x2e1f] = 0xfef5,
++ [0x2e20] = 0xfef6, [0x2e21] = 0xfef7, [0x2e22] = 0xfef8, [0x2e23] = 0xfef9,
++ [0x2e24] = 0xfefa, [0x2e25] = 0xfefb, [0x2e26] = 0xfefc, [0x2e27] = 0xfefd,
++ [0x2e28] = 0xfefe, [0x2e29] = 0xfeff, [0x2e2a] = 0xff00, [0x2e2b] = 0xff5f,
++ [0x2e2c] = 0xff60, [0x2e2d] = 0xff61, [0x2e2e] = 0xff62, [0x2e2f] = 0xff63,
++ [0x2e30] = 0xff64, [0x2e31] = 0xff65, [0x2e32] = 0xff66, [0x2e33] = 0xff67,
++ [0x2e34] = 0xff68, [0x2e35] = 0xff69, [0x2e36] = 0xff6a, [0x2e37] = 0xff6b,
++ [0x2e38] = 0xff6c, [0x2e39] = 0xff6d, [0x2e3a] = 0xff6e, [0x2e3b] = 0xff6f,
++ [0x2e3c] = 0xff70, [0x2e3d] = 0xff71, [0x2e3e] = 0xff72, [0x2e3f] = 0xff73,
++ [0x2e40] = 0xff74, [0x2e41] = 0xff75, [0x2e42] = 0xff76, [0x2e43] = 0xff77,
++ [0x2e44] = 0xff78, [0x2e45] = 0xff79, [0x2e46] = 0xff7a, [0x2e47] = 0xff7b,
++ [0x2e48] = 0xff7c, [0x2e49] = 0xff7d, [0x2e4a] = 0xff7e, [0x2e4b] = 0xff7f,
++ [0x2e4c] = 0xff80, [0x2e4d] = 0xff81, [0x2e4e] = 0xff82, [0x2e4f] = 0xff83,
++ [0x2e50] = 0xff84, [0x2e51] = 0xff85, [0x2e52] = 0xff86, [0x2e53] = 0xff87,
++ [0x2e54] = 0xff88, [0x2e55] = 0xff89, [0x2e56] = 0xff8a, [0x2e57] = 0xff8b,
++ [0x2e58] = 0xff8c, [0x2e59] = 0xff8d, [0x2e5a] = 0xff8e, [0x2e5b] = 0xff8f,
++ [0x2e5c] = 0xff90, [0x2e5d] = 0xff91, [0x2e5e] = 0xff92, [0x2e5f] = 0xff93,
++ [0x2e60] = 0xff94, [0x2e61] = 0xff95, [0x2e62] = 0xff96, [0x2e63] = 0xff97,
++ [0x2e64] = 0xff98, [0x2e65] = 0xff99, [0x2e66] = 0xff9a, [0x2e67] = 0xff9b,
++ [0x2e68] = 0xff9c, [0x2e69] = 0xff9d, [0x2e6a] = 0xff9e, [0x2e6b] = 0xff9f,
++ [0x2e6c] = 0xffa0, [0x2e6d] = 0xffa1, [0x2e6e] = 0xffa2, [0x2e6f] = 0xffa3,
++ [0x2e70] = 0xffa4, [0x2e71] = 0xffa5, [0x2e72] = 0xffa6, [0x2e73] = 0xffa7,
++ [0x2e74] = 0xffa8, [0x2e75] = 0xffa9, [0x2e76] = 0xffaa, [0x2e77] = 0xffab,
++ [0x2e78] = 0xffac, [0x2e79] = 0xffad, [0x2e7a] = 0xffae, [0x2e7b] = 0xffaf,
++ [0x2e7c] = 0xffb0, [0x2e7d] = 0xffb1, [0x2e7e] = 0xffb2, [0x2e7f] = 0xffb3,
++ [0x2e80] = 0xffb4, [0x2e81] = 0xffb5, [0x2e82] = 0xffb6, [0x2e83] = 0xffb7,
++ [0x2e84] = 0xffb8, [0x2e85] = 0xffb9, [0x2e86] = 0xffba, [0x2e87] = 0xffbb,
++ [0x2e88] = 0xffbc, [0x2e89] = 0xffbd, [0x2e8a] = 0xffbe, [0x2e8b] = 0xffbf,
++ [0x2e8c] = 0xffc0, [0x2e8d] = 0xffc1, [0x2e8e] = 0xffc2, [0x2e8f] = 0xffc3,
++ [0x2e90] = 0xffc4, [0x2e91] = 0xffc5, [0x2e92] = 0xffc6, [0x2e93] = 0xffc7,
++ [0x2e94] = 0xffc8, [0x2e95] = 0xffc9, [0x2e96] = 0xffca, [0x2e97] = 0xffcb,
++ [0x2e98] = 0xffcc, [0x2e99] = 0xffcd, [0x2e9a] = 0xffce, [0x2e9b] = 0xffcf,
++ [0x2e9c] = 0xffd0, [0x2e9d] = 0xffd1, [0x2e9e] = 0xffd2, [0x2e9f] = 0xffd3,
++ [0x2ea0] = 0xffd4, [0x2ea1] = 0xffd5, [0x2ea2] = 0xffd6, [0x2ea3] = 0xffd7,
++ [0x2ea4] = 0xffd8, [0x2ea5] = 0xffd9, [0x2ea6] = 0xffda, [0x2ea7] = 0xffdb,
++ [0x2ea8] = 0xffdc, [0x2ea9] = 0xffdd, [0x2eaa] = 0xffde, [0x2eab] = 0xffdf,
+ };
+
+ /* Table for UCS-4 -> GB18030, for the range U+0080..U+9FBB.
+@@ -23448,71 +23453,79 @@ static const unsigned char __ucs_to_gb18030_tab2[][2] =
+ [0x0783] = "\xa5\xfd", [0x0784] = "\xa5\xfe", [0x0785] = "\xa6\xb9",
+ [0x0786] = "\xa6\xba", [0x0787] = "\xa6\xbb", [0x0788] = "\xa6\xbc",
+ [0x0789] = "\xa6\xbd", [0x078a] = "\xa6\xbe", [0x078b] = "\xa6\xbf",
+- [0x078c] = "\xa6\xc0", [0x0797] = "\xa6\xf6", [0x0798] = "\xa6\xf7",
+- [0x0799] = "\xa6\xf8", [0x079a] = "\xa6\xf9", [0x079b] = "\xa6\xfa",
+- [0x079c] = "\xa6\xfb", [0x079d] = "\xa6\xfc", [0x079e] = "\xa6\xfd",
+- [0x079f] = "\xa6\xfe", [0x07a0] = "\xa7\xc2", [0x07a1] = "\xa7\xc3",
+- [0x07a2] = "\xa7\xc4", [0x07a3] = "\xa7\xc5", [0x07a4] = "\xa7\xc6",
+- [0x07a5] = "\xa7\xc7", [0x07a6] = "\xa7\xc8", [0x07a7] = "\xa7\xc9",
+- [0x07a8] = "\xa7\xca", [0x07a9] = "\xa7\xcb", [0x07aa] = "\xa7\xcc",
+- [0x07ab] = "\xa7\xcd", [0x07ac] = "\xa7\xce", [0x07ad] = "\xa7\xcf",
+- [0x07ae] = "\xa7\xd0", [0x07af] = "\xa7\xf2", [0x07b0] = "\xa7\xf3",
+- [0x07b1] = "\xa7\xf4", [0x07b2] = "\xa7\xf5", [0x07b3] = "\xa7\xf6",
+- [0x07b4] = "\xa7\xf7", [0x07b5] = "\xa7\xf8", [0x07b6] = "\xa7\xf9",
+- [0x07b7] = "\xa7\xfa", [0x07b8] = "\xa7\xfb", [0x07b9] = "\xa7\xfc",
+- [0x07ba] = "\xa7\xfd", [0x07bb] = "\xa7\xfe", [0x07bc] = "\xa8\x96",
+- [0x07bd] = "\xa8\x97", [0x07be] = "\xa8\x98", [0x07bf] = "\xa8\x99",
+- [0x07c0] = "\xa8\x9a", [0x07c1] = "\xa8\x9b", [0x07c2] = "\xa8\x9c",
+- [0x07c3] = "\xa8\x9d", [0x07c4] = "\xa8\x9e", [0x07c5] = "\xa8\x9f",
+- [0x07c6] = "\xa8\xa0", [0x07c7] = "\x00\x01", [0x07c8] = "\x65\x9e",
+- [0x07c9] = "\xa8\xc1", [0x07ca] = "\xa8\xc2", [0x07cb] = "\xa8\xc3",
+- [0x07cc] = "\xa8\xc4", [0x07cd] = "\xa8\xea", [0x07ce] = "\xa8\xeb",
+- [0x07cf] = "\xa8\xec", [0x07d0] = "\xa8\xed", [0x07d1] = "\xa8\xee",
+- [0x07d2] = "\xa8\xef", [0x07d3] = "\xa8\xf0", [0x07d4] = "\xa8\xf1",
+- [0x07d5] = "\xa8\xf2", [0x07d6] = "\xa8\xf3", [0x07d7] = "\xa8\xf4",
+- [0x07d8] = "\xa8\xf5", [0x07d9] = "\xa8\xf6", [0x07da] = "\xa8\xf7",
+- [0x07db] = "\xa8\xf8", [0x07dc] = "\xa8\xf9", [0x07dd] = "\xa8\xfa",
+- [0x07de] = "\xa8\xfb", [0x07df] = "\xa8\xfc", [0x07e0] = "\xa8\xfd",
+- [0x07e1] = "\xa8\xfe", [0x07e2] = "\xa9\x58", [0x07e3] = "\xa9\x5b",
+- [0x07e4] = "\xa9\x5d", [0x07e5] = "\xa9\x5e", [0x07e6] = "\xa9\x5f",
+- [0x07e7] = "\x65\x9f", [0x07e8] = "\x65\xa0", [0x07e9] = "\x65\xa1",
+- [0x07ea] = "\x65\xa2", [0x07eb] = "\x65\xa3", [0x07ec] = "\x65\xa4",
+- [0x07ed] = "\x65\xa5", [0x07ee] = "\x65\xa6", [0x07ef] = "\x65\xa7",
+- [0x07f0] = "\x65\xa8", [0x07f1] = "\x65\xa9", [0x07f2] = "\x65\xaa",
+- [0x07f3] = "\x65\xab", [0x07f4] = "\xa9\x97", [0x07f5] = "\xa9\x98",
+- [0x07f6] = "\xa9\x99", [0x07f7] = "\xa9\x9a", [0x07f8] = "\xa9\x9b",
+- [0x07f9] = "\xa9\x9c", [0x07fa] = "\xa9\x9d", [0x07fb] = "\xa9\x9e",
+- [0x07fc] = "\xa9\x9f", [0x07fd] = "\xa9\xa0", [0x07fe] = "\xa9\xa1",
+- [0x07ff] = "\xa9\xa2", [0x0800] = "\xa9\xa3", [0x0801] = "\xa9\xf0",
+- [0x0802] = "\xa9\xf1", [0x0803] = "\xa9\xf2", [0x0804] = "\xa9\xf3",
+- [0x0805] = "\xa9\xf4", [0x0806] = "\xa9\xf5", [0x0807] = "\xa9\xf6",
+- [0x0808] = "\xa9\xf7", [0x0809] = "\xa9\xf8", [0x080a] = "\xa9\xf9",
+- [0x080b] = "\xa9\xfa", [0x080c] = "\xa9\xfb", [0x080d] = "\xa9\xfc",
+- [0x080e] = "\xa9\xfd", [0x080f] = "\xa9\xfe", [0x0810] = "\xd7\xfa",
+- [0x0811] = "\xd7\xfb", [0x0812] = "\xd7\xfc", [0x0813] = "\xd7\xfd",
+- [0x0814] = "\xd7\xfe", [0x0815] = "\x65\xac", [0x0819] = "\x65\xad",
+- [0x081a] = "\x65\xae", [0x081b] = "\x65\xaf", [0x081c] = "\x65\xb0",
+- [0x081d] = "\x65\xb1", [0x081f] = "\x65\xb2", [0x0820] = "\x65\xb3",
+- [0x0821] = "\x65\xb4", [0x0822] = "\x65\xb5", [0x0823] = "\x65\xb6",
+- [0x0824] = "\x65\xb7", [0x0825] = "\x65\xb8", [0x0827] = "\x65\xb9",
++ [0x078c] = "\xa6\xc0", [0x078d] = "\x7b\x84", [0x078e] = "\x7b\x86",
++ [0x078f] = "\x7b\x85", [0x0790] = "\x7b\x87", [0x0791] = "\x7b\x88",
++ [0x0792] = "\x7b\x89", [0x0793] = "\x7b\x8a", [0x0794] = "\x7b\x8b",
++ [0x0795] = "\x7b\x8c", [0x0796] = "\x7b\x8d", [0x0797] = "\xa6\xf6",
++ [0x0798] = "\xa6\xf7", [0x0799] = "\xa6\xf8", [0x079a] = "\xa6\xf9",
++ [0x079b] = "\xa6\xfa", [0x079c] = "\xa6\xfb", [0x079d] = "\xa6\xfc",
++ [0x079e] = "\xa6\xfd", [0x079f] = "\xa6\xfe", [0x07a0] = "\xa7\xc2",
++ [0x07a1] = "\xa7\xc3", [0x07a2] = "\xa7\xc4", [0x07a3] = "\xa7\xc5",
++ [0x07a4] = "\xa7\xc6", [0x07a5] = "\xa7\xc7", [0x07a6] = "\xa7\xc8",
++ [0x07a7] = "\xa7\xc9", [0x07a8] = "\xa7\xca", [0x07a9] = "\xa7\xcb",
++ [0x07aa] = "\xa7\xcc", [0x07ab] = "\xa7\xcd", [0x07ac] = "\xa7\xce",
++ [0x07ad] = "\xa7\xcf", [0x07ae] = "\xa7\xd0", [0x07af] = "\xa7\xf2",
++ [0x07b0] = "\xa7\xf3", [0x07b1] = "\xa7\xf4", [0x07b2] = "\xa7\xf5",
++ [0x07b3] = "\xa7\xf6", [0x07b4] = "\xa7\xf7", [0x07b5] = "\xa7\xf8",
++ [0x07b6] = "\xa7\xf9", [0x07b7] = "\xa7\xfa", [0x07b8] = "\xa7\xfb",
++ [0x07b9] = "\xa7\xfc", [0x07ba] = "\xa7\xfd", [0x07bb] = "\xa7\xfe",
++ [0x07bc] = "\xa8\x96", [0x07bd] = "\xa8\x97", [0x07be] = "\xa8\x98",
++ [0x07bf] = "\xa8\x99", [0x07c0] = "\xa8\x9a", [0x07c1] = "\xa8\x9b",
++ [0x07c2] = "\xa8\x9c", [0x07c3] = "\xa8\x9d", [0x07c4] = "\xa8\x9e",
++ [0x07c5] = "\xa8\x9f", [0x07c6] = "\xa8\xa0", [0x07c7] = "\x00\x01",
++ [0x07c8] = "\x65\x9e", [0x07c9] = "\xa8\xc1", [0x07ca] = "\xa8\xc2",
++ [0x07cb] = "\xa8\xc3", [0x07cc] = "\xa8\xc4", [0x07cd] = "\xa8\xea",
++ [0x07ce] = "\xa8\xeb", [0x07cf] = "\xa8\xec", [0x07d0] = "\xa8\xed",
++ [0x07d1] = "\xa8\xee", [0x07d2] = "\xa8\xef", [0x07d3] = "\xa8\xf0",
++ [0x07d4] = "\xa8\xf1", [0x07d5] = "\xa8\xf2", [0x07d6] = "\xa8\xf3",
++ [0x07d7] = "\xa8\xf4", [0x07d8] = "\xa8\xf5", [0x07d9] = "\xa8\xf6",
++ [0x07da] = "\xa8\xf7", [0x07db] = "\xa8\xf8", [0x07dc] = "\xa8\xf9",
++ [0x07dd] = "\xa8\xfa", [0x07de] = "\xa8\xfb", [0x07df] = "\xa8\xfc",
++ [0x07e0] = "\xa8\xfd", [0x07e1] = "\xa8\xfe", [0x07e2] = "\xa9\x58",
++ [0x07e3] = "\xa9\x5b", [0x07e4] = "\xa9\x5d", [0x07e5] = "\xa9\x5e",
++ [0x07e6] = "\xa9\x5f", [0x07e7] = "\x65\x9f", [0x07e8] = "\x65\xa0",
++ [0x07e9] = "\x65\xa1", [0x07ea] = "\x65\xa2", [0x07eb] = "\x65\xa3",
++ [0x07ec] = "\x65\xa4", [0x07ed] = "\x65\xa5", [0x07ee] = "\x65\xa6",
++ [0x07ef] = "\x65\xa7", [0x07f0] = "\x65\xa8", [0x07f1] = "\x65\xa9",
++ [0x07f2] = "\x65\xaa", [0x07f3] = "\x65\xab", [0x07f4] = "\xa9\x97",
++ [0x07f5] = "\xa9\x98", [0x07f6] = "\xa9\x99", [0x07f7] = "\xa9\x9a",
++ [0x07f8] = "\xa9\x9b", [0x07f9] = "\xa9\x9c", [0x07fa] = "\xa9\x9d",
++ [0x07fb] = "\xa9\x9e", [0x07fc] = "\xa9\x9f", [0x07fd] = "\xa9\xa0",
++ [0x07fe] = "\xa9\xa1", [0x07ff] = "\xa9\xa2", [0x0800] = "\xa9\xa3",
++ [0x0801] = "\xa9\xf0", [0x0802] = "\xa9\xf1", [0x0803] = "\xa9\xf2",
++ [0x0804] = "\xa9\xf3", [0x0805] = "\xa9\xf4", [0x0806] = "\xa9\xf5",
++ [0x0807] = "\xa9\xf6", [0x0808] = "\xa9\xf7", [0x0809] = "\xa9\xf8",
++ [0x080a] = "\xa9\xf9", [0x080b] = "\xa9\xfa", [0x080c] = "\xa9\xfb",
++ [0x080d] = "\xa9\xfc", [0x080e] = "\xa9\xfd", [0x080f] = "\xa9\xfe",
++ [0x0810] = "\xd7\xfa", [0x0811] = "\xd7\xfb", [0x0812] = "\xd7\xfc",
++ [0x0813] = "\xd7\xfd", [0x0814] = "\xd7\xfe", [0x0815] = "\x65\xac",
++ [0x0816] = "\xfe\x51", [0x0817] = "\xfe\x52", [0x0818] = "\xfe\x53",
++ [0x0819] = "\x65\xad", [0x081a] = "\x65\xae", [0x081b] = "\x65\xaf",
++ [0x081c] = "\x65\xb0", [0x081d] = "\x65\xb1", [0x081e] = "\x2d\x51",
++ [0x081f] = "\x65\xb2", [0x0820] = "\x65\xb3", [0x0821] = "\x65\xb4",
++ [0x0822] = "\x65\xb5", [0x0823] = "\x65\xb6", [0x0824] = "\x65\xb7",
++ [0x0825] = "\x65\xb8", [0x0826] = "\x2d\x52", [0x0827] = "\x65\xb9",
+ [0x0828] = "\x65\xba", [0x0829] = "\x65\xbb", [0x082a] = "\x65\xbc",
+- [0x082d] = "\x65\xbd", [0x082e] = "\x65\xbe", [0x082f] = "\x65\xbf",
+- [0x0830] = "\x65\xc0", [0x0833] = "\x65\xc1", [0x0834] = "\x65\xc2",
+- [0x0835] = "\x65\xc3", [0x0836] = "\x65\xc4", [0x0837] = "\x65\xc5",
+- [0x0838] = "\x65\xc6", [0x0839] = "\x65\xc7", [0x083a] = "\x65\xc8",
+- [0x083c] = "\x65\xc9", [0x083d] = "\x65\xca", [0x083e] = "\x65\xcb",
+- [0x083f] = "\x65\xcc", [0x0840] = "\x65\xcd", [0x0841] = "\x65\xce",
+- [0x0842] = "\x65\xcf", [0x0844] = "\x65\xd0", [0x0845] = "\x65\xd1",
++ [0x082b] = "\x2d\x53", [0x082c] = "\x2d\x54", [0x082d] = "\x65\xbd",
++ [0x082e] = "\x65\xbe", [0x082f] = "\x65\xbf", [0x0830] = "\x65\xc0",
++ [0x0831] = "\xfe\x6c", [0x0832] = "\x2d\x55", [0x0833] = "\x65\xc1",
++ [0x0834] = "\x65\xc2", [0x0835] = "\x65\xc3", [0x0836] = "\x65\xc4",
++ [0x0837] = "\x65\xc5", [0x0838] = "\x65\xc6", [0x0839] = "\x65\xc7",
++ [0x083a] = "\x65\xc8", [0x083b] = "\xfe\x76", [0x083c] = "\x65\xc9",
++ [0x083d] = "\x65\xca", [0x083e] = "\x65\xcb", [0x083f] = "\x65\xcc",
++ [0x0840] = "\x65\xcd", [0x0841] = "\x65\xce", [0x0842] = "\x65\xcf",
++ [0x0843] = "\x2d\x56", [0x0844] = "\x65\xd0", [0x0845] = "\x65\xd1",
+ [0x0846] = "\x65\xd2", [0x0847] = "\x65\xd3", [0x0848] = "\x65\xd4",
+ [0x0849] = "\x65\xd5", [0x084a] = "\x65\xd6", [0x084b] = "\x65\xd7",
+ [0x084c] = "\x65\xd8", [0x084d] = "\x65\xd9", [0x084e] = "\x65\xda",
+ [0x084f] = "\x65\xdb", [0x0850] = "\x65\xdc", [0x0851] = "\x65\xdd",
+- [0x0852] = "\x65\xde", [0x0853] = "\x65\xdf", [0x0856] = "\x65\xe0",
+- [0x0857] = "\x65\xe1", [0x0858] = "\x65\xe2", [0x0859] = "\x65\xe3",
+- [0x085a] = "\x65\xe4", [0x085b] = "\x65\xe5", [0x085c] = "\x65\xe6",
+- [0x085d] = "\x65\xe7", [0x085e] = "\x65\xe8", [0x085f] = "\x65\xe9",
+- [0x0860] = "\x65\xea", [0x0861] = "\x65\xeb", [0x0862] = "\x65\xec",
+- [0x0863] = "\x65\xed", [0x0865] = "\xfd\x9c", [0x0866] = "\x76\xb5",
++ [0x0852] = "\x65\xde", [0x0853] = "\x65\xdf", [0x0854] = "\x2d\x57",
++ [0x0855] = "\xfe\x91", [0x0856] = "\x65\xe0", [0x0857] = "\x65\xe1",
++ [0x0858] = "\x65\xe2", [0x0859] = "\x65\xe3", [0x085a] = "\x65\xe4",
++ [0x085b] = "\x65\xe5", [0x085c] = "\x65\xe6", [0x085d] = "\x65\xe7",
++ [0x085e] = "\x65\xe8", [0x085f] = "\x65\xe9", [0x0860] = "\x65\xea",
++ [0x0861] = "\x65\xeb", [0x0862] = "\x65\xec", [0x0863] = "\x65\xed",
++ [0x0864] = "\x2d\x58", [0x0865] = "\xfd\x9c", [0x0866] = "\x76\xb5",
+ [0x0867] = "\x76\xb6", [0x0868] = "\x76\xb7", [0x0869] = "\x76\xb8",
+ [0x086a] = "\x76\xb9", [0x086b] = "\x76\xba", [0x086c] = "\x76\xbb",
+ [0x086d] = "\x76\xbc", [0x086e] = "\x76\xbd", [0x086f] = "\x76\xbe",
+@@ -24222,24 +24235,8 @@ static const unsigned char __ucs_to_gb18030_tab2[][2] =
+ || (ch = __twobyte_to_ucs[idx], \
+ ch == 0 && *inptr != '\0')) \
+ { \
+- /* Handle a few special cases. */ \
+- if (idx == 0x5dd1) \
+- ch = 0x20087; \
+- else if (idx == 0x5dd2) \
+- ch = 0x20089; \
+- else if (idx == 0x5dd3) \
+- ch = 0x200cc; \
+- else if (idx == 0x5dec) \
+- ch = 0x215D7; \
+- else if (idx == 0x5df6) \
+- ch = 0x2298F; \
+- else if (idx == 0x5e11) \
+- ch = 0x241FE; \
+- else \
+- { \
+- /* This is an illegal character. */ \
+- STANDARD_FROM_LOOP_ERR_HANDLER (2); \
+- } \
++ /* This is an illegal character. */ \
++ STANDARD_FROM_LOOP_ERR_HANDLER (2); \
+ } \
+ \
+ inptr += 2; \
+@@ -24331,17 +24328,35 @@ static const unsigned char __ucs_to_gb18030_tab2[][2] =
+ len = 4; \
+ } \
+ else if (ch == 0x20087) \
+- cp = (const unsigned char *) "\xfe\x51"; \
++ { \
++ idx = 0x3E2CF; \
++ len = 4; \
++ } \
+ else if (ch == 0x20089) \
+- cp = (const unsigned char *) "\xfe\x52"; \
++ { \
++ idx = 0x3E2D1; \
++ len = 4; \
++ } \
+ else if (ch == 0x200CC) \
+- cp = (const unsigned char *) "\xfe\x53"; \
++ { \
++ idx = 0x3E314; \
++ len = 4; \
++ } \
+ else if (ch == 0x215d7) \
+- cp = (const unsigned char *) "\xfe\x6c"; \
++ { \
++ idx = 0x3F81F; \
++ len = 4; \
++ } \
+ else if (ch == 0x2298F) \
+- cp = (const unsigned char *) "\xfe\x76"; \
++ { \
++ idx = 0x40BD7; \
++ len = 4; \
++ } \
+ else if (ch == 0x241FE) \
+- cp = (const unsigned char *) "\xfe\x91"; \
++ { \
++ idx = 0x42446; \
++ len = 4; \
++ } \
+ else if (ch >= 0x10000 && ch <= 0x10FFFF) \
+ { \
+ idx = ch + 0x1E248; \
+diff --git a/iconvdata/tst-table-from.c b/iconvdata/tst-table-from.c
+index 9ad1f44e..c881c86b 100644
+--- a/iconvdata/tst-table-from.c
++++ b/iconvdata/tst-table-from.c
+@@ -195,10 +195,9 @@ main (int argc, char *argv[])
+ exit (1);
+ }
+
+- /* When testing UTF-8 or GB18030, stop at 0x10000, otherwise the output
++ /* When testing UTF-8, stop at 0x10000, otherwise the output
+ file gets too big. */
+- bmp_only = (strcmp (charset, "UTF-8") == 0
+- || strcmp (charset, "GB18030") == 0);
++ bmp_only = (strcmp (charset, "UTF-8") == 0);
+ search_depth = (strcmp (charset, "UTF-8") == 0 ? 3 : 4);
+
+ {
+diff --git a/iconvdata/tst-table-to.c b/iconvdata/tst-table-to.c
+index 6f0aa29c..8d097527 100644
+--- a/iconvdata/tst-table-to.c
++++ b/iconvdata/tst-table-to.c
+@@ -33,6 +33,7 @@ main (int argc, char *argv[])
+ const char *charset;
+ iconv_t cd;
+ int bmp_only;
++ int no_tags;
+
+ if (argc != 2)
+ {
+@@ -48,16 +49,19 @@ main (int argc, char *argv[])
+ return 1;
+ }
+
+- /* When testing UTF-8 or GB18030, stop at 0x10000, otherwise the output
++ /* When testing UTF-8, stop at 0x10000, otherwise the output
+ file gets too big. */
+- bmp_only = (strcmp (charset, "UTF-8") == 0
++ bmp_only = (strcmp (charset, "UTF-8") == 0);
++ /* When testing any encoding other than UTF-8 or GB18030, stop at 0xE0000,
++ because the conversion drops Unicode tag characters (range
++ U+E0000..U+E007F). */
++ no_tags = !(strcmp (charset, "UTF-8") == 0
+ || strcmp (charset, "GB18030") == 0);
+
+ {
+ unsigned int i;
+ unsigned char buf[10];
+-
+- for (i = 0; i < (bmp_only ? 0x10000 : 0x30000); i++)
++ for (i = 0; i < (bmp_only ? 0x10000 : no_tags ? 0xE0000 : 0x110000); i++)
+ {
+ unsigned char in[6];
+ unsigned int incount =
+diff --git a/iconvdata/tst-table.sh b/iconvdata/tst-table.sh
+index 04c06136..3c6927ee 100755
+--- a/iconvdata/tst-table.sh
++++ b/iconvdata/tst-table.sh
+@@ -38,7 +38,8 @@ set -e
+ < ../localedata/charmaps/${charmap:-$charset} \
+ > ${objpfx}tst-${charset}.charmap.table
+ # When the charset is GB18030, truncate this table because for this encoding,
+-# the tst-table-from and tst-table-to programs scan the Unicode BMP only.
++# the charmap contains ranges (<Unnnn>..<Ummmm> notation), which the
++# tst-table-charmap.sh script does not grok.
+ if test ${charset} = GB18030; then
+ grep '0x....$' < ${objpfx}tst-${charset}.charmap.table \
+ > ${objpfx}tst-${charset}.truncated.table
+@@ -74,25 +75,42 @@ diff ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.inverse.table
+
+ # Check 1: charmap and iconv forward should be identical, except for
+ # precomposed characters.
+-if test -f ${precomposed}; then
+- cat ${objpfx}tst-${charset}.table ${precomposed} | sort | uniq -u \
+- > ${objpfx}tst-${charset}.tmp.table
+- cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.tmp.table ||
++{ if test -f ${precomposed}; then
++ cat ${objpfx}tst-${charset}.table ${precomposed} | sort | uniq -u
++ else
++ cat ${objpfx}tst-${charset}.table
++ fi
++} | { if test ${charset} = GB18030; then grep '0x....$'; else cat; fi; } \
++ > ${objpfx}tst-${charset}.tmp1.table
++cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.tmp1.table ||
+ exit 1
+-else
+- cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.table ||
+- exit 1
+-fi
+
+ # Check 2: the difference between the charmap and iconv backward.
+-if test -f ${irreversible}; then
+- cat ${objpfx}tst-${charset}.charmap.table ${irreversible} | sort | uniq -u \
+- > ${objpfx}tst-${charset}.tmp.table
+- cmp -s ${objpfx}tst-${charset}.tmp.table ${objpfx}tst-${charset}.inverse.table ||
+- exit 1
+-else
+- cmp -s ${objpfx}tst-${charset}.charmap.table ${objpfx}tst-${charset}.inverse.table ||
++{ if test -f ${irreversible}; then
++ cat ${objpfx}tst-${charset}.charmap.table ${irreversible} | sort | uniq -u
++ else
++ cat ${objpfx}tst-${charset}.charmap.table
++ fi
++} | { if test ${charset} = GB18030; then grep '0x....$'; else cat; fi; } \
++ > ${objpfx}tst-${charset}.tmp2c.table
++cat ${objpfx}tst-${charset}.inverse.table \
++ | { if test ${charset} = GB18030; then grep '0x....$'; else cat; fi; } \
++ > ${objpfx}tst-${charset}.tmp2i.table
++cmp -s ${objpfx}tst-${charset}.tmp2c.table ${objpfx}tst-${charset}.tmp2i.table ||
+ exit 1
++
++# Check 3: the difference between iconv forward and iconv backward. This is
++# necessary only for GB18030, because ${objpfx}tst-${charset}.charmap.table
++# is truncated for this encoding (see above).
++if test ${charset} = GB18030; then
++ { if test -f ${irreversible}; then
++ cat ${objpfx}tst-${charset}.table ${irreversible} | sort | uniq -u
++ else
++ cat ${objpfx}tst-${charset}.table
++ fi
++ } > ${objpfx}tst-${charset}.tmp3.table
++ cmp -s ${objpfx}tst-${charset}.tmp3.table ${objpfx}tst-${charset}.inverse.table ||
++ exit 1
+ fi
+
+ exit 0
+diff --git a/localedata/charmaps/GB18030 b/localedata/charmaps/GB18030
+index ad6728c5..fc3b1d2d 100644
+--- a/localedata/charmaps/GB18030
++++ b/localedata/charmaps/GB18030
+@@ -57234,32 +57234,16 @@ CHARMAP
+ <UE78A> /xa6/xbe <Private Use>
+ <UE78B> /xa6/xbf <Private Use>
+ <UE78C> /xa6/xc0 <Private Use>
+-% The newest GB 18030-2005 standard still uses some private use area
+-% code points. Any implementation which has Unicode 4.1 or newer
+-% support should not use these PUA code points, and instead should
+-% map these entries to their equivalent non-PUA code points. There
+-% are 24 idiograms in GB 18030-2005 which have non-PUA equivalents.
+-% In glibc we only support roundtrip code points, and so must choose
+-% between supporting the old PUA code points, or using the newer
+-% non-PUA code points. We choose to use the non-PUA code points to
+-% be compatible with ICU's similar choice. In choosing the non-PUA
+-% code points we can no longer convert the old PUA code points back
+-% to GB-18030-2005 (technically only fixable if we added support
+-% for non-roundtrip code points e.g. ICU's "fallback mapping").
+-% The recommendation to use the non-PUA code points, where available,
+-% is based on "CJKV Information Processing" 2nd Ed. by Dr. Ken Lunde.
+-%
+-% These 10 PUA mappings use equivalents from <UFE10> to <UFE19>.
+-% <UE78D> /xa6/xd9 <Private Use>
+-% <UE78E> /xa6/xda <Private Use>
+-% <UE78F> /xa6/xdb <Private Use>
+-% <UE790> /xa6/xdc <Private Use>
+-% <UE791> /xa6/xdd <Private Use>
+-% <UE792> /xa6/xde <Private Use>
+-% <UE793> /xa6/xdf <Private Use>
+-% <UE794> /xa6/xec <Private Use>
+-% <UE795> /xa6/xed <Private Use>
+-% <UE796> /xa6/xf3 <Private Use>
++<UE78D> /x84/x31/x82/x36 <Private Use>
++<UE78E> /x84/x31/x82/x38 <Private Use>
++<UE78F> /x84/x31/x82/x37 <Private Use>
++<UE790> /x84/x31/x82/x39 <Private Use>
++<UE791> /x84/x31/x83/x30 <Private Use>
++<UE792> /x84/x31/x83/x31 <Private Use>
++<UE793> /x84/x31/x83/x32 <Private Use>
++<UE794> /x84/x31/x83/x33 <Private Use>
++<UE795> /x84/x31/x83/x34 <Private Use>
++<UE796> /x84/x31/x83/x35 <Private Use>
+ <UE797> /xa6/xf6 <Private Use>
+ <UE798> /xa6/xf7 <Private Use>
+ <UE799> /xa6/xf8 <Private Use>
+@@ -57387,17 +57371,15 @@ CHARMAP
+ <UE813> /xd7/xfd <Private Use>
+ <UE814> /xd7/xfe <Private Use>
+ <UE815> /x83/x36/xc9/x34 <Private Use>
+-% These 3 PUA mappings use equivalents <U20087>, <U20089> and <U200CC>.
+-% <UE816> /xfe/x51 <Private Use>
+-% <UE817> /xfe/x52 <Private Use>
+-% <UE818> /xfe/x53 <Private Use>
++<UE816> /xfe/x51 <Private Use>
++<UE817> /xfe/x52 <Private Use>
++<UE818> /xfe/x53 <Private Use>
+ <UE819> /x83/x36/xc9/x35 <Private Use>
+ <UE81A> /x83/x36/xc9/x36 <Private Use>
+ <UE81B> /x83/x36/xc9/x37 <Private Use>
+ <UE81C> /x83/x36/xc9/x38 <Private Use>
+ <UE81D> /x83/x36/xc9/x39 <Private Use>
+-% This 1 PUA mapping uses the equivalent <U9FB4>.
+-% <UE81E> /xfe/x59 <Private Use>
++<UE81E> /x82/x35/x90/x37 <Private Use>
+ <UE81F> /x83/x36/xca/x30 <Private Use>
+ <UE820> /x83/x36/xca/x31 <Private Use>
+ <UE821> /x83/x36/xca/x32 <Private Use>
+@@ -57405,22 +57387,19 @@ CHARMAP
+ <UE823> /x83/x36/xca/x34 <Private Use>
+ <UE824> /x83/x36/xca/x35 <Private Use>
+ <UE825> /x83/x36/xca/x36 <Private Use>
+-% This 1 PUA mapping uses the equivalent <U9FB5>.
+-% <UE826> /xfe/x61 <Private Use>
++<UE826> /x82/x35/x90/x38 <Private Use>
+ <UE827> /x83/x36/xca/x37 <Private Use>
+ <UE828> /x83/x36/xca/x38 <Private Use>
+ <UE829> /x83/x36/xca/x39 <Private Use>
+ <UE82A> /x83/x36/xcb/x30 <Private Use>
+-% These 2 PUA mappings use the equivalents <U9FB6> and <U9FB7>.
+-% <UE82B> /xfe/x66 <Private Use>
+-% <UE82C> /xfe/x67 <Private Use>
++<UE82B> /x82/x35/x90/x39 <Private Use>
++<UE82C> /x82/x35/x91/x30 <Private Use>
+ <UE82D> /x83/x36/xcb/x31 <Private Use>
+ <UE82E> /x83/x36/xcb/x32 <Private Use>
+ <UE82F> /x83/x36/xcb/x33 <Private Use>
+ <UE830> /x83/x36/xcb/x34 <Private Use>
+-% These 2 PUA mappings use the equivalents <U215D7> and <U9FB8>.
+-% <UE831> /xfe/x6c <Private Use>
+-% <UE832> /xfe/x6d <Private Use>
++<UE831> /xfe/x6c <Private Use>
++<UE832> /x82/x35/x91/x31 <Private Use>
+ <UE833> /x83/x36/xcb/x35 <Private Use>
+ <UE834> /x83/x36/xcb/x36 <Private Use>
+ <UE835> /x83/x36/xcb/x37 <Private Use>
+@@ -57429,8 +57408,7 @@ CHARMAP
+ <UE838> /x83/x36/xcc/x30 <Private Use>
+ <UE839> /x83/x36/xcc/x31 <Private Use>
+ <UE83A> /x83/x36/xcc/x32 <Private Use>
+-% This 1 PUA mapping uses the equivalent <U2298F>.
+-% <UE83B> /xfe/x76 <Private Use>
++<UE83B> /xfe/x76 <Private Use>
+ <UE83C> /x83/x36/xcc/x33 <Private Use>
+ <UE83D> /x83/x36/xcc/x34 <Private Use>
+ <UE83E> /x83/x36/xcc/x35 <Private Use>
+@@ -57438,8 +57416,7 @@ CHARMAP
+ <UE840> /x83/x36/xcc/x37 <Private Use>
+ <UE841> /x83/x36/xcc/x38 <Private Use>
+ <UE842> /x83/x36/xcc/x39 <Private Use>
+-% This 1 PUA mapping uses the equivalent <U9FB9>.
+-% <UE843> /xfe/x7e <Private Use>
++<UE843> /x82/x35/x91/x32 <Private Use>
+ <UE844> /x83/x36/xcd/x30 <Private Use>
+ <UE845> /x83/x36/xcd/x31 <Private Use>
+ <UE846> /x83/x36/xcd/x32 <Private Use>
+@@ -57456,9 +57433,8 @@ CHARMAP
+ <UE851> /x83/x36/xce/x33 <Private Use>
+ <UE852> /x83/x36/xce/x34 <Private Use>
+ <UE853> /x83/x36/xce/x35 <Private Use>
+-% These 2 PUA mappings use the equivalents <U9FBA> and <U241FE>.
+-% <UE854> /xfe/x90 <Private Use>
+-% <UE855> /xfe/x91 <Private Use>
++<UE854> /x82/x35/x91/x33 <Private Use>
++<UE855> /xfe/x91 <Private Use>
+ <UE856> /x83/x36/xce/x36 <Private Use>
+ <UE857> /x83/x36/xce/x37 <Private Use>
+ <UE858> /x83/x36/xce/x38 <Private Use>
+@@ -57473,8 +57449,7 @@ CHARMAP
+ <UE861> /x83/x36/xcf/x37 <Private Use>
+ <UE862> /x83/x36/xcf/x38 <Private Use>
+ <UE863> /x83/x36/xcf/x39 <Private Use>
+-% This 1 PUA mapping uses the equivalent <U9FBB>.
+-% <UE864> /xfe/xa0 <Private Use>
++<UE864> /x82/x35/x91/x34 <Private Use>
+ <UE865> /x83/x36/xd0/x30 <Private Use>
+ <UE866> /x83/x36/xd0/x31 <Private Use>
+ <UE867> /x83/x36/xd0/x32 <Private Use>
+@@ -70447,19 +70422,14 @@ CHARMAP
+ <U00020068>..<U00020071> /x95/x32/x8d/x30 <CJK>
+ <U00020072>..<U0002007B> /x95/x32/x8e/x30 <CJK>
+ <U0002007C>..<U00020085> /x95/x32/x8f/x30 <CJK>
+-<U00020086> /x95/x32/x90/x30 <CJK>
+-<U00020087> /xfe/x51 <CJK>
+-<U00020088> /x95/x32/x90/x32 <CJK>
+-<U00020089> /xfe/x52 <CJK>
+-<U0002008A>..<U0002008F> /x95/x32/x90/x34 <CJK>
++<U00020086>..<U0002008F> /x95/x32/x90/x30 <CJK>
+ <U00020090>..<U00020099> /x95/x32/x91/x30 <CJK>
+ <U0002009A>..<U000200A3> /x95/x32/x92/x30 <CJK>
+ <U000200A4>..<U000200AD> /x95/x32/x93/x30 <CJK>
+ <U000200AE>..<U000200B7> /x95/x32/x94/x30 <CJK>
+ <U000200B8>..<U000200C1> /x95/x32/x95/x30 <CJK>
+ <U000200C2>..<U000200CB> /x95/x32/x96/x30 <CJK>
+-<U000200CC> /xfe/x53 <CJK>
+-<U000200CD>..<U000200D5> /x95/x32/x97/x31 <CJK>
++<U000200CC>..<U000200D5> /x95/x32/x97/x30 <CJK>
+ <U000200D6>..<U000200DF> /x95/x32/x98/x30 <CJK>
+ <U000200E0>..<U000200E9> /x95/x32/x99/x30 <CJK>
+ <U000200EA>..<U000200F3> /x95/x32/x9a/x30 <CJK>
+@@ -70998,8 +70968,7 @@ CHARMAP
+ <U000215BC>..<U000215C5> /x95/x36/xb7/x30 <CJK>
+ <U000215C6>..<U000215CF> /x95/x36/xb8/x30 <CJK>
+ <U000215D0>..<U000215D6> /x95/x36/xb9/x30 <CJK>
+-<U000215D7> /xfe/x6c <CJK>
+-<U000215D8>..<U000215D9> /x95/x36/xb9/x38 <CJK>
++<U000215D7>..<U000215D9> /x95/x36/xb9/x37 <CJK>
+ <U000215DA>..<U000215E3> /x95/x36/xba/x30 <CJK>
+ <U000215E4>..<U000215ED> /x95/x36/xbb/x30 <CJK>
+ <U000215EE>..<U000215F7> /x95/x36/xbc/x30 <CJK>
+@@ -71505,8 +71474,7 @@ CHARMAP
+ <U00022976>..<U0002297F> /x96/x30/xb8/x30 <CJK>
+ <U00022980>..<U00022989> /x96/x30/xb9/x30 <CJK>
+ <U0002298A>..<U0002298E> /x96/x30/xba/x30 <CJK>
+-<U0002298F> /xfe/x76 <CJK>
+-<U00022990>..<U00022993> /x96/x30/xba/x36 <CJK>
++<U0002298F>..<U00022993> /x96/x30/xba/x35 <CJK>
+ <U00022994>..<U0002299D> /x96/x30/xbb/x30 <CJK>
+ <U0002299E>..<U000229A7> /x96/x30/xbc/x30 <CJK>
+ <U000229A8>..<U000229B1> /x96/x30/xbd/x30 <CJK>
+@@ -72132,8 +72100,7 @@ CHARMAP
+ <U000241E0>..<U000241E9> /x96/x35/xb3/x30 <CJK>
+ <U000241EA>..<U000241F3> /x96/x35/xb4/x30 <CJK>
+ <U000241F4>..<U000241FD> /x96/x35/xb5/x30 <CJK>
+-<U000241FE> /xfe/x91 <CJK>
+-<U000241FF>..<U00024207> /x96/x35/xb6/x31 <CJK>
++<U000241FE>..<U00024207> /x96/x35/xb6/x30 <CJK>
+ <U00024208>..<U00024211> /x96/x35/xb7/x30 <CJK>
+ <U00024212>..<U0002421B> /x96/x35/xb8/x30 <CJK>
+ <U0002421C>..<U00024225> /x96/x35/xb9/x30 <CJK>
+--
+2.33.0
+
diff --git a/add-Wl-z-noseparate-code-for-so.patch b/add-Wl-z-noseparate-code-for-so.patch
new file mode 100644
index 0000000..1cdf45f
--- /dev/null
+++ b/add-Wl-z-noseparate-code-for-so.patch
@@ -0,0 +1,29 @@
+From 2eb52cc0dd1ce02871d4f863649a8656831805c7 Mon Sep 17 00:00:00 2001
+From: hongrongxuan <hongrongxuan@huawei.com>
+Date: Tue, 25 Oct 2022 21:24:21 +0800
+Subject: [PATCH] add Wl,-z,noseparate-code for so
+binutils 2.31 add a separate-code(default)/noseparate-code link option to separate
+.rodata from .text segment. Cause this is a dubious feature that intends to
+reduce the number of ROP gadgets, and this will reduce batch program's
+performance, like unixbench shell program, it will reduce 8%~10%. So
+add 'Wl,-z,noseparate-code' to disable this feature.
+
+Refrences:
+https://sourceware.org/pipermail/binutils/2018-February/101950.html
+https://reviews.llvmm.org/D64903
+https://packagehub.suse.com/packages/binutils/2_37-1050100_7_34_1/
+---
+ sysdeps/x86_64/Makeconfig | 1 +
+ 1 file changed, 1 insertion(+)
+ create mode 100644 sysdeps/x86_64/Makeconfig
+
+diff --git a/sysdeps/x86_64/Makeconfig b/sysdeps/x86_64/Makeconfig
+new file mode 100644
+index 00000000..5f544fd7
+--- /dev/null
++++ b/sysdeps/x86_64/Makeconfig
+@@ -0,0 +1 @@
++relro-LDFLAGS = -Wl,-z,relro -Wl,-z,noseparate-code
+--
+2.33.0
+
diff --git a/add-pthread_cond_clockwait-GLIBC_2_28.patch b/add-pthread_cond_clockwait-GLIBC_2_28.patch
new file mode 100644
index 0000000..7d04082
--- /dev/null
+++ b/add-pthread_cond_clockwait-GLIBC_2_28.patch
@@ -0,0 +1,66 @@
+From e6569a3c53c25916f5c04ccc3d6a467c57d4eab8 Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Thu, 19 Jan 2023 21:40:08 +0800
+Subject: [PATCH] add pthread_cond_clockwait@GLIBC_2_28
+
+Since the pthread_cond_clockwait@GLIBC_2_28 is introduced in earlier
+versions, this symbol is required to keep the previous items compatible.
+
+---
+ nptl/Versions | 1 +
+ nptl/pthread_cond_wait.c | 4 ++++
+ sysdeps/unix/sysv/linux/aarch64/libc.abilist | 1 +
+ sysdeps/unix/sysv/linux/x86_64/64/libc.abilist | 1 +
+ 5 files changed, 9 insertions(+)
+
+diff --git a/nptl/Versions b/nptl/Versions
+index 3221de89..dc341f9d 100644
+--- a/nptl/Versions
++++ b/nptl/Versions
+@@ -231,6 +231,7 @@ libc {
+ tss_delete;
+ tss_get;
+ tss_set;
++ pthread_cond_clockwait;
+ }
+ GLIBC_2.30 {
+ pthread_cond_clockwait;
+diff --git a/nptl/pthread_cond_wait.c b/nptl/pthread_cond_wait.c
+index dc8c511f..04eeff34 100644
+--- a/nptl/pthread_cond_wait.c
++++ b/nptl/pthread_cond_wait.c
+@@ -709,3 +709,7 @@ versioned_symbol (libc, ___pthread_cond_clockwait,
+ compat_symbol (libpthread, ___pthread_cond_clockwait,
+ pthread_cond_clockwait, GLIBC_2_30);
+ #endif
++#if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_28, GLIBC_2_34)
++compat_symbol (libpthread, ___pthread_cond_clockwait,
++ pthread_cond_clockwait, GLIBC_2_28);
++#endif
+diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+index a4262419..a0795a80 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
++++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+@@ -383,6 +383,7 @@ GLIBC_2.28 mtx_lock F
+ GLIBC_2.28 mtx_timedlock F
+ GLIBC_2.28 mtx_trylock F
+ GLIBC_2.28 mtx_unlock F
++GLIBC_2.28 pthread_cond_clockwait F
+ GLIBC_2.28 renameat2 F
+ GLIBC_2.28 statx F
+ GLIBC_2.28 thrd_create F
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+index 095e914b..0eaab342 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
++++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+@@ -2413,6 +2413,7 @@ GLIBC_2.28 mtx_lock F
+ GLIBC_2.28 mtx_timedlock F
+ GLIBC_2.28 mtx_trylock F
+ GLIBC_2.28 mtx_unlock F
++GLIBC_2.28 pthread_cond_clockwait F
+ GLIBC_2.28 renameat2 F
+ GLIBC_2.28 statx F
+ GLIBC_2.28 thrd_create F
+--
+2.33.0
+
diff --git a/arm-Simplify-elf_machine_-load_address-dynamic.patch b/arm-Simplify-elf_machine_-load_address-dynamic.patch
new file mode 100644
index 0000000..42987ce
--- /dev/null
+++ b/arm-Simplify-elf_machine_-load_address-dynamic.patch
@@ -0,0 +1,82 @@
+From bca0f5cbc9257c13322b99e55235c4f21ba0bd82 Mon Sep 17 00:00:00 2001
+From: Fangrui Song <maskray@google.com>
+Date: Wed, 18 Aug 2021 11:13:03 -0700
+Subject: [PATCH] arm: Simplify elf_machine_{load_address,dynamic}
+
+and drop reliance on _GLOBAL_OFFSET_TABLE_[0] being the link-time
+address of _DYNAMIC. &__ehdr_start is a better way to get the load address.
+
+This is similar to commits b37b75d269883a2c553bb7019a813094eb4e2dd1
+(x86-64) and 43d06ed218fc8be58987bdfd00e21e5720f0b862 (aarch64).
+
+Reviewed-by: Joseph Myers <joseph@codesourcery.com>
+---
+ sysdeps/arm/dl-machine.h | 47 ++++++++++-------------------------------------
+ 1 file changed, 10 insertions(+), 37 deletions(-)
+
+diff --git a/sysdeps/arm/dl-machine.h b/sysdeps/arm/dl-machine.h
+index ff5e09e..eb13cb8 100644
+--- a/sysdeps/arm/dl-machine.h
++++ b/sysdeps/arm/dl-machine.h
+@@ -37,48 +37,21 @@ elf_machine_matches_host (const Elf32_Ehdr *ehdr)
+ return ehdr->e_machine == EM_ARM;
+ }
+
+-
+-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+- first element of the GOT. */
+-static inline Elf32_Addr __attribute__ ((unused))
+-elf_machine_dynamic (void)
+-{
+- /* Declaring this hidden ensures that a PC-relative reference is used. */
+- extern const Elf32_Addr _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
+- return _GLOBAL_OFFSET_TABLE_[0];
+-}
+-
+-
+ /* Return the run-time load address of the shared object. */
+-static inline Elf32_Addr __attribute__ ((unused))
++static inline ElfW(Addr) __attribute__ ((unused))
+ elf_machine_load_address (void)
+ {
+- Elf32_Addr pcrel_addr;
+-#ifdef SHARED
+- extern Elf32_Addr __dl_start (void *) asm ("_dl_start");
+- Elf32_Addr got_addr = (Elf32_Addr) &__dl_start;
+- asm ("adr %0, _dl_start" : "=r" (pcrel_addr));
+-#else
+- extern Elf32_Addr __dl_relocate_static_pie (void *)
+- asm ("_dl_relocate_static_pie") attribute_hidden;
+- Elf32_Addr got_addr = (Elf32_Addr) &__dl_relocate_static_pie;
+- asm ("adr %0, _dl_relocate_static_pie" : "=r" (pcrel_addr));
+-#endif
+-#ifdef __thumb__
+- /* Clear the low bit of the function address.
+-
+- NOTE: got_addr is from GOT table whose lsb is always set by linker if it's
+- Thumb function address. PCREL_ADDR comes from PC-relative calculation
+- which will finish during assembling. GAS assembler before the fix for
+- PR gas/21458 was not setting the lsb but does after that. Always do the
+- strip for both, so the code works with various combinations of glibc and
+- Binutils. */
+- got_addr &= ~(Elf32_Addr) 1;
+- pcrel_addr &= ~(Elf32_Addr) 1;
+-#endif
+- return pcrel_addr - got_addr;
++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
++ return (ElfW(Addr)) &__ehdr_start;
+ }
+
++/* Return the link-time address of _DYNAMIC. */
++static inline ElfW(Addr) __attribute__ ((unused))
++elf_machine_dynamic (void)
++{
++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
++}
+
+ /* Set up the loaded object described by L so its unrelocated PLT
+ entries will jump to the on-demand fixup code in dl-runtime.c. */
+--
+1.8.3.1
+
diff --git a/backport-Add-TEST_COMPARE_STRING_WIDE-to-support-check.h.patch b/backport-Add-TEST_COMPARE_STRING_WIDE-to-support-check.h.patch
new file mode 100644
index 0000000..e97367b
--- /dev/null
+++ b/backport-Add-TEST_COMPARE_STRING_WIDE-to-support-check.h.patch
@@ -0,0 +1,757 @@
+From de82cb0da4b8fa5b3d56c457438d2568c67ab1b1 Mon Sep 17 00:00:00 2001
+From: Joseph Myers <joseph@codesourcery.com>
+Date: Tue, 12 Oct 2021 13:48:39 +0000
+Subject: [PATCH] Add TEST_COMPARE_STRING_WIDE to support/check.h
+
+I'd like to be able to test narrow and wide string interfaces, with
+the narrow string tests using TEST_COMPARE_STRING and the wide string
+tests using something analogous (possibly generated using macros from
+a common test template for both the narrow and wide string tests where
+appropriate).
+
+Add such a TEST_COMPARE_STRING_WIDE, along with functions
+support_quote_blob_wide and support_test_compare_string_wide that it
+builds on. Those functions are built using macros from common
+templates shared by the narrow and wide string implementations, though
+I didn't do that for the tests of test functions. In
+support_quote_blob_wide, I chose to use the \x{} delimited escape
+sequence syntax proposed for C2X in N2785, rather than e.g. trying to
+generate the end of a string and the start of a new string when
+ambiguity would result from undelimited \x (when the next character
+after such an escape sequence is valid hex) or forcing an escape
+sequence to be used for the next character in the case of such
+ambiguity.
+
+Tested for x86_64.
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=de82cb0da4b8fa5b3d56c457438d2568c67ab1b1
+---
+ support/Makefile | 4 +
+ support/check.h | 15 +++
+ support/support.h | 6 ++
+ support/support_quote_blob.c | 71 ++------------
+ support/support_quote_blob_main.c | 88 +++++++++++++++++
+ support/support_quote_blob_wide.c | 24 +++++
+ support/support_test_compare_string.c | 83 ++--------------
+ support/support_test_compare_string_main.c | 94 ++++++++++++++++++
+ support/support_test_compare_string_wide.c | 28 ++++++
+ support/tst-support_quote_blob_wide.c | 66 +++++++++++++
+ support/tst-test_compare_string_wide.c | 107 +++++++++++++++++++++
+ 11 files changed, 448 insertions(+), 138 deletions(-)
+ create mode 100644 support/support_quote_blob_main.c
+ create mode 100644 support/support_quote_blob_wide.c
+ create mode 100644 support/support_test_compare_string_main.c
+ create mode 100644 support/support_test_compare_string_wide.c
+ create mode 100644 support/tst-support_quote_blob_wide.c
+ create mode 100644 support/tst-test_compare_string_wide.c
+
+diff --git a/support/Makefile b/support/Makefile
+index fd27c8451e..7f03950914 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -71,6 +71,7 @@ libsupport-routines = \
+ support_openpty \
+ support_paths \
+ support_quote_blob \
++ support_quote_blob_wide \
+ support_quote_string \
+ support_record_failure \
+ support_run_diff \
+@@ -84,6 +85,7 @@ libsupport-routines = \
+ support_test_compare_blob \
+ support_test_compare_failure \
+ support_test_compare_string \
++ support_test_compare_string_wide \
+ support_test_main \
+ support_test_verify_impl \
+ support_wait_for_thread_exit \
+@@ -270,11 +272,13 @@ tests = \
+ tst-support-open-dev-null-range \
+ tst-support-process_state \
+ tst-support_quote_blob \
++ tst-support_quote_blob_wide \
+ tst-support_quote_string \
+ tst-support_record_failure \
+ tst-test_compare \
+ tst-test_compare_blob \
+ tst-test_compare_string \
++ tst-test_compare_string_wide \
+ tst-timespec \
+ tst-xreadlink \
+ tst-xsigstack \
+diff --git a/support/check.h b/support/check.h
+index 83662b2d10..9b1844352f 100644
+--- a/support/check.h
++++ b/support/check.h
+@@ -20,6 +20,7 @@
+ #define SUPPORT_CHECK_H
+
+ #include <sys/cdefs.h>
++#include <stddef.h>
+
+ __BEGIN_DECLS
+
+@@ -171,11 +172,25 @@ void support_test_compare_blob (const void *left,
+ (support_test_compare_string (left, right, __FILE__, __LINE__, \
+ #left, #right))
+
++/* Compare the wide strings LEFT and RIGHT and report a test failure
++ if they are different. Also report failure if one of the arguments
++ is a null pointer and the other is not. The strings should be
++ reasonably short because on mismatch, both are printed. */
++#define TEST_COMPARE_STRING_WIDE(left, right) \
++ (support_test_compare_string_wide (left, right, __FILE__, __LINE__, \
++ #left, #right))
++
+ void support_test_compare_string (const char *left, const char *right,
+ const char *file, int line,
+ const char *left_expr,
+ const char *right_expr);
+
++void support_test_compare_string_wide (const wchar_t *left,
++ const wchar_t *right,
++ const char *file, int line,
++ const char *left_expr,
++ const char *right_expr);
++
+ /* Internal function called by the test driver. */
+ int support_report_failure (int status)
+ __attribute__ ((weak, warn_unused_result));
+diff --git a/support/support.h b/support/support.h
+index 837a806531..0ee454da6d 100644
+--- a/support/support.h
++++ b/support/support.h
+@@ -73,6 +73,12 @@ void support_write_file_string (const char *path, const char *contents);
+ the result). */
+ char *support_quote_blob (const void *blob, size_t length);
+
++/* Quote the contents of the wide character array starting at BLOB, of
++ LENGTH wide characters, in such a way that the result string can be
++ included in a C wide string literal (in single/double quotes,
++ without putting the quotes into the result). */
++char *support_quote_blob_wide (const void *blob, size_t length);
++
+ /* Quote the contents of the string, in such a way that the result
+ string can be included in a C literal (in single/double quotes,
+ without putting the quotes into the result). */
+diff --git a/support/support_quote_blob.c b/support/support_quote_blob.c
+index b5e70125f1..611980c9a2 100644
+--- a/support/support_quote_blob.c
++++ b/support/support_quote_blob.c
+@@ -1,4 +1,4 @@
+-/* Quote a blob so that it can be used in C literals.
++/* Quote a narrow string blob so that it can be used in C literals.
+ Copyright (C) 2018-2021 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+@@ -16,68 +16,9 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+-#include <support/support.h>
+-#include <support/xmemstream.h>
++#define CHAR unsigned char
++#define L_(C) C
++#define SUPPORT_QUOTE_BLOB support_quote_blob
++#define WIDE 0
+
+-char *
+-support_quote_blob (const void *blob, size_t length)
+-{
+- struct xmemstream out;
+- xopen_memstream (&out);
+-
+- const unsigned char *p = blob;
+- for (size_t i = 0; i < length; ++i)
+- {
+- unsigned char ch = p[i];
+-
+- /* Use C backslash escapes for those control characters for
+- which they are defined. */
+- switch (ch)
+- {
+- case '\a':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked ('a', out.out);
+- break;
+- case '\b':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked ('b', out.out);
+- break;
+- case '\f':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked ('f', out.out);
+- break;
+- case '\n':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked ('n', out.out);
+- break;
+- case '\r':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked ('r', out.out);
+- break;
+- case '\t':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked ('t', out.out);
+- break;
+- case '\v':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked ('v', out.out);
+- break;
+- case '\\':
+- case '\'':
+- case '\"':
+- putc_unlocked ('\\', out.out);
+- putc_unlocked (ch, out.out);
+- break;
+- default:
+- if (ch < ' ' || ch > '~')
+- /* Use octal sequences because they are fixed width,
+- unlike hexadecimal sequences. */
+- fprintf (out.out, "\\%03o", ch);
+- else
+- putc_unlocked (ch, out.out);
+- }
+- }
+-
+- xfclose_memstream (&out);
+- return out.buffer;
+-}
++#include "support_quote_blob_main.c"
+diff --git a/support/support_quote_blob_main.c b/support/support_quote_blob_main.c
+new file mode 100644
+index 0000000000..19ccfad593
+--- /dev/null
++++ b/support/support_quote_blob_main.c
+@@ -0,0 +1,88 @@
++/* Quote a blob so that it can be used in C literals.
++ Copyright (C) 2018-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <support/support.h>
++#include <support/xmemstream.h>
++
++char *
++SUPPORT_QUOTE_BLOB (const void *blob, size_t length)
++{
++ struct xmemstream out;
++ xopen_memstream (&out);
++
++ const CHAR *p = blob;
++ for (size_t i = 0; i < length; ++i)
++ {
++ CHAR ch = p[i];
++
++ /* Use C backslash escapes for those control characters for
++ which they are defined. */
++ switch (ch)
++ {
++ case L_('\a'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked ('a', out.out);
++ break;
++ case L_('\b'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked ('b', out.out);
++ break;
++ case L_('\f'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked ('f', out.out);
++ break;
++ case L_('\n'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked ('n', out.out);
++ break;
++ case L_('\r'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked ('r', out.out);
++ break;
++ case L_('\t'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked ('t', out.out);
++ break;
++ case L_('\v'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked ('v', out.out);
++ break;
++ case L_('\\'):
++ case L_('\''):
++ case L_('\"'):
++ putc_unlocked ('\\', out.out);
++ putc_unlocked (ch, out.out);
++ break;
++ default:
++ if (ch < L_(' ') || ch > L_('~'))
++ /* For narrow characters, use octal sequences because they
++ are fixed width, unlike hexadecimal sequences. For
++ wide characters, use N2785 delimited escape
++ sequences. */
++ if (WIDE)
++ fprintf (out.out, "\\x{%x}", (unsigned int) ch);
++ else
++ fprintf (out.out, "\\%03o", (unsigned int) ch);
++ else
++ putc_unlocked (ch, out.out);
++ }
++ }
++
++ xfclose_memstream (&out);
++ return out.buffer;
++}
+diff --git a/support/support_quote_blob_wide.c b/support/support_quote_blob_wide.c
+new file mode 100644
+index 0000000000..c451ed889c
+--- /dev/null
++++ b/support/support_quote_blob_wide.c
+@@ -0,0 +1,24 @@
++/* Quote a wide string blob so that it can be used in C literals.
++ Copyright (C) 2018-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define CHAR wchar_t
++#define L_(C) L ## C
++#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
++#define WIDE 1
++
++#include "support_quote_blob_main.c"
+diff --git a/support/support_test_compare_string.c b/support/support_test_compare_string.c
+index cbeaf7b1ee..12bafe43d4 100644
+--- a/support/support_test_compare_string.c
++++ b/support/support_test_compare_string.c
+@@ -16,76 +16,13 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <support/check.h>
+-#include <support/support.h>
+-#include <support/xmemstream.h>
+-
+-static void
+-report_length (const char *what, const char *str, size_t length)
+-{
+- if (str == NULL)
+- printf (" %s string: NULL\n", what);
+- else
+- printf (" %s string: %zu bytes\n", what, length);
+-}
+-
+-static void
+-report_string (const char *what, const unsigned char *blob,
+- size_t length, const char *expr)
+-{
+- if (length > 0)
+- {
+- printf (" %s (evaluated from %s):\n", what, expr);
+- char *quoted = support_quote_blob (blob, length);
+- printf (" \"%s\"\n", quoted);
+- free (quoted);
+-
+- fputs (" ", stdout);
+- for (size_t i = 0; i < length; ++i)
+- printf (" %02X", blob[i]);
+- putc ('\n', stdout);
+- }
+-}
+-
+-static size_t
+-string_length_or_zero (const char *str)
+-{
+- if (str == NULL)
+- return 0;
+- else
+- return strlen (str);
+-}
+-
+-void
+-support_test_compare_string (const char *left, const char *right,
+- const char *file, int line,
+- const char *left_expr, const char *right_expr)
+-{
+- /* Two null pointers are accepted. */
+- if (left == NULL && right == NULL)
+- return;
+-
+- size_t left_length = string_length_or_zero (left);
+- size_t right_length = string_length_or_zero (right);
+-
+- if (left_length != right_length || left == NULL || right == NULL
+- || memcmp (left, right, left_length) != 0)
+- {
+- support_record_failure ();
+- printf ("%s:%d: error: string comparison failed\n", file, line);
+- if (left_length == right_length && right != NULL && left != NULL)
+- printf (" string length: %zu bytes\n", left_length);
+- else
+- {
+- report_length ("left", left, left_length);
+- report_length ("right", right, right_length);
+- }
+- report_string ("left", (const unsigned char *) left,
+- left_length, left_expr);
+- report_string ("right", (const unsigned char *) right,
+- right_length, right_expr);
+- }
+-}
++#define CHAR char
++#define UCHAR unsigned char
++#define LPREFIX ""
++#define STRLEN strlen
++#define MEMCMP memcmp
++#define SUPPORT_QUOTE_BLOB support_quote_blob
++#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string
++#define WIDE 0
++
++#include "support_test_compare_string_main.c"
+diff --git a/support/support_test_compare_string_main.c b/support/support_test_compare_string_main.c
+new file mode 100644
+index 0000000000..0edc0ca97d
+--- /dev/null
++++ b/support/support_test_compare_string_main.c
+@@ -0,0 +1,94 @@
++/* Check two strings for equality.
++ Copyright (C) 2018-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <wchar.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/xmemstream.h>
++
++static void
++report_length (const char *what, const CHAR *str, size_t length)
++{
++ if (str == NULL)
++ printf (" %s string: NULL\n", what);
++ else
++ printf (" %s string: %zu %s\n", what, length,
++ WIDE ? "wide characters" : "bytes");
++}
++
++static void
++report_string (const char *what, const UCHAR *blob,
++ size_t length, const char *expr)
++{
++ if (length > 0)
++ {
++ printf (" %s (evaluated from %s):\n", what, expr);
++ char *quoted = SUPPORT_QUOTE_BLOB (blob, length);
++ printf (" %s\"%s\"\n", LPREFIX, quoted);
++ free (quoted);
++
++ fputs (" ", stdout);
++ for (size_t i = 0; i < length; ++i)
++ printf (" %02X", (unsigned int) blob[i]);
++ putc ('\n', stdout);
++ }
++}
++
++static size_t
++string_length_or_zero (const CHAR *str)
++{
++ if (str == NULL)
++ return 0;
++ else
++ return STRLEN (str);
++}
++
++void
++SUPPORT_TEST_COMPARE_STRING (const CHAR *left, const CHAR *right,
++ const char *file, int line,
++ const char *left_expr, const char *right_expr)
++{
++ /* Two null pointers are accepted. */
++ if (left == NULL && right == NULL)
++ return;
++
++ size_t left_length = string_length_or_zero (left);
++ size_t right_length = string_length_or_zero (right);
++
++ if (left_length != right_length || left == NULL || right == NULL
++ || MEMCMP (left, right, left_length) != 0)
++ {
++ support_record_failure ();
++ printf ("%s:%d: error: string comparison failed\n", file, line);
++ if (left_length == right_length && right != NULL && left != NULL)
++ printf (" string length: %zu %s\n", left_length,
++ WIDE ? "wide characters" : "bytes");
++ else
++ {
++ report_length ("left", left, left_length);
++ report_length ("right", right, right_length);
++ }
++ report_string ("left", (const UCHAR *) left,
++ left_length, left_expr);
++ report_string ("right", (const UCHAR *) right,
++ right_length, right_expr);
++ }
++}
+diff --git a/support/support_test_compare_string_wide.c b/support/support_test_compare_string_wide.c
+new file mode 100644
+index 0000000000..88b560b142
+--- /dev/null
++++ b/support/support_test_compare_string_wide.c
+@@ -0,0 +1,28 @@
++/* Check two wide strings for equality.
++ Copyright (C) 2018-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define CHAR wchar_t
++#define UCHAR wchar_t
++#define LPREFIX "L"
++#define STRLEN wcslen
++#define MEMCMP wmemcmp
++#define SUPPORT_QUOTE_BLOB support_quote_blob_wide
++#define SUPPORT_TEST_COMPARE_STRING support_test_compare_string_wide
++#define WIDE 1
++
++#include "support_test_compare_string_main.c"
+diff --git a/support/tst-support_quote_blob_wide.c b/support/tst-support_quote_blob_wide.c
+new file mode 100644
+index 0000000000..ea71a1f7f8
+--- /dev/null
++++ b/support/tst-support_quote_blob_wide.c
+@@ -0,0 +1,66 @@
++/* Test the support_quote_blob_wide function.
++ Copyright (C) 2018-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <support/check.h>
++#include <support/support.h>
++#include <string.h>
++#include <stdlib.h>
++
++static int
++do_test (void)
++{
++ /* Check handling of the empty blob, both with and without trailing
++ NUL byte. */
++ char *p = support_quote_blob_wide (L"", 0);
++ TEST_COMPARE (strlen (p), 0);
++ free (p);
++ p = support_quote_blob_wide (L"X", 0);
++ TEST_COMPARE (strlen (p), 0);
++ free (p);
++
++ /* Check escaping of backslash-escaped characters, and lack of
++ escaping for other shell meta-characters. */
++ p = support_quote_blob_wide (L"$()*?`@[]{}~\'\"X", 14);
++ TEST_COMPARE (strcmp (p, "$()*?`@[]{}~\\'\\\""), 0);
++ free (p);
++
++ /* Check lack of escaping for letters and digits. */
++#define LETTERS_AND_DIGTS \
++ "abcdefghijklmnopqrstuvwxyz" \
++ "ABCDEFGHIJKLMNOPQRSTUVWXYZ" \
++ "0123456789"
++#define CONCATX(X, Y) X ## Y
++#define CONCAT(X, Y) CONCATX (X, Y)
++#define WLETTERS_AND_DIGTS CONCAT (L, LETTERS_AND_DIGTS)
++ p = support_quote_blob_wide (WLETTERS_AND_DIGTS "@", 2 * 26 + 10);
++ TEST_COMPARE (strcmp (p, LETTERS_AND_DIGTS), 0);
++ free (p);
++
++ /* Check escaping of control characters and other non-printable
++ characters. */
++ p = support_quote_blob_wide (L"\r\n\t\a\b\f\v\1\177\200\377"
++ "\x123\x76543210\xfedcba98\0@", 17);
++ TEST_COMPARE (strcmp (p, "\\r\\n\\t\\a\\b\\f\\v\\x{1}"
++ "\\x{7f}\\x{80}\\x{ff}\\x{123}\\x{76543210}"
++ "\\x{fedcba98}\\x{0}@\\x{0}"), 0);
++ free (p);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/support/tst-test_compare_string_wide.c b/support/tst-test_compare_string_wide.c
+new file mode 100644
+index 0000000000..548f7dcdc6
+--- /dev/null
++++ b/support/tst-test_compare_string_wide.c
+@@ -0,0 +1,107 @@
++/* Basic test for the TEST_COMPARE_STRING_WIDE macro.
++ Copyright (C) 2018-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <string.h>
++#include <support/check.h>
++#include <support/capture_subprocess.h>
++
++static void
++subprocess (void *closure)
++{
++ /* These tests should fail. They were chosen to cover differences
++ in length (with the same contents), single-bit mismatches, and
++ mismatching null pointers. */
++ TEST_COMPARE_STRING_WIDE (L"", NULL); /* Line 29. */
++ TEST_COMPARE_STRING_WIDE (L"X", L""); /* Line 30. */
++ TEST_COMPARE_STRING_WIDE (NULL, L"X"); /* Line 31. */
++ TEST_COMPARE_STRING_WIDE (L"abcd", L"abcD"); /* Line 32. */
++ TEST_COMPARE_STRING_WIDE (L"abcd", NULL); /* Line 33. */
++ TEST_COMPARE_STRING_WIDE (NULL, L"abcd"); /* Line 34. */
++}
++
++/* Same contents, different addresses. */
++wchar_t buffer_abc_1[] = L"abc";
++wchar_t buffer_abc_2[] = L"abc";
++
++static int
++do_test (void)
++{
++ /* This should succeed. Even if the pointers and array contents are
++ different, zero-length inputs are not different. */
++ TEST_COMPARE_STRING_WIDE (NULL, NULL);
++ TEST_COMPARE_STRING_WIDE (L"", L"");
++ TEST_COMPARE_STRING_WIDE (buffer_abc_1, buffer_abc_2);
++ TEST_COMPARE_STRING_WIDE (buffer_abc_1, L"abc");
++
++ struct support_capture_subprocess proc = support_capture_subprocess
++ (&subprocess, NULL);
++
++ /* Discard the reported error. */
++ support_record_failure_reset ();
++
++ puts ("info: *** subprocess output starts ***");
++ fputs (proc.out.buffer, stdout);
++ puts ("info: *** subprocess output ends ***");
++
++ TEST_VERIFY
++ (strcmp (proc.out.buffer,
++"tst-test_compare_string_wide.c:29: error: string comparison failed\n"
++" left string: 0 wide characters\n"
++" right string: NULL\n"
++"tst-test_compare_string_wide.c:30: error: string comparison failed\n"
++" left string: 1 wide characters\n"
++" right string: 0 wide characters\n"
++" left (evaluated from L\"X\"):\n"
++" L\"X\"\n"
++" 58\n"
++"tst-test_compare_string_wide.c:31: error: string comparison failed\n"
++" left string: NULL\n"
++" right string: 1 wide characters\n"
++" right (evaluated from L\"X\"):\n"
++" L\"X\"\n"
++" 58\n"
++"tst-test_compare_string_wide.c:32: error: string comparison failed\n"
++" string length: 4 wide characters\n"
++" left (evaluated from L\"abcd\"):\n"
++" L\"abcd\"\n"
++" 61 62 63 64\n"
++" right (evaluated from L\"abcD\"):\n"
++" L\"abcD\"\n"
++" 61 62 63 44\n"
++"tst-test_compare_string_wide.c:33: error: string comparison failed\n"
++" left string: 4 wide characters\n"
++" right string: NULL\n"
++" left (evaluated from L\"abcd\"):\n"
++" L\"abcd\"\n"
++" 61 62 63 64\n"
++"tst-test_compare_string_wide.c:34: error: string comparison failed\n"
++" left string: NULL\n"
++" right string: 4 wide characters\n"
++" right (evaluated from L\"abcd\"):\n"
++" L\"abcd\"\n"
++" 61 62 63 64\n"
++ ) == 0);
++
++ /* Check that there is no output on standard error. */
++ support_capture_subprocess_check (&proc, "TEST_COMPARE_STRING_WIDE",
++ 0, sc_allow_stdout);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.28.0.windows.1
+
diff --git a/backport-Add-codepoint_collation-support-for-LC_COLLATE.patch b/backport-Add-codepoint_collation-support-for-LC_COLLATE.patch
new file mode 100644
index 0000000..55fe40f
--- /dev/null
+++ b/backport-Add-codepoint_collation-support-for-LC_COLLATE.patch
@@ -0,0 +1,994 @@
+From f5117c6504888fab5423282a4607c552b90fd3f9 Mon Sep 17 00:00:00 2001
+From: Carlos O'Donell <carlos@redhat.com>
+Date: Thu, 29 Jul 2021 22:45:39 -0400
+Subject: [PATCH] Add 'codepoint_collation' support for LC_COLLATE.
+
+Support a new directive 'codepoint_collation' in the LC_COLLATE
+section of a locale source file. This new directive causes all
+collation rules to be dropped and instead STRCMP (strcmp or
+wcscmp) is used for collation of the input character set. This
+is required to allow for a C.UTF-8 that contains zero collation
+rules (minimal size) and sorts using code point sorting.
+
+To date the only implementation of a locale with zero collation
+rules is the C/POSIX locale. The C/POSIX locale provides
+identity tables for _NL_COLLATE_COLLSEQMB and
+_NL_COLLATE_COLLSEQWC that map to ASCII even though it has zero
+rules. This has lead to existing fnmatch, regexec, and regcomp
+implementations that require these tables. It is not correct
+to use these tables when nrules == 0, but the conservative fix
+is to provide these tables when nrules == 0. This assures that
+existing static applications using a new C.UTF-8 locale with
+'codepoint_collation' at least have functional range expressions
+with ASCII e.g. [0-9] or [a-z]. Such static applications would
+not have the fixes to fnmatch, regexec and regcomp that avoid
+the use of the tables when nrules == 0. Future fixes to fnmatch,
+regexec, and regcomp would allow range expressions to use the
+full set of code points for such ranges.
+
+Tested on x86_64 and i686 without regression.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=f5117c6504888fab5423282a4607c552b90fd3f9
+---
+ locale/C-collate-seq.c | 100 +++++++++++
+ locale/C-collate.c | 78 +-------
+ locale/programs/ld-collate.c | 36 +++-
+ locale/programs/locfile-kw.gperf | 1 +
+ locale/programs/locfile-kw.h | 299 ++++++++++++++++---------------
+ locale/programs/locfile-token.h | 1 +
+ 6 files changed, 286 insertions(+), 229 deletions(-)
+ create mode 100644 locale/C-collate-seq.c
+
+diff --git a/locale/C-collate-seq.c b/locale/C-collate-seq.c
+new file mode 100644
+index 0000000000..4fb82cb835
+--- /dev/null
++++ b/locale/C-collate-seq.c
+@@ -0,0 +1,100 @@
++/* Copyright (C) 1995-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdint.h>
++
++static const char collseqmb[] =
++{
++ '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
++ '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
++ '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
++ '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
++ '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
++ '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
++ '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
++ '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
++ '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
++ '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
++ '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
++ '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
++ '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
++ '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
++ '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
++ '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
++ '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
++ '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
++ '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
++ '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
++ '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
++ '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
++ '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
++ '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
++ '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
++ '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
++ '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
++ '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
++ '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
++ '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
++ '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
++ '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff'
++};
++
++/* This table must be 256 bytes in size. We index bytes into the
++ table to find the collation sequence. */
++_Static_assert (sizeof (collseqmb) == 256);
++
++static const uint32_t collseqwc[] =
++{
++ 8, 1, 8, 0x0, 0xff,
++ /* 1st-level table */
++ 6 * sizeof (uint32_t),
++ /* 2nd-level table */
++ 7 * sizeof (uint32_t),
++ /* 3rd-level table */
++ L'\x00', L'\x01', L'\x02', L'\x03', L'\x04', L'\x05', L'\x06', L'\x07',
++ L'\x08', L'\x09', L'\x0a', L'\x0b', L'\x0c', L'\x0d', L'\x0e', L'\x0f',
++ L'\x10', L'\x11', L'\x12', L'\x13', L'\x14', L'\x15', L'\x16', L'\x17',
++ L'\x18', L'\x19', L'\x1a', L'\x1b', L'\x1c', L'\x1d', L'\x1e', L'\x1f',
++ L'\x20', L'\x21', L'\x22', L'\x23', L'\x24', L'\x25', L'\x26', L'\x27',
++ L'\x28', L'\x29', L'\x2a', L'\x2b', L'\x2c', L'\x2d', L'\x2e', L'\x2f',
++ L'\x30', L'\x31', L'\x32', L'\x33', L'\x34', L'\x35', L'\x36', L'\x37',
++ L'\x38', L'\x39', L'\x3a', L'\x3b', L'\x3c', L'\x3d', L'\x3e', L'\x3f',
++ L'\x40', L'\x41', L'\x42', L'\x43', L'\x44', L'\x45', L'\x46', L'\x47',
++ L'\x48', L'\x49', L'\x4a', L'\x4b', L'\x4c', L'\x4d', L'\x4e', L'\x4f',
++ L'\x50', L'\x51', L'\x52', L'\x53', L'\x54', L'\x55', L'\x56', L'\x57',
++ L'\x58', L'\x59', L'\x5a', L'\x5b', L'\x5c', L'\x5d', L'\x5e', L'\x5f',
++ L'\x60', L'\x61', L'\x62', L'\x63', L'\x64', L'\x65', L'\x66', L'\x67',
++ L'\x68', L'\x69', L'\x6a', L'\x6b', L'\x6c', L'\x6d', L'\x6e', L'\x6f',
++ L'\x70', L'\x71', L'\x72', L'\x73', L'\x74', L'\x75', L'\x76', L'\x77',
++ L'\x78', L'\x79', L'\x7a', L'\x7b', L'\x7c', L'\x7d', L'\x7e', L'\x7f',
++ L'\x80', L'\x81', L'\x82', L'\x83', L'\x84', L'\x85', L'\x86', L'\x87',
++ L'\x88', L'\x89', L'\x8a', L'\x8b', L'\x8c', L'\x8d', L'\x8e', L'\x8f',
++ L'\x90', L'\x91', L'\x92', L'\x93', L'\x94', L'\x95', L'\x96', L'\x97',
++ L'\x98', L'\x99', L'\x9a', L'\x9b', L'\x9c', L'\x9d', L'\x9e', L'\x9f',
++ L'\xa0', L'\xa1', L'\xa2', L'\xa3', L'\xa4', L'\xa5', L'\xa6', L'\xa7',
++ L'\xa8', L'\xa9', L'\xaa', L'\xab', L'\xac', L'\xad', L'\xae', L'\xaf',
++ L'\xb0', L'\xb1', L'\xb2', L'\xb3', L'\xb4', L'\xb5', L'\xb6', L'\xb7',
++ L'\xb8', L'\xb9', L'\xba', L'\xbb', L'\xbc', L'\xbd', L'\xbe', L'\xbf',
++ L'\xc0', L'\xc1', L'\xc2', L'\xc3', L'\xc4', L'\xc5', L'\xc6', L'\xc7',
++ L'\xc8', L'\xc9', L'\xca', L'\xcb', L'\xcc', L'\xcd', L'\xce', L'\xcf',
++ L'\xd0', L'\xd1', L'\xd2', L'\xd3', L'\xd4', L'\xd5', L'\xd6', L'\xd7',
++ L'\xd8', L'\xd9', L'\xda', L'\xdb', L'\xdc', L'\xdd', L'\xde', L'\xdf',
++ L'\xe0', L'\xe1', L'\xe2', L'\xe3', L'\xe4', L'\xe5', L'\xe6', L'\xe7',
++ L'\xe8', L'\xe9', L'\xea', L'\xeb', L'\xec', L'\xed', L'\xee', L'\xef',
++ L'\xf0', L'\xf1', L'\xf2', L'\xf3', L'\xf4', L'\xf5', L'\xf6', L'\xf7',
++ L'\xf8', L'\xf9', L'\xfa', L'\xfb', L'\xfc', L'\xfd', L'\xfe', L'\xff'
++};
+diff --git a/locale/C-collate.c b/locale/C-collate.c
+index 02b70570a4..bc93819f32 100644
+--- a/locale/C-collate.c
++++ b/locale/C-collate.c
+@@ -19,83 +19,7 @@
+ #include <stdint.h>
+ #include "localeinfo.h"
+
+-static const char collseqmb[] =
+-{
+- '\x00', '\x01', '\x02', '\x03', '\x04', '\x05', '\x06', '\x07',
+- '\x08', '\x09', '\x0a', '\x0b', '\x0c', '\x0d', '\x0e', '\x0f',
+- '\x10', '\x11', '\x12', '\x13', '\x14', '\x15', '\x16', '\x17',
+- '\x18', '\x19', '\x1a', '\x1b', '\x1c', '\x1d', '\x1e', '\x1f',
+- '\x20', '\x21', '\x22', '\x23', '\x24', '\x25', '\x26', '\x27',
+- '\x28', '\x29', '\x2a', '\x2b', '\x2c', '\x2d', '\x2e', '\x2f',
+- '\x30', '\x31', '\x32', '\x33', '\x34', '\x35', '\x36', '\x37',
+- '\x38', '\x39', '\x3a', '\x3b', '\x3c', '\x3d', '\x3e', '\x3f',
+- '\x40', '\x41', '\x42', '\x43', '\x44', '\x45', '\x46', '\x47',
+- '\x48', '\x49', '\x4a', '\x4b', '\x4c', '\x4d', '\x4e', '\x4f',
+- '\x50', '\x51', '\x52', '\x53', '\x54', '\x55', '\x56', '\x57',
+- '\x58', '\x59', '\x5a', '\x5b', '\x5c', '\x5d', '\x5e', '\x5f',
+- '\x60', '\x61', '\x62', '\x63', '\x64', '\x65', '\x66', '\x67',
+- '\x68', '\x69', '\x6a', '\x6b', '\x6c', '\x6d', '\x6e', '\x6f',
+- '\x70', '\x71', '\x72', '\x73', '\x74', '\x75', '\x76', '\x77',
+- '\x78', '\x79', '\x7a', '\x7b', '\x7c', '\x7d', '\x7e', '\x7f',
+- '\x80', '\x81', '\x82', '\x83', '\x84', '\x85', '\x86', '\x87',
+- '\x88', '\x89', '\x8a', '\x8b', '\x8c', '\x8d', '\x8e', '\x8f',
+- '\x90', '\x91', '\x92', '\x93', '\x94', '\x95', '\x96', '\x97',
+- '\x98', '\x99', '\x9a', '\x9b', '\x9c', '\x9d', '\x9e', '\x9f',
+- '\xa0', '\xa1', '\xa2', '\xa3', '\xa4', '\xa5', '\xa6', '\xa7',
+- '\xa8', '\xa9', '\xaa', '\xab', '\xac', '\xad', '\xae', '\xaf',
+- '\xb0', '\xb1', '\xb2', '\xb3', '\xb4', '\xb5', '\xb6', '\xb7',
+- '\xb8', '\xb9', '\xba', '\xbb', '\xbc', '\xbd', '\xbe', '\xbf',
+- '\xc0', '\xc1', '\xc2', '\xc3', '\xc4', '\xc5', '\xc6', '\xc7',
+- '\xc8', '\xc9', '\xca', '\xcb', '\xcc', '\xcd', '\xce', '\xcf',
+- '\xd0', '\xd1', '\xd2', '\xd3', '\xd4', '\xd5', '\xd6', '\xd7',
+- '\xd8', '\xd9', '\xda', '\xdb', '\xdc', '\xdd', '\xde', '\xdf',
+- '\xe0', '\xe1', '\xe2', '\xe3', '\xe4', '\xe5', '\xe6', '\xe7',
+- '\xe8', '\xe9', '\xea', '\xeb', '\xec', '\xed', '\xee', '\xef',
+- '\xf0', '\xf1', '\xf2', '\xf3', '\xf4', '\xf5', '\xf6', '\xf7',
+- '\xf8', '\xf9', '\xfa', '\xfb', '\xfc', '\xfd', '\xfe', '\xff'
+-};
+-
+-static const uint32_t collseqwc[] =
+-{
+- 8, 1, 8, 0x0, 0xff,
+- /* 1st-level table */
+- 6 * sizeof (uint32_t),
+- /* 2nd-level table */
+- 7 * sizeof (uint32_t),
+- /* 3rd-level table */
+- L'\x00', L'\x01', L'\x02', L'\x03', L'\x04', L'\x05', L'\x06', L'\x07',
+- L'\x08', L'\x09', L'\x0a', L'\x0b', L'\x0c', L'\x0d', L'\x0e', L'\x0f',
+- L'\x10', L'\x11', L'\x12', L'\x13', L'\x14', L'\x15', L'\x16', L'\x17',
+- L'\x18', L'\x19', L'\x1a', L'\x1b', L'\x1c', L'\x1d', L'\x1e', L'\x1f',
+- L'\x20', L'\x21', L'\x22', L'\x23', L'\x24', L'\x25', L'\x26', L'\x27',
+- L'\x28', L'\x29', L'\x2a', L'\x2b', L'\x2c', L'\x2d', L'\x2e', L'\x2f',
+- L'\x30', L'\x31', L'\x32', L'\x33', L'\x34', L'\x35', L'\x36', L'\x37',
+- L'\x38', L'\x39', L'\x3a', L'\x3b', L'\x3c', L'\x3d', L'\x3e', L'\x3f',
+- L'\x40', L'\x41', L'\x42', L'\x43', L'\x44', L'\x45', L'\x46', L'\x47',
+- L'\x48', L'\x49', L'\x4a', L'\x4b', L'\x4c', L'\x4d', L'\x4e', L'\x4f',
+- L'\x50', L'\x51', L'\x52', L'\x53', L'\x54', L'\x55', L'\x56', L'\x57',
+- L'\x58', L'\x59', L'\x5a', L'\x5b', L'\x5c', L'\x5d', L'\x5e', L'\x5f',
+- L'\x60', L'\x61', L'\x62', L'\x63', L'\x64', L'\x65', L'\x66', L'\x67',
+- L'\x68', L'\x69', L'\x6a', L'\x6b', L'\x6c', L'\x6d', L'\x6e', L'\x6f',
+- L'\x70', L'\x71', L'\x72', L'\x73', L'\x74', L'\x75', L'\x76', L'\x77',
+- L'\x78', L'\x79', L'\x7a', L'\x7b', L'\x7c', L'\x7d', L'\x7e', L'\x7f',
+- L'\x80', L'\x81', L'\x82', L'\x83', L'\x84', L'\x85', L'\x86', L'\x87',
+- L'\x88', L'\x89', L'\x8a', L'\x8b', L'\x8c', L'\x8d', L'\x8e', L'\x8f',
+- L'\x90', L'\x91', L'\x92', L'\x93', L'\x94', L'\x95', L'\x96', L'\x97',
+- L'\x98', L'\x99', L'\x9a', L'\x9b', L'\x9c', L'\x9d', L'\x9e', L'\x9f',
+- L'\xa0', L'\xa1', L'\xa2', L'\xa3', L'\xa4', L'\xa5', L'\xa6', L'\xa7',
+- L'\xa8', L'\xa9', L'\xaa', L'\xab', L'\xac', L'\xad', L'\xae', L'\xaf',
+- L'\xb0', L'\xb1', L'\xb2', L'\xb3', L'\xb4', L'\xb5', L'\xb6', L'\xb7',
+- L'\xb8', L'\xb9', L'\xba', L'\xbb', L'\xbc', L'\xbd', L'\xbe', L'\xbf',
+- L'\xc0', L'\xc1', L'\xc2', L'\xc3', L'\xc4', L'\xc5', L'\xc6', L'\xc7',
+- L'\xc8', L'\xc9', L'\xca', L'\xcb', L'\xcc', L'\xcd', L'\xce', L'\xcf',
+- L'\xd0', L'\xd1', L'\xd2', L'\xd3', L'\xd4', L'\xd5', L'\xd6', L'\xd7',
+- L'\xd8', L'\xd9', L'\xda', L'\xdb', L'\xdc', L'\xdd', L'\xde', L'\xdf',
+- L'\xe0', L'\xe1', L'\xe2', L'\xe3', L'\xe4', L'\xe5', L'\xe6', L'\xe7',
+- L'\xe8', L'\xe9', L'\xea', L'\xeb', L'\xec', L'\xed', L'\xee', L'\xef',
+- L'\xf0', L'\xf1', L'\xf2', L'\xf3', L'\xf4', L'\xf5', L'\xf6', L'\xf7',
+- L'\xf8', L'\xf9', L'\xfa', L'\xfb', L'\xfc', L'\xfd', L'\xfe', L'\xff'
+-};
++#include "C-collate-seq.c"
+
+ const struct __locale_data _nl_C_LC_COLLATE attribute_hidden =
+ {
+diff --git a/locale/programs/ld-collate.c b/locale/programs/ld-collate.c
+index f4a8f34e46..06a5203334 100644
+--- a/locale/programs/ld-collate.c
++++ b/locale/programs/ld-collate.c
+@@ -23,6 +23,7 @@
+ #include <wchar.h>
+ #include <stdint.h>
+ #include <sys/param.h>
++#include <array_length.h>
+
+ #include "localedef.h"
+ #include "charmap.h"
+@@ -194,6 +195,9 @@ struct name_list
+ /* The real definition of the struct for the LC_COLLATE locale. */
+ struct locale_collate_t
+ {
++ /* Does the locale use code points to compare the encoding? */
++ bool codepoint_collation;
++
+ int col_weight_max;
+ int cur_weight_max;
+
+@@ -1509,6 +1513,7 @@ collate_startup (struct linereader *ldfile, struct localedef_t *locale,
+ obstack_init (&collate->mempool);
+
+ collate->col_weight_max = -1;
++ collate->codepoint_collation = false;
+ }
+ else
+ /* Reuse the copy_locale's data structures. */
+@@ -1567,6 +1572,10 @@ collate_finish (struct localedef_t *locale, const struct charmap_t *charmap)
+ return;
+ }
+
++ /* No data required. */
++ if (collate->codepoint_collation)
++ return;
++
+ /* If this assertion is hit change the type in `element_t'. */
+ assert (nrules <= sizeof (runp->used_in_level) * 8);
+
+@@ -2091,6 +2100,10 @@ add_to_tablewc (uint32_t ch, struct element_t *runp)
+ }
+ }
+
++/* Include the C locale identity tables for _NL_COLLATE_COLLSEQMB and
++ _NL_COLLATE_COLLSEQWC. */
++#include "C-collate-seq.c"
++
+ void
+ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
+ const char *output_path)
+@@ -2114,7 +2127,7 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
+ add_locale_uint32 (&file, nrules);
+
+ /* If we have no LC_COLLATE data emit only the number of rules as zero. */
+- if (collate == NULL)
++ if (collate == NULL || collate->codepoint_collation)
+ {
+ size_t idx;
+ for (idx = 1; idx < nelems; idx++)
+@@ -2122,6 +2135,17 @@ collate_output (struct localedef_t *locale, const struct charmap_t *charmap,
+ /* The words have to be handled specially. */
+ if (idx == _NL_ITEM_INDEX (_NL_COLLATE_SYMB_HASH_SIZEMB))
+ add_locale_uint32 (&file, 0);
++ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_CODESET)
++ && collate != NULL)
++ /* A valid LC_COLLATE must have a code set name. */
++ add_locale_string (&file, charmap->code_set_name);
++ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQMB)
++ && collate != NULL)
++ add_locale_raw_data (&file, collseqmb, sizeof (collseqmb));
++ else if (idx == _NL_ITEM_INDEX (_NL_COLLATE_COLLSEQWC)
++ && collate != NULL)
++ add_locale_uint32_array (&file, collseqwc,
++ array_length (collseqwc));
+ else
+ add_locale_empty (&file);
+ }
+@@ -2671,6 +2695,10 @@ collate_read (struct linereader *ldfile, struct localedef_t *result,
+
+ switch (nowtok)
+ {
++ case tok_codepoint_collation:
++ collate->codepoint_collation = true;
++ break;
++
+ case tok_copy:
+ /* Allow copying other locales. */
+ now = lr_token (ldfile, charmap, result, NULL, verbose);
+@@ -3741,9 +3769,11 @@ error while adding equivalent collating symbol"));
+ /* Next we assume `LC_COLLATE'. */
+ if (!ignore_content)
+ {
+- if (state == 0 && copy_locale == NULL)
++ if (state == 0
++ && copy_locale == NULL
++ && !collate->codepoint_collation)
+ /* We must either see a copy statement or have
+- ordering values. */
++ ordering values, or codepoint_collation. */
+ lr_error (ldfile,
+ _("%s: empty category description not allowed"),
+ "LC_COLLATE");
+diff --git a/locale/programs/locfile-kw.gperf b/locale/programs/locfile-kw.gperf
+index 0d3b95d77b..5ca9b47085 100644
+--- a/locale/programs/locfile-kw.gperf
++++ b/locale/programs/locfile-kw.gperf
+@@ -53,6 +53,7 @@ translit_end, tok_translit_end, 0
+ translit_ignore, tok_translit_ignore, 0
+ default_missing, tok_default_missing, 0
+ LC_COLLATE, tok_lc_collate, 0
++codepoint_collation, tok_codepoint_collation, 0
+ coll_weight_max, tok_coll_weight_max, 0
+ section-symbol, tok_section_symbol, 0
+ collating-element, tok_collating_element, 0
+diff --git a/locale/programs/locfile-kw.h b/locale/programs/locfile-kw.h
+index dc150bb8f8..c57d74f5f3 100644
+--- a/locale/programs/locfile-kw.h
++++ b/locale/programs/locfile-kw.h
+@@ -53,7 +53,7 @@
+ #line 24 "locfile-kw.gperf"
+ struct keyword_t ;
+
+-#define TOTAL_KEYWORDS 178
++#define TOTAL_KEYWORDS 179
+ #define MIN_WORD_LENGTH 3
+ #define MAX_WORD_LENGTH 22
+ #define MIN_HASH_VALUE 3
+@@ -133,92 +133,92 @@ locfile_hash (register const char *str, register size_t len)
+ #line 31 "locfile-kw.gperf"
+ {"END", tok_end, 0},
+ {""}, {""},
+-#line 70 "locfile-kw.gperf"
++#line 71 "locfile-kw.gperf"
+ {"IGNORE", tok_ignore, 0},
+-#line 129 "locfile-kw.gperf"
++#line 130 "locfile-kw.gperf"
+ {"LC_TIME", tok_lc_time, 0},
+ #line 30 "locfile-kw.gperf"
+ {"LC_CTYPE", tok_lc_ctype, 0},
+ {""},
+-#line 168 "locfile-kw.gperf"
++#line 169 "locfile-kw.gperf"
+ {"LC_ADDRESS", tok_lc_address, 0},
+-#line 153 "locfile-kw.gperf"
++#line 154 "locfile-kw.gperf"
+ {"LC_MESSAGES", tok_lc_messages, 0},
+-#line 161 "locfile-kw.gperf"
++#line 162 "locfile-kw.gperf"
+ {"LC_NAME", tok_lc_name, 0},
+-#line 158 "locfile-kw.gperf"
++#line 159 "locfile-kw.gperf"
+ {"LC_PAPER", tok_lc_paper, 0},
+-#line 186 "locfile-kw.gperf"
++#line 187 "locfile-kw.gperf"
+ {"LC_MEASUREMENT", tok_lc_measurement, 0},
+ #line 56 "locfile-kw.gperf"
+ {"LC_COLLATE", tok_lc_collate, 0},
+ {""},
+-#line 188 "locfile-kw.gperf"
++#line 189 "locfile-kw.gperf"
+ {"LC_IDENTIFICATION", tok_lc_identification, 0},
+-#line 201 "locfile-kw.gperf"
++#line 202 "locfile-kw.gperf"
+ {"revision", tok_revision, 0},
+-#line 69 "locfile-kw.gperf"
++#line 70 "locfile-kw.gperf"
+ {"UNDEFINED", tok_undefined, 0},
+-#line 125 "locfile-kw.gperf"
++#line 126 "locfile-kw.gperf"
+ {"LC_NUMERIC", tok_lc_numeric, 0},
+-#line 82 "locfile-kw.gperf"
++#line 83 "locfile-kw.gperf"
+ {"LC_MONETARY", tok_lc_monetary, 0},
+-#line 181 "locfile-kw.gperf"
++#line 182 "locfile-kw.gperf"
+ {"LC_TELEPHONE", tok_lc_telephone, 0},
+ {""}, {""}, {""},
+-#line 75 "locfile-kw.gperf"
++#line 76 "locfile-kw.gperf"
+ {"define", tok_define, 0},
+-#line 154 "locfile-kw.gperf"
++#line 155 "locfile-kw.gperf"
+ {"yesexpr", tok_yesexpr, 0},
+-#line 141 "locfile-kw.gperf"
++#line 142 "locfile-kw.gperf"
+ {"era_year", tok_era_year, 0},
+ {""},
+ #line 54 "locfile-kw.gperf"
+ {"translit_ignore", tok_translit_ignore, 0},
+-#line 156 "locfile-kw.gperf"
++#line 157 "locfile-kw.gperf"
+ {"yesstr", tok_yesstr, 0},
+ {""},
+-#line 89 "locfile-kw.gperf"
++#line 90 "locfile-kw.gperf"
+ {"negative_sign", tok_negative_sign, 0},
+ {""},
+-#line 137 "locfile-kw.gperf"
++#line 138 "locfile-kw.gperf"
+ {"t_fmt", tok_t_fmt, 0},
+-#line 159 "locfile-kw.gperf"
++#line 160 "locfile-kw.gperf"
+ {"height", tok_height, 0},
+ {""}, {""},
+ #line 52 "locfile-kw.gperf"
+ {"translit_start", tok_translit_start, 0},
+-#line 136 "locfile-kw.gperf"
++#line 137 "locfile-kw.gperf"
+ {"d_fmt", tok_d_fmt, 0},
+ {""},
+ #line 53 "locfile-kw.gperf"
+ {"translit_end", tok_translit_end, 0},
+-#line 94 "locfile-kw.gperf"
++#line 95 "locfile-kw.gperf"
+ {"n_cs_precedes", tok_n_cs_precedes, 0},
+-#line 144 "locfile-kw.gperf"
++#line 145 "locfile-kw.gperf"
+ {"era_t_fmt", tok_era_t_fmt, 0},
+ #line 39 "locfile-kw.gperf"
+ {"space", tok_space, 0},
+-#line 72 "locfile-kw.gperf"
+- {"reorder-end", tok_reorder_end, 0},
+ #line 73 "locfile-kw.gperf"
++ {"reorder-end", tok_reorder_end, 0},
++#line 74 "locfile-kw.gperf"
+ {"reorder-sections-after", tok_reorder_sections_after, 0},
+ {""},
+-#line 142 "locfile-kw.gperf"
++#line 143 "locfile-kw.gperf"
+ {"era_d_fmt", tok_era_d_fmt, 0},
+-#line 189 "locfile-kw.gperf"
++#line 190 "locfile-kw.gperf"
+ {"title", tok_title, 0},
+ {""}, {""},
+-#line 149 "locfile-kw.gperf"
++#line 150 "locfile-kw.gperf"
+ {"timezone", tok_timezone, 0},
+ {""},
+-#line 74 "locfile-kw.gperf"
++#line 75 "locfile-kw.gperf"
+ {"reorder-sections-end", tok_reorder_sections_end, 0},
+ {""}, {""}, {""},
+-#line 95 "locfile-kw.gperf"
++#line 96 "locfile-kw.gperf"
+ {"n_sep_by_space", tok_n_sep_by_space, 0},
+ {""}, {""},
+-#line 100 "locfile-kw.gperf"
++#line 101 "locfile-kw.gperf"
+ {"int_n_cs_precedes", tok_int_n_cs_precedes, 0},
+ {""}, {""}, {""},
+ #line 26 "locfile-kw.gperf"
+@@ -232,147 +232,147 @@ locfile_hash (register const char *str, register size_t len)
+ {"print", tok_print, 0},
+ #line 44 "locfile-kw.gperf"
+ {"xdigit", tok_xdigit, 0},
+-#line 110 "locfile-kw.gperf"
++#line 111 "locfile-kw.gperf"
+ {"duo_n_cs_precedes", tok_duo_n_cs_precedes, 0},
+-#line 127 "locfile-kw.gperf"
++#line 128 "locfile-kw.gperf"
+ {"thousands_sep", tok_thousands_sep, 0},
+-#line 197 "locfile-kw.gperf"
++#line 198 "locfile-kw.gperf"
+ {"territory", tok_territory, 0},
+ #line 36 "locfile-kw.gperf"
+ {"digit", tok_digit, 0},
+ {""}, {""},
+-#line 92 "locfile-kw.gperf"
++#line 93 "locfile-kw.gperf"
+ {"p_cs_precedes", tok_p_cs_precedes, 0},
+ {""}, {""},
+-#line 62 "locfile-kw.gperf"
++#line 63 "locfile-kw.gperf"
+ {"script", tok_script, 0},
+ #line 29 "locfile-kw.gperf"
+ {"include", tok_include, 0},
+ {""},
+-#line 78 "locfile-kw.gperf"
++#line 79 "locfile-kw.gperf"
+ {"else", tok_else, 0},
+-#line 184 "locfile-kw.gperf"
++#line 185 "locfile-kw.gperf"
+ {"int_select", tok_int_select, 0},
+ {""}, {""}, {""},
+-#line 132 "locfile-kw.gperf"
++#line 133 "locfile-kw.gperf"
+ {"week", tok_week, 0},
+ #line 33 "locfile-kw.gperf"
+ {"upper", tok_upper, 0},
+ {""}, {""},
+-#line 194 "locfile-kw.gperf"
++#line 195 "locfile-kw.gperf"
+ {"tel", tok_tel, 0},
+-#line 93 "locfile-kw.gperf"
++#line 94 "locfile-kw.gperf"
+ {"p_sep_by_space", tok_p_sep_by_space, 0},
+-#line 160 "locfile-kw.gperf"
++#line 161 "locfile-kw.gperf"
+ {"width", tok_width, 0},
+ {""},
+-#line 98 "locfile-kw.gperf"
++#line 99 "locfile-kw.gperf"
+ {"int_p_cs_precedes", tok_int_p_cs_precedes, 0},
+ {""}, {""},
+ #line 41 "locfile-kw.gperf"
+ {"punct", tok_punct, 0},
+ {""}, {""},
+-#line 101 "locfile-kw.gperf"
++#line 102 "locfile-kw.gperf"
+ {"int_n_sep_by_space", tok_int_n_sep_by_space, 0},
+ {""}, {""}, {""},
+-#line 108 "locfile-kw.gperf"
++#line 109 "locfile-kw.gperf"
+ {"duo_p_cs_precedes", tok_duo_p_cs_precedes, 0},
+ #line 48 "locfile-kw.gperf"
+ {"charconv", tok_charconv, 0},
+ {""},
+ #line 47 "locfile-kw.gperf"
+ {"class", tok_class, 0},
+-#line 114 "locfile-kw.gperf"
+- {"duo_int_n_cs_precedes", tok_duo_int_n_cs_precedes, 0},
+ #line 115 "locfile-kw.gperf"
++ {"duo_int_n_cs_precedes", tok_duo_int_n_cs_precedes, 0},
++#line 116 "locfile-kw.gperf"
+ {"duo_int_n_sep_by_space", tok_duo_int_n_sep_by_space, 0},
+-#line 111 "locfile-kw.gperf"
++#line 112 "locfile-kw.gperf"
+ {"duo_n_sep_by_space", tok_duo_n_sep_by_space, 0},
+-#line 119 "locfile-kw.gperf"
++#line 120 "locfile-kw.gperf"
+ {"duo_int_n_sign_posn", tok_duo_int_n_sign_posn, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""},
+-#line 58 "locfile-kw.gperf"
++#line 59 "locfile-kw.gperf"
+ {"section-symbol", tok_section_symbol, 0},
+-#line 185 "locfile-kw.gperf"
++#line 186 "locfile-kw.gperf"
+ {"int_prefix", tok_int_prefix, 0},
+ {""}, {""}, {""}, {""},
+ #line 42 "locfile-kw.gperf"
+ {"graph", tok_graph, 0},
+ {""}, {""},
+-#line 99 "locfile-kw.gperf"
++#line 100 "locfile-kw.gperf"
+ {"int_p_sep_by_space", tok_int_p_sep_by_space, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 112 "locfile-kw.gperf"
+- {"duo_int_p_cs_precedes", tok_duo_int_p_cs_precedes, 0},
+ #line 113 "locfile-kw.gperf"
++ {"duo_int_p_cs_precedes", tok_duo_int_p_cs_precedes, 0},
++#line 114 "locfile-kw.gperf"
+ {"duo_int_p_sep_by_space", tok_duo_int_p_sep_by_space, 0},
+-#line 109 "locfile-kw.gperf"
++#line 110 "locfile-kw.gperf"
+ {"duo_p_sep_by_space", tok_duo_p_sep_by_space, 0},
+-#line 118 "locfile-kw.gperf"
++#line 119 "locfile-kw.gperf"
+ {"duo_int_p_sign_posn", tok_duo_int_p_sign_posn, 0},
+-#line 157 "locfile-kw.gperf"
++#line 158 "locfile-kw.gperf"
+ {"nostr", tok_nostr, 0},
+ {""}, {""},
+-#line 140 "locfile-kw.gperf"
++#line 141 "locfile-kw.gperf"
+ {"era", tok_era, 0},
+ {""},
+-#line 84 "locfile-kw.gperf"
++#line 85 "locfile-kw.gperf"
+ {"currency_symbol", tok_currency_symbol, 0},
+ {""},
+-#line 167 "locfile-kw.gperf"
++#line 168 "locfile-kw.gperf"
+ {"name_ms", tok_name_ms, 0},
+-#line 165 "locfile-kw.gperf"
+- {"name_mrs", tok_name_mrs, 0},
+ #line 166 "locfile-kw.gperf"
++ {"name_mrs", tok_name_mrs, 0},
++#line 167 "locfile-kw.gperf"
+ {"name_miss", tok_name_miss, 0},
+-#line 83 "locfile-kw.gperf"
++#line 84 "locfile-kw.gperf"
+ {"int_curr_symbol", tok_int_curr_symbol, 0},
+-#line 190 "locfile-kw.gperf"
++#line 191 "locfile-kw.gperf"
+ {"source", tok_source, 0},
+-#line 164 "locfile-kw.gperf"
++#line 165 "locfile-kw.gperf"
+ {"name_mr", tok_name_mr, 0},
+-#line 163 "locfile-kw.gperf"
++#line 164 "locfile-kw.gperf"
+ {"name_gen", tok_name_gen, 0},
+-#line 202 "locfile-kw.gperf"
++#line 203 "locfile-kw.gperf"
+ {"date", tok_date, 0},
+ {""}, {""},
+-#line 191 "locfile-kw.gperf"
++#line 192 "locfile-kw.gperf"
+ {"address", tok_address, 0},
+-#line 162 "locfile-kw.gperf"
++#line 163 "locfile-kw.gperf"
+ {"name_fmt", tok_name_fmt, 0},
+ #line 32 "locfile-kw.gperf"
+ {"copy", tok_copy, 0},
+-#line 103 "locfile-kw.gperf"
++#line 104 "locfile-kw.gperf"
+ {"int_n_sign_posn", tok_int_n_sign_posn, 0},
+ {""}, {""},
+-#line 131 "locfile-kw.gperf"
++#line 132 "locfile-kw.gperf"
+ {"day", tok_day, 0},
+-#line 105 "locfile-kw.gperf"
++#line 106 "locfile-kw.gperf"
+ {"duo_currency_symbol", tok_duo_currency_symbol, 0},
+ {""}, {""}, {""},
+-#line 150 "locfile-kw.gperf"
++#line 151 "locfile-kw.gperf"
+ {"date_fmt", tok_date_fmt, 0},
+-#line 64 "locfile-kw.gperf"
++#line 65 "locfile-kw.gperf"
+ {"order_end", tok_order_end, 0},
+-#line 117 "locfile-kw.gperf"
++#line 118 "locfile-kw.gperf"
+ {"duo_n_sign_posn", tok_duo_n_sign_posn, 0},
+ {""},
+-#line 170 "locfile-kw.gperf"
++#line 171 "locfile-kw.gperf"
+ {"country_name", tok_country_name, 0},
+-#line 71 "locfile-kw.gperf"
++#line 72 "locfile-kw.gperf"
+ {"reorder-after", tok_reorder_after, 0},
+ {""}, {""},
+-#line 155 "locfile-kw.gperf"
++#line 156 "locfile-kw.gperf"
+ {"noexpr", tok_noexpr, 0},
+ #line 50 "locfile-kw.gperf"
+ {"tolower", tok_tolower, 0},
+-#line 198 "locfile-kw.gperf"
++#line 199 "locfile-kw.gperf"
+ {"audience", tok_audience, 0},
+ {""}, {""}, {""},
+ #line 49 "locfile-kw.gperf"
+ {"toupper", tok_toupper, 0},
+-#line 68 "locfile-kw.gperf"
++#line 69 "locfile-kw.gperf"
+ {"position", tok_position, 0},
+ {""},
+ #line 40 "locfile-kw.gperf"
+@@ -380,196 +380,197 @@ locfile_hash (register const char *str, register size_t len)
+ {""},
+ #line 27 "locfile-kw.gperf"
+ {"comment_char", tok_comment_char, 0},
+-#line 88 "locfile-kw.gperf"
++#line 89 "locfile-kw.gperf"
+ {"positive_sign", tok_positive_sign, 0},
+ {""}, {""}, {""}, {""},
+-#line 61 "locfile-kw.gperf"
++#line 62 "locfile-kw.gperf"
+ {"symbol-equivalence", tok_symbol_equivalence, 0},
+ {""},
+-#line 102 "locfile-kw.gperf"
++#line 103 "locfile-kw.gperf"
+ {"int_p_sign_posn", tok_int_p_sign_posn, 0},
+-#line 175 "locfile-kw.gperf"
++#line 176 "locfile-kw.gperf"
+ {"country_car", tok_country_car, 0},
+ {""}, {""},
+-#line 104 "locfile-kw.gperf"
++#line 105 "locfile-kw.gperf"
+ {"duo_int_curr_symbol", tok_duo_int_curr_symbol, 0},
+ {""}, {""},
+-#line 135 "locfile-kw.gperf"
++#line 136 "locfile-kw.gperf"
+ {"d_t_fmt", tok_d_t_fmt, 0},
+ {""}, {""},
+-#line 116 "locfile-kw.gperf"
++#line 117 "locfile-kw.gperf"
+ {"duo_p_sign_posn", tok_duo_p_sign_posn, 0},
+-#line 187 "locfile-kw.gperf"
++#line 188 "locfile-kw.gperf"
+ {"measurement", tok_measurement, 0},
+-#line 176 "locfile-kw.gperf"
++#line 177 "locfile-kw.gperf"
+ {"country_isbn", tok_country_isbn, 0},
+ #line 37 "locfile-kw.gperf"
+ {"outdigit", tok_outdigit, 0},
+ {""}, {""},
+-#line 143 "locfile-kw.gperf"
++#line 144 "locfile-kw.gperf"
+ {"era_d_t_fmt", tok_era_d_t_fmt, 0},
+ {""}, {""}, {""},
+ #line 34 "locfile-kw.gperf"
+ {"lower", tok_lower, 0},
+-#line 183 "locfile-kw.gperf"
++#line 184 "locfile-kw.gperf"
+ {"tel_dom_fmt", tok_tel_dom_fmt, 0},
+-#line 171 "locfile-kw.gperf"
++#line 172 "locfile-kw.gperf"
+ {"country_post", tok_country_post, 0},
+-#line 148 "locfile-kw.gperf"
++#line 149 "locfile-kw.gperf"
+ {"cal_direction", tok_cal_direction, 0},
+- {""},
+-#line 139 "locfile-kw.gperf"
++#line 57 "locfile-kw.gperf"
++ {"codepoint_collation", tok_codepoint_collation, 0},
++#line 140 "locfile-kw.gperf"
+ {"t_fmt_ampm", tok_t_fmt_ampm, 0},
+-#line 91 "locfile-kw.gperf"
++#line 92 "locfile-kw.gperf"
+ {"frac_digits", tok_frac_digits, 0},
+ {""}, {""},
+-#line 177 "locfile-kw.gperf"
++#line 178 "locfile-kw.gperf"
+ {"lang_name", tok_lang_name, 0},
+-#line 90 "locfile-kw.gperf"
++#line 91 "locfile-kw.gperf"
+ {"int_frac_digits", tok_int_frac_digits, 0},
+ {""},
+-#line 121 "locfile-kw.gperf"
++#line 122 "locfile-kw.gperf"
+ {"uno_valid_to", tok_uno_valid_to, 0},
+-#line 126 "locfile-kw.gperf"
++#line 127 "locfile-kw.gperf"
+ {"decimal_point", tok_decimal_point, 0},
+ {""},
+-#line 133 "locfile-kw.gperf"
++#line 134 "locfile-kw.gperf"
+ {"abmon", tok_abmon, 0},
+ {""}, {""}, {""}, {""},
+-#line 107 "locfile-kw.gperf"
++#line 108 "locfile-kw.gperf"
+ {"duo_frac_digits", tok_duo_frac_digits, 0},
+-#line 182 "locfile-kw.gperf"
++#line 183 "locfile-kw.gperf"
+ {"tel_int_fmt", tok_tel_int_fmt, 0},
+-#line 123 "locfile-kw.gperf"
++#line 124 "locfile-kw.gperf"
+ {"duo_valid_to", tok_duo_valid_to, 0},
+-#line 146 "locfile-kw.gperf"
++#line 147 "locfile-kw.gperf"
+ {"first_weekday", tok_first_weekday, 0},
+ {""},
+-#line 130 "locfile-kw.gperf"
++#line 131 "locfile-kw.gperf"
+ {"abday", tok_abday, 0},
+ {""},
+-#line 200 "locfile-kw.gperf"
++#line 201 "locfile-kw.gperf"
+ {"abbreviation", tok_abbreviation, 0},
+-#line 147 "locfile-kw.gperf"
++#line 148 "locfile-kw.gperf"
+ {"first_workday", tok_first_workday, 0},
+ {""}, {""},
+-#line 97 "locfile-kw.gperf"
++#line 98 "locfile-kw.gperf"
+ {"n_sign_posn", tok_n_sign_posn, 0},
+ {""}, {""}, {""},
+-#line 145 "locfile-kw.gperf"
++#line 146 "locfile-kw.gperf"
+ {"alt_digits", tok_alt_digits, 0},
+ {""}, {""},
+-#line 128 "locfile-kw.gperf"
++#line 129 "locfile-kw.gperf"
+ {"grouping", tok_grouping, 0},
+ {""},
+ #line 45 "locfile-kw.gperf"
+ {"blank", tok_blank, 0},
+ {""}, {""},
+-#line 196 "locfile-kw.gperf"
++#line 197 "locfile-kw.gperf"
+ {"language", tok_language, 0},
+-#line 120 "locfile-kw.gperf"
++#line 121 "locfile-kw.gperf"
+ {"uno_valid_from", tok_uno_valid_from, 0},
+ {""},
+-#line 199 "locfile-kw.gperf"
++#line 200 "locfile-kw.gperf"
+ {"application", tok_application, 0},
+ {""},
+-#line 80 "locfile-kw.gperf"
++#line 81 "locfile-kw.gperf"
+ {"elifndef", tok_elifndef, 0},
+ {""}, {""}, {""}, {""}, {""},
+-#line 122 "locfile-kw.gperf"
++#line 123 "locfile-kw.gperf"
+ {"duo_valid_from", tok_duo_valid_from, 0},
+-#line 57 "locfile-kw.gperf"
++#line 58 "locfile-kw.gperf"
+ {"coll_weight_max", tok_coll_weight_max, 0},
+ {""},
+-#line 79 "locfile-kw.gperf"
++#line 80 "locfile-kw.gperf"
+ {"elifdef", tok_elifdef, 0},
+-#line 67 "locfile-kw.gperf"
++#line 68 "locfile-kw.gperf"
+ {"backward", tok_backward, 0},
+-#line 106 "locfile-kw.gperf"
++#line 107 "locfile-kw.gperf"
+ {"duo_int_frac_digits", tok_duo_int_frac_digits, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+-#line 96 "locfile-kw.gperf"
++#line 97 "locfile-kw.gperf"
+ {"p_sign_posn", tok_p_sign_posn, 0},
+ {""},
+-#line 203 "locfile-kw.gperf"
++#line 204 "locfile-kw.gperf"
+ {"category", tok_category, 0},
+ {""}, {""}, {""}, {""},
+-#line 134 "locfile-kw.gperf"
++#line 135 "locfile-kw.gperf"
+ {"mon", tok_mon, 0},
+ {""},
+-#line 124 "locfile-kw.gperf"
++#line 125 "locfile-kw.gperf"
+ {"conversion_rate", tok_conversion_rate, 0},
+ {""}, {""}, {""}, {""}, {""},
+-#line 63 "locfile-kw.gperf"
++#line 64 "locfile-kw.gperf"
+ {"order_start", tok_order_start, 0},
+ {""}, {""}, {""}, {""}, {""},
+-#line 178 "locfile-kw.gperf"
++#line 179 "locfile-kw.gperf"
+ {"lang_ab", tok_lang_ab, 0},
+-#line 180 "locfile-kw.gperf"
++#line 181 "locfile-kw.gperf"
+ {"lang_lib", tok_lang_lib, 0},
+ {""}, {""}, {""},
+-#line 192 "locfile-kw.gperf"
++#line 193 "locfile-kw.gperf"
+ {"contact", tok_contact, 0},
+ {""}, {""}, {""},
+-#line 173 "locfile-kw.gperf"
++#line 174 "locfile-kw.gperf"
+ {"country_ab3", tok_country_ab3, 0},
+ {""}, {""}, {""},
+-#line 193 "locfile-kw.gperf"
++#line 194 "locfile-kw.gperf"
+ {"email", tok_email, 0},
+-#line 172 "locfile-kw.gperf"
++#line 173 "locfile-kw.gperf"
+ {"country_ab2", tok_country_ab2, 0},
+ {""}, {""}, {""},
+ #line 55 "locfile-kw.gperf"
+ {"default_missing", tok_default_missing, 0},
+ {""}, {""},
+-#line 195 "locfile-kw.gperf"
++#line 196 "locfile-kw.gperf"
+ {"fax", tok_fax, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 174 "locfile-kw.gperf"
++#line 175 "locfile-kw.gperf"
+ {"country_num", tok_country_num, 0},
+ {""}, {""}, {""}, {""}, {""}, {""},
+ #line 51 "locfile-kw.gperf"
+ {"map", tok_map, 0},
+-#line 65 "locfile-kw.gperf"
++#line 66 "locfile-kw.gperf"
+ {"from", tok_from, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 86 "locfile-kw.gperf"
++#line 87 "locfile-kw.gperf"
+ {"mon_thousands_sep", tok_mon_thousands_sep, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""},
+-#line 81 "locfile-kw.gperf"
++#line 82 "locfile-kw.gperf"
+ {"endif", tok_endif, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 151 "locfile-kw.gperf"
++#line 152 "locfile-kw.gperf"
+ {"alt_mon", tok_alt_mon, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 76 "locfile-kw.gperf"
++#line 77 "locfile-kw.gperf"
+ {"undef", tok_undef, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 59 "locfile-kw.gperf"
++#line 60 "locfile-kw.gperf"
+ {"collating-element", tok_collating_element, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 152 "locfile-kw.gperf"
++#line 153 "locfile-kw.gperf"
+ {"ab_alt_mon", tok_ab_alt_mon, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 66 "locfile-kw.gperf"
++#line 67 "locfile-kw.gperf"
+ {"forward", tok_forward, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""},
+-#line 85 "locfile-kw.gperf"
++#line 86 "locfile-kw.gperf"
+ {"mon_decimal_point", tok_mon_decimal_point, 0},
+ {""}, {""},
+-#line 169 "locfile-kw.gperf"
++#line 170 "locfile-kw.gperf"
+ {"postal_fmt", tok_postal_fmt, 0},
+ {""}, {""}, {""}, {""}, {""},
+-#line 60 "locfile-kw.gperf"
++#line 61 "locfile-kw.gperf"
+ {"collating-symbol", tok_collating_symbol, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+@@ -582,15 +583,15 @@ locfile_hash (register const char *str, register size_t len)
+ #line 38 "locfile-kw.gperf"
+ {"alnum", tok_alnum, 0},
+ {""},
+-#line 87 "locfile-kw.gperf"
++#line 88 "locfile-kw.gperf"
+ {"mon_grouping", tok_mon_grouping, 0},
+ {""},
+-#line 179 "locfile-kw.gperf"
++#line 180 "locfile-kw.gperf"
+ {"lang_term", tok_lang_term, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""},
+-#line 77 "locfile-kw.gperf"
++#line 78 "locfile-kw.gperf"
+ {"ifdef", tok_ifdef, 0},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+@@ -598,7 +599,7 @@ locfile_hash (register const char *str, register size_t len)
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""}, {""},
+ {""}, {""}, {""}, {""},
+-#line 138 "locfile-kw.gperf"
++#line 139 "locfile-kw.gperf"
+ {"am_pm", tok_am_pm, 0}
+ };
+
+diff --git a/locale/programs/locfile-token.h b/locale/programs/locfile-token.h
+index abeff8a09e..0bf771c752 100644
+--- a/locale/programs/locfile-token.h
++++ b/locale/programs/locfile-token.h
+@@ -90,6 +90,7 @@ enum token_t
+ tok_translit_ignore,
+ tok_default_missing,
+ tok_lc_collate,
++ tok_codepoint_collation,
+ tok_coll_weight_max,
+ tok_section_symbol,
+ tok_collating_element,
+--
+2.28.0.windows.1
+
diff --git a/backport-Avoid-use-of-atoi-in-some-places-in-libc.patch b/backport-Avoid-use-of-atoi-in-some-places-in-libc.patch
new file mode 100644
index 0000000..c991622
--- /dev/null
+++ b/backport-Avoid-use-of-atoi-in-some-places-in-libc.patch
@@ -0,0 +1,120 @@
+From a3708cf6b0a5a68e2ed1ce3db28a03ed21d368d2 Mon Sep 17 00:00:00 2001
+From: Joseph Myers <joseph@codesourcery.com>
+Date: Mon, 19 Dec 2022 14:45:44 +0000
+Subject: [PATCH] Avoid use of atoi in some places in libc
+
+This patch is split out of
+<https://sourceware.org/pipermail/libc-alpha/2022-December/144122.html>.
+
+atoi has undefined behavior on out-of-range input, which makes it
+problematic to use anywhere in glibc that might be processing input
+out-of-range for atoi but not specified to produce undefined behavior
+for the function calling atoi. Change some uses of atoi to call
+strtol instead; this avoids the undefined behavior, though there is no
+guarantee that the overflow handling of strtol is really right in
+those places either. This also serves to avoid localplt test failures
+given an installed header redirection for strtol (which means that the
+call from the inline atoi implementation doesn't end up at a hidden
+alias from libc_hidden_proto).
+
+Certainly, the use of atoi is questionable in argp-help.c (shared with
+gnulib, so shouldn't depend on glibc implementation details, and
+processing user-provided input), and maybe also in argp-parse.c (I'm
+not sure what that code in argp-parse.c is meant to be used for). I
+also changed inet/rexec.c and resolv/res_init.c similarly to use
+strtol to avoid such localplt failures, although given those files (in
+those versions) are only used in glibc it's not problematic for them
+to rely on the specific behavior of glibc's atoi on out-of-range input
+(in the absence of compiler optimizations based on the undefined
+behavior) in the same way it's problematic for gnulib code to do so.
+
+There may be other uses of atoi (or atol or atoll), in any of glibc's
+installed code, for which it would also be appropriate to avoid the
+undefined behavior on out-of-range input; this patch only fixes the
+specific cases needed to avoid localplt failures.
+
+Tested for x86_64.
+---
+ argp/argp-help.c | 6 +++---
+ argp/argp-parse.c | 2 +-
+ inet/rexec.c | 2 +-
+ resolv/res_init.c | 6 +++---
+ 4 files changed, 8 insertions(+), 8 deletions(-)
+
+diff --git a/argp/argp-help.c b/argp/argp-help.c
+index 90a2795cef..f7f1134c80 100644
+--- a/argp/argp-help.c
++++ b/argp/argp-help.c
+@@ -210,9 +210,9 @@ fill_in_uparams (const struct argp_state *state)
+ }
+ else if (isdigit ((unsigned char) *arg))
+ {
+- val = atoi (arg);
+- while (isdigit ((unsigned char) *arg))
+- arg++;
++ char *ep;
++ val = strtol (arg, &ep, 10);
++ arg = ep;
+ SKIPWS (arg);
+ }
+
+diff --git a/argp/argp-parse.c b/argp/argp-parse.c
+index 68dc45417b..1533b43aaf 100644
+--- a/argp/argp-parse.c
++++ b/argp/argp-parse.c
+@@ -147,7 +147,7 @@ argp_default_parser (int key, char *arg, struct argp_state *state)
+ break;
+
+ case OPT_HANG:
+- _argp_hang = atoi (arg ? arg : "3600");
++ _argp_hang = arg ? strtol (arg, NULL, 10) : 3600;
+ while (_argp_hang-- > 0)
+ __sleep (1);
+ break;
+diff --git a/inet/rexec.c b/inet/rexec.c
+index 064e979d68..c647b7ac34 100644
+--- a/inet/rexec.c
++++ b/inet/rexec.c
+@@ -134,7 +134,7 @@ retry:
+ if (!getnameinfo(&sa2.sa, sa2len,
+ NULL, 0, servbuff, sizeof(servbuff),
+ NI_NUMERICSERV))
+- port = atoi(servbuff);
++ port = strtol(servbuff, NULL, 10);
+ (void) sprintf(num, "%u", port);
+ (void) __write(s, num, strlen(num)+1);
+ { socklen_t len = sizeof (from);
+diff --git a/resolv/res_init.c b/resolv/res_init.c
+index 2c0bea658e..61b958a437 100644
+--- a/resolv/res_init.c
++++ b/resolv/res_init.c
+@@ -654,7 +654,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
+ /* Search for and process individual options. */
+ if (!strncmp (cp, "ndots:", sizeof ("ndots:") - 1))
+ {
+- int i = atoi (cp + sizeof ("ndots:") - 1);
++ int i = strtol (cp + sizeof ("ndots:") - 1, NULL, 10);
+ if (i <= RES_MAXNDOTS)
+ parser->template.ndots = i;
+ else
+@@ -662,7 +662,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
+ }
+ else if (!strncmp (cp, "timeout:", sizeof ("timeout:") - 1))
+ {
+- int i = atoi (cp + sizeof ("timeout:") - 1);
++ int i = strtol (cp + sizeof ("timeout:") - 1, NULL, 10);
+ if (i <= RES_MAXRETRANS)
+ parser->template.retrans = i;
+ else
+@@ -670,7 +670,7 @@ res_setoptions (struct resolv_conf_parser *parser, const char *options)
+ }
+ else if (!strncmp (cp, "attempts:", sizeof ("attempts:") - 1))
+ {
+- int i = atoi (cp + sizeof ("attempts:") - 1);
++ int i = strtol (cp + sizeof ("attempts:") - 1, NULL, 10);
+ if (i <= RES_MAXRETRY)
+ parser->template.retry = i;
+ else
+--
+2.33.0
+
diff --git a/backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch b/backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch
new file mode 100644
index 0000000..c511b66
--- /dev/null
+++ b/backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch
@@ -0,0 +1,146 @@
+From 4cc79c217744743077bf7a0ec5e0a4318f1e6641 Mon Sep 17 00:00:00 2001
+From: Nikita Popov <npv1310@gmail.com>
+Date: Thu, 12 Aug 2021 16:09:50 +0530
+Subject: [PATCH] librt: add test (bug 28213)
+
+This test implements following logic:
+1) Create POSIX message queue.
+ Register a notification with mq_notify (using NULL attributes).
+ Then immediately unregister the notification with mq_notify.
+ Helper thread in a vulnerable version of glibc
+ should cause NULL pointer dereference after these steps.
+2) Once again, register the same notification.
+ Try to send a dummy message.
+ Test is considered successfulif the dummy message
+ is successfully received by the callback function.
+
+Signed-off-by: Nikita Popov <npv1310@gmail.com>
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ rt/Makefile | 1 +
+ rt/tst-bz28213.c | 101 +++++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 102 insertions(+)
+ create mode 100644 rt/tst-bz28213.c
+
+diff --git a/rt/Makefile b/rt/Makefile
+index 113cea03a5..910e775995 100644
+--- a/rt/Makefile
++++ b/rt/Makefile
+@@ -74,6 +74,7 @@ tests := tst-shm tst-timer tst-timer2 \
+ tst-aio7 tst-aio8 tst-aio9 tst-aio10 \
+ tst-mqueue1 tst-mqueue2 tst-mqueue3 tst-mqueue4 \
+ tst-mqueue5 tst-mqueue6 tst-mqueue7 tst-mqueue8 tst-mqueue9 \
++ tst-bz28213 \
+ tst-timer3 tst-timer4 tst-timer5 \
+ tst-cpuclock2 tst-cputimer1 tst-cputimer2 tst-cputimer3 \
+ tst-shm-cancel \
+diff --git a/rt/tst-bz28213.c b/rt/tst-bz28213.c
+new file mode 100644
+index 0000000000..0c096b5a0a
+--- /dev/null
++++ b/rt/tst-bz28213.c
+@@ -0,0 +1,101 @@
++/* Bug 28213: test for NULL pointer dereference in mq_notify.
++ Copyright (C) The GNU Toolchain Authors.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++#include <fcntl.h>
++#include <unistd.h>
++#include <mqueue.h>
++#include <signal.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++
++static mqd_t m = -1;
++static const char msg[] = "hello";
++
++static void
++check_bz28213_cb (union sigval sv)
++{
++ char buf[sizeof (msg)];
++
++ (void) sv;
++
++ TEST_VERIFY_EXIT ((size_t) mq_receive (m, buf, sizeof (buf), NULL)
++ == sizeof (buf));
++ TEST_VERIFY_EXIT (memcmp (buf, msg, sizeof (buf)) == 0);
++
++ exit (0);
++}
++
++static void
++check_bz28213 (void)
++{
++ struct sigevent sev;
++
++ memset (&sev, '\0', sizeof (sev));
++ sev.sigev_notify = SIGEV_THREAD;
++ sev.sigev_notify_function = check_bz28213_cb;
++
++ /* Step 1: Register & unregister notifier.
++ Helper thread should receive NOTIFY_REMOVED notification.
++ In a vulnerable version of glibc, NULL pointer dereference follows. */
++ TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
++ TEST_VERIFY_EXIT (mq_notify (m, NULL) == 0);
++
++ /* Step 2: Once again, register notification.
++ Try to send one message.
++ Test is considered successful, if the callback does exit (0). */
++ TEST_VERIFY_EXIT (mq_notify (m, &sev) == 0);
++ TEST_VERIFY_EXIT (mq_send (m, msg, sizeof (msg), 1) == 0);
++
++ /* Wait... */
++ pause ();
++}
++
++static int
++do_test (void)
++{
++ static const char m_name[] = "/bz28213_queue";
++ struct mq_attr m_attr;
++
++ memset (&m_attr, '\0', sizeof (m_attr));
++ m_attr.mq_maxmsg = 1;
++ m_attr.mq_msgsize = sizeof (msg);
++
++ m = mq_open (m_name,
++ O_RDWR | O_CREAT | O_EXCL,
++ 0600,
++ &m_attr);
++
++ if (m < 0)
++ {
++ if (errno == ENOSYS)
++ FAIL_UNSUPPORTED ("POSIX message queues are not implemented\n");
++ FAIL_EXIT1 ("Failed to create POSIX message queue: %m\n");
++ }
++
++ TEST_VERIFY_EXIT (mq_unlink (m_name) == 0);
++
++ check_bz28213 ();
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.27.0
+
diff --git a/backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch b/backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch
new file mode 100644
index 0000000..3dca8cc
--- /dev/null
+++ b/backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch
@@ -0,0 +1,39 @@
+From b805aebd42364fe696e417808a700fdb9800c9e8 Mon Sep 17 00:00:00 2001
+From: Nikita Popov <npv1310@gmail.com>
+Date: Mon, 9 Aug 2021 20:17:34 +0530
+Subject: [PATCH] librt: fix NULL pointer dereference (bug 28213)
+
+Helper thread frees copied attribute on NOTIFY_REMOVED message
+received from the OS kernel. Unfortunately, it fails to check whether
+copied attribute actually exists (data.attr != NULL). This worked
+earlier because free() checks passed pointer before actually
+attempting to release corresponding memory. But
+__pthread_attr_destroy assumes pointer is not NULL.
+
+So passing NULL pointer to __pthread_attr_destroy will result in
+segmentation fault. This scenario is possible if
+notification->sigev_notify_attributes == NULL (which means default
+thread attributes should be used).
+
+Signed-off-by: Nikita Popov <npv1310@gmail.com>
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ sysdeps/unix/sysv/linux/mq_notify.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/mq_notify.c b/sysdeps/unix/sysv/linux/mq_notify.c
+index 9799dcdaa4..eccae2e4c6 100644
+--- a/sysdeps/unix/sysv/linux/mq_notify.c
++++ b/sysdeps/unix/sysv/linux/mq_notify.c
+@@ -131,7 +131,7 @@ helper_thread (void *arg)
+ to wait until it is done with it. */
+ (void) __pthread_barrier_wait (&notify_barrier);
+ }
+- else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED)
++ else if (data.raw[NOTIFY_COOKIE_LEN - 1] == NOTIFY_REMOVED && data.attr != NULL)
+ {
+ /* The only state we keep is the copy of the thread attributes. */
+ __pthread_attr_destroy (data.attr);
+--
+2.27.0
+
diff --git a/backport-CVE-2023-4806.patch b/backport-CVE-2023-4806.patch
new file mode 100644
index 0000000..acac716
--- /dev/null
+++ b/backport-CVE-2023-4806.patch
@@ -0,0 +1,149 @@
+From 973fe93a5675c42798b2161c6f29c01b0e243994 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Fri, 15 Sep 2023 13:51:12 -0400
+Subject: [PATCH] getaddrinfo: Fix use after free in getcanonname
+ (CVE-2023-4806)
+
+When an NSS plugin only implements the _gethostbyname2_r and
+_getcanonname_r callbacks, getaddrinfo could use memory that was freed
+during tmpbuf resizing, through h_name in a previous query response.
+
+The backing store for res->at->name when doing a query with
+gethostbyname3_r or gethostbyname2_r is tmpbuf, which is reallocated in
+gethosts during the query. For AF_INET6 lookup with AI_ALL |
+AI_V4MAPPED, gethosts gets called twice, once for a v6 lookup and second
+for a v4 lookup. In this case, if the first call reallocates tmpbuf
+enough number of times, resulting in a malloc, th->h_name (that
+res->at->name refers to) ends up on a heap allocated storage in tmpbuf.
+Now if the second call to gethosts also causes the plugin callback to
+return NSS_STATUS_TRYAGAIN, tmpbuf will get freed, resulting in a UAF
+reference in res->at->name. This then gets dereferenced in the
+getcanonname_r plugin call, resulting in the use after free.
+
+Fix this by copying h_name over and freeing it at the end. This
+resolves BZ #30843, which is assigned CVE-2023-4806.
+
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ sysdeps/posix/getaddrinfo.c | 36 +++++++++++++++++++++++++++++-------
+ 1 file changed, 29 insertions(+), 7 deletions(-)
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index 9f1cde27..07fbf441 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -106,6 +106,12 @@ struct gaih_servtuple
+ int port;
+ };
+
++struct gaih_result
++{
++ char *h_name;
++ bool malloc_h_name;
++};
++
+ static const struct gaih_servtuple nullserv;
+
+
+@@ -197,7 +203,8 @@ static bool
+ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
+ int family,
+ struct hostent *h,
+- struct gaih_addrtuple **result)
++ struct gaih_addrtuple **result,
++ struct gaih_result *res)
+ {
+ while (*result)
+ result = &(*result)->next;
+@@ -216,6 +223,16 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
+ if (array == NULL)
+ return false;
+
++ /* Duplicate h_name because it may get reclaimed when the underlying storage
++ is freed. */
++ if (res->h_name == NULL)
++ {
++ res->h_name = __strdup (h->h_name);
++ res->malloc_h_name = true;
++ if (res->h_name == NULL)
++ return false;
++ }
++
+ for (size_t i = 0; i < count; ++i)
+ {
+ if (family == AF_INET && req->ai_family == AF_INET6)
+@@ -232,7 +249,6 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
+ }
+ array[i].next = array + i + 1;
+ }
+- array[0].name = h->h_name;
+ array[count - 1].next = NULL;
+
+ *result = array;
+@@ -275,7 +291,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
+ } \
+ else if (status == NSS_STATUS_SUCCESS) \
+ { \
+- if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem)) \
++ if (!convert_hostent_to_gaih_addrtuple (req, _family, &th, &addrmem, &res)) \
+ { \
+ __resolv_context_put (res_ctx); \
+ result = -EAI_SYSTEM; \
+@@ -307,14 +323,14 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
+ memory allocation failure. The returned string is allocated on the
+ heap; the caller has to free it. */
+ static char *
+-getcanonname (nss_action_list nip, struct gaih_addrtuple *at, const char *name)
++getcanonname (nss_action_list nip, const char *hname, const char *name)
+ {
+ nss_getcanonname_r *cfct = __nss_lookup_function (nip, "getcanonname_r");
+ char *s = (char *) name;
+ if (cfct != NULL)
+ {
+ char buf[256];
+- if (DL_CALL_FCT (cfct, (at->name ?: name, buf, sizeof (buf),
++ if (DL_CALL_FCT (cfct, (hname ?: name, buf, sizeof (buf),
+ &s, &errno, &h_errno)) != NSS_STATUS_SUCCESS)
+ /* If the canonical name cannot be determined, use the passed
+ string. */
+@@ -335,6 +351,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ const char *canon = NULL;
+ const char *orig_name = name;
+
++ struct gaih_result res = {0};
++
+ /* Reserve stack memory for the scratch buffer in the getaddrinfo
+ function. */
+ size_t alloca_used = sizeof (struct scratch_buffer);
+@@ -574,7 +592,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ {
+ /* We found data, convert it. */
+ if (!convert_hostent_to_gaih_addrtuple
+- (req, AF_INET, h, &addrmem))
++ (req, AF_INET, h, &addrmem, &res))
+ {
+ result = -EAI_MEMORY;
+ goto free_and_return;
+@@ -858,7 +876,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ if ((req->ai_flags & AI_CANONNAME) != 0
+ && canon == NULL)
+ {
+- canonbuf = getcanonname (nip, at, name);
++ canonbuf = getcanonname (nip, res.h_name, name);
+ if (canonbuf == NULL)
+ {
+ __resolv_context_put (res_ctx);
+@@ -1101,6 +1119,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ free (addrmem);
+ free (canonbuf);
+
++ if (res.malloc_h_name){
++ free (res.h_name);
++ }
++
+ return result;
+ }
+
+--
+2.33.0
+
diff --git a/backport-CVE-2023-4813.patch b/backport-CVE-2023-4813.patch
new file mode 100644
index 0000000..d41c2be
--- /dev/null
+++ b/backport-CVE-2023-4813.patch
@@ -0,0 +1,285 @@
+From 228cdb00a045ae3b68a91b35c7548bab6029446e Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Thu, 17 Mar 2022 11:44:34 +0530
+Subject: [PATCH] Simplify allocations and fix merge and continue actions [BZ
+ #28931]
+
+Allocations for address tuples is currently a bit confusing because of
+the pointer chasing through PAT, making it hard to observe the sequence
+in which allocations have been made. Narrow scope of the pointer
+chasing through PAT so that it is only used where necessary.
+
+This also tightens actions behaviour with the hosts database in
+getaddrinfo to comply with the manual text. The "continue" action
+discards previous results and the "merge" action results in an immedate
+lookup failure. Consequently, chaining of allocations across modules is
+no longer necessary, thus opening up cleanup opportunities.
+
+A test has been added that checks some combinations to ensure that they
+work correctly.
+
+Resolves: BZ #28931
+
+---
+ sysdeps/posix/getaddrinfo.c | 143 +++++++++++++++++++++++-------------
+ 1 file changed, 91 insertions(+), 52 deletions(-)
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index 9f1cde27..702d8a50 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -458,11 +458,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
+
+ if (name != NULL)
+ {
+- at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
+- at->family = AF_UNSPEC;
+- at->scopeid = 0;
+- at->next = NULL;
+-
+ if (req->ai_flags & AI_IDN)
+ {
+ char *out;
+@@ -473,13 +468,21 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ malloc_name = true;
+ }
+
+- if (__inet_aton_exact (name, (struct in_addr *) at->addr) != 0)
++ uint32_t addr[4];
++ if (__inet_aton_exact (name, (struct in_addr *) addr) != 0)
+ {
++ at = alloca_account (sizeof (struct gaih_addrtuple), alloca_used);
++ at->scopeid = 0;
++ at->next = NULL;
++
+ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET)
+- at->family = AF_INET;
++ {
++ memcpy (at->addr, addr, sizeof (at->addr));
++ at->family = AF_INET;
++ }
+ else if (req->ai_family == AF_INET6 && (req->ai_flags & AI_V4MAPPED))
+ {
+- at->addr[3] = at->addr[0];
++ at->addr[3] = addr[0];
+ at->addr[2] = htonl (0xffff);
+ at->addr[1] = 0;
+ at->addr[0] = 0;
+@@ -493,49 +496,62 @@ gaih_inet (const char *name, const struct gaih_service *service,
+
+ if (req->ai_flags & AI_CANONNAME)
+ canon = name;
++
++ goto process_list;
+ }
+- else if (at->family == AF_UNSPEC)
++
++ char *scope_delim = strchr (name, SCOPE_DELIMITER);
++ int e;
++
++ if (scope_delim == NULL)
++ e = inet_pton (AF_INET6, name, addr);
++ else
++ e = __inet_pton_length (AF_INET6, name, scope_delim - name, addr);
++
++ if (e > 0)
+ {
+- char *scope_delim = strchr (name, SCOPE_DELIMITER);
+- int e;
+- if (scope_delim == NULL)
+- e = inet_pton (AF_INET6, name, at->addr);
++ at = alloca_account (sizeof (struct gaih_addrtuple),
++ alloca_used);
++ at->scopeid = 0;
++ at->next = NULL;
++
++ if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
++ {
++ memcpy (at->addr, addr, sizeof (at->addr));
++ at->family = AF_INET6;
++ }
++ else if (req->ai_family == AF_INET
++ && IN6_IS_ADDR_V4MAPPED (addr))
++ {
++ at->addr[0] = addr[3];
++ at->addr[1] = addr[1];
++ at->addr[2] = addr[2];
++ at->addr[3] = addr[3];
++ at->family = AF_INET;
++ }
+ else
+- e = __inet_pton_length (AF_INET6, name, scope_delim - name,
+- at->addr);
+- if (e > 0)
+ {
+- if (req->ai_family == AF_UNSPEC || req->ai_family == AF_INET6)
+- at->family = AF_INET6;
+- else if (req->ai_family == AF_INET
+- && IN6_IS_ADDR_V4MAPPED (at->addr))
+- {
+- at->addr[0] = at->addr[3];
+- at->family = AF_INET;
+- }
+- else
+- {
+- result = -EAI_ADDRFAMILY;
+- goto free_and_return;
+- }
+-
+- if (scope_delim != NULL
+- && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
+- scope_delim + 1,
+- &at->scopeid) != 0)
+- {
+- result = -EAI_NONAME;
+- goto free_and_return;
+- }
++ result = -EAI_ADDRFAMILY;
++ goto free_and_return;
++ }
+
+- if (req->ai_flags & AI_CANONNAME)
+- canon = name;
++ if (scope_delim != NULL
++ && __inet6_scopeid_pton ((struct in6_addr *) at->addr,
++ scope_delim + 1,
++ &at->scopeid) != 0)
++ {
++ result = -EAI_NONAME;
++ goto free_and_return;
+ }
++
++ if (req->ai_flags & AI_CANONNAME)
++ canon = name;
++
++ goto process_list;
+ }
+
+- if (at->family == AF_UNSPEC && (req->ai_flags & AI_NUMERICHOST) == 0)
++ if ((req->ai_flags & AI_NUMERICHOST) == 0)
+ {
+- struct gaih_addrtuple **pat = &at;
+ int no_data = 0;
+ int no_inet6_data = 0;
+ nss_action_list nip;
+@@ -543,6 +559,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ enum nss_status status = NSS_STATUS_UNAVAIL;
+ int no_more;
+ struct resolv_context *res_ctx = NULL;
++ bool do_merge = false;
+
+ /* If we do not have to look for IPv6 addresses or the canonical
+ name, use the simple, old functions, which do not support
+@@ -579,7 +596,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ result = -EAI_MEMORY;
+ goto free_and_return;
+ }
+- *pat = addrmem;
++ at = addrmem;
+ }
+ else
+ {
+@@ -632,6 +649,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ }
+
+ struct gaih_addrtuple *addrfree = addrmem;
++ struct gaih_addrtuple **pat = &at;
++
+ for (int i = 0; i < air->naddrs; ++i)
+ {
+ socklen_t size = (air->family[i] == AF_INET
+@@ -695,12 +714,6 @@ gaih_inet (const char *name, const struct gaih_service *service,
+
+ free (air);
+
+- if (at->family == AF_UNSPEC)
+- {
+- result = -EAI_NONAME;
+- goto free_and_return;
+- }
+-
+ goto process_list;
+ }
+ else if (err == 0)
+@@ -732,6 +745,22 @@ gaih_inet (const char *name, const struct gaih_service *service,
+
+ while (!no_more)
+ {
++ /* Always start afresh; continue should discard previous results
++ and the hosts database does not support merge. */
++ at = NULL;
++ free (canonbuf);
++ free (addrmem);
++ canon = canonbuf = NULL;
++ addrmem = NULL;
++ got_ipv6 = false;
++
++ if (do_merge)
++ {
++ __set_h_errno (NETDB_INTERNAL);
++ __set_errno (EBUSY);
++ break;
++ }
++
+ no_data = 0;
+ nss_gethostbyname4_r *fct4 = NULL;
+
+@@ -744,12 +773,14 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ {
+ while (1)
+ {
+- status = DL_CALL_FCT (fct4, (name, pat,
++ status = DL_CALL_FCT (fct4, (name, &at,
+ tmpbuf->data, tmpbuf->length,
+ &errno, &h_errno,
+ NULL));
+ if (status == NSS_STATUS_SUCCESS)
+ break;
++ /* gethostbyname4_r may write into AT, so reset it. */
++ at = NULL;
+ if (status != NSS_STATUS_TRYAGAIN
+ || errno != ERANGE || h_errno != NETDB_INTERNAL)
+ {
+@@ -774,7 +805,9 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ no_data = 1;
+
+ if ((req->ai_flags & AI_CANONNAME) != 0 && canon == NULL)
+- canon = (*pat)->name;
++ canon = at->name;
++
++ struct gaih_addrtuple **pat = &at;
+
+ while (*pat != NULL)
+ {
+@@ -826,6 +859,8 @@ gaih_inet (const char *name, const struct gaih_service *service,
+
+ if (fct != NULL)
+ {
++ struct gaih_addrtuple **pat = &at;
++
+ if (req->ai_family == AF_INET6
+ || req->ai_family == AF_UNSPEC)
+ {
+@@ -899,6 +934,10 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ if (nss_next_action (nip, status) == NSS_ACTION_RETURN)
+ break;
+
++ /* The hosts database does not support MERGE. */
++ if (nss_next_action (nip, status) == NSS_ACTION_MERGE)
++ do_merge = true;
++
+ nip++;
+ if (nip->module == NULL)
+ no_more = -1;
+@@ -930,7 +969,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ }
+
+ process_list:
+- if (at->family == AF_UNSPEC)
++ if (at == NULL)
+ {
+ result = -EAI_NONAME;
+ goto free_and_return;
+--
+2.33.0
+
diff --git a/backport-CVE-2023-4911.patch b/backport-CVE-2023-4911.patch
new file mode 100644
index 0000000..6acf3bc
--- /dev/null
+++ b/backport-CVE-2023-4911.patch
@@ -0,0 +1,158 @@
+From 50c547fc0c1667df486c4e5916993e4f6efeca37 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Sat, 7 Oct 2023 18:34:21 +0800
+Subject: [PATCH] tunables: Terminate if end of input is reached
+ (CVE-2023-4911)
+
+The string parsing routine may end up writing beyond bounds of tunestr
+if the input tunable string is malformed, of the form name=name=val.
+This gets processed twice, first as name=name=val and next as name=val,
+resulting in tunestr being name=name=val:name=val, thus overflowing
+tunestr.
+
+Terminate the parsing loop at the first instance itself so that tunestr
+does not overflow.
+
+This also fixes up tst-env-setuid-tunables to actually handle failures
+correct and add new tests to validate the fix for this CVE.
+
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ elf/dl-tunables.c | 17 ++++++++-------
+ elf/tst-env-setuid-tunables.c | 39 +++++++++++++++++++++++++++--------
+ 2 files changed, 40 insertions(+), 16 deletions(-)
+
+diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
+index 1666736b..42631d39 100644
+--- a/elf/dl-tunables.c
++++ b/elf/dl-tunables.c
+@@ -186,11 +186,7 @@ parse_tunables (char *tunestr, char *valstring)
+ /* If we reach the end of the string before getting a valid name-value
+ pair, bail out. */
+ if (p[len] == '\0')
+- {
+- if (__libc_enable_secure)
+- tunestr[off] = '\0';
+- return;
+- }
++ break;
+
+ /* We did not find a valid name-value pair before encountering the
+ colon. */
+@@ -250,9 +246,16 @@ parse_tunables (char *tunestr, char *valstring)
+ }
+ }
+
+- if (p[len] != '\0')
+- p += len + 1;
++ /* We reached the end while processing the tunable string. */
++ if (p[len] == '\0')
++ break;
++
++ p += len + 1;
+ }
++
++ /* Terminate tunestr before we leave. */
++ if (__libc_enable_secure)
++ tunestr[off] = '\0';
+ }
+ #endif
+
+diff --git a/elf/tst-env-setuid-tunables.c b/elf/tst-env-setuid-tunables.c
+index 05619c9a..8ddb1ecd 100644
+--- a/elf/tst-env-setuid-tunables.c
++++ b/elf/tst-env-setuid-tunables.c
+@@ -52,6 +52,8 @@ const char *teststrings[] =
+ "glibc.malloc.perturb=0x800:not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
+ "glibc.not_valid.check=2:glibc.malloc.mmap_threshold=4096",
+ "not_valid.malloc.check=2:glibc.malloc.mmap_threshold=4096",
++ "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
++ "glibc.malloc.check=2",
+ "glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096:glibc.malloc.check=2",
+ "glibc.malloc.check=4:glibc.malloc.garbage=2:glibc.maoc.mmap_threshold=4096",
+ ":glibc.malloc.garbage=2:glibc.malloc.check=1",
+@@ -70,6 +72,8 @@ const char *resultstrings[] =
+ "glibc.malloc.perturb=0x800:glibc.malloc.mmap_threshold=4096",
+ "glibc.malloc.mmap_threshold=4096",
+ "glibc.malloc.mmap_threshold=4096",
++ "glibc.malloc.mmap_threshold=glibc.malloc.mmap_threshold=4096",
++ "",
+ "",
+ "",
+ "",
+@@ -83,13 +87,20 @@ test_child (int off)
+ {
+ const char *val = getenv ("GLIBC_TUNABLES");
+
++ printf (" [%d] GLIBC_TUNABLES is %s\n", off, val);
++ fflush (stdout);
+ #if HAVE_TUNABLES
+ if (val != NULL && strcmp (val, resultstrings[off]) == 0)
+ return 0;
+
+ if (val != NULL)
+- printf ("[%d] Unexpected GLIBC_TUNABLES VALUE %s\n", off, val);
+-
++ printf (" [%d] Unexpected GLIBC_TUNABLES VALUE %s, expected %s\n",
++ off, val, resultstrings[off]);
++ else
++ printf (" [%d] GLIBC_TUNABLES environment variable absent\n", off);
++
++ fflush (stdout);
++
+ return 1;
+ #else
+ if (val != NULL)
+@@ -117,21 +128,26 @@ do_test (int argc, char **argv)
+ if (ret != 0)
+ exit (1);
+
+- exit (EXIT_SUCCESS);
++ /* Special return code to make sure that the child executed all the way
++ through. */
++ exit (42);
+ }
+ else
+ {
+- int ret = 0;
+-
+ /* Spawn tests. */
+ for (int i = 0; i < array_length (teststrings); i++)
+ {
+ char buf[INT_BUFSIZE_BOUND (int)];
+
+- printf ("Spawned test for %s (%d)\n", teststrings[i], i);
++ printf ("[%d] Spawned test for %s\n", i, teststrings[i]);
+ snprintf (buf, sizeof (buf), "%d\n", i);
++ fflush (stdout);
+ if (setenv ("GLIBC_TUNABLES", teststrings[i], 1) != 0)
+- exit (1);
++ {
++ printf (" [%d] Failed to set GLIBC_TUNABLES: %m", i);
++ support_record_failure ();
++ continue;
++ }
+
+ int status = support_capture_subprogram_self_sgid (buf);
+
+@@ -139,9 +155,14 @@ do_test (int argc, char **argv)
+ if (WEXITSTATUS (status) == EXIT_UNSUPPORTED)
+ return EXIT_UNSUPPORTED;
+
+- ret |= status;
++ if (WEXITSTATUS (status) != 42)
++ {
++ printf (" [%d] child failed with status %d\n", i,
++ WEXITSTATUS (status));
++ support_record_failure ();
++ }
+ }
+- return ret;
++ return 0;
+ }
+ }
+
+--
+2.27.0
+
diff --git a/backport-CVE-2023-5156.patch b/backport-CVE-2023-5156.patch
new file mode 100644
index 0000000..8702518
--- /dev/null
+++ b/backport-CVE-2023-5156.patch
@@ -0,0 +1,29 @@
+From ec6b95c3303c700eb89eebeda2d7264cc184a796 Mon Sep 17 00:00:00 2001
+From: Romain Geissler <romain.geissler@amadeus.com>
+Date: Mon, 25 Sep 2023 01:21:51 +0100
+Subject: [PATCH] Fix leak in getaddrinfo introduced by the fix for
+ CVE-2023-4806 [BZ #30843]
+
+This patch fixes a very recently added leak in getaddrinfo.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+---
+ sysdeps/posix/getaddrinfo.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index 614ee39f..b3321913 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -1160,6 +1160,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+
+ if (res.malloc_h_name){
+ free (res.h_name);
++ res.malloc_h_name = false;
+ }
+
+ return result;
+--
+2.23.0
+
diff --git a/backport-CVE-2024-33599-nscd-Stack-based-buffer-overflow-in-netgroup-cache.patch b/backport-CVE-2024-33599-nscd-Stack-based-buffer-overflow-in-netgroup-cache.patch
new file mode 100644
index 0000000..11b04f6
--- /dev/null
+++ b/backport-CVE-2024-33599-nscd-Stack-based-buffer-overflow-in-netgroup-cache.patch
@@ -0,0 +1,41 @@
+From 87801a8fd06db1d654eea3e4f7626ff476a9bdaa Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 25 Apr 2024 15:00:45 +0200
+Subject: [PATCH] CVE-2024-33599: nscd: Stack-based buffer overflow in netgroup
+ cache (bug 31677)
+
+Using alloca matches what other caches do. The request length is
+bounded by MAXKEYLEN.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=patch;h=87801a8fd06db1d654eea3e4f7626ff476a9bdaa
+
+---
+ nscd/netgroupcache.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index 2f71bf29..f13a11b4 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -503,12 +503,13 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+ = (struct indataset *) mempool_alloc (db,
+ sizeof (*dataset) + req->key_len,
+ 1);
+- struct indataset dataset_mem;
+ bool cacheable = true;
+ if (__glibc_unlikely (dataset == NULL))
+ {
+ cacheable = false;
+- dataset = &dataset_mem;
++ /* The alloca is safe because nscd_run_worker verfies that
++ key_len is not larger than MAXKEYLEN. */
++ dataset = alloca (sizeof (*dataset) + req->key_len);
+ }
+
+ datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
+--
+2.33.0
+
diff --git a/backport-CVE-2024-33600-nscd-Avoid-null-pointer-crash-after-not-found-response.patch b/backport-CVE-2024-33600-nscd-Avoid-null-pointer-crash-after-not-found-response.patch
new file mode 100644
index 0000000..d9d6bb3
--- /dev/null
+++ b/backport-CVE-2024-33600-nscd-Avoid-null-pointer-crash-after-not-found-response.patch
@@ -0,0 +1,63 @@
+From b048a482f088e53144d26a61c390bed0210f49f2 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 25 Apr 2024 15:01:07 +0200
+Subject: [PATCH] CVE-2024-33600: nscd: Avoid null pointer crashes after
+ notfound response (bug 31678)
+
+The addgetnetgrentX call in addinnetgrX may have failed to produce
+a result, so the result variable in addinnetgrX can be NULL.
+Use db->negtimeout as the fallback value if there is no result data;
+the timeout is also overwritten below.
+
+Also avoid sending a second not-found response. (The client
+disconnects after receiving the first response, so the data stream did
+not go out of sync even without this fix.) It is still beneficial to
+add the negative response to the mapping, so that the client can get
+it from there in the future, instead of going through the socket.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=patch;h=b048a482f088e53144d26a61c390bed0210f49f2
+
+---
+ nscd/netgroupcache.c | 11 +++++++----
+ 1 file changed, 7 insertions(+), 4 deletions(-)
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index 08668e96..5ed16f87 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -512,14 +512,15 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+
+ datahead_init_pos (&dataset->head, sizeof (*dataset) + req->key_len,
+ sizeof (innetgroup_response_header),
+- he == NULL ? 0 : dh->nreloads + 1, result->head.ttl);
++ he == NULL ? 0 : dh->nreloads + 1,
++ result == NULL ? db->negtimeout : result->head.ttl);
+ /* Set the notfound status and timeout based on the result from
+ getnetgrent. */
+- dataset->head.notfound = result->head.notfound;
++ dataset->head.notfound = result == NULL || result->head.notfound;
+ dataset->head.timeout = timeout;
+
+ dataset->resp.version = NSCD_VERSION;
+- dataset->resp.found = result->resp.found;
++ dataset->resp.found = result != NULL && result->resp.found;
+ /* Until we find a matching entry the result is 0. */
+ dataset->resp.result = 0;
+
+@@ -567,7 +568,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+ goto out;
+ }
+
+- if (he == NULL)
++ /* addgetnetgrentX may have already sent a notfound response. Do
++ not send another one. */
++ if (he == NULL && dataset->resp.found)
+ {
+ /* We write the dataset before inserting it to the database
+ since while inserting this thread might block and so would
+--
+2.33.0
+
diff --git a/backport-CVE-2024-33600-nscd-Do-not-send-missing-not-found-response.patch b/backport-CVE-2024-33600-nscd-Do-not-send-missing-not-found-response.patch
new file mode 100644
index 0000000..0937c54
--- /dev/null
+++ b/backport-CVE-2024-33600-nscd-Do-not-send-missing-not-found-response.patch
@@ -0,0 +1,62 @@
+From 7835b00dbce53c3c87bbbb1754a95fb5e58187aa Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 25 Apr 2024 15:01:07 +0200
+Subject: [PATCH] CVE-2024-33600: nscd: Do not send missing not-found response
+ in addgetnetgrentX (bug 31678)
+
+If we failed to add a not-found response to the cache, the dataset
+point can be null, resulting in a null pointer dereference.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=patch;h=7835b00dbce53c3c87bbbb1754a95fb5e58187aa
+
+---
+ nscd/netgroupcache.c | 14 ++++++--------
+ 1 file changed, 6 insertions(+), 8 deletions(-)
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index f13a11b4..08668e96 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -148,7 +148,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ /* No such service. */
+ cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
+ &key_copy);
+- goto writeout;
++ goto maybe_cache_add;
+ }
+
+ memset (&data, '\0', sizeof (data));
+@@ -349,7 +349,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ {
+ cacheable = do_notfound (db, fd, req, key, &dataset, &total, &timeout,
+ &key_copy);
+- goto writeout;
++ goto maybe_cache_add;
+ }
+
+ total = buffilled;
+@@ -411,14 +411,12 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ }
+
+ if (he == NULL && fd != -1)
+- {
+- /* We write the dataset before inserting it to the database
+- since while inserting this thread might block and so would
+- unnecessarily let the receiver wait. */
+- writeout:
++ /* We write the dataset before inserting it to the database since
++ while inserting this thread might block and so would
++ unnecessarily let the receiver wait. */
+ writeall (fd, &dataset->resp, dataset->head.recsize);
+- }
+
++ maybe_cache_add:
+ if (cacheable)
+ {
+ /* If necessary, we also propagate the data to disk. */
+--
+2.33.0
+
diff --git a/backport-CVE-2024-33601-CVE-2024-33602-nscd-Use-two-buffer-in-addgetnetgrentX.patch b/backport-CVE-2024-33601-CVE-2024-33602-nscd-Use-two-buffer-in-addgetnetgrentX.patch
new file mode 100644
index 0000000..c166d7e
--- /dev/null
+++ b/backport-CVE-2024-33601-CVE-2024-33602-nscd-Use-two-buffer-in-addgetnetgrentX.patch
@@ -0,0 +1,393 @@
+From c04a21e050d64a1193a6daab872bca2528bda44b Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 25 Apr 2024 15:01:07 +0200
+Subject: [PATCH] CVE-2024-33601, CVE-2024-33602: nscd: netgroup: Use two
+ buffers in addgetnetgrentX (bug 31680)
+
+This avoids potential memory corruption when the underlying NSS
+callback function does not use the buffer space to store all strings
+(e.g., for constant strings).
+
+Instead of custom buffer management, two scratch buffers are used.
+This increases stack usage somewhat.
+
+Scratch buffer allocation failure is handled by return -1
+(an invalid timeout value) instead of terminating the process.
+This fixes bug 31679.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=patch;h=c04a21e050d64a1193a6daab872bca2528bda44b
+
+---
+ nscd/netgroupcache.c | 219 ++++++++++++++++++++++++-------------------
+ 1 file changed, 121 insertions(+), 98 deletions(-)
+
+diff --git a/nscd/netgroupcache.c b/nscd/netgroupcache.c
+index 5ed16f87..92c9cb36 100644
+--- a/nscd/netgroupcache.c
++++ b/nscd/netgroupcache.c
+@@ -24,6 +24,7 @@
+ #include <stdlib.h>
+ #include <unistd.h>
+ #include <sys/mman.h>
++#include <scratch_buffer.h>
+
+ #include "../inet/netgroup.h"
+ #include "nscd.h"
+@@ -66,6 +67,16 @@ struct dataset
+ char strdata[0];
+ };
+
++/* Send a notfound response to FD. Always returns -1 to indicate an
++ ephemeral error. */
++static time_t
++send_notfound (int fd)
++{
++ if (fd != -1)
++ TEMP_FAILURE_RETRY (send (fd, &notfound, sizeof (notfound), MSG_NOSIGNAL));
++ return -1;
++}
++
+ /* Sends a notfound message and prepares a notfound dataset to write to the
+ cache. Returns true if there was enough memory to allocate the dataset and
+ returns the dataset in DATASETP, total bytes to write in TOTALP and the
+@@ -84,8 +95,7 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
+ total = sizeof (notfound);
+ timeout = time (NULL) + db->negtimeout;
+
+- if (fd != -1)
+- TEMP_FAILURE_RETRY (send (fd, &notfound, total, MSG_NOSIGNAL));
++ send_notfound (fd);
+
+ dataset = mempool_alloc (db, sizeof (struct dataset) + req->key_len, 1);
+ /* If we cannot permanently store the result, so be it. */
+@@ -110,11 +120,78 @@ do_notfound (struct database_dyn *db, int fd, request_header *req,
+ return cacheable;
+ }
+
++struct addgetnetgrentX_scratch
++{
++ /* This is the result that the caller should use. It can be NULL,
++ point into buffer, or it can be in the cache. */
++ struct dataset *dataset;
++
++ struct scratch_buffer buffer;
++
++ /* Used internally in addgetnetgrentX as a staging area. */
++ struct scratch_buffer tmp;
++
++ /* Number of bytes in buffer that are actually used. */
++ size_t buffer_used;
++};
++
++static void
++addgetnetgrentX_scratch_init (struct addgetnetgrentX_scratch *scratch)
++{
++ scratch->dataset = NULL;
++ scratch_buffer_init (&scratch->buffer);
++ scratch_buffer_init (&scratch->tmp);
++
++ /* Reserve space for the header. */
++ scratch->buffer_used = sizeof (struct dataset);
++ static_assert (sizeof (struct dataset) < sizeof (scratch->tmp.__space),
++ "initial buffer space");
++ memset (scratch->tmp.data, 0, sizeof (struct dataset));
++}
++
++static void
++addgetnetgrentX_scratch_free (struct addgetnetgrentX_scratch *scratch)
++{
++ scratch_buffer_free (&scratch->buffer);
++ scratch_buffer_free (&scratch->tmp);
++}
++
++/* Copy LENGTH bytes from S into SCRATCH. Returns NULL if SCRATCH
++ could not be resized, otherwise a pointer to the copy. */
++static char *
++addgetnetgrentX_append_n (struct addgetnetgrentX_scratch *scratch,
++ const char *s, size_t length)
++{
++ while (true)
++ {
++ size_t remaining = scratch->buffer.length - scratch->buffer_used;
++ if (remaining >= length)
++ break;
++ if (!scratch_buffer_grow_preserve (&scratch->buffer))
++ return NULL;
++ }
++ char *copy = scratch->buffer.data + scratch->buffer_used;
++ memcpy (copy, s, length);
++ scratch->buffer_used += length;
++ return copy;
++}
++
++/* Copy S into SCRATCH, including its null terminator. Returns false
++ if SCRATCH could not be resized. */
++static bool
++addgetnetgrentX_append (struct addgetnetgrentX_scratch *scratch, const char *s)
++{
++ if (s == NULL)
++ s = "";
++ return addgetnetgrentX_append_n (scratch, s, strlen (s) + 1) != NULL;
++}
++
++/* Caller must initialize and free *SCRATCH. If the return value is
++ negative, this function has sent a notfound response. */
+ static time_t
+ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ const char *key, uid_t uid, struct hashentry *he,
+- struct datahead *dh, struct dataset **resultp,
+- void **tofreep)
++ struct datahead *dh, struct addgetnetgrentX_scratch *scratch)
+ {
+ if (__glibc_unlikely (debug_level > 0))
+ {
+@@ -133,14 +210,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+
+ char *key_copy = NULL;
+ struct __netgrent data;
+- size_t buflen = MAX (1024, sizeof (*dataset) + req->key_len);
+- size_t buffilled = sizeof (*dataset);
+- char *buffer = NULL;
+ size_t nentries = 0;
+ size_t group_len = strlen (key) + 1;
+ struct name_list *first_needed
+ = alloca (sizeof (struct name_list) + group_len);
+- *tofreep = NULL;
+
+ if (netgroup_database == NULL
+ && !__nss_database_get (nss_database_netgroup, &netgroup_database))
+@@ -152,8 +225,6 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ }
+
+ memset (&data, '\0', sizeof (data));
+- buffer = xmalloc (buflen);
+- *tofreep = buffer;
+ first_needed->next = first_needed;
+ memcpy (first_needed->name, key, group_len);
+ data.needed_groups = first_needed;
+@@ -196,8 +267,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ while (1)
+ {
+ int e;
+- status = getfct.f (&data, buffer + buffilled,
+- buflen - buffilled - req->key_len, &e);
++ status = getfct.f (&data, scratch->tmp.data,
++ scratch->tmp.length, &e);
+ if (status == NSS_STATUS_SUCCESS)
+ {
+ if (data.type == triple_val)
+@@ -205,68 +276,10 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ const char *nhost = data.val.triple.host;
+ const char *nuser = data.val.triple.user;
+ const char *ndomain = data.val.triple.domain;
+-
+- size_t hostlen = strlen (nhost ?: "") + 1;
+- size_t userlen = strlen (nuser ?: "") + 1;
+- size_t domainlen = strlen (ndomain ?: "") + 1;
+-
+- if (nhost == NULL || nuser == NULL || ndomain == NULL
+- || nhost > nuser || nuser > ndomain)
+- {
+- const char *last = nhost;
+- if (last == NULL
+- || (nuser != NULL && nuser > last))
+- last = nuser;
+- if (last == NULL
+- || (ndomain != NULL && ndomain > last))
+- last = ndomain;
+-
+- size_t bufused
+- = (last == NULL
+- ? buffilled
+- : last + strlen (last) + 1 - buffer);
+-
+- /* We have to make temporary copies. */
+- size_t needed = hostlen + userlen + domainlen;
+-
+- if (buflen - req->key_len - bufused < needed)
+- {
+- buflen += MAX (buflen, 2 * needed);
+- /* Save offset in the old buffer. We don't
+- bother with the NULL check here since
+- we'll do that later anyway. */
+- size_t nhostdiff = nhost - buffer;
+- size_t nuserdiff = nuser - buffer;
+- size_t ndomaindiff = ndomain - buffer;
+-
+- char *newbuf = xrealloc (buffer, buflen);
+- /* Fix up the triplet pointers into the new
+- buffer. */
+- nhost = (nhost ? newbuf + nhostdiff
+- : NULL);
+- nuser = (nuser ? newbuf + nuserdiff
+- : NULL);
+- ndomain = (ndomain ? newbuf + ndomaindiff
+- : NULL);
+- *tofreep = buffer = newbuf;
+- }
+-
+- nhost = memcpy (buffer + bufused,
+- nhost ?: "", hostlen);
+- nuser = memcpy ((char *) nhost + hostlen,
+- nuser ?: "", userlen);
+- ndomain = memcpy ((char *) nuser + userlen,
+- ndomain ?: "", domainlen);
+- }
+-
+- char *wp = buffer + buffilled;
+- wp = memmove (wp, nhost ?: "", hostlen);
+- wp += hostlen;
+- wp = memmove (wp, nuser ?: "", userlen);
+- wp += userlen;
+- wp = memmove (wp, ndomain ?: "", domainlen);
+- wp += domainlen;
+- buffilled = wp - buffer;
++ if (!(addgetnetgrentX_append (scratch, nhost)
++ && addgetnetgrentX_append (scratch, nuser)
++ && addgetnetgrentX_append (scratch, ndomain)))
++ return send_notfound (fd);
+ ++nentries;
+ }
+ else
+@@ -318,8 +331,8 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ }
+ else if (status == NSS_STATUS_TRYAGAIN && e == ERANGE)
+ {
+- buflen *= 2;
+- *tofreep = buffer = xrealloc (buffer, buflen);
++ if (!scratch_buffer_grow (&scratch->tmp))
++ return send_notfound (fd);
+ }
+ else if (status == NSS_STATUS_RETURN
+ || status == NSS_STATUS_NOTFOUND
+@@ -352,10 +365,17 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ goto maybe_cache_add;
+ }
+
+- total = buffilled;
++ /* Capture the result size without the key appended. */
++ total = scratch->buffer_used;
++
++ /* Make a copy of the key. The scratch buffer must not move after
++ this point. */
++ key_copy = addgetnetgrentX_append_n (scratch, key, req->key_len);
++ if (key_copy == NULL)
++ return send_notfound (fd);
+
+ /* Fill in the dataset. */
+- dataset = (struct dataset *) buffer;
++ dataset = scratch->buffer.data;
+ timeout = datahead_init_pos (&dataset->head, total + req->key_len,
+ total - offsetof (struct dataset, resp),
+ he == NULL ? 0 : dh->nreloads + 1,
+@@ -364,11 +384,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ dataset->resp.version = NSCD_VERSION;
+ dataset->resp.found = 1;
+ dataset->resp.nresults = nentries;
+- dataset->resp.result_len = buffilled - sizeof (*dataset);
+-
+- assert (buflen - buffilled >= req->key_len);
+- key_copy = memcpy (buffer + buffilled, key, req->key_len);
+- buffilled += req->key_len;
++ dataset->resp.result_len = total - sizeof (*dataset);
+
+ /* Now we can determine whether on refill we have to create a new
+ record or not. */
+@@ -399,7 +415,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ if (__glibc_likely (newp != NULL))
+ {
+ /* Adjust pointer into the memory block. */
+- key_copy = (char *) newp + (key_copy - buffer);
++ key_copy = (char *) newp + (key_copy - (char *) dataset);
+
+ dataset = memcpy (newp, dataset, total + req->key_len);
+ cacheable = true;
+@@ -440,7 +456,7 @@ addgetnetgrentX (struct database_dyn *db, int fd, request_header *req,
+ }
+
+ out:
+- *resultp = dataset;
++ scratch->dataset = dataset;
+
+ return timeout;
+ }
+@@ -461,6 +477,9 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+ if (user != NULL)
+ key = (char *) rawmemchr (key, '\0') + 1;
+ const char *domain = *key++ ? key : NULL;
++ struct addgetnetgrentX_scratch scratch;
++
++ addgetnetgrentX_scratch_init (&scratch);
+
+ if (__glibc_unlikely (debug_level > 0))
+ {
+@@ -476,12 +495,8 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+ group, group_len,
+ db, uid);
+ time_t timeout;
+- void *tofree;
+ if (result != NULL)
+- {
+- timeout = result->head.timeout;
+- tofree = NULL;
+- }
++ timeout = result->head.timeout;
+ else
+ {
+ request_header req_get =
+@@ -490,7 +505,10 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+ .key_len = group_len
+ };
+ timeout = addgetnetgrentX (db, -1, &req_get, group, uid, NULL, NULL,
+- &result, &tofree);
++ &scratch);
++ result = scratch.dataset;
++ if (timeout < 0)
++ goto out;
+ }
+
+ struct indataset
+@@ -604,7 +622,7 @@ addinnetgrX (struct database_dyn *db, int fd, request_header *req,
+ }
+
+ out:
+- free (tofree);
++ addgetnetgrentX_scratch_free (&scratch);
+ return timeout;
+ }
+
+@@ -614,11 +632,12 @@ addgetnetgrentX_ignore (struct database_dyn *db, int fd, request_header *req,
+ const char *key, uid_t uid, struct hashentry *he,
+ struct datahead *dh)
+ {
+- struct dataset *ignore;
+- void *tofree;
+- time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh,
+- &ignore, &tofree);
+- free (tofree);
++ struct addgetnetgrentX_scratch scratch;
++ addgetnetgrentX_scratch_init (&scratch);
++ time_t timeout = addgetnetgrentX (db, fd, req, key, uid, he, dh, &scratch);
++ addgetnetgrentX_scratch_free (&scratch);
++ if (timeout < 0)
++ timeout = 0;
+ return timeout;
+ }
+
+@@ -662,5 +681,9 @@ readdinnetgr (struct database_dyn *db, struct hashentry *he,
+ .key_len = he->len
+ };
+
+- return addinnetgrX (db, -1, &req, db->data + he->key, he->owner, he, dh);
++ int timeout = addinnetgrX (db, -1, &req, db->data + he->key, he->owner,
++ he, dh);
++ if (timeout < 0)
++ timeout = 0;
++ return timeout;
+ }
+--
+2.33.0
+
diff --git a/backport-Fix-OOB-read-in-stdlib-thousand-grouping-parsing-BZ.patch b/backport-Fix-OOB-read-in-stdlib-thousand-grouping-parsing-BZ.patch
new file mode 100644
index 0000000..f8f5c49
--- /dev/null
+++ b/backport-Fix-OOB-read-in-stdlib-thousand-grouping-parsing-BZ.patch
@@ -0,0 +1,62 @@
+From 17bfe5954baee1f18672aea94caa1126ec36fb81 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Tue, 11 Oct 2022 15:24:41 +0100
+Subject: [PATCH] Fix OOB read in stdlib thousand grouping parsing [BZ
+#29727]
+
+__correctly_grouped_prefixmb only worked with thousands_len == 1,
+otherwise it read past the end of cp or thousands.
+
+This affects scanf formats like %'d, %'f and the internal but
+exposed __strto{l,ul,f,d,..}_internal with grouping flag set
+and an LC_NUMERIC locale where thousands_len > 1.
+
+Avoid OOB access by considering thousands_len when initializing cp.
+This fixes bug 29727.
+
+Found by the morello port with strict bounds checking where
+
+FAIL: stdlib/tst-strtod4
+FAIL: stdlib/tst-strtod5i
+
+crashed using a locale with thousands_len==3.
+---
+ stdlib/grouping.c | 16 +++++++---------
+ 1 file changed, 7 insertions(+), 9 deletions(-)
+
+diff --git a/stdlib/grouping.c b/stdlib/grouping.c
+index d558d930..e2f31b2a 100644
+--- a/stdlib/grouping.c
++++ b/stdlib/grouping.c
+@@ -53,21 +53,19 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ #endif
+ const char *grouping)
+ {
+-#ifndef USE_WIDE_CHAR
+- size_t thousands_len;
+- int cnt;
+-#endif
+-
+ if (grouping == NULL)
+ return end;
+
+-#ifndef USE_WIDE_CHAR
+- thousands_len = strlen (thousands);
++#ifdef USE_WIDE_CHAR
++ size_t thousands_len = 1;
++#else
++ size_t thousands_len = strlen (thousands);
++ int cnt;
+ #endif
+
+- while (end > begin)
++ while (end - begin >= thousands_len)
+ {
+- const STRING_TYPE *cp = end - 1;
++ const STRING_TYPE *cp = end - thousands_len;
+ const char *gp = grouping;
+
+ /* Check first group. */
+--
+2.33.0
+
diff --git a/backport-Fix-invalid-pointer-dereference-in-wcpcpy_chk.patch b/backport-Fix-invalid-pointer-dereference-in-wcpcpy_chk.patch
new file mode 100644
index 0000000..3594c5b
--- /dev/null
+++ b/backport-Fix-invalid-pointer-dereference-in-wcpcpy_chk.patch
@@ -0,0 +1,35 @@
+From 4ee824be757337d8444fdc320aa1ca3e4397c906 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Tue, 21 Jun 2022 15:57:48 +0100
+Subject: [PATCH] Fix invalid pointer dereference in wcpcpy_chk
+
+The src pointer is const and points to a different object, so accessing
+dest via src is invalid.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+---
+ debug/wcpcpy_chk.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+diff --git a/debug/wcpcpy_chk.c b/debug/wcpcpy_chk.c
+index 0e1d381a..16410e17 100644
+--- a/debug/wcpcpy_chk.c
++++ b/debug/wcpcpy_chk.c
+@@ -29,13 +29,12 @@ __wcpcpy_chk (wchar_t *dest, const wchar_t *src, size_t destlen)
+ {
+ wchar_t *wcp = (wchar_t *) dest - 1;
+ wint_t c;
+- const ptrdiff_t off = src - dest + 1;
+
+ do
+ {
+ if (__glibc_unlikely (destlen-- == 0))
+ __chk_fail ();
+- c = wcp[off];
++ c = *src++;
+ *++wcp = c;
+ }
+ while (c != L'\0');
+--
+2.27.0
+
diff --git a/backport-Fix-invalid-pointer-dereference-in-wcscpy_chk.patch b/backport-Fix-invalid-pointer-dereference-in-wcscpy_chk.patch
new file mode 100644
index 0000000..1a3bec1
--- /dev/null
+++ b/backport-Fix-invalid-pointer-dereference-in-wcscpy_chk.patch
@@ -0,0 +1,64 @@
+From 1527ac4626b4bf1bcc46203481003a7f33e2aca5 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Tue, 21 Jun 2022 14:43:30 +0100
+Subject: [PATCH] Fix invalid pointer dereference in wcscpy_chk
+
+The src pointer is const and points to a different object, so accessing
+dest via src is invalid.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+---
+ debug/wcscpy_chk.c | 34 +++++++---------------------------
+ 1 file changed, 7 insertions(+), 27 deletions(-)
+
+diff --git a/debug/wcscpy_chk.c b/debug/wcscpy_chk.c
+index dfe475da..8115b00e 100644
+--- a/debug/wcscpy_chk.c
++++ b/debug/wcscpy_chk.c
+@@ -25,36 +25,16 @@ wchar_t *
+ __wcscpy_chk (wchar_t *dest, const wchar_t *src, size_t n)
+ {
+ wint_t c;
+- wchar_t *wcp;
++ wchar_t *wcp = dest;
+
+- if (__alignof__ (wchar_t) >= sizeof (wchar_t))
++ do
+ {
+- const ptrdiff_t off = dest - src - 1;
+-
+- wcp = (wchar_t *) src;
+-
+- do
+- {
+- if (__glibc_unlikely (n-- == 0))
+- __chk_fail ();
+- c = *wcp++;
+- wcp[off] = c;
+- }
+- while (c != L'\0');
+- }
+- else
+- {
+- wcp = dest;
+-
+- do
+- {
+- if (__glibc_unlikely (n-- == 0))
+- __chk_fail ();
+- c = *src++;
+- *wcp++ = c;
+- }
+- while (c != L'\0');
++ if (__glibc_unlikely (n-- == 0))
++ __chk_fail ();
++ c = *src++;
++ *wcp++ = c;
+ }
++ while (c != L'\0');
+
+ return dest;
+ }
+--
+2.27.0
+
diff --git a/backport-Skip-unusable-entries-in-first-pass-in-prune_cache.patch b/backport-Skip-unusable-entries-in-first-pass-in-prune_cache.patch
new file mode 100644
index 0000000..dcd3609
--- /dev/null
+++ b/backport-Skip-unusable-entries-in-first-pass-in-prune_cache.patch
@@ -0,0 +1,93 @@
+From c00b984fcd53f679ca2dafcd1aee2c89836e6e73 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 29 Aug 2023 08:28:31 +0200
+Subject: [PATCH] nscd: Skip unusable entries in first pass in prune_cache (bug
+ 30800)
+
+Previously, if an entry was marked unusable for any reason, but had
+not timed out yet, the assert would trigger.
+
+One way to get into such state is if a data change is detected during
+re-validation of an entry. This causes the entry to be marked as not
+usable. If exits nscd soon after that, then the clock jumps
+backwards, and nscd restarted, the cache re-validation run after
+startup triggers the removed assert.
+
+The change is more complicated than just the removal of the assert
+because entries marked as not usable should be garbage-collected in
+the second pass. To make this happen, it is necessary to update some
+book-keeping data.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=c00b984fcd53f679ca2dafcd1aee2c89836e6e73
+
+---
+ nscd/cache.c | 25 +++++++++++--------------
+ 1 file changed, 11 insertions(+), 14 deletions(-)
+
+diff --git a/nscd/cache.c b/nscd/cache.c
+index 78b22697..ac5902ae 100644
+--- a/nscd/cache.c
++++ b/nscd/cache.c
+@@ -371,8 +371,11 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
+ serv2str[runp->type], str, dh->timeout);
+ }
+
+- /* Check whether the entry timed out. */
+- if (dh->timeout < now)
++ /* Check whether the entry timed out. Timed out entries
++ will be revalidated. For unusable records, it is still
++ necessary to record that the bucket needs to be scanned
++ again below. */
++ if (dh->timeout < now || !dh->usable)
+ {
+ /* This hash bucket could contain entries which need to
+ be looked at. */
+@@ -384,7 +387,7 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
+ /* We only have to look at the data of the first entries
+ since the count information is kept in the data part
+ which is shared. */
+- if (runp->first)
++ if (runp->first && dh->usable)
+ {
+
+ /* At this point there are two choices: we reload the
+@@ -400,9 +403,6 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
+ {
+ /* Remove the value. */
+ dh->usable = false;
+-
+- /* We definitely have some garbage entries now. */
+- any = true;
+ }
+ else
+ {
+@@ -414,18 +414,15 @@ prune_cache (struct database_dyn *table, time_t now, int fd)
+
+ time_t timeout = readdfcts[runp->type] (table, runp, dh);
+ next_timeout = MIN (next_timeout, timeout);
+-
+- /* If the entry has been replaced, we might need
+- cleanup. */
+- any |= !dh->usable;
+ }
+ }
++
++ /* If the entry has been replaced, we might need cleanup. */
++ any |= !dh->usable;
+ }
+ else
+- {
+- assert (dh->usable);
+- next_timeout = MIN (next_timeout, dh->timeout);
+- }
++ /* Entry has not timed out and is usable. */
++ next_timeout = MIN (next_timeout, dh->timeout);
+
+ run = runp->next;
+ }
+--
+2.33.0
+
diff --git a/backport-Use-errval-not-errno-to-guide-cache-update.patch b/backport-Use-errval-not-errno-to-guide-cache-update.patch
new file mode 100644
index 0000000..c941b0a
--- /dev/null
+++ b/backport-Use-errval-not-errno-to-guide-cache-update.patch
@@ -0,0 +1,49 @@
+From 2d472b48610f6a298d28035b683ab13e9afac4cb Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 24 Jul 2023 15:12:26 +0200
+Subject: [PATCH] nscd: Use errval, not errno to guide cache update (bug 30662)
+
+The errno variable is potentially clobbered by the preceding
+send call. It is not related to the to-be-cached information.
+The parallel code in hstcache.c and servicescache.c already uses
+errval.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=2d472b48610f6a298d28035b683ab13e9afac4cb
+
+---
+ nscd/grpcache.c | 2 +-
+ nscd/pwdcache.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/nscd/grpcache.c b/nscd/grpcache.c
+index 457ca4d8..d18bcabe 100644
+--- a/nscd/grpcache.c
++++ b/nscd/grpcache.c
+@@ -117,7 +117,7 @@ cache_addgr (struct database_dyn *db, int fd, request_header *req,
+
+ /* If we have a transient error or cannot permanently store
+ the result, so be it. */
+- if (errno == EAGAIN || __builtin_expect (db->negtimeout == 0, 0))
++ if (errval == EAGAIN || __glibc_unlikely (db->negtimeout == 0))
+ {
+ /* Mark the old entry as obsolete. */
+ if (dh != NULL)
+diff --git a/nscd/pwdcache.c b/nscd/pwdcache.c
+index dfafb526..409c5acd 100644
+--- a/nscd/pwdcache.c
++++ b/nscd/pwdcache.c
+@@ -123,7 +123,7 @@ cache_addpw (struct database_dyn *db, int fd, request_header *req,
+
+ /* If we have a transient error or cannot permanently store
+ the result, so be it. */
+- if (errno == EAGAIN || __builtin_expect (db->negtimeout == 0, 0))
++ if (errval == EAGAIN || __glibc_unlikely (db->negtimeout == 0))
+ {
+ /* Mark the old entry as obsolete. */
+ if (dh != NULL)
+--
+2.33.0
+
diff --git a/backport-elf-Add-TLS-modid-reuse-test-for-bug-29039.patch b/backport-elf-Add-TLS-modid-reuse-test-for-bug-29039.patch
new file mode 100644
index 0000000..03efbca
--- /dev/null
+++ b/backport-elf-Add-TLS-modid-reuse-test-for-bug-29039.patch
@@ -0,0 +1,209 @@
+From 980450f12685326729d63ff72e93a996113bf073 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Wed, 29 Nov 2023 11:31:37 +0000
+Subject: [PATCH] elf: Add TLS modid reuse test for bug 29039
+
+This is a minimal regression test for bug 29039 which only affects
+targets with TLSDESC and a reproducer requires that
+
+1) Have modid gaps (closed modules) with old generation.
+2) Update a DTV to a newer generation (needs a newer dlopen).
+3) But do not update the closed gap entry in that DTV.
+4) Reuse the modid gap for a new module (another dlopen).
+5) Use dynamic TLSDESC in that new module with old generation (bug).
+6) Access TLS via this TLSDESC and the now outdated DTV.
+
+However step (3) in practice rarely happens: during DTV update the
+entries for closed modids are initialized to "unallocated" and then
+dynamic TLSDESC calls __tls_get_addr independently of its generation.
+The only exception to this is DTV setup at thread creation (gaps are
+initialized to NULL instead of unallocated) or DTV resize where the
+gap entries are outside the previous DTV array (again NULL instead
+of unallocated, and this requires loading > DTV_SURPLUS modules).
+
+So the bug can only cause NULL (+ offset) dereference, not use after
+free. And the easiest way to get (3) is via thread creation.
+
+Note that step (5) requires that the newly loaded module has larger
+TLS than the remaining optional static TLS. And for (6) there cannot
+be other TLS access or dlopen in the thread that updates the DTV.
+
+Tested on aarch64-linux-gnu.
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=980450f12685326729d63ff72e93a996113bf073
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ elf/Makefile | 15 +++++++
+ elf/tst-tlsgap-mod0.c | 2 +
+ elf/tst-tlsgap-mod1.c | 2 +
+ elf/tst-tlsgap-mod2.c | 2 +
+ elf/tst-tlsgap.c | 92 +++++++++++++++++++++++++++++++++++++++++++
+ 5 files changed, 113 insertions(+)
+ create mode 100644 elf/tst-tlsgap-mod0.c
+ create mode 100644 elf/tst-tlsgap-mod1.c
+ create mode 100644 elf/tst-tlsgap-mod2.c
+ create mode 100644 elf/tst-tlsgap.c
+
+diff --git a/elf/Makefile b/elf/Makefile
+index ed13f34d..b5de4dd4 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -425,6 +425,7 @@ tests += \
+ tst-tls5 \
+ tst-tlsalign \
+ tst-tlsalign-extern \
++ tst-tlsgap \
+ tst-tls-dlinfo \
+ tst-tls-ie \
+ tst-tls-ie-dlmopen \
+@@ -704,6 +705,9 @@ modules-names = \
+ tst-tls20mod-bad \
+ tst-tls21mod \
+ tst-tlsalign-lib \
++ tst-tlsgap-mod0 \
++ tst-tlsgap-mod1 \
++ tst-tlsgap-mod2 \
+ tst-tls-ie-mod0 \
+ tst-tls-ie-mod1 \
+ tst-tls-ie-mod2 \
+@@ -2498,3 +2502,14 @@ $(objpfx)tst-non-directory-path.out: tst-non-directory-path.sh \
+ '$(test-wrapper-env)' '$(run_program_env)' \
+ '$(rpath-link)' $(objpfx) > $@; \
+ $(evaluate-test)
++
++$(objpfx)tst-tlsgap: $(shared-thread-library)
++$(objpfx)tst-tlsgap.out: \
++ $(objpfx)tst-tlsgap-mod0.so \
++ $(objpfx)tst-tlsgap-mod1.so \
++ $(objpfx)tst-tlsgap-mod2.so
++ifeq (yes,$(have-mtls-dialect-gnu2))
++CFLAGS-tst-tlsgap-mod0.c += -mtls-dialect=gnu2
++CFLAGS-tst-tlsgap-mod1.c += -mtls-dialect=gnu2
++CFLAGS-tst-tlsgap-mod2.c += -mtls-dialect=gnu2
++endif
+diff --git a/elf/tst-tlsgap-mod0.c b/elf/tst-tlsgap-mod0.c
+new file mode 100644
+index 00000000..1478b0be
+--- /dev/null
++++ b/elf/tst-tlsgap-mod0.c
+@@ -0,0 +1,2 @@
++int __thread tls0;
++int *f0(void) { return &tls0; }
+diff --git a/elf/tst-tlsgap-mod1.c b/elf/tst-tlsgap-mod1.c
+new file mode 100644
+index 00000000..b10fc370
+--- /dev/null
++++ b/elf/tst-tlsgap-mod1.c
+@@ -0,0 +1,2 @@
++int __thread tls1[100]; /* Size > glibc.rtld.optional_static_tls / 2. */
++int *f1(void) { return tls1; }
+diff --git a/elf/tst-tlsgap-mod2.c b/elf/tst-tlsgap-mod2.c
+new file mode 100644
+index 00000000..166c27d7
+--- /dev/null
++++ b/elf/tst-tlsgap-mod2.c
+@@ -0,0 +1,2 @@
++int __thread tls2;
++int *f2(void) { return &tls2; }
+diff --git a/elf/tst-tlsgap.c b/elf/tst-tlsgap.c
+new file mode 100644
+index 00000000..49328850
+--- /dev/null
++++ b/elf/tst-tlsgap.c
+@@ -0,0 +1,92 @@
++/* TLS modid gap reuse regression test for bug 29039.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++#include <dlfcn.h>
++#include <pthread.h>
++#include <support/xdlfcn.h>
++#include <support/xthread.h>
++#include <support/check.h>
++
++static void *mod[3];
++#define MOD(i) "tst-tlsgap-mod" #i ".so"
++static const char *modname[3] = { MOD(0), MOD(1), MOD(2) };
++#undef MOD
++
++static void
++open_mod (int i)
++{
++ mod[i] = xdlopen (modname[i], RTLD_LAZY);
++ printf ("open %s\n", modname[i]);
++}
++
++static void
++close_mod (int i)
++{
++ xdlclose (mod[i]);
++ mod[i] = NULL;
++ printf ("close %s\n", modname[i]);
++}
++
++static void
++access_mod (int i, const char *sym)
++{
++ int *(*f) (void) = xdlsym (mod[i], sym);
++ int *p = f ();
++ printf ("access %s: %s() = %p\n", modname[i], sym, p);
++ TEST_VERIFY_EXIT (p != NULL);
++ ++*p;
++}
++
++static void *
++start (void *arg)
++{
++ /* The DTV generation is at the last dlopen of mod0 and the
++ entry for mod1 is NULL. */
++
++ open_mod (1); /* Reuse modid of mod1. Uses dynamic TLS. */
++
++ /* DTV is unchanged: dlopen only updates the DTV to the latest
++ generation if static TLS is allocated for a loaded module.
++
++ With bug 29039, the TLSDESC relocation in mod1 uses the old
++ dlclose generation of mod1 instead of the new dlopen one so
++ DTV is not updated on TLS access. */
++
++ access_mod (1, "f1");
++
++ return arg;
++}
++
++static int
++do_test (void)
++{
++ open_mod (0);
++ open_mod (1);
++ open_mod (2);
++ close_mod (0);
++ close_mod (1); /* Create modid gap at mod1. */
++ open_mod (0); /* Reuse modid of mod0, bump generation count. */
++
++ /* Create a thread where DTV of mod1 is NULL. */
++ pthread_t t = xpthread_create (NULL, start, NULL);
++ xpthread_join (t);
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.33.0
+
diff --git a/backport-elf-Check-objname-before-calling-fatal_error.patch b/backport-elf-Check-objname-before-calling-fatal_error.patch
new file mode 100644
index 0000000..69376c6
--- /dev/null
+++ b/backport-elf-Check-objname-before-calling-fatal_error.patch
@@ -0,0 +1,35 @@
+From 1cce91d8aed5c3eca2b6f47767c82d9ed3e9e33f Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 8 Apr 2024 09:06:09 -0700
+Subject: [PATCH] elf: Check objname before calling fatal_error
+
+_dl_signal_error may be called with objname == NULL. _dl_exception_create
+checks objname == NULL. But fatal_error doesn't. Check objname before
+calling fatal_error. This fixes BZ #31596.
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=1cce91d8aed5c3eca2b6f47767c82d9ed3e9e33f
+
+Reviewed-by: Sunil K Pandey <skpgkp2@gmail.com>
+---
+ elf/dl-error-skeleton.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/elf/dl-error-skeleton.c b/elf/dl-error-skeleton.c
+index b699936c..26dfab55 100644
+--- a/elf/dl-error-skeleton.c
++++ b/elf/dl-error-skeleton.c
+@@ -121,7 +121,11 @@ _dl_signal_error (int errcode, const char *objname, const char *occation,
+ __longjmp (lcatch->env[0].__jmpbuf, 1);
+ }
+ else
++ {
++ if (objname == NULL)
++ objname = "";
+ fatal_error (errcode, objname, occation, errstring);
++ }
+ }
+ libc_hidden_def (_dl_signal_error)
+
+--
+2.33.0
+
diff --git a/backport-elf-Do-not-completely-clear-reused-namespace-in-dlmo.patch b/backport-elf-Do-not-completely-clear-reused-namespace-in-dlmo.patch
new file mode 100644
index 0000000..ac2e783
--- /dev/null
+++ b/backport-elf-Do-not-completely-clear-reused-namespace-in-dlmo.patch
@@ -0,0 +1,98 @@
+From 2c42257314536b94cc8d52edede86e94e98c1436 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 14 Oct 2022 11:02:25 +0200
+Subject: [PATCH] elf: Do not completely clear reused namespace in
+dlmopen (bug
+ 29600)
+
+The data in the _ns_debug member must be preserved, otherwise
+_dl_debug_initialize enters an infinite loop. To be conservative,
+only clear the libc_map member for now, to fix bug 29528.
+
+Fixes commit d0e357ff45a75553dee3b17ed7d303bfa544f6fe
+("elf: Call __libc_early_init for reused namespaces (bug 29528)"),
+by reverting most of it.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ elf/dl-open.c | 14 ++++++--------
+ elf/tst-dlmopen-twice.c | 28 ++++++++++++++++++++++++----
+ 2 files changed, 30 insertions(+), 12 deletions(-)
+
+diff --git a/elf/dl-open.c b/elf/dl-open.c
+index 9d7b764b..0820c34b 100644
+--- a/elf/dl-open.c
++++ b/elf/dl-open.c
+@@ -857,15 +857,13 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
+ _dl_signal_error (EINVAL, file, NULL, N_("\
+ no more namespaces available for dlmopen()"));
+ }
++ else if (nsid == GL(dl_nns))
++ {
++ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
++ ++GL(dl_nns);
++ }
+
+- if (nsid == GL(dl_nns))
+- ++GL(dl_nns);
+-
+- /* Initialize the new namespace. Most members are
+- zero-initialized, only the lock needs special treatment. */
+- memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid]));
+- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
+-
++ GL(dl_ns)[nsid].libc_map = NULL;
+ _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
+ }
+ /* Never allow loading a DSO in a namespace which is empty. Such
+diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c
+index 449f3c8f..70c71fe1 100644
+--- a/elf/tst-dlmopen-twice.c
++++ b/elf/tst-dlmopen-twice.c
+@@ -16,18 +16,38 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+-#include <support/xdlfcn.h>
++#include <stdio.h>
+ #include <support/check.h>
++#include <support/xdlfcn.h>
+
+-static int
+-do_test (void)
++/* Run the test multiple times, to check finding a new namespace while
++ another namespace is already in use. This used to trigger bug 29600. */
++static void
++recurse (int depth)
+ {
+- void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW);
++ if (depth == 0)
++ return;
++
++ printf ("info: running at depth %d\n", depth);
++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so",
++ RTLD_NOW);
+ xdlclose (handle);
+ handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
+ int (*run_check) (void) = xdlsym (handle, "run_check");
+ TEST_COMPARE (run_check (), 0);
++ recurse (depth - 1);
+ xdlclose (handle);
++}
++
++static int
++do_test (void)
++{
++ /* First run the test without nesting. */
++ recurse (1);
++
++ /* Then with nesting. The constant needs to be less than the
++ internal DL_NNS namespace constant. */
++ recurse (10);
+ return 0;
+ }
+
+--
+2.33.0
+
diff --git a/backport-elf-Fix-TLS-modid-reuse-generation-assignment-BZ-290.patch b/backport-elf-Fix-TLS-modid-reuse-generation-assignment-BZ-290.patch
new file mode 100644
index 0000000..a709c72
--- /dev/null
+++ b/backport-elf-Fix-TLS-modid-reuse-generation-assignment-BZ-290.patch
@@ -0,0 +1,54 @@
+From 3921c5b40f293c57cb326f58713c924b0662ef59 Mon Sep 17 00:00:00 2001
+From: Hector Martin <marcan@marcan.st>
+Date: Tue, 28 Nov 2023 15:23:07 +0900
+Subject: [PATCH] elf: Fix TLS modid reuse generation assignment (BZ 29039)
+
+_dl_assign_tls_modid() assigns a slotinfo entry for a new module, but
+does *not* do anything to the generation counter. The first time this
+happens, the generation is zero and map_generation() returns the current
+generation to be used during relocation processing. However, if
+a slotinfo entry is later reused, it will already have a generation
+assigned. If this generation has fallen behind the current global max
+generation, then this causes an obsolete generation to be assigned
+during relocation processing, as map_generation() returns this
+generation if nonzero. _dl_add_to_slotinfo() eventually resets the
+generation, but by then it is too late. This causes DTV updates to be
+skipped, leading to NULL or broken TLS slot pointers and segfaults.
+
+Fix this by resetting the generation to zero in _dl_assign_tls_modid(),
+so it behaves the same as the first time a slot is assigned.
+_dl_add_to_slotinfo() will still assign the correct static generation
+later during module load, but relocation processing will no longer use
+an obsolete generation.
+
+Note that slotinfo entry (aka modid) reuse typically happens after a
+dlclose and only TLS access via dynamic tlsdesc is affected. Because
+tlsdesc is optimized to use the optional part of static TLS, dynamic
+tlsdesc can be avoided by increasing the glibc.rtld.optional_static_tls
+tunable to a large enough value, or by LD_PRELOAD-ing the affected
+modules.
+
+Fixes bug 29039.
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=3921c5b40f293c57cb326f58713c924b0662ef59
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ elf/dl-tls.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/elf/dl-tls.c b/elf/dl-tls.c
+index 0070c8bb..42868eef 100644
+--- a/elf/dl-tls.c
++++ b/elf/dl-tls.c
+@@ -160,6 +160,7 @@ _dl_assign_tls_modid (struct link_map *l)
+ {
+ /* Mark the entry as used, so any dependency see it. */
+ atomic_store_relaxed (&runp->slotinfo[result - disp].map, l);
++ atomic_store_relaxed (&runp->slotinfo[result - disp].gen, 0);
+ break;
+ }
+
+--
+2.33.0
+
diff --git a/backport-elf-Fix-_dl_debug_vdprintf-to-work-before-self-reloc.patch b/backport-elf-Fix-_dl_debug_vdprintf-to-work-before-self-reloc.patch
new file mode 100644
index 0000000..3e829fe
--- /dev/null
+++ b/backport-elf-Fix-_dl_debug_vdprintf-to-work-before-self-reloc.patch
@@ -0,0 +1,137 @@
+From 434eca873f14f618d6c2279b54fb809fb56f2c50 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 6 Nov 2023 17:25:40 -0300
+Subject: [PATCH] elf: Fix _dl_debug_vdprintf to work before self-relocation
+
+The strlen might trigger and invalid GOT entry if it used before
+the process is self-relocated (for instance on dl-tunables if any
+error occurs).
+
+For i386, _dl_writev with PIE requires to use the old 'int $0x80'
+syscall mode because the calling the TLS register (gs) is not yet
+initialized.
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=434eca873f14f618d6c2279b54fb809fb56f2c50
+
+Checked on x86_64-linux-gnu.
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ elf/dl-misc.c | 15 +++++++++++++--
+ stdio-common/Makefile | 5 +++++
+ stdio-common/_itoa.c | 5 +++++
+ sysdeps/unix/sysv/linux/i386/dl-writev.h | 24 ++++++++++++++++++++++++
+ 4 files changed, 47 insertions(+), 2 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/i386/dl-writev.h
+
+diff --git a/elf/dl-misc.c b/elf/dl-misc.c
+index bba2e714..5b637c7e 100644
+--- a/elf/dl-misc.c
++++ b/elf/dl-misc.c
+@@ -16,6 +16,10 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
++#include <string.h>
++#if BUILD_PIE_DEFAULT
++# pragma GCC visibility push(hidden)
++#endif
+ #include <assert.h>
+ #include <fcntl.h>
+ #include <ldsodefs.h>
+@@ -23,7 +27,6 @@
+ #include <link.h>
+ #include <stdarg.h>
+ #include <stdlib.h>
+-#include <string.h>
+ #include <unistd.h>
+ #include <stdint.h>
+ #include <sys/mman.h>
+@@ -71,6 +74,14 @@ _dl_sysdep_read_whole_file (const char *file, size_t *sizep, int prot)
+ return result;
+ }
+
++/* The function might be called before the process is self-relocated. */
++static size_t
++_dl_debug_strlen (const char *s)
++{
++ const char *p = s;
++ for (; *s != '\0'; s++);
++ return s - p;
++}
+
+ /* Bare-bones printf implementation. This function only knows about
+ the formats and flags needed and can handle only up to 64 stripes in
+@@ -235,7 +246,7 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+ case 's':
+ /* Get the string argument. */
+ iov[niov].iov_base = va_arg (arg, char *);
+- iov[niov].iov_len = strlen (iov[niov].iov_base);
++ iov[niov].iov_len = _dl_debug_strlen (iov[niov].iov_base);
+ if (prec != -1)
+ iov[niov].iov_len = MIN ((size_t) prec, iov[niov].iov_len);
+ ++niov;
+diff --git a/stdio-common/Makefile b/stdio-common/Makefile
+index 803f16da..f9763c27 100644
+--- a/stdio-common/Makefile
++++ b/stdio-common/Makefile
+@@ -181,6 +181,11 @@ CFLAGS-isoc99_scanf.c += -fexceptions
+ CFLAGS-errlist.c += $(fno-unit-at-a-time)
+ CFLAGS-siglist.c += $(fno-unit-at-a-time)
+
++# Called during static library initialization, so turn stack-protection
++# off for non-shared builds.
++CFLAGS-_itoa.o = $(no-stack-protector)
++CFLAGS-_itoa.op = $(no-stack-protector)
++
+ # scanf14a.c and scanf16a.c test a deprecated extension which is no
+ # longer visible under most conformance levels; see the source files
+ # for more detail.
+diff --git a/stdio-common/_itoa.c b/stdio-common/_itoa.c
+index c37d1c35..20c2e384 100644
+--- a/stdio-common/_itoa.c
++++ b/stdio-common/_itoa.c
+@@ -18,6 +18,11 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
++/* Mark symbols hidden in static PIE for early self relocation to work.
++ Note: string.h may have ifuncs which cannot be hidden on i686. */
++#if BUILD_PIE_DEFAULT
++# pragma GCC visibility push(hidden)
++#endif
+ #include <gmp-mparam.h>
+ #include <gmp.h>
+ #include <limits.h>
+diff --git a/sysdeps/unix/sysv/linux/i386/dl-writev.h b/sysdeps/unix/sysv/linux/i386/dl-writev.h
+new file mode 100644
+index 00000000..624d0e46
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/i386/dl-writev.h
+@@ -0,0 +1,24 @@
++/* Message-writing for the dynamic linker. Linux/i386 version.
++ Copyright (C) 2013-2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#if BUILD_PIE_DEFAULT
++/* Can't use "call *%gs:SYSINFO_OFFSET" during startup in static PIE. */
++# define I386_USE_SYSENTER 0
++#endif
++
++#include <sysdeps/unix/sysv/linux/dl-writev.h>
+--
+2.33.0
+
diff --git a/backport-elf-Fix-alloca-size-in-_dl_debug_vdprintf.patch b/backport-elf-Fix-alloca-size-in-_dl_debug_vdprintf.patch
new file mode 100644
index 0000000..9f80a9a
--- /dev/null
+++ b/backport-elf-Fix-alloca-size-in-_dl_debug_vdprintf.patch
@@ -0,0 +1,43 @@
+From 442387b8712c2b6ba92689d4702aa2c9899527d0 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Tue, 11 Oct 2022 14:22:35 +0100
+Subject: [PATCH] elf: Fix alloca size in _dl_debug_vdprintf
+
+Reference: https://sourceware.org/git/?p=glibc.git;a=commit;h=eef17d4d9fcd38c5cbb9bc9515ba72d1773b67a2
+Conflict: _dl_debug_vdprintf is in elf/dl-misc.c, update here
+
+The alloca size did not consider the optional width parameter for
+padding which could cause buffer underflow. The width is currently used
+e.g. by _dl_map_object_from_fd which passes 2 * sizeof(void *) which
+can be larger than the alloca buffer size on targets where
+sizeof(void *) >= 2 * sizeof(unsigned long).
+
+Even if large width is not used on existing targets it is better to fix
+the formatting code to avoid surprises.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+---
+ elf/dl-misc.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/elf/dl-misc.c b/elf/dl-misc.c
+index b256d792..a11d11d5 100644
+--- a/elf/dl-misc.c
++++ b/elf/dl-misc.c
+@@ -206,8 +206,11 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+ /* We use alloca() to allocate the buffer with the most
+ pessimistic guess for the size. Using alloca() allows
+ having more than one integer formatting in a call. */
+- char *buf = (char *) alloca (1 + 3 * sizeof (unsigned long int));
+- char *endp = &buf[1 + 3 * sizeof (unsigned long int)];
++ int size = 1 + 3 * sizeof (unsigned long int);
++ if (width + 1 > size)
++ size = width + 1;
++ char *buf = (char *) alloca (size);
++ char *endp = &buf[size];
+ char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
+
+ /* Pad to the width the user specified. */
+--
+2.38.1
+
diff --git a/backport-elf-Fix-use-after-free-in-ldconfig-BZ-26779.patch b/backport-elf-Fix-use-after-free-in-ldconfig-BZ-26779.patch
new file mode 100644
index 0000000..ddbeb99
--- /dev/null
+++ b/backport-elf-Fix-use-after-free-in-ldconfig-BZ-26779.patch
@@ -0,0 +1,31 @@
+From 03ad86880f68f498ee04e9ea84cd4f0d14473970 Mon Sep 17 00:00:00 2001
+From: Martin Sebor <msebor@redhat.com>
+Date: Tue, 25 Jan 2022 17:37:56 -0700
+Subject: [PATCH] elf: Fix use-after-free in ldconfig [BZ #26779]
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=03ad86880f68f498ee04e9ea84cd4f0d14473970
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ elf/ldconfig.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index d14633f5ec..57bb95ebc3 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -735,9 +735,9 @@ manual_link (char *library)
+ create_links (real_path, path, libname, soname);
+ free (soname);
+ out:
+- free (path);
+ if (path != real_path)
+ free (real_path);
++ free (path);
+ }
+
+
+--
+2.23.0
+
diff --git a/backport-elf-Handle-non-directory-name-in-search-path-BZ-3103.patch b/backport-elf-Handle-non-directory-name-in-search-path-BZ-3103.patch
new file mode 100644
index 0000000..fbd39e1
--- /dev/null
+++ b/backport-elf-Handle-non-directory-name-in-search-path-BZ-3103.patch
@@ -0,0 +1,220 @@
+From a8dcffb30680d6db5704f9ce2fc30621ceb454e7 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Fri, 10 Nov 2023 10:43:12 -0300
+Subject: [PATCH] elf: Handle non-directory name in search path (BZ 31035)
+
+The open_path stops if a relative path in search path contains a
+component that is a non directory (for instance, if the component
+is an existing file).
+
+For instance:
+
+ $ cat > lib.c <<EOF
+ > void foo (void) {}
+ > EOF
+ $ gcc -shared -fPIC -o lib.so lib.c
+ $ cat > main.c <<EOF
+ extern void foo ();
+ int main () { foo (); return 0; }
+ EOF
+ $ gcc -o main main.c lib.so
+ $ LD_LIBRARY_PATH=. ./main
+ $ LD_LIBRARY_PATH=non-existing/path:. ./main
+ $ LD_LIBRARY_PATH=$(pwd)/main:. ./main
+ $ LD_LIBRARY_PATH=./main:. ./main
+ ./main: error while loading shared libraries: lib.so: cannot open shared object file: No such file or directory
+
+The invalid './main' should be ignored as a non-existent one,
+instead as a valid but non accessible file.
+
+Absolute paths do not trigger this issue because their status are
+initialized as 'unknown' and open_path check if this is a directory.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ elf/Makefile | 12 ++++++
+ elf/dl-load.c | 9 ++--
+ elf/tst-non-directory-mod.c | 1 +
+ elf/tst-non-directory-path.c | 7 ++++
+ elf/tst-non-directory-path.sh | 77 +++++++++++++++++++++++++++++++++++
+ 5 files changed, 103 insertions(+), 3 deletions(-)
+ create mode 100644 elf/tst-non-directory-mod.c
+ create mode 100644 elf/tst-non-directory-path.c
+ create mode 100755 elf/tst-non-directory-path.sh
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 6403dd28..ed13f34d 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -400,6 +400,7 @@ tests += \
+ tst-nodelete-dlclose \
+ tst-nodelete-opened \
+ tst-noload \
++ tst-non-directory-path \
+ tst-null-argv \
+ tst-relsort1 \
+ tst-ro-dynamic \
+@@ -682,6 +683,7 @@ modules-names = \
+ tst-ldconfig-soname-lib-without-soname \
+ tst-main1mod \
+ tst-nodelete2mod \
++ tst-non-directory-mod \
+ tst-nodelete-dlclose-dso \
+ tst-nodelete-dlclose-plugin \
+ tst-nodelete-opened-lib \
+@@ -936,6 +938,7 @@ ifeq (yes,$(build-shared))
+ ifeq ($(run-built-tests),yes)
+ tests-special += \
+ $(objpfx)argv0test.out \
++ $(objpfx)tst-non-directory-path.out \
+ $(objpfx)tst-pathopt.out \
+ $(objpfx)tst-rtld-help.out \
+ $(objpfx)tst-rtld-load-self.out \
+@@ -2486,3 +2489,12 @@ $(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \
+ $(objpfx)tst-dlmopen-twice.out: \
+ $(objpfx)tst-dlmopen-twice-mod1.so \
+ $(objpfx)tst-dlmopen-twice-mod2.so
++
++LDFLAGS-tst-non-directory-mod.so = -Wl,-soname,tst-non-directory-mod.so
++$(objpfx)tst-non-directory-path: $(objpfx)tst-non-directory-mod.so
++$(objpfx)tst-non-directory-path.out: tst-non-directory-path.sh \
++ $(objpfx)tst-non-directory-path
++ $(SHELL) tst-non-directory-path.sh $(objpfx)ld.so $(objpfx)tst-non-directory-path \
++ '$(test-wrapper-env)' '$(run_program_env)' \
++ '$(rpath-link)' $(objpfx) > $@; \
++ $(evaluate-test)
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index beb4f995..0c883cb0 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1946,7 +1946,6 @@ open_path (const char *name, size_t namelen, int mode,
+ size_t cnt;
+ char *edp;
+ int here_any = 0;
+- int err;
+
+ /* If we are debugging the search for libraries print the path
+ now if it hasn't happened now. */
+@@ -2047,8 +2046,12 @@ open_path (const char *name, size_t namelen, int mode,
+ return -1;
+ }
+ }
+- if (here_any && (err = errno) != ENOENT && err != EACCES)
+- /* The file exists and is readable, but something went wrong. */
++
++ /* Continue the search if the file does not exist (ENOENT), if it can
++ not be accessed (EACCES), or if the a component in the path is not a
++ directory (for instance, if the component is a existing file meaning
++ essentially that the pathname is invalid - ENOTDIR). */
++ if (here_any && errno != ENOENT && errno != EACCES && errno != ENOTDIR)
+ return -1;
+
+ /* Remember whether we found anything. */
+diff --git a/elf/tst-non-directory-mod.c b/elf/tst-non-directory-mod.c
+new file mode 100644
+index 00000000..aa6d4c27
+--- /dev/null
++++ b/elf/tst-non-directory-mod.c
+@@ -0,0 +1 @@
++void foo (void) {}
+diff --git a/elf/tst-non-directory-path.c b/elf/tst-non-directory-path.c
+new file mode 100644
+index 00000000..1016a97a
+--- /dev/null
++++ b/elf/tst-non-directory-path.c
+@@ -0,0 +1,7 @@
++extern void foo (void);
++
++int main (int argc, char *argv[])
++{
++ foo ();
++ return 0;
++}
+diff --git a/elf/tst-non-directory-path.sh b/elf/tst-non-directory-path.sh
+new file mode 100755
+index 00000000..e804a445
+--- /dev/null
++++ b/elf/tst-non-directory-path.sh
+@@ -0,0 +1,77 @@
++#!/bin/sh
++# Test if library search path does not terminates with non-directory
++# components.
++# Copyright (C) 2023 Free Software Foundation, Inc.
++# This file is part of the GNU C Library.
++#
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++#
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++#
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <https://www.gnu.org/licenses/>.
++
++set -e
++
++rtld=$1
++test_program=$2
++test_wrapper_env=$3
++run_program_env=$4
++# Remove the last space to allow concatenate extra paths.
++library_path=$(echo $5)
++objpfx=$6
++
++test_binary=$(basename ${test_program})
++test_libpath=${test_binary}-x
++
++mkdir -p ${objpfx}/${test_libpath}
++mv ${objpfx}/tst-non-directory-mod.so ${objpfx}/${test_libpath}
++
++# Check with absolute paths.
++${test_wrapper_env} \
++${run_program_env} \
++$rtld --inhibit-cache \
++ --library-path \
++ "$library_path":"${objpfx}"tst-non-directory-invalid:"${objpfx}"${test_libpath} \
++ $test_program 2>&1 && rc=0 || rc=$?
++
++${test_wrapper_env} \
++${run_program_env} \
++$rtld --inhibit-cache \
++ --library-path \
++ "$library_path":"${objpfx}"${test_binary}:"${objpfx}"${test_libpath} \
++ $test_program 2>&1 && rc=0 || rc=$?
++
++# Relative paths along with non-existent path in search list.
++cd "$objpfx"
++${test_wrapper_env} \
++${run_program_env} \
++$rtld --inhibit-cache \
++ --library-path \
++ "$library_path":../elf/tst-non-directory-invalid::../elf/${test_libpath} \
++ $test_program 2>&1 && rc=0 || rc=$?
++
++# Relative paths along with component in the path is not a directory in search list.
++${test_wrapper_env} \
++${run_program_env} \
++$rtld --inhibit-cache \
++ --library-path \
++ "$library_path":../elf/${test_binary}:../elf/${test_libpath} \
++ $test_program 2>&1 && rc=0 || rc=$?
++
++# Relative paths along with non-existent path and a component in the path that is not a directory.
++${test_wrapper_env} \
++${run_program_env} \
++$rtld --inhibit-cache \
++ --library-path \
++ "$library_path":../elf/tst-non-directory-invalid:../elf/${test_binary}:../elf/${test_libpath} \
++ $test_program 2>&1 && rc=0 || rc=$?
++
++exit $rc
+--
+2.27.0
+
diff --git a/backport-elf-Make-more-functions-available-for-binding-during.patch b/backport-elf-Make-more-functions-available-for-binding-during.patch
new file mode 100644
index 0000000..88fecd2
--- /dev/null
+++ b/backport-elf-Make-more-functions-available-for-binding-during.patch
@@ -0,0 +1,236 @@
+From afb81c39036040771feebbeceae92e61877abca5 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 30 May 2023 13:25:50 +0200
+Subject: [PATCH] elf: Make more functions available for binding during dlclose
+ (bug 30425)
+
+Previously, after destructors for a DSO have been invoked, ld.so refused
+to bind against that DSO in all cases. Relax this restriction somewhat
+if the referencing object is itself a DSO that is being unloaded. This
+assumes that the symbol reference is not going to be stored anywhere.
+
+The situation in the test case can arise fairly easily with C++ and
+objects that are built with different optimization levels and therefore
+define different functions with vague linkage.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=d0f07f7df8d9758c838674b70144ac73bcbd1634
+Conflict:NA
+---
+ elf/Makefile | 3 +++
+ elf/dl-lookup.c | 21 ++++++++++++++--
+ elf/tst-dlclose-lazy-mod1.c | 36 +++++++++++++++++++++++++++
+ elf/tst-dlclose-lazy-mod2.c | 49 +++++++++++++++++++++++++++++++++++++
+ elf/tst-dlclose-lazy.c | 47 +++++++++++++++++++++++++++++++++++
+ 5 files changed, 154 insertions(+), 2 deletions(-)
+ create mode 100644 elf/tst-dlclose-lazy-mod1.c
+ create mode 100644 elf/tst-dlclose-lazy-mod2.c
+ create mode 100644 elf/tst-dlclose-lazy.c
+
+diff --git a/elf/Makefile b/elf/Makefile
+index e39cc4f3..888d079c 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -375,6 +375,7 @@ tests += \
+ tst-debug1 \
+ tst-deep1 \
+ tst-dl-is_dso \
++ tst-dlclose-lazy \
+ tst-dlmodcount \
+ tst-dlmopen1 \
+ tst-dlmopen3 \
+@@ -650,6 +651,8 @@ modules-names = \
+ tst-deep1mod2 \
+ tst-deep1mod3 \
+ tst-dlmopen1mod \
++ tst-dlclose-lazy-mod1 \
++ tst-dlclose-lazy-mod2 \
+ tst-dlmopen-dlerror-mod \
+ tst-dlmopen-gethostbyname-mod \
+ tst-dlmopen-twice-mod1 \
+diff --git a/elf/dl-lookup.c b/elf/dl-lookup.c
+index eea217eb..21063289 100644
+--- a/elf/dl-lookup.c
++++ b/elf/dl-lookup.c
+@@ -380,8 +380,25 @@ do_lookup_x (const char *undef_name, uint_fast32_t new_hash,
+ if ((type_class & ELF_RTYPE_CLASS_COPY) && map->l_type == lt_executable)
+ continue;
+
+- /* Do not look into objects which are going to be removed. */
+- if (map->l_removed)
++ /* Do not look into objects which are going to be removed,
++ except when the referencing object itself is being removed.
++
++ The second part covers the situation when an object lazily
++ binds to another object while running its destructor, but the
++ destructor of the other object has already run, so that
++ dlclose has set l_removed. It may not always be obvious how
++ to avoid such a scenario to programmers creating DSOs,
++ particularly if C++ vague linkage is involved and triggers
++ symbol interposition.
++
++ Accepting these to-be-removed objects makes the lazy and
++ BIND_NOW cases more similar. (With BIND_NOW, the symbol is
++ resolved early, before the destructor call, so the issue does
++ not arise.). Behavior matches the constructor scenario: the
++ implementation allows binding to symbols of objects whose
++ constructors have not run. In fact, not doing this would be
++ mostly incompatible with symbol interposition. */
++ if (map->l_removed && !(undef_map != NULL && undef_map->l_removed))
+ continue;
+
+ /* Print some debugging info if wanted. */
+diff --git a/elf/tst-dlclose-lazy-mod1.c b/elf/tst-dlclose-lazy-mod1.c
+new file mode 100644
+index 00000000..8439dc19
+--- /dev/null
++++ b/elf/tst-dlclose-lazy-mod1.c
+@@ -0,0 +1,36 @@
++/* Lazy binding during dlclose. Directly loaded module.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* This function is called from exported_function below. It is only
++ defined in this module. The weak attribute mimics how G++
++ implements vague linkage for C++. */
++void __attribute__ ((weak))
++lazily_bound_exported_function (void)
++{
++}
++
++/* Called from tst-dlclose-lazy-mod2.so. */
++void
++exported_function (int call_it)
++{
++ if (call_it)
++ /* Previous to the fix this would crash when called during dlclose
++ since symbols from the DSO were no longer available for binding
++ (bug 30425) after the DSO started being closed by dlclose. */
++ lazily_bound_exported_function ();
++}
+diff --git a/elf/tst-dlclose-lazy-mod2.c b/elf/tst-dlclose-lazy-mod2.c
+new file mode 100644
+index 00000000..767f69ff
+--- /dev/null
++++ b/elf/tst-dlclose-lazy-mod2.c
+@@ -0,0 +1,49 @@
++/* Lazy binding during dlclose. Indirectly loaded module.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++#include <stdlib.h>
++
++void
++exported_function (int ignored)
++{
++ /* This function is interposed from tst-dlclose-lazy-mod1.so and
++ thus never called. */
++ abort ();
++}
++
++static void __attribute__ ((constructor))
++init (void)
++{
++ puts ("info: tst-dlclose-lazy-mod2.so constructor called");
++
++ /* Trigger lazy binding to the definition in
++ tst-dlclose-lazy-mod1.so, but not for
++ lazily_bound_exported_function in that module. */
++ exported_function (0);
++}
++
++static void __attribute__ ((destructor))
++fini (void)
++{
++ puts ("info: tst-dlclose-lazy-mod2.so destructor called");
++
++ /* Trigger the lazily_bound_exported_function call in
++ exported_function in tst-dlclose-lazy-mod1.so. */
++ exported_function (1);
++}
+diff --git a/elf/tst-dlclose-lazy.c b/elf/tst-dlclose-lazy.c
+new file mode 100644
+index 00000000..976a6bb6
+--- /dev/null
++++ b/elf/tst-dlclose-lazy.c
+@@ -0,0 +1,47 @@
++/* Test lazy binding during dlclose (bug 30425).
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* This test re-creates a situation that can arise naturally for C++
++ applications due to the use of vague linkage and differences in the
++ set of compiler-emitted functions. A function in
++ tst-dlclose-lazy-mod1.so (exported_function) interposes a function
++ in tst-dlclose-lazy-mod2.so. This function is called from the
++ destructor in tst-dlclose-lazy-mod2.so, after the destructor for
++ tst-dlclose-lazy-mod1.so has already completed. Prior to the fix
++ for bug 30425, this would lead to a lazy binding failure in
++ tst-dlclose-lazy-mod1.so because dlclose had already marked the DSO
++ as unavailable for binding (by setting l_removed). */
++
++#include <dlfcn.h>
++#include <support/xdlfcn.h>
++#include <support/check.h>
++
++int
++main (void)
++{
++ /* Load tst-dlclose-lazy-mod1.so, indirectly loading
++ tst-dlclose-lazy-mod2.so. */
++ void *handle = xdlopen ("tst-dlclose-lazy-mod1.so", RTLD_GLOBAL | RTLD_LAZY);
++
++ /* Invoke the destructor of tst-dlclose-lazy-mod2.so, which calls
++ into tst-dlclose-lazy-mod1.so after its destructor has been
++ called. */
++ xdlclose (handle);
++
++ return 0;
++}
+--
+2.33.0
+
diff --git a/backport-elf-Properly-align-PT_LOAD-segments-BZ-28676.patch b/backport-elf-Properly-align-PT_LOAD-segments-BZ-28676.patch
new file mode 100644
index 0000000..365aeca
--- /dev/null
+++ b/backport-elf-Properly-align-PT_LOAD-segments-BZ-28676.patch
@@ -0,0 +1,135 @@
+From 718fdd87b1b98ef88e883a37d9c18867256fa5a4 Mon Sep 17 00:00:00 2001
+From: Rongwei Wang <rongwei.wang@linux.alibaba.com>
+Date: Fri, 10 Dec 2021 20:39:10 +0800
+Subject: [PATCH] elf: Properly align PT_LOAD segments [BZ #28676]
+
+When PT_LOAD segment alignment > the page size, allocate enough space to
+ensure that the segment can be properly aligned. This change helps code
+segments use huge pages become simple and available.
+
+This fixes [BZ #28676].
+
+Signed-off-by: Xu Yu <xuyu@linux.alibaba.com>
+Signed-off-by: Rongwei Wang <rongwei.wang@linux.alibaba.com>
+---
+ elf/dl-load.c | 2 ++
+ elf/dl-load.h | 3 ++-
+ elf/dl-map-segments.h | 50 +++++++++++++++++++++++++++++++++++++++----
+ 3 files changed, 50 insertions(+), 5 deletions(-)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index bf8957e73c..721593135e 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1,5 +1,6 @@
+ /* Map in a shared object's segments from the file.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
++ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -1150,6 +1151,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ c->mapend = ALIGN_UP (ph->p_vaddr + ph->p_filesz, GLRO(dl_pagesize));
+ c->dataend = ph->p_vaddr + ph->p_filesz;
+ c->allocend = ph->p_vaddr + ph->p_memsz;
++ c->mapalign = ph->p_align;
+ c->mapoff = ALIGN_DOWN (ph->p_offset, GLRO(dl_pagesize));
+
+ /* Determine whether there is a gap between the last segment
+diff --git a/elf/dl-load.h b/elf/dl-load.h
+index e329d49a81..e6dabcb336 100644
+--- a/elf/dl-load.h
++++ b/elf/dl-load.h
+@@ -1,5 +1,6 @@
+ /* Map in a shared object's segments from the file.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
++ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -74,7 +75,7 @@ ELF_PREFERRED_ADDRESS_DATA;
+ Its details have been expanded out and converted. */
+ struct loadcmd
+ {
+- ElfW(Addr) mapstart, mapend, dataend, allocend;
++ ElfW(Addr) mapstart, mapend, dataend, allocend, mapalign;
+ ElfW(Off) mapoff;
+ int prot; /* PROT_* bits. */
+ };
+diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
+index f9fb110ee3..70a4c40695 100644
+--- a/elf/dl-map-segments.h
++++ b/elf/dl-map-segments.h
+@@ -1,5 +1,6 @@
+ /* Map in a shared object's segments. Generic version.
+ Copyright (C) 1995-2021 Free Software Foundation, Inc.
++ Copyright The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -18,6 +19,50 @@
+
+ #include <dl-load.h>
+
++/* Map a segment and align it properly. */
++
++static __always_inline ElfW(Addr)
++_dl_map_segment (const struct loadcmd *c, ElfW(Addr) mappref,
++ const size_t maplength, int fd)
++{
++ if (__glibc_likely (c->mapalign <= GLRO(dl_pagesize)))
++ return (ElfW(Addr)) __mmap ((void *) mappref, maplength, c->prot,
++ MAP_COPY|MAP_FILE, fd, c->mapoff);
++
++ /* If the segment alignment > the page size, allocate enough space to
++ ensure that the segment can be properly aligned. */
++ ElfW(Addr) maplen = (maplength >= c->mapalign
++ ? (maplength + c->mapalign)
++ : (2 * c->mapalign));
++ ElfW(Addr) map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplen,
++ PROT_NONE,
++ MAP_ANONYMOUS|MAP_PRIVATE,
++ -1, 0);
++ if (__glibc_unlikely ((void *) map_start == MAP_FAILED))
++ return map_start;
++
++ ElfW(Addr) map_start_aligned = ALIGN_UP (map_start, c->mapalign);
++ map_start_aligned = (ElfW(Addr)) __mmap ((void *) map_start_aligned,
++ maplength, c->prot,
++ MAP_COPY|MAP_FILE|MAP_FIXED,
++ fd, c->mapoff);
++ if (__glibc_unlikely ((void *) map_start_aligned == MAP_FAILED))
++ __munmap ((void *) map_start, maplen);
++ else
++ {
++ /* Unmap the unused regions. */
++ ElfW(Addr) delta = map_start_aligned - map_start;
++ if (delta)
++ __munmap ((void *) map_start, delta);
++ ElfW(Addr) map_end = map_start_aligned + maplength;
++ delta = map_start + maplen - map_end;
++ if (delta)
++ __munmap ((void *) map_end, delta);
++ }
++
++ return map_start_aligned;
++}
++
+ /* This implementation assumes (as does the corresponding implementation
+ of _dl_unmap_segments, in dl-unmap-segments.h) that shared objects
+ are always laid out with all segments contiguous (or with gaps
+@@ -53,10 +98,7 @@ _dl_map_segments (struct link_map *l, int fd,
+ - MAP_BASE_ADDR (l));
+
+ /* Remember which part of the address space this object uses. */
+- l->l_map_start = (ElfW(Addr)) __mmap ((void *) mappref, maplength,
+- c->prot,
+- MAP_COPY|MAP_FILE,
+- fd, c->mapoff);
++ l->l_map_start = _dl_map_segment (c, mappref, maplength, fd);
+ if (__glibc_unlikely ((void *) l->l_map_start == MAP_FAILED))
+ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+
+--
+2.43.0
+
diff --git a/backport-elf-Remove-allocate-use-on-_dl_debug_printf.patch b/backport-elf-Remove-allocate-use-on-_dl_debug_printf.patch
new file mode 100644
index 0000000..28d68a6
--- /dev/null
+++ b/backport-elf-Remove-allocate-use-on-_dl_debug_printf.patch
@@ -0,0 +1,90 @@
+From 40c112ed0d7d0577d2f84851c1f7b8157b3bd2f5 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 31 Oct 2022 15:46:38 -0300
+Subject: [PATCH] elf: Remove allocate use on _dl_debug_printf
+
+The maximum number of directives is already limited by the maximum
+value of iovec, and current padding usage on _dl_map_object_from_fd
+specifies a value of 16 (2 times sizeof (void *)) in hexa, which is
+less than the INT_STRLEN_BOUND(void *) (20 for LP64).
+
+This works if pointers are larger than 8 bytes, for instance 16.
+In this case the maximum padding would be 32 and the IFMTSIZE would
+be 40.
+
+The resulting code does use a slightly larger static stack, the
+output of -fstack-usage (for x86_64):
+
+ * master:
+ dl-printf.c:35:1:_dl_debug_vdprintf 1344 dynamic
+
+ * patch:
+ dl-printf.c:36:1:_dl_debug_vdprintf 2416 static
+
+However, there is an improvement in code generation:
+
+ * master
+ text data bss dec hex filename
+ 330900 3309 ced elf/dl-printf.os
+
+ * patch
+text data bss dec hex filename
+315100 3151 c4f elf/dl-printf.os
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ elf/dl-misc.c | 15 +++++++--------
+ 1 file changed, 7 insertions(+), 8 deletions(-)
+
+diff --git a/elf/dl-misc.c b/elf/dl-misc.c
+index a11d11d5..4a33737c 100644
+--- a/elf/dl-misc.c
++++ b/elf/dl-misc.c
+@@ -34,6 +34,7 @@
+ #include <_itoa.h>
+ #include <dl-writev.h>
+ #include <not-cancel.h>
++#include <intprops.h>
+
+ /* Read the whole contents of FILE into new mmap'd space with given
+ protections. *SIZEP gets the size of the file. On error MAP_FAILED
+@@ -79,6 +80,9 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+ {
+ # define NIOVMAX 64
+ struct iovec iov[NIOVMAX];
++ /* Maximum size for 'd', 'u', and 'x' including padding. */
++ enum { IFMTSIZE = INT_STRLEN_BOUND(void *) };
++ char ifmtbuf[NIOVMAX][IFMTSIZE];
+ int niov = 0;
+ pid_t pid = 0;
+ char pidbuf[12];
+@@ -143,6 +147,8 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+ if (*fmt == '*')
+ {
+ width = va_arg (arg, int);
++ /* The maximum padding accepted is up to pointer size. */
++ assert (width < IFMTSIZE);
+ ++fmt;
+ }
+
+@@ -203,14 +209,7 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+ #endif
+ }
+
+- /* We use alloca() to allocate the buffer with the most
+- pessimistic guess for the size. Using alloca() allows
+- having more than one integer formatting in a call. */
+- int size = 1 + 3 * sizeof (unsigned long int);
+- if (width + 1 > size)
+- size = width + 1;
+- char *buf = (char *) alloca (size);
+- char *endp = &buf[size];
++ char *endp = &ifmtbuf[niov][IFMTSIZE];
+ char *cp = _itoa (num, endp, *fmt == 'x' ? 16 : 10, 0);
+
+ /* Pad to the width the user specified. */
+--
+2.33.0
+
diff --git a/backport-elf-fix-handling-of-negative-numbers-in-dl-printf.patch b/backport-elf-fix-handling-of-negative-numbers-in-dl-printf.patch
new file mode 100644
index 0000000..7eb7044
--- /dev/null
+++ b/backport-elf-fix-handling-of-negative-numbers-in-dl-printf.patch
@@ -0,0 +1,57 @@
+From dae801527386f94e9d2fabf23c37863d1b599153 Mon Sep 17 00:00:00 2001
+From: Roy Eldar <royeldar0@gmail.com>
+Date: Thu, 25 May 2023 17:41:58 +0300
+Subject: [PATCH] elf: fix handling of negative numbers in dl-printf
+
+_dl_debug_vdprintf is a bare-bones printf implementation; currently
+printing a signed integer (using "%d" format specifier) behaves
+incorrectly when the number is negative, as it just prints the
+corresponding unsigned integer, preceeded by a minus sign.
+
+For example, _dl_printf("%d", -1) would print '-4294967295'.
+
+Signed-off-by: Roy Eldar <royeldar0@gmail.com>
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=dae801527386f94e9d2fabf23c37863d1b599153
+Conflict:NA
+---
+ elf/dl-misc.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/elf/dl-misc.c b/elf/dl-misc.c
+index 4a33737c..bba2e714 100644
+--- a/elf/dl-misc.c
++++ b/elf/dl-misc.c
+@@ -193,19 +193,25 @@ _dl_debug_vdprintf (int fd, int tag_p, const char *fmt, va_list arg)
+ if (long_mod)
+ {
+ if ((long int) num < 0)
+- negative = true;
++ {
++ num = -num;
++ negative = true;
++ }
+ }
+ else
+ {
+ if ((int) num < 0)
+ {
+- num = (unsigned int) num;
++ num = -(unsigned int) num;
+ negative = true;
+ }
+ }
+ #else
+ if ((int) num < 0)
+- negative = true;
++ {
++ num = -num;
++ negative = true;
++ }
+ #endif
+ }
+
+--
+2.33.0
+
diff --git a/backport-elf-ldconfig-should-skip-temporary-files-created-by-.patch b/backport-elf-ldconfig-should-skip-temporary-files-created-by-.patch
new file mode 100644
index 0000000..d7fe8a7
--- /dev/null
+++ b/backport-elf-ldconfig-should-skip-temporary-files-created-by-.patch
@@ -0,0 +1,76 @@
+From 2aa0974d2573441bffd596b07bff8698b1f2f18c Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 20 Oct 2023 14:29:50 +0200
+Subject: [PATCH 1/1] elf: ldconfig should skip temporary files created by
+ package managers
+
+This avoids crashes due to partially written files, after a package
+update is interrupted.
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=2aa0974d2573441bffd596b07bff8698b1f2f18c
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ elf/ldconfig.c | 39 +++++++++++++++++++++++++++------------
+ 1 file changed, 27 insertions(+), 12 deletions(-)
+
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index 6190e0ea..73b5ef27 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -746,6 +746,31 @@ struct dlib_entry
+ struct dlib_entry *next;
+ };
+
++/* Skip some temporary DSO files. These files may be partially written
++ and lead to ldconfig crashes when examined. */
++static bool
++skip_dso_based_on_name (const char *name, size_t len)
++{
++ /* Skip temporary files created by the prelink program. Files with
++ names like these are never really DSOs we want to look at. */
++ if (len >= sizeof (".#prelink#") - 1)
++ {
++ if (strcmp (name + len - sizeof (".#prelink#") + 1,
++ ".#prelink#") == 0)
++ return true;
++ if (len >= sizeof (".#prelink#.XXXXXX") - 1
++ && memcmp (name + len - sizeof (".#prelink#.XXXXXX")
++ + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
++ return true;
++ }
++ /* Skip temporary files created by RPM. */
++ if (memchr (name, len, ';') != NULL)
++ return true;
++ /* Skip temporary files created by dpkg. */
++ if (len > 4 && memcmp (name + len - 4, ".tmp", 4) == 0)
++ return true;
++ return false;
++}
+
+ static void
+ search_dir (const struct dir_entry *entry)
+@@ -822,18 +847,8 @@ search_dir (const struct dir_entry *entry)
+ continue;
+
+ size_t len = strlen (direntry->d_name);
+- /* Skip temporary files created by the prelink program. Files with
+- names like these are never really DSOs we want to look at. */
+- if (len >= sizeof (".#prelink#") - 1)
+- {
+- if (strcmp (direntry->d_name + len - sizeof (".#prelink#") + 1,
+- ".#prelink#") == 0)
+- continue;
+- if (len >= sizeof (".#prelink#.XXXXXX") - 1
+- && memcmp (direntry->d_name + len - sizeof (".#prelink#.XXXXXX")
+- + 1, ".#prelink#.", sizeof (".#prelink#.") - 1) == 0)
+- continue;
+- }
++ if (skip_dso_based_on_name (direntry->d_name, len))
++ continue;
+ len += strlen (entry->path) + 2;
+ if (len > file_name_len)
+ {
+--
+2.33.0
+
diff --git a/backport-elf-tlsdeschtab.h-Add-the-Malloc-return-value-check.patch b/backport-elf-tlsdeschtab.h-Add-the-Malloc-return-value-check.patch
new file mode 100644
index 0000000..3a8d862
--- /dev/null
+++ b/backport-elf-tlsdeschtab.h-Add-the-Malloc-return-value-check.patch
@@ -0,0 +1,32 @@
+From d1d0162e50afe7fa1e2fc4a901eb411db48acd7b Mon Sep 17 00:00:00 2001
+From: Xiaoming Ni <nixiaoming@huawei.com>
+Date: Fri, 4 Nov 2022 17:30:00 +0800
+Subject: [PATCH] elf/tlsdeschtab.h: Add the Malloc return value check in
+ _dl_make_tlsdesc_dynamic()
+
+Check the return value of malloc based on the function header comment of
+ _dl_make_tlsdesc_dynamic(). If the return value fails, NULL is
+returned.
+
+Signed-off-by: Xiaoming Ni <nixiaoming@huawei.com>
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ elf/tlsdeschtab.h | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/elf/tlsdeschtab.h b/elf/tlsdeschtab.h
+index 85bd0415..2de61737 100644
+--- a/elf/tlsdeschtab.h
++++ b/elf/tlsdeschtab.h
+@@ -111,6 +111,8 @@ _dl_make_tlsdesc_dynamic (struct link_map *map, size_t ti_offset)
+ }
+
+ *entry = td = malloc (sizeof (struct tlsdesc_dynamic_arg));
++ if (! td)
++ return 0;
+ /* This may be higher than the map's generation, but it doesn't
+ matter much. Worst case, we'll have one extra DTV update per
+ thread. */
+--
+2.33.0
+
diff --git a/backport-gmon-fix-memory-corruption-issues-BZ-30101.patch b/backport-gmon-fix-memory-corruption-issues-BZ-30101.patch
new file mode 100644
index 0000000..61606e5
--- /dev/null
+++ b/backport-gmon-fix-memory-corruption-issues-BZ-30101.patch
@@ -0,0 +1,194 @@
+From bde121872001d8f3224eeafa5b7effb871c3fbca Mon Sep 17 00:00:00 2001
+From: Simon Kissane <skissane@gmail.com>
+Date: Sat, 11 Feb 2023 08:58:02 +1100
+Subject: [PATCH] gmon: fix memory corruption issues [BZ# 30101]
+
+V2 of this patch fixes an issue in V1, where the state was changed to ON not
+OFF at end of _mcleanup. I hadn't noticed that (counterintuitively) ON=0 and
+OFF=3, hence zeroing the buffer turned it back on. So set the state to OFF
+after the memset.
+
+1. Prevent double free, and reads from unallocated memory, when
+ _mcleanup is (incorrectly) called two or more times in a row,
+ without an intervening call to __monstartup; with this patch, the
+ second and subsequent calls effectively become no-ops instead.
+ While setting tos=NULL is minimal fix, safest action is to zero the
+ whole gmonparam buffer.
+
+2. Prevent memory leak when __monstartup is (incorrectly) called two
+ or more times in a row, without an intervening call to _mcleanup;
+ with this patch, the second and subsequent calls effectively become
+ no-ops instead.
+
+3. After _mcleanup, treat __moncontrol(1) as __moncontrol(0) instead.
+ With zeroing of gmonparam buffer in _mcleanup, this stops the
+ state incorrectly being changed to GMON_PROF_ON despite profiling
+ actually being off. If we'd just done the minimal fix to _mcleanup
+ of setting tos=NULL, there is risk of far worse memory corruption:
+ kcount would point to deallocated memory, and the __profil syscall
+ would make the kernel write profiling data into that memory,
+ which could have since been reallocated to something unrelated.
+
+4. Ensure __moncontrol(0) still turns off profiling even in error
+ state. Otherwise, if mcount overflows and sets state to
+ GMON_PROF_ERROR, when _mcleanup calls __moncontrol(0), the __profil
+ syscall to disable profiling will not be invoked. _mcleanup will
+ free the buffer, but the kernel will still be writing profiling
+ data into it, potentially corrupted arbitrary memory.
+
+Also adds a test case for (1). Issues (2)-(4) are not feasible to test.
+
+Signed-off-by: Simon Kissane <skissane@gmail.com>
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ gmon/Makefile | 15 ++++++++++++++-
+ gmon/gmon.c | 26 +++++++++++++++++++-------
+ gmon/tst-mcleanup.c | 31 +++++++++++++++++++++++++++++++
+ 3 files changed, 64 insertions(+), 8 deletions(-)
+ create mode 100644 gmon/tst-mcleanup.c
+
+diff --git a/gmon/Makefile b/gmon/Makefile
+index 706f50f7..475e533c 100644
+--- a/gmon/Makefile
++++ b/gmon/Makefile
+@@ -1,4 +1,5 @@
+ # Copyright (C) 1995-2021 Free Software Foundation, Inc.
++# Copyright The GNU Toolchain Authors.
+ # This file is part of the GNU C Library.
+
+ # The GNU C Library is free software; you can redistribute it and/or
+@@ -25,7 +26,7 @@ include ../Makeconfig
+ headers := sys/gmon.h sys/gmon_out.h sys/profil.h
+ routines := gmon mcount profil sprofil prof-freq
+
+-tests = tst-sprofil tst-gmon tst-mcount-overflow
++tests = tst-sprofil tst-gmon tst-mcount-overflow tst-mcleanup
+ ifeq ($(build-profile),yes)
+ tests += tst-profile-static
+ tests-static += tst-profile-static
+@@ -68,6 +69,14 @@ ifeq ($(run-built-tests),yes)
+ tests-special += $(objpfx)tst-mcount-overflow-check.out
+ endif
+
++CFLAGS-tst-mcleanup.c := -fno-omit-frame-pointer -pg
++tst-mcleanup-no-pie = yes
++CRT-tst-mcleanup := $(csu-objpfx)g$(start-installed-name)
++tst-mcleanup-ENV := GMON_OUT_PREFIX=$(objpfx)tst-mcleanup.data
++ifeq ($(run-built-tests),yes)
++tests-special += $(objpfx)tst-mcleanup.out
++endif
++
+ CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
+ CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o
+ tst-gmon-static-no-pie = yes
+@@ -123,6 +132,10 @@ $(objpfx)tst-mcount-overflow-check.out: tst-mcount-overflow-check.sh $(objpfx)ts
+ $(SHELL) $< $(objpfx)tst-mcount-overflow > $@; \
+ $(evaluate-test)
+
++$(objpfx)tst-mcleanup.out: clean-tst-mcleanup-data
++clean-tst-mcleanup-data:
++ rm -f $(objpfx)tst-mcleanup.data.*
++
+ $(objpfx)tst-gmon-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon.out
+ $(SHELL) $< $(GPROF) $(objpfx)tst-gmon $(objpfx)tst-gmon.data.* > $@; \
+ $(evaluate-test)
+diff --git a/gmon/gmon.c b/gmon/gmon.c
+index 689bf801..5e99a735 100644
+--- a/gmon/gmon.c
++++ b/gmon/gmon.c
+@@ -102,11 +102,8 @@ __moncontrol (int mode)
+ {
+ struct gmonparam *p = &_gmonparam;
+
+- /* Don't change the state if we ran into an error. */
+- if (p->state == GMON_PROF_ERROR)
+- return;
+-
+- if (mode)
++ /* Treat start request as stop if error or gmon not initialized. */
++ if (mode && p->state != GMON_PROF_ERROR && p->tos != NULL)
+ {
+ /* start */
+ __profil((void *) p->kcount, p->kcountsize, p->lowpc, s_scale);
+@@ -116,7 +113,9 @@ __moncontrol (int mode)
+ {
+ /* stop */
+ __profil(NULL, 0, 0, 0);
+- p->state = GMON_PROF_OFF;
++ /* Don't change the state if we ran into an error. */
++ if (p->state != GMON_PROF_ERROR)
++ p->state = GMON_PROF_OFF;
+ }
+ }
+ libc_hidden_def (__moncontrol)
+@@ -146,6 +145,14 @@ __monstartup (u_long lowpc, u_long highpc)
+ maxarcs = MAXARCS;
+ #endif
+
++ /*
++ * If we are incorrectly called twice in a row (without an
++ * intervening call to _mcleanup), ignore the second call to
++ * prevent leaking memory.
++ */
++ if (p->tos != NULL)
++ return;
++
+ /*
+ * round lowpc and highpc to multiples of the density we're using
+ * so the rest of the scaling (here and in gprof) stays in ints.
+@@ -463,9 +470,14 @@ _mcleanup (void)
+ {
+ __moncontrol (0);
+
+- if (_gmonparam.state != GMON_PROF_ERROR)
++ if (_gmonparam.state != GMON_PROF_ERROR && _gmonparam.tos != NULL)
+ write_gmon ();
+
+ /* free the memory. */
+ free (_gmonparam.tos);
++
++ /* reset buffer to initial state for safety */
++ memset(&_gmonparam, 0, sizeof _gmonparam);
++ /* somewhat confusingly, ON=0, OFF=3 */
++ _gmonparam.state = GMON_PROF_OFF;
+ }
+diff --git a/gmon/tst-mcleanup.c b/gmon/tst-mcleanup.c
+new file mode 100644
+index 00000000..b259653e
+--- /dev/null
++++ b/gmon/tst-mcleanup.c
+@@ -0,0 +1,31 @@
++/* Test program for repeated invocation of _mcleanup
++ Copyright The GNU Toolchain Authors.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Intentionally calls _mcleanup() twice: once manually, it will be
++ called again as an atexit handler. This is incorrect use of the API,
++ but the point of the test is to make sure we don't crash when the
++ API is misused in this way. */
++
++#include <sys/gmon.h>
++
++int
++main (void)
++{
++ _mcleanup();
++ return 0;
++}
+--
+2.33.0
+
diff --git a/backport-gmon-improve-mcount-overflow-handling-BZ-27576.patch b/backport-gmon-improve-mcount-overflow-handling-BZ-27576.patch
new file mode 100644
index 0000000..c303e18
--- /dev/null
+++ b/backport-gmon-improve-mcount-overflow-handling-BZ-27576.patch
@@ -0,0 +1,424 @@
+From 31be941e4367c001b2009308839db5c67bf9dcbc Mon Sep 17 00:00:00 2001
+From: Simon Kissane <skissane@gmail.com>
+Date: Sat, 11 Feb 2023 20:12:13 +1100
+Subject: [PATCH] gmon: improve mcount overflow handling [BZ# 27576]
+
+When mcount overflows, no gmon.out file is generated, but no message is printed
+to the user, leaving the user with no idea why, and thinking maybe there is
+some bug - which is how BZ 27576 ended up being logged. Print a message to
+stderr in this case so the user knows what is going on.
+
+As a comment in sys/gmon.h acknowledges, the hardcoded MAXARCS value is too
+small for some large applications, including the test case in that BZ. Rather
+than increase it, add tunables to enable MINARCS and MAXARCS to be overridden
+at runtime (glibc.gmon.minarcs and glibc.gmon.maxarcs). So if a user gets the
+mcount overflow error, they can try increasing maxarcs (they might need to
+increase minarcs too if the heuristic is wrong in their case.)
+
+Note setting minarcs/maxarcs too large can cause monstartup to fail with an
+out of memory error. If you set them large enough, it can cause an integer
+overflow in calculating the buffer size. I haven't done anything to defend
+against that - it would not generally be a security vulnerability, since these
+tunables will be ignored in suid/sgid programs (due to the SXID_ERASE default),
+and if you can set GLIBC_TUNABLES in the environment of a process, you can take
+it over anyway (LD_PRELOAD, LD_LIBRARY_PATH, etc). I thought about modifying
+the code of monstartup to defend against integer overflows, but doing so is
+complicated, and I realise the existing code is susceptible to them even prior
+to this change (e.g. try passing a pathologically large highpc argument to
+monstartup), so I decided just to leave that possibility in-place.
+
+Add a test case which demonstrates mcount overflow and the tunables.
+
+Document the new tunables in the manual.
+
+Signed-off-by: Simon Kissane <skissane@gmail.com>
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ elf/dl-tunables.list | 13 ++++++
+ gmon/Makefile | 22 +++++++++-
+ gmon/gmon.c | 29 +++++++++++--
+ gmon/mcount.c | 5 +++
+ gmon/sys/gmon.h | 6 ++-
+ gmon/tst-mcount-overflow-check.sh | 45 +++++++++++++++++++
+ gmon/tst-mcount-overflow.c | 72 +++++++++++++++++++++++++++++++
+ manual/tunables.texi | 59 +++++++++++++++++++++++++
+ 8 files changed, 244 insertions(+), 7 deletions(-)
+ create mode 100644 gmon/tst-mcount-overflow-check.sh
+ create mode 100644 gmon/tst-mcount-overflow.c
+
+diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
+index 379701b8..ea19387d 100644
+--- a/elf/dl-tunables.list
++++ b/elf/dl-tunables.list
+@@ -160,4 +160,17 @@ glibc {
+ security_level: SXID_IGNORE
+ }
+ }
++
++ gmon {
++ minarcs {
++ type: INT_32
++ minval: 50
++ default: 50
++ }
++ maxarcs {
++ type: INT_32
++ minval: 50
++ default: 1048576
++ }
++ }
+ }
+diff --git a/gmon/Makefile b/gmon/Makefile
+index 7b7b8543..706f50f7 100644
+--- a/gmon/Makefile
++++ b/gmon/Makefile
+@@ -25,7 +25,7 @@ include ../Makeconfig
+ headers := sys/gmon.h sys/gmon_out.h sys/profil.h
+ routines := gmon mcount profil sprofil prof-freq
+
+-tests = tst-sprofil tst-gmon
++tests = tst-sprofil tst-gmon tst-mcount-overflow
+ ifeq ($(build-profile),yes)
+ tests += tst-profile-static
+ tests-static += tst-profile-static
+@@ -56,6 +56,18 @@ ifeq ($(run-built-tests),yes)
+ tests-special += $(objpfx)tst-gmon-gprof.out
+ endif
+
++CFLAGS-tst-mcount-overflow.c := -fno-omit-frame-pointer -pg
++tst-mcount-overflow-no-pie = yes
++CRT-tst-mcount-overflow := $(csu-objpfx)g$(start-installed-name)
++# Intentionally use invalid config where maxarcs<minarcs to check warning is printed
++tst-mcount-overflow-ENV := GMON_OUT_PREFIX=$(objpfx)tst-mcount-overflow.data \
++ GLIBC_TUNABLES=glibc.gmon.minarcs=51:glibc.gmon.maxarcs=50
++# Send stderr into output file because we make sure expected messages are printed
++tst-mcount-overflow-ARGS := 2>&1 1>/dev/null | cat
++ifeq ($(run-built-tests),yes)
++tests-special += $(objpfx)tst-mcount-overflow-check.out
++endif
++
+ CFLAGS-tst-gmon-static.c := $(PIE-ccflag) -fno-omit-frame-pointer -pg
+ CRT-tst-gmon-static := $(csu-objpfx)gcrt1.o
+ tst-gmon-static-no-pie = yes
+@@ -103,6 +115,14 @@ $(objpfx)tst-gmon.out: clean-tst-gmon-data
+ clean-tst-gmon-data:
+ rm -f $(objpfx)tst-gmon.data.*
+
++$(objpfx)tst-mcount-overflow.o: clean-tst-mcount-overflow-data
++clean-tst-mcount-overflow-data:
++ rm -f $(objpfx)tst-mcount-overflow.data.*
++
++$(objpfx)tst-mcount-overflow-check.out: tst-mcount-overflow-check.sh $(objpfx)tst-mcount-overflow.out
++ $(SHELL) $< $(objpfx)tst-mcount-overflow > $@; \
++ $(evaluate-test)
++
+ $(objpfx)tst-gmon-gprof.out: tst-gmon-gprof.sh $(objpfx)tst-gmon.out
+ $(SHELL) $< $(GPROF) $(objpfx)tst-gmon $(objpfx)tst-gmon.data.* > $@; \
+ $(evaluate-test)
+diff --git a/gmon/gmon.c b/gmon/gmon.c
+index bf76358d..689bf801 100644
+--- a/gmon/gmon.c
++++ b/gmon/gmon.c
+@@ -46,6 +46,11 @@
+ #include <libc-internal.h>
+ #include <not-cancel.h>
+
++#if HAVE_TUNABLES
++# define TUNABLE_NAMESPACE gmon
++# include <elf/dl-tunables.h>
++#endif
++
+ #ifdef PIC
+ # include <link.h>
+
+@@ -124,6 +129,22 @@ __monstartup (u_long lowpc, u_long highpc)
+ int o;
+ char *cp;
+ struct gmonparam *p = &_gmonparam;
++ long int minarcs, maxarcs;
++
++#if HAVE_TUNABLES
++ /* Read minarcs/maxarcs tunables. */
++ minarcs = TUNABLE_GET (minarcs, int32_t, NULL);
++ maxarcs = TUNABLE_GET (maxarcs, int32_t, NULL);
++ if (maxarcs < minarcs)
++ {
++ ERR("monstartup: maxarcs < minarcs, setting maxarcs = minarcs\n");
++ maxarcs = minarcs;
++ }
++#else
++ /* No tunables, we use hardcoded defaults */
++ minarcs = MINARCS;
++ maxarcs = MAXARCS;
++#endif
+
+ /*
+ * round lowpc and highpc to multiples of the density we're using
+@@ -146,10 +167,10 @@ __monstartup (u_long lowpc, u_long highpc)
+ }
+ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
+ p->tolimit = p->textsize * ARCDENSITY / 100;
+- if (p->tolimit < MINARCS)
+- p->tolimit = MINARCS;
+- else if (p->tolimit > MAXARCS)
+- p->tolimit = MAXARCS;
++ if (p->tolimit < minarcs)
++ p->tolimit = minarcs;
++ else if (p->tolimit > maxarcs)
++ p->tolimit = maxarcs;
+ p->tossize = p->tolimit * sizeof(struct tostruct);
+
+ cp = calloc (p->kcountsize + p->fromssize + p->tossize, 1);
+diff --git a/gmon/mcount.c b/gmon/mcount.c
+index 9d4a1a50..f7180fdb 100644
+--- a/gmon/mcount.c
++++ b/gmon/mcount.c
+@@ -41,6 +41,10 @@ static char sccsid[] = "@(#)mcount.c 8.1 (Berkeley) 6/4/93";
+
+ #include <atomic.h>
+
++#include <not-cancel.h>
++#include <unistd.h>
++#define ERR(s) __write_nocancel (STDERR_FILENO, s, sizeof (s) - 1)
++
+ /*
+ * mcount is called on entry to each function compiled with the profiling
+ * switch set. _mcount(), which is declared in a machine-dependent way
+@@ -170,6 +174,7 @@ done:
+ return;
+ overflow:
+ p->state = GMON_PROF_ERROR;
++ ERR("mcount: call graph buffer size limit exceeded, gmon.out will not be generated\n");
+ return;
+ }
+
+diff --git a/gmon/sys/gmon.h b/gmon/sys/gmon.h
+index b4cc3b04..af0582a3 100644
+--- a/gmon/sys/gmon.h
++++ b/gmon/sys/gmon.h
+@@ -111,6 +111,8 @@ extern struct __bb *__bb_head;
+ * Always allocate at least this many tostructs. This
+ * hides the inadequacy of the ARCDENSITY heuristic, at least
+ * for small programs.
++ *
++ * Value can be overridden at runtime by glibc.gmon.minarcs tunable.
+ */
+ #define MINARCS 50
+
+@@ -124,8 +126,8 @@ extern struct __bb *__bb_head;
+ * Used to be max representable value of ARCINDEX minus 2, but now
+ * that ARCINDEX is a long, that's too large; we don't really want
+ * to allow a 48 gigabyte table.
+- * The old value of 1<<16 wasn't high enough in practice for large C++
+- * programs; will 1<<20 be adequate for long? FIXME
++ *
++ * Value can be overridden at runtime by glibc.gmon.maxarcs tunable.
+ */
+ #define MAXARCS (1 << 20)
+
+diff --git a/gmon/tst-mcount-overflow-check.sh b/gmon/tst-mcount-overflow-check.sh
+new file mode 100644
+index 00000000..27eb5538
+--- /dev/null
++++ b/gmon/tst-mcount-overflow-check.sh
+@@ -0,0 +1,45 @@
++#!/bin/sh
++# Test expected messages generated when mcount overflows
++# Copyright (C) 2017-2023 Free Software Foundation, Inc.
++# Copyright The GNU Toolchain Authors.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <https://www.gnu.org/licenses/>.
++
++LC_ALL=C
++export LC_ALL
++set -e
++exec 2>&1
++
++program="$1"
++
++check_msg() {
++ if ! grep -q "$1" "$program.out"; then
++ echo "FAIL: expected message not in output: $1"
++ exit 1
++ fi
++}
++
++check_msg 'monstartup: maxarcs < minarcs, setting maxarcs = minarcs'
++check_msg 'mcount: call graph buffer size limit exceeded, gmon.out will not be generated'
++
++for data_file in $1.data.*; do
++ if [ -f "$data_file" ]; then
++ echo "FAIL: expected no data files, but found $data_file"
++ exit 1
++ fi
++done
++
++echo PASS
+diff --git a/gmon/tst-mcount-overflow.c b/gmon/tst-mcount-overflow.c
+new file mode 100644
+index 00000000..06cc93ef
+--- /dev/null
++++ b/gmon/tst-mcount-overflow.c
+@@ -0,0 +1,72 @@
++/* Test program to trigger mcount overflow in profiling collection.
++ Copyright (C) 2017-2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Program with sufficiently complex, yet pointless, call graph
++ that it will trigger an mcount overflow, when you set the
++ minarcs/maxarcs tunables to very low values. */
++
++#define PREVENT_TAIL_CALL asm volatile ("")
++
++/* Calls REP(n) macro 16 times, for n=0..15.
++ * You need to define REP(n) before using this.
++ */
++#define REPS \
++ REP(0) REP(1) REP(2) REP(3) REP(4) REP(5) REP(6) REP(7) \
++ REP(8) REP(9) REP(10) REP(11) REP(12) REP(13) REP(14) REP(15)
++
++/* Defines 16 leaf functions named f1_0 to f1_15 */
++#define REP(n) \
++ __attribute__ ((noinline, noclone, weak)) void f1_##n (void) {};
++REPS
++#undef REP
++
++/* Calls all 16 leaf functions f1_* in succession */
++__attribute__ ((noinline, noclone, weak)) void
++f2 (void)
++{
++# define REP(n) f1_##n();
++ REPS
++# undef REP
++ PREVENT_TAIL_CALL;
++}
++
++/* Defines 16 functions named f2_0 to f2_15, which all just call f2 */
++#define REP(n) \
++ __attribute__ ((noinline, noclone, weak)) void \
++ f2_##n (void) { f2(); PREVENT_TAIL_CALL; };
++REPS
++#undef REP
++
++__attribute__ ((noinline, noclone, weak)) void
++f3 (int count)
++{
++ for (int i = 0; i < count; ++i)
++ {
++ /* Calls f1_0(), f2_0(), f1_1(), f2_1(), f3_0(), etc */
++# define REP(n) f1_##n(); f2_##n();
++ REPS
++# undef REP
++ }
++}
++
++int
++main (void)
++{
++ f3 (1000);
++ return 0;
++}
+diff --git a/manual/tunables.texi b/manual/tunables.texi
+index 00a83b0c..ff98a18f 100644
+--- a/manual/tunables.texi
++++ b/manual/tunables.texi
+@@ -77,6 +77,9 @@ glibc.malloc.check: 0 (min: 0, max: 3)
+ capabilities seen by @theglibc{}
+ * Memory Related Tunables:: Tunables that control the use of memory by
+ @theglibc{}.
++* gmon Tunables:: Tunables that control the gmon profiler, used in
++ conjunction with gprof
++
+ @end menu
+
+ @node Tunable names
+@@ -598,3 +601,59 @@ support in the kernel if this tunable has any non-zero value.
+
+ The default value is @samp{0}, which disables all memory tagging.
+ @end deftp
++
++@node gmon Tunables
++@section gmon Tunables
++@cindex gmon tunables
++
++@deftp {Tunable namespace} glibc.gmon
++This tunable namespace affects the behaviour of the gmon profiler.
++gmon is a component of @theglibc{} which is normally used in
++conjunction with gprof.
++
++When GCC compiles a program with the @code{-pg} option, it instruments
++the program with calls to the @code{mcount} function, to record the
++program's call graph. At program startup, a memory buffer is allocated
++to store this call graph; the size of the buffer is calculated using a
++heuristic based on code size. If during execution, the buffer is found
++to be too small, profiling will be aborted and no @file{gmon.out} file
++will be produced. In that case, you will see the following message
++printed to standard error:
++
++@example
++mcount: call graph buffer size limit exceeded, gmon.out will not be generated
++@end example
++
++Most of the symbols discussed in this section are defined in the header
++@code{sys/gmon.h}. However, some symbols (for example @code{mcount})
++are not defined in any header file, since they are only intended to be
++called from code generated by the compiler.
++@end deftp
++
++@deftp Tunable glibc.mem.minarcs
++The heuristic for sizing the call graph buffer is known to be
++insufficient for small programs; hence, the calculated value is clamped
++to be at least a minimum size. The default minimum (in units of
++call graph entries, @code{struct tostruct}), is given by the macro
++@code{MINARCS}. If you have some program with an unusually complex
++call graph, for which the heuristic fails to allocate enough space,
++you can use this tunable to increase the minimum to a larger value.
++@end deftp
++
++@deftp Tunable glibc.mem.maxarcs
++To prevent excessive memory consumption when profiling very large
++programs, the call graph buffer is allowed to have a maximum of
++@code{MAXARCS} entries. For some very large programs, the default
++value of @code{MAXARCS} defined in @file{sys/gmon.h} is too small; in
++that case, you can use this tunable to increase it.
++
++Note the value of the @code{maxarcs} tunable must be greater or equal
++to that of the @code{minarcs} tunable; if this constraint is violated,
++a warning will printed to standard error at program startup, and
++the @code{minarcs} value will be used as the maximum as well.
++
++Setting either tunable too high may result in a call graph buffer
++whose size exceeds the available memory; in that case, an out of memory
++error will be printed at program startup, the profiler will be
++disabled, and no @file{gmon.out} file will be generated.
++@end deftp
+--
+2.33.0
+
diff --git a/backport-ldconfig-Fixes-for-skipping-temporary-files.patch b/backport-ldconfig-Fixes-for-skipping-temporary-files.patch
new file mode 100644
index 0000000..1fa1061
--- /dev/null
+++ b/backport-ldconfig-Fixes-for-skipping-temporary-files.patch
@@ -0,0 +1,68 @@
+From cfb5a97a93ea656e3b2263e42142a4032986d9ba Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 23 Oct 2023 12:53:16 +0200
+Subject: [PATCH] ldconfig: Fixes for skipping temporary files.
+
+Arguments to a memchr call were swapped, causing incorrect skipping
+of files.
+
+Files related to dpkg have different names: they actually end in
+.dpkg-new and .dpkg-tmp, not .tmp as I mistakenly assumed.
+
+Fixes commit 2aa0974d2573441bffd59 ("elf: ldconfig should skip
+temporary files created by package managers").
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=cfb5a97a93ea656e3b2263e42142a4032986d9ba
+---
+ elf/ldconfig.c | 19 +++++++++++++++----
+ 1 file changed, 15 insertions(+), 4 deletions(-)
+
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index 73b5ef27..5812a951 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -746,6 +746,17 @@ struct dlib_entry
+ struct dlib_entry *next;
+ };
+
++/* Return true if the N bytes at NAME end with with the characters in
++ the string SUFFIX. (NAME[N + 1] does not have to be a null byte.)
++ Expected to be called with a string literal for SUFFIX. */
++static inline bool
++endswithn (const char *name, size_t n, const char *suffix)
++{
++ return (n >= strlen (suffix)
++ && memcmp (name + n - strlen (suffix), suffix,
++ strlen (suffix)) == 0);
++}
++
+ /* Skip some temporary DSO files. These files may be partially written
+ and lead to ldconfig crashes when examined. */
+ static bool
+@@ -755,8 +766,7 @@ skip_dso_based_on_name (const char *name, size_t len)
+ names like these are never really DSOs we want to look at. */
+ if (len >= sizeof (".#prelink#") - 1)
+ {
+- if (strcmp (name + len - sizeof (".#prelink#") + 1,
+- ".#prelink#") == 0)
++ if (endswithn (name, len, ".#prelink#"))
+ return true;
+ if (len >= sizeof (".#prelink#.XXXXXX") - 1
+ && memcmp (name + len - sizeof (".#prelink#.XXXXXX")
+@@ -764,10 +774,11 @@ skip_dso_based_on_name (const char *name, size_t len)
+ return true;
+ }
+ /* Skip temporary files created by RPM. */
+- if (memchr (name, len, ';') != NULL)
++ if (memchr (name, ';', len) != NULL)
+ return true;
+ /* Skip temporary files created by dpkg. */
+- if (len > 4 && memcmp (name + len - 4, ".tmp", 4) == 0)
++ if (endswithn (name, len, ".dpkg-new")
++ || endswithn (name, len, ".dpkg-tmp"))
+ return true;
+ return false;
+ }
+--
+2.33.0
+
diff --git a/backport-localedata-Adjust-C.UTF-8-to-align-with-C-POSIX.patch b/backport-localedata-Adjust-C.UTF-8-to-align-with-C-POSIX.patch
new file mode 100644
index 0000000..31a6cbb
--- /dev/null
+++ b/backport-localedata-Adjust-C.UTF-8-to-align-with-C-POSIX.patch
@@ -0,0 +1,702 @@
+From 7e0ad15c0fbfe25435c1acd0ed3e9cedfbff2488 Mon Sep 17 00:00:00 2001
+From: Carlos O'Donell <carlos@redhat.com>
+Date: Mon, 31 Jan 2022 00:34:42 -0500
+Subject: [PATCH] localedata: Adjust C.UTF-8 to align with C/POSIX.
+
+We have had one downstream report from Canonical [1] that
+an rrdtool test was broken by the differences in LC_TIME
+that we had in the non-builtin C locale (C.UTF-8). If one
+application has an issue there are going to be others, and
+so with this commit we review and fix all the issues that
+cause the builtin C locale to be different from C.UTF-8,
+which includes:
+* mon_decimal_point should be empty e.g. ""
+ - Depends on mon_decimal_point_wc fix.
+* negative_sign should be empty e.g. ""
+* week should be aligned with the builtin C/POSIX locale
+* d_fmt corrected with escaped slashes e.g. "%m//%d//%y"
+* yesstr and nostr should be empty e.g. ""
+* country_ab2 and country_ab3 should be empty e.g. ""
+
+We bump LC_IDENTIFICATION version and adjust the date to
+indicate the change in the locale.
+
+A new tst-c-utf8-consistency test is added to ensure
+consistency between C/POSIX and C.UTF-8.
+
+Tested on x86_64 and i686 without regression.
+
+[1] https://sourceware.org/pipermail/libc-alpha/2022-January/135703.html
+
+Co-authored-by: Florian Weimer <fweimer@redhat.com>
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=7e0ad15c0fbfe25435c1acd0ed3e9cedfbff2488
+---
+ localedata/Makefile | 30 +-
+ localedata/locales/C | 22 +-
+ localedata/tst-c-utf8-consistency.c | 539 ++++++++++++++++++++++++++++
+ 3 files changed, 578 insertions(+), 13 deletions(-)
+ create mode 100644 localedata/tst-c-utf8-consistency.c
+
+diff --git a/localedata/Makefile b/localedata/Makefile
+index 79db713925..9ae2e5c161 100644
+--- a/localedata/Makefile
++++ b/localedata/Makefile
+@@ -155,11 +155,31 @@ locale_test_suite := tst_iswalnum tst_iswalpha tst_iswcntrl \
+ tst_wcsxfrm tst_wctob tst_wctomb tst_wctrans \
+ tst_wctype tst_wcwidth
+
+-tests = $(locale_test_suite) tst-digits tst-setlocale bug-iconv-trans \
+- tst-leaks tst-mbswcs1 tst-mbswcs2 tst-mbswcs3 tst-mbswcs4 tst-mbswcs5 \
+- tst-mbswcs6 tst-xlocale1 tst-xlocale2 bug-usesetlocale \
+- tst-strfmon1 tst-sscanf bug-setlocale1 tst-setlocale2 tst-setlocale3 \
+- tst-wctype tst-iconv-math-trans
++tests = \
++ $(locale_test_suite) \
++ bug-iconv-trans \
++ bug-setlocale1 \
++ bug-usesetlocale \
++ tst-c-utf8-consistency \
++ tst-digits \
++ tst-iconv-math-trans \
++ tst-leaks \
++ tst-mbswcs1 \
++ tst-mbswcs2 \
++ tst-mbswcs3 \
++ tst-mbswcs4 \
++ tst-mbswcs5 \
++ tst-mbswcs6 \
++ tst-setlocale \
++ tst-setlocale2 \
++ tst-setlocale3 \
++ tst-sscanf \
++ tst-strfmon1 \
++ tst-wctype \
++ tst-xlocale1 \
++ tst-xlocale2 \
++ # tests
++
+ tests-static = bug-setlocale1-static
+ tests += $(tests-static)
+ ifeq (yes,$(build-shared))
+diff --git a/localedata/locales/C b/localedata/locales/C
+index ca801c79cf..fc0614e551 100644
+--- a/localedata/locales/C
++++ b/localedata/locales/C
+@@ -12,8 +12,8 @@ tel ""
+ fax ""
+ language ""
+ territory ""
+-revision "2.0"
+-date "2020-06-28"
++revision "2.1"
++date "2022-01-30"
+ category "i18n:2012";LC_IDENTIFICATION
+ category "i18n:2012";LC_CTYPE
+ category "i18n:2012";LC_COLLATE
+@@ -68,11 +68,11 @@ LC_MONETARY
+ % glibc/locale/C-monetary.c.).
+ int_curr_symbol ""
+ currency_symbol ""
+-mon_decimal_point "."
++mon_decimal_point ""
+ mon_thousands_sep ""
+ mon_grouping -1
+ positive_sign ""
+-negative_sign "-"
++negative_sign ""
+ int_frac_digits -1
+ frac_digits -1
+ p_cs_precedes -1
+@@ -121,7 +121,9 @@ mon "January";"February";"March";"April";"May";"June";"July";/
+ %
+ % ISO 8601 conforming applications should use the values 7, 19971201 (a
+ % Monday), and 4 (Thursday), respectively.
+-week 7;19971201;4
++%
++% This field is consciously aligned with the builtin C/POSIX locale.
++week 7;19971130;4
+ first_weekday 1
+ first_workday 2
+
+@@ -129,7 +131,7 @@ first_workday 2
+ d_t_fmt "%a %b %e %H:%M:%S %Y"
+
+ % Appropriate date representation (%x)
+-d_fmt "%m/%d/%y"
++d_fmt "%m//%d//%y"
+
+ % Appropriate time representation (%X)
+ t_fmt "%H:%M:%S"
+@@ -150,8 +152,8 @@ LC_MESSAGES
+ %
+ yesexpr "^[yY]"
+ noexpr "^[nN]"
+-yesstr "Yes"
+-nostr "No"
++yesstr ""
++nostr ""
+ END LC_MESSAGES
+
+ LC_PAPER
+@@ -175,6 +177,10 @@ LC_ADDRESS
+ % the LC_ADDRESS category.
+ % (also used in the built in C/POSIX locale in glibc/locale/C-address.c)
+ postal_fmt "%a%N%f%N%d%N%b%N%s %h %e %r%N%C-%z %T%N%c%N"
++% The abbreviated 2 char and 3 char should be set to empty strings to
++% match the C/POSIX locale.
++country_ab2 ""
++country_ab3 ""
+ END LC_ADDRESS
+
+ LC_TELEPHONE
+diff --git a/localedata/tst-c-utf8-consistency.c b/localedata/tst-c-utf8-consistency.c
+new file mode 100644
+index 0000000000..50feed3090
+--- /dev/null
++++ b/localedata/tst-c-utf8-consistency.c
+@@ -0,0 +1,539 @@
++/* Test that C/POSIX and C.UTF-8 are consistent.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <langinfo.h>
++#include <locale.h>
++#include <stdbool.h>
++#include <stdio.h>
++#include <support/check.h>
++
++/* Initialized by do_test using newlocale. */
++static locale_t c_utf8;
++
++/* Set to true for second pass. */
++static bool use_nl_langinfo_l;
++
++static void
++switch_to_c (void)
++{
++ if (setlocale (LC_ALL, "C") == NULL)
++ FAIL_EXIT1 ("setlocale (LC_ALL, \"C\")");
++}
++
++static void
++switch_to_c_utf8 (void)
++{
++ if (setlocale (LC_ALL, "C.UTF-8") == NULL)
++ FAIL_EXIT1 ("setlocale (LC_ALL, \"C.UTF-8\")");
++}
++
++static char *
++str (nl_item item)
++{
++ if (!use_nl_langinfo_l)
++ switch_to_c ();
++ return nl_langinfo (item);
++}
++
++static char *
++str_utf8 (nl_item item)
++{
++ if (use_nl_langinfo_l)
++ return nl_langinfo_l (item, c_utf8);
++ else
++ {
++ switch_to_c_utf8 ();
++ return nl_langinfo (item);
++ }
++}
++
++static wchar_t *
++wstr (nl_item item)
++{
++ return (wchar_t *) str (item);
++}
++
++static wchar_t *
++wstr_utf8 (nl_item item)
++{
++ return (wchar_t *) str_utf8 (item);
++}
++
++static int
++byte (nl_item item)
++{
++ return (signed char) *str (item);
++}
++
++static int
++byte_utf8 (nl_item item)
++{
++ return (signed char) *str_utf8 (item);
++}
++
++static int
++word (nl_item item)
++{
++ union
++ {
++ char *ptr;
++ int word;
++ } u;
++ u.ptr = str (item);
++ return u.word;
++}
++
++static int
++word_utf8 (nl_item item)
++{
++ union
++ {
++ char *ptr;
++ int word;
++ } u;
++ u.ptr = str_utf8 (item);
++ return u.word;
++}
++
++static void
++one_pass (void)
++{
++ /* LC_TIME. */
++ TEST_COMPARE_STRING (str (ABDAY_1), str_utf8 (ABDAY_1));
++ TEST_COMPARE_STRING (str (ABDAY_2), str_utf8 (ABDAY_2));
++ TEST_COMPARE_STRING (str (ABDAY_3), str_utf8 (ABDAY_3));
++ TEST_COMPARE_STRING (str (ABDAY_4), str_utf8 (ABDAY_4));
++ TEST_COMPARE_STRING (str (ABDAY_5), str_utf8 (ABDAY_5));
++ TEST_COMPARE_STRING (str (ABDAY_6), str_utf8 (ABDAY_6));
++ TEST_COMPARE_STRING (str (ABDAY_7), str_utf8 (ABDAY_7));
++
++ TEST_COMPARE_STRING (str (DAY_1), str_utf8 (DAY_1));
++ TEST_COMPARE_STRING (str (DAY_2), str_utf8 (DAY_2));
++ TEST_COMPARE_STRING (str (DAY_3), str_utf8 (DAY_3));
++ TEST_COMPARE_STRING (str (DAY_4), str_utf8 (DAY_4));
++ TEST_COMPARE_STRING (str (DAY_5), str_utf8 (DAY_5));
++ TEST_COMPARE_STRING (str (DAY_6), str_utf8 (DAY_6));
++ TEST_COMPARE_STRING (str (DAY_7), str_utf8 (DAY_7));
++
++ TEST_COMPARE_STRING (str (ABMON_1), str_utf8 (ABMON_1));
++ TEST_COMPARE_STRING (str (ABMON_2), str_utf8 (ABMON_2));
++ TEST_COMPARE_STRING (str (ABMON_3), str_utf8 (ABMON_3));
++ TEST_COMPARE_STRING (str (ABMON_4), str_utf8 (ABMON_4));
++ TEST_COMPARE_STRING (str (ABMON_5), str_utf8 (ABMON_5));
++ TEST_COMPARE_STRING (str (ABMON_6), str_utf8 (ABMON_6));
++ TEST_COMPARE_STRING (str (ABMON_7), str_utf8 (ABMON_7));
++ TEST_COMPARE_STRING (str (ABMON_8), str_utf8 (ABMON_8));
++ TEST_COMPARE_STRING (str (ABMON_9), str_utf8 (ABMON_9));
++ TEST_COMPARE_STRING (str (ABMON_10), str_utf8 (ABMON_10));
++ TEST_COMPARE_STRING (str (ABMON_11), str_utf8 (ABMON_11));
++ TEST_COMPARE_STRING (str (ABMON_12), str_utf8 (ABMON_12));
++
++ TEST_COMPARE_STRING (str (MON_1), str_utf8 (MON_1));
++ TEST_COMPARE_STRING (str (MON_2), str_utf8 (MON_2));
++ TEST_COMPARE_STRING (str (MON_3), str_utf8 (MON_3));
++ TEST_COMPARE_STRING (str (MON_4), str_utf8 (MON_4));
++ TEST_COMPARE_STRING (str (MON_5), str_utf8 (MON_5));
++ TEST_COMPARE_STRING (str (MON_6), str_utf8 (MON_6));
++ TEST_COMPARE_STRING (str (MON_7), str_utf8 (MON_7));
++ TEST_COMPARE_STRING (str (MON_8), str_utf8 (MON_8));
++ TEST_COMPARE_STRING (str (MON_9), str_utf8 (MON_9));
++ TEST_COMPARE_STRING (str (MON_10), str_utf8 (MON_10));
++ TEST_COMPARE_STRING (str (MON_11), str_utf8 (MON_11));
++ TEST_COMPARE_STRING (str (MON_12), str_utf8 (MON_12));
++
++ TEST_COMPARE_STRING (str (AM_STR), str_utf8 (AM_STR));
++ TEST_COMPARE_STRING (str (PM_STR), str_utf8 (PM_STR));
++
++ TEST_COMPARE_STRING (str (D_T_FMT), str_utf8 (D_T_FMT));
++ TEST_COMPARE_STRING (str (D_FMT), str_utf8 (D_FMT));
++ TEST_COMPARE_STRING (str (T_FMT), str_utf8 (T_FMT));
++ TEST_COMPARE_STRING (str (T_FMT_AMPM),
++ str_utf8 (T_FMT_AMPM));
++
++ TEST_COMPARE_STRING (str (ERA), str_utf8 (ERA));
++ TEST_COMPARE_STRING (str (ERA_YEAR), str_utf8 (ERA_YEAR));
++ TEST_COMPARE_STRING (str (ERA_D_FMT), str_utf8 (ERA_D_FMT));
++ TEST_COMPARE_STRING (str (ALT_DIGITS), str_utf8 (ALT_DIGITS));
++ TEST_COMPARE_STRING (str (ERA_D_T_FMT), str_utf8 (ERA_D_T_FMT));
++ TEST_COMPARE_STRING (str (ERA_T_FMT), str_utf8 (ERA_T_FMT));
++ TEST_COMPARE (word (_NL_TIME_ERA_NUM_ENTRIES),
++ word_utf8 (_NL_TIME_ERA_NUM_ENTRIES));
++ /* No array elements, so nothing to compare for _NL_TIME_ERA_ENTRIES. */
++ TEST_COMPARE (word (_NL_TIME_ERA_NUM_ENTRIES), 0);
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_1), wstr_utf8 (_NL_WABDAY_1));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_2), wstr_utf8 (_NL_WABDAY_2));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_3), wstr_utf8 (_NL_WABDAY_3));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_4), wstr_utf8 (_NL_WABDAY_4));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_5), wstr_utf8 (_NL_WABDAY_5));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_6), wstr_utf8 (_NL_WABDAY_6));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABDAY_7), wstr_utf8 (_NL_WABDAY_7));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_1), wstr_utf8 (_NL_WDAY_1));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_2), wstr_utf8 (_NL_WDAY_2));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_3), wstr_utf8 (_NL_WDAY_3));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_4), wstr_utf8 (_NL_WDAY_4));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_5), wstr_utf8 (_NL_WDAY_5));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_6), wstr_utf8 (_NL_WDAY_6));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WDAY_7), wstr_utf8 (_NL_WDAY_7));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_1), wstr_utf8 (_NL_WABMON_1));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_2), wstr_utf8 (_NL_WABMON_2));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_3), wstr_utf8 (_NL_WABMON_3));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_4), wstr_utf8 (_NL_WABMON_4));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_5), wstr_utf8 (_NL_WABMON_5));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_6), wstr_utf8 (_NL_WABMON_6));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_7), wstr_utf8 (_NL_WABMON_7));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_8), wstr_utf8 (_NL_WABMON_8));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_9), wstr_utf8 (_NL_WABMON_9));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_10), wstr_utf8 (_NL_WABMON_10));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_11), wstr_utf8 (_NL_WABMON_11));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABMON_12), wstr_utf8 (_NL_WABMON_12));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_1), wstr_utf8 (_NL_WMON_1));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_2), wstr_utf8 (_NL_WMON_2));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_3), wstr_utf8 (_NL_WMON_3));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_4), wstr_utf8 (_NL_WMON_4));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_5), wstr_utf8 (_NL_WMON_5));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_6), wstr_utf8 (_NL_WMON_6));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_7), wstr_utf8 (_NL_WMON_7));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_8), wstr_utf8 (_NL_WMON_8));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_9), wstr_utf8 (_NL_WMON_9));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_10), wstr_utf8 (_NL_WMON_10));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_11), wstr_utf8 (_NL_WMON_11));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WMON_12), wstr_utf8 (_NL_WMON_12));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WAM_STR), wstr_utf8 (_NL_WAM_STR));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WPM_STR), wstr_utf8 (_NL_WPM_STR));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WD_T_FMT), wstr_utf8 (_NL_WD_T_FMT));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WD_FMT), wstr_utf8 (_NL_WD_FMT));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WT_FMT), wstr_utf8 (_NL_WT_FMT));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WT_FMT_AMPM),
++ wstr_utf8 (_NL_WT_FMT_AMPM));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_YEAR), wstr_utf8 (_NL_WERA_YEAR));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_D_FMT), wstr_utf8 (_NL_WERA_D_FMT));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALT_DIGITS),
++ wstr_utf8 (_NL_WALT_DIGITS));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_D_T_FMT),
++ wstr_utf8 (_NL_WERA_D_T_FMT));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WERA_T_FMT), wstr_utf8 (_NL_WERA_T_FMT));
++
++ /* This is somewhat inconsistent, but see locale/categories.def. */
++ TEST_COMPARE (byte (_NL_TIME_WEEK_NDAYS), byte_utf8 (_NL_TIME_WEEK_NDAYS));
++ TEST_COMPARE (word (_NL_TIME_WEEK_1STDAY),
++ word_utf8 (_NL_TIME_WEEK_1STDAY));
++ TEST_COMPARE (byte (_NL_TIME_WEEK_1STWEEK),
++ byte_utf8 (_NL_TIME_WEEK_1STWEEK));
++ TEST_COMPARE (byte (_NL_TIME_FIRST_WEEKDAY),
++ byte_utf8 (_NL_TIME_FIRST_WEEKDAY));
++ TEST_COMPARE (byte (_NL_TIME_FIRST_WORKDAY),
++ byte_utf8 (_NL_TIME_FIRST_WORKDAY));
++ TEST_COMPARE (byte (_NL_TIME_CAL_DIRECTION),
++ byte_utf8 (_NL_TIME_CAL_DIRECTION));
++ TEST_COMPARE_STRING (str (_NL_TIME_TIMEZONE), str_utf8 (_NL_TIME_TIMEZONE));
++
++ TEST_COMPARE_STRING (str (_DATE_FMT), str_utf8 (_DATE_FMT));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_W_DATE_FMT), wstr_utf8 (_NL_W_DATE_FMT));
++
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_TIME_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_TIME_CODESET), "UTF-8");
++
++ TEST_COMPARE_STRING (str (ALTMON_1), str_utf8 (ALTMON_1));
++ TEST_COMPARE_STRING (str (ALTMON_2), str_utf8 (ALTMON_2));
++ TEST_COMPARE_STRING (str (ALTMON_3), str_utf8 (ALTMON_3));
++ TEST_COMPARE_STRING (str (ALTMON_4), str_utf8 (ALTMON_4));
++ TEST_COMPARE_STRING (str (ALTMON_5), str_utf8 (ALTMON_5));
++ TEST_COMPARE_STRING (str (ALTMON_6), str_utf8 (ALTMON_6));
++ TEST_COMPARE_STRING (str (ALTMON_7), str_utf8 (ALTMON_7));
++ TEST_COMPARE_STRING (str (ALTMON_8), str_utf8 (ALTMON_8));
++ TEST_COMPARE_STRING (str (ALTMON_9), str_utf8 (ALTMON_9));
++ TEST_COMPARE_STRING (str (ALTMON_10), str_utf8 (ALTMON_10));
++ TEST_COMPARE_STRING (str (ALTMON_11), str_utf8 (ALTMON_11));
++ TEST_COMPARE_STRING (str (ALTMON_12), str_utf8 (ALTMON_12));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_1), wstr_utf8 (_NL_WALTMON_1));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_2), wstr_utf8 (_NL_WALTMON_2));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_3), wstr_utf8 (_NL_WALTMON_3));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_4), wstr_utf8 (_NL_WALTMON_4));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_5), wstr_utf8 (_NL_WALTMON_5));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_6), wstr_utf8 (_NL_WALTMON_6));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_7), wstr_utf8 (_NL_WALTMON_7));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_8), wstr_utf8 (_NL_WALTMON_8));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_9), wstr_utf8 (_NL_WALTMON_9));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_10), wstr_utf8 (_NL_WALTMON_10));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_11), wstr_utf8 (_NL_WALTMON_11));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WALTMON_12), wstr_utf8 (_NL_WALTMON_12));
++
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_1), str_utf8 (_NL_ABALTMON_1));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_2), str_utf8 (_NL_ABALTMON_2));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_3), str_utf8 (_NL_ABALTMON_3));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_4), str_utf8 (_NL_ABALTMON_4));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_5), str_utf8 (_NL_ABALTMON_5));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_6), str_utf8 (_NL_ABALTMON_6));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_7), str_utf8 (_NL_ABALTMON_7));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_8), str_utf8 (_NL_ABALTMON_8));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_9), str_utf8 (_NL_ABALTMON_9));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_10), str_utf8 (_NL_ABALTMON_10));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_11), str_utf8 (_NL_ABALTMON_11));
++ TEST_COMPARE_STRING (str (_NL_ABALTMON_12), str_utf8 (_NL_ABALTMON_12));
++
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_1),
++ wstr_utf8 (_NL_WABALTMON_1));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_2),
++ wstr_utf8 (_NL_WABALTMON_2));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_3),
++ wstr_utf8 (_NL_WABALTMON_3));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_4),
++ wstr_utf8 (_NL_WABALTMON_4));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_5),
++ wstr_utf8 (_NL_WABALTMON_5));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_6),
++ wstr_utf8 (_NL_WABALTMON_6));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_7),
++ wstr_utf8 (_NL_WABALTMON_7));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_8),
++ wstr_utf8 (_NL_WABALTMON_8));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_9),
++ wstr_utf8 (_NL_WABALTMON_9));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_10),
++ wstr_utf8 (_NL_WABALTMON_10));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_11),
++ wstr_utf8 (_NL_WABALTMON_11));
++ TEST_COMPARE_STRING_WIDE (wstr (_NL_WABALTMON_12),
++ wstr_utf8 (_NL_WABALTMON_12));
++
++ /* LC_COLLATE. Mostly untested, only expected differences. */
++ TEST_COMPARE_STRING (str (_NL_COLLATE_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_COLLATE_CODESET), "UTF-8");
++
++ /* LC_CTYPE. Mostly untested, only expected differences. */
++ TEST_COMPARE_STRING (str (CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (CODESET), "UTF-8");
++
++ /* LC_MONETARY. */
++ TEST_COMPARE_STRING (str (INT_CURR_SYMBOL), str_utf8 (INT_CURR_SYMBOL));
++ TEST_COMPARE_STRING (str (CURRENCY_SYMBOL), str_utf8 (CURRENCY_SYMBOL));
++ TEST_COMPARE_STRING (str (MON_DECIMAL_POINT), str_utf8 (MON_DECIMAL_POINT));
++ TEST_COMPARE_STRING (str (MON_THOUSANDS_SEP), str_utf8 (MON_THOUSANDS_SEP));
++ TEST_COMPARE_STRING (str (MON_GROUPING), str_utf8 (MON_GROUPING));
++ TEST_COMPARE_STRING (str (POSITIVE_SIGN), str_utf8 (POSITIVE_SIGN));
++ TEST_COMPARE_STRING (str (NEGATIVE_SIGN), str_utf8 (NEGATIVE_SIGN));
++ TEST_COMPARE (byte (INT_FRAC_DIGITS), byte_utf8 (INT_FRAC_DIGITS));
++ TEST_COMPARE (byte (FRAC_DIGITS), byte_utf8 (FRAC_DIGITS));
++ TEST_COMPARE (byte (P_CS_PRECEDES), byte_utf8 (P_CS_PRECEDES));
++ TEST_COMPARE (byte (P_SEP_BY_SPACE), byte_utf8 (P_SEP_BY_SPACE));
++ TEST_COMPARE (byte (N_CS_PRECEDES), byte_utf8 (N_CS_PRECEDES));
++ TEST_COMPARE (byte (N_SEP_BY_SPACE), byte_utf8 (N_SEP_BY_SPACE));
++ TEST_COMPARE (byte (P_SIGN_POSN), byte_utf8 (P_SIGN_POSN));
++ TEST_COMPARE (byte (N_SIGN_POSN), byte_utf8 (N_SIGN_POSN));
++ TEST_COMPARE_STRING (str (CRNCYSTR), str_utf8 (CRNCYSTR));
++ TEST_COMPARE (byte (INT_P_CS_PRECEDES), byte_utf8 (INT_P_CS_PRECEDES));
++ TEST_COMPARE (byte (INT_P_SEP_BY_SPACE), byte_utf8 (INT_P_SEP_BY_SPACE));
++ TEST_COMPARE (byte (INT_N_CS_PRECEDES), byte_utf8 (INT_N_CS_PRECEDES));
++ TEST_COMPARE (byte (INT_N_SEP_BY_SPACE), byte_utf8 (INT_N_SEP_BY_SPACE));
++ TEST_COMPARE (byte (INT_P_SIGN_POSN), byte_utf8 (INT_P_SIGN_POSN));
++ TEST_COMPARE (byte (INT_N_SIGN_POSN), byte_utf8 (INT_N_SIGN_POSN));
++ TEST_COMPARE_STRING (str (_NL_MONETARY_DUO_INT_CURR_SYMBOL),
++ str_utf8 (_NL_MONETARY_DUO_INT_CURR_SYMBOL));
++ TEST_COMPARE_STRING (str (_NL_MONETARY_DUO_CURRENCY_SYMBOL),
++ str_utf8 (_NL_MONETARY_DUO_CURRENCY_SYMBOL));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_FRAC_DIGITS),
++ byte_utf8 (_NL_MONETARY_DUO_INT_FRAC_DIGITS));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_FRAC_DIGITS),
++ byte_utf8 (_NL_MONETARY_DUO_FRAC_DIGITS));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_CS_PRECEDES),
++ byte_utf8 (_NL_MONETARY_DUO_P_CS_PRECEDES));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_SEP_BY_SPACE),
++ byte_utf8 (_NL_MONETARY_DUO_P_SEP_BY_SPACE));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_CS_PRECEDES),
++ byte_utf8 (_NL_MONETARY_DUO_N_CS_PRECEDES));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_SEP_BY_SPACE),
++ byte_utf8 (_NL_MONETARY_DUO_N_SEP_BY_SPACE));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_CS_PRECEDES),
++ byte_utf8 (_NL_MONETARY_DUO_INT_P_CS_PRECEDES));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE),
++ byte_utf8 (_NL_MONETARY_DUO_INT_P_SEP_BY_SPACE));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_CS_PRECEDES),
++ byte_utf8 (_NL_MONETARY_DUO_INT_N_CS_PRECEDES));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE),
++ byte_utf8 (_NL_MONETARY_DUO_INT_N_SEP_BY_SPACE));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SIGN_POSN),
++ byte_utf8 (_NL_MONETARY_DUO_INT_P_SIGN_POSN));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SIGN_POSN),
++ byte_utf8 (_NL_MONETARY_DUO_INT_N_SIGN_POSN));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_P_SIGN_POSN),
++ byte_utf8 (_NL_MONETARY_DUO_P_SIGN_POSN));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_N_SIGN_POSN),
++ byte_utf8 (_NL_MONETARY_DUO_N_SIGN_POSN));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_P_SIGN_POSN),
++ byte_utf8 (_NL_MONETARY_DUO_INT_P_SIGN_POSN));
++ TEST_COMPARE (byte (_NL_MONETARY_DUO_INT_N_SIGN_POSN),
++ byte_utf8 (_NL_MONETARY_DUO_INT_N_SIGN_POSN));
++ TEST_COMPARE (word (_NL_MONETARY_UNO_VALID_FROM),
++ word_utf8 (_NL_MONETARY_UNO_VALID_FROM));
++ TEST_COMPARE (word (_NL_MONETARY_UNO_VALID_TO),
++ word_utf8 (_NL_MONETARY_UNO_VALID_TO));
++ TEST_COMPARE (word (_NL_MONETARY_DUO_VALID_FROM),
++ word_utf8 (_NL_MONETARY_DUO_VALID_FROM));
++ TEST_COMPARE (word (_NL_MONETARY_DUO_VALID_TO),
++ word_utf8 (_NL_MONETARY_DUO_VALID_TO));
++ /* _NL_MONETARY_CONVERSION_RATE cannot be tested (word array). */
++ TEST_COMPARE (word (_NL_MONETARY_DECIMAL_POINT_WC),
++ word_utf8 (_NL_MONETARY_DECIMAL_POINT_WC));
++ TEST_COMPARE (word (_NL_MONETARY_THOUSANDS_SEP_WC),
++ word_utf8 (_NL_MONETARY_THOUSANDS_SEP_WC));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_MONETARY_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_MONETARY_CODESET), "UTF-8");
++
++ /* LC_NUMERIC. */
++
++ TEST_COMPARE_STRING (str (DECIMAL_POINT), str_utf8 (DECIMAL_POINT));
++ TEST_COMPARE_STRING (str (RADIXCHAR), str_utf8 (RADIXCHAR));
++ TEST_COMPARE_STRING (str (THOUSANDS_SEP), str_utf8 (THOUSANDS_SEP));
++ TEST_COMPARE_STRING (str (THOUSEP), str_utf8 (THOUSEP));
++ TEST_COMPARE_STRING (str (GROUPING), str_utf8 (GROUPING));
++ TEST_COMPARE (word (_NL_NUMERIC_DECIMAL_POINT_WC),
++ word_utf8 (_NL_NUMERIC_DECIMAL_POINT_WC));
++ TEST_COMPARE (word (_NL_NUMERIC_THOUSANDS_SEP_WC),
++ word_utf8 (_NL_NUMERIC_THOUSANDS_SEP_WC));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_NUMERIC_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_NUMERIC_CODESET), "UTF-8");
++
++ /* LC_MESSAGES. */
++
++ TEST_COMPARE_STRING (str (YESEXPR), str_utf8 (YESEXPR));
++ TEST_COMPARE_STRING (str (NOEXPR), str_utf8 (NOEXPR));
++ TEST_COMPARE_STRING (str (YESSTR), str_utf8 (YESSTR));
++ TEST_COMPARE_STRING (str (NOSTR), str_utf8 (NOSTR));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_MESSAGES_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_MESSAGES_CODESET), "UTF-8");
++
++ /* LC_PAPER. */
++
++ TEST_COMPARE (word (_NL_PAPER_HEIGHT), word_utf8 (_NL_PAPER_HEIGHT));
++ TEST_COMPARE (word (_NL_PAPER_WIDTH), word_utf8 (_NL_PAPER_WIDTH));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_PAPER_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_PAPER_CODESET), "UTF-8");
++
++ /* LC_NAME. */
++
++ TEST_COMPARE_STRING (str (_NL_NAME_NAME_FMT),
++ str_utf8 (_NL_NAME_NAME_FMT));
++ TEST_COMPARE_STRING (str (_NL_NAME_NAME_GEN),
++ str_utf8 (_NL_NAME_NAME_GEN));
++ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MR),
++ str_utf8 (_NL_NAME_NAME_MR));
++ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MRS),
++ str_utf8 (_NL_NAME_NAME_MRS));
++ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MISS),
++ str_utf8 (_NL_NAME_NAME_MISS));
++ TEST_COMPARE_STRING (str (_NL_NAME_NAME_MS),
++ str_utf8 (_NL_NAME_NAME_MS));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_NAME_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_NAME_CODESET), "UTF-8");
++
++ /* LC_ADDRESS. */
++
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_POSTAL_FMT),
++ str_utf8 (_NL_ADDRESS_POSTAL_FMT));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_NAME),
++ str_utf8 (_NL_ADDRESS_COUNTRY_NAME));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_POST),
++ str_utf8 (_NL_ADDRESS_COUNTRY_POST));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_AB2),
++ str_utf8 (_NL_ADDRESS_COUNTRY_AB2));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_AB3),
++ str_utf8 (_NL_ADDRESS_COUNTRY_AB3));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_CAR),
++ str_utf8 (_NL_ADDRESS_COUNTRY_CAR));
++ TEST_COMPARE (word (_NL_ADDRESS_COUNTRY_NUM),
++ word_utf8 (_NL_ADDRESS_COUNTRY_NUM));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_COUNTRY_ISBN),
++ str_utf8 (_NL_ADDRESS_COUNTRY_ISBN));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_NAME),
++ str_utf8 (_NL_ADDRESS_LANG_NAME));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_AB),
++ str_utf8 (_NL_ADDRESS_LANG_AB));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_TERM),
++ str_utf8 (_NL_ADDRESS_LANG_TERM));
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_LANG_LIB),
++ str_utf8 (_NL_ADDRESS_LANG_LIB));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_ADDRESS_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_ADDRESS_CODESET), "UTF-8");
++
++ /* LC_TELEPHONE. */
++
++ TEST_COMPARE_STRING (str (_NL_TELEPHONE_TEL_INT_FMT),
++ str_utf8 (_NL_TELEPHONE_TEL_INT_FMT));
++ TEST_COMPARE_STRING (str (_NL_TELEPHONE_TEL_DOM_FMT),
++ str_utf8 (_NL_TELEPHONE_TEL_DOM_FMT));
++ TEST_COMPARE_STRING (str (_NL_TELEPHONE_INT_SELECT),
++ str_utf8 (_NL_TELEPHONE_INT_SELECT));
++ TEST_COMPARE_STRING (str (_NL_TELEPHONE_INT_PREFIX),
++ str_utf8 (_NL_TELEPHONE_INT_PREFIX));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_TELEPHONE_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_TELEPHONE_CODESET), "UTF-8");
++
++ /* LC_MEASUREMENT. */
++
++ TEST_COMPARE (byte (_NL_MEASUREMENT_MEASUREMENT),
++ byte_utf8 (_NL_MEASUREMENT_MEASUREMENT));
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_MEASUREMENT_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_MEASUREMENT_CODESET), "UTF-8");
++
++ /* LC_IDENTIFICATION is skipped since C.UTF-8 is distinct from C. */
++
++ /* _NL_IDENTIFICATION_CATEGORY cannot be tested because it is a
++ string array. */
++ /* Expected difference. */
++ TEST_COMPARE_STRING (str (_NL_IDENTIFICATION_CODESET), "ANSI_X3.4-1968");
++ TEST_COMPARE_STRING (str_utf8 (_NL_IDENTIFICATION_CODESET), "UTF-8");
++}
++
++static int
++do_test (void)
++{
++ puts ("info: using setlocale and nl_langinfo");
++ one_pass ();
++
++ puts ("info: using nl_langinfo_l");
++
++ c_utf8 = newlocale (LC_ALL_MASK, "C.UTF-8", (locale_t) 0);
++ TEST_VERIFY_EXIT (c_utf8 != (locale_t) 0);
++
++ switch_to_c ();
++ use_nl_langinfo_l = true;
++ one_pass ();
++
++ freelocale (c_utf8);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.28.0.windows.1
+
diff --git a/backport-localedef-Fix-handling-of-empty-mon_decimal_point-Bu.patch b/backport-localedef-Fix-handling-of-empty-mon_decimal_point-Bu.patch
new file mode 100644
index 0000000..bb03288
--- /dev/null
+++ b/backport-localedef-Fix-handling-of-empty-mon_decimal_point-Bu.patch
@@ -0,0 +1,74 @@
+From 1d8e3a2c6636cf0b1b8fa2f869cef6ec10726933 Mon Sep 17 00:00:00 2001
+From: Carlos O'Donell <carlos@redhat.com>
+Date: Mon, 31 Jan 2022 00:34:41 -0500
+Subject: [PATCH] localedef: Fix handling of empty mon_decimal_point (Bug
+ 28847)
+
+The handling of mon_decimal_point is incorrect when it comes to
+handling the empty "" value. The existing parser in monetary_read()
+will correctly handle setting the non-wide-character value and the
+wide-character value e.g. STR_ELEM_WC(mon_decimal_point) if they are
+set in the locale definition. However, in monetary_finish() we have
+conflicting TEST_ELEM() which sets a default value (if the locale
+definition doesn't include one), and subsequent code which looks for
+mon_decimal_point to be NULL to issue a specific error message and set
+the defaults. The latter is unused because TEST_ELEM() always sets a
+default. The simplest solution is to remove the TEST_ELEM() check,
+and allow the existing check to look to see if mon_decimal_point is
+NULL and set an appropriate default. The final fix is to move the
+setting of mon_decimal_point_wc so it occurs only when
+mon_decimal_point is being set to a default, keeping both values
+consistent. There is no way to tell the difference between
+mon_decimal_point_wc having been set to the empty string and not
+having been defined at all, for that distinction we must use
+mon_decimal_point being NULL or "", and so we must logically set
+the default together with mon_decimal_point.
+
+Lastly, there are more fixes similar to this that could be made to
+ld-monetary.c, but we avoid that in order to fix just the code
+required for mon_decimal_point, which impacts the ability for C.UTF-8
+to set mon_decimal_point to "", since without this fix we end up with
+an inconsistent setting of mon_decimal_point set to "", but
+mon_decimal_point_wc set to "." which is incorrect.
+
+Tested on x86_64 and i686 without regression.
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=1d8e3a2c6636cf0b1b8fa2f869cef6ec10726933
+---
+ locale/programs/ld-monetary.c | 4 +---
+ 1 file changed, 1 insertion(+), 3 deletions(-)
+
+diff --git a/locale/programs/ld-monetary.c b/locale/programs/ld-monetary.c
+index 277b9ff042..3b0412b405 100644
+--- a/locale/programs/ld-monetary.c
++++ b/locale/programs/ld-monetary.c
+@@ -207,7 +207,6 @@ No definition for %s category found"), "LC_MONETARY");
+
+ TEST_ELEM (int_curr_symbol, "");
+ TEST_ELEM (currency_symbol, "");
+- TEST_ELEM (mon_decimal_point, ".");
+ TEST_ELEM (mon_thousands_sep, "");
+ TEST_ELEM (positive_sign, "");
+ TEST_ELEM (negative_sign, "");
+@@ -257,6 +256,7 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
+ record_error (0, 0, _("%s: field `%s' not defined"),
+ "LC_MONETARY", "mon_decimal_point");
+ monetary->mon_decimal_point = ".";
++ monetary->mon_decimal_point_wc = L'.';
+ }
+ else if (monetary->mon_decimal_point[0] == '\0' && ! be_quiet && ! nothing)
+ {
+@@ -264,8 +264,6 @@ not correspond to a valid name in ISO 4217 [--no-warnings=intcurrsym]"),
+ %s: value for field `%s' must not be an empty string"),
+ "LC_MONETARY", "mon_decimal_point");
+ }
+- if (monetary->mon_decimal_point_wc == L'\0')
+- monetary->mon_decimal_point_wc = L'.';
+
+ if (monetary->mon_grouping_len == 0)
+ {
+--
+2.28.0.windows.1
+
diff --git a/backport-mktime-improve-heuristic-for-ca-1986-Indiana-DST.patch b/backport-mktime-improve-heuristic-for-ca-1986-Indiana-DST.patch
new file mode 100644
index 0000000..0142918
--- /dev/null
+++ b/backport-mktime-improve-heuristic-for-ca-1986-Indiana-DST.patch
@@ -0,0 +1,78 @@
+From 675ba1f361ea424626b48a40cfd24d113dfc1b65 Mon Sep 17 00:00:00 2001
+From: Paul Eggert <eggert@cs.ucla.edu>
+Date: Thu, 8 Sep 2022 20:08:32 -0500
+Subject: [PATCH] mktime: improve heuristic for ca-1986 Indiana DST
+
+This patch syncs mktime.c from Gnulib, fixing a
+problem reported by Mark Krenz <https://bugs.gnu.org/48085>,
+and it should fix BZ#29035 too.
+* time/mktime.c (__mktime_internal): Be more generous about
+accepting arguments with the wrong value of tm_isdst, by falling
+back to a one-hour DST difference if we find no nearby DST that is
+unusual. This fixes a problem where "1986-04-28 00:00 EDT" was
+rejected when TZ="America/Indianapolis" because the nearest DST
+timestamp occurred in 1970, a temporal distance too great for the
+old heuristic. This also also narrows the search a bit, which
+is a minor performance win.
+
+(cherry picked from commit 83859e1115269cf56d21669361d4ddbe2687831c)
+---
+ time/mktime.c | 28 ++++++++++++++++++++--------
+ 1 file changed, 20 insertions(+), 8 deletions(-)
+
+diff --git a/time/mktime.c b/time/mktime.c
+index 8e78006eea..74d9bbaa5b 100644
+--- a/time/mktime.c
++++ b/time/mktime.c
+@@ -429,8 +429,13 @@ __mktime_internal (struct tm *tp,
+ time with the right value, and use its UTC offset.
+
+ Heuristic: probe the adjacent timestamps in both directions,
+- looking for the desired isdst. This should work for all real
+- time zone histories in the tz database. */
++ looking for the desired isdst. If none is found within a
++ reasonable duration bound, assume a one-hour DST difference.
++ This should work for all real time zone histories in the tz
++ database. */
++
++ /* +1 if we wanted standard time but got DST, -1 if the reverse. */
++ int dst_difference = (isdst == 0) - (tm.tm_isdst == 0);
+
+ /* Distance between probes when looking for a DST boundary. In
+ tzdata2003a, the shortest period of DST is 601200 seconds
+@@ -441,12 +446,14 @@ __mktime_internal (struct tm *tp,
+ periods when probing. */
+ int stride = 601200;
+
+- /* The longest period of DST in tzdata2003a is 536454000 seconds
+- (e.g., America/Jujuy starting 1946-10-01 01:00). The longest
+- period of non-DST is much longer, but it makes no real sense
+- to search for more than a year of non-DST, so use the DST
+- max. */
+- int duration_max = 536454000;
++ /* In TZDB 2021e, the longest period of DST (or of non-DST), in
++ which the DST (or adjacent DST) difference is not one hour,
++ is 457243209 seconds: e.g., America/Cambridge_Bay with leap
++ seconds, starting 1965-10-31 00:00 in a switch from
++ double-daylight time (-05) to standard time (-07), and
++ continuing to 1980-04-27 02:00 in a switch from standard time
++ (-07) to daylight time (-06). */
++ int duration_max = 457243209;
+
+ /* Search in both directions, so the maximum distance is half
+ the duration; add the stride to avoid off-by-1 problems. */
+@@ -483,6 +490,11 @@ __mktime_internal (struct tm *tp,
+ }
+ }
+
++ /* No unusual DST offset was found nearby. Assume one-hour DST. */
++ t += 60 * 60 * dst_difference;
++ if (mktime_min <= t && t <= mktime_max && convert_time (convert, t, &tm))
++ goto offset_found;
++
+ __set_errno (EOVERFLOW);
+ return -1;
+ }
+--
+2.43.5
+
diff --git a/backport-nscd-Fix-netlink-cache-invalidation-if-epoll-is-used.patch b/backport-nscd-Fix-netlink-cache-invalidation-if-epoll-is-used.patch
new file mode 100644
index 0000000..ee0eeef
--- /dev/null
+++ b/backport-nscd-Fix-netlink-cache-invalidation-if-epoll-is-used.patch
@@ -0,0 +1,48 @@
+From 02ca25fef2785974011e9c5beecc99b900b69fd7 Mon Sep 17 00:00:00 2001
+From: Fabian Vogt <fvogt@suse.de>
+Date: Wed, 27 Jul 2022 11:44:07 +0200
+Subject: [PATCH] nscd: Fix netlink cache invalidation if epoll is used [BZ
+ #29415]
+
+Processes cache network interface information such as whether IPv4 or IPv6
+are enabled. This is only checked again if the "netlink timestamp" provided
+by nscd changed, which is triggered by netlink socket activity.
+
+However, in the epoll handler for the netlink socket, it was missed to
+assign the new timestamp to the nscd database. The handler for plain poll
+did that properly, copy that over.
+
+This bug caused that e.g. processes which started before network
+configuration got unusuable addresses from getaddrinfo, like IPv6 only even
+though only IPv4 is available:
+https://gitlab.freedesktop.org/NetworkManager/NetworkManager/-/issues/1041
+
+It's a bit hard to reproduce, so I verified this by checking the timestamp
+on calls to __check_pf manually. Without this patch it's stuck at 1, now
+it's increasing on network changes as expected.
+
+Conflict: NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=02ca25fef2785974011e9c5beecc99b900b69fd7
+
+Signed-off-by: Fabian Vogt <fvogt@suse.de>
+---
+ nscd/connections.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/nscd/connections.c b/nscd/connections.c
+index 61d1674eb4..531d2e83df 100644
+--- a/nscd/connections.c
++++ b/nscd/connections.c
+@@ -2284,7 +2284,8 @@ main_loop_epoll (int efd)
+ sizeof (buf))) != -1)
+ ;
+
+- __bump_nl_timestamp ();
++ dbs[hstdb].head->extra_data[NSCD_HST_IDX_CONF_TIMESTAMP]
++ = __bump_nl_timestamp ();
+ }
+ # endif
+ else
+--
+2.27.0
+
diff --git a/backport-nss_dns-In-gaih_getanswer_slice-skip-strange-aliases-bug-12154.patch b/backport-nss_dns-In-gaih_getanswer_slice-skip-strange-aliases-bug-12154.patch
new file mode 100644
index 0000000..73ae2ec
--- /dev/null
+++ b/backport-nss_dns-In-gaih_getanswer_slice-skip-strange-aliases-bug-12154.patch
@@ -0,0 +1,58 @@
+From 32b599ac8c21c4c332cc3900a792a1395bca79c7 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 30 Aug 2022 10:02:49 +0200
+Subject: [PATCH] nss_dns: In gaih_getanswer_slice, skip strange aliases (bug
+ 12154)
+
+If the name is not a host name, skip adding it to the result, instead
+of reporting query failure. This fixes bug 12154 for getaddrinfo.
+
+This commit still keeps the old parsing code, and only adjusts when
+a host name is copied.
+
+Conflict: NA
+Reference: https://sourceware.org/git/?p=glibc.git;a=commit;h=32b599ac8c21c4c332cc3900a792a1395bca79c7
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ resolv/nss_dns/dns-host.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/resolv/nss_dns/dns-host.c b/resolv/nss_dns/dns-host.c
+index b887e77e9c..bea505d697 100644
+--- a/resolv/nss_dns/dns-host.c
++++ b/resolv/nss_dns/dns-host.c
+@@ -970,12 +970,12 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+
+ n = -1;
+ }
+- if (__glibc_unlikely (n < 0 || __libc_res_hnok (buffer) == 0))
++ if (__glibc_unlikely (n < 0))
+ {
+ ++had_error;
+ continue;
+ }
+- if (*firstp && canon == NULL)
++ if (*firstp && canon == NULL && __libc_res_hnok (buffer))
+ {
+ h_name = buffer;
+ buffer += h_namelen;
+@@ -1021,14 +1021,14 @@ gaih_getanswer_slice (const querybuf *answer, int anslen, const char *qname,
+
+ n = __libc_dn_expand (answer->buf, end_of_message, cp,
+ tbuf, sizeof tbuf);
+- if (__glibc_unlikely (n < 0 || __libc_res_hnok (tbuf) == 0))
++ if (__glibc_unlikely (n < 0))
+ {
+ ++had_error;
+ continue;
+ }
+ cp += n;
+
+- if (*firstp)
++ if (*firstp && __libc_res_hnok (tbuf))
+ {
+ /* Reclaim buffer space. */
+ if (h_name + h_namelen == buffer)
+--
+2.23.0
diff --git a/backport-posix-Fix-some-crashes-in-wordexp-BZ-18096.patch b/backport-posix-Fix-some-crashes-in-wordexp-BZ-18096.patch
new file mode 100644
index 0000000..668a563
--- /dev/null
+++ b/backport-posix-Fix-some-crashes-in-wordexp-BZ-18096.patch
@@ -0,0 +1,86 @@
+From 31bfe3ef4ea898df606cb6cc59ac72de27002b01 Mon Sep 17 00:00:00 2001
+From: Julian Squires <julian@cipht.net>
+Date: Wed, 22 Mar 2023 14:09:57 -0230
+Subject: [PATCH] posix: Fix some crashes in wordexp [BZ #18096]
+
+Without these fixes, the first three included tests segfault (on a
+NULL dereference); the fourth aborts on an assertion, which is itself
+unnecessary.
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=31bfe3ef4ea898df606cb6cc59ac72de27002b01
+
+Signed-off-by: Julian Squires <julian@cipht.net>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ posix/wordexp-test.c | 4 ++++
+ posix/wordexp.c | 11 ++++-------
+ 2 files changed, 8 insertions(+), 7 deletions(-)
+
+diff --git a/posix/wordexp-test.c b/posix/wordexp-test.c
+index f7a591149b..bae27d6cee 100644
+--- a/posix/wordexp-test.c
++++ b/posix/wordexp-test.c
+@@ -117,6 +117,8 @@ struct test_case_struct
+ { 0, NULL, "$((010+0x10))", 0, 1, { "24" }, IFS },
+ { 0, NULL, "$((-010+0x10))", 0, 1, { "8" }, IFS },
+ { 0, NULL, "$((-0x10+010))", 0, 1, { "-8" }, IFS },
++ { 0, NULL, "$(())", 0, 1, { "0", }, IFS },
++ { 0, NULL, "$[]", 0, 1, { "0", }, IFS },
+
+ /* Advanced parameter expansion */
+ { 0, NULL, "${var:-bar}", 0, 1, { "bar", }, IFS },
+@@ -138,6 +140,8 @@ struct test_case_struct
+ { 0, "12345", "${#var}", 0, 1, { "5", }, IFS },
+ { 0, NULL, "${var:-'}'}", 0, 1, { "}", }, IFS },
+ { 0, NULL, "${var-}", 0, 0, { NULL }, IFS },
++ { 0, NULL, "${a?}", 0, 0, { NULL, }, IFS },
++ { 0, NULL, "${#a=}", 0, 1, { "0", }, IFS },
+
+ { 0, "pizza", "${var#${var}}", 0, 0, { NULL }, IFS },
+ { 0, "pepperoni", "${var%$(echo oni)}", 0, 1, { "pepper" }, IFS },
+diff --git a/posix/wordexp.c b/posix/wordexp.c
+index 0da98f5b08..b34c4a939b 100644
+--- a/posix/wordexp.c
++++ b/posix/wordexp.c
+@@ -720,7 +720,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
+ ++(*offset);
+
+ /* Go - evaluate. */
+- if (*expr && eval_expr (expr, &numresult) != 0)
++ if (expr && eval_expr (expr, &numresult) != 0)
+ {
+ free (expr);
+ return WRDE_SYNTAX;
+@@ -758,7 +758,7 @@ parse_arith (char **word, size_t *word_length, size_t *max_length,
+ long int numresult = 0;
+
+ /* Go - evaluate. */
+- if (*expr && eval_expr (expr, &numresult) != 0)
++ if (expr && eval_expr (expr, &numresult) != 0)
+ {
+ free (expr);
+ return WRDE_SYNTAX;
+@@ -1790,7 +1790,7 @@ envsubst:
+ {
+ const char *str = pattern;
+
+- if (str[0] == '\0')
++ if (!str || str[0] == '\0')
+ str = _("parameter null or not set");
+
+ __fxprintf (NULL, "%s: %s\n", env, str);
+@@ -1883,10 +1883,7 @@ envsubst:
+ _itoa_word (value ? strlen (value) : 0,
+ &param_length[20], 10, 0));
+ if (free_value)
+- {
+- assert (value != NULL);
+- free (value);
+- }
++ free (value);
+
+ return *word ? 0 : WRDE_NOSPACE;
+ }
+--
+2.33.0
diff --git a/backport-posix-Fix-system-blocks-SIGCHLD-erroneously-BZ-30163.patch b/backport-posix-Fix-system-blocks-SIGCHLD-erroneously-BZ-30163.patch
new file mode 100644
index 0000000..78bebb6
--- /dev/null
+++ b/backport-posix-Fix-system-blocks-SIGCHLD-erroneously-BZ-30163.patch
@@ -0,0 +1,290 @@
+From 436a604b7dc741fc76b5a6704c6cd8bb178518e7 Mon Sep 17 00:00:00 2001
+From: Adam Yi <ayi@janestreet.com>
+Date: Tue, 7 Mar 2023 07:30:02 -0500
+Subject: [PATCH] posix: Fix system blocks SIGCHLD erroneously [BZ #30163]
+
+Fix bug that SIGCHLD is erroneously blocked forever in the following
+scenario:
+
+1. Thread A calls system but hasn't returned yet
+2. Thread B calls another system but returns
+
+SIGCHLD would be blocked forever in thread B after its system() returns,
+even after the system() in thread A returns.
+
+Although POSIX does not require, glibc system implementation aims to be
+thread and cancellation safe. This bug was introduced in
+5fb7fc96350575c9adb1316833e48ca11553be49 when we moved reverting signal
+mask to happen when the last concurrently running system returns,
+despite that signal mask is per thread. This commit reverts this logic
+and adds a test.
+
+Signed-off-by: Adam Yi <ayi@janestreet.com>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ stdlib/tst-system.c | 26 +++++++++++++++++++
+ support/Makefile | 2 ++
+ support/dtotimespec-time64.c | 27 +++++++++++++++++++
+ support/dtotimespec.c | 50 ++++++++++++++++++++++++++++++++++++
+ support/shell-container.c | 28 ++++++++++++++++++++
+ support/timespec.h | 4 +++
+ sysdeps/posix/system.c | 6 ++---
+ 7 files changed, 140 insertions(+), 3 deletions(-)
+ create mode 100644 support/dtotimespec-time64.c
+ create mode 100644 support/dtotimespec.c
+
+diff --git a/stdlib/tst-system.c b/stdlib/tst-system.c
+index 178808e0..d1413d7c 100644
+--- a/stdlib/tst-system.c
++++ b/stdlib/tst-system.c
+@@ -26,6 +26,7 @@
+ #include <support/check.h>
+ #include <support/temp_file.h>
+ #include <support/support.h>
++#include <support/xthread.h>
+ #include <support/xunistd.h>
+
+ static char *tmpdir;
+@@ -72,6 +73,20 @@ call_system (void *closure)
+ }
+ }
+
++static void *
++sleep_and_check_sigchld (void *closure)
++{
++ double *seconds = (double *) closure;
++ char cmd[namemax];
++ sprintf (cmd, "sleep %lf" , *seconds);
++ TEST_COMPARE (system (cmd), 0);
++
++ sigset_t blocked = {0};
++ TEST_COMPARE (sigprocmask (SIG_BLOCK, NULL, &blocked), 0);
++ TEST_COMPARE (sigismember (&blocked, SIGCHLD), 0);
++ return NULL;
++}
++
+ static int
+ do_test (void)
+ {
+@@ -155,6 +170,17 @@ do_test (void)
+ xchmod (_PATH_BSHELL, st.st_mode);
+ }
+
++ {
++ pthread_t long_sleep_thread = xpthread_create (NULL,
++ sleep_and_check_sigchld,
++ &(double) { 0.2 });
++ pthread_t short_sleep_thread = xpthread_create (NULL,
++ sleep_and_check_sigchld,
++ &(double) { 0.1 });
++ xpthread_join (short_sleep_thread);
++ xpthread_join (long_sleep_thread);
++ }
++
+ TEST_COMPARE (system (""), 0);
+
+ return 0;
+diff --git a/support/Makefile b/support/Makefile
+index 724ae6d7..936af554 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -32,6 +32,8 @@ libsupport-routines = \
+ check_hostent \
+ check_netent \
+ delayed_exit \
++ dtotimespec \
++ dtotimespec-time64 \
+ ignore_stderr \
+ next_to_fault \
+ oom_error \
+diff --git a/support/dtotimespec-time64.c b/support/dtotimespec-time64.c
+new file mode 100644
+index 00000000..b3d5e351
+--- /dev/null
++++ b/support/dtotimespec-time64.c
+@@ -0,0 +1,27 @@
++/* Convert double to timespec. 64-bit time support.
++ Copyright (C) 2011-2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library and is also part of gnulib.
++ Patches to this file should be submitted to both projects.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <time.h>
++
++#if __TIMESIZE != 64
++# define timespec __timespec64
++# define time_t __time64_t
++# define dtotimespec dtotimespec_time64
++# include "dtotimespec.c"
++#endif
+diff --git a/support/dtotimespec.c b/support/dtotimespec.c
+new file mode 100644
+index 00000000..cde5b4d7
+--- /dev/null
++++ b/support/dtotimespec.c
+@@ -0,0 +1,50 @@
++/* Convert double to timespec.
++ Copyright (C) 2011-2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library and is also part of gnulib.
++ Patches to this file should be submitted to both projects.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Convert the double value SEC to a struct timespec. Round toward
++ positive infinity. On overflow, return an extremal value. */
++
++#include <support/timespec.h>
++#include <intprops.h>
++
++struct timespec
++dtotimespec (double sec)
++{
++ if (sec <= TYPE_MINIMUM (time_t))
++ return make_timespec (TYPE_MINIMUM (time_t), 0);
++ else if (sec >= 1.0 + TYPE_MAXIMUM (time_t))
++ return make_timespec (TYPE_MAXIMUM (time_t), TIMESPEC_HZ - 1);
++ else
++ {
++ time_t s = sec;
++ double frac = TIMESPEC_HZ * (sec - s);
++ long ns = frac;
++ ns += ns < frac;
++ s += ns / TIMESPEC_HZ;
++ ns %= TIMESPEC_HZ;
++
++ if (ns < 0)
++ {
++ s--;
++ ns += TIMESPEC_HZ;
++ }
++
++ return make_timespec (s, ns);
++ }
++}
+diff --git a/support/shell-container.c b/support/shell-container.c
+index b2a4324d..6fe925dc 100644
+--- a/support/shell-container.c
++++ b/support/shell-container.c
+@@ -39,6 +39,7 @@
+ #include <error.h>
+
+ #include <support/support.h>
++#include <support/timespec.h>
+
+ /* Design considerations
+
+@@ -171,6 +172,32 @@ kill_func (char **argv)
+ return 0;
+ }
+
++/* Emulate the "/bin/sleep" command. No suffix support. Options are
++ ignored. */
++static int
++sleep_func (char **argv)
++{
++ if (argv[0] == NULL)
++ {
++ fprintf (stderr, "sleep: missing operand\n");
++ return 1;
++ }
++ char *endptr = NULL;
++ double sec = strtod (argv[0], &endptr);
++ if (endptr == argv[0] || errno == ERANGE || sec < 0)
++ {
++ fprintf (stderr, "sleep: invalid time interval '%s'\n", argv[0]);
++ return 1;
++ }
++ struct timespec ts = dtotimespec (sec);
++ if (nanosleep (&ts, NULL) < 0)
++ {
++ fprintf (stderr, "sleep: failed to nanosleep: %s\n", strerror (errno));
++ return 1;
++ }
++ return 0;
++}
++
+ /* This is a list of all the built-in commands we understand. */
+ static struct {
+ const char *name;
+@@ -181,6 +208,7 @@ static struct {
+ { "cp", copy_func },
+ { "exit", exit_func },
+ { "kill", kill_func },
++ { "sleep", sleep_func },
+ { NULL, NULL }
+ };
+
+diff --git a/support/timespec.h b/support/timespec.h
+index 0478aef5..843a90d6 100644
+--- a/support/timespec.h
++++ b/support/timespec.h
+@@ -57,6 +57,8 @@ int support_timespec_check_in_range (struct timespec expected,
+ struct timespec observed,
+ double lower_bound, double upper_bound);
+
++struct timespec dtotimespec (double sec) __attribute__((const));
++
+ #else
+ struct timespec __REDIRECT (timespec_add, (struct timespec, struct timespec),
+ timespec_add_time64);
+@@ -82,6 +84,8 @@ int __REDIRECT (support_timespec_check_in_range, (struct timespec expected,
+ double lower_bound,
+ double upper_bound),
+ support_timespec_check_in_range_time64);
++
++struct timespec __REDIRECT (dtotimespec, (double sec), dtotimespec_time64);
+ #endif
+
+ /* Check that the timespec on the left represents a time before the
+diff --git a/sysdeps/posix/system.c b/sysdeps/posix/system.c
+index 48668fb3..b9676abb 100644
+--- a/sysdeps/posix/system.c
++++ b/sysdeps/posix/system.c
+@@ -179,16 +179,16 @@ do_system (const char *line)
+ as if the shell had terminated using _exit(127). */
+ status = W_EXITCODE (127, 0);
+
++ /* sigaction can not fail with SIGINT/SIGQUIT used with old
++ disposition. Same applies for sigprocmask. */
+ DO_LOCK ();
+ if (SUB_REF () == 0)
+ {
+- /* sigaction can not fail with SIGINT/SIGQUIT used with old
+- disposition. Same applies for sigprocmask. */
+ __sigaction (SIGINT, &intr, NULL);
+ __sigaction (SIGQUIT, &quit, NULL);
+- __sigprocmask (SIG_SETMASK, &omask, NULL);
+ }
+ DO_UNLOCK ();
++ __sigprocmask (SIG_SETMASK, &omask, NULL);
+
+ if (ret != 0)
+ __set_errno (ret);
+--
+2.33.0
+
diff --git a/backport-resolv-fix-non-existing-second-DNS-response-error.patch b/backport-resolv-fix-non-existing-second-DNS-response-error.patch
new file mode 100644
index 0000000..9e914c3
--- /dev/null
+++ b/backport-resolv-fix-non-existing-second-DNS-response-error.patch
@@ -0,0 +1,197 @@
+From 09ce1e84db1b175195584dd20aa7241f3e95061f Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 14 Jun 2024 08:20:48 +0200
+Subject: [PATCH 2/4] resolv: Do not wait for non-existing second DNS response after error (bug 30081)
+Message-ID: <09ce1e84db1b175195584dd20aa7241f3e95061f.1718345824.git.fweimer@redhat.com> (raw)
+In-Reply-To: <cover.1718345824.git.fweimer@redhat.com>
+
+In single-request mode, there is no second response after an error
+because the second query has not been sent yet. Waiting for it
+introduces an unnecessary timeout.
+
+Conflict:The tst-resolv-short-response test case does not exist. Therefore, the modification of this test case is not incorporated.
+Reference:https://inbox.sourceware.org/libc-alpha/09ce1e84db1b175195584dd20aa7241f3e95061f.1718345824.git.fweimer@redhat.com/
+
+---
+ resolv/Makefile | 3 +
+ resolv/res_send.c | 2 +-
+ resolv/tst-resolv-semi-failure.c | 133 +++++++++++++++++++++++++++++++
+ 3 files changed, 137 insertions(+), 1 deletion(-)
+ create mode 100644 resolv/tst-resolv-semi-failure.c
+
+diff --git a/resolv/Makefile b/resolv/Makefile
+index 59e59953..9e12d364 100644
+--- a/resolv/Makefile
++++ b/resolv/Makefile
+@@ -96,6 +96,7 @@ tests += \
+ tst-resolv-nondecimal \
+ tst-resolv-res_init-multi \
+ tst-resolv-search \
++ tst-resolv-semi-failure \
+ tst-resolv-trailing \
+
+ # This test calls __res_context_send directly, which is not exported
+@@ -260,6 +261,8 @@ $(objpfx)tst-resolv-nondecimal: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-qtypes: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-rotate: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-search: $(objpfx)libresolv.so $(shared-thread-library)
++$(objpfx)tst-resolv-semi-failure: $(objpfx)libresolv.so \
++ $(shared-thread-library)
+ $(objpfx)tst-resolv-trailing: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-threads: $(objpfx)libresolv.so $(shared-thread-library)
+ $(objpfx)tst-resolv-txnid-collision: $(objpfx)libresolv.a \
+diff --git a/resolv/res_send.c b/resolv/res_send.c
+index 9f86f5fe..54226a2e 100644
+--- a/resolv/res_send.c
++++ b/resolv/res_send.c
+@@ -1222,7 +1222,7 @@ send_dg(res_state statp,
+ *resplen2 = 0;
+ return resplen;
+ }
+- if (buf2 != NULL)
++ if (buf2 != NULL && !single_request)
+ {
+ /* No data from the first reply. */
+ resplen = 0;
+diff --git a/resolv/tst-resolv-semi-failure.c b/resolv/tst-resolv-semi-failure.c
+new file mode 100644
+index 00000000..aa9798b5
+--- /dev/null
++++ b/resolv/tst-resolv-semi-failure.c
+@@ -0,0 +1,133 @@
++/* Test parallel failure/success responses (bug 30081).
++ Copyright (C) 2024 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <resolv.h>
++#include <support/check.h>
++#include <support/resolv_test.h>
++#include <support/check_nss.h>
++
++/* The rcode in the initial response. */
++static volatile int rcode;
++
++/* Whether to fail the initial A query (!fail_aaaa) or the initial
++ AAAA query (fail_aaaa). */
++static volatile bool fail_aaaa;
++
++static void
++response (const struct resolv_response_context *ctx,
++ struct resolv_response_builder *b,
++ const char *qname, uint16_t qclass, uint16_t qtype)
++{
++ /* Handle the failing query. */
++ if ((fail_aaaa && qtype == T_AAAA) && ctx->server_index == 0)
++ {
++ struct resolv_response_flags flags = {.rcode = rcode};
++ resolv_response_init (b, flags);
++ return;
++ }
++
++ /* Otherwise produce a response. */
++ resolv_response_init (b, (struct resolv_response_flags) {});
++ resolv_response_add_question (b, qname, qclass, qtype);
++ resolv_response_section (b, ns_s_an);
++ resolv_response_open_record (b, qname, qclass, qtype, 0);
++ switch (qtype)
++ {
++ case T_A:
++ {
++ char ipv4[4] = {192, 0, 2, 17};
++ resolv_response_add_data (b, &ipv4, sizeof (ipv4));
++ }
++ break;
++ case T_AAAA:
++ {
++ char ipv6[16]
++ = {0x20, 0x01, 0xd, 0xb8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1};
++ resolv_response_add_data (b, &ipv6, sizeof (ipv6));
++ }
++ break;
++ default:
++ FAIL_EXIT1 ("unexpected TYPE%d query", qtype);
++ }
++ resolv_response_close_record (b);
++}
++
++static void
++check_one (void)
++{
++
++ /* The buggy 1-second query timeout results in 30 seconds of delay,
++ which triggers are test timeout failure. */
++ for (int i = 0; i < 30; ++i)
++ {
++ static const struct addrinfo hints =
++ {
++ .ai_family = AF_UNSPEC,
++ .ai_socktype = SOCK_STREAM,
++ };
++ struct addrinfo *ai;
++ int ret = getaddrinfo ("www.example", "80", &hints, &ai);
++ const char *expected;
++ if (ret == 0 && ai->ai_next != NULL)
++ expected = ("address: STREAM/TCP 192.0.2.17 80\n"
++ "address: STREAM/TCP 2001:db8::1 80\n");
++ else
++ /* Only one response because the AAAA lookup failure is
++ treated as an ignoreable error. */
++ expected = "address: STREAM/TCP 192.0.2.17 80\n";
++ check_addrinfo ("www.example", ai, ret, expected);
++ if (ret == 0)
++ freeaddrinfo (ai);
++ }
++}
++
++static int
++do_test (void)
++{
++ for (int do_single_lookup = 0; do_single_lookup < 2; ++do_single_lookup)
++ {
++ struct resolv_test *aux = resolv_test_start
++ ((struct resolv_redirect_config)
++ {
++ .response_callback = response,
++ });
++
++ if (do_single_lookup)
++ _res.options |= RES_SNGLKUP;
++
++ for (int do_fail_aaaa = 0; do_fail_aaaa < 2; ++do_fail_aaaa)
++ {
++ fail_aaaa = do_fail_aaaa;
++
++ rcode = 2; /* SERVFAIL. */
++ check_one ();
++
++ rcode = 4; /* NOTIMP. */
++ check_one ();
++
++ rcode = 5; /* REFUSED. */
++ check_one ();
++ }
++
++ resolv_test_end (aux);
++ }
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.33.0
+
diff --git a/backport-resolv_conf-release-lock-on-allocation-failure-bug-30527.patch b/backport-resolv_conf-release-lock-on-allocation-failure-bug-30527.patch
new file mode 100644
index 0000000..f4fc1b3
--- /dev/null
+++ b/backport-resolv_conf-release-lock-on-allocation-failure-bug-30527.patch
@@ -0,0 +1,31 @@
+From abcf8db7fa46b73fd5b8193ce11f9312301b84c7 Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@suse.de>
+Date: Wed, 7 Jun 2023 11:21:48 +0200
+Subject: [PATCH] resolv_conf: release lock on allocation failure (bug 30527)
+
+When the initial allocation of global fails, the local lock is left
+locked.
+
+Reported by Steffen Lammel of SAP HANA development.
+---
+ resolv/resolv_conf.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/resolv/resolv_conf.c b/resolv/resolv_conf.c
+index bd5890773b..8bc9edc634 100644
+--- a/resolv/resolv_conf.c
++++ b/resolv/resolv_conf.c
+@@ -93,7 +93,10 @@ get_locked_global (void)
+ {
+ global_copy = calloc (1, sizeof (*global));
+ if (global_copy == NULL)
+- return NULL;
++ {
++ __libc_lock_unlock (lock);
++ return NULL;
++ }
+ atomic_store_relaxed (&global, global_copy);
+ resolv_conf_array_init (&global_copy->array);
+ }
+--
+2.23.0
diff --git a/backport-rtld-properly-handle-root-directory-in-load-path-bug-30435.patch b/backport-rtld-properly-handle-root-directory-in-load-path-bug-30435.patch
new file mode 100644
index 0000000..bef51b3
--- /dev/null
+++ b/backport-rtld-properly-handle-root-directory-in-load-path-bug-30435.patch
@@ -0,0 +1,31 @@
+
+From e0189b25403f8b67e7a5513d6c33fb09cb2e5e20 Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@suse.de>
+Date: Tue, 16 May 2023 14:41:46 +0200
+Subject: [PATCH] rtld: properly handle root directory in load path (bug 30435)
+
+Don't strip the trailing slash when checking for existence of a load path
+element to handle the special case of the root directory.
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=e0189b25403f8b67e7a5513d6c33fb09cb2e5e20
+Conflict:NA
+---
+ elf/dl-load.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index 39c63ff1b3..2aa487b49a 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1859,7 +1859,7 @@ open_path (const char *name, size_t namelen, int mode,
+ test whether there is any directory at all. */
+ struct __stat64_t64 st;
+
+- buf[buflen - namelen - 1] = '\0';
++ buf[buflen - namelen] = '\0';
+
+ if (__stat64_time64 (buf, &st) != 0
+ || ! S_ISDIR (st.st_mode))
+--
+2.23.0
+
diff --git a/backport-stdlib-Undo-post-review-change-to-16adc58e73f3-BZ-27.patch b/backport-stdlib-Undo-post-review-change-to-16adc58e73f3-BZ-27.patch
new file mode 100644
index 0000000..efcbff9
--- /dev/null
+++ b/backport-stdlib-Undo-post-review-change-to-16adc58e73f3-BZ-27.patch
@@ -0,0 +1,140 @@
+From fd78cfa72ea2bab30fdb4e1e0672b34471426c05 Mon Sep 17 00:00:00 2001
+From: Vitaly Buka <vitalybuka@google.com>
+Date: Sat, 18 Feb 2023 12:53:41 -0800
+Subject: [PATCH] stdlib: Undo post review change to 16adc58e73f3 [BZ #27749]
+
+Post review removal of "goto restart" from
+https://sourceware.org/pipermail/libc-alpha/2021-April/125470.html
+introduced a bug when some atexit handers skipped.
+
+Signed-off-by: Vitaly Buka <vitalybuka@google.com>
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ stdlib/Makefile | 1 +
+ stdlib/exit.c | 7 +++-
+ stdlib/test-atexit-recursive.c | 75 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 81 insertions(+), 2 deletions(-)
+ create mode 100644 stdlib/test-atexit-recursive.c
+
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index a4ac30d1..73cd3370 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -73,6 +73,7 @@ tests := \
+ test-a64l \
+ test-at_quick_exit-race \
+ test-atexit-race \
++ test-atexit-recursive \
+ test-bz22786 \
+ test-canon \
+ test-canon2 \
+diff --git a/stdlib/exit.c b/stdlib/exit.c
+index 453eb85b..546343f7 100644
+--- a/stdlib/exit.c
++++ b/stdlib/exit.c
+@@ -53,7 +53,10 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
+ exit (). */
+ while (true)
+ {
+- struct exit_function_list *cur = *listp;
++ struct exit_function_list *cur;
++
++ restart:
++ cur = *listp;
+
+ if (cur == NULL)
+ {
+@@ -118,7 +121,7 @@ __run_exit_handlers (int status, struct exit_function_list **listp,
+ if (__glibc_unlikely (new_exitfn_called != __new_exitfn_called))
+ /* The last exit function, or another thread, has registered
+ more exit functions. Start the loop over. */
+- continue;
++ goto restart;
+ }
+
+ *listp = cur->next;
+diff --git a/stdlib/test-atexit-recursive.c b/stdlib/test-atexit-recursive.c
+new file mode 100644
+index 00000000..0596b976
+--- /dev/null
++++ b/stdlib/test-atexit-recursive.c
+@@ -0,0 +1,75 @@
++/* Support file for atexit/exit, etc. race tests (BZ #27749).
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Check that atexit handler registed from another handler still called. */
++
++#include <stdio.h>
++#include <stdlib.h>
++#include <support/check.h>
++#include <support/xunistd.h>
++#include <sys/wait.h>
++#include <unistd.h>
++
++static void
++atexit_cb (void)
++{
++}
++
++static void
++atexit_last (void)
++{
++ _exit (1);
++}
++
++static void
++atexit_recursive (void)
++{
++ atexit (&atexit_cb);
++ atexit (&atexit_last);
++}
++
++_Noreturn static void
++test_and_exit (int count)
++{
++ for (int i = 0; i < count; ++i)
++ atexit (&atexit_cb);
++ atexit (&atexit_recursive);
++ exit (0);
++}
++
++static int
++do_test (void)
++{
++ for (int i = 0; i < 100; ++i)
++ if (xfork () == 0)
++ test_and_exit (i);
++
++ for (int i = 0; i < 100; ++i)
++ {
++ int status;
++ xwaitpid (0, &status, 0);
++ if (!WIFEXITED (status))
++ FAIL_EXIT1 ("Failed iterations %d", i);
++ TEST_COMPARE (WEXITSTATUS (status), 1);
++ }
++
++ return 0;
++}
++
++#define TEST_FUNCTION do_test
++#include <support/test-driver.c>
+--
+2.33.0
+
diff --git a/backport-stdlib-fix-grouping-verification-with-multi-byte-tho.patch b/backport-stdlib-fix-grouping-verification-with-multi-byte-tho.patch
new file mode 100644
index 0000000..196707b
--- /dev/null
+++ b/backport-stdlib-fix-grouping-verification-with-multi-byte-tho.patch
@@ -0,0 +1,131 @@
+From 69239bd7a216007692470aa9d5f3658024638742 Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@suse.de>
+Date: Wed, 11 Oct 2023 16:22:16 +0200
+Subject: [PATCH] stdlib: fix grouping verification with multi-byte thousands
+ separator (bug 30964)
+
+The grouping verification only worked for a single-byte thousands
+separator. With a multi-byte separator it returned as if no separators
+were present. The actual parsing in str_to_mpn will then go wrong when
+there are multiple adjacent multi-byte separators in the number.
+
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=69239bd7a216007692470aa9d5f3658024638742
+Conflict:NA
+
+---
+ stdlib/grouping.c | 33 ++++++++++-----------------------
+ stdlib/tst-strtod4.c | 4 +++-
+ 2 files changed, 13 insertions(+), 24 deletions(-)
+
+diff --git a/stdlib/grouping.c b/stdlib/grouping.c
+index b6bf1dbab2..16b266d3e0 100644
+--- a/stdlib/grouping.c
++++ b/stdlib/grouping.c
+@@ -59,7 +59,6 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ size_t thousands_len = 1;
+ #else
+ size_t thousands_len = strlen (thousands);
+- int cnt;
+ #endif
+
+ while (end - begin >= thousands_len)
+@@ -74,14 +73,8 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ if (*cp == thousands)
+ break;
+ #else
+- if (cp[thousands_len - 1] == *thousands)
+- {
+- for (cnt = 1; thousands[cnt] != '\0'; ++cnt)
+- if (thousands[cnt] != cp[thousands_len - 1 - cnt])
+- break;
+- if (thousands[cnt] == '\0')
+- break;
+- }
++ if (memcmp (cp, thousands, thousands_len) == 0)
++ break;
+ #endif
+ --cp;
+ }
+@@ -91,7 +84,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ if (cp < begin)
+ return end;
+
+- if (end - cp == (int) *gp + 1)
++ if (end - cp == (int) *gp + thousands_len)
+ {
+ /* This group matches the specification. */
+
+@@ -105,7 +98,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ remainder of the string from BEGIN to NEW_END is the part we
+ will consider if there is a grouping error in this trailing
+ portion from CP to END. */
+- new_end = cp - 1;
++ new_end = cp;
+
+ /* Loop while the grouping is correct. */
+ while (1)
+@@ -132,10 +125,7 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ if (*cp == thousands)
+ break;
+ #else
+- for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+- if (thousands[cnt] != cp[thousands_len - cnt - 1])
+- break;
+- if (thousands[cnt] == '\0')
++ if (memcmp (cp, thousands, thousands_len) == 0)
+ break;
+ #endif
+ --cp;
+@@ -156,20 +146,17 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ if (*cp == thousands)
+ break;
+ #else
+- for (cnt = 0; thousands[cnt] != '\0'; ++cnt)
+- if (thousands[cnt] != cp[thousands_len - cnt - 1])
+- break;
+- if (thousands[cnt] == '\0')
++ if (memcmp (cp, thousands, thousands_len) == 0)
+ break;
+ #endif
+ --cp;
+ }
+
+- if (cp < begin && group_end - cp <= (int) *gp)
++ if (cp < begin && group_end - cp <= (int) *gp + thousands_len - 1)
+ /* Final group is correct. */
+ return end;
+
+- if (cp < begin || group_end - cp != (int) *gp)
++ if (cp < begin || group_end - cp != (int) *gp + thousands_len - 1)
+ /* Incorrect group. Punt. */
+ break;
+ }
+@@ -183,8 +170,8 @@ __correctly_grouped_prefixmb (const STRING_TYPE *begin, const STRING_TYPE *end,
+ else
+ {
+ /* Even the first group was wrong; determine maximum shift. */
+- if (end - cp > (int) *gp + 1)
+- end = cp + (int) *gp + 1;
++ if (end - cp > (int) *gp + thousands_len)
++ end = cp + (int) *gp + thousands_len;
+ else if (cp < begin)
+ /* This number does not fill the first group, but is correct. */
+ return end;
+diff --git a/stdlib/tst-strtod4.c b/stdlib/tst-strtod4.c
+index aae9835d82..6cc4e843c7 100644
+--- a/stdlib/tst-strtod4.c
++++ b/stdlib/tst-strtod4.c
+@@ -13,7 +13,9 @@ static const struct
+ } tests[] =
+ {
+ { "000"NNBSP"000"NNBSP"000", "", 0.0 },
+- { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 }
++ { "1"NNBSP"000"NNBSP"000,5x", "x", 1000000.5 },
++ /* Bug 30964 */
++ { "10"NNBSP NNBSP"200", NNBSP NNBSP"200", 10.0 }
+ };
+ #define NTESTS (sizeof (tests) / sizeof (tests[0]))
+
+--
+2.37.3.1
+
diff --git a/backport-string-strerror-must-not-return-NULL-bug-30555.patch b/backport-string-strerror-must-not-return-NULL-bug-30555.patch
new file mode 100644
index 0000000..95acf94
--- /dev/null
+++ b/backport-string-strerror-must-not-return-NULL-bug-30555.patch
@@ -0,0 +1,141 @@
+From d68468ccde45b80e271735d8bbbdb7d3cc7eb420 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 15 Jun 2023 12:08:22 +0200
+Subject: [PATCH] string: strerror must not return NULL (bug 30555)
+
+For strerror, this fixes commit 28aff047818eb1726394296d27b ("string:
+Implement strerror in terms of strerror_l"). This commit avoids
+returning NULL for strerror_l as well, although POSIX allows this
+behavior for strerror_l.
+
+Reviewed-by: Arjun Shankar <arjun@redhat.com>
+---
+ string/Makefile | 2 +-
+ string/strerror_l.c | 13 +++++--
+ string/tst-strerror-fail.c | 77 ++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 87 insertions(+), 5 deletions(-)
+ create mode 100644 string/tst-strerror-fail.c
+
+diff --git a/string/Makefile b/string/Makefile
+index f0fce2a0..a385c8fd 100644
+--- a/string/Makefile
++++ b/string/Makefile
+@@ -63,7 +63,7 @@ tests := tester inl-tester noinl-tester testcopy test-ffs \
+ tst-strtok_r bug-strcoll2 tst-cmp tst-xbzero-opt \
+ test-endian-types test-endian-file-scope \
+ test-endian-sign-conversion tst-memmove-overflow \
+- test-sig_np
++ test-sig_np tst-strerror-fail
+
+ # Both tests require the .mo translation files generated by msgfmt.
+ tests-translation := tst-strsignal \
+diff --git a/string/strerror_l.c b/string/strerror_l.c
+index a381c79c..20aa3efe 100644
+--- a/string/strerror_l.c
++++ b/string/strerror_l.c
+@@ -43,10 +43,15 @@ __strerror_l (int errnum, locale_t loc)
+ struct tls_internal_t *tls_internal = __glibc_tls_internal ();
+ free (tls_internal->strerror_l_buf);
+ if (__asprintf (&tls_internal->strerror_l_buf, "%s%d",
+- translate ("Unknown error ", loc), errnum) == -1)
+- tls_internal->strerror_l_buf = NULL;
+-
+- err = tls_internal->strerror_l_buf;
++ translate ("Unknown error ", loc), errnum) > 0)
++ err = tls_internal->strerror_l_buf;
++ else
++ {
++ /* The memory was freed above. */
++ tls_internal->strerror_l_buf = NULL;
++ /* Provide a fallback translation. */
++ err = (char *) translate ("Unknown error", loc);
++ }
+ }
+ else
+ err = (char *) translate (err, loc);
+diff --git a/string/tst-strerror-fail.c b/string/tst-strerror-fail.c
+new file mode 100644
+index 00000000..e0fa45ab
+--- /dev/null
++++ b/string/tst-strerror-fail.c
+@@ -0,0 +1,77 @@
++/* Check that strerror, strerror_l do not return NULL on failure (bug 30555).
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++
++#include <locale.h>
++#include <stdbool.h>
++#include <stdlib.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/namespace.h>
++#include <support/xdlfcn.h>
++
++/* Interposed malloc that can be used to inject allocation failures. */
++
++static volatile bool fail_malloc;
++
++void *
++malloc (size_t size)
++{
++ if (fail_malloc)
++ return NULL;
++
++ static void *(*original_malloc) (size_t);
++ if (original_malloc == NULL)
++ original_malloc = xdlsym (RTLD_NEXT, "malloc");
++ return original_malloc (size);
++}
++
++/* Callbacks for the actual tests. Use fork to run both tests with a
++ clean state. */
++
++static void
++test_strerror (void *closure)
++{
++ fail_malloc = true;
++ const char *s = strerror (999);
++ fail_malloc = false;
++ TEST_COMPARE_STRING (s, "Unknown error");
++}
++
++static void
++test_strerror_l (void *closure)
++{
++ locale_t loc = newlocale (LC_ALL, "C", (locale_t) 0);
++ TEST_VERIFY (loc != (locale_t) 0);
++ fail_malloc = true;
++ const char *s = strerror_l (999, loc);
++ fail_malloc = false;
++ TEST_COMPARE_STRING (s, "Unknown error");
++ freelocale (loc);
++}
++
++static int
++do_test (void)
++{
++ support_isolate_in_subprocess (test_strerror, NULL);
++ support_isolate_in_subprocess (test_strerror_l, NULL);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.40.1
+
diff --git a/backport-sunrpc-Suppress-GCC-Os-warning-on-user2netname.patch b/backport-sunrpc-Suppress-GCC-Os-warning-on-user2netname.patch
new file mode 100644
index 0000000..bfb0d1d
--- /dev/null
+++ b/backport-sunrpc-Suppress-GCC-Os-warning-on-user2netname.patch
@@ -0,0 +1,63 @@
+From 6128e82ebe973163d2dd614d31753c88c0c4d645 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella Netto <adhemerval.zanella@linaro.org>
+Date: Wed, 21 Sep 2022 10:51:07 -0300
+Subject: [PATCH] sunrpc: Suppress GCC -Os warning on user2netname
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+GCC with -Os warns that sprint might overflow:
+
+ netname.c: In function ‘user2netname’:
+ netname.c:51:28: error: ‘%s’ directive writing up to 255 bytes into a
+ region of size between 239 and 249 [-Werror=format-overflow=]
+ 51 | sprintf (netname, "%s.%d@%s", OPSYS, uid, dfltdom);
+ | ^~ ~~~~~~~
+ netname.c:51:3: note: ‘sprintf’ output between 8 and 273 bytes into a
+ destination of size 256
+ 51 | sprintf (netname, "%s.%d@%s", OPSYS, uid, dfltdom);
+ | ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ cc1: all warnings being treated as errors
+
+However the code does test prior the sprintf call that dfltdom plus
+the required extra space for OPSYS, uid, and extra character will not
+overflow and return 0 instead.
+
+Checked on x86_64-linux-gnu and i686-linux-gnu.
+
+Conflict: NA
+Reference: https://sourceware.org/git/?p=glibc.git;a=patch;h=6128e82ebe973163d2dd614d31753c88c0c4d645
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ sunrpc/netname.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+diff --git a/sunrpc/netname.c b/sunrpc/netname.c
+index bf7f0b81c4..c1d1c43e50 100644
+--- a/sunrpc/netname.c
++++ b/sunrpc/netname.c
+@@ -20,6 +20,7 @@
+ #include <string.h>
+ #include <rpc/rpc.h>
+ #include <shlib-compat.h>
++#include <libc-diag.h>
+
+ #include "nsswitch.h"
+
+@@ -48,7 +49,12 @@ user2netname (char netname[MAXNETNAMELEN + 1], const uid_t uid,
+ if ((strlen (dfltdom) + OPSYS_LEN + 3 + MAXIPRINT) > (size_t) MAXNETNAMELEN)
+ return 0;
+
++ /* GCC with -Os warns that sprint might overflow while handling dfltdom,
++ however the above test does check if an overflow would happen. */
++ DIAG_PUSH_NEEDS_COMMENT;
++ DIAG_IGNORE_Os_NEEDS_COMMENT (8, "-Wformat-overflow");
+ sprintf (netname, "%s.%d@%s", OPSYS, uid, dfltdom);
++ DIAG_POP_NEEDS_COMMENT;
+ i = strlen (netname);
+ if (netname[i - 1] == '.')
+ netname[i - 1] = '\0';
+--
+2.23.0
diff --git a/backport-x86-Fix-wcsnlen-avx2-page-cross-length-comparison-BZ.patch b/backport-x86-Fix-wcsnlen-avx2-page-cross-length-comparison-BZ.patch
new file mode 100644
index 0000000..5f2a9b7
--- /dev/null
+++ b/backport-x86-Fix-wcsnlen-avx2-page-cross-length-comparison-BZ.patch
@@ -0,0 +1,136 @@
+From b0969fa53a28b4ab2159806bf6c99a98999502ee Mon Sep 17 00:00:00 2001
+From: Noah Goldstein <goldstein.w.n@gmail.com>
+Date: Tue, 20 Sep 2022 17:58:04 -0700
+Subject: [PATCH] x86: Fix wcsnlen-avx2 page cross length comparison [BZ
+ #29591]
+
+Previous implementation was adjusting length (rsi) to match
+bytes (eax), but since there is no bound to length this can cause
+overflow.
+
+Fix is to just convert the byte-count (eax) to length by dividing by
+sizeof (wchar_t) before the comparison.
+
+Conflict:adapt context.
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=b0969fa53a28b4ab2159806bf6c99a98999502ee
+
+Full check passes on x86-64 and build succeeds w/ and w/o multiarch.
+---
+ string/test-strnlen.c | 70 +++++++++++++++-----------
+ sysdeps/x86_64/multiarch/strlen-avx2.S | 7 +--
+ 2 files changed, 43 insertions(+), 34 deletions(-)
+
+diff --git a/string/test-strnlen.c b/string/test-strnlen.c
+index 4a9375112a..5cbaf4b734 100644
+--- a/string/test-strnlen.c
++++ b/string/test-strnlen.c
+@@ -73,7 +73,7 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char)
+ {
+ size_t i;
+
+- align &= 63;
++ align &= (getpagesize () / sizeof (CHAR) - 1);
+ if ((align + len) * sizeof (CHAR) >= page_size)
+ return;
+
+@@ -90,36 +90,50 @@ do_test (size_t align, size_t len, size_t maxlen, int max_char)
+ static void
+ do_overflow_tests (void)
+ {
+- size_t i, j, len;
++ size_t i, j, al_idx, repeats, len;
+ const size_t one = 1;
+ uintptr_t buf_addr = (uintptr_t) buf1;
++ const size_t alignments[] = { 0, 1, 7, 9, 31, 33, 63, 65, 95, 97, 127, 129 };
+
+- for (i = 0; i < 750; ++i)
++ for (al_idx = 0; al_idx < sizeof (alignments) / sizeof (alignments[0]);
++ al_idx++)
+ {
+- do_test (0, i, SIZE_MAX - i, BIG_CHAR);
+- do_test (0, i, i - buf_addr, BIG_CHAR);
+- do_test (0, i, -buf_addr - i, BIG_CHAR);
+- do_test (0, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
+- do_test (0, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
+-
+- len = 0;
+- for (j = 8 * sizeof(size_t) - 1; j ; --j)
+- {
+- len |= one << j;
+- do_test (0, i, len - i, BIG_CHAR);
+- do_test (0, i, len + i, BIG_CHAR);
+- do_test (0, i, len - buf_addr - i, BIG_CHAR);
+- do_test (0, i, len - buf_addr + i, BIG_CHAR);
+-
+- do_test (0, i, ~len - i, BIG_CHAR);
+- do_test (0, i, ~len + i, BIG_CHAR);
+- do_test (0, i, ~len - buf_addr - i, BIG_CHAR);
+- do_test (0, i, ~len - buf_addr + i, BIG_CHAR);
+-
+- do_test (0, i, -buf_addr, BIG_CHAR);
+- do_test (0, i, j - buf_addr, BIG_CHAR);
+- do_test (0, i, -buf_addr - j, BIG_CHAR);
+- }
++ for (repeats = 0; repeats < 2; ++repeats)
++ {
++ size_t align = repeats ? (getpagesize () - alignments[al_idx])
++ : alignments[al_idx];
++ align /= sizeof (CHAR);
++ for (i = 0; i < 750; ++i)
++ {
++ do_test (align, i, SIZE_MAX, BIG_CHAR);
++
++ do_test (align, i, SIZE_MAX - i, BIG_CHAR);
++ do_test (align, i, i - buf_addr, BIG_CHAR);
++ do_test (align, i, -buf_addr - i, BIG_CHAR);
++ do_test (align, i, SIZE_MAX - buf_addr - i, BIG_CHAR);
++ do_test (align, i, SIZE_MAX - buf_addr + i, BIG_CHAR);
++
++ len = 0;
++ for (j = 8 * sizeof (size_t) - 1; j; --j)
++ {
++ len |= one << j;
++ do_test (align, i, len, BIG_CHAR);
++ do_test (align, i, len - i, BIG_CHAR);
++ do_test (align, i, len + i, BIG_CHAR);
++ do_test (align, i, len - buf_addr - i, BIG_CHAR);
++ do_test (align, i, len - buf_addr + i, BIG_CHAR);
++
++ do_test (align, i, ~len - i, BIG_CHAR);
++ do_test (align, i, ~len + i, BIG_CHAR);
++ do_test (align, i, ~len - buf_addr - i, BIG_CHAR);
++ do_test (align, i, ~len - buf_addr + i, BIG_CHAR);
++
++ do_test (align, i, -buf_addr, BIG_CHAR);
++ do_test (align, i, j - buf_addr, BIG_CHAR);
++ do_test (align, i, -buf_addr - j, BIG_CHAR);
++ }
++ }
++ }
+ }
+ }
+
+diff --git a/sysdeps/x86_64/multiarch/strlen-avx2.S b/sysdeps/x86_64/multiarch/strlen-avx2.S
+index 0593fb303b..b9b58ef599 100644
+--- a/sysdeps/x86_64/multiarch/strlen-avx2.S
++++ b/sysdeps/x86_64/multiarch/strlen-avx2.S
+@@ -544,14 +544,11 @@ L(return_vzeroupper):
+ L(cross_page_less_vec):
+ tzcntl %eax, %eax
+ # ifdef USE_AS_WCSLEN
+- /* NB: Multiply length by 4 to get byte count. */
+- sall $2, %esi
++ /* NB: Divide by 4 to convert from byte-count to length. */
++ shrl $2, %eax
+ # endif
+ cmpq %rax, %rsi
+ cmovb %esi, %eax
+-# ifdef USE_AS_WCSLEN
+- shrl $2, %eax
+-# endif
+ VZEROUPPER_RETURN
+ # endif
+
+--
+2.33.0
+
diff --git a/bench.mk b/bench.mk
new file mode 100644
index 0000000..dfe46bd
--- /dev/null
+++ b/bench.mk
@@ -0,0 +1,77 @@
+objpfx = $(prefix)/$(ver)/usr/libexec/glibc-benchtests/
+
+bench-math := acos acosh asin asinh atan atanh cos cosh exp exp2 ffs ffsll \
+ log log2 modf pow rint sin sincos sinh sqrt tan tanh
+
+bench-pthread := pthread_once
+
+bench := $(bench-math) $(bench-pthread)
+
+run-bench := $(prefix)/$(ver)/lib64/ld-linux-x86-64.so.2 --library-path $(prefix)/$(ver)/lib64 $${run}
+
+# String function benchmarks.
+string-bench := bcopy bzero memccpy memchr memcmp memcpy memmem memmove \
+ mempcpy memset rawmemchr stpcpy stpncpy strcasecmp strcasestr \
+ strcat strchr strchrnul strcmp strcpy strcspn strlen \
+ strncasecmp strncat strncmp strncpy strnlen strpbrk strrchr \
+ strspn strstr strcpy_chk stpcpy_chk memrchr strsep strtok
+string-bench-all := $(string-bench)
+
+stdlib-bench := strtod
+
+benchset := $(string-bench-all) $(stdlib-bench)
+
+bench-malloc := malloc-thread
+
+binaries-bench := $(addprefix $(objpfx)bench-,$(bench))
+binaries-benchset := $(addprefix $(objpfx)bench-,$(benchset))
+binaries-bench-malloc := $(addprefix $(objpfx)bench-,$(bench-malloc))
+
+DETAILED_OPT :=
+
+ifdef DETAILED
+ DETAILED_OPT := -d
+endif
+
+bench: bench-set bench-func bench-malloc
+
+bench-set: $(binaries-benchset)
+ for run in $^; do \
+ outfile=$(prefix)/$$(basename $${run}.$(ver).out); \
+ echo "Running $${run}"; \
+ $(run-bench) > $${outfile}.tmp; \
+ mv $${outfile}{.tmp,}; \
+ done
+
+bench-malloc: $(binaries-bench-malloc)
+ run=$(objpfx)bench-malloc-thread; \
+ outfile=$(prefix)/$$(basename $${run}.$(ver).out); \
+ for thr in 1 8 16 32; do \
+ echo "Running $${run} $${thr}"; \
+ $(run-bench) $${thr} > $${outfile}.tmp; \
+ mv $${outfile}{.tmp,}; \
+ done
+
+# Build and execute the benchmark functions. This target generates JSON
+# formatted bench.out. Each of the programs produce independent JSON output,
+# so one could even execute them individually and process it using any JSON
+# capable language or tool.
+bench-func: $(binaries-bench)
+ { echo "{\"timing_type\": \"hp-timing\","; \
+ echo " \"functions\": {"; \
+ for run in $^; do \
+ if ! [ "x$${run}" = "x$<" ]; then \
+ echo ","; \
+ fi; \
+ echo "Running $${run}" >&2; \
+ $(run-bench) $(DETAILED_OPT); \
+ done; \
+ echo; \
+ echo " }"; \
+ echo "}"; } > $(prefix)/bench.$(ver).out-tmp; \
+ if [ -f $(prefix)/bench.$(ver).out ]; then \
+ mv -f $(prefix)/bench.$(ver).out{,.old}; \
+ fi; \
+ mv -f $(prefix)/bench.$(ver).out{-tmp,}
+# scripts/validate_benchout.py bench.out \
+# scripts/benchout.schema.json
diff --git a/copy_and_spawn_sgid-Avoid-double-calls-to-close.patch b/copy_and_spawn_sgid-Avoid-double-calls-to-close.patch
new file mode 100644
index 0000000..0f47990
--- /dev/null
+++ b/copy_and_spawn_sgid-Avoid-double-calls-to-close.patch
@@ -0,0 +1,28 @@
+From 45caed9d67a00af917d8b5b88d4b5eb1225b7aef Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Tue, 3 Aug 2021 21:10:53 +0530
+Subject: [PATCH] copy_and_spawn_sgid: Avoid double calls to close()
+
+If close() on infd and outfd succeeded, reset the fd numbers so that
+we don't attempt to close them again.
+
+Reviewed-by: Arjun Shankar <arjun@redhat.com>
+---
+ support/support_capture_subprocess.c | 1 +
+ 1 file changed, 1 insertion(+)
+
+diff --git a/support/support_capture_subprocess.c b/support/support_capture_subprocess.c
+index 27bfd19..0bacf6d 100644
+--- a/support/support_capture_subprocess.c
++++ b/support/support_capture_subprocess.c
+@@ -170,6 +170,7 @@ copy_and_spawn_sgid (char *child_id, gid_t gid)
+ support_subprogram because we only want the program exit status, not the
+ contents. */
+ ret = 0;
++ infd = outfd = -1;
+
+ char * const args[] = {execname, child_id, NULL};
+
+--
+1.8.3.1
+
diff --git a/delete-check-installed-headers-c-and-check-installed.patch b/delete-check-installed-headers-c-and-check-installed.patch
new file mode 100644
index 0000000..b4fa934
--- /dev/null
+++ b/delete-check-installed-headers-c-and-check-installed.patch
@@ -0,0 +1,60 @@
+From dd2efa50d197e2205acd8edbf29aba717d71bdbb Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Tue, 4 Jan 2022 19:55:28 +0800
+Subject: [PATCH] testsuit: delete check-installed-headers-c and check-installed-headers-cxx
+
+check-installed-headers-c and check-installed-headers-cxx checked at CI
+and can be deleted during building
+
+---
+ Makefile | 4 ++--
+ Rules | 4 ++--
+ 2 files changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/Makefile b/Makefile
+index f98d5a9e..83200a75 100644
+--- a/Makefile
++++ b/Makefile
+@@ -532,7 +532,7 @@ $(objpfx)check-local-headers.out: scripts/check-local-headers.sh
+
+ ifneq "$(headers)" ""
+ # Special test of all the installed headers in this directory.
+-tests-special += $(objpfx)check-installed-headers-c.out
++# tests-special += $(objpfx)check-installed-headers-c.out
+ libof-check-installed-headers-c := testsuite
+ $(objpfx)check-installed-headers-c.out: \
+ scripts/check-installed-headers.sh $(headers)
+@@ -542,7 +541,7 @@ $(objpfx)check-installed-headers-c.out: \
+ $(evaluate-test)
+
+ ifneq "$(CXX)" ""
+-tests-special += $(objpfx)check-installed-headers-cxx.out
++# tests-special += $(objpfx)check-installed-headers-cxx.out
+ libof-check-installed-headers-cxx := testsuite
+ $(objpfx)check-installed-headers-cxx.out: \
+ scripts/check-installed-headers.sh $(headers)
+diff --git a/Rules b/Rules
+index b1137afe..ca29abd7 100644
+--- a/Rules
++++ b/Rules
+@@ -84,7 +84,7 @@ common-generated += dummy.o dummy.c
+ ifneq "$(headers)" ""
+ # Test that all of the headers installed by this directory can be compiled
+ # in isolation.
+-tests-special += $(objpfx)check-installed-headers-c.out
++# tests-special += $(objpfx)check-installed-headers-c.out
+ libof-check-installed-headers-c := testsuite
+ $(objpfx)check-installed-headers-c.out: \
+ $(..)scripts/check-installed-headers.sh $(headers)
+@@ -96,7 +95,7 @@ $(objpfx)check-installed-headers-c.out: \
+ ifneq "$(CXX)" ""
+ # If a C++ compiler is available, also test that they can be compiled
+ # in isolation as C++.
+-tests-special += $(objpfx)check-installed-headers-cxx.out
++# tests-special += $(objpfx)check-installed-headers-cxx.out
+ libof-check-installed-headers-cxx := testsuite
+ $(objpfx)check-installed-headers-cxx.out: \
+ $(..)scripts/check-installed-headers.sh $(headers)
+--
+2.27.0
+
diff --git a/delete-no-hard-link-to-avoid-all_language-package-to.patch b/delete-no-hard-link-to-avoid-all_language-package-to.patch
new file mode 100644
index 0000000..1ccebcc
--- /dev/null
+++ b/delete-no-hard-link-to-avoid-all_language-package-to.patch
@@ -0,0 +1,26 @@
+From ba6891f0633d394a59d14f0a54090fa1b6260c16 Mon Sep 17 00:00:00 2001
+From: buque <wuxu.wu@hotmail.com>
+Date: Wed, 15 Jul 2020 15:09:54 +0800
+Subject: [PATCH] delete --no-hard-link to avoid all_language package too
+ large.
+
+---
+ Makefile | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/localedata/Makefile b/localedata/Makefile
+index b8a3b67..c78d0fe 100644
+--- a/localedata/Makefile
++++ b/localedata/Makefile
+@@ -444,7 +444,7 @@ $(INSTALL-SUPPORTED-LOCALE-ARCHIVE): install-locales-dir
+ $(build-one-locale)
+
+ $(INSTALL-SUPPORTED-LOCALE-FILES): install-locales-dir
+- @flags="-c --no-archive --no-hard-links"; \
++ @flags="-c --no-archive"; \
+ $(build-one-locale)
+
+ tst-setlocale-ENV = LC_ALL=ja_JP.EUC-JP
+--
+2.25.1
+
diff --git a/dlfcn-Do-not-use-rtld_active-to-determine-ld.so-stat.patch b/dlfcn-Do-not-use-rtld_active-to-determine-ld.so-stat.patch
new file mode 100644
index 0000000..2a4e89b
--- /dev/null
+++ b/dlfcn-Do-not-use-rtld_active-to-determine-ld.so-stat.patch
@@ -0,0 +1,400 @@
+From 8dcb6d0af07fda3607b541857e4f3970a74ed55b Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 26 Apr 2022 14:23:02 +0200
+Subject: [PATCH] dlfcn: Do not use rtld_active () to determine ld.so state
+ (bug 29078)
+
+Conflict:adapt Makefile context
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=8dcb6d0af07fda3607b541857e4f3970a74ed55b
+
+When audit modules are loaded, ld.so initialization is not yet
+complete, and rtld_active () returns false even though ld.so is
+mostly working. Instead, the static dlopen hook is used, but that
+does not work at all because this is not a static dlopen situation.
+
+Commit 466c1ea15f461edb8e3ffaf5d86d708876343bbf ("dlfcn: Rework
+static dlopen hooks") moved the hook pointer into _rtld_global_ro,
+which means that separate protection is not needed anymore and the
+hook pointer can be checked directly.
+
+The guard for disabling libio vtable hardening in _IO_vtable_check
+should stay for now.
+
+Fixes commit 8e1472d2c1e25e6eabc2059170731365f6d5b3d1 ("ld.so:
+Examine GLRO to detect inactive loader [BZ #20204]").
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ dlfcn/dladdr.c | 2 +-
+ dlfcn/dladdr1.c | 2 +-
+ dlfcn/dlclose.c | 2 +-
+ dlfcn/dlerror.c | 2 +-
+ dlfcn/dlinfo.c | 2 +-
+ dlfcn/dlmopen.c | 2 +-
+ dlfcn/dlopen.c | 2 +-
+ dlfcn/dlopenold.c | 2 +-
+ dlfcn/dlsym.c | 2 +-
+ dlfcn/dlvsym.c | 2 +-
+ elf/Makefile | 6 +++
+ elf/dl-libc.c | 8 ++--
+ elf/tst-audit26.c | 35 +++++++++++++++
+ elf/tst-auditmod26.c | 104 +++++++++++++++++++++++++++++++++++++++++++
+ 14 files changed, 159 insertions(+), 14 deletions(-)
+ create mode 100644 elf/tst-audit26.c
+ create mode 100644 elf/tst-auditmod26.c
+
+diff --git a/dlfcn/dladdr.c b/dlfcn/dladdr.c
+index ead117326f..d188d0e289 100644
+--- a/dlfcn/dladdr.c
++++ b/dlfcn/dladdr.c
+@@ -24,7 +24,7 @@ int
+ __dladdr (const void *address, Dl_info *info)
+ {
+ #ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dladdr (address, info);
+ #endif
+ return _dl_addr (address, info, NULL, NULL);
+diff --git a/dlfcn/dladdr1.c b/dlfcn/dladdr1.c
+index 5dadfd1220..e0c9526c90 100644
+--- a/dlfcn/dladdr1.c
++++ b/dlfcn/dladdr1.c
+@@ -24,7 +24,7 @@ int
+ __dladdr1 (const void *address, Dl_info *info, void **extra, int flags)
+ {
+ #ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dladdr1 (address, info, extra, flags);
+ #endif
+
+diff --git a/dlfcn/dlclose.c b/dlfcn/dlclose.c
+index a9921c3169..aab88c47fc 100644
+--- a/dlfcn/dlclose.c
++++ b/dlfcn/dlclose.c
+@@ -24,7 +24,7 @@ int
+ __dlclose (void *handle)
+ {
+ #ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlclose (handle);
+ #endif
+
+diff --git a/dlfcn/dlerror.c b/dlfcn/dlerror.c
+index 3bf6049e3c..b899d252a1 100644
+--- a/dlfcn/dlerror.c
++++ b/dlfcn/dlerror.c
+@@ -32,7 +32,7 @@ char *
+ __dlerror (void)
+ {
+ # ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlerror ();
+ # endif
+
+diff --git a/dlfcn/dlinfo.c b/dlfcn/dlinfo.c
+index fc63c02681..068db5260c 100644
+--- a/dlfcn/dlinfo.c
++++ b/dlfcn/dlinfo.c
+@@ -89,7 +89,7 @@ dlinfo_implementation (void *handle, int request, void *arg)
+ int
+ ___dlinfo (void *handle, int request, void *arg)
+ {
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlinfo (handle, request, arg);
+ else
+ return dlinfo_implementation (handle, request, arg);
+diff --git a/dlfcn/dlmopen.c b/dlfcn/dlmopen.c
+index 2437f5ce22..b41778f16c 100644
+--- a/dlfcn/dlmopen.c
++++ b/dlfcn/dlmopen.c
+@@ -80,7 +80,7 @@ dlmopen_implementation (Lmid_t nsid, const char *file, int mode,
+ void *
+ ___dlmopen (Lmid_t nsid, const char *file, int mode)
+ {
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlmopen (nsid, file, mode, RETURN_ADDRESS (0));
+ else
+ return dlmopen_implementation (nsid, file, mode, RETURN_ADDRESS (0));
+diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
+index 846ca38338..2696dde4b1 100644
+--- a/dlfcn/dlopen.c
++++ b/dlfcn/dlopen.c
+@@ -75,7 +75,7 @@ dlopen_implementation (const char *file, int mode, void *dl_caller)
+ void *
+ ___dlopen (const char *file, int mode)
+ {
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlopen (file, mode, RETURN_ADDRESS (0));
+ else
+ return dlopen_implementation (file, mode, RETURN_ADDRESS (0));
+diff --git a/dlfcn/dlopenold.c b/dlfcn/dlopenold.c
+index 67601434df..5c21a00496 100644
+--- a/dlfcn/dlopenold.c
++++ b/dlfcn/dlopenold.c
+@@ -70,7 +70,7 @@ __dlopen_nocheck (const char *file, int mode)
+ mode |= RTLD_LAZY;
+ args.mode = mode;
+
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlopen (file, mode, RETURN_ADDRESS (0));
+
+ return _dlerror_run (dlopen_doit, &args) ? NULL : args.new;
+diff --git a/dlfcn/dlsym.c b/dlfcn/dlsym.c
+index a71f8ae247..2e9ff98e79 100644
+--- a/dlfcn/dlsym.c
++++ b/dlfcn/dlsym.c
+@@ -62,7 +62,7 @@ dlsym_implementation (void *handle, const char *name, void *dl_caller)
+ void *
+ ___dlsym (void *handle, const char *name)
+ {
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlsym (handle, name, RETURN_ADDRESS (0));
+ else
+ return dlsym_implementation (handle, name, RETURN_ADDRESS (0));
+diff --git a/dlfcn/dlvsym.c b/dlfcn/dlvsym.c
+index 72219d6da6..caa46ba1e0 100644
+--- a/dlfcn/dlvsym.c
++++ b/dlfcn/dlvsym.c
+@@ -65,7 +65,7 @@ dlvsym_implementation (void *handle, const char *name, const char *version,
+ void *
+ ___dlvsym (void *handle, const char *name, const char *version)
+ {
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->dlvsym (handle, name, version,
+ RETURN_ADDRESS (0));
+ else
+diff --git a/elf/Makefile b/elf/Makefile
+index 8ed6c3b0b1..e4907d5de9 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -390,6 +390,7 @@ tests += \
+ tst-audit16 \
+ tst-audit17 \
+ tst-audit21 \
++ tst-audit26 \
+ tst-auditmany \
+ tst-auxobj \
+ tst-auxobj-dlopen \
+@@ -767,6 +768,7 @@ modules-names = \
+ tst-auditmod12 \
+ tst-auditmod21a \
+ tst-auditmod21b \
++ tst-auditmod26 \
+ tst-auxvalmod \
+ tst-big-note-lib \
+ tst-deep1mod1 \
+@@ -2286,6 +2288,10 @@ $(objpfx)tst-audit25b: $(objpfx)tst-audit25mod1.so \
+ $(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so
+ tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so
+
++$(objpfx)tst-audit26.out: $(objpfx)tst-auditmod26.so
++$(objpfx)tst-auditmod26.so: $(libsupport)
++tst-audit26-ENV = LD_AUDIT=$(objpfx)tst-auditmod26.so
++
+ # tst-sonamemove links against an older implementation of the library.
+ LDFLAGS-tst-sonamemove-linkmod1.so = \
+ -Wl,--version-script=tst-sonamemove-linkmod1.map \
+diff --git a/elf/dl-libc.c b/elf/dl-libc.c
+index a7180d0af8..266e068da6 100644
+--- a/elf/dl-libc.c
++++ b/elf/dl-libc.c
+@@ -156,7 +156,7 @@ __libc_dlopen_mode (const char *name, int mode)
+ args.caller_dlopen = RETURN_ADDRESS (0);
+
+ #ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->libc_dlopen_mode (name, mode);
+ #endif
+ return dlerror_run (do_dlopen, &args) ? NULL : (void *) args.map;
+@@ -184,7 +184,7 @@ __libc_dlsym (void *map, const char *name)
+ args.name = name;
+
+ #ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->libc_dlsym (map, name);
+ #endif
+ return (dlerror_run (do_dlsym, &args) ? NULL
+@@ -198,7 +198,7 @@ void *
+ __libc_dlvsym (void *map, const char *name, const char *version)
+ {
+ #ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->libc_dlvsym (map, name, version);
+ #endif
+
+@@ -221,7 +221,7 @@ int
+ __libc_dlclose (void *map)
+ {
+ #ifdef SHARED
+- if (!rtld_active ())
++ if (GLRO (dl_dlfcn_hook) != NULL)
+ return GLRO (dl_dlfcn_hook)->libc_dlclose (map);
+ #endif
+ return dlerror_run (do_dlclose, map);
+diff --git a/elf/tst-audit26.c b/elf/tst-audit26.c
+new file mode 100644
+index 0000000000..3f920e83ba
+--- /dev/null
++++ b/elf/tst-audit26.c
+@@ -0,0 +1,35 @@
++/* Check the usability of <dlfcn.h> functions in audit modules.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <gnu/lib-names.h>
++
++#include <support/check.h>
++#include <support/xdlfcn.h>
++
++static int
++do_test (void)
++{
++ /* Check that the audit module has been loaded. */
++ void *handle = xdlopen ("mapped to libc", RTLD_LOCAL | RTLD_NOW);
++ TEST_VERIFY (handle
++ == xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD));
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/elf/tst-auditmod26.c b/elf/tst-auditmod26.c
+new file mode 100644
+index 0000000000..db7ba95abe
+--- /dev/null
++++ b/elf/tst-auditmod26.c
+@@ -0,0 +1,104 @@
++/* Check the usability of <dlfcn.h> functions in audit modules. Audit module.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <dlfcn.h>
++#include <first-versions.h>
++#include <gnu/lib-names.h>
++#include <link.h>
++#include <stdio.h>
++#include <string.h>
++#include <unistd.h>
++
++#include <support/check.h>
++#include <support/xdlfcn.h>
++
++unsigned int
++la_version (unsigned int current)
++{
++ /* Exercise various <dlfcn.h> functions. */
++
++ /* Check dlopen, dlsym, dlclose. */
++ void *handle = xdlopen (LIBM_SO, RTLD_LOCAL | RTLD_NOW);
++ void *ptr = xdlsym (handle, "sincos");
++ TEST_VERIFY (ptr != NULL);
++ ptr = dlsym (handle, "SINCOS");
++ TEST_VERIFY (ptr == NULL);
++ const char *message = dlerror ();
++ TEST_VERIFY (strstr (message, ": undefined symbol: SINCOS") != NULL);
++ ptr = dlsym (handle, "SINCOS");
++ TEST_VERIFY (ptr == NULL);
++ xdlclose (handle);
++ TEST_COMPARE_STRING (dlerror (), NULL);
++
++ handle = xdlopen (LIBC_SO, RTLD_LOCAL | RTLD_NOW | RTLD_NOLOAD);
++
++ /* Check dlvsym. _exit is unlikely to gain another symbol
++ version. */
++ TEST_VERIFY (xdlsym (handle, "_exit")
++ == xdlvsym (handle, "_exit", FIRST_VERSION_libc__exit_STRING));
++
++ /* Check dlinfo. */
++ {
++ void *handle2 = NULL;
++ TEST_COMPARE (dlinfo (handle, RTLD_DI_LINKMAP, &handle2), 0);
++ TEST_VERIFY (handle2 == handle);
++ }
++
++ /* Check dladdr and dladdr1. */
++ Dl_info info = { };
++ TEST_VERIFY (dladdr (&_exit, &info) != 0);
++ if (strcmp (info.dli_sname, "_Exit") != 0) /* _Exit is an alias. */
++ TEST_COMPARE_STRING (info.dli_sname, "_exit");
++ TEST_VERIFY (info.dli_saddr == &_exit);
++ TEST_VERIFY (strstr (info.dli_fname, LIBC_SO));
++ void *extra_info;
++ memset (&info, 0, sizeof (info));
++ TEST_VERIFY (dladdr1 (&_exit, &info, &extra_info, RTLD_DL_LINKMAP) != 0);
++ TEST_VERIFY (extra_info == handle);
++
++ /* Verify that dlmopen creates a new namespace. */
++ void *dlmopen_handle = xdlmopen (LM_ID_NEWLM, LIBC_SO, RTLD_NOW);
++ TEST_VERIFY (dlmopen_handle != handle);
++ memset (&info, 0, sizeof (info));
++ extra_info = NULL;
++ ptr = xdlsym (dlmopen_handle, "_exit");
++ TEST_VERIFY (dladdr1 (ptr, &info, &extra_info, RTLD_DL_LINKMAP) != 0);
++ TEST_VERIFY (extra_info == dlmopen_handle);
++ xdlclose (dlmopen_handle);
++
++ /* Terminate the process with an error state. This does not happen
++ automatically because the audit module state is not shared with
++ the main program. */
++ if (support_record_failure_is_failed ())
++ {
++ fflush (stdout);
++ fflush (stderr);
++ _exit (1);
++ }
++
++ return LAV_CURRENT;
++}
++
++char *
++la_objsearch (const char *name, uintptr_t *cookie, unsigned int flag)
++{
++ if (strcmp (name, "mapped to libc") == 0)
++ return (char *) LIBC_SO;
++ else
++ return (char *) name;
++}
+--
+2.27.0
+
diff --git a/dlfcn-Pass-caller-pointer-to-static-dlopen-implement.patch b/dlfcn-Pass-caller-pointer-to-static-dlopen-implement.patch
new file mode 100644
index 0000000..0b49ec3
--- /dev/null
+++ b/dlfcn-Pass-caller-pointer-to-static-dlopen-implement.patch
@@ -0,0 +1,31 @@
+From ed0185e4129130cbe081c221efb758fb400623ce Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 4 Aug 2022 17:54:48 +0200
+Subject: [PATCH] dlfcn: Pass caller pointer to static dlopen implementation
+ (bug 29446)
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=ed0185e4129130cbe081c221efb758fb400623ce
+
+Fixes commit 0c1c3a771eceec46e66ce1183cf988e2303bd373 ("dlfcn: Move
+dlopen into libc").
+---
+ dlfcn/dlopen.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/dlfcn/dlopen.c b/dlfcn/dlopen.c
+index 2696dde4b1..9b07b4e132 100644
+--- a/dlfcn/dlopen.c
++++ b/dlfcn/dlopen.c
+@@ -90,7 +90,7 @@ compat_symbol (libdl, ___dlopen, dlopen, GLIBC_2_1);
+ void *
+ __dlopen (const char *file, int mode, void *dl_caller)
+ {
+- return dlopen_implementation (file, mode, RETURN_ADDRESS (0));
++ return dlopen_implementation (file, mode, dl_caller);
+ }
+
+ void *
+--
+2.27.0
+
diff --git a/elf-Add-a-comment-after-trailing-backslashes.patch b/elf-Add-a-comment-after-trailing-backslashes.patch
new file mode 100644
index 0000000..101371e
--- /dev/null
+++ b/elf-Add-a-comment-after-trailing-backslashes.patch
@@ -0,0 +1,49 @@
+From 511b244cc55074dc7f8476c39598d5d00811963e Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Tue, 4 Jan 2022 06:58:34 -0800
+Subject: [PATCH] elf: Add a comment after trailing backslashes
+
+(cherry picked from commit f4f70c2895e3d325188a42c10eb7bb4335be6773)
+---
+ elf/Makefile | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index ec1cd49bb3..5859d47fc7 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -318,6 +318,7 @@ tests-cxx = \
+ tst-nodelete \
+ tst-unique3 \
+ tst-unique4 \
++# tests-cxx
+
+ tests += $(if $(CXX),$(tests-cxx))
+ tests-internal += loadtest unload unload2 circleload1 \
+@@ -582,6 +583,7 @@ modules-names = \
+ vismod1 \
+ vismod2 \
+ vismod3 \
++# modules-names
+
+ modules-names-cxx = \
+ tst-dlopen-nodelete-reloc-mod1 \
+@@ -607,6 +609,7 @@ modules-names-cxx = \
+ tst-unique3lib \
+ tst-unique3lib2 \
+ tst-unique4lib \
++# modules-names-cxx
+
+ modules-names += \
+ $(if $(CXX),$(modules-names-cxx)) \
+@@ -616,6 +619,7 @@ modules-names += \
+ $(tst-tls-many-dynamic-modules-dep-bad) \
+ $(tlsmod17a-modules) \
+ $(tlsmod18a-modules) \
++# modules-names
+
+ # Most modules build with _ISOMAC defined, but those filtered out
+ # depend on internal headers.
+--
+2.27.0
+
diff --git a/elf-Add-a-way-to-check-if-tunable-is-set-BZ-27069.patch b/elf-Add-a-way-to-check-if-tunable-is-set-BZ-27069.patch
new file mode 100644
index 0000000..945a22e
--- /dev/null
+++ b/elf-Add-a-way-to-check-if-tunable-is-set-BZ-27069.patch
@@ -0,0 +1,202 @@
+From a4c3f5f46e850c977cda81c251036475aab8313c Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 23 Nov 2023 14:29:14 -0300
+Subject: [PATCH] elf: Add a way to check if tunable is set (BZ 27069)
+
+The patch adds two new macros, TUNABLE_GET_DEFAULT and TUNABLE_IS_INITIALIZED,
+here the former get the default value with a signature similar to
+TUNABLE_GET, while the later returns whether the tunable was set by
+the environment variable.
+
+Checked on x86_64-linux-gnu.
+Reviewed-by: DJ Delorie <dj@redhat.com>
+Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
+
+Conflict: this adapt the context of elf/Versions, scripts/gen-tunables.awk and
+ elf/dl-tunables.h
+---
+ elf/Versions | 1 +
+ elf/dl-tunable-types.h | 1 +
+ elf/dl-tunables.c | 40 ++++++++++++++++++++++++++++++++++++++++
+ elf/dl-tunables.h | 28 ++++++++++++++++++++++++++++
+ elf/dl-tunables.list | 1 +
+ scripts/gen-tunables.awk | 4 ++--
+ 6 files changed, 73 insertions(+), 2 deletions(-)
+
+diff --git a/elf/Versions b/elf/Versions
+index 2af210b8..9318b44a 100644
+--- a/elf/Versions
++++ b/elf/Versions
+@@ -74,6 +74,7 @@ ld {
+ _dl_signal_error; _dl_catch_error;
+
+ # Set value of a tunable.
++ __tunable_is_initialized;
+ __tunable_get_val;
+ }
+ }
+diff --git a/elf/dl-tunable-types.h b/elf/dl-tunable-types.h
+index 39bf738d..d36b0d75 100644
+--- a/elf/dl-tunable-types.h
++++ b/elf/dl-tunable-types.h
+@@ -61,6 +61,7 @@ struct _tunable
+ {
+ const char name[TUNABLE_NAME_MAX]; /* Internal name of the tunable. */
+ tunable_type_t type; /* Data type of the tunable. */
++ const tunable_val_t def; /* The value. */
+ tunable_val_t val; /* The value. */
+ bool initialized; /* Flag to indicate that the tunable is
+ initialized. */
+diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
+index 42631d39..a325e701 100644
+--- a/elf/dl-tunables.c
++++ b/elf/dl-tunables.c
+@@ -150,6 +150,13 @@ tunable_initialize (tunable_t *cur, const char *strval)
+ do_tunable_update_val (cur, &val, NULL, NULL);
+ }
+
++bool
++__tunable_is_initialized (tunable_id_t id)
++{
++ return tunable_list[id].initialized;
++}
++rtld_hidden_def (__tunable_is_initialized)
++
+ void
+ __tunable_set_val (tunable_id_t id, tunable_val_t *valp, tunable_num_t *minp,
+ tunable_num_t *maxp)
+@@ -397,6 +404,39 @@ __tunables_print (void)
+ }
+ }
+
++void
++__tunable_get_default (tunable_id_t id, void *valp)
++{
++ tunable_t *cur = &tunable_list[id];
++
++ switch (cur->type.type_code)
++ {
++ case TUNABLE_TYPE_UINT_64:
++ {
++ *((uint64_t *) valp) = (uint64_t) cur->def.numval;
++ break;
++ }
++ case TUNABLE_TYPE_INT_32:
++ {
++ *((int32_t *) valp) = (int32_t) cur->def.numval;
++ break;
++ }
++ case TUNABLE_TYPE_SIZE_T:
++ {
++ *((size_t *) valp) = (size_t) cur->def.numval;
++ break;
++ }
++ case TUNABLE_TYPE_STRING:
++ {
++ *((const char **)valp) = cur->def.strval;
++ break;
++ }
++ default:
++ __builtin_unreachable ();
++ }
++}
++rtld_hidden_def (__tunable_get_default)
++
+ /* Set the tunable value. This is called by the module that the tunable exists
+ in. */
+ void
+diff --git a/elf/dl-tunables.h b/elf/dl-tunables.h
+index 3880e4aa..9873c623 100644
+--- a/elf/dl-tunables.h
++++ b/elf/dl-tunables.h
+@@ -53,18 +53,26 @@ typedef void (*tunable_callback_t) (tunable_val_t *);
+
+ extern void __tunables_init (char **);
+ extern void __tunables_print (void);
++extern bool __tunable_is_initialized (tunable_id_t);
+ extern void __tunable_get_val (tunable_id_t, void *, tunable_callback_t);
+ extern void __tunable_set_val (tunable_id_t, tunable_val_t *, tunable_num_t *,
+ tunable_num_t *);
++extern void __tunable_get_default (tunable_id_t id, void *valp);
+ rtld_hidden_proto (__tunables_init)
+ rtld_hidden_proto (__tunables_print)
++rtld_hidden_proto (__tunable_is_initialized)
+ rtld_hidden_proto (__tunable_get_val)
+ rtld_hidden_proto (__tunable_set_val)
++rtld_hidden_proto (__tunable_get_default)
+
+ /* Define TUNABLE_GET and TUNABLE_SET in short form if TOP_NAMESPACE and
+ TUNABLE_NAMESPACE are defined. This is useful shorthand to get and set
+ tunables within a module. */
+ #if defined TOP_NAMESPACE && defined TUNABLE_NAMESPACE
++# define TUNABLE_IS_INITIALIZED(__id) \
++ TUNABLE_IS_INITIALIZED_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE, __id)
++# define TUNABLE_GET_DEFAULT(__id, __type) \
++ TUNABLE_GET_DEFAULT_FULL(TOP_NAMESPACE, TUNABLE_NAMESPACE,__id, __type)
+ # define TUNABLE_GET(__id, __type, __cb) \
+ TUNABLE_GET_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, __type, __cb)
+ # define TUNABLE_SET(__id, __val) \
+@@ -73,6 +81,10 @@ rtld_hidden_proto (__tunable_set_val)
+ TUNABLE_SET_WITH_BOUNDS_FULL (TOP_NAMESPACE, TUNABLE_NAMESPACE, __id, \
+ __val, __min, __max)
+ #else
++# define TUNABLE_IS_INITIALIZED(__top, __ns, __id) \
++ TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id)
++# define TUNABLE_GET_DEFAULT(__top, __ns, __type) \
++ TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type)
+ # define TUNABLE_GET(__top, __ns, __id, __type, __cb) \
+ TUNABLE_GET_FULL (__top, __ns, __id, __type, __cb)
+ # define TUNABLE_SET(__top, __ns, __id, __val) \
+@@ -81,6 +93,22 @@ rtld_hidden_proto (__tunable_set_val)
+ TUNABLE_SET_WITH_BOUNDS_FULL (__top, __ns, __id, __val, __min, __max)
+ #endif
+
++/* Return whether the tunable was initialized by the environment variable. */
++#define TUNABLE_IS_INITIALIZED_FULL(__top, __ns, __id) \
++({ \
++ tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id); \
++ __tunable_is_initialized (id); \
++})
++
++/* Return the default value of the tunable. */
++#define TUNABLE_GET_DEFAULT_FULL(__top, __ns, __id, __type) \
++({ \
++ tunable_id_t id = TUNABLE_ENUM_NAME (__top, __ns, __id); \
++ __type __ret; \
++ __tunable_get_default (id, &__ret); \
++ __ret; \
++})
++
+ /* Get and return a tunable value. If the tunable was set externally and __CB
+ is defined then call __CB before returning the value. */
+ # define TUNABLE_GET_FULL(__top, __ns, __id, __type, __cb) \
+diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
+index ea19387d..befecc34 100644
+--- a/elf/dl-tunables.list
++++ b/elf/dl-tunables.list
+@@ -20,6 +20,7 @@
+ # type: Defaults to STRING
+ # minval: Optional minimum acceptable value
+ # maxval: Optional maximum acceptable value
++# default: Optional default value (if not specified it will be 0 or "")
+ # env_alias: An alias environment variable
+ # security_level: Specify security level of the tunable for AT_SECURE binaries.
+ # Valid values are:
+diff --git a/scripts/gen-tunables.awk b/scripts/gen-tunables.awk
+index fa63e86d..29f94c63 100644
+--- a/scripts/gen-tunables.awk
++++ b/scripts/gen-tunables.awk
+@@ -177,8 +177,8 @@ END {
+ n = indices[2];
+ m = indices[3];
+ printf (" {TUNABLE_NAME_S(%s, %s, %s)", t, n, m)
+- printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
+- types[t,n,m], minvals[t,n,m], maxvals[t,n,m],
++ printf (", {TUNABLE_TYPE_%s, %s, %s}, {%s}, {%s}, NULL, TUNABLE_SECLEVEL_%s, %s},\n",
++ types[t,n,m], minvals[t,n,m], maxvals[t,n,m], default_val[t,n,m],
+ default_val[t,n,m], security_level[t,n,m], env_alias[t,n,m]);
+ }
+ print "};"
+--
+2.33.0
+
diff --git a/elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch b/elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch
new file mode 100644
index 0000000..da70902
--- /dev/null
+++ b/elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch
@@ -0,0 +1,482 @@
+From 83b5323261bb72313bffcf37476c1b8f0847c736 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Wed, 15 Sep 2021 15:16:19 +0100
+Subject: [PATCH] elf: Avoid deadlock between pthread_create and ctors [BZ
+ #28357]
+
+The fix for bug 19329 caused a regression such that pthread_create can
+deadlock when concurrent ctors from dlopen are waiting for it to finish.
+Use a new GL(dl_load_tls_lock) in pthread_create that is not taken
+around ctors in dlopen.
+
+The new lock is also used in __tls_get_addr instead of GL(dl_load_lock).
+
+The new lock is held in _dl_open_worker and _dl_close_worker around
+most of the logic before/after the init/fini routines. When init/fini
+routines are running then TLS is in a consistent, usable state.
+In _dl_open_worker the new lock requires catching and reraising dlopen
+failures that happen in the critical section.
+
+The new lock is reinitialized in a fork child, to keep the existing
+behaviour and it is kept recursive in case malloc interposition or TLS
+access from signal handlers can retake it. It is not obvious if this
+is necessary or helps, but avoids changing the preexisting behaviour.
+
+The new lock may be more appropriate for dl_iterate_phdr too than
+GL(dl_load_write_lock), since TLS state of an incompletely loaded
+module may be accessed. If the new lock can replace the old one,
+that can be a separate change.
+
+Fixes bug 28357.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ elf/dl-close.c | 6 ++
+ elf/dl-open.c | 35 +++++++++++-
+ elf/dl-support.c | 7 +++
+ elf/dl-tls.c | 16 +++---
+ elf/rtld.c | 1 +
+ posix/fork.c | 3 +
+ sysdeps/generic/ldsodefs.h | 9 ++-
+ sysdeps/pthread/Makefile | 10 +++-
+ sysdeps/pthread/tst-create1.c | 119 +++++++++++++++++++++++++++++++++++++++
+ sysdeps/pthread/tst-create1mod.c | 41 ++++++++++++++
+ 10 files changed, 235 insertions(+), 12 deletions(-)
+ create mode 100644 sysdeps/pthread/tst-create1.c
+ create mode 100644 sysdeps/pthread/tst-create1mod.c
+
+diff --git a/elf/dl-close.c b/elf/dl-close.c
+index 93ff5c9..cfe0f1c 100644
+--- a/elf/dl-close.c
++++ b/elf/dl-close.c
+@@ -549,6 +549,9 @@ _dl_close_worker (struct link_map *map, bool force)
+ size_t tls_free_end;
+ tls_free_start = tls_free_end = NO_TLS_OFFSET;
+
++ /* Protects global and module specitic TLS state. */
++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
++
+ /* We modify the list of loaded objects. */
+ __rtld_lock_lock_recursive (GL(dl_load_write_lock));
+
+@@ -784,6 +787,9 @@ _dl_close_worker (struct link_map *map, bool force)
+ GL(dl_tls_static_used) = tls_free_start;
+ }
+
++ /* TLS is cleaned up for the unloaded modules. */
++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
++
+ #ifdef SHARED
+ /* Auditing checkpoint: we have deleted all objects. */
+ if (__glibc_unlikely (do_audit))
+diff --git a/elf/dl-open.c b/elf/dl-open.c
+index 5295e93..6ea5dd2 100644
+--- a/elf/dl-open.c
++++ b/elf/dl-open.c
+@@ -66,6 +66,9 @@ struct dl_open_args
+ libc_map value in the namespace in case of a dlopen failure. */
+ bool libc_already_loaded;
+
++ /* Set to true if the end of dl_open_worker_begin was reached. */
++ bool worker_continue;
++
+ /* Original parameters to the program and the current environment. */
+ int argc;
+ char **argv;
+@@ -482,7 +485,7 @@ call_dl_init (void *closure)
+ }
+
+ static void
+-dl_open_worker (void *a)
++dl_open_worker_begin (void *a)
+ {
+ struct dl_open_args *args = a;
+ const char *file = args->file;
+@@ -774,6 +777,36 @@ dl_open_worker (void *a)
+ _dl_call_libc_early_init (libc_map, false);
+ }
+
++ args->worker_continue = true;
++}
++
++static void
++dl_open_worker (void *a)
++{
++ struct dl_open_args *args = a;
++
++ args->worker_continue = false;
++
++ {
++ /* Protects global and module specific TLS state. */
++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
++
++ struct dl_exception ex;
++ int err = _dl_catch_exception (&ex, dl_open_worker_begin, args);
++
++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
++
++ if (__glibc_unlikely (ex.errstring != NULL))
++ /* Reraise the error. */
++ _dl_signal_exception (err, &ex, NULL);
++ }
++
++ if (!args->worker_continue)
++ return;
++
++ int mode = args->mode;
++ struct link_map *new = args->map;
++
+ /* Run the initializer functions of new objects. Temporarily
+ disable the exception handler, so that lazy binding failures are
+ fatal. */
+diff --git a/elf/dl-support.c b/elf/dl-support.c
+index 02e2ed7..d99c1f1 100644
+--- a/elf/dl-support.c
++++ b/elf/dl-support.c
+@@ -228,6 +228,13 @@ __rtld_lock_define_initialized_recursive (, _dl_load_lock)
+ list of loaded objects while an object is added to or removed from
+ that list. */
+ __rtld_lock_define_initialized_recursive (, _dl_load_write_lock)
++ /* This lock protects global and module specific TLS related data.
++ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
++ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
++ accessed and when TLS related relocations are processed for a
++ module. It was introduced to keep pthread_create accessing TLS
++ state that is being set up. */
++__rtld_lock_define_initialized_recursive (, _dl_load_tls_lock)
+
+
+ #ifdef HAVE_AUX_VECTOR
+diff --git a/elf/dl-tls.c b/elf/dl-tls.c
+index d554ae4..9260d2d 100644
+--- a/elf/dl-tls.c
++++ b/elf/dl-tls.c
+@@ -532,7 +532,7 @@ _dl_allocate_tls_init (void *result)
+ size_t maxgen = 0;
+
+ /* Protects global dynamic TLS related state. */
+- __rtld_lock_lock_recursive (GL(dl_load_lock));
++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
+
+ /* Check if the current dtv is big enough. */
+ if (dtv[-1].counter < GL(dl_tls_max_dtv_idx))
+@@ -606,7 +606,7 @@ _dl_allocate_tls_init (void *result)
+ listp = listp->next;
+ assert (listp != NULL);
+ }
+- __rtld_lock_unlock_recursive (GL(dl_load_lock));
++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
+
+ /* The DTV version is up-to-date now. */
+ dtv[0].counter = maxgen;
+@@ -745,7 +745,7 @@ _dl_update_slotinfo (unsigned long int req_modid)
+
+ Here the dtv needs to be updated to new_gen generation count.
+
+- This code may be called during TLS access when GL(dl_load_lock)
++ This code may be called during TLS access when GL(dl_load_tls_lock)
+ is not held. In that case the user code has to synchronize with
+ dlopen and dlclose calls of relevant modules. A module m is
+ relevant if the generation of m <= new_gen and dlclose of m is
+@@ -867,11 +867,11 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
+ if (__glibc_unlikely (the_map->l_tls_offset
+ != FORCED_DYNAMIC_TLS_OFFSET))
+ {
+- __rtld_lock_lock_recursive (GL(dl_load_lock));
++ __rtld_lock_lock_recursive (GL(dl_load_tls_lock));
+ if (__glibc_likely (the_map->l_tls_offset == NO_TLS_OFFSET))
+ {
+ the_map->l_tls_offset = FORCED_DYNAMIC_TLS_OFFSET;
+- __rtld_lock_unlock_recursive (GL(dl_load_lock));
++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
+ }
+ else if (__glibc_likely (the_map->l_tls_offset
+ != FORCED_DYNAMIC_TLS_OFFSET))
+@@ -883,7 +883,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
+ #else
+ # error "Either TLS_TCB_AT_TP or TLS_DTV_AT_TP must be defined"
+ #endif
+- __rtld_lock_unlock_recursive (GL(dl_load_lock));
++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
+
+ dtv[GET_ADDR_MODULE].pointer.to_free = NULL;
+ dtv[GET_ADDR_MODULE].pointer.val = p;
+@@ -891,7 +891,7 @@ tls_get_addr_tail (GET_ADDR_ARGS, dtv_t *dtv, struct link_map *the_map)
+ return (char *) p + GET_ADDR_OFFSET;
+ }
+ else
+- __rtld_lock_unlock_recursive (GL(dl_load_lock));
++ __rtld_lock_unlock_recursive (GL(dl_load_tls_lock));
+ }
+ struct dtv_pointer result = allocate_and_init (the_map);
+ dtv[GET_ADDR_MODULE].pointer = result;
+@@ -962,7 +962,7 @@ _dl_tls_get_addr_soft (struct link_map *l)
+ return NULL;
+
+ dtv_t *dtv = THREAD_DTV ();
+- /* This may be called without holding the GL(dl_load_lock). Reading
++ /* This may be called without holding the GL(dl_load_tls_lock). Reading
+ arbitrary gen value is fine since this is best effort code. */
+ size_t gen = atomic_load_relaxed (&GL(dl_tls_generation));
+ if (__glibc_unlikely (dtv[0].counter != gen))
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 8d2bba3..9642eb9 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -322,6 +322,7 @@ struct rtld_global _rtld_global =
+ #ifdef _LIBC_REENTRANT
+ ._dl_load_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
+ ._dl_load_write_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
++ ._dl_load_tls_lock = _RTLD_LOCK_RECURSIVE_INITIALIZER,
+ #endif
+ ._dl_nns = 1,
+ ._dl_ns =
+diff --git a/posix/fork.c b/posix/fork.c
+index c471f7b..021691b 100644
+--- a/posix/fork.c
++++ b/posix/fork.c
+@@ -99,6 +99,9 @@ __libc_fork (void)
+ /* Reset the lock the dynamic loader uses to protect its data. */
+ __rtld_lock_initialize (GL(dl_load_lock));
+
++ /* Reset the lock protecting dynamic TLS related data. */
++ __rtld_lock_initialize (GL(dl_load_tls_lock));
++
+ reclaim_stacks ();
+
+ /* Run the handlers registered for the child. */
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index d49529d..9ec1511 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -369,6 +369,13 @@ struct rtld_global
+ list of loaded objects while an object is added to or removed
+ from that list. */
+ __rtld_lock_define_recursive (EXTERN, _dl_load_write_lock)
++ /* This lock protects global and module specific TLS related data.
++ E.g. it is held in dlopen and dlclose when GL(dl_tls_generation),
++ GL(dl_tls_max_dtv_idx) or GL(dl_tls_dtv_slotinfo_list) are
++ accessed and when TLS related relocations are processed for a
++ module. It was introduced to keep pthread_create accessing TLS
++ state that is being set up. */
++ __rtld_lock_define_recursive (EXTERN, _dl_load_tls_lock)
+
+ /* Incremented whenever something may have been added to dl_loaded. */
+ EXTERN unsigned long long _dl_load_adds;
+@@ -1268,7 +1275,7 @@ extern int _dl_scope_free (void *) attribute_hidden;
+
+ /* Add module to slot information data. If DO_ADD is false, only the
+ required memory is allocated. Must be called with GL
+- (dl_load_lock) acquired. If the function has already been called
++ (dl_load_tls_lock) acquired. If the function has already been called
+ for the link map L with !do_add, then this function will not raise
+ an exception, otherwise it is possible that it encounters a memory
+ allocation failure. */
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index 0af9c59..df8943f 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -152,15 +152,17 @@ tests += tst-cancelx2 tst-cancelx3 tst-cancelx6 tst-cancelx8 tst-cancelx9 \
+ tst-cleanupx0 tst-cleanupx1 tst-cleanupx2 tst-cleanupx3
+
+ ifeq ($(build-shared),yes)
+-tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1
++tests += tst-atfork2 tst-pt-tls4 tst-_res1 tst-fini1 tst-create1
+ tests-nolibpthread += tst-fini1
+ endif
+
+ modules-names += tst-atfork2mod tst-tls4moda tst-tls4modb \
+- tst-_res1mod1 tst-_res1mod2 tst-fini1mod
++ tst-_res1mod1 tst-_res1mod2 tst-fini1mod \
++ tst-create1mod
+ test-modules = $(addprefix $(objpfx),$(addsuffix .so,$(modules-names)))
+
+ tst-atfork2mod.so-no-z-defs = yes
++tst-create1mod.so-no-z-defs = yes
+
+ ifeq ($(build-shared),yes)
+ # Build all the modules even when not actually running test programs.
+@@ -279,4 +281,8 @@ LDFLAGS-tst-join7mod.so = -Wl,-soname,tst-join7mod.so
+
+ CFLAGS-tst-unwind-thread.c += -funwind-tables
+
++LDFLAGS-tst-create1 = -Wl,-export-dynamic
++$(objpfx)tst-create1: $(shared-thread-library)
++$(objpfx)tst-create1.out: $(objpfx)tst-create1mod.so
++
+ endif
+diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
+new file mode 100644
+index 0000000..932586c
+--- /dev/null
++++ b/sysdeps/pthread/tst-create1.c
+@@ -0,0 +1,119 @@
++/* Verify that pthread_create does not deadlock when ctors take locks.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++#include <support/xdlfcn.h>
++#include <support/xthread.h>
++
++/*
++Check if ctor and pthread_create deadlocks in
++
++thread 1: dlopen -> ctor -> lock(user_lock)
++thread 2: lock(user_lock) -> pthread_create
++
++or in
++
++thread 1: dlclose -> dtor -> lock(user_lock)
++thread 2: lock(user_lock) -> pthread_create
++*/
++
++static pthread_barrier_t bar_ctor;
++static pthread_barrier_t bar_dtor;
++static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
++
++void
++ctor (void)
++{
++ xpthread_barrier_wait (&bar_ctor);
++ dprintf (1, "thread 1: in ctor: started.\n");
++ xpthread_mutex_lock (&user_lock);
++ dprintf (1, "thread 1: in ctor: locked user_lock.\n");
++ xpthread_mutex_unlock (&user_lock);
++ dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
++ dprintf (1, "thread 1: in ctor: done.\n");
++}
++
++void
++dtor (void)
++{
++ xpthread_barrier_wait (&bar_dtor);
++ dprintf (1, "thread 1: in dtor: started.\n");
++ xpthread_mutex_lock (&user_lock);
++ dprintf (1, "thread 1: in dtor: locked user_lock.\n");
++ xpthread_mutex_unlock (&user_lock);
++ dprintf (1, "thread 1: in dtor: unlocked user_lock.\n");
++ dprintf (1, "thread 1: in dtor: done.\n");
++}
++
++static void *
++thread3 (void *a)
++{
++ dprintf (1, "thread 3: started.\n");
++ dprintf (1, "thread 3: done.\n");
++ return 0;
++}
++
++static void *
++thread2 (void *a)
++{
++ pthread_t t3;
++ dprintf (1, "thread 2: started.\n");
++
++ xpthread_mutex_lock (&user_lock);
++ dprintf (1, "thread 2: locked user_lock.\n");
++ xpthread_barrier_wait (&bar_ctor);
++ t3 = xpthread_create (0, thread3, 0);
++ xpthread_mutex_unlock (&user_lock);
++ dprintf (1, "thread 2: unlocked user_lock.\n");
++ xpthread_join (t3);
++
++ xpthread_mutex_lock (&user_lock);
++ dprintf (1, "thread 2: locked user_lock.\n");
++ xpthread_barrier_wait (&bar_dtor);
++ t3 = xpthread_create (0, thread3, 0);
++ xpthread_mutex_unlock (&user_lock);
++ dprintf (1, "thread 2: unlocked user_lock.\n");
++ xpthread_join (t3);
++
++ dprintf (1, "thread 2: done.\n");
++ return 0;
++}
++
++static void
++thread1 (void)
++{
++ dprintf (1, "thread 1: started.\n");
++ xpthread_barrier_init (&bar_ctor, NULL, 2);
++ xpthread_barrier_init (&bar_dtor, NULL, 2);
++ pthread_t t2 = xpthread_create (0, thread2, 0);
++ void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL);
++ dprintf (1, "thread 1: dlopen done.\n");
++ xdlclose (p);
++ dprintf (1, "thread 1: dlclose done.\n");
++ xpthread_join (t2);
++ dprintf (1, "thread 1: done.\n");
++}
++
++static int
++do_test (void)
++{
++ thread1 ();
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/pthread/tst-create1mod.c b/sysdeps/pthread/tst-create1mod.c
+new file mode 100644
+index 0000000..62c9006
+--- /dev/null
++++ b/sysdeps/pthread/tst-create1mod.c
+@@ -0,0 +1,41 @@
++/* Verify that pthread_create does not deadlock when ctors take locks.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++
++/* Require TLS setup for the module. */
++__thread int tlsvar;
++
++void ctor (void);
++void dtor (void);
++
++static void __attribute__ ((constructor))
++do_init (void)
++{
++ dprintf (1, "constructor started: %d.\n", tlsvar++);
++ ctor ();
++ dprintf (1, "constructor done: %d.\n", tlsvar++);
++}
++
++static void __attribute__ ((destructor))
++do_end (void)
++{
++ dprintf (1, "destructor started: %d.\n", tlsvar++);
++ dtor ();
++ dprintf (1, "destructor done: %d.\n", tlsvar++);
++}
+--
+1.8.3.1
+
diff --git a/elf-Call-__libc_early_init-for-reused-namespaces-bug.patch b/elf-Call-__libc_early_init-for-reused-namespaces-bug.patch
new file mode 100644
index 0000000..4985f74
--- /dev/null
+++ b/elf-Call-__libc_early_init-for-reused-namespaces-bug.patch
@@ -0,0 +1,221 @@
+From d0e357ff45a75553dee3b17ed7d303bfa544f6fe Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 26 Aug 2022 21:15:43 +0200
+Subject: [PATCH] elf: Call __libc_early_init for reused namespaces (bug 29528)
+
+Conflict:adapt context
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=d0e357ff45a75553dee3b17ed7d303bfa544f6fe
+
+libc_map is never reset to NULL, neither during dlclose nor on a
+dlopen call which reuses the namespace structure. As a result, if a
+namespace is reused, its libc is not initialized properly. The most
+visible result is a crash in the <ctype.h> functions.
+
+To prevent similar bugs on namespace reuse from surfacing,
+unconditionally initialize the chosen namespace to zero using memset.
+---
+ elf/Makefile | 7 +++++
+ elf/dl-open.c | 13 ++++++----
+ elf/tst-dlmopen-twice-mod1.c | 37 ++++++++++++++++++++++++++
+ elf/tst-dlmopen-twice-mod2.c | 50 ++++++++++++++++++++++++++++++++++++
+ elf/tst-dlmopen-twice.c | 34 ++++++++++++++++++++++++
+ 5 files changed, 136 insertions(+), 5 deletions(-)
+ create mode 100644 elf/tst-dlmopen-twice-mod1.c
+ create mode 100644 elf/tst-dlmopen-twice-mod2.c
+ create mode 100644 elf/tst-dlmopen-twice.c
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 3928a08787..008770bfaf 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -410,6 +410,7 @@ tests += \
+ tst-dlmopen3 \
+ tst-dlmopen-dlerror \
+ tst-dlmopen-gethostbyname \
++ tst-dlmopen-twice \
+ tst-dlopenfail \
+ tst-dlopenfail-2 \
+ tst-dlopenrpath \
+@@ -839,6 +840,8 @@ modules-names += \
+ tst-dlmopen1mod \
+ tst-dlmopen-dlerror-mod \
+ tst-dlmopen-gethostbyname-mod \
++ tst-dlmopen-twice-mod1 \
++ tst-dlmopen-twice-mod2 \
+ tst-dlopenfaillinkmod \
+ tst-dlopenfailmod1 \
+ tst-dlopenfailmod2 \
+@@ -2976,3 +2979,7 @@ $(objpfx)tst-audit-tlsdesc.out: $(objpfx)tst-auditmod-tlsdesc.so
+ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
+ -Wl,--script=tst-ro-dynamic-mod.map \
+ $(objpfx)tst-ro-dynamic-mod.os
++
++$(objpfx)tst-dlmopen-twice.out: \
++ $(objpfx)tst-dlmopen-twice-mod1.so \
++ $(objpfx)tst-dlmopen-twice-mod2.so
+diff --git a/elf/dl-open.c b/elf/dl-open.c
+index a23e65926b..46e8066fd8 100644
+--- a/elf/dl-open.c
++++ b/elf/dl-open.c
+@@ -844,11 +844,14 @@ _dl_open (const char *file, int mode, const void *caller_dlopen, Lmid_t nsid,
+ _dl_signal_error (EINVAL, file, NULL, N_("\
+ no more namespaces available for dlmopen()"));
+ }
+- else if (nsid == GL(dl_nns))
+- {
+- __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
+- ++GL(dl_nns);
+- }
++
++ if (nsid == GL(dl_nns))
++ ++GL(dl_nns);
++
++ /* Initialize the new namespace. Most members are
++ zero-initialized, only the lock needs special treatment. */
++ memset (&GL(dl_ns)[nsid], 0, sizeof (GL(dl_ns)[nsid]));
++ __rtld_lock_initialize (GL(dl_ns)[nsid]._ns_unique_sym_table.lock);
+
+ _dl_debug_initialize (0, nsid)->r_state = RT_CONSISTENT;
+ }
+diff --git a/elf/tst-dlmopen-twice-mod1.c b/elf/tst-dlmopen-twice-mod1.c
+new file mode 100644
+index 0000000000..0eaf04948c
+--- /dev/null
++++ b/elf/tst-dlmopen-twice-mod1.c
+@@ -0,0 +1,37 @@
++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 1.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++
++static void __attribute__ ((constructor))
++init (void)
++{
++ puts ("info: tst-dlmopen-twice-mod1.so loaded");
++ fflush (stdout);
++}
++
++static void __attribute__ ((destructor))
++fini (void)
++{
++ puts ("info: tst-dlmopen-twice-mod1.so about to be unloaded");
++ fflush (stdout);
++}
++
++/* Large allocation. The second module does not have this, so it
++ should load libc at a different address. */
++char large_allocate[16 * 1024 * 1024];
+diff --git a/elf/tst-dlmopen-twice-mod2.c b/elf/tst-dlmopen-twice-mod2.c
+new file mode 100644
+index 0000000000..40c6c01f96
+--- /dev/null
++++ b/elf/tst-dlmopen-twice-mod2.c
+@@ -0,0 +1,50 @@
++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Module 2.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <ctype.h>
++#include <stdio.h>
++
++static void __attribute__ ((constructor))
++init (void)
++{
++ puts ("info: tst-dlmopen-twice-mod2.so loaded");
++ fflush (stdout);
++}
++
++static void __attribute__ ((destructor))
++fini (void)
++{
++ puts ("info: tst-dlmopen-twice-mod2.so about to be unloaded");
++ fflush (stdout);
++}
++
++int
++run_check (void)
++{
++ puts ("info: about to call isalpha");
++ fflush (stdout);
++
++ volatile char ch = 'a';
++ if (!isalpha (ch))
++ {
++ puts ("error: isalpha ('a') is not true");
++ fflush (stdout);
++ return 1;
++ }
++ return 0;
++}
+diff --git a/elf/tst-dlmopen-twice.c b/elf/tst-dlmopen-twice.c
+new file mode 100644
+index 0000000000..449f3c8fa9
+--- /dev/null
++++ b/elf/tst-dlmopen-twice.c
+@@ -0,0 +1,34 @@
++/* Initialization of libc after dlmopen/dlclose/dlmopen (bug 29528). Main.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <support/xdlfcn.h>
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++ void *handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod1.so", RTLD_NOW);
++ xdlclose (handle);
++ handle = xdlmopen (LM_ID_NEWLM, "tst-dlmopen-twice-mod2.so", RTLD_NOW);
++ int (*run_check) (void) = xdlsym (handle, "run_check");
++ TEST_COMPARE (run_check (), 0);
++ xdlclose (handle);
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.27.0
+
diff --git a/elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch b/elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch
new file mode 100644
index 0000000..1cd2fc2
--- /dev/null
+++ b/elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch
@@ -0,0 +1,543 @@
+From 33c50ef42878b07ee6ead8b3f1a81d8c2c74697c Mon Sep 17 00:00:00 2001
+From: Fangrui Song <maskray@google.com>
+Date: Mon, 16 Aug 2021 09:59:30 -0700
+Subject: [PATCH] elf: Drop elf/tls-macros.h in favor of __thread and tls_model
+ attributes [BZ #28152] [BZ #28205]
+
+elf/tls-macros.h was added for TLS testing when GCC did not support
+__thread. __thread and tls_model attributes are mature now and have been
+used by many newer tests.
+
+Also delete tst-tls2.c which tests .tls_common (unused by modern GCC and
+unsupported by Clang/LLD). .tls_common and .tbss definition are almost
+identical after linking, so the runtime test doesn't add additional
+coverage. Assembler and linker tests should be on the binutils side.
+
+When LLD 13.0.0 is allowed in configure.ac
+(https://sourceware.org/pipermail/libc-alpha/2021-August/129866.html),
+`make check` result is on par with glibc built with GNU ld on aarch64
+and x86_64.
+
+As a future clean-up, TLS_GD/TLS_LD/TLS_IE/TLS_IE macros can be removed from
+sysdeps/*/tls-macros.h. We can add optional -mtls-dialect={gnu2,trad}
+tests to ensure coverage.
+
+Tested on aarch64-linux-gnu, powerpc64le-linux-gnu, and x86_64-linux-gnu.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ elf/Makefile | 4 +-
+ elf/tls-macros.h | 25 -----------
+ elf/tst-tls1.c | 64 +++++++++++-----------------
+ elf/tst-tls2.c | 82 ------------------------------------
+ elf/tst-tls3.c | 26 +++++-------
+ elf/tst-tlsmod1.c | 24 +++++------
+ elf/tst-tlsmod2.c | 6 +--
+ elf/tst-tlsmod3.c | 8 ++--
+ elf/tst-tlsmod4.c | 6 +--
+ elf/tst-tlsmod5.c | 4 +-
+ elf/tst-tlsmod6.c | 4 +-
+ sysdeps/powerpc/mod-tlsopt-powerpc.c | 6 +--
+ sysdeps/powerpc/tst-tlsifunc.c | 4 +-
+ 13 files changed, 64 insertions(+), 199 deletions(-)
+ delete mode 100644 elf/tls-macros.h
+ delete mode 100644 elf/tst-tls2.c
+
+diff --git a/elf/Makefile b/elf/Makefile
+index d05f410..725537c 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -163,7 +163,7 @@ tests-static-normal := tst-array1-static tst-array5-static \
+ tst-single_threaded-static tst-single_threaded-pthread-static \
+ tst-dst-static tst-getauxval-static
+
+-tests-static-internal := tst-tls1-static tst-tls2-static \
++tests-static-internal := tst-tls1-static \
+ tst-ptrguard1-static tst-stackguard1-static \
+ tst-tls1-static-non-pie
+
+@@ -183,7 +183,7 @@ endif
+ tests := tst-tls9 tst-leaks1 \
+ tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
+ tst-auxv tst-stringtable
+-tests-internal := tst-tls1 tst-tls2 $(tests-static-internal)
++tests-internal := tst-tls1 $(tests-static-internal)
+ tests-static := $(tests-static-normal) $(tests-static-internal)
+
+ ifeq (yes,$(build-shared))
+diff --git a/elf/tls-macros.h b/elf/tls-macros.h
+deleted file mode 100644
+index e25e33b..0000000
+--- a/elf/tls-macros.h
++++ /dev/null
+@@ -1,25 +0,0 @@
+-/* Macros to support TLS testing in times of missing compiler support. */
+-
+-#define COMMON_INT_DEF(x) \
+- asm (".tls_common " #x ",4,4")
+-/* XXX Until we get compiler support we don't need declarations. */
+-#define COMMON_INT_DECL(x)
+-
+-/* XXX This definition will probably be machine specific, too. */
+-#define VAR_INT_DEF(x) \
+- asm (".section .tdata\n\t" \
+- ".globl " #x "\n" \
+- ".balign 4\n" \
+- #x ":\t.long 0\n\t" \
+- ".size " #x ",4\n\t" \
+- ".previous")
+-/* XXX Until we get compiler support we don't need declarations. */
+-#define VAR_INT_DECL(x)
+-
+-#include_next <tls-macros.h>
+-
+- /* XXX Each architecture must have its own asm for now. */
+-#if !defined TLS_LE || !defined TLS_IE \
+- || !defined TLS_LD || !defined TLS_GD
+-# error "No support for this architecture so far."
+-#endif
+diff --git a/elf/tst-tls1.c b/elf/tst-tls1.c
+index c31da56..b341221 100644
+--- a/elf/tst-tls1.c
++++ b/elf/tst-tls1.c
+@@ -1,13 +1,14 @@
+ /* glibc test for TLS in ld.so. */
+ #include <stdio.h>
+
+-#include "tls-macros.h"
+-
+-
+-/* Two common 'int' variables in TLS. */
+-COMMON_INT_DEF(foo);
+-COMMON_INT_DEF(bar);
+
++__thread int foo, bar __attribute__ ((tls_model("local-exec")));
++extern __thread int foo_gd asm ("foo") __attribute__ ((tls_model("global-dynamic")));
++extern __thread int foo_ld asm ("foo") __attribute__ ((tls_model("local-dynamic")));
++extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec")));
++extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic")));
++extern __thread int bar_ld asm ("bar") __attribute__ ((tls_model("local-dynamic")));
++extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec")));
+
+ static int
+ do_test (void)
+@@ -18,63 +19,48 @@ do_test (void)
+
+ /* Set the variable using the local exec model. */
+ puts ("set bar to 1 (LE)");
+- ap = TLS_LE (bar);
+- *ap = 1;
++ bar = 1;
+
+
+ /* Get variables using initial exec model. */
+ fputs ("get sum of foo and bar (IE)", stdout);
+- ap = TLS_IE (foo);
+- bp = TLS_IE (bar);
++ ap = &foo_ie;
++ bp = &bar_ie;
+ printf (" = %d\n", *ap + *bp);
+ result |= *ap + *bp != 1;
+- if (*ap != 0)
+- {
+- printf ("foo = %d\n", *ap);
+- result = 1;
+- }
+- if (*bp != 1)
++ if (*ap != 0 || *bp != 1)
+ {
+- printf ("bar = %d\n", *bp);
++ printf ("foo = %d\nbar = %d\n", *ap, *bp);
+ result = 1;
+ }
+
+
+- /* Get variables using local dynamic model. */
+- fputs ("get sum of foo and bar (LD)", stdout);
+- ap = TLS_LD (foo);
+- bp = TLS_LD (bar);
++ /* Get variables using local dynamic model or TLSDESC. */
++ fputs ("get sum of foo and bar (LD or TLSDESC)", stdout);
++ ap = &foo_ld;
++ bp = &bar_ld;
+ printf (" = %d\n", *ap + *bp);
+ result |= *ap + *bp != 1;
+- if (*ap != 0)
+- {
+- printf ("foo = %d\n", *ap);
+- result = 1;
+- }
+- if (*bp != 1)
++ if (*ap != 0 || *bp != 1)
+ {
+- printf ("bar = %d\n", *bp);
++ printf ("foo = %d\nbar = %d\n", *ap, *bp);
+ result = 1;
+ }
+
+
+- /* Get variables using generic dynamic model. */
+- fputs ("get sum of foo and bar (GD)", stdout);
+- ap = TLS_GD (foo);
+- bp = TLS_GD (bar);
++ /* Get variables using general dynamic model or TLSDESC. */
++ fputs ("get sum of foo and bar (GD or TLSDESC)", stdout);
++ ap = &foo_gd;
++ bp = &bar_gd;
+ printf (" = %d\n", *ap + *bp);
+ result |= *ap + *bp != 1;
+- if (*ap != 0)
+- {
+- printf ("foo = %d\n", *ap);
+- result = 1;
+- }
+- if (*bp != 1)
++ if (*ap != 0 || *bp != 1)
+ {
+- printf ("bar = %d\n", *bp);
++ printf ("foo = %d\nbar = %d\n", *ap, *bp);
+ result = 1;
+ }
+
++
+ return result;
+ }
+
+diff --git a/elf/tst-tls2.c b/elf/tst-tls2.c
+deleted file mode 100644
+index 963b8d6..0000000
+--- a/elf/tst-tls2.c
++++ /dev/null
+@@ -1,82 +0,0 @@
+-/* glibc test for TLS in ld.so. */
+-#include <stdio.h>
+-
+-#include "tls-macros.h"
+-
+-
+-/* Two 'int' variables in TLS. */
+-VAR_INT_DEF(foo);
+-VAR_INT_DEF(bar);
+-
+-
+-static int
+-do_test (void)
+-{
+- int result = 0;
+- int *ap, *bp;
+-
+-
+- /* Set the variable using the local exec model. */
+- puts ("set bar to 1 (LE)");
+- ap = TLS_LE (bar);
+- *ap = 1;
+-
+-
+- /* Get variables using initial exec model. */
+- fputs ("get sum of foo and bar (IE)", stdout);
+- ap = TLS_IE (foo);
+- bp = TLS_IE (bar);
+- printf (" = %d\n", *ap + *bp);
+- result |= *ap + *bp != 1;
+- if (*ap != 0)
+- {
+- printf ("foo = %d\n", *ap);
+- result = 1;
+- }
+- if (*bp != 1)
+- {
+- printf ("bar = %d\n", *bp);
+- result = 1;
+- }
+-
+-
+- /* Get variables using local dynamic model. */
+- fputs ("get sum of foo and bar (LD)", stdout);
+- ap = TLS_LD (foo);
+- bp = TLS_LD (bar);
+- printf (" = %d\n", *ap + *bp);
+- result |= *ap + *bp != 1;
+- if (*ap != 0)
+- {
+- printf ("foo = %d\n", *ap);
+- result = 1;
+- }
+- if (*bp != 1)
+- {
+- printf ("bar = %d\n", *bp);
+- result = 1;
+- }
+-
+-
+- /* Get variables using generic dynamic model. */
+- fputs ("get sum of foo and bar (GD)", stdout);
+- ap = TLS_GD (foo);
+- bp = TLS_GD (bar);
+- printf (" = %d\n", *ap + *bp);
+- result |= *ap + *bp != 1;
+- if (*ap != 0)
+- {
+- printf ("foo = %d\n", *ap);
+- result = 1;
+- }
+- if (*bp != 1)
+- {
+- printf ("bar = %d\n", *bp);
+- result = 1;
+- }
+-
+- return result;
+-}
+-
+-
+-#include <support/test-driver.c>
+diff --git a/elf/tst-tls3.c b/elf/tst-tls3.c
+index 7e0abb4..222b179 100644
+--- a/elf/tst-tls3.c
++++ b/elf/tst-tls3.c
+@@ -1,13 +1,12 @@
+ /* glibc test for TLS in ld.so. */
+ #include <stdio.h>
+
+-#include "tls-macros.h"
+
+-
+-/* One define int variable, two externs. */
+-COMMON_INT_DECL(foo);
+-VAR_INT_DECL(bar);
+-VAR_INT_DEF(baz);
++__thread int foo, bar __attribute__ ((tls_model("initial-exec")));
++__thread int baz __attribute__ ((tls_model("local-exec")));
++extern __thread int foo_gd __attribute__ ((alias("foo"), tls_model("global-dynamic")));
++extern __thread int bar_gd __attribute__ ((alias("bar"), tls_model("global-dynamic")));
++extern __thread int baz_ld __attribute__ ((alias("baz"), tls_model("local-dynamic")));
+
+
+ extern int in_dso (void);
+@@ -22,23 +21,20 @@ do_test (void)
+
+ /* Set the variable using the local exec model. */
+ puts ("set baz to 3 (LE)");
+- ap = TLS_LE (baz);
+- *ap = 3;
++ baz = 3;
+
+
+ /* Get variables using initial exec model. */
+ puts ("set variables foo and bar (IE)");
+- ap = TLS_IE (foo);
+- *ap = 1;
+- bp = TLS_IE (bar);
+- *bp = 2;
++ foo = 1;
++ bar = 2;
+
+
+ /* Get variables using local dynamic model. */
+ fputs ("get sum of foo, bar (GD) and baz (LD)", stdout);
+- ap = TLS_GD (foo);
+- bp = TLS_GD (bar);
+- cp = TLS_LD (baz);
++ ap = &foo_gd;
++ bp = &bar_gd;
++ cp = &baz_ld;
+ printf (" = %d\n", *ap + *bp + *cp);
+ result |= *ap + *bp + *cp != 6;
+ if (*ap != 1)
+diff --git a/elf/tst-tlsmod1.c b/elf/tst-tlsmod1.c
+index 8d91567..a448c4d 100644
+--- a/elf/tst-tlsmod1.c
++++ b/elf/tst-tlsmod1.c
+@@ -1,12 +1,12 @@
+ #include <stdio.h>
+
+-#include "tls-macros.h"
+
++__thread int foo, bar __attribute__ ((tls_model("global-dynamic")));
++extern __thread int baz __attribute__ ((tls_model("global-dynamic")));
++extern __thread int foo_ie asm ("foo") __attribute__ ((tls_model("initial-exec")));
++extern __thread int bar_ie asm ("bar") __attribute__ ((tls_model("initial-exec")));
++extern __thread int baz_ie asm ("baz") __attribute__ ((tls_model("initial-exec")));
+
+-/* One define int variable, two externs. */
+-COMMON_INT_DEF(foo);
+-VAR_INT_DEF(bar);
+-VAR_INT_DECL(baz);
+
+ extern int in_dso (void);
+
+@@ -19,8 +19,8 @@ in_dso (void)
+ /* Get variables using initial exec model. */
+ fputs ("get sum of foo and bar (IE)", stdout);
+ asm ("" ::: "memory");
+- ap = TLS_IE (foo);
+- bp = TLS_IE (bar);
++ ap = &foo_ie;
++ bp = &bar_ie;
+ printf (" = %d\n", *ap + *bp);
+ result |= *ap + *bp != 3;
+ if (*ap != 1)
+@@ -35,11 +35,11 @@ in_dso (void)
+ }
+
+
+- /* Get variables using generic dynamic model. */
+- fputs ("get sum of foo and bar and baz (GD)", stdout);
+- ap = TLS_GD (foo);
+- bp = TLS_GD (bar);
+- cp = TLS_GD (baz);
++ /* Get variables using generic dynamic model or TLSDESC. */
++ fputs ("get sum of foo and bar and baz (GD or TLSDESC)", stdout);
++ ap = &foo;
++ bp = &bar;
++ cp = &baz;
+ printf (" = %d\n", *ap + *bp + *cp);
+ result |= *ap + *bp + *cp != 6;
+ if (*ap != 1)
+diff --git a/elf/tst-tlsmod2.c b/elf/tst-tlsmod2.c
+index 40eb140..3223fe4 100644
+--- a/elf/tst-tlsmod2.c
++++ b/elf/tst-tlsmod2.c
+@@ -1,9 +1,7 @@
+ #include <stdio.h>
+
+-#include "tls-macros.h"
+
+-
+-COMMON_INT_DEF(foo);
++__thread int foo;
+
+
+ int
+@@ -15,7 +13,7 @@ in_dso (int n, int *caller_foop)
+ puts ("foo"); /* Make sure PLT is used before macros. */
+ asm ("" ::: "memory");
+
+- foop = TLS_GD (foo);
++ foop = &foo;
+
+ if (caller_foop != NULL && foop != caller_foop)
+ {
+diff --git a/elf/tst-tlsmod3.c b/elf/tst-tlsmod3.c
+index 6d186c4..d6e7498 100644
+--- a/elf/tst-tlsmod3.c
++++ b/elf/tst-tlsmod3.c
+@@ -1,10 +1,10 @@
+ #include <stdio.h>
+
+-#include "tls-macros.h"
+
+ extern int in_dso (int n, int *caller_foop);
+
+-COMMON_INT_DEF(comm_n);
++extern __thread int foo;
++__thread int comm_n;
+
+
+
+@@ -20,8 +20,8 @@ in_dso2 (void)
+ puts ("foo"); /* Make sure PLT is used before macros. */
+ asm ("" ::: "memory");
+
+- foop = TLS_GD (foo);
+- np = TLS_GD (comm_n);
++ foop = &foo;
++ np = &comm_n;
+
+ if (n != *np)
+ {
+diff --git a/elf/tst-tlsmod4.c b/elf/tst-tlsmod4.c
+index 86889aa..f38919a 100644
+--- a/elf/tst-tlsmod4.c
++++ b/elf/tst-tlsmod4.c
+@@ -1,9 +1,7 @@
+ #include <stdio.h>
+
+-#include "tls-macros.h"
+
+-
+-COMMON_INT_DEF(baz);
++__thread int baz;
+
+
+ int
+@@ -15,7 +13,7 @@ in_dso (int n, int *caller_bazp)
+ puts ("foo"); /* Make sure PLT is used before macros. */
+ asm ("" ::: "memory");
+
+- bazp = TLS_GD (baz);
++ bazp = &baz;
+
+ if (caller_bazp != NULL && bazp != caller_bazp)
+ {
+diff --git a/elf/tst-tlsmod5.c b/elf/tst-tlsmod5.c
+index a97c7e5..3f39c5b 100644
+--- a/elf/tst-tlsmod5.c
++++ b/elf/tst-tlsmod5.c
+@@ -1,3 +1 @@
+-#include "tls-macros.h"
+-
+-COMMON_INT_DEF(foo);
++__thread int foo;
+diff --git a/elf/tst-tlsmod6.c b/elf/tst-tlsmod6.c
+index e968596..7b3571f 100644
+--- a/elf/tst-tlsmod6.c
++++ b/elf/tst-tlsmod6.c
+@@ -1,3 +1 @@
+-#include "tls-macros.h"
+-
+-COMMON_INT_DEF(bar);
++__thread int bar;
+diff --git a/sysdeps/powerpc/mod-tlsopt-powerpc.c b/sysdeps/powerpc/mod-tlsopt-powerpc.c
+index ee0db12..2a82e53 100644
+--- a/sysdeps/powerpc/mod-tlsopt-powerpc.c
++++ b/sysdeps/powerpc/mod-tlsopt-powerpc.c
+@@ -1,11 +1,9 @@
+ /* shared library to test for __tls_get_addr optimization. */
+ #include <stdio.h>
+
+-#include "../../elf/tls-macros.h"
+ #include "dl-tls.h"
+
+-/* common 'int' variable in TLS. */
+-COMMON_INT_DEF(foo);
++__thread int foo __attribute__ ((tls_model("global-dynamic")));
+
+
+ int
+@@ -14,7 +12,7 @@ tls_get_addr_opt_test (void)
+ int result = 0;
+
+ /* Get variable using general dynamic model. */
+- int *ap = TLS_GD (foo);
++ int *ap = &foo;
+ if (*ap != 0)
+ {
+ printf ("foo = %d\n", *ap);
+diff --git a/sysdeps/powerpc/tst-tlsifunc.c b/sysdeps/powerpc/tst-tlsifunc.c
+index 3095d41..c8c0bad 100644
+--- a/sysdeps/powerpc/tst-tlsifunc.c
++++ b/sysdeps/powerpc/tst-tlsifunc.c
+@@ -21,9 +21,9 @@
+ #include <stdint.h>
+ #include <inttypes.h>
+ #include <libc-symbols.h>
+-#include <tls-macros.h>
+
+ __thread int bar;
++extern __thread int bar_gd asm ("bar") __attribute__ ((tls_model("global-dynamic")));
+ static int *bar_ptr = NULL;
+
+ static uint32_t resolver_platform = 0;
+@@ -57,7 +57,7 @@ get_platform (void)
+ void
+ init_foo (void)
+ {
+- bar_ptr = TLS_GD (bar);
++ bar_ptr = &bar_gd;
+ }
+
+ int
+--
+1.8.3.1
+
diff --git a/elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch b/elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch
new file mode 100644
index 0000000..3d5bd60
--- /dev/null
+++ b/elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch
@@ -0,0 +1,73 @@
+From ea32ec354c65ddad11b82ca9d057010df13a9cea Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 5 Nov 2021 17:01:24 +0100
+Subject: [PATCH] elf: Earlier missing dynamic segment check in
+ _dl_map_object_from_fd
+
+Separated debuginfo files have PT_DYNAMIC with p_filesz == 0. We
+need to check for that before the _dl_map_segments call because
+that could attempt to write to mappings that extend beyond the end
+of the file, resulting in SIGBUS.
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+---
+ elf/dl-load.c | 22 ++++++++++++----------
+ 1 file changed, 12 insertions(+), 10 deletions(-)
+
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index a1f1682..9f4fa96 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1135,6 +1135,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ struct loadcmd loadcmds[l->l_phnum];
+ size_t nloadcmds = 0;
+ bool has_holes = false;
++ bool empty_dynamic = false;
+
+ /* The struct is initialized to zero so this is not necessary:
+ l->l_ld = 0;
+@@ -1147,7 +1148,9 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ segments are mapped in. We record the addresses it says
+ verbatim, and later correct for the run-time load address. */
+ case PT_DYNAMIC:
+- if (ph->p_filesz)
++ if (ph->p_filesz == 0)
++ empty_dynamic = true; /* Usually separate debuginfo. */
++ else
+ {
+ /* Debuginfo only files from "objcopy --only-keep-debug"
+ contain a PT_DYNAMIC segment with p_filesz == 0. Skip
+@@ -1270,6 +1273,13 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ goto lose;
+ }
+
++ /* This check recognizes most separate debuginfo files. */
++ if (__glibc_unlikely ((l->l_ld == 0 && type == ET_DYN) || empty_dynamic))
++ {
++ errstring = N_("object file has no dynamic section");
++ goto lose;
++ }
++
+ /* Length of the sections to be loaded. */
+ maplength = loadcmds[nloadcmds - 1].allocend - loadcmds[0].mapstart;
+
+@@ -1287,15 +1297,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ }
+ }
+
+- if (l->l_ld == 0)
+- {
+- if (__glibc_unlikely (type == ET_DYN))
+- {
+- errstring = N_("object file has no dynamic section");
+- goto lose;
+- }
+- }
+- else
++ if (l->l_ld != 0)
+ l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr);
+
+ elf_get_dynamic_info (l);
+--
+1.8.3.1
+
diff --git a/elf-Fix-DNDEBUG-warning-in-_dl_start_args_adjust.patch b/elf-Fix-DNDEBUG-warning-in-_dl_start_args_adjust.patch
new file mode 100644
index 0000000..4b36ff5
--- /dev/null
+++ b/elf-Fix-DNDEBUG-warning-in-_dl_start_args_adjust.patch
@@ -0,0 +1,30 @@
+From c1ada668a381e122ee37cb8be7f0637111f63ea7 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 28 Jun 2022 10:40:16 +0200
+Subject: [PATCH] elf: Fix -DNDEBUG warning in _dl_start_args_adjust
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=c1ada668a381e122ee37cb8be7f0637111f63ea7
+
+This is another blocker for building glibc with the default
+-Werror setting and -DNDEBUG.
+---
+ elf/rtld.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index f5a3d1968f..cbbaf4a331 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -1307,7 +1307,7 @@ _dl_start_args_adjust (int skip_args)
+ return;
+
+ /* Sanity check. */
+- intptr_t argc = (intptr_t) sp[0] - skip_args;
++ intptr_t argc __attribute__ ((unused)) = (intptr_t) sp[0] - skip_args;
+ assert (argc == _dl_argc);
+
+ /* Adjust argc on stack. */
+--
+2.27.0
+
diff --git a/elf-Fix-compile-error-with-Werror-and-DNDEBUG.patch b/elf-Fix-compile-error-with-Werror-and-DNDEBUG.patch
new file mode 100644
index 0000000..dcfa41f
--- /dev/null
+++ b/elf-Fix-compile-error-with-Werror-and-DNDEBUG.patch
@@ -0,0 +1,36 @@
+From 5e89ed42fd8997414732525c9460878d65363b3f Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Fri, 15 Apr 2022 17:25:05 +0800
+Subject: [PATCH] elf: Fix compile error with -Werror and -DNDEBUG
+
+Using -Werror and -DNDEBUG at the same time will trigger the
+following compiler error:
+
+cache.c: In function 'save_cache':
+cache.c:758:15: error: unused variable 'old_offset' [-Werror=unused-variable]
+ 758 | off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
+ | ^~~~~~~~~~
+
+-DNDEBUG disables the assertion, making old_offset unused.
+Use __attribute__ ((unused)) to disable this warning.
+---
+ elf/cache.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/elf/cache.c b/elf/cache.c
+index abe2e49..3d7d3a6 100644
+--- a/elf/cache.c
++++ b/elf/cache.c
+@@ -727,7 +727,8 @@ save_cache (const char *cache_name)
+ if (opt_format != opt_format_old)
+ {
+ /* Align file position to 4. */
+- off64_t old_offset = lseek64 (fd, extension_offset, SEEK_SET);
++ __attribute__ ((unused)) off64_t old_offset
++ = lseek64 (fd, extension_offset, SEEK_SET);
+ assert ((unsigned long long int) (extension_offset - old_offset) < 4);
+ write_extensions (fd, str_offset, extension_offset);
+ }
+--
+1.8.3.1
+
diff --git a/elf-Fix-hwcaps-string-size-overestimation.patch b/elf-Fix-hwcaps-string-size-overestimation.patch
new file mode 100644
index 0000000..f0b2857
--- /dev/null
+++ b/elf-Fix-hwcaps-string-size-overestimation.patch
@@ -0,0 +1,62 @@
+From a23820f6052a740246fdc7dcd9c43ce8eed0c45a Mon Sep 17 00:00:00 2001
+From: Javier Pello <devel@otheo.eu>
+Date: Mon, 5 Sep 2022 20:09:01 +0200
+Subject: [PATCH] elf: Fix hwcaps string size overestimation
+
+Conflict:NA
+Reference:https://sourceware.org/git/?p=glibc.git;a=commit;h=a23820f6052a740246fdc7dcd9c43ce8eed0c45a
+
+Commit dad90d528259b669342757c37dedefa8577e2636 added glibc-hwcaps
+support for LD_LIBRARY_PATH and, for this, it adjusted the total
+string size required in _dl_important_hwcaps. However, in doing so
+it inadvertently altered the calculation of the size required for
+the power set strings, as the computation of the power set string
+size depended on the first value assigned to the total variable,
+which is later shifted, resulting in overallocation of string
+space. Fix this now by using a different variable to hold the
+string size required for glibc-hwcaps.
+
+Signed-off-by: Javier Pello <devel@otheo.eu>
+---
+ elf/dl-hwcaps.c | 8 +++++---
+ 1 file changed, 5 insertions(+), 3 deletions(-)
+
+diff --git a/elf/dl-hwcaps.c b/elf/dl-hwcaps.c
+index 6f161f6ad5..92eb53790e 100644
+--- a/elf/dl-hwcaps.c
++++ b/elf/dl-hwcaps.c
+@@ -193,7 +193,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
+ /* Each hwcaps subdirectory has a GLIBC_HWCAPS_PREFIX string prefix
+ and a "/" suffix once stored in the result. */
+ hwcaps_counts.maximum_length += strlen (GLIBC_HWCAPS_PREFIX) + 1;
+- size_t total = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
++ size_t hwcaps_sz = (hwcaps_counts.count * (strlen (GLIBC_HWCAPS_PREFIX) + 1)
+ + hwcaps_counts.total_length);
+
+ /* Count the number of bits set in the masked value. */
+@@ -229,11 +229,12 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
+ assert (m == cnt);
+
+ /* Determine the total size of all strings together. */
++ size_t total;
+ if (cnt == 1)
+- total += temp[0].len + 1;
++ total = temp[0].len + 1;
+ else
+ {
+- total += temp[0].len + temp[cnt - 1].len + 2;
++ total = temp[0].len + temp[cnt - 1].len + 2;
+ if (cnt > 2)
+ {
+ total <<= 1;
+@@ -255,6 +256,7 @@ _dl_important_hwcaps (const char *glibc_hwcaps_prepend,
+ /* This is the overall result, including both glibc-hwcaps
+ subdirectories and the legacy hwcaps subdirectories using the
+ power set construction. */
++ total += hwcaps_sz;
+ struct r_strlenpair *overall_result
+ = malloc (*sz * sizeof (*result) + total);
+ if (overall_result == NULL)
+--
+2.27.0
+
diff --git a/elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch b/elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch
new file mode 100644
index 0000000..bd00864
--- /dev/null
+++ b/elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch
@@ -0,0 +1,313 @@
+From 254d3d5aef2fd8430c469e1938209ac100ebf132 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 24 Jan 2022 10:46:16 -0300
+Subject: [PATCH] elf: Fix initial-exec TLS access on audit modules (BZ #28096)
+
+For audit modules and dependencies with initial-exec TLS, we can not
+set the initial TLS image on default loader initialization because it
+would already be set by the audit setup. However, subsequent thread
+creation would need to follow the default behaviour.
+
+This patch fixes it by setting l_auditing link_map field not only
+for the audit modules, but also for all its dependencies. This is
+used on _dl_allocate_tls_init to avoid the static TLS initialization
+at load time.
+
+Checked on x86_64-linux-gnu, i686-linux-gnu, and aarch64-linux-gnu.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ elf/Makefile | 8 ++++
+ elf/dl-tls.c | 17 ++++++--
+ elf/rtld.c | 2 +-
+ elf/tst-audit21.c | 42 ++++++++++++++++++++
+ elf/tst-auditmod21a.c | 80 ++++++++++++++++++++++++++++++++++++++
+ elf/tst-auditmod21b.c | 22 +++++++++++
+ nptl/allocatestack.c | 2 +-
+ sysdeps/generic/ldsodefs.h | 2 +-
+ 8 files changed, 169 insertions(+), 6 deletions(-)
+ create mode 100644 elf/tst-audit21.c
+ create mode 100644 elf/tst-auditmod21a.c
+ create mode 100644 elf/tst-auditmod21b.c
+
+diff --git a/elf/Makefile b/elf/Makefile
+index ddd0e84afc..72ba6a1e66 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -377,6 +377,7 @@ tests += \
+ tst-audit15 \
+ tst-audit16 \
+ tst-audit17 \
++ tst-audit21 \
+ tst-auditmany \
+ tst-auxobj \
+ tst-auxobj-dlopen \
+@@ -697,6 +698,8 @@ modules-names = \
+ tst-auditmod9b \
+ tst-auditmod11 \
+ tst-auditmod12 \
++ tst-auditmod21a \
++ tst-auditmod21b \
+ tst-auxvalmod \
+ tst-big-note-lib \
+ tst-deep1mod1 \
+@@ -2139,6 +2142,11 @@ tst-audit19b-ARGS = -- $(host-test-program-cmd)
+ CFLAGS-.os += $(call elide-stack-protector,.os,tst-auditmod17)
+ tst-audit17-ENV = LD_AUDIT=$(objpfx)tst-auditmod17.so
+
++$(objpfx)tst-audit21: $(shared-thread-library)
++$(objpfx)tst-audit21.out: $(objpfx)tst-auditmod21a.so
++$(objpfx)tst-auditmod21a.so: $(objpfx)tst-auditmod21b.so
++tst-audit21-ENV = LD_AUDIT=$(objpfx)tst-auditmod21a.so
++
+ # tst-sonamemove links against an older implementation of the library.
+ LDFLAGS-tst-sonamemove-linkmod1.so = \
+ -Wl,--version-script=tst-sonamemove-linkmod1.map \
+diff --git a/elf/dl-tls.c b/elf/dl-tls.c
+index 8ba70c9a9d..093cdddb7e 100644
+--- a/elf/dl-tls.c
++++ b/elf/dl-tls.c
+@@ -519,8 +519,12 @@ _dl_resize_dtv (dtv_t *dtv, size_t max_modid)
+ }
+
+
++/* Allocate initial TLS. RESULT should be a non-NULL pointer to storage
++ for the TLS space. The DTV may be resized, and so this function may
++ call malloc to allocate that space. The loader's GL(dl_load_tls_lock)
++ is taken when manipulating global TLS-related data in the loader. */
+ void *
+-_dl_allocate_tls_init (void *result)
++_dl_allocate_tls_init (void *result, bool init_tls)
+ {
+ if (result == NULL)
+ /* The memory allocation failed. */
+@@ -593,7 +597,14 @@ _dl_allocate_tls_init (void *result)
+ some platforms use in static programs requires it. */
+ dtv[map->l_tls_modid].pointer.val = dest;
+
+- /* Copy the initialization image and clear the BSS part. */
++ /* Copy the initialization image and clear the BSS part. For
++ audit modules or dependencies with initial-exec TLS, we can not
++ set the initial TLS image on default loader initialization
++ because it would already be set by the audit setup. However,
++ subsequent thread creation would need to follow the default
++ behaviour. */
++ if (map->l_ns != LM_ID_BASE && !init_tls)
++ continue;
+ memset (__mempcpy (dest, map->l_tls_initimage,
+ map->l_tls_initimage_size), '\0',
+ map->l_tls_blocksize - map->l_tls_initimage_size);
+@@ -620,7 +631,7 @@ _dl_allocate_tls (void *mem)
+ {
+ return _dl_allocate_tls_init (mem == NULL
+ ? _dl_allocate_tls_storage ()
+- : allocate_dtv (mem));
++ : allocate_dtv (mem), true);
+ }
+ rtld_hidden_def (_dl_allocate_tls)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 8d233f77be..10436f7034 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -2462,7 +2462,7 @@ dl_main (const ElfW(Phdr) *phdr,
+ into the main thread's TLS area, which we allocated above.
+ Note: thread-local variables must only be accessed after completing
+ the next step. */
+- _dl_allocate_tls_init (tcbp);
++ _dl_allocate_tls_init (tcbp, false);
+
+ /* And finally install it for the main thread. */
+ if (! tls_init_tp_called)
+diff --git a/elf/tst-audit21.c b/elf/tst-audit21.c
+new file mode 100644
+index 0000000000..3a47ab64d4
+--- /dev/null
++++ b/elf/tst-audit21.c
+@@ -0,0 +1,42 @@
++/* Check LD_AUDIT with static TLS.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <ctype.h>
++#include <support/xthread.h>
++#include <support/check.h>
++
++static volatile __thread int out __attribute__ ((tls_model ("initial-exec")));
++
++static void *
++tf (void *arg)
++{
++ TEST_COMPARE (out, 0);
++ out = isspace (' ');
++ return NULL;
++}
++
++int main (int argc, char *argv[])
++{
++ TEST_COMPARE (out, 0);
++ out = isspace (' ');
++
++ pthread_t t = xpthread_create (NULL, tf, NULL);
++ xpthread_join (t);
++
++ return 0;
++}
+diff --git a/elf/tst-auditmod21a.c b/elf/tst-auditmod21a.c
+new file mode 100644
+index 0000000000..f6d51b5c05
+--- /dev/null
++++ b/elf/tst-auditmod21a.c
+@@ -0,0 +1,80 @@
++/* Check LD_AUDIT with static TLS.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <ctype.h>
++#include <stdlib.h>
++#include <link.h>
++
++#define tls_ie __attribute__ ((tls_model ("initial-exec")))
++
++__thread int tls_var0 tls_ie;
++__thread int tls_var1 tls_ie = 0x10;
++
++/* Defined at tst-auditmod21b.so */
++extern __thread int tls_var2;
++extern __thread int tls_var3;
++
++static volatile int out;
++
++static void
++call_libc (void)
++{
++ /* isspace accesses the initial-exec glibc TLS variables, which are
++ setup in glibc initialization. */
++ out = isspace (' ');
++}
++
++unsigned int
++la_version (unsigned int v)
++{
++ tls_var0 = 0x1;
++ if (tls_var1 != 0x10)
++ abort ();
++ tls_var1 = 0x20;
++
++ tls_var2 = 0x2;
++ if (tls_var3 != 0x20)
++ abort ();
++ tls_var3 = 0x40;
++
++ call_libc ();
++
++ return LAV_CURRENT;
++}
++
++unsigned int
++la_objopen (struct link_map* map, Lmid_t lmid, uintptr_t* cookie)
++{
++ call_libc ();
++ *cookie = (uintptr_t) map;
++ return 0;
++}
++
++void
++la_activity (uintptr_t* cookie, unsigned int flag)
++{
++ if (tls_var0 != 0x1 || tls_var1 != 0x20)
++ abort ();
++ call_libc ();
++}
++
++void
++la_preinit (uintptr_t* cookie)
++{
++ call_libc ();
++}
+diff --git a/elf/tst-auditmod21b.c b/elf/tst-auditmod21b.c
+new file mode 100644
+index 0000000000..6ba5335b75
+--- /dev/null
++++ b/elf/tst-auditmod21b.c
+@@ -0,0 +1,22 @@
++/* Check LD_AUDIT with static TLS.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define tls_ie __attribute__ ((tls_model ("initial-exec")))
++
++__thread int tls_var2 tls_ie;
++__thread int tls_var3 tls_ie = 0x20;
+diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
+index 3fb085f9a1..34a33164ff 100644
+--- a/nptl/allocatestack.c
++++ b/nptl/allocatestack.c
+@@ -138,7 +138,7 @@ get_cached_stack (size_t *sizep, void **memp)
+ memset (dtv, '\0', (dtv[-1].counter + 1) * sizeof (dtv_t));
+
+ /* Re-initialize the TLS. */
+- _dl_allocate_tls_init (TLS_TPADJ (result));
++ _dl_allocate_tls_init (TLS_TPADJ (result), true);
+
+ return result;
+ }
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index f6b2b415a6..97061bdf9f 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -1282,7 +1282,7 @@ extern void _dl_allocate_static_tls (struct link_map *map) attribute_hidden;
+ /* These are internal entry points to the two halves of _dl_allocate_tls,
+ only used within rtld.c itself at startup time. */
+ extern void *_dl_allocate_tls_storage (void) attribute_hidden;
+-extern void *_dl_allocate_tls_init (void *);
++extern void *_dl_allocate_tls_init (void *, bool);
+ rtld_hidden_proto (_dl_allocate_tls_init)
+
+ /* Deallocate memory allocated with _dl_allocate_tls. */
+--
+2.27.0
+
diff --git a/elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch b/elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch
new file mode 100644
index 0000000..ffd1cb1
--- /dev/null
+++ b/elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch
@@ -0,0 +1,27 @@
+From 82fbcd7118d760492e2ecc9fa291e358b9ba0361 Mon Sep 17 00:00:00 2001
+From: Arjun Shankar <arjun@redhat.com>
+Date: Fri, 20 Aug 2021 16:24:05 +0200
+Subject: [PATCH] elf: Fix missing colon in LD_SHOW_AUXV output [BZ #28253]
+
+This commit adds a missing colon in the AT_MINSIGSTKSZ entry in
+the _dl_show_auxv function.
+---
+ elf/dl-sysdep.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/elf/dl-sysdep.c b/elf/dl-sysdep.c
+index d47bef1..2c684c2 100644
+--- a/elf/dl-sysdep.c
++++ b/elf/dl-sysdep.c
+@@ -317,7 +317,7 @@ _dl_show_auxv (void)
+ [AT_SYSINFO_EHDR - 2] = { "SYSINFO_EHDR: 0x", hex },
+ [AT_RANDOM - 2] = { "RANDOM: 0x", hex },
+ [AT_HWCAP2 - 2] = { "HWCAP2: 0x", hex },
+- [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ ", dec },
++ [AT_MINSIGSTKSZ - 2] = { "MINSIGSTKSZ: ", dec },
+ [AT_L1I_CACHESIZE - 2] = { "L1I_CACHESIZE: ", dec },
+ [AT_L1I_CACHEGEOMETRY - 2] = { "L1I_CACHEGEOMETRY: 0x", hex },
+ [AT_L1D_CACHESIZE - 2] = { "L1D_CACHESIZE: ", dec },
+--
+1.8.3.1
+
diff --git a/elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch b/elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch
new file mode 100644
index 0000000..1d1f790
--- /dev/null
+++ b/elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch
@@ -0,0 +1,544 @@
+From de6cdd68753ed126a3ecf105d98e8c0ee8cb6ec4 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 14 Jan 2022 20:16:05 +0100
+Subject: [PATCH] elf/Makefile: Reflow and sort most variable assignments
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+(cherry picked from commit 7de01e60c200c431d3469deb784da8fd4508fc15)
+---
+ elf/Makefile | 386 +++++++++++++++++++++++++++++++++++++++------------
+ 1 file changed, 294 insertions(+), 92 deletions(-)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 5859d47fc7..f930e04e27 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -21,21 +21,62 @@ subdir := elf
+
+ include ../Makeconfig
+
+-headers = elf.h bits/elfclass.h link.h bits/link.h
+-routines = $(all-dl-routines) dl-support dl-iteratephdr \
+- dl-addr dl-addr-obj enbl-secure dl-profstub \
+- dl-origin dl-libc dl-sym dl-sysdep dl-error \
+- dl-reloc-static-pie libc_early_init rtld_static_init
++headers = \
++ bits/elfclass.h \
++ bits/link.h \
++ elf.h \
++ link.h \
++ # headers
++
++routines = \
++ $(all-dl-routines) \
++ dl-addr \
++ dl-addr-obj \
++ dl-error \
++ dl-iteratephdr \
++ dl-libc \
++ dl-origin \
++ dl-profstub \
++ dl-reloc-static-pie \
++ dl-support \
++ dl-sym \
++ dl-sysdep \
++ enbl-secure \
++ libc_early_init \
++ rtld_static_init \
++ # routines
+
+ # The core dynamic linking functions are in libc for the static and
+ # profiled libraries.
+-dl-routines = $(addprefix dl-,load lookup object reloc deps \
+- runtime init fini debug misc \
+- version profile tls origin scope \
+- execstack open close trampoline \
+- exception sort-maps lookup-direct \
+- call-libc-early-init write \
+- thread_gscope_wait tls_init_tp)
++dl-routines = \
++ dl-call-libc-early-init \
++ dl-close \
++ dl-debug \
++ dl-deps \
++ dl-exception \
++ dl-execstack \
++ dl-fini \
++ dl-init \
++ dl-load \
++ dl-lookup \
++ dl-lookup-direct \
++ dl-misc \
++ dl-object \
++ dl-open \
++ dl-origin \
++ dl-profile \
++ dl-reloc \
++ dl-runtime \
++ dl-scope \
++ dl-sort-maps \
++ dl-thread_gscope_wait \
++ dl-tls \
++ dl-tls_init_tp \
++ dl-trampoline \
++ dl-version \
++ dl-write \
++ # dl-routines
++
+ ifeq (yes,$(use-ldconfig))
+ dl-routines += dl-cache
+ endif
+@@ -58,16 +99,38 @@ endif
+
+ all-dl-routines = $(dl-routines) $(sysdep-dl-routines)
+ # But they are absent from the shared libc, because that code is in ld.so.
+-elide-routines.os = $(all-dl-routines) dl-support enbl-secure dl-origin \
+- dl-sysdep dl-exception dl-reloc-static-pie \
+- thread_gscope_wait rtld_static_init
++elide-routines.os = \
++ $(all-dl-routines) \
++ dl-exception \
++ dl-origin \
++ dl-reloc-static-pie \
++ dl-support \
++ dl-sysdep \
++ enbl-secure \
++ rtld_static_init \
++ thread_gscope_wait \
++ # elide-routines.os
+
+ # ld.so uses those routines, plus some special stuff for being the program
+ # interpreter and operating independent of libc.
+-rtld-routines = rtld $(all-dl-routines) dl-sysdep dl-environ dl-minimal \
+- dl-error-minimal dl-conflict dl-hwcaps dl-hwcaps_split dl-hwcaps-subdirs \
+- dl-usage dl-diagnostics dl-diagnostics-kernel dl-diagnostics-cpu \
+- dl-mutex
++rtld-routines = \
++ $(all-dl-routines) \
++ dl-conflict \
++ dl-diagnostics \
++ dl-diagnostics-cpu \
++ dl-diagnostics-kernel \
++ dl-environ \
++ dl-error-minimal \
++ dl-hwcaps \
++ dl-hwcaps-subdirs \
++ dl-hwcaps_split \
++ dl-minimal \
++ dl-mutex \
++ dl-sysdep \
++ dl-usage \
++ rtld \
++ # rtld-routines
++
+ all-rtld-routines = $(rtld-routines) $(sysdep-rtld-routines)
+
+ CFLAGS-dl-runtime.c += -fexceptions -fasynchronous-unwind-tables
+@@ -102,8 +165,16 @@ ld-map = $(common-objpfx)ld.map
+ endif
+
+ ifeq (yes,$(build-shared))
+-extra-objs = $(all-rtld-routines:%=%.os) sofini.os interp.os
+-generated += librtld.os dl-allobjs.os ld.so ldd
++extra-objs = \
++ $(all-rtld-routines:%=%.os) \
++ sofini.os \
++ interp.os \
++ # extra-objs
++generated += \
++ dl-allobjs.os \
++ ld.so ldd \
++ librtld.os \
++ # generated
+ install-others = $(inst_rtlddir)/$(rtld-installed-name)
+ install-bin-script = ldd
+ endif
+@@ -121,8 +192,15 @@ others-static += ldconfig
+ others += ldconfig
+ install-rootsbin += ldconfig
+
+-ldconfig-modules := cache readlib xmalloc xstrdup chroot_canon static-stubs \
+- stringtable
++ldconfig-modules := \
++ cache \
++ chroot_canon \
++ readlib \
++ static-stubs \
++ stringtable \
++ xmalloc \
++ xstrdup \
++ # ldconfig-modules
+ extra-objs += $(ldconfig-modules:=.o)
+ others-extras = $(ldconfig-modules)
+ endif
+@@ -156,23 +234,35 @@ $(inst_auditdir)/sotruss-lib.so: $(objpfx)sotruss-lib.so $(+force)
+ $(do-install-program)
+ endif
+
+-tests-static-normal := tst-array1-static tst-array5-static \
+- tst-dl-iter-static \
+- tst-tlsalign-static tst-tlsalign-extern-static \
+- tst-linkall-static tst-env-setuid tst-env-setuid-tunables \
+- tst-single_threaded-static tst-single_threaded-pthread-static \
+- tst-dst-static tst-getauxval-static
+-
+-tests-static-internal := tst-tls1-static \
+- tst-ptrguard1-static tst-stackguard1-static \
+- tst-tls1-static-non-pie
++tests-static-normal := \
++ tst-array1-static \
++ tst-array5-static \
++ tst-dl-iter-static \
++ tst-dst-static \
++ tst-env-setuid \
++ tst-env-setuid-tunables \
++ tst-getauxval-static \
++ tst-linkall-static \
++ tst-single_threaded-pthread-static \
++ tst-single_threaded-static \
++ tst-tlsalign-extern-static \
++ tst-tlsalign-static \
++ # tests-static-normal
++
++tests-static-internal := \
++ tst-ptrguard1-static \
++ tst-stackguard1-static \
++ tst-tls1-static \
++ tst-tls1-static-non-pie \
++ # tests-static-internal
+
+ CRT-tst-tls1-static-non-pie := $(csu-objpfx)crt1.o
+ tst-tls1-static-non-pie-no-pie = yes
+
+ tests-container := \
+- tst-ldconfig-bad-aux-cache \
+- tst-ldconfig-ld_so_conf-update
++ tst-ldconfig-bad-aux-cache \
++ tst-ldconfig-ld_so_conf-update \
++ # tests-container
+
+ ifeq (no,$(build-hardcoded-path-in-tests))
+ # This is an ld.so.cache test, and RPATH/RUNPATH in the executable
+@@ -180,14 +271,31 @@ ifeq (no,$(build-hardcoded-path-in-tests))
+ tests-container += tst-glibc-hwcaps-prepend-cache
+ endif
+
+-tests := tst-tls9 tst-leaks1 \
+- tst-array1 tst-array2 tst-array3 tst-array4 tst-array5 \
+- tst-auxv tst-stringtable
+-tests-internal := tst-tls1 $(tests-static-internal)
++tests := \
++ tst-array1 \
++ tst-array2 \
++ tst-array3 \
++ tst-array4 \
++ tst-array5 \
++ tst-auxv \
++ tst-leaks1 \
++ tst-stringtable \
++ tst-tls9 \
++ # tests
++
++tests-internal := \
++ $(tests-static-internal) \
++ tst-tls1 \
++ # tests-internal
++
+ tests-static := $(tests-static-normal) $(tests-static-internal)
+
+ ifeq (yes,$(build-shared))
+-tests-static += tst-tls9-static tst-single_threaded-static-dlopen
++tests-static += \
++ tst-single_threaded-static-dlopen \
++ tst-tls9-static \
++ # tests-static
++
+ static-dlopen-environment = \
+ LD_LIBRARY_PATH=$(ld-library-path):$(common-objpfx)dlfcn
+ tst-tls9-static-ENV = $(static-dlopen-environment)
+@@ -312,33 +421,65 @@ tests += \
+ unload6 \
+ unload7 \
+ unload8 \
+-# reldep9
++ # tests
+ tests-cxx = \
+ tst-dlopen-nodelete-reloc \
+ tst-nodelete \
+ tst-unique3 \
+ tst-unique4 \
+-# tests-cxx
++ # tests-cxx
+
+ tests += $(if $(CXX),$(tests-cxx))
+-tests-internal += loadtest unload unload2 circleload1 \
+- neededtest neededtest2 neededtest3 neededtest4 \
+- tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
+- tst-ptrguard1 tst-stackguard1 \
+- tst-create_format1 tst-tls-surplus tst-dl-hwcaps_split
+-tests-container += tst-pldd tst-dlopen-tlsmodid-container \
+- tst-dlopen-self-container tst-preload-pthread-libc
+-test-srcs = tst-pathopt
++tests-internal += \
++ circleload1 \
++ loadtest \
++ neededtest \
++ neededtest2 \
++ neededtest3 \
++ neededtest4 \
++ tst-create_format1 \
++ tst-dl-hwcaps_split \
++ tst-dlmopen2 \
++ tst-ptrguard1 \
++ tst-stackguard1 \
++ tst-tls-surplus \
++ tst-tls3 \
++ tst-tls6 \
++ tst-tls7 \
++ tst-tls8 \
++ unload \
++ unload2 \
++ # tests-internal
++
++tests-container += \
++ tst-dlopen-self-container \
++ tst-dlopen-tlsmodid-container \
++ tst-pldd \
++ tst-preload-pthread-libc \
++ # tests-container
++
++test-srcs = \
++ tst-pathopt \
++ # tests-srcs
++
+ selinux-enabled := $(shell cat /selinux/enforce 2> /dev/null)
++
+ ifneq ($(selinux-enabled),1)
+-tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog
++tests-execstack-yes = \
++ tst-execstack \
++ tst-execstack-needed \
++ tst-execstack-prog \
++ # tests-execstack-yes
+ endif
+ endif
+ tests += $(tests-execstack-$(have-z-execstack))
+ ifeq ($(run-built-tests),yes)
+-tests-special += $(objpfx)tst-leaks1-mem.out \
+- $(objpfx)noload-mem.out \
+- $(objpfx)tst-ldconfig-X.out $(objpfx)tst-rtld-help.out
++tests-special += \
++ $(objpfx)noload-mem.out \
++ $(objpfx)tst-ldconfig-X.out \
++ $(objpfx)tst-leaks1-mem.out \
++ $(objpfx)tst-rtld-help.out \
++ # tests-special
+ endif
+ tlsmod17a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+ tlsmod18a-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
+@@ -355,9 +496,16 @@ tst-tls-many-dynamic-modules-dep = \
+ tst-tls-many-dynamic-modules-dep-bad-suffixes = 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14
+ tst-tls-many-dynamic-modules-dep-bad = \
+ $(foreach n,$(tst-tls-many-dynamic-modules-dep-bad-suffixes),tst-tls-manydynamic$(n)mod-dep-bad)
+-extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \
+- tst-tlsalign-vars.o
+-test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars
++extra-test-objs += \
++ $(tlsmod17a-modules:=.os) \
++ $(tlsmod18a-modules:=.os) \
++ tst-tlsalign-vars.o \
++ # extra-test-objs
++test-extras += \
++ tst-tlsalign-vars \
++ tst-tlsmod17a \
++ tst-tlsmod18a \
++ # test-extras
+ modules-names = \
+ circlemod1 \
+ circlemod1a \
+@@ -609,17 +757,17 @@ modules-names-cxx = \
+ tst-unique3lib \
+ tst-unique3lib2 \
+ tst-unique4lib \
+-# modules-names-cxx
++ # modules-names-cxx
+
+ modules-names += \
+ $(if $(CXX),$(modules-names-cxx)) \
+ $(modules-execstack-$(have-z-execstack)) \
++ $(tlsmod17a-modules) \
++ $(tlsmod18a-modules) \
+ $(tst-tls-many-dynamic-modules) \
+ $(tst-tls-many-dynamic-modules-dep) \
+ $(tst-tls-many-dynamic-modules-dep-bad) \
+- $(tlsmod17a-modules) \
+- $(tlsmod18a-modules) \
+-# modules-names
++ # modules-names
+
+ # Most modules build with _ISOMAC defined, but those filtered out
+ # depend on internal headers.
+@@ -668,35 +816,70 @@ modules-names-nobuild := filtmod1 tst-big-note-lib tst-ro-dynamic-mod
+ tests += $(tests-static)
+
+ ifeq (yes,$(have-ifunc))
+-tests-ifuncstatic := ifuncmain1static ifuncmain1picstatic \
+- ifuncmain2static ifuncmain2picstatic \
+- ifuncmain4static ifuncmain4picstatic \
+- ifuncmain5static ifuncmain5picstatic \
+- ifuncmain7static ifuncmain7picstatic
++tests-ifuncstatic := \
++ ifuncmain1static \
++ ifuncmain1picstatic \
++ ifuncmain2static \
++ ifuncmain2picstatic \
++ ifuncmain4static \
++ ifuncmain4picstatic \
++ ifuncmain5static \
++ ifuncmain5picstatic \
++ ifuncmain7static \
++ ifuncmain7picstatic \
++ # tests-ifuncstatic
+ ifeq (yes,$(have-gcc-ifunc))
+ tests-ifuncstatic += ifuncmain9static ifuncmain9picstatic
+ endif
+ tests-static += $(tests-ifuncstatic)
+ tests-internal += $(tests-ifuncstatic)
+ ifeq (yes,$(build-shared))
+-tests += tst-ifunc-fault-lazy tst-ifunc-fault-bindnow
++tests += \
++ tst-ifunc-fault-bindnow \
++ tst-ifunc-fault-lazy \
++ # tests
+ # Note: sysdeps/x86_64/ifuncmain8.c uses ifuncmain8.
+ tests-internal += \
+- ifuncmain1 ifuncmain1pic ifuncmain1vis ifuncmain1vispic \
+- ifuncmain1staticpic \
+- ifuncmain2 ifuncmain2pic ifuncmain3 ifuncmain4 \
+- ifuncmain5 ifuncmain5pic ifuncmain5staticpic \
+- ifuncmain7 ifuncmain7pic
++ ifuncmain1 \
++ ifuncmain1pic \
++ ifuncmain1staticpic \
++ ifuncmain1vis \
++ ifuncmain1vispic \
++ ifuncmain2 \
++ ifuncmain2pic \
++ ifuncmain3 \
++ ifuncmain4 \
++ ifuncmain5 \
++ ifuncmain5pic \
++ ifuncmain5staticpic \
++ ifuncmain7 \
++ ifuncmain7pic \
++ # tests-internal
+ ifeq (yes,$(have-gcc-ifunc))
+-tests-internal += ifuncmain9 ifuncmain9pic
++tests-internal += \
++ ifuncmain9 \
++ ifuncmain9pic \
++ # tests-internal
+ endif
+-ifunc-test-modules = ifuncdep1 ifuncdep1pic ifuncdep2 ifuncdep2pic \
+- ifuncdep5 ifuncdep5pic
++ifunc-test-modules = \
++ ifuncdep1 \
++ ifuncdep1pic \
++ ifuncdep2 \
++ ifuncdep2pic \
++ ifuncdep5 \
++ ifuncdep5pic \
++ # ifunc-test-modules
+ extra-test-objs += $(ifunc-test-modules:=.o)
+ test-internal-extras += $(ifunc-test-modules)
+ ifeq (yes,$(have-fpie))
+-ifunc-pie-tests = ifuncmain1pie ifuncmain1vispie ifuncmain1staticpie \
+- ifuncmain5pie ifuncmain6pie ifuncmain7pie
++ifunc-pie-tests = \
++ ifuncmain1pie \
++ ifuncmain1staticpie \
++ ifuncmain1vispie \
++ ifuncmain5pie \
++ ifuncmain6pie \
++ ifuncmain7pie \
++ # ifunc-pie-tests
+ ifeq (yes,$(have-gcc-ifunc))
+ ifunc-pie-tests += ifuncmain9pie
+ endif
+@@ -706,30 +889,50 @@ endif
+ tests-internal += $(ifunc-pie-tests)
+ tests-pie += $(ifunc-pie-tests)
+ endif
+-modules-names += ifuncmod1 ifuncmod3 ifuncmod5 ifuncmod6
++modules-names += \
++ ifuncmod1 \
++ ifuncmod3 \
++ ifuncmod5 \
++ ifuncmod6 \
++ # module-names
+ endif
+ endif
+
+ ifeq (yes,$(build-shared))
+ ifeq ($(run-built-tests),yes)
+-tests-special += $(objpfx)tst-pathopt.out $(objpfx)tst-rtld-load-self.out \
+- $(objpfx)tst-rtld-preload.out $(objpfx)argv0test.out \
+- $(objpfx)tst-rtld-help.out
++tests-special += \
++ $(objpfx)argv0test.out \
++ $(objpfx)tst-pathopt.out \
++ $(objpfx)tst-rtld-help.out \
++ $(objpfx)tst-rtld-load-self.out \
++ $(objpfx)tst-rtld-preload.out \
++ # tests-special
+ endif
+-tests-special += $(objpfx)check-textrel.out $(objpfx)check-execstack.out \
+- $(objpfx)check-wx-segment.out \
+- $(objpfx)check-localplt.out $(objpfx)check-initfini.out
++tests-special += \
++ $(objpfx)check-execstack.out \
++ $(objpfx)check-initfini.out \
++ $(objpfx)check-localplt.out \
++ $(objpfx)check-textrel.out \
++ $(objpfx)check-wx-segment.out \
++ # tests-special
+ endif
+
+ ifeq ($(run-built-tests),yes)
+-tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \
+- $(objpfx)tst-array1-static-cmp.out \
+- $(objpfx)tst-array2-cmp.out $(objpfx)tst-array3-cmp.out \
+- $(objpfx)tst-array4-cmp.out $(objpfx)tst-array5-cmp.out \
+- $(objpfx)tst-array5-static-cmp.out $(objpfx)order2-cmp.out \
+- $(objpfx)tst-initorder-cmp.out \
+- $(objpfx)tst-initorder2-cmp.out $(objpfx)tst-unused-dep.out \
+- $(objpfx)tst-unused-dep-cmp.out
++tests-special += \
++ $(objpfx)order-cmp.out \
++ $(objpfx)order2-cmp.out \
++ $(objpfx)tst-array1-cmp.out \
++ $(objpfx)tst-array1-static-cmp.out \
++ $(objpfx)tst-array2-cmp.out \
++ $(objpfx)tst-array3-cmp.out \
++ $(objpfx)tst-array4-cmp.out \
++ $(objpfx)tst-array5-cmp.out \
++ $(objpfx)tst-array5-static-cmp.out \
++ $(objpfx)tst-initorder-cmp.out \
++ $(objpfx)tst-initorder2-cmp.out \
++ $(objpfx)tst-unused-dep-cmp.out \
++ $(objpfx)tst-unused-dep.out \
++ # tests-special
+ endif
+
+ check-abi: $(objpfx)check-abi-ld.out
+@@ -811,6 +1014,7 @@ rtld-stubbed-symbols = \
+ free \
+ malloc \
+ realloc \
++ # rtld-stubbed-symbols
+
+ ifeq ($(have-ssp),yes)
+ # rtld is not built with the stack protector, so these references will
+--
+2.27.0
+
diff --git a/elf-Replace-nsid-with-args.nsid-BZ-27609.patch b/elf-Replace-nsid-with-args.nsid-BZ-27609.patch
new file mode 100644
index 0000000..47a7031
--- /dev/null
+++ b/elf-Replace-nsid-with-args.nsid-BZ-27609.patch
@@ -0,0 +1,50 @@
+From 1e1ecea62e899acb58c3fdf3b320a0833ddd0dff Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Thu, 30 Sep 2021 10:29:17 -0700
+Subject: [PATCH] elf: Replace nsid with args.nsid [BZ #27609]
+
+commit ec935dea6332cb22f9881cd1162bad156173f4b0
+Author: Florian Weimer <fweimer@redhat.com>
+Date: Fri Apr 24 22:31:15 2020 +0200
+
+ elf: Implement __libc_early_init
+
+has
+
+@@ -856,6 +876,11 @@ no more namespaces available for dlmopen()"));
+ /* See if an error occurred during loading. */
+ if (__glibc_unlikely (exception.errstring != NULL))
+ {
++ /* Avoid keeping around a dangling reference to the libc.so link
++ map in case it has been cached in libc_map. */
++ if (!args.libc_already_loaded)
++ GL(dl_ns)[nsid].libc_map = NULL;
++
+
+do_dlopen calls _dl_open with nsid == __LM_ID_CALLER (-2), which calls
+dl_open_worker with args.nsid = nsid. dl_open_worker updates args.nsid
+if it is __LM_ID_CALLER. After dl_open_worker returns, it is wrong to
+use nsid.
+
+Replace nsid with args.nsid after dl_open_worker returns. This fixes
+BZ #27609.
+---
+ elf/dl-open.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/elf/dl-open.c b/elf/dl-open.c
+index a25443f..5295e93 100644
+--- a/elf/dl-open.c
++++ b/elf/dl-open.c
+@@ -886,7 +886,7 @@ no more namespaces available for dlmopen()"));
+ /* Avoid keeping around a dangling reference to the libc.so link
+ map in case it has been cached in libc_map. */
+ if (!args.libc_already_loaded)
+- GL(dl_ns)[nsid].libc_map = NULL;
++ GL(dl_ns)[args.nsid].libc_map = NULL;
+
+ /* Remove the object from memory. It may be in an inconsistent
+ state if relocation failed, for example. */
+--
+1.8.3.1
+
diff --git a/elf-Restore-ldconfig-libc6-implicit-soname-logic-BZ-.patch b/elf-Restore-ldconfig-libc6-implicit-soname-logic-BZ-.patch
new file mode 100644
index 0000000..cee3932
--- /dev/null
+++ b/elf-Restore-ldconfig-libc6-implicit-soname-logic-BZ-.patch
@@ -0,0 +1,214 @@
+From 1b0ea8c5d886fedabd611a569b5ec58a6f5153e6 Mon Sep 17 00:00:00 2001
+From: Joan Bruguera <joanbrugueram@gmail.com>
+Date: Sat, 18 Feb 2023 21:52:15 +0000
+Subject: [PATCH] elf: Restore ldconfig libc6 implicit soname logic [BZ #30125]
+
+While cleaning up old libc version support, the deprecated libc4 code was
+accidentally kept in `implicit_soname`, instead of the libc6 code.
+
+This causes additional symlinks to be created by `ldconfig` for libraries
+without a soname, e.g. a library `libsomething.123.456.789` without a soname
+will create a `libsomething.123` -> `libsomething.123.456.789` symlink.
+
+As the libc6 version of the `implicit_soname` code is a trivial `xstrdup`,
+just inline it and remove `implicit_soname` altogether.
+
+Some further simplification looks possible (e.g. the call to `create_links`
+looks like a no-op if `soname == NULL`, other than the verbose printfs), but
+logic is kept as-is for now.
+
+Fixes: BZ #30125
+Fixes: 8ee878592c4a ("Assume only FLAG_ELF_LIBC6 suport")
+Signed-off-by: Joan Bruguera <joanbrugueram@gmail.com>
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+Rebased-by: laokz <zhangkai@iscas.ac.cn>
+---
+ elf/Makefile | 14 ++++++
+ elf/ldconfig.c | 4 +-
+ elf/readlib.c | 19 --------
+ elf/tst-ldconfig-soname-lib-with-soname.c | 1 +
+ elf/tst-ldconfig-soname-lib-without-soname.c | 1 +
+ elf/tst-ldconfig-soname.sh | 49 ++++++++++++++++++++
+ sysdeps/generic/ldconfig.h | 2 -
+ 7 files changed, 67 insertions(+), 23 deletions(-)
+ create mode 100644 elf/tst-ldconfig-soname-lib-with-soname.c
+ create mode 100644 elf/tst-ldconfig-soname-lib-without-soname.c
+ create mode 100644 elf/tst-ldconfig-soname.sh
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 2fc6391183..0d19964d42 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -627,6 +627,7 @@ ifeq ($(run-built-tests),yes)
+ tests-special += \
+ $(objpfx)noload-mem.out \
+ $(objpfx)tst-ldconfig-X.out \
++ $(objpfx)tst-ldconfig-soname.out \
+ $(objpfx)tst-leaks1-mem.out \
+ $(objpfx)tst-rtld-help.out \
+ # tests-special
+@@ -859,6 +860,8 @@ modules-names += \
+ tst-initorderb2 \
+ tst-latepthreadmod \
+ tst-ldconfig-ld-mod \
++ tst-ldconfig-soname-lib-with-soname \
++ tst-ldconfig-soname-lib-without-soname \
+ tst-main1mod \
+ tst-nodelete2mod \
+ tst-nodelete-dlclose-dso \
+@@ -2402,6 +2405,17 @@
+ '$(run-program-env)' > $@; \
+ $(evaluate-test)
+
++LDFLAGS-tst-ldconfig-soname-lib-with-soname.so = \
++ -Wl,-soname,libtst-ldconfig-soname-lib-with-soname.so.1
++
++$(objpfx)tst-ldconfig-soname.out : tst-ldconfig-soname.sh \
++ $(objpfx)ldconfig \
++ $(objpfx)tst-ldconfig-soname-lib-with-soname.so \
++ $(objpfx)tst-ldconfig-soname-lib-without-soname.so
++ $(SHELL) $< '$(common-objpfx)' '$(test-wrapper-env)' \
++ '$(run-program-env)' > $@; \
++ $(evaluate-test)
++
+ # Test static linking of all the libraries we can possibly link
+ # together. Note that in some configurations this may be less than the
+ # complete list of libraries we build but we try to maxmimize this list.
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index 3f1b30c570..2fc45ad825 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -616,7 +616,7 @@ manual_link (char *library)
+ goto out;
+ }
+ if (soname == NULL)
+- soname = implicit_soname (libname, flag);
++ soname = xstrdup (libname);
+ create_links (real_path, path, libname, soname);
+ free (soname);
+ out:
+@@ -849,7 +849,7 @@ search_dir (const struct dir_entry *entry)
+ }
+
+ if (soname == NULL)
+- soname = implicit_soname (direntry->d_name, flag);
++ soname = xstrdup (direntry->d_name);
+
+ /* A link may just point to itself. */
+ if (is_link)
+diff --git a/elf/readlib.c b/elf/readlib.c
+index c5c3591eef..bc13d9acc6 100644
+--- a/elf/readlib.c
++++ b/elf/readlib.c
+@@ -166,24 +166,5 @@ process_file (const char *real_file_name, const char *file_name,
+ return ret;
+ }
+
+-/* Returns made up soname if lib doesn't have explicit DT_SONAME. */
+-
+-char *
+-implicit_soname (const char *lib, int flag)
+-{
+- char *soname = xstrdup (lib);
+-
+- /* Aout files don't have a soname, just return the name
+- including the major number. */
+- char *major = strstr (soname, ".so.");
+- if (major)
+- {
+- char *dot = strstr (major + 4, ".");
+- if (dot)
+- *dot = '\0';
+- }
+- return soname;
+-}
+-
+ /* Get architecture specific version of process_elf_file. */
+ #include <readelflib.c>
+diff --git a/elf/tst-ldconfig-soname-lib-with-soname.c b/elf/tst-ldconfig-soname-lib-with-soname.c
+new file mode 100644
+index 0000000000..d1ab56ad58
+--- /dev/null
++++ b/elf/tst-ldconfig-soname-lib-with-soname.c
+@@ -0,0 +1 @@
++/* This file intentionally left blank */
+diff --git a/elf/tst-ldconfig-soname-lib-without-soname.c b/elf/tst-ldconfig-soname-lib-without-soname.c
+new file mode 100644
+index 0000000000..d1ab56ad58
+--- /dev/null
++++ b/elf/tst-ldconfig-soname-lib-without-soname.c
+@@ -0,0 +1 @@
++/* This file intentionally left blank */
+diff --git a/elf/tst-ldconfig-soname.sh b/elf/tst-ldconfig-soname.sh
+new file mode 100644
+index 0000000000..406f526dbf
+--- /dev/null
++++ b/elf/tst-ldconfig-soname.sh
+@@ -0,0 +1,49 @@
++#!/bin/sh
++# Test that ldconfig creates symlinks according to the library's soname
++# (and in particular, does not create symlinks for libraries without a soname)
++# Copyright (C) 2000-2023 Free Software Foundation, Inc.
++# Copyright The GNU Toolchain Authors.
++# This file is part of the GNU C Library.
++
++# The GNU C Library is free software; you can redistribute it and/or
++# modify it under the terms of the GNU Lesser General Public
++# License as published by the Free Software Foundation; either
++# version 2.1 of the License, or (at your option) any later version.
++
++# The GNU C Library is distributed in the hope that it will be useful,
++# but WITHOUT ANY WARRANTY; without even the implied warranty of
++# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++# Lesser General Public License for more details.
++
++# You should have received a copy of the GNU Lesser General Public
++# License along with the GNU C Library; if not, see
++# <https://www.gnu.org/licenses/>.
++
++set -ex
++
++common_objpfx=$1
++test_wrapper_env=$2
++run_program_env=$3
++
++testroot="${common_objpfx}elf/bug30125-test-directory"
++cleanup () {
++ rm -rf "$testroot"
++}
++trap cleanup 0
++
++rm -rf "$testroot"
++mkdir -p $testroot/lib
++cp "${common_objpfx}elf/tst-ldconfig-soname-lib-with-soname.so" \
++ $testroot/lib/libtst-ldconfig-soname-lib-with-soname.so.1.2.3
++cp "${common_objpfx}elf/tst-ldconfig-soname-lib-without-soname.so" \
++ $testroot/lib/libtst-ldconfig-soname-lib-without-soname.so.1.2.3
++
++${test_wrapper_env} \
++${run_program_env} \
++${common_objpfx}elf/ldconfig -vn $testroot/lib
++
++LINKS=$(cd $testroot/lib && find . -type l)
++if [ "$LINKS" != "./libtst-ldconfig-soname-lib-with-soname.so.1" ]; then
++ echo "error: $0 - extra symlinks found"
++ exit 1
++fi
+diff --git a/sysdeps/generic/ldconfig.h b/sysdeps/generic/ldconfig.h
+index 0e1a9a9515..e9e9e19d0f 100644
+--- a/sysdeps/generic/ldconfig.h
++++ b/sysdeps/generic/ldconfig.h
+@@ -90,8 +90,6 @@ extern int process_file (const char *real_file_name, const char *file_name,
+ char **soname, int is_link,
+ struct stat64 *stat_buf);
+
+-extern char *implicit_soname (const char *lib, int flag);
+-
+ /* Declared in readelflib.c. */
+ extern int process_elf_file (const char *file_name, const char *lib,
+ int *flag, unsigned int *osversion,
+--
+2.39.2
+
diff --git a/elf-Sort-tests-and-modules-names.patch b/elf-Sort-tests-and-modules-names.patch
new file mode 100644
index 0000000..49bab1d
--- /dev/null
+++ b/elf-Sort-tests-and-modules-names.patch
@@ -0,0 +1,546 @@
+From 31186e2cb74b2403726060276512c39cc89a1478 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 13 Dec 2021 09:43:52 -0800
+Subject: [PATCH] elf: Sort tests and modules-names
+
+Sort tests and modules-names to reduce future conflicts.
+
+(cherry picked from commit 28713c06129f8f64f88c423266e6ff2880216509)
+---
+ elf/Makefile | 512 ++++++++++++++++++++++++++++++++++++++-------------
+ 1 file changed, 385 insertions(+), 127 deletions(-)
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 118d579c42..ec1cd49bb3 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -193,39 +193,133 @@ static-dlopen-environment = \
+ tst-tls9-static-ENV = $(static-dlopen-environment)
+ tst-single_threaded-static-dlopen-ENV = $(static-dlopen-environment)
+
+-tests += restest1 preloadtest loadfail multiload origtest resolvfail \
+- constload1 order noload filter \
+- reldep reldep2 reldep3 reldep4 nodelete nodelete2 \
+- nodlopen nodlopen2 lateglobal initfirst global \
+- restest2 next dblload dblunload reldep5 reldep6 reldep7 reldep8 \
+- tst-tls4 tst-tls5 \
+- tst-tls10 tst-tls11 tst-tls12 tst-tls13 tst-tls14 tst-tls15 \
+- tst-tls16 tst-tls17 tst-tls18 tst-tls19 tst-tls-dlinfo \
+- tst-align tst-align2 \
+- tst-dlmodcount tst-dlopenrpath tst-deep1 \
+- tst-dlmopen1 tst-dlmopen3 \
+- unload3 unload4 unload5 unload6 unload7 unload8 tst-global1 order2 \
+- tst-audit1 tst-audit2 tst-audit8 tst-audit9 \
+- tst-addr1 tst-thrlock \
+- tst-unique1 tst-unique2 $(if $(CXX),tst-unique3 tst-unique4 \
+- tst-nodelete tst-dlopen-nodelete-reloc) \
+- tst-initorder tst-initorder2 tst-relsort1 tst-null-argv \
+- tst-tlsalign tst-tlsalign-extern tst-nodelete-opened \
+- tst-nodelete2 tst-audit11 tst-audit12 tst-dlsym-error tst-noload \
+- tst-latepthread tst-tls-manydynamic tst-nodelete-dlclose \
+- tst-debug1 tst-main1 tst-absolute-sym tst-absolute-zero tst-big-note \
+- tst-unwind-ctor tst-unwind-main tst-audit13 \
+- tst-sonamemove-link tst-sonamemove-dlopen tst-dlopen-tlsmodid \
+- tst-dlopen-self tst-auditmany tst-initfinilazyfail tst-dlopenfail \
+- tst-dlopenfail-2 \
+- tst-filterobj tst-filterobj-dlopen tst-auxobj tst-auxobj-dlopen \
+- tst-audit14 tst-audit15 tst-audit16 tst-audit17 \
+- tst-single_threaded tst-single_threaded-pthread \
+- tst-tls-ie tst-tls-ie-dlmopen argv0test \
+- tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
+- tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \
+- tst-dl-is_dso tst-ro-dynamic
++tests += \
++ argv0test \
++ constload1 \
++ dblload \
++ dblunload \
++ filter \
++ global \
++ initfirst \
++ lateglobal \
++ loadfail \
++ multiload \
++ next \
++ nodelete \
++ nodelete2 \
++ nodlopen \
++ nodlopen2 \
++ noload \
++ order \
++ order2 \
++ origtest \
++ preloadtest \
++ reldep \
++ reldep2 \
++ reldep3 \
++ reldep4 \
++ reldep5 \
++ reldep6 \
++ reldep7 \
++ reldep8 \
++ resolvfail \
++ restest1 \
++ restest2 \
++ tst-absolute-sym \
++ tst-absolute-zero \
++ tst-addr1 \
++ tst-align \
++ tst-align2 \
++ tst-audit1 \
++ tst-audit2 \
++ tst-audit8 \
++ tst-audit9 \
++ tst-audit11 \
++ tst-audit12 \
++ tst-audit13 \
++ tst-audit14 \
++ tst-audit15 \
++ tst-audit16 \
++ tst-audit17 \
++ tst-auditmany \
++ tst-auxobj \
++ tst-auxobj-dlopen \
++ tst-big-note \
++ tst-debug1 \
++ tst-deep1 \
++ tst-dl-is_dso \
++ tst-dlmodcount \
++ tst-dlmopen1 \
++ tst-dlmopen3 \
++ tst-dlmopen-dlerror \
++ tst-dlmopen-gethostbyname \
++ tst-dlopenfail \
++ tst-dlopenfail-2 \
++ tst-dlopenrpath \
++ tst-dlopen-self \
++ tst-dlopen-tlsmodid \
++ tst-dlsym-error \
++ tst-filterobj \
++ tst-filterobj-dlopen \
++ tst-glibc-hwcaps \
++ tst-glibc-hwcaps-mask \
++ tst-glibc-hwcaps-prepend \
++ tst-global1 \
++ tst-initfinilazyfail \
++ tst-initorder \
++ tst-initorder2 \
++ tst-latepthread \
++ tst-main1 \
++ tst-nodelete2 \
++ tst-nodelete-dlclose \
++ tst-nodelete-opened \
++ tst-noload \
++ tst-null-argv \
++ tst-relsort1 \
++ tst-ro-dynamic \
++ tst-single_threaded \
++ tst-single_threaded-pthread \
++ tst-sonamemove-dlopen \
++ tst-sonamemove-link \
++ tst-thrlock \
++ tst-tls10 \
++ tst-tls11 \
++ tst-tls12 \
++ tst-tls13 \
++ tst-tls14 \
++ tst-tls15 \
++ tst-tls16 \
++ tst-tls17 \
++ tst-tls18 \
++ tst-tls19 \
++ tst-tls20 \
++ tst-tls21 \
++ tst-tls4 \
++ tst-tls5 \
++ tst-tlsalign \
++ tst-tlsalign-extern \
++ tst-tls-dlinfo \
++ tst-tls-ie \
++ tst-tls-ie-dlmopen \
++ tst-tls-manydynamic \
++ tst-unique1 \
++ tst-unique2 \
++ tst-unwind-ctor \
++ tst-unwind-main \
++ unload3 \
++ unload4 \
++ unload5 \
++ unload6 \
++ unload7 \
++ unload8 \
+ # reldep9
++tests-cxx = \
++ tst-dlopen-nodelete-reloc \
++ tst-nodelete \
++ tst-unique3 \
++ tst-unique4 \
++
++tests += $(if $(CXX),$(tests-cxx))
+ tests-internal += loadtest unload unload2 circleload1 \
+ neededtest neededtest2 neededtest3 neededtest4 \
+ tst-tls3 tst-tls6 tst-tls7 tst-tls8 tst-dlmopen2 \
+@@ -263,101 +357,265 @@ tst-tls-many-dynamic-modules-dep-bad = \
+ extra-test-objs += $(tlsmod17a-modules:=.os) $(tlsmod18a-modules:=.os) \
+ tst-tlsalign-vars.o
+ test-extras += tst-tlsmod17a tst-tlsmod18a tst-tlsalign-vars
+-modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+- testobj1_1 failobj constload2 constload3 unloadmod \
+- dep1 dep2 dep3 dep4 vismod1 vismod2 vismod3 \
+- nodelmod1 nodelmod2 nodelmod3 nodelmod4 \
+- nodel2mod1 nodel2mod2 nodel2mod3 \
+- nodlopenmod nodlopenmod2 filtmod1 filtmod2 \
+- reldepmod1 reldepmod2 reldepmod3 reldepmod4 nextmod1 nextmod2 \
+- reldep4mod1 reldep4mod2 reldep4mod3 reldep4mod4 \
+- neededobj1 neededobj2 neededobj3 neededobj4 \
+- neededobj5 neededobj6 firstobj globalmod1 \
+- unload2mod unload2dep ltglobmod1 ltglobmod2 pathoptobj \
+- dblloadmod1 dblloadmod2 dblloadmod3 reldepmod5 reldepmod6 \
+- reldep6mod0 reldep6mod1 reldep6mod2 reldep6mod3 reldep6mod4 \
+- reldep7mod1 reldep7mod2 \
+- tst-tlsmod1 tst-tlsmod2 tst-tlsmod3 tst-tlsmod4 \
+- tst-tlsmod5 tst-tlsmod6 tst-tlsmod7 tst-tlsmod8 \
+- tst-tlsmod9 tst-tlsmod10 tst-tlsmod11 tst-tlsmod12 \
+- tst-tlsmod13 tst-tlsmod13a tst-tlsmod14a tst-tlsmod14b \
+- tst-tlsmod15a tst-tlsmod15b tst-tlsmod16a tst-tlsmod16b \
+- $(tlsmod17a-modules) tst-tlsmod17b $(tlsmod18a-modules) \
+- tst-tls19mod1 tst-tls19mod2 tst-tls19mod3 \
+- circlemod1 circlemod1a circlemod2 circlemod2a \
+- circlemod3 circlemod3a \
+- reldep8mod1 reldep8mod2 reldep8mod3 \
+- reldep9mod1 reldep9mod2 reldep9mod3 \
+- tst-alignmod tst-alignmod2 \
+- $(modules-execstack-$(have-z-execstack)) \
+- tst-dlopenrpathmod tst-deep1mod1 tst-deep1mod2 tst-deep1mod3 \
+- tst-dlmopen1mod tst-auditmod1 \
+- unload3mod1 unload3mod2 unload3mod3 unload3mod4 \
+- unload4mod1 unload4mod2 unload4mod3 unload4mod4 \
+- unload6mod1 unload6mod2 unload6mod3 \
+- unload7mod1 unload7mod2 \
+- unload8mod1 unload8mod1x unload8mod2 unload8mod3 \
+- order2mod1 order2mod2 order2mod3 order2mod4 \
+- tst-unique1mod1 tst-unique1mod2 \
+- tst-unique2mod1 tst-unique2mod2 \
+- tst-auditmod9a tst-auditmod9b \
+- $(if $(CXX),tst-unique3lib tst-unique3lib2 tst-unique4lib \
+- tst-nodelete-uniquemod tst-nodelete-rtldmod \
+- tst-nodelete-zmod \
+- tst-dlopen-nodelete-reloc-mod1 \
+- tst-dlopen-nodelete-reloc-mod2 \
+- tst-dlopen-nodelete-reloc-mod3 \
+- tst-dlopen-nodelete-reloc-mod4 \
+- tst-dlopen-nodelete-reloc-mod5 \
+- tst-dlopen-nodelete-reloc-mod6 \
+- tst-dlopen-nodelete-reloc-mod7 \
+- tst-dlopen-nodelete-reloc-mod8 \
+- tst-dlopen-nodelete-reloc-mod9 \
+- tst-dlopen-nodelete-reloc-mod10 \
+- tst-dlopen-nodelete-reloc-mod11 \
+- tst-dlopen-nodelete-reloc-mod12 \
+- tst-dlopen-nodelete-reloc-mod13 \
+- tst-dlopen-nodelete-reloc-mod14 \
+- tst-dlopen-nodelete-reloc-mod15 \
+- tst-dlopen-nodelete-reloc-mod16 \
+- tst-dlopen-nodelete-reloc-mod17) \
+- tst-initordera1 tst-initorderb1 \
+- tst-initordera2 tst-initorderb2 \
+- tst-initordera3 tst-initordera4 \
+- tst-initorder2a tst-initorder2b tst-initorder2c \
+- tst-initorder2d \
+- tst-relsort1mod1 tst-relsort1mod2 tst-array2dep \
+- tst-array5dep tst-null-argv-lib \
+- tst-tlsalign-lib tst-nodelete-opened-lib tst-nodelete2mod \
+- tst-audit11mod1 tst-audit11mod2 tst-auditmod11 \
+- tst-audit12mod1 tst-audit12mod2 tst-audit12mod3 tst-auditmod12 \
+- tst-latepthreadmod $(tst-tls-many-dynamic-modules) \
+- $(tst-tls-many-dynamic-modules-dep) \
+- $(tst-tls-many-dynamic-modules-dep-bad) \
+- tst-nodelete-dlclose-dso tst-nodelete-dlclose-plugin \
+- tst-main1mod tst-absolute-sym-lib \
+- tst-absolute-zero-lib tst-big-note-lib tst-unwind-ctor-lib \
+- tst-audit13mod1 tst-sonamemove-linkmod1 \
+- tst-sonamemove-runmod1 tst-sonamemove-runmod2 \
+- tst-auditmanymod1 tst-auditmanymod2 tst-auditmanymod3 \
+- tst-auditmanymod4 tst-auditmanymod5 tst-auditmanymod6 \
+- tst-auditmanymod7 tst-auditmanymod8 tst-auditmanymod9 \
+- tst-initlazyfailmod tst-finilazyfailmod \
+- tst-dlopenfailmod1 tst-dlopenfaillinkmod tst-dlopenfailmod2 \
+- tst-dlopenfailmod3 tst-dlopenfailnodelmod tst-ldconfig-ld-mod \
+- tst-filterobj-flt tst-filterobj-aux tst-filterobj-filtee \
+- tst-auditlogmod-1 tst-auditlogmod-2 tst-auditlogmod-3 \
+- tst-single_threaded-mod1 tst-single_threaded-mod2 \
+- tst-single_threaded-mod3 tst-single_threaded-mod4 \
+- tst-tls-ie-mod0 tst-tls-ie-mod1 tst-tls-ie-mod2 \
+- tst-tls-ie-mod3 tst-tls-ie-mod4 tst-tls-ie-mod5 \
+- tst-tls-ie-mod6 libmarkermod1-1 libmarkermod1-2 libmarkermod1-3 \
+- libmarkermod2-1 libmarkermod2-2 \
+- libmarkermod3-1 libmarkermod3-2 libmarkermod3-3 \
+- libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \
+- tst-tls20mod-bad tst-tls21mod tst-dlmopen-dlerror-mod \
+- tst-auxvalmod \
+- tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \
++modules-names = \
++ circlemod1 \
++ circlemod1a \
++ circlemod2 \
++ circlemod2a \
++ circlemod3 \
++ circlemod3a \
++ constload2 \
++ constload3 \
++ dblloadmod1 \
++ dblloadmod2 \
++ dblloadmod3 \
++ dep1 \
++ dep2 \
++ dep3 \
++ dep4 \
++ failobj \
++ filtmod1 \
++ filtmod2 \
++ firstobj \
++ globalmod1 \
++ libmarkermod1-1 \
++ libmarkermod1-2 \
++ libmarkermod1-3 \
++ libmarkermod2-1 \
++ libmarkermod2-2 \
++ libmarkermod3-1 \
++ libmarkermod3-2 \
++ libmarkermod3-3 \
++ libmarkermod4-1 \
++ libmarkermod4-2 \
++ libmarkermod4-3 \
++ libmarkermod4-4 \
++ ltglobmod1 \
++ ltglobmod2 \
++ neededobj1 \
++ neededobj2 \
++ neededobj3 \
++ neededobj4 \
++ neededobj5 \
++ neededobj6 \
++ nextmod1 \
++ nextmod2 \
++ nodel2mod1 \
++ nodel2mod2 \
++ nodel2mod3 \
++ nodelmod1 \
++ nodelmod2 \
++ nodelmod3 \
++ nodelmod4 \
++ nodlopenmod \
++ nodlopenmod2 \
++ order2mod1 \
++ order2mod2 \
++ order2mod3 \
++ order2mod4 \
++ pathoptobj \
++ reldep4mod1 \
++ reldep4mod2 \
++ reldep4mod3 \
++ reldep4mod4 \
++ reldep6mod0 \
++ reldep6mod1 \
++ reldep6mod2 \
++ reldep6mod3 \
++ reldep6mod4 \
++ reldep7mod1 \
++ reldep7mod2 \
++ reldep8mod1 \
++ reldep8mod2 \
++ reldep8mod3 \
++ reldep9mod1 \
++ reldep9mod2 \
++ reldep9mod3 \
++ reldepmod1 \
++ reldepmod2 \
++ reldepmod3 \
++ reldepmod4 \
++ reldepmod5 \
++ reldepmod6 \
++ testobj1 \
++ testobj1_1 \
++ testobj2 \
++ testobj3 \
++ testobj4 \
++ testobj5 \
++ testobj6 \
++ tst-absolute-sym-lib \
++ tst-absolute-zero-lib \
++ tst-alignmod \
++ tst-alignmod2 \
++ tst-array2dep \
++ tst-array5dep \
++ tst-audit11mod1 \
++ tst-audit11mod2 \
++ tst-audit12mod1 \
++ tst-audit12mod2 \
++ tst-audit12mod3 \
++ tst-audit13mod1 \
++ tst-auditlogmod-1 \
++ tst-auditlogmod-2 \
++ tst-auditlogmod-3 \
++ tst-auditmanymod1 \
++ tst-auditmanymod2 \
++ tst-auditmanymod3 \
++ tst-auditmanymod4 \
++ tst-auditmanymod5 \
++ tst-auditmanymod6 \
++ tst-auditmanymod7 \
++ tst-auditmanymod8 \
++ tst-auditmanymod9 \
++ tst-auditmod1 \
++ tst-auditmod9a \
++ tst-auditmod9b \
++ tst-auditmod11 \
++ tst-auditmod12 \
++ tst-auxvalmod \
++ tst-big-note-lib \
++ tst-deep1mod1 \
++ tst-deep1mod2 \
++ tst-deep1mod3 \
++ tst-dlmopen1mod \
++ tst-dlmopen-dlerror-mod \
++ tst-dlmopen-gethostbyname-mod \
++ tst-dlopenfaillinkmod \
++ tst-dlopenfailmod1 \
++ tst-dlopenfailmod2 \
++ tst-dlopenfailmod3 \
++ tst-dlopenfailnodelmod \
++ tst-dlopenrpathmod \
++ tst-filterobj-aux \
++ tst-filterobj-filtee \
++ tst-filterobj-flt \
++ tst-finilazyfailmod \
++ tst-initlazyfailmod \
++ tst-initorder2a \
++ tst-initorder2b \
++ tst-initorder2c \
++ tst-initorder2d \
++ tst-initordera1 \
++ tst-initordera2 \
++ tst-initordera3 \
++ tst-initordera4 \
++ tst-initorderb1 \
++ tst-initorderb2 \
++ tst-latepthreadmod \
++ tst-ldconfig-ld-mod \
++ tst-main1mod \
++ tst-nodelete2mod \
++ tst-nodelete-dlclose-dso \
++ tst-nodelete-dlclose-plugin \
++ tst-nodelete-opened-lib \
++ tst-null-argv-lib \
++ tst-relsort1mod1 \
++ tst-relsort1mod2 \
++ tst-ro-dynamic-mod \
++ tst-single_threaded-mod1 \
++ tst-single_threaded-mod2 \
++ tst-single_threaded-mod3 \
++ tst-single_threaded-mod4 \
++ tst-sonamemove-linkmod1 \
++ tst-sonamemove-runmod1 \
++ tst-sonamemove-runmod2 \
++ tst-tls19mod1 \
++ tst-tls19mod2 \
++ tst-tls19mod3 \
++ tst-tls20mod-bad \
++ tst-tls21mod \
++ tst-tlsalign-lib \
++ tst-tls-ie-mod0 \
++ tst-tls-ie-mod1 \
++ tst-tls-ie-mod2 \
++ tst-tls-ie-mod3 \
++ tst-tls-ie-mod4 \
++ tst-tls-ie-mod5 \
++ tst-tls-ie-mod6 \
++ tst-tlsmod1 \
++ tst-tlsmod10 \
++ tst-tlsmod11 \
++ tst-tlsmod12 \
++ tst-tlsmod13 \
++ tst-tlsmod13a \
++ tst-tlsmod14a \
++ tst-tlsmod14b \
++ tst-tlsmod15a \
++ tst-tlsmod15b \
++ tst-tlsmod16a \
++ tst-tlsmod16b \
++ tst-tlsmod17b \
++ tst-tlsmod2 \
++ tst-tlsmod3 \
++ tst-tlsmod4 \
++ tst-tlsmod5 \
++ tst-tlsmod6 \
++ tst-tlsmod7 \
++ tst-tlsmod8 \
++ tst-tlsmod9 \
++ tst-unique1mod1 \
++ tst-unique1mod2 \
++ tst-unique2mod1 \
++ tst-unique2mod2 \
++ tst-unwind-ctor-lib \
++ unload2dep \
++ unload2mod \
++ unload3mod1 \
++ unload3mod2 \
++ unload3mod3 \
++ unload3mod4 \
++ unload4mod1 \
++ unload4mod2 \
++ unload4mod3 \
++ unload4mod4 \
++ unload6mod1 \
++ unload6mod2 \
++ unload6mod3 \
++ unload7mod1 \
++ unload7mod2 \
++ unload8mod1 \
++ unload8mod1x \
++ unload8mod2 \
++ unload8mod3 \
++ unloadmod \
++ vismod1 \
++ vismod2 \
++ vismod3 \
++
++modules-names-cxx = \
++ tst-dlopen-nodelete-reloc-mod1 \
++ tst-dlopen-nodelete-reloc-mod10 \
++ tst-dlopen-nodelete-reloc-mod11 \
++ tst-dlopen-nodelete-reloc-mod12 \
++ tst-dlopen-nodelete-reloc-mod13 \
++ tst-dlopen-nodelete-reloc-mod14 \
++ tst-dlopen-nodelete-reloc-mod15 \
++ tst-dlopen-nodelete-reloc-mod16 \
++ tst-dlopen-nodelete-reloc-mod17 \
++ tst-dlopen-nodelete-reloc-mod2 \
++ tst-dlopen-nodelete-reloc-mod3 \
++ tst-dlopen-nodelete-reloc-mod4 \
++ tst-dlopen-nodelete-reloc-mod5 \
++ tst-dlopen-nodelete-reloc-mod6 \
++ tst-dlopen-nodelete-reloc-mod7 \
++ tst-dlopen-nodelete-reloc-mod8 \
++ tst-dlopen-nodelete-reloc-mod9 \
++ tst-nodelete-rtldmod \
++ tst-nodelete-uniquemod \
++ tst-nodelete-zmod \
++ tst-unique3lib \
++ tst-unique3lib2 \
++ tst-unique4lib \
++
++modules-names += \
++ $(if $(CXX),$(modules-names-cxx)) \
++ $(modules-execstack-$(have-z-execstack)) \
++ $(tst-tls-many-dynamic-modules) \
++ $(tst-tls-many-dynamic-modules-dep) \
++ $(tst-tls-many-dynamic-modules-dep-bad) \
++ $(tlsmod17a-modules) \
++ $(tlsmod18a-modules) \
+
+ # Most modules build with _ISOMAC defined, but those filtered out
+ # depend on internal headers.
+--
+2.27.0
+
diff --git a/elf-Unconditionally-use-__ehdr_start.patch b/elf-Unconditionally-use-__ehdr_start.patch
new file mode 100644
index 0000000..b30438d
--- /dev/null
+++ b/elf-Unconditionally-use-__ehdr_start.patch
@@ -0,0 +1,177 @@
+From 302247c89121e8d4c7629e589edbb4974fff6edb Mon Sep 17 00:00:00 2001
+From: Fangrui Song <maskray@google.com>
+Date: Tue, 10 Aug 2021 11:04:56 -0700
+Subject: [PATCH] elf: Unconditionally use __ehdr_start
+
+We can consider __ehdr_start (from binutils 2.23 onwards)
+unconditionally supported, since configure.ac requires binutils>=2.25.
+
+The configure.ac check is related to an ia64 bug fixed by binutils 2.24.
+See https://sourceware.org/pipermail/libc-alpha/2014-August/053503.html
+
+Tested on x86_64-linux-gnu. Tested build-many-glibcs.py with
+aarch64-linux-gnu and s390x-linux-gnu.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ config.h.in | 3 ---
+ configure | 52 ----------------------------------------------------
+ configure.ac | 34 ----------------------------------
+ elf/rtld.c | 13 ++++---------
+ 4 files changed, 4 insertions(+), 98 deletions(-)
+
+diff --git a/config.h.in b/config.h.in
+index 8b45a3a..0d92504 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -198,9 +198,6 @@
+ /* Define if CC supports attribute retain. */
+ #undef HAVE_GNU_RETAIN
+
+-/* Define if the linker defines __ehdr_start. */
+-#undef HAVE_EHDR_START
+-
+ /* Define to 1 if the assembler needs intermediate aliases to define
+ multiple symbol versions for one symbol. */
+ #define SYMVER_NEEDS_ALIAS 0
+diff --git a/configure b/configure
+index 9619c10..7272fbf 100755
+--- a/configure
++++ b/configure
+@@ -6636,58 +6636,6 @@ if test $libc_cv_predef_fortify_source = yes; then
+ fi
+
+
+-# Some linkers on some architectures support __ehdr_start but with
+-# bugs. Make sure usage of it does not create relocations in the
+-# output (as the linker should resolve them all for us).
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the linker provides working __ehdr_start" >&5
+-$as_echo_n "checking whether the linker provides working __ehdr_start... " >&6; }
+-if ${libc_cv_ehdr_start+:} false; then :
+- $as_echo_n "(cached) " >&6
+-else
+-
+-old_CFLAGS="$CFLAGS"
+-old_LDFLAGS="$LDFLAGS"
+-old_LIBS="$LIBS"
+-CFLAGS="$CFLAGS -fPIC"
+-LDFLAGS="$LDFLAGS -nostdlib -nostartfiles -shared $no_ssp"
+-LIBS=
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h. */
+-
+-typedef struct {
+- char foo;
+- long val;
+-} Ehdr;
+-extern const Ehdr __ehdr_start __attribute__ ((visibility ("hidden")));
+-long ehdr (void) { return __ehdr_start.val; }
+-
+-_ACEOF
+-if ac_fn_c_try_link "$LINENO"; then :
+- if $READELF -r conftest | grep -F __ehdr_start >/dev/null; then
+- libc_cv_ehdr_start=broken
+- else
+- libc_cv_ehdr_start=yes
+- fi
+-else
+- libc_cv_ehdr_start=no
+-fi
+-rm -f core conftest.err conftest.$ac_objext \
+- conftest$ac_exeext conftest.$ac_ext
+-CFLAGS="$old_CFLAGS"
+-LDFLAGS="$old_LDFLAGS"
+-LIBS="$old_LIBS"
+-
+-fi
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_ehdr_start" >&5
+-$as_echo "$libc_cv_ehdr_start" >&6; }
+-if test "$libc_cv_ehdr_start" = yes; then
+- $as_echo "#define HAVE_EHDR_START 1" >>confdefs.h
+-
+-elif test "$libc_cv_ehdr_start" = broken; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: WARNING: linker is broken -- you should upgrade" >&5
+-$as_echo "$as_me: WARNING: linker is broken -- you should upgrade" >&2;}
+-fi
+-
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether the assembler requires one version per symbol" >&5
+ $as_echo_n "checking whether the assembler requires one version per symbol... " >&6; }
+ if ${libc_cv_symver_needs_alias+:} false; then :
+diff --git a/configure.ac b/configure.ac
+index 34ecbba..af47cd5 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -1662,40 +1662,6 @@ if test $libc_cv_predef_fortify_source = yes; then
+ fi
+ AC_SUBST(CPPUNDEFS)
+
+-# Some linkers on some architectures support __ehdr_start but with
+-# bugs. Make sure usage of it does not create relocations in the
+-# output (as the linker should resolve them all for us).
+-AC_CACHE_CHECK([whether the linker provides working __ehdr_start],
+- libc_cv_ehdr_start, [
+-old_CFLAGS="$CFLAGS"
+-old_LDFLAGS="$LDFLAGS"
+-old_LIBS="$LIBS"
+-CFLAGS="$CFLAGS -fPIC"
+-LDFLAGS="$LDFLAGS -nostdlib -nostartfiles -shared $no_ssp"
+-LIBS=
+-AC_LINK_IFELSE([AC_LANG_SOURCE([
+-typedef struct {
+- char foo;
+- long val;
+-} Ehdr;
+-extern const Ehdr __ehdr_start __attribute__ ((visibility ("hidden")));
+-long ehdr (void) { return __ehdr_start.val; }
+-])],
+- [if $READELF -r conftest | grep -F __ehdr_start >/dev/null; then
+- libc_cv_ehdr_start=broken
+- else
+- libc_cv_ehdr_start=yes
+- fi], [libc_cv_ehdr_start=no])
+-CFLAGS="$old_CFLAGS"
+-LDFLAGS="$old_LDFLAGS"
+-LIBS="$old_LIBS"
+-])
+-if test "$libc_cv_ehdr_start" = yes; then
+- AC_DEFINE([HAVE_EHDR_START])
+-elif test "$libc_cv_ehdr_start" = broken; then
+- AC_MSG_WARN([linker is broken -- you should upgrade])
+-fi
+-
+ dnl Starting with binutils 2.35, GAS can attach multiple symbol versions
+ dnl to one symbol (PR 23840).
+ AC_CACHE_CHECK(whether the assembler requires one version per symbol,
+diff --git a/elf/rtld.c b/elf/rtld.c
+index d733359..878e648 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -1684,21 +1684,16 @@ dl_main (const ElfW(Phdr) *phdr,
+ if (GLRO(dl_use_load_bias) == (ElfW(Addr)) -2)
+ GLRO(dl_use_load_bias) = main_map->l_addr == 0 ? -1 : 0;
+
+- /* Set up the program header information for the dynamic linker
+- itself. It is needed in the dl_iterate_phdr callbacks. */
+- const ElfW(Ehdr) *rtld_ehdr;
+-
+ /* Starting from binutils-2.23, the linker will define the magic symbol
+ __ehdr_start to point to our own ELF header if it is visible in a
+ segment that also includes the phdrs. If that's not available, we use
+ the old method that assumes the beginning of the file is part of the
+ lowest-addressed PT_LOAD segment. */
+-#ifdef HAVE_EHDR_START
+ extern const ElfW(Ehdr) __ehdr_start __attribute__ ((visibility ("hidden")));
+- rtld_ehdr = &__ehdr_start;
+-#else
+- rtld_ehdr = (void *) GL(dl_rtld_map).l_map_start;
+-#endif
++
++ /* Set up the program header information for the dynamic linker
++ itself. It is needed in the dl_iterate_phdr callbacks. */
++ const ElfW(Ehdr) *rtld_ehdr = &__ehdr_start;
+ assert (rtld_ehdr->e_ehsize == sizeof *rtld_ehdr);
+ assert (rtld_ehdr->e_phentsize == sizeof (ElfW(Phdr)));
+
+--
+1.8.3.1
+
diff --git a/elf-ld.so-Consider-maybe-existing-hole-between-PT_LO.patch b/elf-ld.so-Consider-maybe-existing-hole-between-PT_LO.patch
new file mode 100644
index 0000000..9ce5870
--- /dev/null
+++ b/elf-ld.so-Consider-maybe-existing-hole-between-PT_LO.patch
@@ -0,0 +1,47 @@
+From 1b296563c92c896f072343b5f19286e8b5942b9e Mon Sep 17 00:00:00 2001
+From: hubin <hubin73@huawei.com>
+Date: Fri, 28 Apr 2023 11:30:47 +0800
+Subject: [PATCH] elf/ld.so: Consider maybe-existing hole between PT_LOAD
+ segments when mmap reserved area
+
+When mmap reserved area do NOT consider existing hole between PT_LOAD
+segments, this will cause reserved virtual address space too small to
+contain all the sections in the PT_LOAD segment. Since the address space
+mapping of subsequent segments is based on the reserved address space,
+each mmap has a MAP_FIXED flag, which will overwrite the reserved
+address space, if the reserved space is too small, these mmap with
+MAP_FIEXED flag will conflict with other address space. e.g. in some
+case, the address sapce in the .bss section(last data segment) conflicts
+with the address space in the heap(maybe other address space) cause the
+program coredump.
+---
+ elf/dl-map-segments-hugepage.h | 10 +++++++++-
+ 1 file changed, 9 insertions(+), 1 deletion(-)
+
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+index b99f726f..218e93a0 100644
+--- a/elf/dl-map-segments-hugepage.h
++++ b/elf/dl-map-segments-hugepage.h
+@@ -47,10 +47,18 @@ __mmap_reserved_area(const struct loadcmd loadcmds[], size_t nloadcmds,
+ const struct loadcmd * c = loadcmds;
+ *maparealen = 0;
+
++ /*
++ * Consider maybe-existing hole between PT_LOAD segments
++ */
+ while (c < &loadcmds[nloadcmds])
+ {
+- *maparealen += ALIGN_UP((c->mapend > c->allocend ? c->mapend : c->allocend), SIZE_2MB) -
++ // c is not the last loadcmd
++ if (c + 1 < &loadcmds[nloadcmds]) {
++ *maparealen += ALIGN_UP((c + 1)->mapstart - c->mapstart, SIZE_2MB);
++ } else {
++ *maparealen += ALIGN_UP((c->mapend > c->allocend ? c->mapend : c->allocend), SIZE_2MB) -
+ ALIGN_DOWN(c->mapstart, SIZE_2MB);
++ }
+ c++;
+ }
+
+--
+2.38.1
+
diff --git a/elf-ld.so-add-MAP_NORESERVE-flag-for-the-first-mmap-2MB-contig.patch b/elf-ld.so-add-MAP_NORESERVE-flag-for-the-first-mmap-2MB-contig.patch
new file mode 100644
index 0000000..b2b62ac
--- /dev/null
+++ b/elf-ld.so-add-MAP_NORESERVE-flag-for-the-first-mmap-2MB-contig.patch
@@ -0,0 +1,33 @@
+
+From 9145e7cc47b0a43620273ec6f3d1bf016618eb62 Mon Sep 17 00:00:00 2001
+From: chenziyang <chenziyang4@huawei.com>
+Date: Sat, 4 Mar 2023 17:13:57 +0800
+Subject: [PATCH 1/2] elf/ld.so: add MAP_NORESERVE flag for the first mmap 2MB contiguous va
+
+If environment only has 50MB hugepage resources, RX PT_LOAD segment
+requires 25MB and RW PT_LOAD segment requires 100MB memory. Before this
+patch, we would exit mmap hugepage because we will try to mmap 125MB
+hugepage. After this change, ld.so will allow RX PT_LOAD to map into 2MB
+hugepage
+
+Signed-off-by: Chen Ziyang<chenziyang4@huawei.com>
+---
+ elf/dl-map-segments-hugepage.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/elf/dl-map-segments-hugepage.h b/elf/dl-map-segments-hugepage.h
+index 5ea89a36..6ab5f939 100644
+--- a/elf/dl-map-segments-hugepage.h
++++ b/elf/dl-map-segments-hugepage.h
+@@ -59,7 +59,7 @@ __mmap_reserved_area(const struct loadcmd loadcmds[], size_t nloadcmds,
+ * This va space can not be munmap in case of multi thread dlopen concurrently
+ */
+ void *map_area_start = __mmap(0, *maparealen, PROT_NONE,
+- MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|(SHFIT_2MB << MAP_HUGE_SHIFT), -1, 0);
++ MAP_PRIVATE|MAP_ANONYMOUS|MAP_HUGETLB|MAP_NORESERVE|(SHFIT_2MB << MAP_HUGE_SHIFT), -1, 0);
+ if (__glibc_unlikely (map_area_start == MAP_FAILED))
+ return MAP_FAILED;
+
+--
+2.33.0
+
diff --git a/elf-ld.so-prohibit-multiple-i-options-and-do-not-allow-i-speci.patch b/elf-ld.so-prohibit-multiple-i-options-and-do-not-allow-i-speci.patch
new file mode 100644
index 0000000..0422a5c
--- /dev/null
+++ b/elf-ld.so-prohibit-multiple-i-options-and-do-not-allow-i-speci.patch
@@ -0,0 +1,54 @@
+
+From f46625e444f2bbab110e217a34abd0898a242c11 Mon Sep 17 00:00:00 2001
+From: chenziyang <chenziyang4@huawei.com>
+Date: Sun, 5 Mar 2023 17:04:09 +0800
+Subject: [PATCH 2/2] prohibit multiple -i options and do not allow -i specify non
+ PT_LOAD segment
+
+Signed-off-by: Chen Ziyang<chenziyang4@huawei.com>
+
+---
+ elf/hugepageedit.c | 13 ++++++++++++-
+ 1 file changed, 12 insertions(+), 1 deletion(-)
+
+diff --git a/elf/hugepageedit.c b/elf/hugepageedit.c
+index 0a44ece6..38b4db70 100644
+--- a/elf/hugepageedit.c
++++ b/elf/hugepageedit.c
+@@ -75,7 +75,7 @@ int main(int argc, char *argv[])
+ size_t length;
+ int exit_status = -1;
+ int i, opt, delete = 0, exec_only = 0, index_set = 0;
+- long index = -1;
++ long index = -1, index_count = 0;
+ while ((opt = getopt(argc, argv, "dxi:")) != -1)
+ {
+ switch (opt)
+@@ -91,6 +91,11 @@ int main(int argc, char *argv[])
+ index_set = 1;
+ if (index < 0)
+ return -1;
++ index_count++;
++ if (index_count > 1) {
++ fprintf(stderr, "too many -i options in command line\n");
++ return -1;
++ }
+ break;
+ default:
+ print_usage();
+@@ -150,6 +155,12 @@ int main(int argc, char *argv[])
+ continue;
+ phdr[i].p_flags |= PF_HUGEPAGE;
+ }
++ } else {
++ if (index_set && index == i) {
++ fprintf(stderr, "Index %ld in -i %s option is not a PT_LOAD segment\n",
++ index, argv[optind]);
++ goto unmap;
++ }
+ }
+ }
+ exit_status = 0;
+--
+2.33.0
+
diff --git a/fix-CVE-2019-1010023.patch b/fix-CVE-2019-1010023.patch
new file mode 100644
index 0000000..efa322e
--- /dev/null
+++ b/fix-CVE-2019-1010023.patch
@@ -0,0 +1,66 @@
+From fe1ffef2eec9c6634a1e9af951eb68f0f5614470 Mon Sep 17 00:00:00 2001
+From: xujing <xujing99@huawei.com>
+Date: Thu, 2 Dec 2021 11:41:46 +0800
+Subject: [PATCH] glibc: fix CVE-2019-1010023
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+| PT_LOAD
+|
+| […] Loadable segment entries in the program header table appear in
+| ascending order, sorted on the p_vaddr member.
+
+http://www.sco.com/developers/gabi/latest/ch5.pheader.html
+
+Some check needed to fix vulnerability in load commands mapping reported by
+
+https://sourceware.org/bugzilla/show_bug.cgi?id=22851
+
+Signed-off-by: lvying <lvying6@huawei.com>
+Signed-off-by: xujing <xujing99@huawei.com>
+---
+ elf/dl-map-segments.h | 9 +++++++++
+ 1 file changed, 9 insertions(+)
+
+diff --git a/elf/dl-map-segments.h b/elf/dl-map-segments.h
+index 084076a2..a41ae73b 100644
+--- a/elf/dl-map-segments.h
++++ b/elf/dl-map-segments.h
+@@ -33,6 +33,7 @@ _dl_map_segments (struct link_map *l, int fd,
+ struct link_map *loader)
+ {
+ const struct loadcmd *c = loadcmds;
++ ElfW(Addr) l_map_end_aligned;
+
+ if (__glibc_likely (type == ET_DYN))
+ {
+@@ -61,6 +62,8 @@ _dl_map_segments (struct link_map *l, int fd,
+ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
+
+ l->l_map_end = l->l_map_start + maplength;
++ l_map_end_aligned = ((l->l_map_end + GLRO(dl_pagesize) - 1)
++ & ~(GLRO(dl_pagesize) - 1));
+ l->l_addr = l->l_map_start - c->mapstart;
+
+ if (has_holes)
+@@ -85,10 +88,16 @@ _dl_map_segments (struct link_map *l, int fd,
+ /* Remember which part of the address space this object uses. */
+ l->l_map_start = c->mapstart + l->l_addr;
+ l->l_map_end = l->l_map_start + maplength;
++ l_map_end_aligned = ((l->l_map_end + GLRO(dl_pagesize) - 1)
++ & ~(GLRO(dl_pagesize) - 1));
+ l->l_contiguous = !has_holes;
+
+ while (c < &loadcmds[nloadcmds])
+ {
++ if ((l->l_addr + c->mapend) > l_map_end_aligned ||
++ (l->l_addr + c->mapstart) < l->l_map_start)
++ return DL_MAP_SEGMENTS_ERROR_MAP_SEGMENT;
++
+ if (c->mapend > c->mapstart
+ /* Map the segment contents from the file. */
+ && (__mmap ((void *) (l->l_addr + c->mapstart),
+--
+2.23.0
+
diff --git a/fix-Segmentation-fault-in-nss-module.patch b/fix-Segmentation-fault-in-nss-module.patch
new file mode 100644
index 0000000..21d75b9
--- /dev/null
+++ b/fix-Segmentation-fault-in-nss-module.patch
@@ -0,0 +1,40 @@
+From f5b9e0f2a8ada29cebeb6e51cbcbea396375ab26 Mon Sep 17 00:00:00 2001
+From: huangyu <huangyu106@huawei.com>
+Date: Wed, 7 Dec 2022 14:35:26 +0800
+Subject: [PATCH] fix Segmentation fault in nss module
+
+Signed-off-by: huangyu <huangyu106@huawei.com>
+---
+ nss/nss_module.c | 2 +-
+ nss/nsswitch.c | 2 +-
+ 2 files changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/nss/nss_module.c b/nss/nss_module.c
+index b28cb94a..bb2807e9 100644
+--- a/nss/nss_module.c
++++ b/nss/nss_module.c
+@@ -352,7 +352,7 @@ nss_load_all_libraries (enum nss_database service)
+ {
+ nss_action_list ni = NULL;
+
+- if (__nss_database_get (service, &ni))
++ if (__nss_database_get (service, &ni) && ni != NULL)
+ while (ni->module != NULL)
+ {
+ __nss_module_load (ni->module);
+diff --git a/nss/nsswitch.c b/nss/nsswitch.c
+index 6b7d4c78..c9d7e372 100644
+--- a/nss/nsswitch.c
++++ b/nss/nsswitch.c
+@@ -133,7 +133,7 @@ libc_hidden_def (__nss_next2)
+ void *
+ __nss_lookup_function (nss_action_list ni, const char *fct_name)
+ {
+- if (ni->module == NULL)
++ if (ni == NULL || ni->module == NULL)
+ return NULL;
+ return __nss_module_get_function (ni->module, fct_name);
+ }
+--
+2.33.0
+
diff --git a/fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch b/fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch
new file mode 100644
index 0000000..2a635da
--- /dev/null
+++ b/fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch
@@ -0,0 +1,55 @@
+From 34d9611a38eceba7adf7270d0318629b4a325f56 Mon Sep 17 00:00:00 2001
+From: Qingqing Li <liqingqing3@huawei.com>
+Date: Mon, 7 Feb 2022 20:37:25 +0800
+Subject: [PATCH] fix tst-glibcsyscalls due to kernel reserved some syscalls
+kernel has resolved kabi_reserved441 ~ kabi_reserved456, and this will cause
+misc/tst-glibcsyscalls failed, errors are like below:
+
+[ 1241s] =====FAIL: misc/tst-glibcsyscalls.out=====
+[ 1241s] info: glibc syscall 'mount_setattr' not known to kernel
+[ 1241s] info: glibc syscall 'epoll_pwait2' not known to kernel
+[ 1241s] info: glibc syscall 'landlock_add_rule' not known to kernel
+[ 1241s] info: glibc syscall 'landlock_restrict_self' not known to kernel
+[ 1241s] info: glibc syscall 'landlock_create_ruleset' not known to kernel
+[ 1241s] error: kernel syscall 'kabi_reserved454' (454) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved442' (442) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved448' (448) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved447' (447) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved450' (450) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved456' (456) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved441' (441) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved443' (443) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved449' (449) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved455' (455) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved444' (444) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved452' (452) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved453' (453) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved445' (445) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved451' (451) not known to glibc
+[ 1241s] error: kernel syscall 'kabi_reserved446' (446) not known to glibc
+
+---
+ sysdeps/unix/sysv/linux/tst-glibcsyscalls.py | 7 ++++---
+ 1 file changed, 4 insertions(+), 3 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py b/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py
+index 4a00bbab..d2d74c9c 100644
+--- a/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py
++++ b/sysdeps/unix/sysv/linux/tst-glibcsyscalls.py
+@@ -67,9 +67,10 @@ def main():
+ # superset of the kernel system call set.
+ if glibc_names.kernel_version >= kernel_version:
+ for name in kernel_constants.keys() - glibc_constants.keys():
+- print("error: kernel syscall {!r} ({}) not known to glibc"
+- .format(name, kernel_constants[name]))
+- errors = 1
++ if 'kabi_reserved' not in name:
++ print("error: kernel syscall {!r} ({}) not known to glibc"
++ .format(name, kernel_constants[name]))
++ errors = 1
+ else:
+ for name in kernel_constants.keys() - glibc_constants.keys():
+ print("warning: kernel syscall {!r} ({}) not known to glibc"
+--
+2.27.0
+
diff --git a/fix_nss_database_check_reload_and_get_memleak.patch b/fix_nss_database_check_reload_and_get_memleak.patch
new file mode 100644
index 0000000..6fc5789
--- /dev/null
+++ b/fix_nss_database_check_reload_and_get_memleak.patch
@@ -0,0 +1,38 @@
+From 66c23fa97a1bf8819051f1c358ae5eb38eeefae2 Mon Sep 17 00:00:00 2001
+From: huangyu <huangyu106@huawei.com>
+Date: Tue, 6 Sep 2022 11:55:40 +0800
+Subject: [PATCH] huawei-fix_nss_database_check_reload_and_get_memleak.patch
+The return nss_database_check_reload_adn_get (local, actions, db) does not check
+whether the local value is empty before invoking the local interface.
+
+Signed-off-by: huangyu <huangyu106@huawei.com>
+---
+ nss/nss_database.c | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/nss/nss_database.c b/nss/nss_database.c
+index 54561f03..a503890a 100644
+--- a/nss/nss_database.c
++++ b/nss/nss_database.c
+@@ -254,6 +254,8 @@ __nss_configure_lookup (const char *dbname, const char *service_line)
+ __nss_database_get (db, &result);
+
+ local = nss_database_state_get ();
++ if (local == NULL)
++ return -1;
+
+ result = __nss_action_parse (service_line);
+ if (result == NULL)
+@@ -399,6 +401,9 @@ nss_database_check_reload_and_get (struct nss_database_state *local,
+ /* Acquire MO is needed because the thread that sets reload_disabled
+ may have loaded the configuration first, so synchronize with the
+ Release MO store there. */
++ if (local == NULL)
++ return false;
++
+ if (atomic_load_acquire (&local->data.reload_disabled))
+ {
+ *result = local->data.services[database_index];
+--
+2.33.0
+
diff --git a/gaiconf_init-Avoid-double-free-in-label-and-preceden.patch b/gaiconf_init-Avoid-double-free-in-label-and-preceden.patch
new file mode 100644
index 0000000..7ebc183
--- /dev/null
+++ b/gaiconf_init-Avoid-double-free-in-label-and-preceden.patch
@@ -0,0 +1,36 @@
+From 77a34079d8f3d63b61543bf3af93043f8674e4c4 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Tue, 3 Aug 2021 21:11:03 +0530
+Subject: [PATCH] gaiconf_init: Avoid double-free in label and precedence lists
+
+labellist and precedencelist could get freed a second time if there
+are allocation failures, so set them to NULL to avoid a double-free.
+
+Reviewed-by: Arjun Shankar <arjun@redhat.com>
+---
+ sysdeps/posix/getaddrinfo.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index 838a68f..43dfc67 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -2008,6 +2008,7 @@ gaiconf_init (void)
+ l = l->next;
+ }
+ free_prefixlist (labellist);
++ labellist = NULL;
+
+ /* Sort the entries so that the most specific ones are at
+ the beginning. */
+@@ -2046,6 +2047,7 @@ gaiconf_init (void)
+ l = l->next;
+ }
+ free_prefixlist (precedencelist);
++ precedencelist = NULL;
+
+ /* Sort the entries so that the most specific ones are at
+ the beginning. */
+--
+1.8.3.1
+
diff --git a/gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch b/gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch
new file mode 100644
index 0000000..2c546ea
--- /dev/null
+++ b/gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch
@@ -0,0 +1,185 @@
+From ff012870b2c02a62598c04daa1e54632e020fd7d Mon Sep 17 00:00:00 2001
+From: Nikita Popov <npv1310@gmail.com>
+Date: Tue, 2 Nov 2021 13:21:42 +0500
+Subject: [PATCH] gconv: Do not emit spurious NUL character in ISO-2022-JP-3
+ (bug 28524)
+
+Bugfix 27256 has introduced another issue:
+In conversion from ISO-2022-JP-3 encoding, it is possible
+to force iconv to emit extra NUL character on internal state reset.
+To do this, it is sufficient to feed iconv with escape sequence
+which switches active character set.
+The simplified check 'data->__statep->__count != ASCII_set'
+introduced by the aforementioned bugfix picks that case and
+behaves as if '\0' character has been queued thus emitting it.
+
+To eliminate this issue, these steps are taken:
+* Restore original condition
+'(data->__statep->__count & ~7) != ASCII_set'.
+It is necessary since bits 0-2 may contain
+number of buffered input characters.
+* Check that queued character is not NUL.
+Similar step is taken for main conversion loop.
+
+Bundled test case follows following logic:
+* Try to convert ISO-2022-JP-3 escape sequence
+switching active character set
+* Reset internal state by providing NULL as input buffer
+* Ensure that nothing has been converted.
+
+Signed-off-by: Nikita Popov <npv1310@gmail.com>
+---
+ iconvdata/Makefile | 5 +++-
+ iconvdata/bug-iconv15.c | 60 +++++++++++++++++++++++++++++++++++++++
+ iconvdata/iso-2022-jp-3.c | 28 ++++++++++++------
+ 3 files changed, 84 insertions(+), 9 deletions(-)
+ create mode 100644 iconvdata/bug-iconv15.c
+
+diff --git a/iconvdata/Makefile b/iconvdata/Makefile
+index c216f959..d5507a04 100644
+--- a/iconvdata/Makefile
++++ b/iconvdata/Makefile
+@@ -1,4 +1,5 @@
+ # Copyright (C) 1997-2021 Free Software Foundation, Inc.
++# Copyright (C) The GNU Toolchain Authors.
+ # This file is part of the GNU C Library.
+
+ # The GNU C Library is free software; you can redistribute it and/or
+@@ -74,7 +75,7 @@ ifeq (yes,$(build-shared))
+ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
+ tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
+ bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
+- bug-iconv13 bug-iconv14
++ bug-iconv13 bug-iconv14 bug-iconv15
+ ifeq ($(have-thread-library),yes)
+ tests += bug-iconv3
+ endif
+@@ -327,6 +328,8 @@ $(objpfx)bug-iconv12.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
+ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
++$(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
++ $(addprefix $(objpfx),$(modules.so))
+
+ $(objpfx)iconv-test.out: run-iconv-test.sh \
+ $(addprefix $(objpfx), $(gconv-modules)) \
+diff --git a/iconvdata/bug-iconv15.c b/iconvdata/bug-iconv15.c
+new file mode 100644
+index 00000000..cc04bd03
+--- /dev/null
++++ b/iconvdata/bug-iconv15.c
+@@ -0,0 +1,60 @@
++/* Bug 28524: Conversion from ISO-2022-JP-3 with iconv
++ may emit spurious NUL character on state reset.
++ Copyright (C) The GNU Toolchain Authors.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stddef.h>
++#include <iconv.h>
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++ char in[] = "\x1b(I";
++ char *inbuf = in;
++ size_t inleft = sizeof (in) - 1;
++ char out[1];
++ char *outbuf = out;
++ size_t outleft = sizeof (out);
++ iconv_t cd;
++
++ cd = iconv_open ("UTF8", "ISO-2022-JP-3");
++ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
++
++ /* First call to iconv should alter internal state.
++ Now, JISX0201_Kana_set is selected and
++ state value != ASCII_set. */
++ TEST_VERIFY (iconv (cd, &inbuf, &inleft, &outbuf, &outleft) != (size_t) -1);
++
++ /* No bytes should have been added to
++ the output buffer at this point. */
++ TEST_VERIFY (outbuf == out);
++ TEST_VERIFY (outleft == sizeof (out));
++
++ /* Second call shall emit spurious NUL character in unpatched glibc. */
++ TEST_VERIFY (iconv (cd, NULL, NULL, &outbuf, &outleft) != (size_t) -1);
++
++ /* No characters are expected to be produced. */
++ TEST_VERIFY (outbuf == out);
++ TEST_VERIFY (outleft == sizeof (out));
++
++ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/iconvdata/iso-2022-jp-3.c b/iconvdata/iso-2022-jp-3.c
+index c8ba88cd..5fc0c0f7 100644
+--- a/iconvdata/iso-2022-jp-3.c
++++ b/iconvdata/iso-2022-jp-3.c
+@@ -1,5 +1,6 @@
+ /* Conversion module for ISO-2022-JP-3.
+ Copyright (C) 1998-2021 Free Software Foundation, Inc.
++ Copyright (C) The GNU Toolchain Authors.
+ This file is part of the GNU C Library.
+ Contributed by Ulrich Drepper <drepper@cygnus.com>, 1998,
+ and Bruno Haible <bruno@clisp.org>, 2002.
+@@ -81,20 +82,31 @@ enum
+ the output state to the initial state. This has to be done during the
+ flushing. */
+ #define EMIT_SHIFT_TO_INIT \
+- if (data->__statep->__count != ASCII_set) \
++ if ((data->__statep->__count & ~7) != ASCII_set) \
+ { \
+ if (FROM_DIRECTION) \
+ { \
+- if (__glibc_likely (outbuf + 4 <= outend)) \
++ uint32_t ch = data->__statep->__count >> 6; \
++ \
++ if (__glibc_unlikely (ch != 0)) \
+ { \
+- /* Write out the last character. */ \
+- *((uint32_t *) outbuf) = data->__statep->__count >> 6; \
+- outbuf += sizeof (uint32_t); \
+- data->__statep->__count = ASCII_set; \
++ if (__glibc_likely (outbuf + 4 <= outend)) \
++ { \
++ /* Write out the last character. */ \
++ put32u (outbuf, ch); \
++ outbuf += 4; \
++ data->__statep->__count &= 7; \
++ data->__statep->__count |= ASCII_set; \
++ } \
++ else \
++ /* We don't have enough room in the output buffer. */ \
++ status = __GCONV_FULL_OUTPUT; \
+ } \
+ else \
+- /* We don't have enough room in the output buffer. */ \
+- status = __GCONV_FULL_OUTPUT; \
++ { \
++ data->__statep->__count &= 7; \
++ data->__statep->__count |= ASCII_set; \
++ } \
+ } \
+ else \
+ { \
+--
+2.23.0
+
diff --git a/gconv_parseconfdir-Fix-memory-leak.patch b/gconv_parseconfdir-Fix-memory-leak.patch
new file mode 100644
index 0000000..de306cc
--- /dev/null
+++ b/gconv_parseconfdir-Fix-memory-leak.patch
@@ -0,0 +1,37 @@
+From 5f9b78fe35d08739b6da1e5b356786d41116c108 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Tue, 3 Aug 2021 21:10:20 +0530
+Subject: [PATCH] gconv_parseconfdir: Fix memory leak
+
+The allocated `conf` would leak if we have to skip over the file due
+to the underlying filesystem not supporting dt_type.
+
+Reviewed-by: Arjun Shankar <arjun@redhat.com>
+---
+ iconv/gconv_parseconfdir.h | 9 ++++-----
+ 1 file changed, 4 insertions(+), 5 deletions(-)
+
+diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
+index a4153e5..2f06268 100644
+--- a/iconv/gconv_parseconfdir.h
++++ b/iconv/gconv_parseconfdir.h
+@@ -153,12 +153,11 @@ gconv_parseconfdir (const char *dir, size_t dir_len)
+ struct stat64 st;
+ if (asprintf (&conf, "%s/%s", buf, ent->d_name) < 0)
+ continue;
+- if (ent->d_type == DT_UNKNOWN
+- && (lstat64 (conf, &st) == -1
+- || !S_ISREG (st.st_mode)))
+- continue;
+
+- found |= read_conf_file (conf, dir, dir_len);
++ if (ent->d_type != DT_UNKNOWN
++ || (lstat64 (conf, &st) != -1 && S_ISREG (st.st_mode)))
++ found |= read_conf_file (conf, dir, dir_len);
++
+ free (conf);
+ }
+ }
+--
+1.8.3.1
+
diff --git a/getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch b/getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch
new file mode 100644
index 0000000..6d258a2
--- /dev/null
+++ b/getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch
@@ -0,0 +1,355 @@
+From 472e799a5f2102bc0c3206dbd5a801765fceb39c Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Fri, 21 Jan 2022 23:32:56 +0530
+Subject: [PATCH] getcwd: Set errno to ERANGE for size == 1 (CVE-2021-3999)
+
+No valid path returned by getcwd would fit into 1 byte, so reject the
+size early and return NULL with errno set to ERANGE. This change is
+prompted by CVE-2021-3999, which describes a single byte buffer
+underflow and overflow when all of the following conditions are met:
+
+- The buffer size (i.e. the second argument of getcwd) is 1 byte
+- The current working directory is too long
+- '/' is also mounted on the current working directory
+
+Sequence of events:
+
+- In sysdeps/unix/sysv/linux/getcwd.c, the syscall returns ENAMETOOLONG
+ because the linux kernel checks for name length before it checks
+ buffer size
+
+- The code falls back to the generic getcwd in sysdeps/posix
+
+- In the generic func, the buf[0] is set to '\0' on line 250
+
+- this while loop on line 262 is bypassed:
+
+ while (!(thisdev == rootdev && thisino == rootino))
+
+ since the rootfs (/) is bind mounted onto the directory and the flow
+ goes on to line 449, where it puts a '/' in the byte before the
+ buffer.
+
+- Finally on line 458, it moves 2 bytes (the underflowed byte and the
+ '\0') to the buf[0] and buf[1], resulting in a 1 byte buffer overflow.
+
+- buf is returned on line 469 and errno is not set.
+
+This resolves BZ #28769.
+
+Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Signed-off-by: Qualys Security Advisory <qsa@qualys.com>
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit 23e0e8f5f1fb5ed150253d986ecccdc90c2dcd5e)
+---
+ NEWS | 6 +
+ sysdeps/posix/getcwd.c | 7 +
+ sysdeps/unix/sysv/linux/Makefile | 7 +-
+ .../unix/sysv/linux/tst-getcwd-smallbuff.c | 241 ++++++++++++++++++
+ 4 files changed, 260 insertions(+), 1 deletion(-)
+ create mode 100644 sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
+
+diff --git a/NEWS b/NEWS
+index b4f81c2668..8d7467d2c1 100644
+--- a/NEWS
++++ b/NEWS
+@@ -20,6 +20,12 @@ Security related changes:
+ function could result in a memory leak and potential access of
+ uninitialized memory. Reported by Qualys.
+
++ CVE-2021-3999: Passing a buffer of size exactly 1 byte to the getcwd
++ function may result in an off-by-one buffer underflow and overflow
++ when the current working directory is longer than PATH_MAX and also
++ corresponds to the / directory through an unprivileged mount
++ namespace. Reported by Qualys.
++
+ The following bugs are resolved with this release:
+
+ [12889] nptl: Fix race between pthread_kill and thread exit
+diff --git a/sysdeps/posix/getcwd.c b/sysdeps/posix/getcwd.c
+index 13680026ff..b6984a382c 100644
+--- a/sysdeps/posix/getcwd.c
++++ b/sysdeps/posix/getcwd.c
+@@ -187,6 +187,13 @@ __getcwd_generic (char *buf, size_t size)
+ size_t allocated = size;
+ size_t used;
+
++ /* A size of 1 byte is never useful. */
++ if (allocated == 1)
++ {
++ __set_errno (ERANGE);
++ return NULL;
++ }
++
+ #if HAVE_MINIMALLY_WORKING_GETCWD
+ /* If AT_FDCWD is not defined, the algorithm below is O(N**2) and
+ this is much slower than the system getcwd (at least on
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index 76ad06361c..9380d3848d 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -331,7 +331,12 @@ sysdep_routines += xstatconv internal_statvfs \
+
+ sysdep_headers += bits/fcntl-linux.h
+
+-tests += tst-fallocate tst-fallocate64 tst-o_path-locks
++tests += \
++ tst-fallocate \
++ tst-fallocate64 \
++ tst-getcwd-smallbuff \
++ tst-o_path-locks \
++# tests
+ endif
+
+ ifeq ($(subdir),elf)
+diff --git a/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
+new file mode 100644
+index 0000000000..d460d6e766
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-getcwd-smallbuff.c
+@@ -0,0 +1,241 @@
++/* Verify that getcwd returns ERANGE for size 1 byte and does not underflow
++ buffer when the CWD is too long and is also a mount target of /. See bug
++ #28769 or CVE-2021-3999 for more context.
++ Copyright The GNU Toolchain Authors.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <fcntl.h>
++#include <intprops.h>
++#include <limits.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++#include <sys/mount.h>
++#include <sys/stat.h>
++#include <sys/types.h>
++#include <sys/wait.h>
++
++#include <sys/socket.h>
++#include <sys/un.h>
++#include <support/check.h>
++#include <support/temp_file.h>
++#include <support/xsched.h>
++#include <support/xunistd.h>
++
++static char *base;
++#define BASENAME "tst-getcwd-smallbuff"
++#define MOUNT_NAME "mpoint"
++static int sockfd[2];
++
++static void
++do_cleanup (void)
++{
++ support_chdir_toolong_temp_directory (base);
++ TEST_VERIFY_EXIT (rmdir (MOUNT_NAME) == 0);
++ free (base);
++}
++
++static void
++send_fd (const int sock, const int fd)
++{
++ struct msghdr msg = {0};
++ union
++ {
++ struct cmsghdr hdr;
++ char buf[CMSG_SPACE (sizeof (int))];
++ } cmsgbuf = {0};
++ struct cmsghdr *cmsg;
++ struct iovec vec;
++ char ch = 'A';
++ ssize_t n;
++
++ msg.msg_control = &cmsgbuf.buf;
++ msg.msg_controllen = sizeof (cmsgbuf.buf);
++
++ cmsg = CMSG_FIRSTHDR (&msg);
++ cmsg->cmsg_len = CMSG_LEN (sizeof (int));
++ cmsg->cmsg_level = SOL_SOCKET;
++ cmsg->cmsg_type = SCM_RIGHTS;
++ memcpy (CMSG_DATA (cmsg), &fd, sizeof (fd));
++
++ vec.iov_base = &ch;
++ vec.iov_len = 1;
++ msg.msg_iov = &vec;
++ msg.msg_iovlen = 1;
++
++ while ((n = sendmsg (sock, &msg, 0)) == -1 && errno == EINTR);
++
++ TEST_VERIFY_EXIT (n == 1);
++}
++
++static int
++recv_fd (const int sock)
++{
++ struct msghdr msg = {0};
++ union
++ {
++ struct cmsghdr hdr;
++ char buf[CMSG_SPACE(sizeof(int))];
++ } cmsgbuf = {0};
++ struct cmsghdr *cmsg;
++ struct iovec vec;
++ ssize_t n;
++ char ch = '\0';
++ int fd = -1;
++
++ vec.iov_base = &ch;
++ vec.iov_len = 1;
++ msg.msg_iov = &vec;
++ msg.msg_iovlen = 1;
++
++ msg.msg_control = &cmsgbuf.buf;
++ msg.msg_controllen = sizeof (cmsgbuf.buf);
++
++ while ((n = recvmsg (sock, &msg, 0)) == -1 && errno == EINTR);
++ if (n != 1 || ch != 'A')
++ return -1;
++
++ cmsg = CMSG_FIRSTHDR (&msg);
++ if (cmsg == NULL)
++ return -1;
++ if (cmsg->cmsg_type != SCM_RIGHTS)
++ return -1;
++ memcpy (&fd, CMSG_DATA (cmsg), sizeof (fd));
++ if (fd < 0)
++ return -1;
++ return fd;
++}
++
++static int
++child_func (void * const arg)
++{
++ xclose (sockfd[0]);
++ const int sock = sockfd[1];
++ char ch;
++
++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1);
++ TEST_VERIFY_EXIT (ch == '1');
++
++ if (mount ("/", MOUNT_NAME, NULL, MS_BIND | MS_REC, NULL))
++ FAIL_EXIT1 ("mount failed: %m\n");
++ const int fd = xopen ("mpoint",
++ O_RDONLY | O_PATH | O_DIRECTORY | O_NOFOLLOW, 0);
++
++ send_fd (sock, fd);
++ xclose (fd);
++
++ TEST_VERIFY_EXIT (read (sock, &ch, 1) == 1);
++ TEST_VERIFY_EXIT (ch == 'a');
++
++ xclose (sock);
++ return 0;
++}
++
++static void
++update_map (char * const mapping, const char * const map_file)
++{
++ const size_t map_len = strlen (mapping);
++
++ const int fd = xopen (map_file, O_WRONLY, 0);
++ xwrite (fd, mapping, map_len);
++ xclose (fd);
++}
++
++static void
++proc_setgroups_write (const long child_pid, const char * const str)
++{
++ const size_t str_len = strlen(str);
++
++ char setgroups_path[sizeof ("/proc//setgroups") + INT_STRLEN_BOUND (long)];
++
++ snprintf (setgroups_path, sizeof (setgroups_path),
++ "/proc/%ld/setgroups", child_pid);
++
++ const int fd = open (setgroups_path, O_WRONLY);
++
++ if (fd < 0)
++ {
++ TEST_VERIFY_EXIT (errno == ENOENT);
++ FAIL_UNSUPPORTED ("/proc/%ld/setgroups not found\n", child_pid);
++ }
++
++ xwrite (fd, str, str_len);
++ xclose(fd);
++}
++
++static char child_stack[1024 * 1024];
++
++int
++do_test (void)
++{
++ base = support_create_and_chdir_toolong_temp_directory (BASENAME);
++
++ xmkdir (MOUNT_NAME, S_IRWXU);
++ atexit (do_cleanup);
++
++ TEST_VERIFY_EXIT (socketpair (AF_UNIX, SOCK_STREAM, 0, sockfd) == 0);
++ pid_t child_pid = xclone (child_func, NULL, child_stack,
++ sizeof (child_stack),
++ CLONE_NEWUSER | CLONE_NEWNS | SIGCHLD);
++
++ xclose (sockfd[1]);
++ const int sock = sockfd[0];
++
++ char map_path[sizeof ("/proc//uid_map") + INT_STRLEN_BOUND (long)];
++ char map_buf[sizeof ("0 1") + INT_STRLEN_BOUND (long)];
++
++ snprintf (map_path, sizeof (map_path), "/proc/%ld/uid_map",
++ (long) child_pid);
++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getuid());
++ update_map (map_buf, map_path);
++
++ proc_setgroups_write ((long) child_pid, "deny");
++ snprintf (map_path, sizeof (map_path), "/proc/%ld/gid_map",
++ (long) child_pid);
++ snprintf (map_buf, sizeof (map_buf), "0 %ld 1", (long) getgid());
++ update_map (map_buf, map_path);
++
++ TEST_VERIFY_EXIT (send (sock, "1", 1, MSG_NOSIGNAL) == 1);
++ const int fd = recv_fd (sock);
++ TEST_VERIFY_EXIT (fd >= 0);
++ TEST_VERIFY_EXIT (fchdir (fd) == 0);
++
++ static char buf[2 * 10 + 1];
++ memset (buf, 'A', sizeof (buf));
++
++ /* Finally, call getcwd and check if it resulted in a buffer underflow. */
++ char * cwd = getcwd (buf + sizeof (buf) / 2, 1);
++ TEST_VERIFY (cwd == NULL);
++ TEST_VERIFY (errno == ERANGE);
++
++ for (int i = 0; i < sizeof (buf); i++)
++ if (buf[i] != 'A')
++ {
++ printf ("buf[%d] = %02x\n", i, (unsigned int) buf[i]);
++ support_record_failure ();
++ }
++
++ TEST_VERIFY_EXIT (send (sock, "a", 1, MSG_NOSIGNAL) == 1);
++ xclose (sock);
++ TEST_VERIFY_EXIT (xwaitpid (child_pid, NULL, 0) == child_pid);
++
++ return 0;
++}
++
++#define CLEANUP_HANDLER do_cleanup
++#include <support/test-driver.c>
+--
+2.27.0
+
diff --git a/gethosts-Remove-unused-argument-_type.patch b/gethosts-Remove-unused-argument-_type.patch
new file mode 100644
index 0000000..1fb60e7
--- /dev/null
+++ b/gethosts-Remove-unused-argument-_type.patch
@@ -0,0 +1,44 @@
+From b17e842a60819098d2a203ecc8b8371b7e1d6c65 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Wed, 4 Aug 2021 02:21:01 +0530
+Subject: [PATCH] gethosts: Remove unused argument _type
+
+The generated code is unchanged.
+---
+ sysdeps/posix/getaddrinfo.c | 6 +++---
+ 1 file changed, 3 insertions(+), 3 deletions(-)
+
+diff --git a/sysdeps/posix/getaddrinfo.c b/sysdeps/posix/getaddrinfo.c
+index 43dfc67..9f1cde2 100644
+--- a/sysdeps/posix/getaddrinfo.c
++++ b/sysdeps/posix/getaddrinfo.c
+@@ -239,7 +239,7 @@ convert_hostent_to_gaih_addrtuple (const struct addrinfo *req,
+ return true;
+ }
+
+-#define gethosts(_family, _type) \
++#define gethosts(_family) \
+ { \
+ struct hostent th; \
+ char *localcanon = NULL; \
+@@ -829,7 +829,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ if (req->ai_family == AF_INET6
+ || req->ai_family == AF_UNSPEC)
+ {
+- gethosts (AF_INET6, struct in6_addr);
++ gethosts (AF_INET6);
+ no_inet6_data = no_data;
+ inet6_status = status;
+ }
+@@ -841,7 +841,7 @@ gaih_inet (const char *name, const struct gaih_service *service,
+ know we are not going to need them. */
+ && ((req->ai_flags & AI_ALL) || !got_ipv6)))
+ {
+- gethosts (AF_INET, struct in_addr);
++ gethosts (AF_INET);
+
+ if (req->ai_family == AF_INET)
+ {
+--
+1.8.3.1
+
diff --git a/glibc-1070416.patch b/glibc-1070416.patch
new file mode 100644
index 0000000..0975e0f
--- /dev/null
+++ b/glibc-1070416.patch
@@ -0,0 +1,38 @@
+Short description: Add syslog.target dependency.
+Author(s): Fedora glibc team <glibc@lists.fedoraproject.org>
+Origin: PATCH
+Bug-Fedora: #1070416
+Upstream status: not-needed
+
+Fedora-specific changes to the nscd.service file.
+See also: glibc-nscd-sysconfig.patch.
+
+--- a/nscd/nscd.service
++++ b/nscd/nscd.service
+@@ -2,6 +2,7 @@
+
+ [Unit]
+ Description=Name Service Cache Daemon
++After=syslog.target
+
+ [Service]
+ Type=forking
+@@ -17,3 +18,4 @@
+
+ [Install]
+ WantedBy=multi-user.target
++Also=nscd.socket
+diff --git a/nscd/nscd.socket b/nscd/nscd.socket
+new file mode 100644
+index 0000000..7e512d5
+--- /dev/null
++++ b/nscd/nscd.socket
+@@ -0,0 +1,8 @@
++[Unit]
++Description=Name Service Cache Daemon Socket
++
++[Socket]
++ListenDatagram=/var/run/nscd/socket
++
++[Install]
++WantedBy=sockets.target
diff --git a/glibc-bench-compare b/glibc-bench-compare
new file mode 100644
index 0000000..84e3aba
--- /dev/null
+++ b/glibc-bench-compare
@@ -0,0 +1,153 @@
+#!/usr/bin/bash
+# This script can be invoked as follows:
+#
+# glibc-bench-compare [options] <BUILD> [BUILD]
+#
+# Options may be one of the following:
+#
+# -t The BUILD arguments are task ids and not a version-release string
+# -a ARCH Do comparison for ARCH architecture
+#
+# If any of the above options are given, both BUILD arguments must be given.
+# Otherwise, if only one BUILD is specified, then it is compared against the
+# installed glibc.
+
+# Silence the pushd/popd messages
+pushd() {
+ command pushd "$@" > /dev/null 2>&1
+}
+
+popd() {
+ command popd "$@" > /dev/null 2>&1
+}
+
+# Clean up any downloaded files before we exit
+trap "rm -rf /tmp/glibc-bench-compare.$BASHPID.*" EXIT
+
+task=0
+arch=$(uname -i)
+options=0
+path=0
+installed=
+
+# Look for any commandline options
+while getopts ":tpa:" opt; do
+ case $opt in
+ p)
+ path=1
+ ;;
+ t)
+ task=1
+ options=1
+ echo "Not implemented."
+ exit 1
+ ;;
+ a)
+ arch=$OPTARG
+ options=1
+ ;;
+ *)
+ ;;
+ esac
+done
+
+# Done, now shift all option arguments out.
+shift $((OPTIND-1))
+
+if [ $# -gt 2 ] || [ $# -eq 0 ] || [ $# -lt 2 -a $options -eq 1 ]; then
+ echo "Usage: $0 [OPTIONS] <old> [new]"
+ echo
+ echo "OPTIONS:"
+ echo -e "\t-t\tCompare two brew tasks"
+ echo -e "\t-a ARCH\tGet rpms for the ARCH architecture"
+ echo -e "\t-p\tCompare built rpms in two paths."
+ echo -e "\t\tThis minimally needs glibc, glibc-common and glibc-benchtests"
+ exit 1
+fi
+
+if [ -z $2 ]; then
+ new="$1"
+ old=$(rpm --queryformat "%{VERSION}-%{RELEASE}\n" -q glibc | head -1)
+ installed=$old
+else
+ new="$2"
+ old="$1"
+fi
+
+decompress_rpms() {
+ # We were given a path to the rpms. Figure out the version-release and
+ # decompress the rpms.
+ if [ -n $1 ]; then
+ vr=$(rpm --queryformat="%{VERSION}-%{RELEASE}" -qp $1/glibc-2*.rpm | head -1)
+ mkdir $vr && pushd $vr
+ fi
+
+ for r in $1*.rpm; do
+ ( rpm2cpio $r | cpio -di ) > /dev/null
+ done
+
+ if [ -n $1 ]; then
+ popd
+ echo $vr
+ fi
+}
+
+# Get rpms for a build and decompress them
+get_build() {
+ echo "Processing build $1"
+ mkdir $1 && pushd $1
+ brew buildinfo "glibc-$1" |
+ sed -n -e "s|/mnt/koji\(.\+$arch.\+\)|http://kojipkgs.fedoraproject.org\1|p" |
+ while read url; do
+ echo "Downloading $url"
+ wget -q $url
+ done
+ decompress_rpms
+
+ echo "Removing rpms"
+ rm -f $1/*.rpm
+
+ popd
+}
+
+# Run benchmarks for a build
+run_bench() {
+ if [ -z $1 ]; then
+ make DETAILED=1 ver=$installed prefix= -f /usr/libexec/glibc-benchtests/bench.mk bench
+ else
+ make DETAILED=1 ver=$1 prefix=$PWD -f $1/usr/libexec/glibc-benchtests/bench.mk bench
+ fi
+}
+
+# Get absolute paths if needed, since we will change into the working directory
+# next.
+if [ $path -eq 1 ]; then
+ old_path=$(realpath $old)/
+ new_path=$(realpath $new)/
+fi
+
+tmpdir=$(mktemp -p /tmp -d glibc-bench-compare.$$.XXXX)
+pushd $tmpdir
+
+# Get both builds.
+if [ $path -eq 0 ]; then
+ if [ -z $installed ]; then
+ get_build $old
+ fi
+ get_build $new
+else
+ old=$(decompress_rpms $old_path)
+ new=$(decompress_rpms $new_path)
+fi
+
+# make bench for each of those.
+if [ -z $installed ]; then
+ run_bench $old
+else
+ run_bench
+fi
+run_bench $new
+
+# Now run the comparison script.
+$old/usr/libexec/glibc-benchtests/compare_bench.py $old/usr/libexec/glibc-benchtests/benchout.schema.json \
+ bench.$old.out bench.$new.out
diff --git a/glibc.spec b/glibc.spec
new file mode 100644
index 0000000..1cb9711
--- /dev/null
+++ b/glibc.spec
@@ -0,0 +1,2284 @@
+%global __requires_exclude GLIBC_PRIVATE
+%global __provides_exclude GLIBC_PRIVATE
+
+%define rpm_ver_major %(eval "echo `rpm -q rpm |cut -d '-' -f2 |cut -d. -f1`")
+%define rpm_ver_minor %(eval "echo `rpm -q rpm |cut -d '-' -f2 |cut -d. -f2`")
+%define rpm_version_ge_412 %(eval "if [ %{rpm_ver_major} -gt 4 -o %{rpm_ver_major} -eq 4 -a %{rpm_ver_minor} -ge 12 ]; then echo 1; else echo 0; fi")
+%define gcc_version %(eval "echo `gcc --version |head -1 |awk '{print $3}' |awk -F '.' '{print $1}'`")
+##############################################################################
+# We support the following options:
+# --with/--without,
+# * testsuite
+# - Running the testsuite. It must run for production builds.
+# - Default: Always run the testsuite.
+# * benchtests
+# - Running and building benchmark subpackage.
+# - Default: Always build the benchtests.
+# * bootstrap
+# - Bootstrapping the package.
+# - Default: Not bootstrapping.
+# * werror
+# - Build with -Werror
+# - Default: Enable using -Werror
+# * docs
+# - Build with documentation and the required dependencies.
+# - Default: Always build documentation.
+# * valgrind
+# - Run smoke tests with valgrind to verify dynamic loader.
+# - Default: Always run valgrind tests if there is architecture support.
+##############################################################################
+%bcond_with benchtests
+%bcond_with bootstrap
+%ifarch ppc64le
+%bcond_with testsuite
+%bcond_with werror
+%else
+%bcond_without testsuite
+%bcond_without werror
+%endif
+%bcond_without docs
+%ifarch x86_64 aarch64
+%bcond_without compat_2_17
+%endif
+
+%ifarch %{valgrind_arches}
+%bcond_without valgrind
+%else
+%bcond_with valgrind
+%endif
+
+%if %{with bootstrap}
+%undefine with_benchtests
+%undefine with_werror
+%undefine with_docs
+%undefine with_valgrind
+%endif
+
+# Only some architectures have static PIE support
+%define pie_arches %{ix86} x86_64 aarch64 loongarch64
+
+%define enablekernel 3.2
+%define target %{_target_cpu}-%{_vendor}-linux
+%ifarch %{arm}
+%define target %{_target_cpu}-%{_vendor}-linuxeabi
+%endif
+%define x86_arches %{ix86} x86_64
+%define all_license LGPLv2+ and LGPLv2+ with exceptions and GPLv2+ and GPLv2+ with exceptions and BSD and Inner-Net and ISC and Public Domain and GFDL
+%define GCC gcc
+%define GXX g++
+##############################################################################
+# glibc - The GNU C Library (glibc) core package.
+##############################################################################
+Name: glibc
+Version: 2.34
+Release: 156
+Summary: The GNU libc libraries
+License: %{all_license}
+URL: http://www.gnu.org/software/glibc/
+
+Source0: https://ftp.gnu.org/gnu/glibc/%{name}-%{version}.tar.xz
+Source1: nscd.conf
+Source2: nsswitch.conf
+Source3: bench.mk
+Source4: glibc-bench-compare
+Source5: LanguageList
+Source6: LicenseList
+Source7: replace_same_file_to_hard_link.py
+
+%if %{with testsuite}
+Source8: testsuite_whitelist
+%endif
+
+Patch1: glibc-1070416.patch
+Patch2: backport-CVE-2021-38604-0001-librt-add-test-bug-28213.patch
+Patch3: backport-CVE-2021-38604-0002-librt-fix-NULL-pointer-dereference-bug-28213.patch
+Patch4: copy_and_spawn_sgid-Avoid-double-calls-to-close.patch
+Patch5: gaiconf_init-Avoid-double-free-in-label-and-preceden.patch
+Patch6: gconv_parseconfdir-Fix-memory-leak.patch
+Patch7: gethosts-Remove-unused-argument-_type.patch
+Patch8: iconv_charmap-Close-output-file-when-done.patch
+Patch9: ldconfig-avoid-leak-on-empty-paths-in-config-file.patch
+Patch10: Linux-Fix-fcntl-ioctl-prctl-redirects-for-_TIME_BITS.patch
+Patch11: nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch
+Patch12: rt-Set-the-correct-message-queue-for-tst-mqueue10.patch
+Patch13: 1-5-AArch64-Improve-A64FX-memset-for-small-sizes.patch
+Patch14: 2-5-AArch64-Improve-A64FX-memset-for-large-sizes.patch
+Patch15: 3-5-AArch64-Improve-A64FX-memset-for-remaining-bytes.patch
+Patch16: 4-5-AArch64-Improve-A64FX-memset-by-removing-unroll3.patch
+Patch17: 5-5-AArch64-Improve-A64FX-memset-medium-loops.patch
+Patch18: elf-Unconditionally-use-__ehdr_start.patch
+Patch19: aarch64-Make-elf_machine_-load_address-dynamic-robus.patch
+Patch20: mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch
+Patch21: time-Fix-overflow-itimer-tests-on-32-bit-systems.patch
+Patch22: arm-Simplify-elf_machine_-load_address-dynamic.patch
+Patch23: elf-Drop-elf-tls-macros.h-in-favor-of-__thread-and-t.patch
+Patch24: elf-Fix-missing-colon-in-LD_SHOW_AUXV-output-BZ-2825.patch
+Patch25: Remove-sysdeps-tls-macros.h.patch
+Patch26: riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch
+Patch27: x86_64-Simplify-elf_machine_-load_address-dynamic.patch
+Patch28: x86-fix-Autoconf-caching-of-instruction-support-chec.patch
+Patch29: Update-string-test-memmove.c-to-cover-16KB-copy.patch
+Patch30: x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch
+Patch31: mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch
+Patch32: rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch
+Patch33: Use-__executable_start-as-the-lowest-address-for-pro.patch
+Patch34: x86-64-Use-testl-to-check-__x86_string_control.patch
+Patch35: AArch64-Update-A64FX-memset-not-to-degrade-at-16KB.patch
+Patch36: support-Add-support_wait_for_thread_exit.patch
+Patch37: nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch
+Patch38: nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch
+Patch39: nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch
+Patch40: nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch
+Patch41: nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch
+Patch42: nptl-pthread_kill-must-send-signals-to-a-specific-th.patch
+Patch43: iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch
+Patch44: gconv-Do-not-emit-spurious-NUL-character-in-ISO-2022.patch
+Patch45: elf-Avoid-deadlock-between-pthread_create-and-ctors-.patch
+Patch46: ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch
+Patch47: ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch
+Patch48: Avoid-warning-overriding-recipe-for-.-tst-ro-dynamic.patch
+Patch49: posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch
+Patch50: Linux-Simplify-__opensock-and-fix-race-condition-BZ-.patch
+Patch51: linux-Simplify-get_nprocs.patch
+Patch52: misc-Add-__get_nprocs_sched.patch
+Patch53: linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch
+Patch54: pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch
+Patch55: support-Add-support_open_dev_null_range.patch
+Patch56: Use-support_open_dev_null_range-io-tst-closefrom-mis.patch
+Patch57: Fix-failing-nss-tst-nss-files-hosts-long-with-local-.patch
+Patch58: nptl-Add-one-more-barrier-to-nptl-tst-create1.patch
+Patch59: io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch
+Patch60: Do-not-define-tgmath.h-fmaxmag-fminmag-macros-for-C2.patch
+Patch61: ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch
+Patch62: elf-Replace-nsid-with-args.nsid-BZ-27609.patch
+Patch63: support-Also-return-fd-when-it-is-0.patch
+Patch64: elf-Earlier-missing-dynamic-segment-check-in-_dl_map.patch
+Patch65: Handle-NULL-input-to-malloc_usable_size-BZ-28506.patch
+Patch66: intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch
+Patch67: linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch
+Patch68: nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch
+Patch69: nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch
+Patch70: timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch
+Patch71: AArch64-Check-for-SVE-in-ifuncs-BZ-28744.patch
+Patch72: Fix-subscript-error-with-odd-TZif-file-BZ-28338.patch
+Patch73: timezone-handle-truncated-timezones-from-tzcode-2021.patch
+Patch74: timezone-test-case-for-BZ-28707.patch
+Patch75: socket-Add-the-__sockaddr_un_set-function.patch
+Patch76: CVE-2022-23219-Buffer-overflow-in-sunrpc-clnt_create.patch
+Patch77: sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch
+Patch78: CVE-2022-23218-Buffer-overflow-in-sunrpc-svcunix_cre.patch
+Patch79: support-Add-check-for-TID-zero-in-support_wait_for_t.patch
+Patch80: support-Add-helpers-to-create-paths-longer-than-PATH.patch
+Patch81: stdlib-Sort-tests-in-Makefile.patch
+Patch82: stdlib-Fix-formatting-of-tests-list-in-Makefile.patch
+Patch83: realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch
+Patch84: tst-realpath-toolong-Fix-hurd-build.patch
+Patch85: getcwd-Set-errno-to-ERANGE-for-size-1-CVE-2021-3999.patch
+Patch86: Linux-Detect-user-namespace-support-in-io-tst-getcwd.patch
+Patch87: Disable-debuginfod-in-printer-tests-BZ-28757.patch
+Patch88: i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch
+Patch89: x86-use-default-cache-size-if-it-cannot-be-determine.patch
+Patch90: x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch
+Patch91: x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch
+Patch92: linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch
+Patch93: elf-Sort-tests-and-modules-names.patch
+Patch94: elf-Add-a-comment-after-trailing-backslashes.patch
+Patch95: elf-Makefile-Reflow-and-sort-most-variable-assignmen.patch
+Patch96: Fix-glibc-2.34-ABI-omission-missing-GLIBC_2.34-in-dy.patch
+Patch97: x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch
+Patch98: x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch
+Patch99: support-Add-support_socket_so_timestamp_time64.patch
+Patch100: linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch
+Patch101: Linux-Only-generate-64-bit-timestamps-for-64-bit-tim.patch
+Patch102: socket-Do-not-use-AF_NETLINK-in-__opensock.patch
+Patch103: tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch
+Patch104: linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch
+Patch105: linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch
+Patch106: rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch
+Patch107: rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch
+Patch108: rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch
+Patch109: rseq-nptl-Add-rseq-registration.patch
+Patch110: rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch
+Patch111: rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch
+Patch112: rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch
+Patch113: rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch
+Patch114: rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch
+Patch115: x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch
+Patch116: x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch
+Patch117: x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch
+Patch118: Add-PTRACE_GET_RSEQ_CONFIGURATION-from-Linux-5.13-to.patch
+Patch119: malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch
+Patch120: malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch
+Patch121: malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch
+Patch122: malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch
+Patch123: malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch
+Patch124: malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch
+Patch125: malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch
+Patch126: localedef-Handle-symbolic-links-when-generating-loca.patch
+Patch127: libio-Ensure-output-buffer-for-wchars-bug-28828.patch
+Patch128: libio-Flush-only-_IO_str_overflow-must-not-return-EO.patch
+Patch129: linux-Fix-__closefrom_fallback-iterates-until-max-in.patch
+Patch130: nptl-Handle-spurious-EINTR-when-thread-cancellation-.patch
+Patch131: nptl-Fix-pthread_cancel-cancelhandling-atomic-operat.patch
+Patch132: elf-Fix-initial-exec-TLS-access-on-audit-modules-BZ-.patch
+Patch133: posix-glob.c-update-from-gnulib.patch
+Patch134: linux-Fix-fchmodat-with-AT_SYMLINK_NOFOLLOW-for-64-b.patch
+Patch135: linux-Fix-posix_spawn-return-code-if-clone-fails-BZ-.patch
+Patch136: backport-elf-Fix-use-after-free-in-ldconfig-BZ-26779.patch
+Patch137: realpath-Avoid-overwriting-preexisting-error-CVE-2021-3998.patch
+Patch138: Linux-Avoid-closing-1-on-failure-in-__closefrom_fall.patch
+Patch139: Fix-deadlock-when-pthread_atfork-handler-calls-pthre.patch
+Patch140: linux-Fix-mq_timereceive-check-for-32-bit-fallback-c.patch
+Patch141: elf-Fix-compile-error-with-Werror-and-DNDEBUG.patch
+Patch142: dlfcn-Do-not-use-rtld_active-to-determine-ld.so-stat.patch
+Patch143: Remove-_dl_skip_args_internal-declaration.patch
+Patch144: rtld-Use-generic-argv-adjustment-in-ld.so-BZ-23293.patch
+Patch145: rtld-Remove-DL_ARGV_NOT_RELRO-and-make-_dl_skip_args.patch
+Patch146: linux-Add-a-getauxval-test-BZ-23293.patch
+Patch147: aarch64-Move-ld.so-_start-to-separate-file-and-drop-.patch
+Patch148: elf-Fix-DNDEBUG-warning-in-_dl_start_args_adjust.patch
+Patch149: nptl-Fix-___pthread_unregister_cancel_restore-asynch.patch
+Patch150: socket-Fix-mistyped-define-statement-in-socket-sys-s.patch
+Patch151: elf-Call-__libc_early_init-for-reused-namespaces-bug.patch
+Patch152: dlfcn-Pass-caller-pointer-to-static-dlopen-implement.patch
+Patch153: elf-Fix-hwcaps-string-size-overestimation.patch
+Patch154: backport-elf-Fix-alloca-size-in-_dl_debug_vdprintf.patch
+Patch155: backport-elf-tlsdeschtab.h-Add-the-Malloc-return-value-check.patch
+Patch156: backport-Fix-OOB-read-in-stdlib-thousand-grouping-parsing-BZ.patch
+Patch157: backport-elf-Remove-allocate-use-on-_dl_debug_printf.patch
+Patch158: backport-elf-Do-not-completely-clear-reused-namespace-in-dlmo.patch
+Patch159: io-Fix-use-after-free-in-ftw-BZ-26779.patch
+Patch160: backport-x86-Fix-wcsnlen-avx2-page-cross-length-comparison-BZ.patch
+Patch161: gmon-Fix-allocated-buffer-overflow-bug-29444.patch
+Patch162: malloc-Fix-transposed-arguments-in-sysmalloc_mmap_fa.patch
+Patch163: backport-Avoid-use-of-atoi-in-some-places-in-libc.patch
+Patch164: backport-stdlib-Undo-post-review-change-to-16adc58e73f3-BZ-27.patch
+patch165: backport-gmon-improve-mcount-overflow-handling-BZ-27576.patch
+Patch166: backport-gmon-fix-memory-corruption-issues-BZ-30101.patch
+Patch167: backport-posix-Fix-system-blocks-SIGCHLD-erroneously-BZ-30163.patch
+Patch168: backport-nscd-Fix-netlink-cache-invalidation-if-epoll-is-used.patch
+Patch169: backport-nss_dns-In-gaih_getanswer_slice-skip-strange-aliases-bug-12154.patch
+Patch170: backport-sunrpc-Suppress-GCC-Os-warning-on-user2netname.patch
+Patch171: malloc-Fix-Wuse-after-free-warning-in-tst-mallocalig.patch
+Patch172: riscv-align-stack-in-clone-BZ-28702.patch
+Patch173: stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch
+Patch174: Assume-only-FLAG_ELF_LIBC6-suport.patch
+Patch175: elf-Restore-ldconfig-libc6-implicit-soname-logic-BZ-.patch
+Patch176: backport-Add-codepoint_collation-support-for-LC_COLLATE.patch
+Patch177: backport-Add-generic-C.UTF-8-locale-Bug-17318.patch
+Patch178: backport-localedef-Fix-handling-of-empty-mon_decimal_point-Bu.patch
+Patch179: backport-Add-TEST_COMPARE_STRING_WIDE-to-support-check.h.patch
+Patch180: backport-localedata-Adjust-C.UTF-8-to-align-with-C-POSIX.patch
+Patch181: backport-elf-Make-more-functions-available-for-binding-during.patch
+Patch182: backport-elf-fix-handling-of-negative-numbers-in-dl-printf.patch
+Patch183: backport-rtld-properly-handle-root-directory-in-load-path-bug-30435.patch
+Patch184: time-Fix-use-after-free-in-getdate.patch
+Patch185: time-strftime_l-Avoid-an-unbounded-alloca.patch
+Patch186: backport-string-strerror-must-not-return-NULL-bug-30555.patch
+Patch187: backport-CVE-2023-4813.patch
+Patch188: backport-CVE-2023-4806.patch
+Patch189: backport-CVE-2023-5156.patch
+Patch190: backport-CVE-2023-4911.patch
+Patch191: linux-Only-build-fstatat-fallback-if-required.patch
+Patch192: Fix-ununsed-fstatat64_time64_statx.patch
+Patch193: linux-use-statx-for-fstat-if-neither-newfstatat-nor-.patch
+Patch194: io-Do-not-implement-fstat-with-fstatat.patch
+Patch195: backport-posix-Fix-some-crashes-in-wordexp-BZ-18096.patch
+Patch196: backport-elf-Handle-non-directory-name-in-search-path-BZ-3103.patch
+Patch197: backport-Fix-invalid-pointer-dereference-in-wcscpy_chk.patch
+Patch198: backport-Fix-invalid-pointer-dereference-in-wcpcpy_chk.patch
+Patch199: elf-Add-a-way-to-check-if-tunable-is-set-BZ-27069.patch
+Patch200: malloc-Improve-MAP_HUGETLB-with-glibc.malloc.hugetlb.patch
+Patch201: iconv-ISO-2022-CN-EXT-fix-out-of-bound-writes-when-w.patch
+Patch202: backport-resolv_conf-release-lock-on-allocation-failure-bug-30527.patch
+Patch203: backport-CVE-2024-33599-nscd-Stack-based-buffer-overflow-in-netgroup-cache.patch
+Patch204: backport-CVE-2024-33600-nscd-Do-not-send-missing-not-found-response.patch
+Patch205: backport-CVE-2024-33600-nscd-Avoid-null-pointer-crash-after-not-found-response.patch
+Patch206: backport-CVE-2024-33601-CVE-2024-33602-nscd-Use-two-buffer-in-addgetnetgrentX.patch
+Patch207: backport-Use-errval-not-errno-to-guide-cache-update.patch
+Patch208: backport-Skip-unusable-entries-in-first-pass-in-prune_cache.patch
+Patch209: backport-elf-Add-TLS-modid-reuse-test-for-bug-29039.patch
+Patch210: backport-elf-Fix-TLS-modid-reuse-generation-assignment-BZ-290.patch
+Patch211: backport-elf-Check-objname-before-calling-fatal_error.patch
+Patch212: backport-elf-Fix-_dl_debug_vdprintf-to-work-before-self-reloc.patch
+Patch213: backport-elf-ldconfig-should-skip-temporary-files-created-by-.patch
+Patch214: backport-ldconfig-Fixes-for-skipping-temporary-files.patch
+Patch215: backport-elf-Properly-align-PT_LOAD-segments-BZ-28676.patch
+Patch216: backport-stdlib-fix-grouping-verification-with-multi-byte-tho.patch
+Patch217: backport-resolv-fix-non-existing-second-DNS-response-error.patch
+Patch218: backport-mktime-improve-heuristic-for-ca-1986-Indiana-DST.patch
+
+Patch9000: turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
+Patch9001: delete-no-hard-link-to-avoid-all_language-package-to.patch
+Patch9002: 0001-add-base-files-for-libphtread-condition-family.patch
+Patch9003: 0002-add-header-files-for-libphtread_2_17_so.patch
+Patch9004: 0003-add-build-script-and-files-of-libpthread_2_17_so.patch
+Patch9005: 0004-add-two-header-files-with-some-deleted-macros.patch
+Patch9006: 0005-add-pthread-functions_h.patch
+Patch9007: 0006-add-elsion-function-which-moved-to-libc-in-glibc-2.34.patch
+Patch9008: 0007-add-lowlevellock_2_17_c.patch
+Patch9009: 0008-add-pause_nocancel_2_17.patch
+Patch9010: 0009_nptl_2.17_adapt_for_bug_29029.patch
+Patch9011: 0009-add-unwind-with-longjmp.patch
+Patch9012: delete-check-installed-headers-c-and-check-installed.patch
+Patch9013: fix-CVE-2019-1010023.patch
+Patch9014: fix-tst-glibcsyscalls-due-to-kernel-reserved-some-sy.patch
+Patch9015: use-region-to-instead-of-country-for-extract-timezon.patch
+Patch9016: strcmp-delete-align-for-loop_aligned.patch
+Patch9017: 0001-elf-dynamic-linker-load-shared-object-use-hugepage-a.patch
+Patch9018: 0002-elf-ld.so-add-testcase-for-ld.so-load-shared-object-.patch
+Patch9019: 0003-elf-ld.so-use-special-mmap-for-hugepage-to-get-symbo.patch
+Patch9020: malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch
+Patch9021: x86-use-total-l3cache-for-non_temporal_threshold.patch
+Patch9022: login-Add-back-libutil-as-an-empty-library.patch
+Patch9023: malloc-Fix-malloc-debug-for-2.35-onwards.patch
+Patch9024: LoongArch-Port.patch
+Patch9025: 1_6-LoongArch-Optimize-string-functions-memcpy-memmove.patch
+Patch9026: 2_6-LoongArch-Optimize-string-functions-strchr-strchrnul.patch
+Patch9027: 3_6-LoongArch-Optimize-string-function-memset.patch
+Patch9028: 4_6-LoongArch-Optimize-string-functions-strcmp-strncmp.patch
+Patch9029: 5_6-LoongArch-Optimize-string-function-strcpy.patch
+Patch9030: 6_6-LoongArch-Optimize-string-functions-strlen-strnlen.patch
+Patch9031: math-Fix-asin-and-acos-invalid-exception-with-old-gc.patch
+Patch9032: LoongArch-Fix-ptr-mangling-demangling-and-SHMLBA.patch
+Patch9033: LoongArch-Add-static-PIE-support.patch
+Patch9034: LoongArch-Fix-the-condition-to-use-PC-relative-addre.patch
+Patch9035: LoongArch-Further-refine-the-condition-to-enable-sta.patch
+Patch9036: add-pthread_cond_clockwait-GLIBC_2_28.patch
+Patch9037: 0001-ld.so-support-ld.so-mmap-hugetlb-hugepage-according-.patch
+Patch9038: 0002-elf-ld.so-keep-compatible-with-the-original-policy-o.patch
+Patch9039: 0003-elf-ld.so-remove-_mmap_hole-when-ld.so-mmap-PT_LOAD-.patch
+Patch9040: elf-ld.so-add-MAP_NORESERVE-flag-for-the-first-mmap-2MB-contig.patch
+Patch9041: elf-ld.so-prohibit-multiple-i-options-and-do-not-allow-i-speci.patch
+Patch9042: elf-ld.so-Consider-maybe-existing-hole-between-PT_LO.patch
+Patch9043: add-GB18030-2022-charmap-BZ-30243.patch
+Patch9044: add-Wl-z-noseparate-code-for-so.patch
+Patch9045: fix-Segmentation-fault-in-nss-module.patch
+Patch9046: fix_nss_database_check_reload_and_get_memleak.patch
+Patch9047: inet-fix-warn-unused-result.patch
+Patch9048: LoongArch-Add-missing-relocation-type-in-elf.h.patch
+Patch9049: Check-the-validity-of-len-before-mmap.patch
+
+Provides: ldconfig rtld(GNU_HASH) bundled(gnulib)
+
+BuildRequires: audit-libs-devel >= 1.1.3, sed >= 3.95, libcap-devel, gettext
+BuildRequires: procps-ng, util-linux, gawk, systemtap-sdt-devel, systemd, python3
+BuildRequires: make >= 4.0, bison >= 2.7, binutils >= 2.30-17, gcc >= 7.2.1-6
+BuildRequires: m4 gcc_secure chrpath
+
+%if %{without bootstrap}
+BuildRequires: gd-devel libpng-devel zlib-devel
+%endif
+
+%if %{with docs}
+BuildRequires: texinfo >= 5.0
+%endif
+
+%if %{without bootstrap}
+BuildRequires: libselinux-devel >= 1.33.4-3
+%endif
+
+%if %{with valgrind}
+BuildRequires: valgrind
+%endif
+
+%if 0%{?_enable_debug_packages}
+BuildRequires: elfutils >= 0.72 rpm >= 4.2-0.56
+%endif
+
+%if %{without bootstrap}
+%if %{with testsuite}
+BuildRequires: gcc-c++ libstdc++-static glibc-devel libidn2
+%endif
+%endif
+
+Requires: glibc-common = %{version}-%{release}
+Requires: glibc-langpack = %{version}-%{release}
+Requires: basesystem
+
+%description
+The GNU C Library project provides the core libraries for the GNU system and
+GNU/Linux systems, as well as many other systems that use Linux as the kernel.
+These libraries provide critical APIs including ISO C11, POSIX.1-2008, BSD,
+OS-specific APIs and more. These APIs include such foundational facilities as
+open, read, write, malloc, printf, getaddrinfo, dlopen, pthread_create, crypt,
+ login, exit and more.
+
+##############################################################################
+# glibc "common" sub-package
+##############################################################################
+%package common
+Summary: Common binaries and locale data for glibc
+Provides: glibc-langpack = %{version}-%{release}
+
+Provides: glibc-langpack-en = %{version}-%{release}
+Provides: glibc-langpack-en%{?_isa} = %{version}-%{release}
+Provides: glibc-langpack-zh = %{version}-%{release}
+Provides: glibc-langpack-zh%{?_isa} = %{version}-%{release}
+
+Requires: %{name} = %{version}-%{release}
+Requires: tzdata >= 2003a
+
+%description common
+The glibc-common package includes common binaries for the GNU libc
+libraries and national language (locale) support. Besides, zh_CN and
+en_US are included.
+
+%transfiletriggerin common -P 2000000 -- /lib /usr/lib /lib64 /usr/lib64
+/sbin/ldconfig
+%end
+
+%transfiletriggerpostun common -P 2000000 -- /lib /usr/lib /lib64 /usr/lib64
+/sbin/ldconfig
+%end
+
+%undefine __brp_ldconfig
+
+##############################################################################
+# glibc "all-langpacks" sub-package
+##############################################################################
+%package all-langpacks
+Summary: All language packs for %{name}.
+Requires: %{name} = %{version}-%{release}
+Requires: %{name}-common = %{version}-%{release}
+Provides: %{name}-langpack = %{version}-%{release}
+Obsoletes: %{name}-minimal-langpack <= 2.28
+
+%{lua:
+-- List the Symbol provided by all-langpacks
+lang_provides = {}
+for line in io.lines(rpm.expand("%{SOURCE5}")) do
+ print(rpm.expand([[
+Provides:]]..line..[[ = %{version}-%{release}
+Obsoletes:]]..line..[[ <= 2.28
+]]))
+end
+}
+
+%description all-langpacks
+The glibc-all-langpacks provides all the glibc-langpacks. Every entry
+includes the basic information required to support the corresponding
+language in your applications.
+
+##############################################################################
+# glibc "locale-source" sub-package
+##############################################################################
+%package locale-source
+Summary: The sources package of locales
+Requires: %{name} = %{version}-%{release}
+Requires: %{name}-common = %{version}-%{release}
+
+%description locale-source
+The locale-source package contains all language packs which are built custom
+locales
+
+##############################################################################
+# glibc "locale-archive" sub-package
+##############################################################################
+%package locale-archive
+Summary: The locale-archive of glibc
+Requires: %{name} = %{version}-%{release}
+Requires: %{name}-common = %{version}-%{release}
+
+%description locale-archive
+The locale-archive sub package contains the locale-archive. In the past,
+this file is provided in "glibc-common".Now, we provide basic language support
+in "glibc-common", but if you need a customized language, you can extract
+it from the "local-archive".
+
+##############################################################################
+# glibc "devel" sub-package
+##############################################################################
+%package devel
+Summary: The devel for %{name}
+Requires: %{name} = %{version}-%{release}
+Requires: libgcc%{_isa}
+Requires(pre): kernel-headers
+Requires(pre): coreutils
+Requires: kernel-headers >= 3.2
+%if 0%{rpm_version_ge_412}
+Requires: libxcrypt-devel%{_isa} >= 4.0.0
+Requires: libxcrypt-static%{?_isa} >= 4.0.0
+%endif
+BuildRequires: kernel-headers >= 3.2
+
+Provides: %{name}-static = %{version}-%{release}
+Provides: %{name}-static%{_isa} = %{version}-%{release}
+Provides: %{name}-headers = %{version}-%{release}
+Provides: %{name}-headers(%{_target_cpu})
+Provides: %{name}-headers%{_isa} = %{version}-%{release}
+
+Obsoletes: %{name}-static <= 2.28
+Obsoletes: %{name}-headers <= 2.28
+
+%description devel
+The glibc-devel package contains the object files necessary for developing
+programs which use the standard C libraries. Besides, it contains the
+headers. Thus, it is necessory to install glibc-devel if you ned develop programs.
+
+##############################################################################
+# glibc "nscd" sub-package
+##############################################################################
+%package -n nscd
+Summary: Name caching service daemon.
+Requires: %{name} = %{version}-%{release}
+%if %{without bootstrap}
+Requires: libselinux >= 1.17.10-1
+%endif
+Requires: audit-libs >= 1.1.3
+Requires(pre): shadow-utils, coreutils
+Requires: systemd
+Requires(postun): shadow-utils
+
+%description -n nscd
+The nscd package is able to daemon caches name service lookups and improve
+the performance with LDAP.
+
+##############################################################################
+# nss modules sub-package
+##############################################################################
+%package -n nss_modules
+Summary: Name Service Switch module using hash-indexed files and Hesiod
+Requires: %{name}%{_isa} = %{version}-%{release}
+Provides: nss_db = %{version}-%{release}
+Provides: nss_db%{_isa} = %{version}-%{release}
+Provides: nss_hesiod = %{version}-%{release}
+Provides: nss_hesiod%{_isa} = %{version}-%{release}
+Obsoletes: nss_db <= 2.28, nss_hesiod <= 2.28
+
+%description -n nss_modules
+This package contains nss_db and nss_hesiod. The former uses hash-indexed files
+to speed up user, group, service, host name, and other NSS-based lookups.The
+latter uses the Domain Name System (DNS) as a source for user, group, and service
+information to follow the Hesiod convention of Project Athena.
+
+##############################################################################
+# nss-devel sub-package
+##############################################################################
+%package nss-devel
+Summary: The devel for directly linking NSS service modules
+Requires: nss_db%{_isa} = %{version}-%{release}
+Requires: nss_hesiod%{_isa} = %{version}-%{release}
+
+%description nss-devel
+This package contains the necessary devel files to compile applications and
+libraries which directly link against NSS modules supplied by glibc. This
+package is rarely used, and in most cases use the glibc-devel package instead.
+
+##############################################################################
+# libnsl subpackage
+##############################################################################
+%package -n libnsl
+Summary: Public client interface for NIS(YP) and NIS+
+Requires: %{name}%{_isa} = %{version}-%{release}
+
+%description -n libnsl
+The libnsl package contains the public client interface for NIS(YP) and NIS+.
+It replaces the NIS library that used to be in glibc.
+
+##############################################################################
+# glibc benchtests sub-package
+##############################################################################
+%if %{with benchtests}
+
+%package benchtests
+Summary: Build benchmarking binaries and scripts for %{name}
+
+%description benchtests
+This package provides built benchmark binaries and scripts which will be used
+to run microbenchmark tests on the system.
+%endif
+
+##############################################################################
+# glibc debugutils sub-package
+##############################################################################
+%package debugutils
+Summary: debug files for %{name}
+Requires: %{name} = %{version}-%{release}
+Provides: %{name}-utils = %{version}-%{release}
+Provides: %{name}-utils%{_isa} = %{version}-%{release}
+
+Obsoletes: %{name}-utils <= 2.28
+
+%description debugutils
+This package provides memusage, a memory usage profiler, mtrace, a memory leak
+tracer and xtrace, a function call tracer, all of which is not necessory for you.
+
+##############################################################################
+# glibc help sub-package
+##############################################################################
+%package help
+Summary: The doc and man for %{name}
+Buildarch: noarch
+Requires: man info
+Requires: %{name} = %{version}-%{release}
+
+%description help
+This package provides all doc,man and info files of %{name}
+
+##############################################################################
+# glibc compat-2.17 sub-package
+##############################################################################
+%if %{with compat_2_17}
+%package compat-2.17
+Summary: provides pthread library with glibc-2.17
+
+%description compat-2.17
+This subpackage to provide the function of the glibc-2.17 pthread library.
+Currently, provide pthread_condition function.
+To keep older applications compatible, glibc-compat-2.17 provides libpthread_nonshared.a
+%endif
+
+##############################################################################
+# Prepare for the build.
+##############################################################################
+%prep
+%autosetup -n %{name}-%{version} -p1
+
+chmod +x benchtests/scripts/*.py scripts/pylint
+
+find . -type f -size 0 -o -name "*.orig" -exec rm -f {} \;
+
+touch `find . -name configure`
+
+touch locale/programs/*-kw.h
+
+##############################################################################
+# Build glibc...
+##############################################################################
+%build
+
+BuildFlags="-O2 -g"
+BuildFlags="$BuildFlags -DNDEBUG"
+
+%ifarch aarch64
+BuildFlags="$BuildFlags -mno-outline-atomics"
+%endif
+
+reference=" \
+ "-Wp,-D_GLIBCXX_ASSERTIONS" \
+ "-fasynchronous-unwind-tables" \
+ "-fstack-clash-protection" \
+ "-funwind-tables" \
+ "-m31" \
+ "-m32" \
+ "-m64" \
+ "-march=haswell" \
+ "-march=i686" \
+ "-march=x86-64" \
+ "-march=z13" \
+ "-march=z14" \
+ "-march=zEC12" \
+ "-mfpmath=sse" \
+ "-msse2" \
+ "-mstackrealign" \
+ "-mtune=generic" \
+ "-mtune=z13" \
+ "-mtune=z14" \
+ "-mtune=zEC12" \
+ "-specs=/usr/lib/rpm/%{_vendor}/%{_vendor}-annobin-cc1" "
+
+for flag in $RPM_OPT_FLAGS $RPM_LD_FLAGS ; do
+ if echo "$reference" | grep -q -F " $flag " ; then
+ BuildFlags="$BuildFlags $flag"
+ fi
+done
+
+%define glibc_make_flags_as ASFLAGS="-g -Wa,--generate-missing-build-notes=yes"
+%define glibc_make_flags %{glibc_make_flags_as}
+
+EnableKernel="--enable-kernel=%{enablekernel}"
+
+builddir=build-%{target}
+rm -rf $builddir
+mkdir $builddir
+pushd $builddir
+../configure CC="%GCC" CXX="%GXX" CFLAGS="$BuildFlags" \
+ --prefix=%{_prefix} \
+ --with-headers=%{_prefix}/include $EnableKernel \
+ --with-nonshared-cflags=-Wp,-D_FORTIFY_SOURCE=2 \
+ --enable-bind-now \
+ --build=%{target} \
+ --enable-stack-protector=strong \
+%ifarch %{pie_arches}
+%if 0%{?gcc_version} >= 8
+ --enable-static-pie \
+%endif
+%endif
+%ifarch %{x86_arches}
+%if 0%{?gcc_version} >= 8
+ --enable-cet \
+%endif
+%endif
+ --enable-tunables \
+ --enable-systemtap \
+%ifarch %{ix86}
+ --disable-multi-arch \
+%endif
+%if %{without werror}
+ --disable-werror \
+%endif
+ --disable-profile \
+%if %{with bootstrap}
+ --without-selinux \
+%endif
+%if 0%{rpm_version_ge_412}
+ --disable-crypt \
+%endif
+ ||
+ { cat config.log; false; }
+
+make %{?_smp_mflags} -O -r %{glibc_make_flags}
+popd
+
+##############################################################################
+# Build libpthread-2.17.so
+##############################################################################
+%if %{with compat_2_17}
+ cd nptl_2_17
+ sh build_libpthread-2.17.so.sh %{_target_cpu} $builddir
+ cd ..
+%endif
+
+##############################################################################
+# Install glibc...
+##############################################################################
+%install
+%ifarch riscv64
+for d in $RPM_BUILD_ROOT%{_libdir} $RPM_BUILD_ROOT/%{_lib}; do
+ mkdir -p $d
+ (cd $d && ln -sf . lp64d)
+done
+%endif
+
+make %{?_smp_mflags} install_root=$RPM_BUILD_ROOT install -C build-%{target}
+
+pushd build-%{target}
+
+make %{?_smp_mflags} install_root=$RPM_BUILD_ROOT \
+ install-locale-files -C ../localedata objdir=`pwd`
+popd
+
+python3 %{SOURCE7} $RPM_BUILD_ROOT/usr/lib/locale
+
+rm -f $RPM_BUILD_ROOT/%{_libdir}/libNoVersion*
+rm -f $RPM_BUILD_ROOT/%{_lib}/libNoVersion*
+rm -f $RPM_BUILD_ROOT/%{_lib}/libnss1-*
+rm -f $RPM_BUILD_ROOT/%{_lib}/libnss-*.so.1
+rm -f $RPM_BUILD_ROOT/{usr/,}sbin/sln
+
+mkdir -p $RPM_BUILD_ROOT/var/cache/ldconfig
+truncate -s 0 $RPM_BUILD_ROOT/var/cache/ldconfig/aux-cache
+
+$RPM_BUILD_ROOT/sbin/ldconfig -N -r $RPM_BUILD_ROOT
+
+# Install info files
+%if %{with docs}
+# Move the info files if glibc installed them into the wrong location.
+if [ -d $RPM_BUILD_ROOT%{_prefix}/info -a "%{_infodir}" != "%{_prefix}/info" ]; then
+ mkdir -p $RPM_BUILD_ROOT%{_infodir}
+ mv -f $RPM_BUILD_ROOT%{_prefix}/info/* $RPM_BUILD_ROOT%{_infodir}
+ rm -rf $RPM_BUILD_ROOT%{_prefix}/info
+fi
+
+# Compress all of the info files.
+gzip -9nvf $RPM_BUILD_ROOT%{_infodir}/libc*
+
+%else
+rm -f $RPM_BUILD_ROOT%{_infodir}/dir
+rm -f $RPM_BUILD_ROOT%{_infodir}/libc.info*
+%endif
+
+# Create all-packages libc.lang
+olddir=`pwd`
+pushd $RPM_BUILD_ROOT%{_prefix}/lib/locale
+rm -f locale-archive
+$olddir/build-%{target}/elf/ld.so \
+ --library-path $olddir/build-%{target}/ \
+ $olddir/build-%{target}/locale/localedef \
+ --alias-file=$olddir/intl/locale.alias \
+ --prefix $RPM_BUILD_ROOT --add-to-archive \
+ eo *_*
+%{find_lang} libc
+# In the past, locale-archive is provided by common.
+# In the current version, locale-archive is provided by locale-archive.
+# Due to the change of the packing mode, the locale-archive fails to be
+# replaced during the upgrade. Therefore, a backup file is required to
+# replace the locale-archive.
+mv locale-archive locale-archive.update
+
+$olddir/build-%{target}/elf/ld.so \
+ --library-path $olddir/build-%{target}/ \
+ $olddir/build-%{target}/locale/localedef \
+ --alias-file=$olddir/intl/locale.alias \
+ --prefix $RPM_BUILD_ROOT --add-to-archive \
+ zh_* en_*
+mv locale-archive locale-archive.default
+popd
+mv $RPM_BUILD_ROOT%{_prefix}/lib/locale/libc.lang .
+
+# Install configuration files for services
+install -p -m 644 %{SOURCE2} $RPM_BUILD_ROOT/etc/nsswitch.conf
+
+# This is for compat-2.17
+%if %{with compat_2_17}
+install -p -m 755 build-%{target}/nptl/libpthread-2.17.so $RPM_BUILD_ROOT%{_libdir}
+# Build an empty libpthread_nonshared.a for compatiliby with applications
+# that have old linker scripts that reference this file.
+ar cr $RPM_BUILD_ROOT/%{_prefix}/%{_lib}/libpthread_nonshared.a
+%endif
+
+# This is for ncsd - in glibc 2.2
+install -m 644 nscd/nscd.conf $RPM_BUILD_ROOT/etc
+mkdir -p $RPM_BUILD_ROOT%{_tmpfilesdir}
+install -m 644 %{SOURCE1} %{buildroot}%{_tmpfilesdir}
+mkdir -p $RPM_BUILD_ROOT/lib/systemd/system
+install -m 644 nscd/nscd.service nscd/nscd.socket $RPM_BUILD_ROOT/lib/systemd/system
+
+# Include ld.so.conf
+echo 'include ld.so.conf.d/*.conf' > $RPM_BUILD_ROOT/etc/ld.so.conf
+truncate -s 0 $RPM_BUILD_ROOT/etc/ld.so.cache
+chmod 644 $RPM_BUILD_ROOT/etc/ld.so.conf
+mkdir -p $RPM_BUILD_ROOT/etc/ld.so.conf.d
+mkdir -p $RPM_BUILD_ROOT/etc/sysconfig
+truncate -s 0 $RPM_BUILD_ROOT/etc/sysconfig/nscd
+truncate -s 0 $RPM_BUILD_ROOT/etc/gai.conf
+
+# Include %{_libdir}/gconv/gconv-modules.cache
+truncate -s 0 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache
+chmod 644 $RPM_BUILD_ROOT%{_libdir}/gconv/gconv-modules.cache
+
+# Remove any zoneinfo files; they are maintained by tzdata.
+rm -rf $RPM_BUILD_ROOT%{_prefix}/share/zoneinfo
+
+touch -r %{SOURCE0} $RPM_BUILD_ROOT/etc/ld.so.conf
+touch -r inet/etc.rpc $RPM_BUILD_ROOT/etc/rpc
+
+# Lastly copy some additional documentation for the packages.
+rm -rf documentation
+mkdir documentation
+cp timezone/README documentation/README.timezone
+cp posix/gai.conf documentation/
+
+%if %{with benchtests}
+# Build benchmark binaries. Ignore the output of the benchmark runs.
+pushd build-%{target}
+make BENCH_DURATION=1 bench-build
+popd
+
+# Copy over benchmark binaries.
+mkdir -p $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests
+cp $(find build-%{target}/benchtests -type f -executable) $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/
+
+#makefile.
+for b in %{SOURCE3} %{SOURCE4}; do
+ cp $b $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/
+done
+
+#comparison scripts.
+for i in benchout.schema.json compare_bench.py import_bench.py validate_benchout.py; do
+ cp benchtests/scripts/$i $RPM_BUILD_ROOT%{_prefix}/libexec/glibc-benchtests/
+done
+%endif
+
+pushd locale
+ln -s programs/*.gperf .
+popd
+
+pushd iconv
+ln -s ../locale/programs/charmap-kw.gperf .
+popd
+
+%if %{with docs}
+rm -f $RPM_BUILD_ROOT%{_infodir}/dir
+%endif
+
+mkdir -p $RPM_BUILD_ROOT/var/{db,run}/nscd
+touch $RPM_BUILD_ROOT/var/{db,run}/nscd/{passwd,group,hosts,services}
+touch $RPM_BUILD_ROOT/var/run/nscd/{socket,nscd.pid}
+
+mkdir -p $RPM_BUILD_ROOT%{_libdir}
+mv -f $RPM_BUILD_ROOT/%{_lib}/lib{pcprofile,memusage}.so \
+ $RPM_BUILD_ROOT%{_libdir}
+
+# Strip all of the installed object files.
+strip -g $RPM_BUILD_ROOT%{_libdir}/*.o
+
+# create a null libpthread static link for compatibility.
+pushd $RPM_BUILD_ROOT%{_prefix}/%{_lib}/
+rm libpthread.a
+ar rc libpthread.a
+popd
+
+for i in $RPM_BUILD_ROOT%{_prefix}/bin/{xtrace,memusage}; do
+%if %{with bootstrap}
+ test -w $i || continue
+%endif
+ sed -e 's~=/%{_lib}/libpcprofile.so~=%{_libdir}/libpcprofile.so~' \
+ -e 's~=/%{_lib}/libmemusage.so~=%{_libdir}/libmemusage.so~' \
+ -e 's~='\''/\\\$LIB/libpcprofile.so~='\''%{_prefix}/\\$LIB/libpcprofile.so~' \
+ -e 's~='\''/\\\$LIB/libmemusage.so~='\''%{_prefix}/\\$LIB/libmemusage.so~' \
+ -i $i
+done
+
+touch master.filelist
+touch glibc.filelist
+touch common.filelist
+touch devel.filelist
+touch nscd.filelist
+touch nss_modules.filelist
+touch nss-devel.filelist
+%ifnarch loongarch64
+touch libnsl.filelist
+%endif
+touch debugutils.filelist
+touch benchtests.filelist
+touch help.filelist
+%if %{with compat_2_17}
+touch compat-2.17.filelist
+%endif
+
+{
+ find $RPM_BUILD_ROOT \( -type f -o -type l \) \
+ \( \
+ -name etc -printf "%%%%config " -o \
+ -name gconv-modules \
+ -printf "%%%%verify(not md5 size mtime) %%%%config(noreplace) " -o \
+ -name gconv-modules.cache \
+ -printf "%%%%verify(not md5 size mtime) " \
+ , \
+ ! -path "*/lib/debug/*" -printf "/%%P\n" \)
+
+ find $RPM_BUILD_ROOT -type d \
+ \( -path '*%{_prefix}/share/locale' -prune -o \
+ \( -path '*%{_prefix}/share/*' \
+%if %{with docs}
+ ! -path '*%{_infodir}' -o \
+%endif
+ -path "*%{_prefix}/include/*" \
+ \) -printf "%%%%dir /%%P\n" \)
+} | {
+ sed -e '\,.*/share/locale/\([^/_]\+\).*/LC_MESSAGES/.*\.mo,d' \
+ -e '\,.*/share/i18n/locales/.*,d' \
+ -e '\,.*/share/i18n/charmaps/.*,d' \
+ -e '\,.*/etc/\(localtime\|nsswitch.conf\|ld\.so\.conf\|ld\.so\.cache\|default\|rpc\|gai\.conf\),d' \
+ -e '\,.*%{_libdir}/lib\(pcprofile\|memusage\)\.so,d' \
+%if %{with compat_2_17}
+ -e '\,.*%{_libdir}/libpthread-2.17.so,d' \
+ -e '\,.*%{_libdir}/libpthread_nonshared.a,d' \
+%endif
+ -e '\,.*/bin/\(memusage\|mtrace\|xtrace\|pcprofiledump\),d'
+} | sort > master.filelist
+
+chmod 0444 master.filelist
+
+##############################################################################
+# glibc - The GNU C Library (glibc) core package.
+##############################################################################
+cat master.filelist \
+ | grep -v \
+ -e '%{_infodir}' \
+ -e '%{_libdir}/lib.*_p.a' \
+ -e '%{_prefix}/include' \
+ -e '%{_libdir}/lib.*\.a' \
+ -e '%{_libdir}/.*\.o' \
+ -e '%{_libdir}/lib.*\.so' \
+ -e 'nscd' \
+ -e '%{_prefix}/bin' \
+ -e '%{_prefix}/lib/locale' \
+ -e '%{_prefix}/sbin/[^i]' \
+ -e '%{_prefix}/share' \
+ -e '/var/db/Makefile' \
+ -e '/libnss_.*\.so[0-9.]*$' \
+%ifnarch loongarch64
+ -e '/libnsl' \
+%endif
+ -e 'glibc-benchtests' \
+ -e 'aux-cache' \
+ > glibc.filelist
+
+for module in compat files dns; do
+ cat master.filelist \
+ | grep -E \
+ -e "/libnss_$module(\.so\.[0-9.]+|-[0-9.]+\.so)$" \
+ >> glibc.filelist
+done
+
+echo '%{_libdir}/libmemusage.so' >> glibc.filelist
+echo '%{_libdir}/libpcprofile.so' >> glibc.filelist
+
+##############################################################################
+# glibc "common" sub-package
+##############################################################################
+grep '%{_prefix}/bin' master.filelist > common.filelist
+grep '%{_prefix}/sbin' master.filelist \
+ | grep -v '%{_prefix}/sbin/iconvconfig' \
+ | grep -v 'nscd' >> common.filelist
+
+grep '%{_prefix}/share' master.filelist \
+ | grep -v \
+ -e '%{_prefix}/share/info/libc.info.*' \
+ -e '%%dir %{prefix}/share/info' \
+ -e '%%dir %{prefix}/share' \
+ >> common.filelist
+
+###############################################################################
+# glibc "devel" sub-package
+###############################################################################
+%if %{with docs}
+grep '%{_infodir}' master.filelist | grep -v '%{_infodir}/dir' > help.filelist
+%endif
+
+grep '%{_libdir}/lib.*\.a' master.filelist \
+ | grep '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \
+ >> devel.filelist
+
+grep '%{_libdir}/.*\.o' < master.filelist >> devel.filelist
+grep '%{_libdir}/lib.*\.so' < master.filelist >> devel.filelist
+
+sed -i -e '\,/libnss_[a-z]*\.so$,d' devel.filelist
+
+grep '%{_prefix}/include' < master.filelist >> devel.filelist
+
+grep '%{_libdir}/lib.*\.a' < master.filelist \
+ | grep -v '/lib\(\(c\|pthread\|nldbl\|mvec\)_nonshared\|g\|ieee\|mcheck\)\.a$' \
+ >> devel.filelist
+
+
+##############################################################################
+# glibc "nscd" sub-package
+##############################################################################
+echo '%{_prefix}/sbin/nscd' > nscd.filelist
+
+##############################################################################
+# nss modules sub-package
+##############################################################################
+grep -E "/libnss_(db|hesiod)(\.so\.[0-9.]+|-[0-9.]+\.so)$" \
+master.filelist > nss_modules.filelist
+
+##############################################################################
+# nss-devel sub-package
+##############################################################################
+grep '/libnss_[a-z]*\.so$' master.filelist > nss-devel.filelist
+
+##############################################################################
+# libnsl subpackage
+##############################################################################
+%ifnarch loongarch64
+grep -E '/libnsl\.so\.[0-9]+$' master.filelist > libnsl.filelist
+test $(wc -l < libnsl.filelist) -eq 1
+%endif
+##############################################################################
+# glibc debugutils sub-package
+##############################################################################
+cat > debugutils.filelist <<EOF
+%if %{without bootstrap}
+%{_prefix}/bin/memusage
+%{_prefix}/bin/memusagestat
+%endif
+%{_prefix}/bin/mtrace
+%{_prefix}/bin/pcprofiledump
+%{_prefix}/bin/xtrace
+EOF
+
+%if %{with benchtests}
+##############################################################################
+# glibc benchtests sub-package
+##############################################################################
+find build-%{target}/benchtests -type f -executable | while read b; do
+ echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)"
+done > benchtests.filelist
+# ... and the makefile.
+for b in %{SOURCE3} %{SOURCE4}; do
+ echo "%{_prefix}/libexec/glibc-benchtests/$(basename $b)" >> benchtests.filelist
+done
+# ... and finally, the comparison scripts.
+echo "%{_prefix}/libexec/glibc-benchtests/benchout.schema.json" >> benchtests.filelist
+echo "%{_prefix}/libexec/glibc-benchtests/compare_bench.py*" >> benchtests.filelist
+echo "%{_prefix}/libexec/glibc-benchtests/import_bench.py*" >> benchtests.filelist
+echo "%{_prefix}/libexec/glibc-benchtests/validate_benchout.py*" >> benchtests.filelist
+%endif
+
+%if %{with compat_2_17}
+##############################################################################
+# glibc compat-2.17 sub-package
+##############################################################################
+ echo "%{_libdir}/libpthread-2.17.so" >> compat-2.17.filelist
+ echo "%{_libdir}/libpthread_nonshared.a" >> compat-2.17.filelist
+%endif
+
+reliantlib=""
+
+function findReliantLib()
+{
+ local library=$1
+ reliantlib=$(readelf -d $library | grep "(NEEDED)" | awk -F "Shared library" '{print $2}')$reliantlib
+}
+
+# remove gconv rpath/runpath
+function removeLoadPath()
+{
+ local file=$1
+ local rpathInfo=$(chrpath -l $file | grep "RPATH=")
+ local runpathInfo=$(chrpath -l $file | grep "RUNPATH=")
+
+ local currPath=""
+ if [ x"$rpathInfo" != x"" ]; then
+ currPath=$(echo $rpathInfo | awk -F "RPATH=" '{print $2}')
+ fi
+
+ if [ x"$runpathInfo" != x"" ]; then
+ currPath=$(echo $runpathInfo | awk -F "RUNPATH=" '{print $2}')
+ fi
+
+ if [ x"$currPath" == x"\$ORIGIN" ]; then
+ chrpath -d $file
+
+ findReliantLib $file
+ fi
+}
+
+set +e
+
+# find and remove RPATH/RUNPATH
+for file in $(find $RPM_BUILD_ROOT%{_libdir}/gconv/ -name "*.so" -exec file {} ';' | grep "\<ELF\>" | awk -F ':' '{print $1}')
+do
+ removeLoadPath $file
+done
+
+function createSoftLink()
+{
+ # pick up the dynamic libraries and create softlink for them
+ local tmplib=$(echo $reliantlib | sed 's/://g' | sed 's/ //g' | sed 's/\[//g' | sed 's/]/\n/g' | sort | uniq)
+
+ for temp in $tmplib
+ do
+ if [ -f "$RPM_BUILD_ROOT%{_libdir}/gconv/$temp" ]; then
+ ln -sf %{_libdir}/gconv/$temp $RPM_BUILD_ROOT%{_libdir}/$temp
+ echo %{_libdir}/$temp >> glibc.filelist
+ fi
+ done
+}
+
+# create soft link for the reliant libraries
+createSoftLink
+set -e
+
+##############################################################################
+# Run the glibc testsuite
+##############################################################################
+%check
+%if %{with testsuite}
+
+omit_testsuite() {
+ while read testsuite; do
+ testsuite_escape=$(echo "$testsuite" | \
+ sed 's/\([.+?^$\/\\|()\[]\|\]\)/\\\0/g')
+ sed -i "/${testsuite_escape}/d" rpmbuild.tests.sum.not-passing
+ done
+}
+
+# Increase timeouts
+export TIMEOUTFACTOR=16
+parent=$$
+echo ====================TESTING=========================
+
+# Default libraries.
+pushd build-%{target}
+make %{?_smp_mflags} -O check |& tee rpmbuild.check.log >&2
+test -s tests.sum
+
+# This hides a test suite build failure, which should be fatal. We
+# check "Summary of test results:" below to verify that all tests
+# were built and run.
+if ! grep -q '^Summary of test results:$' rpmbuild.check.log ; then
+ echo "FAIL: test suite build of target: $(basename "$(pwd)")" >& 2
+ exit 1
+fi
+grep -v ^PASS: tests.sum | grep -v ^UNSUPPORTED > rpmbuild.tests.sum.not-passing || true
+
+# Delete the testsuite from the whitelist
+cat %{SOURCE8} | \
+ grep -v "^$\|^#" | \
+ awk -F':' '{if($2 == "" || $2 ~ /'%{_target_cpu}'/ ) {print $1}}' |\
+ omit_testsuite
+
+set +x
+if test -s rpmbuild.tests.sum.not-passing ; then
+ echo ===================FAILED TESTS===================== >&2
+ echo "Target: $(basename "$(pwd)")" >& 2
+ cat rpmbuild.tests.sum.not-passing >&2
+ while read failed_code failed_test ; do
+ for suffix in out test-result ; do
+ if test -e "$failed_test.$suffix"; then
+ echo >&2
+ echo "=====$failed_code $failed_test.$suffix=====" >&2
+ cat -- "$failed_test.$suffix" >&2
+ echo >&2
+ fi
+ done
+ done <rpmbuild.tests.sum.not-passing
+%if 0%{?glibc_abort_after_test_fail}
+ exit 1
+%endif
+fi
+
+# Unconditonally dump differences in the system call list.
+echo "* System call consistency checks:" >&2
+cat misc/tst-syscall-list.out >&2
+set -x
+popd
+
+echo ====================TESTING END=====================
+PLTCMD='/^Relocation section .*\(\.rela\?\.plt\|\.rela\.IA_64\.pltoff\)/,/^$/p'
+echo ====================PLT RELOCS LD.SO================
+readelf -Wr $RPM_BUILD_ROOT/%{_lib}/ld-*.so | sed -n -e "$PLTCMD"
+echo ====================PLT RELOCS LIBC.SO==============
+readelf -Wr $RPM_BUILD_ROOT/%{_lib}/libc-*.so | sed -n -e "$PLTCMD"
+echo ====================PLT RELOCS END==================
+
+pushd build-%{target}
+LD_SHOW_AUXV=1 elf/ld.so --library-path .:elf:nptl:dlfcn /bin/true
+
+%if %{with valgrind}
+elf/ld.so --library-path .:elf:nptl:dlfcn \
+ /usr/bin/valgrind --error-exitcode=1 \
+ elf/ld.so --library-path .:elf:nptl:dlfcn /usr/bin/true
+%endif
+popd
+
+%endif
+
+##############################################################################
+# Install and uninstall scripts
+##############################################################################
+%pre -p <lua>
+-- Check that the running kernel is new enough
+required = '%{enablekernel}'
+rel = posix.uname("%r")
+if rpm.vercmp(rel, required) < 0 then
+ error("FATAL: kernel too old", 0)
+end
+
+%post -p <lua>
+-- We use lua's posix.exec because there may be no shell that we can
+-- run during glibc upgrade.
+function post_exec (program, ...)
+ local pid = posix.fork ()
+ if pid == 0 then
+ assert (posix.exec (program, ...))
+ elseif pid > 0 then
+ posix.wait (pid)
+ end
+end
+
+-- (1) Remove multilib libraries from previous installs.
+-- In order to support in-place upgrades, we must immediately remove
+-- obsolete platform directories after installing a new glibc
+-- version. RPM only deletes files removed by updates near the end
+-- of the transaction. If we did not remove the obsolete platform
+-- directories here, they may be preferred by the dynamic linker
+-- during the execution of subsequent RPM scriptlets, likely
+-- resulting in process startup failures.
+
+-- Full set of libraries glibc may install.
+install_libs = { "anl", "BrokenLocale", "c", "dl", "m", "mvec",
+ "nss_compat", "nss_db", "nss_dns", "nss_files",
+ "nss_hesiod", "pthread", "resolv", "rt", "SegFault",
+ "thread_db", "util" }
+
+-- We are going to remove these libraries. Generally speaking we remove
+-- all core libraries in the multilib directory.
+-- We employ a tight match where X.Y is in [2.0,9.9*], so we would
+-- match "libc-2.0.so" and so on up to "libc-9.9*".
+remove_regexps = {}
+for i = 1, #install_libs do
+ remove_regexps[i] = ("lib" .. install_libs[i]
+ .. "%%-[2-9]%%.[0-9]+%%.so$")
+end
+
+-- Two exceptions:
+remove_regexps[#install_libs + 1] = "libthread_db%%-1%%.0%%.so"
+remove_regexps[#install_libs + 2] = "libSegFault%%.so"
+
+-- We are going to search these directories.
+local remove_dirs = { "%{_libdir}/i686",
+ "%{_libdir}/i686/nosegneg" }
+
+-- Walk all the directories with files we need to remove...
+for _, rdir in ipairs (remove_dirs) do
+ if posix.access (rdir) then
+ -- If the directory exists we look at all the files...
+ local remove_files = posix.files (rdir)
+ for rfile in remove_files do
+ for _, rregexp in ipairs (remove_regexps) do
+ -- Does it match the regexp?
+ local dso = string.match (rfile, rregexp)
+ if (dso ~= nil) then
+ -- Removing file...
+ os.remove (rdir .. '/' .. rfile)
+ end
+ end
+ end
+ end
+end
+
+-- (2) Update /etc/ld.so.conf
+-- Next we update /etc/ld.so.conf to ensure that it starts with
+-- a literal "include ld.so.conf.d/*.conf".
+
+local ldsoconf = "/etc/ld.so.conf"
+local ldsoconf_tmp = "/etc/glibc_post_upgrade.ld.so.conf"
+
+if posix.access (ldsoconf) then
+
+ -- We must have a "include ld.so.conf.d/*.conf" line.
+ local have_include = false
+ for line in io.lines (ldsoconf) do
+ -- This must match, and we don't ignore whitespace.
+ if string.match (line, "^include ld.so.conf.d/%%*%%.conf$") ~= nil then
+ have_include = true
+ end
+ end
+
+ if not have_include then
+ -- Insert "include ld.so.conf.d/*.conf" line at the start of the
+ -- file. We only support one of these post upgrades running at
+ -- a time (temporary file name is fixed).
+ local tmp_fd = io.open (ldsoconf_tmp, "w")
+ if tmp_fd ~= nil then
+ tmp_fd:write ("include ld.so.conf.d/*.conf\n")
+ for line in io.lines (ldsoconf) do
+ tmp_fd:write (line .. "\n")
+ end
+ tmp_fd:close ()
+ local res = os.rename (ldsoconf_tmp, ldsoconf)
+ if res == nil then
+ io.stdout:write ("Error: Unable to update configuration file (rename).\n")
+ end
+ else
+ io.stdout:write ("Error: Unable to update configuration file (open).\n")
+ end
+ end
+end
+
+-- (3) Rebuild ld.so.cache early.
+-- If the format of the cache changes then we need to rebuild
+-- the cache early to avoid any problems running binaries with
+-- the new glibc.
+
+-- Note: We use _prefix because Fedora's UsrMove says so.
+post_exec ("%{_prefix}/sbin/ldconfig")
+
+-- (4) Update gconv modules cache.
+-- If the /usr/lib/gconv/gconv-modules.cache exists, then update it
+-- with the latest set of modules that were just installed.
+-- We assume that the cache is in _libdir/gconv and called
+-- "gconv-modules.cache".
+local iconv_dir = "%{_libdir}/gconv"
+local iconv_cache = iconv_dir .. "/gconv-modules.cache"
+if (posix.utime (iconv_cache) == 0) then
+ post_exec ("%{_prefix}/sbin/iconvconfig",
+ "-o", iconv_cache,
+ "--nostdlib",
+ iconv_dir)
+else
+ io.stdout:write ("Error: Missing " .. iconv_cache .. " file.\n")
+end
+
+%postun -p <lua> common
+archive_path = "%{_prefix}/lib/locale/locale-archive"
+os.remove (archive_path)
+
+%posttrans -p <lua> common
+archive_path = "%{_prefix}/lib/locale/locale-archive"
+default_path = "%{_prefix}/lib/locale/locale-archive.default"
+os.remove (archive_path)
+posix.link(default_path, archive_path)
+
+%postun -p <lua> locale-archive
+archive_path = "%{_prefix}/lib/locale/locale-archive"
+default_path = "%{_prefix}/lib/locale/locale-archive.default"
+os.remove (archive_path)
+posix.link(default_path, archive_path)
+
+%posttrans -p <lua> locale-archive
+archive_path = "%{_prefix}/lib/locale/locale-archive"
+update_path = "%{_prefix}/lib/locale/locale-archive.update"
+os.remove (archive_path)
+posix.link(update_path, archive_path)
+
+%pre devel
+# this used to be a link and it is causing nightmares now
+if [ -L %{_prefix}/include/scsi ] ; then
+ rm -f %{_prefix}/include/scsi
+fi
+
+%pre -n nscd
+getent group nscd >/dev/null || /usr/sbin/groupadd -g 28 -r nscd
+getent passwd nscd >/dev/null ||
+ /usr/sbin/useradd -M -o -r -d / -s /sbin/nologin \
+ -c "NSCD Daemon" -u 28 -g nscd nscd
+
+%post -n nscd
+%systemd_post nscd.service
+
+%preun -n nscd
+%systemd_preun nscd.service
+
+%postun -n nscd
+if test $1 = 0; then
+ /usr/sbin/userdel nscd > /dev/null 2>&1 || :
+fi
+%systemd_postun_with_restart nscd.service
+
+##############################################################################
+# Files list
+##############################################################################
+%files -f glibc.filelist
+%dir %{_prefix}/%{_lib}/audit
+%verify(not md5 size mtime) %config(noreplace) /etc/nsswitch.conf
+%verify(not md5 size mtime) %config(noreplace) /etc/ld.so.conf
+%verify(not md5 size mtime) %config(noreplace) /etc/rpc
+%dir /etc/ld.so.conf.d
+%dir %{_prefix}/libexec/getconf
+%dir %{_libdir}/gconv
+%dir %attr(0700,root,root) /var/cache/ldconfig
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/cache/ldconfig/aux-cache
+%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/ld.so.cache
+%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /etc/gai.conf
+%{!?_licensedir:%global license %%doc}
+%license COPYING COPYING.LIB LICENSES
+
+%files -f common.filelist common
+%dir %{_prefix}/lib/locale
+%dir %{_prefix}/lib/locale/C.utf8
+%{_prefix}/lib/locale/C.utf8/*
+%attr(0644,root,root) %config(noreplace) %{_prefix}/lib/locale/locale-archive.default
+
+%files -f libc.lang all-langpacks
+%{_prefix}/lib/locale
+%exclude %{_prefix}/lib/locale/locale-archive
+%exclude %{_prefix}/lib/locale/locale-archive.update
+%exclude %{_prefix}/lib/locale/locale-archive.default
+%exclude %{_prefix}/lib/locale/C.utf8
+
+%files locale-source
+%dir %{_prefix}/share/i18n/locales
+%{_prefix}/share/i18n/locales/*
+%dir %{_prefix}/share/i18n/charmaps
+%{_prefix}/share/i18n/charmaps/*
+
+%files locale-archive
+%attr(0644,root,root) %{_prefix}/lib/locale/locale-archive.update
+
+%files -f devel.filelist devel
+
+%files -f nscd.filelist -n nscd
+%config(noreplace) /etc/nscd.conf
+%dir %attr(0755,root,root) /var/run/nscd
+%dir %attr(0755,root,root) /var/db/nscd
+/lib/systemd/system/nscd.service
+/lib/systemd/system/nscd.socket
+%{_tmpfilesdir}/nscd.conf
+%attr(0644,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/nscd.pid
+%attr(0666,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/socket
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/passwd
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/group
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/hosts
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/run/nscd/services
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/passwd
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/group
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/hosts
+%attr(0600,root,root) %verify(not md5 size mtime) %ghost %config(missingok,noreplace) /var/db/nscd/services
+%ghost %config(missingok,noreplace) /etc/sysconfig/nscd
+
+%files -f nss_modules.filelist -n nss_modules
+/var/db/Makefile
+
+%files -f nss-devel.filelist nss-devel
+
+%ifnarch loongarch64
+%files -f libnsl.filelist -n libnsl
+/%{_lib}/libnsl.so.1
+%endif
+
+%files -f debugutils.filelist debugutils
+
+%if %{with benchtests}
+%files -f benchtests.filelist benchtests
+%endif
+
+%files -f help.filelist help
+#Doc of glibc package
+%doc README NEWS INSTALL elf/rtld-debugger-interface.txt
+#Doc of common sub-package
+%doc documentation/README.timezone
+%doc documentation/gai.conf
+#Doc of nss_modules sub-package
+%doc hesiod/README.hesiod
+
+%if %{with compat_2_17}
+%files -f compat-2.17.filelist compat-2.17
+%endif
+
+%changelog
+* Sat Aug 03 2024 Funda Wang <fundawang@yeah.net> - 2.34-156
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:mktime: improve heuristic for ca-1986 Indiana DST
+
+* Sat Jul 27 2024 chengyechun <chengyechun1@huawei.com> - 2.34-155
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:resolv:Do not wait for no existing second DNS response error
+
+* Sat Jul 20 2024 zhuofeng <zhuofeng2@huawei.com> - 2.34-154
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:stdlib: fix grouping verification with multi-byte thousands
+
+* Mon Jul 15 2024 taoyuxiang <taoyuxiang2@huawei.com> - 2.34-153
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:Check the validity of len before mmap
+
+* Tue Jun 25 2024 chenhaixiang <chenhaixiang3@huawei.com> - 2.34-152
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:elf: Properly align PT_LOAD segments
+
+* Mon Jun 17 2024 hefq343 <fengqing.he@shingroup.cn> - 2.34-151
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:fix compile error for ppc64le
+
+* Fri May 10 2024 shixuantong <shixuantong1@huawei.com> - 2.34-150
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:elf: Add TLS modid reuse test for bug 29039
+ elf: Fix TLS modid reuse generation assignment
+ elf: Check objname before calling fatal_error
+ elf: Fix _dl_debug_vdprintf to work before self-relocation
+ elf: ldconfig should skip temporary files created by package managers
+ ldconfig: Fixes for skipping temporary files.
+
+* Mon May 06 2024 chengyechun <chengyechun1@huaiwe.com> - 2.34-149
+- Type:bugfix
+- ID:
+- SUG:NA
+- DESC:nscd: Use errval, not errno to guide cache update
+ nsce :Skip unusable entries in first pass in prune_cache
+
+* Mon Apr 29 2024 chengyechun <chengyechun1@huawei.com> - 2.34-148
+- Type:CVE
+- ID:CVE-2024-33599 CVE-2024-33600 CVE-2024-33601 CVE-2024-33602
+- SUG:NA
+- DESC:fix CVE-2024-33599 CVE-2024-33600 CVE-2024-33601 CVE-2024-33602
+
+* Wed Apr 24 2024 Lixing <lixing@loongson.cn> - 2.34-147
+- Add missing LoongArch relocation type in elf.h
+
+* Tue Apr 23 2024 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-146
+- iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing escape sequence (CVE-2024-2961)
+
+* Sat Jan 13 2024 Qingqing Li <liqingqing3@huawei.com> - 2.34-145
+- elf: Add a way to check if tunable is set (BZ 27069)
+- malloc: Improve MAP_HUGETLB with glibc.malloc.hugetlb=2
+
+* Fri Dec 29 2023 shixuantong <shixuantong1@huawei.com> - 2.34-144
+- Fix invalid pointer dereference in wcpcpy_chk and wcscpy_chk
+
+* Thu Dec 14 2023 shixuantong <shixuantong1@huawei.com> - 2.34-143
+- elf: Handle non-directory name in search path (BZ 31035)
+
+* Tue Dec 5 2023 nicunshu <nicunshu@huawei.com> - 2.34-142
+- add the missing patch to the source package
+
+* Mon Nov 13 2023 lixing <lixing@loongson.cn> - 2.34-141
+- Fixup LoongArch Port errors
+
+* Thu Nov 9 2023 doupengda <doupengda@loongson.cn> - 2.34-140
+- Modify patch 9030 defined multiple times
+
+* Thu Oct 26 2023 zhangnaichuan <zhangnaichuan@huawei.com> - 2.34-139
+- posix: Fix some crashes in wordexp
+
+* Mon Oct 16 2023 lijianglin <lijianglin2@huawei.com> - 2.34-138
+- io: Do not implement fstat with fstatat
+
+* Sat Oct 7 2023 liningjie <liningjie@xfusion.com> - 2.34-137
+- fix CVE-2023-4911
+
+* Tue Sep 26 2023 zhanghao<zhanghao383@huawei.com> - 2.34-136
+- fix CVE-2023-5156
+
+* Mon Sep 25 2023 zhanghao<zhanghao383@huawei.com> - 2.34-135
+- fix CVE-2023-4806 CVE-2023-5156
+
+* Sat Sep 23 2023 zhanghao<zhanghao383@huawei.com> - 2.34-134
+- fix CVE-2023-4813
+
+* Wed Aug 30 2023 Lv Ying<lvying6@huawei.com> - 2.34-133
+- string: strerror must not return NULL (bug 30555)
+
+* Tue Aug 29 2023 chenhaixiang<chenhaixiang3@huawei.com> - 2.34-132
+- time: strftime_l: Avoid an unbounded alloca.
+
+* Mon Aug 14 2023 zhanghao<zhanghao383@huawei.com> - 2.34-131
+- resolv_conf: release lock on allocation failure (bug 30527)
+
+* Wed Aug 9 2023 liubo<liubo335@huawei.com> - 2.34-130
+- inet fix warn unused result
+
+* Mon Aug 7 2023 zhanghao<zhanghao383@huawei.com> - 2.34-129
+- fix Segmentation fault in nss module
+- fix nss database check reload and get memleak
+
+* Fri Jul 28 2023 lixing <lixing@loongson.cn> - 2.34-128
+- DESC: Add static PIE support for LoongArch
+
+* Sun Jul 16 2023 Qingqing Li <liqingqing3@huawei.com> - 2.34-127
+- time: Fix use-after-free in getdate
+
+* Tue Jul 11 2023 lijianglin<lijianglin2@huawei.com> - 2.34-126
+- add the test of the entire GB18030 charmap
+
+* Fri Jun 30 2023 chenziyang <chenziyang4@huawei.com> - 2.34-125
+- DESC: backport upstream patches
+ elf: prevent crash in dlclose
+ elf: fix undefined behavior of negative input of __dl_printf()
+ elf: fix dlopen error when searching '/' directory
+
+* Thu Jun 8 2023 lijianglin <lijianglin2@huawei.com> - 2.34-124
+- display declaration fstat function, make fstat call the system fstat function
+
+* Sun Jun 4 2023 Qingqing Li <liqingqing3@huawei.com> - 2.34-123
+- x86: add noseparate-code for bash program performance
+
+* Mon May 29 2023 Qingqing Li <liqingqing3@huawei.com> - 2.34-122
+- locale: reduce the size of locale C.utf-8
+
+* Wed May 24 2023 lijianglin<lijianglin2@huawei.com> - 2.34-121
+- add GB18030-2022 charmap
+
+* Fri May 19 2023 Peng Fan <fanpeng@loongson.cn> - 2.34-120
+- Backport LoongArch patches:
+- Fix ptr mangling/demangling features.
+- Keep SHMLBA the same value with kernel.
+
+* Mon May 08 2023 laokz <zhangkai@iscas.ac.cn> - 2.34-119
+- Backport RISC-V patches:
+ - Align stack in clone (from v2.35)
+ - Add copysign to stdlib strfrom to fix NAN issue (from v2.37)
+ - Assume only FLAG_ELF_LIBC6 suport (from v2.37)
+ - Restore libc6 implicit soname logic (from v2.38)
+
+* Fri Apr 28 2023 Lv Ying <lvying6@huawei.com> - 2.34-118
+- malloc: elf/ld.so: Consider maybe-existing hole between PT_LOAD segments when mmap reserved area
+
+* Thu Apr 13 2023 Qingqing Li <liqingqing3@huawei.com> - 2.34-117
+- malloc: Fix -Wuse-after-free warning in tst-mallocalign1 [BZ #26779]
+
+* Tue Apr 11 2023 zhanghao <zhanghao383@huawei.com> - 2.34-116
+- nscd: Fix netlink cache invalidation if epoll is used [BZ #29415]
+- nss_dns: In gaih_getanswer_slice, skip strange aliases (bug 12154)
+- sunrpc: Suppress GCC -Os warning on user2netname
+
+* Mon Mar 27 2023 shixuantong <shixuantong1@huawei.com> - 2.34-115
+- Avoid use of atoi in some places in libc
+- stdlib: Undo post review change to 16adc58e73f3
+- gmon: improve mcount overflow handling
+- gmon: fix memory corruption issues
+- posix: Fix system blocks SIGCHLD erroneously
+
+* Sat Mar 25 2023 Chen Ziyang<chenziyang4@huawei.com> - 2.34-114
+- elf/ld.so: fix 2 bugs in ld.so mmap shared object use hugepage
+ - bugfix: ld.so mmap now first mmap 2MB continuous memory by MAP_NORESERVE flag because we do not want to revert to 4KB when 2MB resources is smaller then entire so. We want to check resources happend in later _mmap_segment_filesz function
+ - bugfix: fix hugepageedit tool range check logic, prohibit multiple -i options and do not allow -i specify non PT_LOAD segment index
+
+* Tue Mar 14 2023 Qingqing Li <liqingqing3@huawei.com> - 2.34-113
+- malloc: Fix transposed arguments in sysmalloc_mmap_fallback call
+
+* Sat Feb 25 2023 Lv Ying <lvying6@huawei.com> - 2.34-112
+- elf/ld.so: ld.so mmap shared object use hugepage new feature and bugfix:
+ - feature: support HUGEPAGE_PROBE + hugepageedit mark shared object
+ specified segment, just try to use hugepage to mmap specified segment
+ instead of all the segments in the shared object
+ - bugfix: remove _mmap_hole when ld.so mmap PT_LOAD segment try to use hugepage
+
+* Thu Feb 23 2023 Qingqing Li <liqingqing3@huawei.com> - 2.34-111
+- gmon: Fix allocated buffer overflow (bug 29444)
+
+* Wed Feb 8 2023 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-110
+- fix error patch number
+
+* Mon Feb 6 2023 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-109
+- Since the pthread_cond_clockwait@GLIBC_2_28 is introduced in earlier
+ versions, this symbol is required to keep the previous items compatible.
+
+* Thu Feb 2 2023 lixing <lixing@loongson.cn> - 2.34-108
+- Fixup asin and acos errors for LoongArch.
+
+* Tue Jan 31 2023 lixing <lixing@loongson.cn> - 2.34-107
+- Fixup testsuite_whitelist for LoongArch.
+
+* Sun Jan 29 2023 Xue Liu <liuxue@loongson.cn> - 2.34-106
+- LoongArch: Optimize some string functions including memcpy, memmove,
+ memset, strchr, strchrnul, strcmp, strncmp, ctrcpy, ctrlen, strnlen.
+
+* Wed Dec 21 2022 wanghongliang <wanghongliang@loongson.cn> - 2.34-105
+- LoongArch Port
+- Add login-Add-back-libutil-as-an-empty-library.patch from upstream
+ to fix libutil build error.
+- Add malloc-Fix-malloc-debug-for-2.35-onwards.patch from upstream
+ to fix memory bug
+- After glibc 2.28,removed libnsl.LoongArch Port in glibc 2.34,not support libnsl.
+- Left some test fails in testsuite_whitelist.
+
+* Fri Dec 16 2022 lijianglin <lijianglin2@huawei.com> - 2.34-104
+- x86: Fix wcsnlen-avx2 page cross length comparison(BZ #29591)
+
+* Mon Dec 12 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-103
+- io: Fix use after free in ftw (BZ 26779)
+
+* Thu Dec 08 2022 shixuantong <shixuantong1@huawei.com> - 2.34-102
+- elf: Do not completely clear reused namespace in dlmopen (bug 29600)
+- elf: Remove allocate use on _dl_debug_printf
+- elf/tlsdeschtab.h: Add the Malloc return value check in _dl_make_tlsdesc_dynamic()
+- Fix OOB read in stdlib thousand grouping parsing [BZ#29727]
+
+* Tue Nov 29 2022 Lv Ying <lvying6@huawei.com> - 2.34-101
+- elf: Fix alloca size in _dl_debug_vdprintf
+
+* Sat Oct 22 2022 xujing <xujing125@huawei.com> - 2.34-100
+- elf: Fix hwcaps string size overestimation
+
+* Mon Oct 10 2022 xujing <xujing125@huawei.com> - 2.34-99
+- elf: Call __libc_early_init for reused namespaces (bug 29528)
+ dlfcn: Pass caller pointer to static dlopen implementation (bug 29446)
+
+* Mon Oct 10 2022 Lv Ying <lvying6@huawei.com>- 2.34-98
+- elf: LD_HUGEPAGE_LIB HUGEPAGE_PROBE and LD_DEBUG no longer share GLRO(dl_debug_mask)
+ elf: remove use-mlock-to-determine-hugepage-RLIMIT_MEMLOCK-soft-.patch
+
+* Sun Oct 9 2022 Zhen Chen <chenzhen126@huawei.com> - 2.34-97
+- socket: Fix mistyped define statement in socket/sys/socket.h(BZ #29225)
+
+* Thu Sep 8 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-96
+- nptl: Fix ___pthread_unregister_cancel_restore asynchronous
+
+* Thu Sep 8 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-95
+- add requires between glibc-info and glibc
+
+* Thu Aug 11 2022 Lv Ying <lvying6@huawei.com> - 2.34-94
+- fix LD_HUGEPAGE_LIB env does not take effect
+
+* Mon Aug 1 2022 xujing <xujing125@huawei.com> - 2.34-93
+- sync patches from upstream community
+
+* Thu Jul 28 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-92
+- optimize Obsoletes version
+
+* Wed Jul 6 2022 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-91
+- add libpthread_nonshared.a in glibc-compat-2.17 for old applications
+
+* Wed Jul 6 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-90
+- enable -werror by default
+
+* Fri Jul 1 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-89
+- Fix mq_timereceive check for 32 bit fallback code (BZ 29304)
+
+* Tue Jun 28 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-88
+- aarch64: add -mno-outline-atomics to prevent mallocT2_xx performance regression
+
+* Mon Jun 27 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-87
+- x86: use total l3cache for non_temporal_threshold
+
+* Tue Jun 14 2022 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-86
+- Use Lua to compile the installation scripts of glibc-common and glibc-locale-archive.
+
+* Wed Jun 1 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-85
+- use locale-archive to prevent basic command performance regression
+
+* Tue May 31 2022 SuperHugePan <zhangpan26@huawei.com> - 2.34-84
+- Fix deadlock when pthread_atwork handler calls pthread_atwork or dlclose
+
+* Mon May 30 2022 QingqingLi <liqingqing3@huawei.com> - 2.34-83
+- Linux: Avoid closing -1 on faiure in __closefrom_fallback
+
+* Sat May 28 2022 QingqingLi <liqingqing3@huawei.com> - 2.34-82
+- realpath: Avoid overwriting preexisting error (CVE-2021-3998)
+
+* Fri May 20 2022 xujing <xujing125@huawei.com> - 2.34-81
+- elf: Fix use-after-free in ldconfig [BZ #26779]
+
+* Sat May 7 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-80
+- linux: Fix posix_spawn return code if clone fails (BZ#29109)
+
+* Thu May 05 2022 jiangheng <jiangheng14@huawei.com> - 2.34-79
+- restore nscd
+
+* Thu May 5 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-78
+- linux: Fix fchmodat with AT_SYMLINK_NOFOLLOW for 64 bit time_t (BZ#29097)
+
+* Fri Apr 29 2022 Pan Zhang <zhangpan26@huawei.com> - 2.34-77
+- posix/glob.c: update from gnulib
+
+* Sun Apr 24 2022 xujing <xujing99@huawei.com> - 2.34-76
+- elf: Fix initial-exec TLS access on audit modules (BZ #28096)
+
+* Mon Apr 18 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-75
+- nptl: Handle spurious EINTR when thread cancellation is disabled (BZ#29029)
+
+* Sat Apr 9 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-74
+- libio: Ensure output buffer for wchars bug 28828
+- libio: libio Flush onlu _IO_str_overflow must not return EOF bug 28949
+- linux: Fix _closefrom_fallback iterates until max int bug 28993
+
+* Fri Apr 8 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-73
+- localedef: Handle symbolic links when generating locale-archive
+
+* Wed Mar 30 2022 Lv Ying <lvying6@huawei.com> - 2.34-72
+- use mlock to determine hugepage RLIMIT_MEMLOCK soft resource limit is valid
+
+* Tue Mar 29 2022 Yang Yanchao <yangyanchao@huawei.com> - 2.34-71
+- mv libc.info.gz* to the package glibc-help
+
+* Tue Mar 15 2022 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-70
+- malloc: Add madvise support for Transparent Huge Pages
+- malloc: Add THP/madvise support for sbrk
+- malloc: Move mmap logic to its own function
+- malloc: Add Huge Page support for mmap
+- malloc: Add Huge Page support to arenas
+- malloc: Move MORECORE fallback mmap to sysmalloc_mmap_fallback
+- malloc: Enable huge page support on main arena
+
+* Sat Mar 12 2022 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-69
+- malloc: use __get_nprocs replace __get_nprocs_sched.
+
+* Sat Mar 5 2022 zhoukang <gameoverboss@163.com> - 2.34-68
+- add dynamic linker load lib use hugepage
+
+* Thu Mar 3 2022 qinyu <qinyu16@huawei.com> - 2.34-67
+- disable rseq by default with tunable
+
+* Thu Mar 3 2022 Yunfeng Ye <yeyunfeng@huawei.com> - 2.34-66
+- add PTRACE_GET_RSEQ_CONFIGURATION
+
+* Thu Mar 3 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-65
+- add chrpath to BuildRequires to make
+ 'remove shared library's RPATH/RUNPATH' to take effect
+
+* Wed Mar 2 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-64
+- x86: strncmp-avx2-rtm and wcsncmp-avx2-rtm fallback on
+ non-rtm variants when avoiding overflow. [BZ #28896]
+
+* Tue Mar 1 2022 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-63
+- Merge testsuite_whitelist.aarch64 and testsuite_whitelist.x86_64 to testsuite_whitelist.
+
+* Tue Mar 1 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-62
+- remove shared library's RPATH/RUNPATH for security
+
+* Fri Feb 25 2022 qinyu<qinyu16@huawei.com> - 2.34-61
+- add rseq support
+
+* Thu Feb 24 2022 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-60
+- Only in the CI environment, the build is interrupted due to test case failure.
+
+* Wed Feb 23 2022 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-59
+- strcmp: delete align for loop_aligned
+
+* Wed Feb 23 2022 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-58
+- The release of glibc.src.rpm in OpenEuler is not based on the architecture.
+ Developers only have glibc.src.rpm in the ARM, so add all testsuite_whitelist in glibc.src.rpm.
+
+* Tue Feb 22 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-57
+- tzselect: use region to instead of country for extract timezone selection.
+
+* Thu Feb 10 2022 jiangheng <jiangheng12@huawei.com> - 2.34-56
+- remove nscd; the functionality nscd currently provides can be
+ achieved by using systemd-resolved for DNS caching and the sssd
+ daemon for everything else
+
+* Wed Feb 9 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-55
+- linux: fix accurarcy of get_nprocs and get_nprocs_conf [BZ #28865]
+
+* Tue Feb 8 2022 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-54
+- disable rt/tst-cpuclock2 which often fails in CI.
+
+* Tue Feb 8 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-53
+- elf: fix glibc 2.34 ABI omission
+- x86: black list more intel cpus for TSX [BZ #27398]
+- recvmsg/recvmmsg: fix ancillary 64-bit time timestamp comversion [BZ #28349, BZ #28350]
+- socket: do not use AF_NETLINK in __opensock
+
+* Mon Feb 7 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-52
+- fix misc/tst-glibcsyscalls failed due to kernel reserve some syscalls
+
+* Mon Feb 7 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-51
+- Pass the actual number of bytes returned by the kernel.
+ Fixes: 33099d72e41c ("linux: Simplify get_nprocs")
+
+* Fri Jan 28 2022 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-50
+- The default debuginfo management mechanism is deleted.
+ Instead, Use the default macro of RPM.
+ There are two changes:
+ 1. The source files in /usr/src are
+ correctly packed into the glibc-debugsource.
+ 2. The debugging file contains the glibc version number.
+
+* Fri Jan 28 2022 Lv Ying <lvying6@huawei.com> - 2.34-49
+- fix CVE-2019-1010023
+
+* Fri Jan 28 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-48
+- Fix __wcsncmp_evex in strcmp-evex.S [BZ #28755]
+- Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ #28755]
+
+* Tue Jan 25 2022 Chuang Fang <fangchuangchuang@huawei.com> - 2.34-47
+- Disable debuginfod in printer tests [BZ #28757]
+- i386: Remove broken CAN_USE_REGISTER_ASM_EBP (bug 28771)
+- x86: use default cache size if it cannot be determined [BZ #28784]
+
+* Tue Jan 25 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-46
+- fix CVE-2021-3998 and CVE-2021-3999
+
+* Fri Jan 21 2022 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-45
+- disable check-installed-headers-c and check-installed-headers-cxx
+ and delete glibc-benchtest to improve build speed
+
+* Fri Jan 21 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-44
+- support: Add check for TID zero in support_wait_for_thread_exit
+
+* Tue Jan 18 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-43
+- fix CVE-2022-23218 and CVE-2022-23219
+
+* Tue Jan 11 2022 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-42
+- delete macro __filter_GLIBC_PRIVATE which is not support in rpm-4.17
+ Use arbitrary filtering to control GLIBC_PRIVATE
+
+* Mon Jan 10 2022 Qingqing Li <liqingqing3@huawei.com> - 2.34-41
+- timex: Use 64-bit fields on 32-bit TIMESIZE=64 systems. BZ #28469
+- malloc: Handle NULL input to malloc usable size. BZ #28506
+- elf: Earlier missing dynamic segment check in _dl_map_object_from_fd
+- nptl: Do not set signal mask on second setjmp return. BZ #28607
+- linux: use /proc/stat fallback for __get_nprocs_conf. BZ #28624
+- nss: Use "file dns" as the default for the hosts database. BZ #28700
+- int/plural.y: Avoid conflicting declarations of yyerror and yylex
+- aarch64: Check for SVE in ifuncs BZ #28744
+- Fix subscript error with odd TZif file BZ #28338
+- timezone: handle truncated timezones from tzcode 2021
+- timezone: test case for BZ #28707
+
+* Mon Jan 10 2022 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-40
+- rpm-build move find-debuginfo.sh into debugedit.
+ and change the path from "/usr/lib/rpm" to "/usr/bin"
+ adapts this change
+
+* Tue Dec 28 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-39
+- support: Also return fd when it is 0.
+
+* Mon Dec 27 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-38
+- elf: replace nsid with args.nsid [BZ #27609]
+
+* Sat Dec 25 2021 liusirui <liusirui@huawei.com> - 2.34-37
+- ld.so: Don't fill the DT_DEBUG entry in ld.so [BZ #28129]
+
+* Fri Dec 24 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-36
+- do not define tgmath.h fmaxmag, fminmag macros for C2X (BZ #28397)
+
+* Fri Dec 24 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-35
+- io: Fix ftw internal realloc buffer (BZ #28126)
+
+* Tue Dec 21 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-34
+- tst: fix failing nss/tst-nss-files-hosts-long with local resolver
+ use support_open_dev_null_range io/tst-closefrom, mise/tst-close_range, and posix/tst-spawn5(BZ#28260)
+ nptl: add one more barrier to nptl/tst-create1
+
+* Wed Dec 15 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-33
+- pthread/tst-cancel28: Fix barrier re-init race condition
+
+* Thu Dec 9 2021 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-32
+- Deleted some unnecessary command when make master.filelist
+
+* Thu Dec 9 2021 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-31
+- support all Chinese and English by default
+ add zh_* and en_* to glibc-common
+ the size of glibc-common is increased from 1.8MB to 3.5MB
+
+* Fri Dec 3 2021 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-30
+- turn the default value of x86_rep_stosb_threshold from 2k to 1M
+
+* Thu Dec 2 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-29
+- revert the use of sched_getaffinity [BZ #28310]
+
+* Tue Nov 30 2021 Bin Wang <wangbin224@huawei.com> - 2.34-28
+- Linux: Simplify __opensock and fix race condition [BZ #28353]
+
+* Wed Nov 24 2021 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-27
+- Refactor the libpthread-2.17.so code and pass all test cases.
+ delete libpthread-2.17.so from glibc-devel
+
+* Fri Nov 19 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-26
+- revert supress -Wcast-qual warnings in bsearch
+
+* Mon Nov 15 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-25
+- fix attribute access mode on getcwd [BZ #27476]
+- supress -Wcast-qual warnings in bsearch
+
+* Mon Nov 15 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-24
+- elf: fix ld.so crash while loading a DSO with a read-only dynamic section
+ https://sourceware.org/bugzilla/show_bug.cgi?id=28340
+
+* Wed Nov 10 2021 Qingqing Li <liqingqing3@huawei.com> - 2.34-23
+- gconv: Do not emit spurious NUL character in ISO-2022-JP-3,
+ this also fix CVE-2021-43396.
+ uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=28524
+
+* Tue Nov 9 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-22
+- iconvconfig: Fix behaviour with --prefix
+ uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=28199
+
+* Mon Nov 8 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-21
+- nptl: pthread_kill race condition issues fixed.
+ uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=19193
+ https://sourceware.org/bugzilla/show_bug.cgi?id=12889
+ https://sourceware.org/bugzilla/show_bug.cgi?id=28036
+ https://sourceware.org/bugzilla/show_bug.cgi?id=28363
+ https://sourceware.org/bugzilla/show_bug.cgi?id=28407
+
+* Thu Nov 4 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-20
+- nptl: pthread_kill and pthread_cancel return success
+ for satisfy posix standard.
+ uplink: https://sourceware.org/bugzilla/show_bug.cgi?id=19193
+
+* Fri Oct 29 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-19
+- aarch64: update a64fx memset not to degrade at 16KB
+
+* Thu Oct 28 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-18
+- use testl instead of andl to check __x86_string_control to
+ avoid updating __x86_string_control
+
+* Tue Oct 26 2021 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-17
+- Show more debugging information during testsuite
+
+* Tue Oct 26 2021 Chuangchuang Fang<fangchuangchuang@huawei.com> - 2.34-16
+- Use __executable_start as the lowest address for profiling
+
+* Tue Oct 26 2021 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-15
+- add glibc-compat-2.17 subpackage to provide the function of
+ the glibc-2.17 pthread library.
+ Currently, provide pthread_condition function.
+
+* Mon Oct 25 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-14
+- mtrace fix output with PIE and ASLR.
+- elf: rtld copy terminating null in tunables strdup.
+
+* Mon Oct 25 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-13
+- fpu: x86-64 optimize load of all bits set into ZMM register.
+
+* Tue Oct 19 2021 Yang Yanchao <yangyanchao6@huawei.com> - 2.34-12
+- Add locale-archive sub packages to support more languages
+ and reduce memory usage.
+
+* Tue Oct 12 2021 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-11
+- Add the testsuite whitelist.
+ If a test case out of the trustlist fails, the compilation is interrupted.
+
+* Mon Oct 11 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-10
+- update test memmove.c to cover 16KB.
+
+* Wed Sep 29 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-9
+- elf: drop elf/tls-macros.h in favor of thread tls_mode attribute.
+- use __ehdr_start for __GLOBAL_OFFSET_TABLE[0]
+
+* Wed Sep 29 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-8
+- fix overflow ittimer tests on 32 bit system
+
+* Mon Sep 27 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-7
+- mtrace: use a static buffer for printing, fix memory leak.
+ upstream link: https://sourceware.org/bugzilla/show_bug.cgi?id=25947
+
+* Sun Sep 26 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-6
+- elf: Unconditionally use __ehdr_start.
+- aarch64: Make elf_machine_{load_addr,dynamic} robust [BZ #28203].
+ upstream link: https://sourceware.org/bugzilla/show_bug.cgi?id=28203
+
+* Fri Sep 17 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-5
+- aarch64: optimize memset performance.
+
+* Fri Sep 17 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-4
+- backport upstream patches to fix some memory leak and double free bugs
+
+* Tue Sep 14 2021 Yang Yanchao<yangyanchao6@huawei.com> - 2.34-3
+- add --enable-static-pie in aarch64
+
+* Wed Aug 25 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-2
+- fix CVE-2021-38604
+ https://sourceware.org/bugzilla/show_bug.cgi?id=28213
+
+* Thu Aug 5 2021 Qingqing Li<liqingqing3@huawei.com> - 2.34-1
+- upgrade to 2.34.
+
+* Fri Jul 23 2021 zhouwenpei<zhouwenpei1@huawei.com> - 2.33-7
+- remove unnecessary build require.
+
+* Sat Jul 3 2021 Qingqing Li<liqingqing3@huawei.com> - 2.33-6
+- malloc: tcache shutdown sequence does not work if the thread never allocated anything. (bug 28028)
+ https://sourceware.org/bugzilla/show_bug.cgi?id=28028
+
+* Thu Jul 1 2021 Qingqing Li<liqingqing3@huawei.com> - 2.33-5
+- wordexp: Use strtoul instead of atoi so that overflow can be detected. (bug 28011)
+ https://sourceware.org/bugzilla/show_bug.cgi?id=28011
+
+* Fri Jun 18 2021 Qingqing Li<liqingqing3@huawei.com> - 2.33-4
+- fix CVE-2021-33574(bug 27896)
+ https://sourceware.org/bugzilla/show_bug.cgi?id=27896
+
+* Tue Apr 27 2021 xuhuijie<xuhujie@huawei.com> - 2.33-3
+- Fix locales BEP inconsistence, use python to replace same file
+ to hard link
+
+* Wed Apr 7 2021 xieliuhua<xieliuhua@huawei.com> - 2.33-2
+- Fix-the-inaccuracy-of-j0f-j1f-y0f-y1f-BZ.patch
+
+* Fri Mar 5 2021 Wang Shuo<wangshuo_1994@foxmail.com> - 2.33-1
+- upgrade glibc to 2.33-1
+
+* Tue Jan 26 2021 shanzhikun <shanzhikun@huawei.com> - 2.31-9
+- elf: Allow dlopen of filter object to work [BZ #16272]
+ https://sourceware.org/bugzilla/show_bug.cgi?id=16272
+
+* Fri Jan 8 2021 Wang Shuo<wangshuo_1994@foxmail.com> - 2.31-8
+- Replace "openEuler" by %{_vendor} for versatility
+
+* Tue Nov 10 2020 liusirui <liusirui@huawei.com> - 2.31-7
+- Fix CVE-2020-27618, iconv accept redundant shift sequences in IBM1364 [BZ #26224]
+ https://sourceware.org/bugzilla/show_bug.cgi?id=26224
+
+* Tue Sep 15 2020 shanzhikun<shanzhikun@huawei.com> - 2.31-6
+- rtld: Avoid using up static TLS surplus for optimizations [BZ #25051].
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=ffb17e7ba3a5ba9632cee97330b325072fbe41dd
+
+* Fri Sep 4 2020 MarsChan<chenmingmin@huawei.com> - 2.31-5
+- For political reasons, remove country selection from tzselect.ksh
+
+* Fri Aug 14 2020 Xu Huijie<546391727@qq.com> - 2.31-4
+- since the new version of the pthread_cond_wait()
+ function has performance degradation in multi-core
+ scenarios, here is an extra libpthreadcond.so using
+ old version of the function. you can use it by adding
+ LD_PRELOAD=./libpthreadcond.so in front of your program
+ (eg: LD_PRELOAD=./libpthreadcond.so ./test).
+ use with-libpthreadcond to compile it.
+ warning:2.17 version pthread_cond_wait() does not meet
+ the posix standard, you should pay attention when using
+ it.
+
+* Fri Jul 24 2020 Wang Shuo<wangshuo_1994@foxmail.com> - 2.31-3
+- backport patch to disable warnings due to deprecated libselinux
+- symbols used by nss and nscd
+
+* Fri Jul 24 2020 Wang Shuo<wangshuo_1994@foxmail.com> - 2.31-2
+- fix CVE-2020-6096
+- fix bugzilla 26137, 26214 and 26215
+
+* Thu Jul 9 2020 wuxu<wuxu.wu@hotmail.com> - 2.31-1
+- upgrade glibc to 2.31-1
+- delete build-locale-archive command
+- delete nsswitch.conf file
+- replace glibc_post_upgrade function with lua
+- remove sys/sysctl.h header file
+- delete stime, ftime function
+
+* Tue Jul 7 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-45
+- disable rpc, it has been splited to libnss and libtirpc
+- disable parallel compilation
+
+* Tue Jul 7 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-44
+- backup to version 40
+
+* Mon Jul 6 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-43
+- disable rpc, it has been splited to libnss and libtirpc
+- disable parallel compilation
+
+* Mon Jul 6 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-42
+- add zh and en to LanguageList
+
+* Thu Jul 2 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-41
+- add filelist to improve the scalability
+- backport many patch for bugfix
+
+* Sat May 30 2020 liqingqing<liqignqing3@huawei.com> - 2.28-40
+- Fix array overflow in backtrace on PowerPC (bug 25423)
+
+* Thu May 28 2020 jdkboy<guoge1@huawei.com> - 2.28-39
+- Disable compilation warnings temporarily
+
+* Tue Apr 28 2020 liqingqing<liqignqing3@huawei.com> - 2.28-38
+- Avoid ldbl-96 stack corruption from range reduction of pseudo-zero (bug 25487)
+
+* Thu Apr 16 2020 wangbin<wangbin224@huawei.com> - 2.28-37
+- backport Kunpeng patches
+
+* Thu Mar 19 2020 yuxiangyang<yuxiangyang4@huawei.com> - 2.28-36
+- fix build src.rpm error
+
+* Fri Mar 13 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-35
+- exclude conflict files about rpc
+
+* Fri Mar 13 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-34
+- enable obsolete rpc
+
+* Tue Mar 10 2020 liqingqing<liqingqing3@huawei.com> - 2.28-33
+- fix use after free in glob when expanding user bug
+
+* Wed Feb 26 2020 Wang Shuo<wangshuo47@huawei.com> - 2.28-32
+- remove aditional require for debugutils package
+
+* Tue Jan 7 2020 Wang Shuo <wangshuo47@huawei.com> - 2.28-31
+- Fix compile macro
+
+* Mon Jan 6 2020 Wang Shuo <wangshuo47@huawei.com> - 2.28-30
+- add obsoletes symbol for language
+
+* Fri Dec 20 2019 liqingqing <liqingqing3@huawei.com> - 2.28-29
+- remove country selection from tzselect
+- fix some bugs https://sourceware.org/git/?p=glibc.git;a=commit;h=1df872fd74f730bcae3df201a229195445d2e18a
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=823624bdc47f1f80109c9c52dee7939b9386d708
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=bc10e22c90e42613bd5dafb77b80a9ea1759dd1b
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=6c29942cbf059aca47fd4bbd852ea42c9d46b71f
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=31effacee2fc1b327bedc9a5fcb4b83f227c6539
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=5b06f538c5aee0389ed034f60d90a8884d6d54de
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=57ada43c905eec7ba28fe60a08b93a52d88e26c1
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=e0e4c321c3145b6ac0e8f6e894f87790cf9437ce
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=182a3746b8cc28784718c8ea27346e97d1423945
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=02d8b5ab1c89bcef2627d2b621bfb35b573852c2
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=f59a54ab0c2dcaf9ee946df2bfee9d4be81f09b8
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=fefa21790b5081e5d04662a240e2efd18603ef86
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=2bd81b60d6ffdf7e0d22006d69f4b812b1c80513
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=a55541fd1c4774d483c2d2b4bd17bcb9faac62e7
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=b6d2c4475d5abc05dd009575b90556bdd3c78ad0
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=8a80ee5e2bab17a1f8e1e78fab5c33ac7efa8b29
+ https://sourceware.org/git/?p=glibc.git;a=commit;h=c0fd3244e71db39cef1e2d1d8ba12bb8b7375ce4
+- fix CVE-2016-10739 CVE-2019-19126 CVE-2019-6488
+- add pie compile option for debug/Makefile and remove -static for build-locale-archive
+
+* Fri Dec 20 2019 liusirui <liusirui@huawei.com> - 2.28-28
+- Fix null pointer in mtrace
+
+* Thu Nov 21 2019 mengxian <mengxian@huawei.com> - 2.28-27
+- In x86, configure static pie and cet only with gcc 8 or above
+
+* Wed Nov 13 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.28-26
+- Optimized instructions for Kunpeng processor
+
+* Fri Jan 18 2019 openEuler Buildteam <buildteam@openeuler.org> - 2.28-25
+- Package init
diff --git a/gmon-Fix-allocated-buffer-overflow-bug-29444.patch b/gmon-Fix-allocated-buffer-overflow-bug-29444.patch
new file mode 100644
index 0000000..d4c6221
--- /dev/null
+++ b/gmon-Fix-allocated-buffer-overflow-bug-29444.patch
@@ -0,0 +1,79 @@
+From 801af9fafd4689337ebf27260aa115335a0cb2bc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?=D0=9B=D0=B5=D0=BE=D0=BD=D0=B8=D0=B4=20=D0=AE=D1=80=D1=8C?=
+ =?UTF-8?q?=D0=B5=D0=B2=20=28Leonid=20Yuriev=29?= <leo@yuriev.ru>
+Date: Sat, 4 Feb 2023 14:41:38 +0300
+Subject: [PATCH] gmon: Fix allocated buffer overflow (bug 29444)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The `__monstartup()` allocates a buffer used to store all the data
+accumulated by the monitor.
+
+The size of this buffer depends on the size of the internal structures
+used and the address range for which the monitor is activated, as well
+as on the maximum density of call instructions and/or callable functions
+that could be potentially on a segment of executable code.
+
+In particular a hash table of arcs is placed at the end of this buffer.
+The size of this hash table is calculated in bytes as
+ p->fromssize = p->textsize / HASHFRACTION;
+
+but actually should be
+ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
+
+This results in writing beyond the end of the allocated buffer when an
+added arc corresponds to a call near from the end of the monitored
+address range, since `_mcount()` check the incoming caller address for
+monitored range but not the intermediate result hash-like index that
+uses to write into the table.
+
+It should be noted that when the results are output to `gmon.out`, the
+table is read to the last element calculated from the allocated size in
+bytes, so the arcs stored outside the buffer boundary did not fall into
+`gprof` for analysis. Thus this "feature" help me to found this bug
+during working with https://sourceware.org/bugzilla/show_bug.cgi?id=29438
+
+Just in case, I will explicitly note that the problem breaks the
+`make test t=gmon/tst-gmon-dso` added for Bug 29438.
+There, the arc of the `f3()` call disappears from the output, since in
+the DSO case, the call to `f3` is located close to the end of the
+monitored range.
+
+Signed-off-by: Леонид Юрьев (Leonid Yuriev) <leo@yuriev.ru>
+
+Another minor error seems a related typo in the calculation of
+`kcountsize`, but since kcounts are smaller than froms, this is
+actually to align the p->froms data.
+
+Co-authored-by: DJ Delorie <dj@redhat.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ gmon/gmon.c | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/gmon/gmon.c b/gmon/gmon.c
+index dee64803ad..bf76358d5b 100644
+--- a/gmon/gmon.c
++++ b/gmon/gmon.c
+@@ -132,6 +132,8 @@ __monstartup (u_long lowpc, u_long highpc)
+ p->lowpc = ROUNDDOWN(lowpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->highpc = ROUNDUP(highpc, HISTFRACTION * sizeof(HISTCOUNTER));
+ p->textsize = p->highpc - p->lowpc;
++ /* This looks like a typo, but it's here to align the p->froms
++ section. */
+ p->kcountsize = ROUNDUP(p->textsize / HISTFRACTION, sizeof(*p->froms));
+ p->hashfraction = HASHFRACTION;
+ p->log_hashfraction = -1;
+@@ -142,7 +144,7 @@ __monstartup (u_long lowpc, u_long highpc)
+ instead of integer division. Precompute shift amount. */
+ p->log_hashfraction = ffs(p->hashfraction * sizeof(*p->froms)) - 1;
+ }
+- p->fromssize = p->textsize / HASHFRACTION;
++ p->fromssize = ROUNDUP(p->textsize / HASHFRACTION, sizeof(*p->froms));
+ p->tolimit = p->textsize * ARCDENSITY / 100;
+ if (p->tolimit < MINARCS)
+ p->tolimit = MINARCS;
+--
+2.33.0
+
diff --git a/i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch b/i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch
new file mode 100644
index 0000000..181b177
--- /dev/null
+++ b/i386-Remove-broken-CAN_USE_REGISTER_ASM_EBP-bug-2877.patch
@@ -0,0 +1,463 @@
+From 2fe2af88abd13ae5636881da2e26f461ecb7dfb5 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 13 Jan 2022 14:59:29 +0100
+Subject: [PATCH] i386: Remove broken CAN_USE_REGISTER_ASM_EBP (bug 28771)
+
+The configure check for CAN_USE_REGISTER_ASM_EBP tried to compile a
+simple function that uses %ebp as an inline assembly operand. If
+compilation failed, CAN_USE_REGISTER_ASM_EBP was set 0, which
+eventually had these consequences:
+
+(1) %ebx was avoided as an inline assembly operand, with an
+ assembler macro hack to avoid unnecessary register moves.
+(2) %ebp was avoided as an inline assembly operand, using an
+ out-of-line syscall function for 6-argument system calls.
+
+(1) is no longer needed for any GCC version that is supported for
+building glibc. %ebx can be used directly as a register operand.
+Therefore, this commit removes the %ebx avoidance completely. This
+avoids the assembler macro hack, which turns out to be incompatible
+with the current Systemtap probe macros (which switch to .altmacro
+unconditionally).
+
+(2) is still needed in many build configurations. The existing
+configure check cannot really capture that because the simple function
+succeeds to compile, while the full glibc build still fails.
+Therefore, this commit removes the check, the CAN_USE_REGISTER_ASM_EBP
+macro, and uses the out-of-line syscall function for 6-argument system
+calls unconditionally.
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+(cherry picked from commit a78e6a10d0b50d0ca80309775980fc99944b1727)
+---
+ NEWS | 1 +
+ config.h.in | 4 -
+ sysdeps/unix/sysv/linux/i386/configure | 39 ----
+ sysdeps/unix/sysv/linux/i386/configure.ac | 17 --
+ sysdeps/unix/sysv/linux/i386/sysdep.h | 222 +++-------------------
+ 5 files changed, 28 insertions(+), 255 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 5c253a4392..759a80b1b5 100644
+--- a/NEWS
++++ b/NEWS
+@@ -30,6 +30,7 @@ The following bugs are resolved with this release:
+ AMD64 cpus
+ [28091] network: ns_name_skip may return 0 for domain names without
+ terminator
++ [28771] %ebx optimization macros are incompatible with .altmacro
+
+
+ Version 2.33
+diff --git a/config.h.in b/config.h.in
+index 8b45a3a61d..37207df94f 100644
+--- a/config.h.in
++++ b/config.h.in
+@@ -283,10 +283,6 @@
+ /* Define if static PIE is enabled. */
+ #define ENABLE_STATIC_PIE 0
+
+-/* Some compiler options may now allow to use ebp in __asm__ (used mainly
+- in i386 6 argument syscall issue). */
+-#define CAN_USE_REGISTER_ASM_EBP 0
+-
+ /* The default value of x86 CET control. */
+ #define DEFAULT_DL_X86_CET_CONTROL cet_elf_property
+
+diff --git a/sysdeps/unix/sysv/linux/i386/configure b/sysdeps/unix/sysv/linux/i386/configure
+index 0327590486..f119e62fc3 100644
+--- a/sysdeps/unix/sysv/linux/i386/configure
++++ b/sysdeps/unix/sysv/linux/i386/configure
+@@ -1,44 +1,5 @@
+ # This file is generated from configure.ac by Autoconf. DO NOT EDIT!
+ # Local configure fragment for sysdeps/unix/sysv/linux/i386.
+
+-# Check if CFLAGS allows compiler to use ebp register in inline assembly.
+-
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking if compiler flags allows ebp in inline assembly" >&5
+-$as_echo_n "checking if compiler flags allows ebp in inline assembly... " >&6; }
+-if ${libc_cv_can_use_register_asm_ebp+:} false; then :
+- $as_echo_n "(cached) " >&6
+-else
+-
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h. */
+-
+- void foo (int i)
+- {
+- register int reg asm ("ebp") = i;
+- asm ("# %0" : : "r" (reg));
+- }
+-int
+-main ()
+-{
+-
+- ;
+- return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_compile "$LINENO"; then :
+- libc_cv_can_use_register_asm_ebp=yes
+-else
+- libc_cv_can_use_register_asm_ebp=no
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+-
+-fi
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_can_use_register_asm_ebp" >&5
+-$as_echo "$libc_cv_can_use_register_asm_ebp" >&6; }
+-if test $libc_cv_can_use_register_asm_ebp = yes; then
+- $as_echo "#define CAN_USE_REGISTER_ASM_EBP 1" >>confdefs.h
+-
+-fi
+-
+ libc_cv_gcc_unwind_find_fde=yes
+ ldd_rewrite_script=sysdeps/unix/sysv/linux/ldd-rewrite.sed
+diff --git a/sysdeps/unix/sysv/linux/i386/configure.ac b/sysdeps/unix/sysv/linux/i386/configure.ac
+index 9e980784bb..64ab2cc2c8 100644
+--- a/sysdeps/unix/sysv/linux/i386/configure.ac
++++ b/sysdeps/unix/sysv/linux/i386/configure.ac
+@@ -1,22 +1,5 @@
+ GLIBC_PROVIDES dnl See aclocal.m4 in the top level source directory.
+ # Local configure fragment for sysdeps/unix/sysv/linux/i386.
+
+-# Check if CFLAGS allows compiler to use ebp register in inline assembly.
+-AC_CACHE_CHECK([if compiler flags allows ebp in inline assembly],
+- libc_cv_can_use_register_asm_ebp, [
+-AC_COMPILE_IFELSE(
+- [AC_LANG_PROGRAM([
+- void foo (int i)
+- {
+- register int reg asm ("ebp") = i;
+- asm ("# %0" : : "r" (reg));
+- }])],
+- [libc_cv_can_use_register_asm_ebp=yes],
+- [libc_cv_can_use_register_asm_ebp=no])
+-])
+-if test $libc_cv_can_use_register_asm_ebp = yes; then
+- AC_DEFINE(CAN_USE_REGISTER_ASM_EBP)
+-fi
+-
+ libc_cv_gcc_unwind_find_fde=yes
+ ldd_rewrite_script=sysdeps/unix/sysv/linux/ldd-rewrite.sed
+diff --git a/sysdeps/unix/sysv/linux/i386/sysdep.h b/sysdeps/unix/sysv/linux/i386/sysdep.h
+index 8a9911b7ac..39d6a3c134 100644
+--- a/sysdeps/unix/sysv/linux/i386/sysdep.h
++++ b/sysdeps/unix/sysv/linux/i386/sysdep.h
+@@ -43,15 +43,6 @@
+ # endif
+ #endif
+
+-/* Since GCC 5 and above can properly spill %ebx with PIC when needed,
+- we can inline syscalls with 6 arguments if GCC 5 or above is used
+- to compile glibc. Disable GCC 5 optimization when compiling for
+- profiling or when -fno-omit-frame-pointer is used since asm ("ebp")
+- can't be used to put the 6th argument in %ebp for syscall. */
+-#if !defined PROF && CAN_USE_REGISTER_ASM_EBP
+-# define OPTIMIZE_FOR_GCC_5
+-#endif
+-
+ #ifdef __ASSEMBLER__
+
+ /* Linux uses a negative return value to indicate syscall errors,
+@@ -239,36 +230,6 @@
+ extern int __syscall_error (int)
+ attribute_hidden __attribute__ ((__regparm__ (1)));
+
+-#ifndef OPTIMIZE_FOR_GCC_5
+-/* We need some help from the assembler to generate optimal code. We
+- define some macros here which later will be used. */
+-asm (".L__X'%ebx = 1\n\t"
+- ".L__X'%ecx = 2\n\t"
+- ".L__X'%edx = 2\n\t"
+- ".L__X'%eax = 3\n\t"
+- ".L__X'%esi = 3\n\t"
+- ".L__X'%edi = 3\n\t"
+- ".L__X'%ebp = 3\n\t"
+- ".L__X'%esp = 3\n\t"
+- ".macro bpushl name reg\n\t"
+- ".if 1 - \\name\n\t"
+- ".if 2 - \\name\n\t"
+- "error\n\t"
+- ".else\n\t"
+- "xchgl \\reg, %ebx\n\t"
+- ".endif\n\t"
+- ".endif\n\t"
+- ".endm\n\t"
+- ".macro bpopl name reg\n\t"
+- ".if 1 - \\name\n\t"
+- ".if 2 - \\name\n\t"
+- "error\n\t"
+- ".else\n\t"
+- "xchgl \\reg, %ebx\n\t"
+- ".endif\n\t"
+- ".endif\n\t"
+- ".endm\n\t");
+-
+ /* Six-argument syscalls use an out-of-line helper, because an inline
+ asm using all registers apart from %esp cannot work reliably and
+ the assembler does not support describing an asm that saves and
+@@ -279,7 +240,6 @@ struct libc_do_syscall_args
+ {
+ int ebx, edi, ebp;
+ };
+-#endif
+
+ # define VDSO_NAME "LINUX_2.6"
+ # define VDSO_HASH 61765110
+@@ -332,14 +292,8 @@ struct libc_do_syscall_args
+
+ /* Each object using 6-argument inline syscalls must include a
+ definition of __libc_do_syscall. */
+-#ifdef OPTIMIZE_FOR_GCC_5
+-# define INTERNAL_SYSCALL_MAIN_6(name, args...) \
+- INTERNAL_SYSCALL_MAIN_INLINE(name, 6, args)
+-# define INTERNAL_SYSCALL_MAIN_NCS_6(name, args...) \
+- INTERNAL_SYSCALL_MAIN_NCS(name, 6, args)
+-#else /* GCC 5 */
+-# define INTERNAL_SYSCALL_MAIN_6(name, arg1, arg2, arg3, \
+- arg4, arg5, arg6) \
++#define INTERNAL_SYSCALL_MAIN_6(name, arg1, arg2, arg3, \
++ arg4, arg5, arg6) \
+ struct libc_do_syscall_args _xv = \
+ { \
+ (int) (arg1), \
+@@ -352,8 +306,8 @@ struct libc_do_syscall_args
+ : "=a" (resultvar) \
+ : "i" (__NR_##name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \
+ : "memory", "cc")
+-# define INTERNAL_SYSCALL_MAIN_NCS_6(name, arg1, arg2, arg3, \
+- arg4, arg5, arg6) \
++#define INTERNAL_SYSCALL_MAIN_NCS_6(name, arg1, arg2, arg3, \
++ arg4, arg5, arg6) \
+ struct libc_do_syscall_args _xv = \
+ { \
+ (int) (arg1), \
+@@ -366,7 +320,6 @@ struct libc_do_syscall_args
+ : "=a" (resultvar) \
+ : "a" (name), "c" (arg2), "d" (arg3), "S" (arg4), "D" (&_xv) \
+ : "memory", "cc")
+-#endif /* GCC 5 */
+
+ #define INTERNAL_SYSCALL(name, nr, args...) \
+ ({ \
+@@ -380,193 +333,72 @@ struct libc_do_syscall_args
+ (int) resultvar; })
+
+ #if I386_USE_SYSENTER
+-# ifdef OPTIMIZE_FOR_GCC_5
+-# ifdef PIC
+-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
++# ifdef PIC
++# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
+ LOADREGS_##nr(args) \
+ asm volatile ( \
+ "call *%%gs:%P2" \
+ : "=a" (resultvar) \
+ : "a" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \
+ ASMARGS_##nr(args) : "memory", "cc")
+-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
++# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
+ LOADREGS_##nr(args) \
+ asm volatile ( \
+ "call *%%gs:%P2" \
+ : "=a" (resultvar) \
+ : "a" (name), "i" (offsetof (tcbhead_t, sysinfo)) \
+ ASMARGS_##nr(args) : "memory", "cc")
+-# else
+-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
++# else /* I386_USE_SYSENTER && !PIC */
++# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
+ LOADREGS_##nr(args) \
+ asm volatile ( \
+ "call *_dl_sysinfo" \
+ : "=a" (resultvar) \
+ : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
+-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
++# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
+ LOADREGS_##nr(args) \
+ asm volatile ( \
+ "call *_dl_sysinfo" \
+ : "=a" (resultvar) \
+ : "a" (name) ASMARGS_##nr(args) : "memory", "cc")
+-# endif
+-# else /* GCC 5 */
+-# ifdef PIC
+-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
+- EXTRAVAR_##nr \
+- asm volatile ( \
+- LOADARGS_##nr \
+- "movl %1, %%eax\n\t" \
+- "call *%%gs:%P2\n\t" \
+- RESTOREARGS_##nr \
+- : "=a" (resultvar) \
+- : "i" (__NR_##name), "i" (offsetof (tcbhead_t, sysinfo)) \
+- ASMFMT_##nr(args) : "memory", "cc")
+-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
+- EXTRAVAR_##nr \
+- asm volatile ( \
+- LOADARGS_##nr \
+- "call *%%gs:%P2\n\t" \
+- RESTOREARGS_##nr \
+- : "=a" (resultvar) \
+- : "0" (name), "i" (offsetof (tcbhead_t, sysinfo)) \
+- ASMFMT_##nr(args) : "memory", "cc")
+-# else
+-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
+- EXTRAVAR_##nr \
+- asm volatile ( \
+- LOADARGS_##nr \
+- "movl %1, %%eax\n\t" \
+- "call *_dl_sysinfo\n\t" \
+- RESTOREARGS_##nr \
+- : "=a" (resultvar) \
+- : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
+-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
+- EXTRAVAR_##nr \
+- asm volatile ( \
+- LOADARGS_##nr \
+- "call *_dl_sysinfo\n\t" \
+- RESTOREARGS_##nr \
+- : "=a" (resultvar) \
+- : "0" (name) ASMFMT_##nr(args) : "memory", "cc")
+-# endif
+-# endif /* GCC 5 */
+-#else
+-# ifdef OPTIMIZE_FOR_GCC_5
+-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
++# endif /* I386_USE_SYSENTER && !PIC */
++#else /* !I386_USE_SYSENTER */
++# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
+ LOADREGS_##nr(args) \
+ asm volatile ( \
+ "int $0x80" \
+ : "=a" (resultvar) \
+ : "a" (__NR_##name) ASMARGS_##nr(args) : "memory", "cc")
+-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
++# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
+ LOADREGS_##nr(args) \
+ asm volatile ( \
+ "int $0x80" \
+ : "=a" (resultvar) \
+ : "a" (name) ASMARGS_##nr(args) : "memory", "cc")
+-# else /* GCC 5 */
+-# define INTERNAL_SYSCALL_MAIN_INLINE(name, nr, args...) \
+- EXTRAVAR_##nr \
+- asm volatile ( \
+- LOADARGS_##nr \
+- "movl %1, %%eax\n\t" \
+- "int $0x80\n\t" \
+- RESTOREARGS_##nr \
+- : "=a" (resultvar) \
+- : "i" (__NR_##name) ASMFMT_##nr(args) : "memory", "cc")
+-# define INTERNAL_SYSCALL_MAIN_NCS(name, nr, args...) \
+- EXTRAVAR_##nr \
+- asm volatile ( \
+- LOADARGS_##nr \
+- "int $0x80\n\t" \
+- RESTOREARGS_##nr \
+- : "=a" (resultvar) \
+- : "0" (name) ASMFMT_##nr(args) : "memory", "cc")
+-# endif /* GCC 5 */
+-#endif
+-
+-#define LOADARGS_0
+-#ifdef __PIC__
+-# if I386_USE_SYSENTER && defined PIC
+-# define LOADARGS_1 \
+- "bpushl .L__X'%k3, %k3\n\t"
+-# define LOADARGS_5 \
+- "movl %%ebx, %4\n\t" \
+- "movl %3, %%ebx\n\t"
+-# else
+-# define LOADARGS_1 \
+- "bpushl .L__X'%k2, %k2\n\t"
+-# define LOADARGS_5 \
+- "movl %%ebx, %3\n\t" \
+- "movl %2, %%ebx\n\t"
+-# endif
+-# define LOADARGS_2 LOADARGS_1
+-# define LOADARGS_3 \
+- "xchgl %%ebx, %%edi\n\t"
+-# define LOADARGS_4 LOADARGS_3
+-#else
+-# define LOADARGS_1
+-# define LOADARGS_2
+-# define LOADARGS_3
+-# define LOADARGS_4
+-# define LOADARGS_5
+-#endif
+-
+-#define RESTOREARGS_0
+-#ifdef __PIC__
+-# if I386_USE_SYSENTER && defined PIC
+-# define RESTOREARGS_1 \
+- "bpopl .L__X'%k3, %k3\n\t"
+-# define RESTOREARGS_5 \
+- "movl %4, %%ebx"
+-# else
+-# define RESTOREARGS_1 \
+- "bpopl .L__X'%k2, %k2\n\t"
+-# define RESTOREARGS_5 \
+- "movl %3, %%ebx"
+-# endif
+-# define RESTOREARGS_2 RESTOREARGS_1
+-# define RESTOREARGS_3 \
+- "xchgl %%edi, %%ebx\n\t"
+-# define RESTOREARGS_4 RESTOREARGS_3
+-#else
+-# define RESTOREARGS_1
+-# define RESTOREARGS_2
+-# define RESTOREARGS_3
+-# define RESTOREARGS_4
+-# define RESTOREARGS_5
+-#endif
++#endif /* !I386_USE_SYSENTER */
+
+-#ifdef OPTIMIZE_FOR_GCC_5
+-# define LOADREGS_0()
+-# define ASMARGS_0()
+-# define LOADREGS_1(arg1) \
++#define LOADREGS_0()
++#define ASMARGS_0()
++#define LOADREGS_1(arg1) \
+ LOADREGS_0 ()
+-# define ASMARGS_1(arg1) \
++#define ASMARGS_1(arg1) \
+ ASMARGS_0 (), "b" ((unsigned int) (arg1))
+-# define LOADREGS_2(arg1, arg2) \
++#define LOADREGS_2(arg1, arg2) \
+ LOADREGS_1 (arg1)
+-# define ASMARGS_2(arg1, arg2) \
++#define ASMARGS_2(arg1, arg2) \
+ ASMARGS_1 (arg1), "c" ((unsigned int) (arg2))
+-# define LOADREGS_3(arg1, arg2, arg3) \
++#define LOADREGS_3(arg1, arg2, arg3) \
+ LOADREGS_2 (arg1, arg2)
+-# define ASMARGS_3(arg1, arg2, arg3) \
++#define ASMARGS_3(arg1, arg2, arg3) \
+ ASMARGS_2 (arg1, arg2), "d" ((unsigned int) (arg3))
+-# define LOADREGS_4(arg1, arg2, arg3, arg4) \
++#define LOADREGS_4(arg1, arg2, arg3, arg4) \
+ LOADREGS_3 (arg1, arg2, arg3)
+-# define ASMARGS_4(arg1, arg2, arg3, arg4) \
++#define ASMARGS_4(arg1, arg2, arg3, arg4) \
+ ASMARGS_3 (arg1, arg2, arg3), "S" ((unsigned int) (arg4))
+-# define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \
++#define LOADREGS_5(arg1, arg2, arg3, arg4, arg5) \
+ LOADREGS_4 (arg1, arg2, arg3, arg4)
+-# define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \
++#define ASMARGS_5(arg1, arg2, arg3, arg4, arg5) \
+ ASMARGS_4 (arg1, arg2, arg3, arg4), "D" ((unsigned int) (arg5))
+-# define LOADREGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
+- register unsigned int _a6 asm ("ebp") = (unsigned int) (arg6); \
+- LOADREGS_5 (arg1, arg2, arg3, arg4, arg5)
+-# define ASMARGS_6(arg1, arg2, arg3, arg4, arg5, arg6) \
+- ASMARGS_5 (arg1, arg2, arg3, arg4, arg5), "r" (_a6)
+-#endif /* GCC 5 */
+
+ #define ASMFMT_0()
+ #ifdef __PIC__
+--
+2.27.0
+
diff --git a/iconv-ISO-2022-CN-EXT-fix-out-of-bound-writes-when-w.patch b/iconv-ISO-2022-CN-EXT-fix-out-of-bound-writes-when-w.patch
new file mode 100644
index 0000000..4e39cca
--- /dev/null
+++ b/iconv-ISO-2022-CN-EXT-fix-out-of-bound-writes-when-w.patch
@@ -0,0 +1,214 @@
+From f9dc609e06b1136bb0408be9605ce7973a767ada Mon Sep 17 00:00:00 2001
+From: Charles Fol <folcharles@gmail.com>
+Date: Thu, 28 Mar 2024 12:25:38 -0300
+Subject: [PATCH] iconv: ISO-2022-CN-EXT: fix out-of-bound writes when writing
+ escape sequence (CVE-2024-2961)
+
+ISO-2022-CN-EXT uses escape sequences to indicate character set changes
+(as specified by RFC 1922). While the SOdesignation has the expected
+bounds checks, neither SS2designation nor SS3designation have its;
+allowing a write overflow of 1, 2, or 3 bytes with fixed values:
+'$+I', '$+J', '$+K', '$+L', '$+M', or '$*H'.
+
+Checked on aarch64-linux-gnu.
+
+Co-authored-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ iconvdata/Makefile | 5 +-
+ iconvdata/iso-2022-cn-ext.c | 12 +++
+ iconvdata/tst-iconv-iso-2022-cn-ext.c | 128 ++++++++++++++++++++++++++
+ 3 files changed, 144 insertions(+), 1 deletion(-)
+ create mode 100644 iconvdata/tst-iconv-iso-2022-cn-ext.c
+
+diff --git a/iconvdata/Makefile b/iconvdata/Makefile
+index ea019ce5c0..7196a8744b 100644
+--- a/iconvdata/Makefile
++++ b/iconvdata/Makefile
+@@ -75,7 +75,8 @@ ifeq (yes,$(build-shared))
+ tests = bug-iconv1 bug-iconv2 tst-loading tst-e2big tst-iconv4 bug-iconv4 \
+ tst-iconv6 bug-iconv5 bug-iconv6 tst-iconv7 bug-iconv8 bug-iconv9 \
+ bug-iconv10 bug-iconv11 bug-iconv12 tst-iconv-big5-hkscs-to-2ucs4 \
+- bug-iconv13 bug-iconv14 bug-iconv15
++ bug-iconv13 bug-iconv14 bug-iconv15 \
++ tst-iconv-iso-2022-cn-ext
+ ifeq ($(have-thread-library),yes)
+ tests += bug-iconv3
+ endif
+@@ -330,6 +331,8 @@ $(objpfx)bug-iconv14.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
+ $(objpfx)bug-iconv15.out: $(addprefix $(objpfx), $(gconv-modules)) \
+ $(addprefix $(objpfx),$(modules.so))
++$(objpfx)tst-iconv-iso-2022-cn-ext.out: $(addprefix $(objpfx), $(gconv-modules)) \
++ $(addprefix $(objpfx),$(modules.so))
+
+ $(objpfx)iconv-test.out: run-iconv-test.sh \
+ $(addprefix $(objpfx), $(gconv-modules)) \
+diff --git a/iconvdata/iso-2022-cn-ext.c b/iconvdata/iso-2022-cn-ext.c
+index b34c8a36f4..cce29b1969 100644
+--- a/iconvdata/iso-2022-cn-ext.c
++++ b/iconvdata/iso-2022-cn-ext.c
+@@ -574,6 +574,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
+ { \
+ const char *escseq; \
+ \
++ if (outptr + 4 > outend) \
++ { \
++ result = __GCONV_FULL_OUTPUT; \
++ break; \
++ } \
++ \
+ assert (used == CNS11643_2_set); /* XXX */ \
+ escseq = "*H"; \
+ *outptr++ = ESC; \
+@@ -587,6 +593,12 @@ DIAG_IGNORE_Os_NEEDS_COMMENT (5, "-Wmaybe-uninitialized");
+ { \
+ const char *escseq; \
+ \
++ if (outptr + 4 > outend) \
++ { \
++ result = __GCONV_FULL_OUTPUT; \
++ break; \
++ } \
++ \
+ assert ((used >> 5) >= 3 && (used >> 5) <= 7); \
+ escseq = "+I+J+K+L+M" + ((used >> 5) - 3) * 2; \
+ *outptr++ = ESC; \
+diff --git a/iconvdata/tst-iconv-iso-2022-cn-ext.c b/iconvdata/tst-iconv-iso-2022-cn-ext.c
+new file mode 100644
+index 0000000000..96a8765fd5
+--- /dev/null
++++ b/iconvdata/tst-iconv-iso-2022-cn-ext.c
+@@ -0,0 +1,128 @@
++/* Verify ISO-2022-CN-EXT does not write out of the bounds.
++ Copyright (C) 2024 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <stdio.h>
++#include <string.h>
++
++#include <errno.h>
++#include <iconv.h>
++#include <sys/mman.h>
++
++#include <support/xunistd.h>
++#include <support/check.h>
++#include <support/support.h>
++
++/* The test sets up a two memory page buffer with the second page marked
++ PROT_NONE to trigger a fault if the conversion writes beyond the exact
++ expected amount. Then we carry out various conversions and precisely
++ place the start of the output buffer in order to trigger a SIGSEGV if the
++ process writes anywhere between 1 and page sized bytes more (only one
++ PROT_NONE page is setup as a canary) than expected. These tests exercise
++ all three of the cases in ISO-2022-CN-EXT where the converter must switch
++ character sets and may run out of buffer space while doing the
++ operation. */
++
++static int
++do_test (void)
++{
++ iconv_t cd = iconv_open ("ISO-2022-CN-EXT", "UTF-8");
++ TEST_VERIFY_EXIT (cd != (iconv_t) -1);
++
++ char *ntf;
++ size_t ntfsize;
++ char *outbufbase;
++ {
++ int pgz = getpagesize ();
++ TEST_VERIFY_EXIT (pgz > 0);
++ ntfsize = 2 * pgz;
++
++ ntf = xmmap (NULL, ntfsize, PROT_READ | PROT_WRITE, MAP_PRIVATE
++ | MAP_ANONYMOUS, -1);
++ xmprotect (ntf + pgz, pgz, PROT_NONE);
++
++ outbufbase = ntf + pgz;
++ }
++
++ /* Check if SOdesignation escape sequence does not trigger an OOB write. */
++ {
++ char inbuf[] = "\xe4\xba\xa4\xe6\x8d\xa2";
++
++ for (int i = 0; i < 9; i++)
++ {
++ char *inp = inbuf;
++ size_t inleft = sizeof (inbuf) - 1;
++
++ char *outp = outbufbase - i;
++ size_t outleft = i;
++
++ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
++ == (size_t) -1);
++ TEST_COMPARE (errno, E2BIG);
++
++ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
++ }
++ }
++
++ /* Same as before for SS2designation. */
++ {
++ char inbuf[] = "ã´½ \xe3\xb4\xbd";
++
++ for (int i = 0; i < 14; i++)
++ {
++ char *inp = inbuf;
++ size_t inleft = sizeof (inbuf) - 1;
++
++ char *outp = outbufbase - i;
++ size_t outleft = i;
++
++ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
++ == (size_t) -1);
++ TEST_COMPARE (errno, E2BIG);
++
++ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
++ }
++ }
++
++ /* Same as before for SS3designation. */
++ {
++ char inbuf[] = "劄 \xe5\x8a\x84";
++
++ for (int i = 0; i < 14; i++)
++ {
++ char *inp = inbuf;
++ size_t inleft = sizeof (inbuf) - 1;
++
++ char *outp = outbufbase - i;
++ size_t outleft = i;
++
++ TEST_VERIFY_EXIT (iconv (cd, &inp, &inleft, &outp, &outleft)
++ == (size_t) -1);
++ TEST_COMPARE (errno, E2BIG);
++
++ TEST_VERIFY_EXIT (iconv (cd, NULL, NULL, NULL, NULL) == 0);
++ }
++ }
++
++ TEST_VERIFY_EXIT (iconv_close (cd) != -1);
++
++ xmunmap (ntf, ntfsize);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.33.0
+
diff --git a/iconv_charmap-Close-output-file-when-done.patch b/iconv_charmap-Close-output-file-when-done.patch
new file mode 100644
index 0000000..a966922
--- /dev/null
+++ b/iconv_charmap-Close-output-file-when-done.patch
@@ -0,0 +1,26 @@
+From 1e0e6d656db9dfa12ef7eb67976385d3deb0d4ff Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Tue, 3 Aug 2021 21:10:29 +0530
+Subject: [PATCH] iconv_charmap: Close output file when done
+
+Reviewed-by: Arjun Shankar <arjun@redhat.com>
+---
+ iconv/iconv_charmap.c | 2 ++
+ 1 file changed, 2 insertions(+)
+
+diff --git a/iconv/iconv_charmap.c b/iconv/iconv_charmap.c
+index e2d53fe..a8b6b56 100644
+--- a/iconv/iconv_charmap.c
++++ b/iconv/iconv_charmap.c
+@@ -234,6 +234,8 @@ charmap_conversion (const char *from_code, struct charmap_t *from_charmap,
+ while (++remaining < argc);
+
+ /* All done. */
++ if (output != stdout)
++ fclose (output);
+ free_table (cvtbl);
+ return status;
+ }
+--
+1.8.3.1
+
diff --git a/iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch b/iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch
new file mode 100644
index 0000000..6df7a82
--- /dev/null
+++ b/iconvconfig-Fix-behaviour-with-prefix-BZ-28199.patch
@@ -0,0 +1,123 @@
+From 43cea6d5652b6b9e61ac6ecc69419c909b504f47 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Mon, 13 Sep 2021 20:48:35 +0530
+Subject: [PATCH] iconvconfig: Fix behaviour with --prefix [BZ #28199]
+
+The consolidation of configuration parsing broke behaviour with
+--prefix, where the prefix bled into the modules cache. Accept a
+prefix which, when non-NULL, is prepended to the path when looking for
+configuration files but only the original directory is added to the
+modules cache.
+
+This has no effect on the codegen of gconv_conf since it passes NULL.
+
+Reported-by: Patrick McCarty <patrick.mccarty@intel.com>
+Reported-by: Michael Hudson-Doyle <michael.hudson@canonical.com>
+Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
+---
+ iconv/gconv_conf.c | 2 +-
+ iconv/gconv_parseconfdir.h | 22 +++++++++++++++-------
+ iconv/iconvconfig.c | 16 ++++++++++++----
+ 3 files changed, 28 insertions(+), 12 deletions(-)
+
+diff --git a/iconv/gconv_conf.c b/iconv/gconv_conf.c
+index 09ffe02..077082a 100644
+--- a/iconv/gconv_conf.c
++++ b/iconv/gconv_conf.c
+@@ -477,7 +477,7 @@ __gconv_read_conf (void)
+ __gconv_get_path ();
+
+ for (cnt = 0; __gconv_path_elem[cnt].name != NULL; ++cnt)
+- gconv_parseconfdir (__gconv_path_elem[cnt].name,
++ gconv_parseconfdir (NULL, __gconv_path_elem[cnt].name,
+ __gconv_path_elem[cnt].len);
+ #endif
+
+diff --git a/iconv/gconv_parseconfdir.h b/iconv/gconv_parseconfdir.h
+index 2f06268..a586268 100644
+--- a/iconv/gconv_parseconfdir.h
++++ b/iconv/gconv_parseconfdir.h
+@@ -39,7 +39,6 @@
+ /* Name of the file containing the module information in the directories
+ along the path. */
+ static const char gconv_conf_filename[] = "gconv-modules";
+-static const char gconv_conf_dirname[] = "gconv-modules.d";
+
+ static void add_alias (char *);
+ static void add_module (char *, const char *, size_t, int);
+@@ -110,19 +109,28 @@ read_conf_file (const char *filename, const char *directory, size_t dir_len)
+ return true;
+ }
+
++/* Prefix DIR (with length DIR_LEN) with PREFIX if the latter is non-NULL and
++ parse configuration in it. */
++
+ static __always_inline bool
+-gconv_parseconfdir (const char *dir, size_t dir_len)
++gconv_parseconfdir (const char *prefix, const char *dir, size_t dir_len)
+ {
+- /* No slash needs to be inserted between dir and gconv_conf_filename;
+- dir already ends in a slash. */
+- char *buf = malloc (dir_len + sizeof (gconv_conf_dirname));
++ /* No slash needs to be inserted between dir and gconv_conf_filename; dir
++ already ends in a slash. The additional 2 is to accommodate the ".d"
++ when looking for configuration files in gconv-modules.d. */
++ size_t buflen = dir_len + sizeof (gconv_conf_filename) + 2;
++ char *buf = malloc (buflen + (prefix != NULL ? strlen (prefix) : 0));
++ char *cp = buf;
+ bool found = false;
+
+ if (buf == NULL)
+ return false;
+
+- char *cp = mempcpy (mempcpy (buf, dir, dir_len), gconv_conf_filename,
+- sizeof (gconv_conf_filename));
++ if (prefix != NULL)
++ cp = stpcpy (cp, prefix);
++
++ cp = mempcpy (mempcpy (cp, dir, dir_len), gconv_conf_filename,
++ sizeof (gconv_conf_filename));
+
+ /* Read the gconv-modules configuration file first. */
+ found = read_conf_file (buf, dir, dir_len);
+diff --git a/iconv/iconvconfig.c b/iconv/iconvconfig.c
+index fd61cf2..a89b62e 100644
+--- a/iconv/iconvconfig.c
++++ b/iconv/iconvconfig.c
+@@ -652,13 +652,21 @@ add_module (char *rp, const char *directory,
+ static int
+ handle_dir (const char *dir)
+ {
++ char *newp = NULL;
+ size_t dirlen = strlen (dir);
+ bool found = false;
+
+- char *fulldir = xasprintf ("%s%s%s", dir[0] == '/' ? prefix : "",
+- dir, dir[dirlen - 1] != '/' ? "/" : "");
++ /* End directory path with a '/' if it doesn't already. */
++ if (dir[dirlen - 1] != '/')
++ {
++ newp = xmalloc (dirlen + 2);
++ memcpy (newp, dir, dirlen);
++ newp[dirlen++] = '/';
++ newp[dirlen] = '\0';
++ dir = newp;
++ }
+
+- found = gconv_parseconfdir (fulldir, strlen (fulldir));
++ found = gconv_parseconfdir (dir[0] == '/' ? prefix : NULL, dir, dirlen);
+
+ if (!found)
+ {
+@@ -670,7 +678,7 @@ handle_dir (const char *dir)
+ "configuration files with names ending in .conf.");
+ }
+
+- free (fulldir);
++ free (newp);
+
+ return found ? 0 : 1;
+ }
+--
+1.8.3.1
+
diff --git a/inet-fix-warn-unused-result.patch b/inet-fix-warn-unused-result.patch
new file mode 100644
index 0000000..4887598
--- /dev/null
+++ b/inet-fix-warn-unused-result.patch
@@ -0,0 +1,41 @@
+From 1629adf2a6eefe5ddddc2445e2d056ca80edfe8b Mon Sep 17 00:00:00 2001
+From: =?utf8?q?Fr=C3=A9d=C3=A9ric=20B=C3=A9rat?= <fberat@redhat.com>
+Date: Tue, 18 Apr 2023 09:01:00 -0400
+Subject: [PATCH] inet/rcmd.c: fix warn unused result
+
+Fix unused result warnings, detected when _FORTIFY_SOURCE is enabled in
+glibc.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ inet/rcmd.c | 7 +++++--
+ 1 file changed, 5 insertions(+), 2 deletions(-)
+
+diff --git a/inet/rcmd.c b/inet/rcmd.c
+index ad8a894907..c1cd9daeb5 100644
+--- a/inet/rcmd.c
++++ b/inet/rcmd.c
+@@ -561,7 +561,9 @@ ruserok2_sa (struct sockaddr *ra, size_t ralen, int superuser,
+ reading an NFS mounted file system, can't read files that
+ are protected read/write owner only. */
+ uid = __geteuid ();
+- seteuid (pwd->pw_uid);
++ if (seteuid (pwd->pw_uid) < 0)
++ return -1;
++
+ hostf = iruserfopen (pbuf, pwd->pw_uid);
+
+ if (hostf != NULL)
+@@ -570,7 +572,8 @@ ruserok2_sa (struct sockaddr *ra, size_t ralen, int superuser,
+ fclose (hostf);
+ }
+
+- seteuid (uid);
++ if (seteuid (uid) < 0)
++ return -1;
+ return isbad;
+ }
+ return -1;
+--
+2.39.3
+
diff --git a/intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch b/intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch
new file mode 100644
index 0000000..4931c9e
--- /dev/null
+++ b/intl-plural.y-Avoid-conflicting-declarations-of-yyer.patch
@@ -0,0 +1,42 @@
+From c6d7d6312c21bbcfb236d48bb7c11cedb234389f Mon Sep 17 00:00:00 2001
+From: Andrea Monaco <andrea.monaco@autistici.org>
+Date: Sun, 12 Dec 2021 10:24:28 +0100
+Subject: [PATCH] intl/plural.y: Avoid conflicting declarations of yyerror and
+ yylex
+
+bison-3.8 includes these lines in the generated intl/plural.c:
+
+ #if !defined __gettexterror && !defined YYERROR_IS_DECLARED
+ void __gettexterror (struct parse_args *arg, const char *msg);
+ #endif
+ #if !defined __gettextlex && !defined YYLEX_IS_DECLARED
+ int __gettextlex (YYSTYPE *yylvalp, struct parse_args *arg);
+ #endif
+
+Those default prototypes provided by bison conflict with the
+declarations later on in plural.y. This patch solves the issue.
+
+Reviewed-by: Arjun Shankar <arjun@redhat.com>
+---
+ intl/plural.y | 5 +++++
+ 1 file changed, 5 insertions(+)
+
+diff --git a/intl/plural.y b/intl/plural.y
+index e02e745..2ee128b 100644
+--- a/intl/plural.y
++++ b/intl/plural.y
+@@ -40,6 +40,11 @@
+ # define __gettextparse PLURAL_PARSE
+ #endif
+
++/* Later we provide those prototypes. Without these macros, bison may
++ generate its own prototypes with possible conflicts. */
++#define YYLEX_IS_DECLARED
++#define YYERROR_IS_DECLARED
++
+ %}
+ %parse-param {struct parse_args *arg}
+ %lex-param {struct parse_args *arg}
+--
+1.8.3.1
+
diff --git a/io-Do-not-implement-fstat-with-fstatat.patch b/io-Do-not-implement-fstat-with-fstatat.patch
new file mode 100644
index 0000000..98aab20
--- /dev/null
+++ b/io-Do-not-implement-fstat-with-fstatat.patch
@@ -0,0 +1,165 @@
+From 551101e8240b7514fc646d1722f8b79c90362b8f Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 11 Sep 2023 10:25:48 -0300
+Subject: [PATCH] io: Do not implement fstat with fstatat
+
+AT_EMPTY_PATH is a requirement to implement fstat over fstatat,
+however it does not prevent the kernel to read the path argument.
+It is not an issue, but on x86-64 with SMAP-capable CPUs the kernel is
+forced to perform expensive user memory access. After that regular
+lookup is performed which adds even more overhead.
+
+Instead, issue the fstat syscall directly on LFS fstat implementation
+(32 bit architectures will still continue to use statx, which is
+required to have 64 bit time_t support). it should be even a
+small performance gain on non x86_64, since there is no need
+to handle the path argument.
+
+Checked on x86_64-linux-gnu.
+---
+ sysdeps/unix/sysv/linux/fstat64.c | 37 +++++++++++++++++++++++--
+ sysdeps/unix/sysv/linux/fstatat64.c | 12 ++------
+ sysdeps/unix/sysv/linux/internal-stat.h | 31 +++++++++++++++++++++
+ 3 files changed, 68 insertions(+), 12 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/internal-stat.h
+
+diff --git a/sysdeps/unix/sysv/linux/fstat64.c b/sysdeps/unix/sysv/linux/fstat64.c
+index 124384e57f..a291f0825b 100644
+--- a/sysdeps/unix/sysv/linux/fstat64.c
++++ b/sysdeps/unix/sysv/linux/fstat64.c
+@@ -19,20 +19,53 @@
+ #define __fstat __redirect___fstat
+ #define fstat __redirect_fstat
+ #include <sys/stat.h>
++#undef __fstat
++#undef fstat
+ #include <fcntl.h>
+-#include <kernel_stat.h>
+-#include <stat_t64_cp.h>
++#include <internal-stat.h>
+ #include <errno.h>
+
+ int
+ __fstat64_time64 (int fd, struct __stat64_t64 *buf)
+ {
++#if !FSTATAT_USE_STATX
++# if XSTAT_IS_XSTAT64
++# ifdef __NR_fstat
++ /* 64-bit kABI, e.g. aarch64, ia64, powerpc64*, s390x, riscv64, and
++ x86_64. */
++ return INLINE_SYSCALL_CALL (fstat, fd, buf);
++# elif defined __NR_fstat64
++# if STAT64_IS_KERNEL_STAT64
++ /* 64-bit kABI outlier, e.g. alpha */
++ return INLINE_SYSCALL_CALL (fstat64, fd, buf);
++# else
++ /* 64-bit kABI outlier, e.g. sparc64. */
++ struct kernel_stat64 kst64;
++ int r = INLINE_SYSCALL_CALL (fstat64, fd, &kst64);
++ if (r == 0)
++ __cp_stat64_kstat64 (buf, &kst64);
++ return r;
++# endif /* STAT64_IS_KERNEL_STAT64 */
++# endif
++# else /* XSTAT_IS_XSTAT64 */
++ /* 64-bit kabi outlier, e.g. mips64 and mips64-n32. */
++ struct kernel_stat kst;
++ int r = INLINE_SYSCALL_CALL (fstat, fd, &kst);
++ if (r == 0)
++ __cp_kstat_stat64_t64 (&kst, buf);
++ return r;
++# endif
++#else /* !FSTATAT_USE_STATX */
++ /* All kABIs with non-LFS support and with old 32-bit time_t support
++ e.g. arm, csky, i386, hppa, m68k, microblaze, nios2, sh, powerpc32,
++ and sparc32. */
+ if (fd < 0)
+ {
+ __set_errno (EBADF);
+ return -1;
+ }
+ return __fstatat64_time64 (fd, "", buf, AT_EMPTY_PATH);
++#endif
+ }
+ #if __TIMESIZE != 64
+ hidden_def (__fstat64_time64)
+diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
+index 3509d3ca6d..127c6ff601 100644
+--- a/sysdeps/unix/sysv/linux/fstatat64.c
++++ b/sysdeps/unix/sysv/linux/fstatat64.c
+@@ -21,12 +21,10 @@
+ #include <sys/stat.h>
+ #include <fcntl.h>
+ #include <string.h>
+-#include <kernel_stat.h>
+ #include <sysdep.h>
+ #include <time.h>
+-#include <kstat_cp.h>
+-#include <stat_t64_cp.h>
+ #include <sys/sysmacros.h>
++#include <internal-stat.h>
+
+ #if __TIMESIZE == 64 \
+ && (__WORDSIZE == 32 \
+@@ -40,11 +38,7 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
+ "__blkcnt_t and __blkcnt64_t must match");
+ #endif
+
+-#if (__WORDSIZE == 32 \
+- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+- || defined STAT_HAS_TIME32 \
+- || (!defined __NR_newfstatat && !defined __NR_fstatat64)
+-# define FSTATAT_USE_STATX 1
++#if FSTATAT_USE_STATX
+
+ static inline int
+ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
+@@ -79,8 +73,6 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
+
+ return r;
+ }
+-#else
+-# define FSTATAT_USE_STATX 0
+ #endif
+
+ /* Only statx supports 64-bit timestamps for 32-bit architectures with
+diff --git a/sysdeps/unix/sysv/linux/internal-stat.h b/sysdeps/unix/sysv/linux/internal-stat.h
+new file mode 100644
+index 0000000000..e3b0569853
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/internal-stat.h
+@@ -0,0 +1,31 @@
++/* Internal stat definitions.
++ Copyright (C) 2023 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <sysdep.h>
++#include <stat_t64_cp.h>
++#include <kernel_stat.h>
++#include <kstat_cp.h>
++
++#if (__WORDSIZE == 32 \
++ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
++ || defined STAT_HAS_TIME32 \
++ || (!defined __NR_newfstatat && !defined __NR_fstatat64)
++# define FSTATAT_USE_STATX 1
++#else
++# define FSTATAT_USE_STATX 0
++#endif
+--
+2.33.0
+
diff --git a/io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch b/io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch
new file mode 100644
index 0000000..09767bd
--- /dev/null
+++ b/io-Fix-ftw-internal-realloc-buffer-BZ-28126.patch
@@ -0,0 +1,210 @@
+From 1836bb2ebf62bd9a3588f2ed2d851c8ae810097a Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 25 Aug 2021 11:17:06 -0300
+Subject: [PATCH] io: Fix ftw internal realloc buffer (BZ #28126)
+
+The 106ff08526d3ca did not take in consideration the buffer might be
+reallocated if the total path is larger than PATH_MAX. The realloc
+uses 'dirbuf', where 'dirstreams' is the allocated buffer.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+---
+ io/Makefile | 1 +
+ io/ftw.c | 39 ++++++++++-----------
+ io/tst-ftw-bz28126.c | 97 ++++++++++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 117 insertions(+), 20 deletions(-)
+ create mode 100644 io/tst-ftw-bz28126.c
+
+diff --git a/io/Makefile b/io/Makefile
+index 9871ecb..ecf65ab 100644
+--- a/io/Makefile
++++ b/io/Makefile
+@@ -79,6 +79,7 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
+ tst-futimens \
+ tst-utimensat \
+ tst-closefrom \
++ tst-ftw-bz28126
+
+ tests-time64 := \
+ tst-futimens-time64 \
+diff --git a/io/ftw.c b/io/ftw.c
+index f0db173..fe95345 100644
+--- a/io/ftw.c
++++ b/io/ftw.c
+@@ -203,6 +203,20 @@ struct ftw_data
+ void *known_objects;
+ };
+
++static bool
++ftw_allocate (struct ftw_data *data, size_t newsize)
++{
++ void *newp = realloc (data->dirstreams, data->maxdir
++ * sizeof (struct dir_data *)
++ + newsize);
++ if (newp == NULL)
++ return false;
++ data->dirstreams = newp;
++ data->dirbufsize = newsize;
++ data->dirbuf = (char *) data->dirstreams
++ + data->maxdir * sizeof (struct dir_data *);
++ return true;
++}
+
+ /* Internally we use the FTW_* constants used for `nftw'. When invoked
+ as `ftw', map each flag to the subset of values used by `ftw'. */
+@@ -388,17 +402,9 @@ process_entry (struct ftw_data *data, struct dir_data *dir, const char *name,
+ return 0;
+
+ new_buflen = data->ftw.base + namlen + 2;
+- if (data->dirbufsize < new_buflen)
+- {
+- /* Enlarge the buffer. */
+- char *newp;
+-
+- data->dirbufsize = 2 * new_buflen;
+- newp = (char *) realloc (data->dirbuf, data->dirbufsize);
+- if (newp == NULL)
+- return -1;
+- data->dirbuf = newp;
+- }
++ if (data->dirbufsize < new_buflen
++ && !ftw_allocate (data, 2 * new_buflen))
++ return -1;
+
+ *((char *) __mempcpy (data->dirbuf + data->ftw.base, name, namlen)) = '\0';
+
+@@ -628,7 +634,7 @@ __attribute ((noinline))
+ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
+ int flags)
+ {
+- struct ftw_data data;
++ struct ftw_data data = { .dirstreams = NULL };
+ struct STRUCT_STAT st;
+ int result = 0;
+ int save_err;
+@@ -646,16 +652,9 @@ ftw_startup (const char *dir, int is_nftw, void *func, int descriptors,
+ data.maxdir = descriptors < 1 ? 1 : descriptors;
+ data.actdir = 0;
+ /* PATH_MAX is always defined when we get here. */
+- data.dirbufsize = MAX (2 * strlen (dir), PATH_MAX);
+- data.dirstreams = malloc (data.maxdir * sizeof (struct dir_data *)
+- + data.dirbufsize);
+- if (data.dirstreams == NULL)
++ if (!ftw_allocate (&data, MAX (2 * strlen (dir), PATH_MAX)))
+ return -1;
+-
+ memset (data.dirstreams, '\0', data.maxdir * sizeof (struct dir_data *));
+-
+- data.dirbuf = (char *) data.dirstreams
+- + data.maxdir * sizeof (struct dir_data *);
+ cp = __stpcpy (data.dirbuf, dir);
+ /* Strip trailing slashes. */
+ while (cp > data.dirbuf + 1 && cp[-1] == '/')
+diff --git a/io/tst-ftw-bz28126.c b/io/tst-ftw-bz28126.c
+new file mode 100644
+index 0000000..94044ab
+--- /dev/null
++++ b/io/tst-ftw-bz28126.c
+@@ -0,0 +1,97 @@
++/* Check if internal buffer reallocation work for large paths (BZ #28126)
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <ftw.h>
++#include <limits.h>
++#include <string.h>
++#include <stdlib.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/temp_file.h>
++#include <support/xunistd.h>
++#include <stdio.h>
++
++static int
++my_func (const char *file, const struct stat *sb, int flag)
++{
++ return 0;
++}
++
++static const char folder[NAME_MAX] = { [0 ... 253] = 'a', [254] = '\0' };
++
++#define NSUBFOLDERS 16
++static int nsubfolders;
++
++static void
++do_cleanup (void)
++{
++ xchdir ("..");
++ for (int i = 0; i < nsubfolders; i++)
++ {
++ remove (folder);
++ xchdir ("..");
++ }
++ remove (folder);
++}
++#define CLEANUP_HANDLER do_cleanup
++
++static void
++check_mkdir (const char *path)
++{
++ int r = mkdir (path, 0777);
++ /* Some filesystem such as overlayfs does not support larger path required
++ to trigger the internal buffer reallocation. */
++ if (r != 0)
++ {
++ if (errno == ENAMETOOLONG)
++ FAIL_UNSUPPORTED ("the filesystem does not support the required"
++ "large path");
++ else
++ FAIL_EXIT1 ("mkdir (\"%s\", 0%o): %m", folder, 0777);
++ }
++}
++
++static int
++do_test (void)
++{
++ char *tempdir = support_create_temp_directory ("tst-bz28126");
++
++ /* Create path with various subfolders to force an internal buffer
++ reallocation within ntfw. */
++ char *path = xasprintf ("%s/%s", tempdir, folder);
++ check_mkdir (path);
++ xchdir (path);
++ free (path);
++ for (int i = 0; i < NSUBFOLDERS - 1; i++)
++ {
++ check_mkdir (folder);
++ xchdir (folder);
++ nsubfolders++;
++ }
++
++ TEST_COMPARE (ftw (tempdir, my_func, 20), 0);
++
++ free (tempdir);
++
++ do_cleanup ();
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/io-Fix-use-after-free-in-ftw-BZ-26779.patch b/io-Fix-use-after-free-in-ftw-BZ-26779.patch
new file mode 100644
index 0000000..813d906
--- /dev/null
+++ b/io-Fix-use-after-free-in-ftw-BZ-26779.patch
@@ -0,0 +1,29 @@
+From ee52ab25ba875f458981fce22c54e3c04c7a17d3 Mon Sep 17 00:00:00 2001
+From: Martin Sebor <msebor@redhat.com>
+Date: Tue, 25 Jan 2022 17:39:02 -0700
+Subject: [PATCH] io: Fix use-after-free in ftw [BZ #26779]
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ io/ftw.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/io/ftw.c b/io/ftw.c
+index 2742541f36..94bd5a93e4 100644
+--- a/io/ftw.c
++++ b/io/ftw.c
+@@ -323,8 +323,9 @@ open_dir_stream (int *dfdp, struct ftw_data *data, struct dir_data *dirp)
+ buf[actsize++] = '\0';
+
+ /* Shrink the buffer to what we actually need. */
+- data->dirstreams[data->actdir]->content = realloc (buf, actsize);
+- if (data->dirstreams[data->actdir]->content == NULL)
++ void *content = realloc (buf, actsize);
++ data->dirstreams[data->actdir]->content = content;
++ if (content == NULL)
+ {
+ int save_err = errno;
+ free (buf);
+--
+2.33.0
+
diff --git a/ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch b/ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch
new file mode 100644
index 0000000..93d45e9
--- /dev/null
+++ b/ld.so-Don-t-fill-the-DT_DEBUG-entry-in-ld.so-BZ-2812.patch
@@ -0,0 +1,37 @@
+From 3234a31b489707f19ec6d4c9909af06f20ddb901 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 2 Aug 2021 13:52:36 -0700
+Subject: [PATCH] ld.so: Don't fill the DT_DEBUG entry in ld.so [BZ #28129]
+
+Linker creates the DT_DEBUG entry only in executables. Don't fill the
+non-existent DT_DEBUG entry in ld.so with the run-time address of the
+r_debug structure. This fixes BZ #28129.
+---
+ elf/rtld.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 9642eb9c92..628245d8cd 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -1761,17 +1761,11 @@ dl_main (const ElfW(Phdr) *phdr,
+ #ifdef ELF_MACHINE_DEBUG_SETUP
+ /* Some machines (e.g. MIPS) don't use DT_DEBUG in this way. */
+ ELF_MACHINE_DEBUG_SETUP (main_map, r);
+- ELF_MACHINE_DEBUG_SETUP (&GL(dl_rtld_map), r);
+ #else
+ if (main_map->l_info[DT_DEBUG] != NULL)
+ /* There is a DT_DEBUG entry in the dynamic section. Fill it in
+ with the run-time address of the r_debug structure */
+ main_map->l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
+-
+- /* Fill in the pointer in the dynamic linker's own dynamic section, in
+- case you run gdb on the dynamic linker directly. */
+- if (GL(dl_rtld_map).l_info[DT_DEBUG] != NULL)
+- GL(dl_rtld_map).l_info[DT_DEBUG]->d_un.d_ptr = (ElfW(Addr)) r;
+ #endif
+
+ /* We start adding objects. */
+--
+2.25.1
+
diff --git a/ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch b/ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch
new file mode 100644
index 0000000..d1f4271
--- /dev/null
+++ b/ld.so-Initialize-bootstrap_map.l_ld_readonly-BZ-2834.patch
@@ -0,0 +1,124 @@
+From 2ec99d8c42b2ff1a1231e4df462a0910a9b7fdef Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Thu, 23 Sep 2021 09:06:49 -0700
+Subject: [PATCH] ld.so: Initialize bootstrap_map.l_ld_readonly [BZ #28340]
+
+1. Define DL_RO_DYN_SECTION to initalize bootstrap_map.l_ld_readonly
+before calling elf_get_dynamic_info to get dynamic info in bootstrap_map,
+2. Define a single
+
+static inline bool
+dl_relocate_ld (const struct link_map *l)
+{
+ /* Don't relocate dynamic section if it is readonly */
+ return !(l->l_ld_readonly || DL_RO_DYN_SECTION);
+}
+
+This updates BZ #28340 fix.
+---
+ elf/rtld.c | 1 +
+ sysdeps/generic/dl-relocate-ld.h | 11 ++---------
+ sysdeps/generic/ldsodefs.h | 10 ++++++++++
+ sysdeps/mips/dl-relocate-ld.h | 11 ++---------
+ sysdeps/riscv/dl-relocate-ld.h | 11 ++---------
+ 5 files changed, 17 insertions(+), 27 deletions(-)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index c66a1d0..b8ba2d8 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -547,6 +547,7 @@ _dl_start (void *arg)
+
+ /* Read our own dynamic section and fill in the info array. */
+ bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
++ bootstrap_map.l_ld_readonly = DL_RO_DYN_SECTION;
+ elf_get_dynamic_info (&bootstrap_map);
+
+ #if NO_TLS_OFFSET != 0
+diff --git a/sysdeps/generic/dl-relocate-ld.h b/sysdeps/generic/dl-relocate-ld.h
+index 5fae206..cfb86c2 100644
+--- a/sysdeps/generic/dl-relocate-ld.h
++++ b/sysdeps/generic/dl-relocate-ld.h
+@@ -19,14 +19,7 @@
+ #ifndef _DL_RELOCATE_LD_H
+ #define _DL_RELOCATE_LD_H
+
+-/* Return true if dynamic section in the shared library L should be
+- relocated. */
+-
+-static inline bool
+-dl_relocate_ld (const struct link_map *l)
+-{
+- /* Don't relocate dynamic section if it is readonly */
+- return !l->l_ld_readonly;
+-}
++/* The dynamic section is writable. */
++#define DL_RO_DYN_SECTION 0
+
+ #endif /* _DL_RELOCATE_LD_H */
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index 9ec1511..0410f77 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -69,6 +69,16 @@ __BEGIN_DECLS
+ `ElfW(TYPE)' is used in place of `Elf32_TYPE' or `Elf64_TYPE'. */
+ #define ELFW(type) _ElfW (ELF, __ELF_NATIVE_CLASS, type)
+
++/* Return true if dynamic section in the shared library L should be
++ relocated. */
++
++static inline bool
++dl_relocate_ld (const struct link_map *l)
++{
++ /* Don't relocate dynamic section if it is readonly */
++ return !(l->l_ld_readonly || DL_RO_DYN_SECTION);
++}
++
+ /* All references to the value of l_info[DT_PLTGOT],
+ l_info[DT_STRTAB], l_info[DT_SYMTAB], l_info[DT_RELA],
+ l_info[DT_REL], l_info[DT_JMPREL], and l_info[VERSYMIDX (DT_VERSYM)]
+diff --git a/sysdeps/mips/dl-relocate-ld.h b/sysdeps/mips/dl-relocate-ld.h
+index 0c18d9a..376ad75 100644
+--- a/sysdeps/mips/dl-relocate-ld.h
++++ b/sysdeps/mips/dl-relocate-ld.h
+@@ -19,14 +19,7 @@
+ #ifndef _DL_RELOCATE_LD_H
+ #define _DL_RELOCATE_LD_H
+
+-/* Return true if dynamic section in the shared library L should be
+- relocated. */
+-
+-static inline bool
+-dl_relocate_ld (const struct link_map *l)
+-{
+- /* Never relocate dynamic section. */
+- return false;
+-}
++/* The dynamic section is readonly. */
++#define DL_RO_DYN_SECTION 1
+
+ #endif /* _DL_RELOCATE_LD_H */
+diff --git a/sysdeps/riscv/dl-relocate-ld.h b/sysdeps/riscv/dl-relocate-ld.h
+index 1032745..2ab2b8a 100644
+--- a/sysdeps/riscv/dl-relocate-ld.h
++++ b/sysdeps/riscv/dl-relocate-ld.h
+@@ -19,14 +19,7 @@
+ #ifndef _DL_RELOCATE_LD_H
+ #define _DL_RELOCATE_LD_H
+
+-/* Return true if dynamic section in the shared library L should be
+- relocated. */
+-
+-static inline bool
+-dl_relocate_ld (const struct link_map *l)
+-{
+- /* Never relocate dynamic section for ABI compatibility. */
+- return false;
+-}
++/* The dynamic section is readonly for ABI compatibility. */
++#define DL_RO_DYN_SECTION 1
+
+ #endif /* _DL_RELOCATE_LD_H */
+--
+1.8.3.1
+
diff --git a/ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch b/ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch
new file mode 100644
index 0000000..077b996
--- /dev/null
+++ b/ld.so-Replace-DL_RO_DYN_SECTION-with-dl_relocate_ld-.patch
@@ -0,0 +1,515 @@
+From b413280cfb16834450f66f554bc0d618bb513851 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Thu, 16 Sep 2021 08:15:29 -0700
+Subject: [PATCH] ld.so: Replace DL_RO_DYN_SECTION with dl_relocate_ld [BZ
+ #28340]
+
+We can't relocate entries in dynamic section if it is readonly:
+
+1. Add a l_ld_readonly field to struct link_map to indicate if dynamic
+section is readonly and set it based on p_flags of PT_DYNAMIC segment.
+2. Replace DL_RO_DYN_SECTION with dl_relocate_ld to decide if dynamic
+section should be relocated.
+3. Remove DL_RO_DYN_TEMP_CNT.
+4. Don't use a static dynamic section to make readonly dynamic section
+in vDSO writable.
+5. Remove the temp argument from elf_get_dynamic_info.
+
+This fixes BZ #28340.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ elf/Makefile | 11 +++++++++--
+ elf/dl-load.c | 3 ++-
+ elf/dl-reloc-static-pie.c | 12 +++++++++++-
+ elf/get-dynamic-info.h | 21 +++------------------
+ elf/rtld.c | 6 ++++--
+ elf/setup-vdso.h | 5 ++---
+ elf/tst-ro-dynamic-mod.c | 19 +++++++++++++++++++
+ elf/tst-ro-dynamic-mod.map | 16 ++++++++++++++++
+ elf/tst-ro-dynamic.c | 31 +++++++++++++++++++++++++++++++
+ include/link.h | 3 +++
+ sysdeps/generic/dl-relocate-ld.h | 32 ++++++++++++++++++++++++++++++++
+ sysdeps/generic/ldsodefs.h | 7 ++-----
+ sysdeps/mips/dl-relocate-ld.h | 32 ++++++++++++++++++++++++++++++++
+ sysdeps/mips/ldsodefs.h | 4 ----
+ sysdeps/riscv/dl-relocate-ld.h | 32 ++++++++++++++++++++++++++++++++
+ sysdeps/riscv/ldsodefs.h | 5 -----
+ 16 files changed, 198 insertions(+), 41 deletions(-)
+ create mode 100644 elf/tst-ro-dynamic-mod.c
+ create mode 100644 elf/tst-ro-dynamic-mod.map
+ create mode 100644 elf/tst-ro-dynamic.c
+ create mode 100644 sysdeps/generic/dl-relocate-ld.h
+ create mode 100644 sysdeps/mips/dl-relocate-ld.h
+ create mode 100644 sysdeps/riscv/dl-relocate-ld.h
+
+diff --git a/elf/Makefile b/elf/Makefile
+index 835b85b..0cdccaa 100644
+--- a/elf/Makefile
++++ b/elf/Makefile
+@@ -224,7 +224,7 @@ tests += restest1 preloadtest loadfail multiload origtest resolvfail \
+ tst-tls-ie tst-tls-ie-dlmopen argv0test \
+ tst-glibc-hwcaps tst-glibc-hwcaps-prepend tst-glibc-hwcaps-mask \
+ tst-tls20 tst-tls21 tst-dlmopen-dlerror tst-dlmopen-gethostbyname \
+- tst-dl-is_dso
++ tst-dl-is_dso tst-ro-dynamic
+ # reldep9
+ tests-internal += loadtest unload unload2 circleload1 \
+ neededtest neededtest2 neededtest3 neededtest4 \
+@@ -360,7 +360,7 @@ modules-names = testobj1 testobj2 testobj3 testobj4 testobj5 testobj6 \
+ libmarkermod4-1 libmarkermod4-2 libmarkermod4-3 libmarkermod4-4 \
+ tst-tls20mod-bad tst-tls21mod tst-dlmopen-dlerror-mod \
+ tst-auxvalmod \
+- tst-dlmopen-gethostbyname-mod \
++ tst-dlmopen-gethostbyname-mod tst-ro-dynamic-mod \
+
+ # Most modules build with _ISOMAC defined, but those filtered out
+ # depend on internal headers.
+@@ -1911,3 +1911,10 @@ $(objpfx)tst-getauxval-static.out: $(objpfx)tst-auxvalmod.so
+ tst-getauxval-static-ENV = LD_LIBRARY_PATH=$(objpfx):$(common-objpfx)
+
+ $(objpfx)tst-dlmopen-gethostbyname.out: $(objpfx)tst-dlmopen-gethostbyname-mod.so
++
++$(objpfx)tst-ro-dynamic: $(objpfx)tst-ro-dynamic-mod.so
++$(objpfx)tst-ro-dynamic-mod.so: $(objpfx)tst-ro-dynamic-mod.os \
++ tst-ro-dynamic-mod.map
++ $(LINK.o) -nostdlib -nostartfiles -shared -o $@ \
++ -Wl,--script=tst-ro-dynamic-mod.map \
++ $(objpfx)tst-ro-dynamic-mod.os
+diff --git a/elf/dl-load.c b/elf/dl-load.c
+index 39e0d07..6ea7107 100644
+--- a/elf/dl-load.c
++++ b/elf/dl-load.c
+@@ -1149,6 +1149,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ such a segment to avoid a crash later. */
+ l->l_ld = (void *) ph->p_vaddr;
+ l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
++ l->l_ld_readonly = (ph->p_flags & PF_W) == 0;
+ }
+ break;
+
+@@ -1292,7 +1293,7 @@ _dl_map_object_from_fd (const char *name, const char *origname, int fd,
+ else
+ l->l_ld = (ElfW(Dyn) *) ((ElfW(Addr)) l->l_ld + l->l_addr);
+
+- elf_get_dynamic_info (l, NULL);
++ elf_get_dynamic_info (l);
+
+ /* Make sure we are not dlopen'ing an object that has the
+ DF_1_NOOPEN flag set, or a PIE object. */
+diff --git a/elf/dl-reloc-static-pie.c b/elf/dl-reloc-static-pie.c
+index 289651b..68ded17 100644
+--- a/elf/dl-reloc-static-pie.c
++++ b/elf/dl-reloc-static-pie.c
+@@ -40,7 +40,17 @@ _dl_relocate_static_pie (void)
+
+ /* Read our own dynamic section and fill in the info array. */
+ main_map->l_ld = ((void *) main_map->l_addr + elf_machine_dynamic ());
+- elf_get_dynamic_info (main_map, NULL);
++
++ const ElfW(Phdr) *ph, *phdr = GL(dl_phdr);
++ size_t phnum = GL(dl_phnum);
++ for (ph = phdr; ph < &phdr[phnum]; ++ph)
++ if (ph->p_type == PT_DYNAMIC)
++ {
++ main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
++ break;
++ }
++
++ elf_get_dynamic_info (main_map);
+
+ # ifdef ELF_MACHINE_BEFORE_RTLD_RELOC
+ ELF_MACHINE_BEFORE_RTLD_RELOC (main_map->l_info);
+diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
+index d8ec323..4aa2058 100644
+--- a/elf/get-dynamic-info.h
++++ b/elf/get-dynamic-info.h
+@@ -28,7 +28,7 @@ static
+ auto
+ #endif
+ inline void __attribute__ ((unused, always_inline))
+-elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
++elf_get_dynamic_info (struct link_map *l)
+ {
+ #if __ELF_NATIVE_CLASS == 32
+ typedef Elf32_Word d_tag_utype;
+@@ -69,28 +69,15 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
+ info[i] = dyn;
+ }
+
+-#define DL_RO_DYN_TEMP_CNT 8
+-
+-#ifndef DL_RO_DYN_SECTION
+ /* Don't adjust .dynamic unnecessarily. */
+- if (l->l_addr != 0)
++ if (l->l_addr != 0 && dl_relocate_ld (l))
+ {
+ ElfW(Addr) l_addr = l->l_addr;
+- int cnt = 0;
+
+ # define ADJUST_DYN_INFO(tag) \
+ do \
+ if (info[tag] != NULL) \
+- { \
+- if (temp) \
+- { \
+- temp[cnt].d_tag = info[tag]->d_tag; \
+- temp[cnt].d_un.d_ptr = info[tag]->d_un.d_ptr + l_addr; \
+- info[tag] = temp + cnt++; \
+- } \
+- else \
+- info[tag]->d_un.d_ptr += l_addr; \
+- } \
++ info[tag]->d_un.d_ptr += l_addr; \
+ while (0)
+
+ ADJUST_DYN_INFO (DT_HASH);
+@@ -107,9 +94,7 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
+ ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM));
+ ADJUST_DYN_INFO (ADDRIDX (DT_GNU_HASH));
+ # undef ADJUST_DYN_INFO
+- assert (cnt <= DL_RO_DYN_TEMP_CNT);
+ }
+-#endif
+ if (info[DT_PLTREL] != NULL)
+ {
+ #if ELF_MACHINE_NO_RELA
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 742c413..8d2bba3 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -463,6 +463,7 @@ _dl_start_final (void *arg, struct dl_start_final_info *info)
+ #ifndef DONT_USE_BOOTSTRAP_MAP
+ GL(dl_rtld_map).l_addr = info->l.l_addr;
+ GL(dl_rtld_map).l_ld = info->l.l_ld;
++ GL(dl_rtld_map).l_ld_readonly = info->l.l_ld_readonly;
+ memcpy (GL(dl_rtld_map).l_info, info->l.l_info,
+ sizeof GL(dl_rtld_map).l_info);
+ GL(dl_rtld_map).l_mach = info->l.l_mach;
+@@ -546,7 +547,7 @@ _dl_start (void *arg)
+
+ /* Read our own dynamic section and fill in the info array. */
+ bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic ();
+- elf_get_dynamic_info (&bootstrap_map, NULL);
++ elf_get_dynamic_info (&bootstrap_map);
+
+ #if NO_TLS_OFFSET != 0
+ bootstrap_map.l_tls_offset = NO_TLS_OFFSET;
+@@ -1468,6 +1469,7 @@ dl_main (const ElfW(Phdr) *phdr,
+ /* This tells us where to find the dynamic section,
+ which tells us everything we need to do. */
+ main_map->l_ld = (void *) main_map->l_addr + ph->p_vaddr;
++ main_map->l_ld_readonly = (ph->p_flags & PF_W) == 0;
+ break;
+ case PT_INTERP:
+ /* This "interpreter segment" was used by the program loader to
+@@ -1613,7 +1615,7 @@ dl_main (const ElfW(Phdr) *phdr,
+ if (! rtld_is_main)
+ {
+ /* Extract the contents of the dynamic section for easy access. */
+- elf_get_dynamic_info (main_map, NULL);
++ elf_get_dynamic_info (main_map);
+
+ /* If the main map is libc.so, update the base namespace to
+ refer to this map. If libc.so is loaded later, this happens
+diff --git a/elf/setup-vdso.h b/elf/setup-vdso.h
+index 86c491e..f44748b 100644
+--- a/elf/setup-vdso.h
++++ b/elf/setup-vdso.h
+@@ -33,8 +33,6 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
+ 0, LM_ID_BASE);
+ if (__glibc_likely (l != NULL))
+ {
+- static ElfW(Dyn) dyn_temp[DL_RO_DYN_TEMP_CNT] attribute_relro;
+-
+ l->l_phdr = ((const void *) GLRO(dl_sysinfo_dso)
+ + GLRO(dl_sysinfo_dso)->e_phoff);
+ l->l_phnum = GLRO(dl_sysinfo_dso)->e_phnum;
+@@ -45,6 +43,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
+ {
+ l->l_ld = (void *) ph->p_vaddr;
+ l->l_ldnum = ph->p_memsz / sizeof (ElfW(Dyn));
++ l->l_ld_readonly = (ph->p_flags & PF_W) == 0;
+ }
+ else if (ph->p_type == PT_LOAD)
+ {
+@@ -65,7 +64,7 @@ setup_vdso (struct link_map *main_map __attribute__ ((unused)),
+ l->l_map_end += l->l_addr;
+ l->l_text_end += l->l_addr;
+ l->l_ld = (void *) ((ElfW(Addr)) l->l_ld + l->l_addr);
+- elf_get_dynamic_info (l, dyn_temp);
++ elf_get_dynamic_info (l);
+ _dl_setup_hash (l);
+ l->l_relocated = 1;
+
+diff --git a/elf/tst-ro-dynamic-mod.c b/elf/tst-ro-dynamic-mod.c
+new file mode 100644
+index 0000000..6d99925
+--- /dev/null
++++ b/elf/tst-ro-dynamic-mod.c
+@@ -0,0 +1,19 @@
++/* Test case for DSO with readonly dynamic section.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++int foo = -1;
+diff --git a/elf/tst-ro-dynamic-mod.map b/elf/tst-ro-dynamic-mod.map
+new file mode 100644
+index 0000000..2fe4a29
+--- /dev/null
++++ b/elf/tst-ro-dynamic-mod.map
+@@ -0,0 +1,16 @@
++SECTIONS
++{
++ . = SIZEOF_HEADERS;
++ .dynamic : { *(.dynamic) } :text :dynamic
++ .rodata : { *(.data*) *(.bss*) } :text
++ /DISCARD/ : {
++ *(.note.gnu.property)
++ }
++ .note : { *(.note.*) } :text :note
++}
++PHDRS
++{
++ text PT_LOAD FLAGS(5) FILEHDR PHDRS;
++ dynamic PT_DYNAMIC FLAGS(4);
++ note PT_NOTE FLAGS(4);
++}
+diff --git a/elf/tst-ro-dynamic.c b/elf/tst-ro-dynamic.c
+new file mode 100644
+index 0000000..3a18f87
+--- /dev/null
++++ b/elf/tst-ro-dynamic.c
+@@ -0,0 +1,31 @@
++/* Test case for DSO with readonly dynamic section.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <support/check.h>
++#include <support/test-driver.h>
++
++extern int foo;
++
++static int
++do_test (void)
++{
++ TEST_COMPARE (foo, -1);
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/include/link.h b/include/link.h
+index 7b8250d..484ee6c 100644
+--- a/include/link.h
++++ b/include/link.h
+@@ -205,6 +205,7 @@ struct link_map
+ unsigned int l_free_initfini:1; /* Nonzero if l_initfini can be
+ freed, ie. not allocated with
+ the dummy malloc in ld.so. */
++ unsigned int l_ld_readonly:1; /* Nonzero if dynamic section is readonly. */
+
+ /* NODELETE status of the map. Only valid for maps of type
+ lt_loaded. Lazy binding sets l_nodelete_active directly,
+@@ -342,6 +343,8 @@ struct link_map
+ unsigned long long int l_serial;
+ };
+
++#include <dl-relocate-ld.h>
++
+ /* Information used by audit modules. For most link maps, this data
+ immediate follows the link map in memory. For the dynamic linker,
+ it is allocated separately. See link_map_audit_state in
+diff --git a/sysdeps/generic/dl-relocate-ld.h b/sysdeps/generic/dl-relocate-ld.h
+new file mode 100644
+index 0000000..5fae206
+--- /dev/null
++++ b/sysdeps/generic/dl-relocate-ld.h
+@@ -0,0 +1,32 @@
++/* Check if dynamic section should be relocated. Generic version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _DL_RELOCATE_LD_H
++#define _DL_RELOCATE_LD_H
++
++/* Return true if dynamic section in the shared library L should be
++ relocated. */
++
++static inline bool
++dl_relocate_ld (const struct link_map *l)
++{
++ /* Don't relocate dynamic section if it is readonly */
++ return !l->l_ld_readonly;
++}
++
++#endif /* _DL_RELOCATE_LD_H */
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index 6e50fcd..d49529d 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -75,11 +75,8 @@ __BEGIN_DECLS
+ have to be accessed via the D_PTR macro. The macro is needed since for
+ most architectures the entry is already relocated - but for some not
+ and we need to relocate at access time. */
+-#ifdef DL_RO_DYN_SECTION
+-# define D_PTR(map, i) ((map)->i->d_un.d_ptr + (map)->l_addr)
+-#else
+-# define D_PTR(map, i) (map)->i->d_un.d_ptr
+-#endif
++#define D_PTR(map, i) \
++ ((map)->i->d_un.d_ptr + (dl_relocate_ld (map) ? 0 : (map)->l_addr))
+
+ /* Result of the lookup functions and how to retrieve the base address. */
+ typedef struct link_map *lookup_t;
+diff --git a/sysdeps/mips/dl-relocate-ld.h b/sysdeps/mips/dl-relocate-ld.h
+new file mode 100644
+index 0000000..0c18d9a
+--- /dev/null
++++ b/sysdeps/mips/dl-relocate-ld.h
+@@ -0,0 +1,32 @@
++/* Check if dynamic section should be relocated. MIPS version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _DL_RELOCATE_LD_H
++#define _DL_RELOCATE_LD_H
++
++/* Return true if dynamic section in the shared library L should be
++ relocated. */
++
++static inline bool
++dl_relocate_ld (const struct link_map *l)
++{
++ /* Never relocate dynamic section. */
++ return false;
++}
++
++#endif /* _DL_RELOCATE_LD_H */
+diff --git a/sysdeps/mips/ldsodefs.h b/sysdeps/mips/ldsodefs.h
+index 4db7c60..36fd09a 100644
+--- a/sysdeps/mips/ldsodefs.h
++++ b/sysdeps/mips/ldsodefs.h
+@@ -75,10 +75,6 @@ struct La_mips_64_retval;
+ struct La_mips_64_retval *, \
+ const char *);
+
+-/* The MIPS ABI specifies that the dynamic section has to be read-only. */
+-
+-#define DL_RO_DYN_SECTION 1
+-
+ #include_next <ldsodefs.h>
+
+ /* The 64-bit MIPS ELF ABI uses an unusual reloc format. Each
+diff --git a/sysdeps/riscv/dl-relocate-ld.h b/sysdeps/riscv/dl-relocate-ld.h
+new file mode 100644
+index 0000000..1032745
+--- /dev/null
++++ b/sysdeps/riscv/dl-relocate-ld.h
+@@ -0,0 +1,32 @@
++/* Check if dynamic section should be relocated. RISC-V version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _DL_RELOCATE_LD_H
++#define _DL_RELOCATE_LD_H
++
++/* Return true if dynamic section in the shared library L should be
++ relocated. */
++
++static inline bool
++dl_relocate_ld (const struct link_map *l)
++{
++ /* Never relocate dynamic section for ABI compatibility. */
++ return false;
++}
++
++#endif /* _DL_RELOCATE_LD_H */
+diff --git a/sysdeps/riscv/ldsodefs.h b/sysdeps/riscv/ldsodefs.h
+index 0c69671..8947ffe 100644
+--- a/sysdeps/riscv/ldsodefs.h
++++ b/sysdeps/riscv/ldsodefs.h
+@@ -38,11 +38,6 @@ struct La_riscv_retval;
+ struct La_riscv_retval *, \
+ const char *);
+
+-/* Although the RISC-V ABI does not specify that the dynamic section has
+- to be read-only, it needs to be kept for ABI compatibility. */
+-
+-#define DL_RO_DYN_SECTION 1
+-
+ #include_next <ldsodefs.h>
+
+ #endif
+--
+1.8.3.1
+
diff --git a/ldconfig-avoid-leak-on-empty-paths-in-config-file.patch b/ldconfig-avoid-leak-on-empty-paths-in-config-file.patch
new file mode 100644
index 0000000..c415a47
--- /dev/null
+++ b/ldconfig-avoid-leak-on-empty-paths-in-config-file.patch
@@ -0,0 +1,30 @@
+From b0234d79e7d82475d1666f25326ec045c045b3ed Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Tue, 3 Aug 2021 21:10:10 +0530
+Subject: [PATCH] ldconfig: avoid leak on empty paths in config file
+
+Reviewed-by: Arjun Shankar <arjun@redhat.com>
+---
+ elf/ldconfig.c | 6 +++++-
+ 1 file changed, 5 insertions(+), 1 deletion(-)
+
+diff --git a/elf/ldconfig.c b/elf/ldconfig.c
+index 1037e8d..b889363 100644
+--- a/elf/ldconfig.c
++++ b/elf/ldconfig.c
+@@ -503,7 +503,11 @@ add_dir_1 (const char *line, const char *from_file, int from_line)
+ entry->path[--i] = '\0';
+
+ if (i == 0)
+- return;
++ {
++ free (entry->path);
++ free (entry);
++ return;
++ }
+
+ char *path = entry->path;
+ if (opt_chroot != NULL)
+--
+1.8.3.1
+
diff --git a/libio-Ensure-output-buffer-for-wchars-bug-28828.patch b/libio-Ensure-output-buffer-for-wchars-bug-28828.patch
new file mode 100644
index 0000000..6cb10d5
--- /dev/null
+++ b/libio-Ensure-output-buffer-for-wchars-bug-28828.patch
@@ -0,0 +1,110 @@
+From edc696a73a7cb07b1aa68792a845a98d036ee7eb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Jos=C3=A9=20Bollo?= <jobol@nonadev.net>
+Date: Tue, 8 Mar 2022 09:58:16 +0100
+Subject: [PATCH] libio: Ensure output buffer for wchars (bug #28828)
+
+The _IO_wfile_overflow does not check if the write pointer for wide
+data is valid before access, different than _IO_file_overflow. This
+leads to crash on some cases, as described by bug 28828.
+
+The minimal sequence to produce the crash was:
+
+ #include <stdio.h>
+ #include <wchar.h>
+ int main (int ac, char **av)
+ {
+ setvbuf (stdout, NULL, _IOLBF, 0);
+ fgetwc (stdin);
+ fputwc (10, stdout); /*CRASH HERE!*/
+ return 0;
+ }
+
+The "fgetwc(stdin);" is necessary since it triggers the bug by setting
+the flag _IO_CURRENTLY_PUTTING on stdout indirectly (file wfileops.c,
+function _IO_wfile_underflow, line 213).
+
+Signed-off-by: Jose Bollo <jobol@nonadev.net>
+---
+ libio/Makefile | 2 +-
+ libio/tst-bz28828.c | 32 ++++++++++++++++++++++++++++++++
+ libio/tst-bz28828.input | 1 +
+ libio/wfileops.c | 3 ++-
+ 4 files changed, 36 insertions(+), 2 deletions(-)
+ create mode 100644 libio/tst-bz28828.c
+ create mode 100644 libio/tst-bz28828.input
+
+diff --git a/libio/Makefile b/libio/Makefile
+index 0e5f348..e973877 100644
+--- a/libio/Makefile
++++ b/libio/Makefile
+@@ -66,7 +66,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
+ tst-fwrite-error tst-ftell-partial-wide tst-ftell-active-handler \
+ tst-ftell-append tst-fputws tst-bz22415 tst-fgetc-after-eof \
+ tst-sprintf-ub tst-sprintf-chk-ub tst-bz24051 tst-bz24153 \
+- tst-wfile-sync
++ tst-wfile-sync tst-bz28828
+
+ tests-internal = tst-vtables tst-vtables-interposed
+
+diff --git a/libio/tst-bz28828.c b/libio/tst-bz28828.c
+new file mode 100644
+index 0000000..638a6e2
+--- /dev/null
++++ b/libio/tst-bz28828.c
+@@ -0,0 +1,32 @@
++/* Unit test for BZ#28828.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <support/xstdio.h>
++#include <support/check.h>
++#include <wchar.h>
++
++static int
++do_test (void)
++{
++ setvbuf (stdout, NULL, _IOLBF, 0);
++ fgetwc (stdin);
++ fputwc (10, stdout); /* It should not crash here. */
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/libio/tst-bz28828.input b/libio/tst-bz28828.input
+new file mode 100644
+index 0000000..ce01362
+--- /dev/null
++++ b/libio/tst-bz28828.input
+@@ -0,0 +1 @@
++hello
+diff --git a/libio/wfileops.c b/libio/wfileops.c
+index fb9d45b..b59a988 100644
+--- a/libio/wfileops.c
++++ b/libio/wfileops.c
+@@ -412,7 +412,8 @@ _IO_wfile_overflow (FILE *f, wint_t wch)
+ return WEOF;
+ }
+ /* If currently reading or no buffer allocated. */
+- if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0)
++ if ((f->_flags & _IO_CURRENTLY_PUTTING) == 0
++ || f->_wide_data->_IO_write_base == NULL)
+ {
+ /* Allocate a buffer if needed. */
+ if (f->_wide_data->_IO_write_base == 0)
+--
+1.8.3.1
+
diff --git a/libio-Flush-only-_IO_str_overflow-must-not-return-EO.patch b/libio-Flush-only-_IO_str_overflow-must-not-return-EO.patch
new file mode 100644
index 0000000..ab1962f
--- /dev/null
+++ b/libio-Flush-only-_IO_str_overflow-must-not-return-EO.patch
@@ -0,0 +1,54 @@
+From 88ed43ff0cf2561481de7cba00686386794515d6 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 18 Mar 2022 21:27:54 +0100
+Subject: [PATCH] libio: Flush-only _IO_str_overflow must not return EOF (bug
+ 28949)
+
+In general, _IO_str_overflow returns the character passed as an argument
+on success. However, if flush-only operation is requested by passing
+EOF, returning EOF looks like an error, and the caller cannot tell
+whether the operation was successful or not.
+
+_IO_wstr_overflow had the same bug regarding WEOF.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ libio/strops.c | 5 ++++-
+ libio/wstrops.c | 5 ++++-
+ 2 files changed, 8 insertions(+), 2 deletions(-)
+
+diff --git a/libio/strops.c b/libio/strops.c
+index 6a9a884..1cd0bf6 100644
+--- a/libio/strops.c
++++ b/libio/strops.c
+@@ -133,7 +133,10 @@ _IO_str_overflow (FILE *fp, int c)
+ *fp->_IO_write_ptr++ = (unsigned char) c;
+ if (fp->_IO_write_ptr > fp->_IO_read_end)
+ fp->_IO_read_end = fp->_IO_write_ptr;
+- return c;
++ if (flush_only)
++ return 0;
++ else
++ return c;
+ }
+ libc_hidden_def (_IO_str_overflow)
+
+diff --git a/libio/wstrops.c b/libio/wstrops.c
+index 8e44f86..2aec3149 100644
+--- a/libio/wstrops.c
++++ b/libio/wstrops.c
+@@ -130,7 +130,10 @@ _IO_wstr_overflow (FILE *fp, wint_t c)
+ *fp->_wide_data->_IO_write_ptr++ = c;
+ if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_read_end)
+ fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_write_ptr;
+- return c;
++ if (flush_only)
++ return 0;
++ else
++ return c;
+ }
+
+
+--
+1.8.3.1
+
diff --git a/linux-Add-a-getauxval-test-BZ-23293.patch b/linux-Add-a-getauxval-test-BZ-23293.patch
new file mode 100644
index 0000000..f3f41cf
--- /dev/null
+++ b/linux-Add-a-getauxval-test-BZ-23293.patch
@@ -0,0 +1,114 @@
+From 9faf5262c77487c96da8a3e961b88c0b1879e186 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Tue, 3 May 2022 13:18:04 +0100
+Subject: [PATCH 3/4] linux: Add a getauxval test [BZ #23293]
+
+Conflict:adapt Makefile context
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=9faf5262c77487c96da8a3e961b88c0b1879e186
+
+This is for bug 23293 and it relies on the glibc test system running
+tests via explicit ld.so invokation by default.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ sysdeps/unix/sysv/linux/Makefile | 1 +
+ sysdeps/unix/sysv/linux/tst-getauxval.c | 74 +++++++++++++++++++++++++
+ 2 files changed, 75 insertions(+)
+ create mode 100644 sysdeps/unix/sysv/linux/tst-getauxval.c
+
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index ca953804d0..89cb005c7d 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -126,6 +126,7 @@ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
+ tst-close_range \
+ tst-prctl \
+ tst-scm_rights \
++ tst-getauxval \
+ # tests
+
+ # Test for the symbol version of fcntl that was replaced in glibc 2.28.
+diff --git a/sysdeps/unix/sysv/linux/tst-getauxval.c b/sysdeps/unix/sysv/linux/tst-getauxval.c
+new file mode 100644
+index 0000000000..c4b6195743
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-getauxval.c
+@@ -0,0 +1,74 @@
++/* Basic test for getauxval.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <unistd.h>
++#include <stdio.h>
++#include <support/check.h>
++#include <sys/auxv.h>
++
++static int missing;
++static int mismatch;
++
++static void
++check_nonzero (unsigned long t, const char *s)
++{
++ unsigned long v = getauxval (t);
++ printf ("%s: %lu (0x%lx)\n", s, v, v);
++ if (v == 0)
++ missing++;
++}
++
++static void
++check_eq (unsigned long t, const char *s, unsigned long want)
++{
++ unsigned long v = getauxval (t);
++ printf ("%s: %lu want: %lu\n", s, v, want);
++ if (v != want)
++ mismatch++;
++}
++
++#define NZ(x) check_nonzero (x, #x)
++#define EQ(x, want) check_eq (x, #x, want)
++
++static int
++do_test (void)
++{
++ /* These auxv entries should be non-zero on Linux. */
++ NZ (AT_PHDR);
++ NZ (AT_PHENT);
++ NZ (AT_PHNUM);
++ NZ (AT_PAGESZ);
++ NZ (AT_ENTRY);
++ NZ (AT_CLKTCK);
++ NZ (AT_RANDOM);
++ NZ (AT_EXECFN);
++ if (missing)
++ FAIL_EXIT1 ("Found %d missing auxv entries.\n", missing);
++
++ /* Check against syscalls. */
++ EQ (AT_UID, getuid ());
++ EQ (AT_EUID, geteuid ());
++ EQ (AT_GID, getgid ());
++ EQ (AT_EGID, getegid ());
++ if (mismatch)
++ FAIL_EXIT1 ("Found %d mismatching auxv entries.\n", mismatch);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.27.0
+
diff --git a/linux-Fix-__closefrom_fallback-iterates-until-max-in.patch b/linux-Fix-__closefrom_fallback-iterates-until-max-in.patch
new file mode 100644
index 0000000..1b46598
--- /dev/null
+++ b/linux-Fix-__closefrom_fallback-iterates-until-max-in.patch
@@ -0,0 +1,58 @@
+From 053fe273434056f551ed8f81daf750db9dab5931 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 23 Mar 2022 17:40:01 -0300
+Subject: [PATCH] linux: Fix __closefrom_fallback iterates until max int
+ (BZ#28993)
+
+The __closefrom_fallback tries to get a available file descriptor
+if the initial open ("/proc/self/fd/", ...) fails. It assumes the
+failure would be only if procfs is not mount (ENOENT), however if
+the the proc file is not accessible (due some other kernel filtering
+such apparmor) it will iterate over a potentially large file set
+issuing close calls.
+
+It should only try the close fallback if open returns EMFILE,
+ENFILE, or ENOMEM.
+
+Checked on x86_64-linux-gnu.
+---
+ sysdeps/unix/sysv/linux/closefrom_fallback.c | 11 ++++++-----
+ 1 file changed, 6 insertions(+), 5 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/closefrom_fallback.c b/sysdeps/unix/sysv/linux/closefrom_fallback.c
+index 60101aa..a9dd0c4 100644
+--- a/sysdeps/unix/sysv/linux/closefrom_fallback.c
++++ b/sysdeps/unix/sysv/linux/closefrom_fallback.c
+@@ -30,16 +30,16 @@
+ _Bool
+ __closefrom_fallback (int from, _Bool dirfd_fallback)
+ {
+- bool ret = false;
+-
+ int dirfd = __open_nocancel (FD_TO_FILENAME_PREFIX, O_RDONLY | O_DIRECTORY,
+ 0);
+ if (dirfd == -1)
+ {
+- /* The closefrom should work even when process can't open new files. */
+- if (errno == ENOENT || !dirfd_fallback)
+- goto err;
++ /* Return if procfs can not be opened for some reason. */
++ if ((errno != EMFILE && errno != ENFILE && errno != ENOMEM)
++ || !dirfd_fallback)
++ return false;
+
++ /* The closefrom should work even when process can't open new files. */
+ for (int i = from; i < INT_MAX; i++)
+ {
+ int r = __close_nocancel (i);
+@@ -54,6 +54,7 @@ __closefrom_fallback (int from, _Bool dirfd_fallback)
+ }
+
+ char buffer[1024];
++ bool ret = false;
+ while (true)
+ {
+ ssize_t ret = __getdents64 (dirfd, buffer, sizeof (buffer));
+--
+1.8.3.1
+
diff --git a/linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch b/linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch
new file mode 100644
index 0000000..a4bf1ed
--- /dev/null
+++ b/linux-Fix-ancillary-64-bit-time-timestamp-conversion.patch
@@ -0,0 +1,457 @@
+From e098446037da532d4a250efac9a813bc22f3669f Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 24 Jan 2022 08:55:53 -0300
+Subject: [PATCH] linux: Fix ancillary 64-bit time timestamp conversion (BZ
+ #28349, BZ#28350)
+
+The __convert_scm_timestamps only updates the control message last
+pointer for SOL_SOCKET type, so if the message control buffer contains
+multiple ancillary message types the converted timestamp one might
+overwrite a valid message.
+
+The test checks if the extra ancillary space is correctly handled
+by recvmsg/recvmmsg, where if there is no extra space for the 64-bit
+time_t converted message the control buffer should be marked with
+MSG_TRUNC. It also check if recvmsg/recvmmsg handle correctly multiple
+ancillary data.
+
+Checked on x86_64-linux and on i686-linux-gnu on both 5.11 and
+4.15 kernel.
+
+Co-authored-by: Fabian Vogt <fvogt@suse.de>
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+(cherry picked from commit 8fba672472ae0055387e9315fc2eddfa6775ca79)
+---
+ NEWS | 3 +
+ sysdeps/unix/sysv/linux/Makefile | 3 +
+ .../unix/sysv/linux/convert_scm_timestamps.c | 14 +-
+ .../sysv/linux/tst-socket-timestamp-time64.c | 1 +
+ .../unix/sysv/linux/tst-socket-timestamp.c | 336 ++++++++++++++++++
+ 5 files changed, 351 insertions(+), 6 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c
+ create mode 100644 sysdeps/unix/sysv/linux/tst-socket-timestamp.c
+
+diff --git a/NEWS b/NEWS
+index db50b2af..e5225e9f 100644
+--- a/NEWS
++++ b/NEWS
+@@ -26,6 +26,9 @@ The following bugs are resolved with this release:
+ [12889] nptl: Fix race between pthread_kill and thread exit
+ [19193] nptl: pthread_kill, pthread_cancel should not fail after exit
+ [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix"
++ [28349] libc: Segfault for ping -R on qemux86 caused by recvmsg()
++ [28350] libc: ping receives SIGABRT on lib32-qemux86-64 caused by
++ recvmsg()
+
+
+ Version 2.34
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index 76ad0636..3399c874 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -262,6 +262,9 @@ sysdep_routines += cmsg_nxthdr
+ CFLAGS-recvmmsg.c = -fexceptions -fasynchronous-unwind-tables
+ CFLAGS-sendmmsg.c = -fexceptions -fasynchronous-unwind-tables
+
++tests += tst-socket-timestamp
++tests-time64 += tst-socket-timestamp-time64
++
+ tests-special += $(objpfx)tst-socket-consts.out
+ $(objpfx)tst-socket-consts.out: ../sysdeps/unix/sysv/linux/tst-socket-consts.py
+ PYTHONPATH=../scripts \
+diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
+index 00c934c4..5d3c4199 100644
+--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
++++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
+@@ -54,6 +54,8 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
+ cmsg != NULL;
+ cmsg = CMSG_NXTHDR (msg, cmsg))
+ {
++ last = cmsg;
++
+ if (cmsg->cmsg_level != SOL_SOCKET)
+ continue;
+
+@@ -75,11 +77,9 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
+ tvts[1] = tmp[1];
+ break;
+ }
+-
+- last = cmsg;
+ }
+
+- if (last == NULL || type == 0)
++ if (type == 0)
+ return;
+
+ if (CMSG_SPACE (sizeof tvts) > msgsize - msg->msg_controllen)
+@@ -88,10 +88,12 @@ __convert_scm_timestamps (struct msghdr *msg, socklen_t msgsize)
+ return;
+ }
+
++ /* Zero memory for the new cmsghdr, so reading cmsg_len field
++ by CMSG_NXTHDR does not trigger UB. */
++ memset (msg->msg_control + msg->msg_controllen, 0,
++ CMSG_SPACE (sizeof tvts));
+ msg->msg_controllen += CMSG_SPACE (sizeof tvts);
+- cmsg = CMSG_NXTHDR(msg, last);
+- if (cmsg == NULL)
+- return;
++ cmsg = CMSG_NXTHDR (msg, last);
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = type;
+ cmsg->cmsg_len = CMSG_LEN (sizeof tvts);
+diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c
+new file mode 100644
+index 00000000..ae424c2a
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-time64.c
+@@ -0,0 +1 @@
++#include "tst-socket-timestamp.c"
+diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c
+new file mode 100644
+index 00000000..9c2e76f7
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp.c
+@@ -0,0 +1,336 @@
++/* Check recvmsg/recvmmsg 64-bit timestamp support.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <array_length.h>
++#include <arpa/inet.h>
++#include <errno.h>
++#include <string.h>
++#include <stdio.h>
++#include <support/check.h>
++#include <support/next_to_fault.h>
++#include <support/support.h>
++#include <support/test-driver.h>
++#include <support/xunistd.h>
++#include <support/xsocket.h>
++#include <sys/mman.h>
++
++/* Some extra space added for ancillary data, it might be used to convert
++ 32-bit timestamp to 64-bit for _TIME_BITS=64. */
++enum { slack_max_size = 64 };
++static const int slack[] = { 0, 4, 8, 16, 32, slack_max_size };
++
++static bool support_64_timestamp;
++/* AF_INET socket and address used to receive data. */
++static int srv;
++static struct sockaddr_in srv_addr;
++
++static int
++do_sendto (const struct sockaddr_in *addr, int nmsgs)
++{
++ int s = xsocket (AF_INET, SOCK_DGRAM | SOCK_CLOEXEC, 0);
++ xconnect (s, (const struct sockaddr *) addr, sizeof (*addr));
++
++ for (int i = 0; i < nmsgs; i++)
++ xsendto (s, &i, sizeof (i), 0, (const struct sockaddr *) addr,
++ sizeof (*addr));
++
++ xclose (s);
++
++ return 0;
++}
++
++static void
++do_recvmsg_slack_ancillary (bool use_multi_call, int s, void *cmsg,
++ size_t slack, size_t tsize, int exp_payload)
++{
++ int payload;
++ struct iovec iov =
++ {
++ .iov_base = &payload,
++ .iov_len = sizeof (payload)
++ };
++ size_t msg_controllen = CMSG_SPACE (tsize) + slack;
++ char *msg_control = cmsg - msg_controllen;
++ memset (msg_control, 0x55, msg_controllen);
++ struct mmsghdr mmhdr =
++ {
++ .msg_hdr =
++ {
++ .msg_name = NULL,
++ .msg_namelen = 0,
++ .msg_iov = &iov,
++ .msg_iovlen = 1,
++ .msg_control = msg_control,
++ .msg_controllen = msg_controllen
++ },
++ };
++
++ int r;
++ if (use_multi_call)
++ {
++ r = recvmmsg (s, &mmhdr, 1, 0, NULL);
++ if (r >= 0)
++ r = mmhdr.msg_len;
++ }
++ else
++ r = recvmsg (s, &mmhdr.msg_hdr, 0);
++ TEST_COMPARE (r, sizeof (int));
++ TEST_COMPARE (payload, exp_payload);
++
++ if (cmsg == NULL)
++ return;
++
++ /* A timestamp is expected if 32-bit timestamp are used (support in every
++ configuration) or if underlying kernel support 64-bit timestamps.
++ Otherwise recvmsg will need extra space do add the 64-bit timestamp. */
++ bool exp_timestamp;
++ if (sizeof (time_t) == 4 || support_64_timestamp)
++ exp_timestamp = true;
++ else
++ exp_timestamp = slack >= CMSG_SPACE (tsize);
++
++ bool timestamp = false;
++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
++ cmsg != NULL;
++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
++ {
++ if (cmsg->cmsg_level != SOL_SOCKET)
++ continue;
++ if (cmsg->cmsg_type == SCM_TIMESTAMP
++ && cmsg->cmsg_len == CMSG_LEN (sizeof (struct timeval)))
++ {
++ struct timeval tv;
++ memcpy (&tv, CMSG_DATA (cmsg), sizeof (tv));
++ if (test_verbose)
++ printf ("SCM_TIMESTAMP: {%jd, %jd}\n", (intmax_t)tv.tv_sec,
++ (intmax_t)tv.tv_usec);
++ timestamp = true;
++ }
++ else if (cmsg->cmsg_type == SCM_TIMESTAMPNS
++ && cmsg->cmsg_len == CMSG_LEN (sizeof (struct timespec)))
++ {
++ struct timespec ts;
++ memcpy (&ts, CMSG_DATA (cmsg), sizeof (ts));
++ if (test_verbose)
++ printf ("SCM_TIMESTAMPNS: {%jd, %jd}\n", (intmax_t)ts.tv_sec,
++ (intmax_t)ts.tv_nsec);
++ timestamp = true;
++ }
++ }
++
++ TEST_COMPARE (timestamp, exp_timestamp);
++}
++
++/* Check if the extra ancillary space is correctly handled by recvmsg and
++ recvmmsg with different extra space for the ancillaty buffer. */
++static void
++do_test_slack_space (void)
++{
++ /* Setup the ancillary data buffer with an extra page with PROT_NONE to
++ check the possible timestamp conversion on some systems. */
++ struct support_next_to_fault nf =
++ support_next_to_fault_allocate (slack_max_size);
++ void *msgbuf = nf.buffer + slack_max_size;
++
++ /* Enable the timestamp using struct timeval precision. */
++ {
++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++ }
++ /* Check recvmsg. */
++ do_sendto (&srv_addr, array_length (slack));
++ for (int s = 0; s < array_length (slack); s++)
++ {
++ memset (nf.buffer, 0x55, nf.length);
++ do_recvmsg_slack_ancillary (false, srv, msgbuf, slack[s],
++ sizeof (struct timeval), s);
++ }
++ /* Check recvmmsg. */
++ do_sendto (&srv_addr, array_length (slack));
++ for (int s = 0; s < array_length (slack); s++)
++ {
++ memset (nf.buffer, 0x55, nf.length);
++ do_recvmsg_slack_ancillary (true, srv, msgbuf, slack[s],
++ sizeof (struct timeval), s);
++ }
++
++ /* Now enable timestamp using a higher precision, it overwrites the previous
++ precision. */
++ {
++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMPNS, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++ }
++ /* Check recvmsg. */
++ do_sendto (&srv_addr, array_length (slack));
++ for (int s = 0; s < array_length (slack); s++)
++ do_recvmsg_slack_ancillary (false, srv, msgbuf, slack[s],
++ sizeof (struct timespec), s);
++ /* Check recvmmsg. */
++ do_sendto (&srv_addr, array_length (slack));
++ for (int s = 0; s < array_length (slack); s++)
++ do_recvmsg_slack_ancillary (true, srv, msgbuf, slack[s],
++ sizeof (struct timespec), s);
++
++ support_next_to_fault_free (&nf);
++}
++
++/* Check if the converted 64-bit timestamp is correctly appended when there
++ are multiple ancillary messages. */
++static void
++do_recvmsg_multiple_ancillary (bool use_multi_call, int s, void *cmsg,
++ size_t cmsgsize, int exp_msg)
++{
++ int msg;
++ struct iovec iov =
++ {
++ .iov_base = &msg,
++ .iov_len = sizeof (msg)
++ };
++ size_t msgs = cmsgsize;
++ struct mmsghdr mmhdr =
++ {
++ .msg_hdr =
++ {
++ .msg_name = NULL,
++ .msg_namelen = 0,
++ .msg_iov = &iov,
++ .msg_iovlen = 1,
++ .msg_controllen = msgs,
++ .msg_control = cmsg,
++ },
++ };
++
++ int r;
++ if (use_multi_call)
++ {
++ r = recvmmsg (s, &mmhdr, 1, 0, NULL);
++ if (r >= 0)
++ r = mmhdr.msg_len;
++ }
++ else
++ r = recvmsg (s, &mmhdr.msg_hdr, 0);
++ TEST_COMPARE (r, sizeof (int));
++ TEST_COMPARE (msg, exp_msg);
++
++ if (cmsg == NULL)
++ return;
++
++ bool timestamp = false;
++ bool origdstaddr = false;
++ for (struct cmsghdr *cmsg = CMSG_FIRSTHDR (&mmhdr.msg_hdr);
++ cmsg != NULL;
++ cmsg = CMSG_NXTHDR (&mmhdr.msg_hdr, cmsg))
++ {
++ if (cmsg->cmsg_level == SOL_IP
++ && cmsg->cmsg_type == IP_ORIGDSTADDR
++ && cmsg->cmsg_len >= CMSG_LEN (sizeof (struct sockaddr_in)))
++ {
++ struct sockaddr_in sa;
++ memcpy (&sa, CMSG_DATA (cmsg), sizeof (sa));
++ if (test_verbose)
++ {
++ char str[INET_ADDRSTRLEN];
++ inet_ntop (AF_INET, &sa.sin_addr, str, INET_ADDRSTRLEN);
++ printf ("IP_ORIGDSTADDR: %s:%d\n", str, ntohs (sa.sin_port));
++ }
++ origdstaddr = sa.sin_addr.s_addr == srv_addr.sin_addr.s_addr
++ && sa.sin_port == srv_addr.sin_port;
++ }
++ if (cmsg->cmsg_level == SOL_SOCKET
++ && cmsg->cmsg_type == SCM_TIMESTAMP
++ && cmsg->cmsg_len >= CMSG_LEN (sizeof (struct timeval)))
++ {
++ struct timeval tv;
++ memcpy (&tv, CMSG_DATA (cmsg), sizeof (tv));
++ if (test_verbose)
++ printf ("SCM_TIMESTAMP: {%jd, %jd}\n", (intmax_t)tv.tv_sec,
++ (intmax_t)tv.tv_usec);
++ timestamp = true;
++ }
++ }
++
++ TEST_COMPARE (timestamp, true);
++ TEST_COMPARE (origdstaddr, true);
++}
++
++static void
++do_test_multiple_ancillary (void)
++{
++ {
++ int r = setsockopt (srv, SOL_SOCKET, SO_TIMESTAMP, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++ }
++ {
++ int r = setsockopt (srv, IPPROTO_IP, IP_RECVORIGDSTADDR, &(int){1},
++ sizeof (int));
++ TEST_VERIFY_EXIT (r != -1);
++ }
++
++ /* Enougth data for default SO_TIMESTAMP, the IP_RECVORIGDSTADDR, and the
++ extra 64-bit SO_TIMESTAMP. */
++ enum { msgbuflen = CMSG_SPACE (2 * sizeof (uint64_t))
++ + CMSG_SPACE (sizeof (struct sockaddr_in))
++ + CMSG_SPACE (2 * sizeof (uint64_t)) };
++ char msgbuf[msgbuflen];
++
++ enum { nmsgs = 8 };
++ /* Check recvmsg. */
++ do_sendto (&srv_addr, nmsgs);
++ for (int s = 0; s < nmsgs; s++)
++ do_recvmsg_multiple_ancillary (false, srv, msgbuf, msgbuflen, s);
++ /* Check recvmmsg. */
++ do_sendto (&srv_addr, nmsgs);
++ for (int s = 0; s < nmsgs; s++)
++ do_recvmsg_multiple_ancillary (true, srv, msgbuf, msgbuflen, s);
++}
++
++static int
++do_test (void)
++{
++ srv = xsocket (AF_INET, SOCK_DGRAM, 0);
++ srv_addr = (struct sockaddr_in) {
++ .sin_family = AF_INET,
++ .sin_addr = {.s_addr = htonl (INADDR_LOOPBACK) },
++ };
++ xbind (srv, (struct sockaddr *) &srv_addr, sizeof (srv_addr));
++ {
++ socklen_t sa_len = sizeof (srv_addr);
++ xgetsockname (srv, (struct sockaddr *) &srv_addr, &sa_len);
++ TEST_VERIFY (sa_len == sizeof (srv_addr));
++ }
++
++ TEST_COMPARE (recvmsg (-1, NULL, 0), -1);
++ TEST_COMPARE (errno, EBADF);
++ TEST_COMPARE (recvmmsg (-1, NULL, 0, 0, NULL), -1);
++ TEST_COMPARE (errno, EBADF);
++
++ /* If underlying kernel does not support */
++ support_64_timestamp = support_socket_so_timestamp_time64 (srv);
++
++ do_test_slack_space ();
++ do_test_multiple_ancillary ();
++
++ xclose (srv);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.27.0
+
diff --git a/linux-Fix-fchmodat-with-AT_SYMLINK_NOFOLLOW-for-64-b.patch b/linux-Fix-fchmodat-with-AT_SYMLINK_NOFOLLOW-for-64-b.patch
new file mode 100644
index 0000000..023912b
--- /dev/null
+++ b/linux-Fix-fchmodat-with-AT_SYMLINK_NOFOLLOW-for-64-b.patch
@@ -0,0 +1,139 @@
+From 88a8637cb4658cd91a002659db05867716b88b36 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 27 Apr 2022 13:40:30 -0300
+Subject: [PATCH] linux: Fix fchmodat with AT_SYMLINK_NOFOLLOW for 64 bit
+ time_t (BZ#29097)
+
+The AT_SYMLINK_NOFOLLOW emulation ues the default 32 bit stat internal
+calls, which fails with EOVERFLOW if the file constains timestamps
+beyond 2038.
+
+Checked on i686-linux-gnu.
+
+(cherry picked from commit 118a2aee07f64d605b6668cbe195c1f44eac6be6)
+---
+ NEWS | 2 ++
+ io/Makefile | 8 +++++---
+ io/tst-lchmod-time64.c | 2 ++
+ io/tst-lchmod.c | 22 +++++++++++++++++++++-
+ sysdeps/unix/sysv/linux/fchmodat.c | 4 ++--
+ 5 files changed, 32 insertions(+), 6 deletions(-)
+ create mode 100644 io/tst-lchmod-time64.c
+
+diff --git a/NEWS b/NEWS
+index 4965818..b444478 100644
+--- a/NEWS
++++ b/NEWS
+@@ -39,6 +39,8 @@ The following bugs are resolved with this release:
+ without /sys and /proc
+ [29029] nptl: poll() spuriously returns EINTR during thread
+ cancellation and with cancellation disabled
++ [29097] time: fchmodat does not handle 64 bit time_t for
++ AT_SYMLINK_NOFOLLOW
+
+
+ Version 2.34
+diff --git a/io/Makefile b/io/Makefile
+index 9871ecb..01968b8 100644
+--- a/io/Makefile
++++ b/io/Makefile
+@@ -82,16 +82,17 @@ tests := test-utime test-stat test-stat2 test-lfs tst-getcwd \
+ tst-ftw-bz28126
+
+ tests-time64 := \
++ tst-fcntl-time64 \
++ tst-fts-time64 \
+ tst-futimens-time64 \
+ tst-futimes-time64\
+- tst-fts-time64 \
++ tst-futimesat-time64 \
++ tst-lchmod-time64 \
+ tst-lutimes-time64 \
+ tst-stat-time64 \
+- tst-futimesat-time64 \
+ tst-utime-time64 \
+ tst-utimensat-time64 \
+ tst-utimes-time64 \
+- tst-fcntl-time64 \
+ # tests-time64
+
+ # Likewise for statx, but we do not need static linking here.
+@@ -134,6 +135,7 @@ CFLAGS-close.c += -fexceptions -fasynchronous-unwind-tables
+
+ CFLAGS-test-stat.c += -D_FILE_OFFSET_BITS=64 -D_LARGEFILE64_SOURCE
+ CFLAGS-test-lfs.c += -D_LARGEFILE64_SOURCE
++CFLAGS-tst-lchmod.c += -D_FILE_OFFSET_BITS=64
+
+ test-stat2-ARGS = Makefile . $(objpfx)test-stat2
+
+diff --git a/io/tst-lchmod-time64.c b/io/tst-lchmod-time64.c
+new file mode 100644
+index 0000000..f2b7cc9
+--- /dev/null
++++ b/io/tst-lchmod-time64.c
+@@ -0,0 +1,2 @@
++#define CHECK_TIME64
++#include "tst-lchmod.c"
+diff --git a/io/tst-lchmod.c b/io/tst-lchmod.c
+index 0fe98e0..472766b 100644
+--- a/io/tst-lchmod.c
++++ b/io/tst-lchmod.c
+@@ -67,9 +67,26 @@ select_path (bool do_relative_path, const char *full_path, const char *relative_
+ }
+
+ static void
++update_file_time_to_y2038 (const char *fname, int flags)
++{
++#ifdef CHECK_TIME64
++ /* Y2038 threshold plus 1 second. */
++ const struct timespec ts[] = { { 0x80000001LL, 0}, { 0x80000001LL } };
++ TEST_VERIFY_EXIT (utimensat (AT_FDCWD, fname, ts, flags) == 0);
++#endif
++}
++
++static void
+ test_1 (bool do_relative_path, int (*chmod_func) (int fd, const char *, mode_t, int))
+ {
+ char *tempdir = support_create_temp_directory ("tst-lchmod-");
++#ifdef CHECK_TIME64
++ if (!support_path_support_time64 (tempdir))
++ {
++ puts ("info: test skipped, filesystem does not support 64 bit time_t");
++ return;
++ }
++#endif
+
+ char *path_dangling = xasprintf ("%s/dangling", tempdir);
+ char *path_file = xasprintf ("%s/file", tempdir);
+@@ -93,9 +110,12 @@ test_1 (bool do_relative_path, int (*chmod_func) (int fd, const char *, mode_t,
+ xsymlink ("loop", path_loop);
+ xsymlink ("target-does-not-exist", path_dangling);
+
++ update_file_time_to_y2038 (path_file, 0);
++ update_file_time_to_y2038 (path_to_file, AT_SYMLINK_NOFOLLOW);
++
+ /* Check that the modes do not collide with what we will use in the
+ test. */
+- struct stat64 st;
++ struct stat st;
+ xstat (path_file, &st);
+ TEST_VERIFY ((st.st_mode & 0777) != 1);
+ xlstat (path_to_file, &st);
+diff --git a/sysdeps/unix/sysv/linux/fchmodat.c b/sysdeps/unix/sysv/linux/fchmodat.c
+index 5bd1eb9..b0cf619 100644
+--- a/sysdeps/unix/sysv/linux/fchmodat.c
++++ b/sysdeps/unix/sysv/linux/fchmodat.c
+@@ -48,8 +48,8 @@ fchmodat (int fd, const char *file, mode_t mode, int flag)
+
+ /* Use fstatat because fstat does not work on O_PATH descriptors
+ before Linux 3.6. */
+- struct stat64 st;
+- if (__fstatat64 (pathfd, "", &st, AT_EMPTY_PATH) != 0)
++ struct __stat64_t64 st;
++ if (__fstatat64_time64 (pathfd, "", &st, AT_EMPTY_PATH) != 0)
+ {
+ __close_nocancel (pathfd);
+ return -1;
+--
+1.8.3.1
+
diff --git a/linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch b/linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch
new file mode 100644
index 0000000..bcfed33
--- /dev/null
+++ b/linux-Fix-missing-__convert_scm_timestamps-BZ-28860.patch
@@ -0,0 +1,37 @@
+From 0351c75c5f94134fcec0e778e8cf86d149f8bbfb Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 3 Feb 2022 16:52:52 -0300
+Subject: [PATCH] linux: Fix missing __convert_scm_timestamps (BZ #28860)
+
+Commit 948ce73b31 made recvmsg/recvmmsg to always call
+__convert_scm_timestamps for 64 bit time_t symbol, so adjust it to
+always build it for __TIMESIZE != 64.
+
+It fixes build for architecture with 32 bit time_t support when
+configured with minimum kernel of 5.1.
+
+(cherry-picked from 798d716df71fb23dc89d1d5dba1fc26a1b5c0024)
+---
+ sysdeps/unix/sysv/linux/convert_scm_timestamps.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
+index 5d3c4199e0..953ce97bd2 100644
+--- a/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
++++ b/sysdeps/unix/sysv/linux/convert_scm_timestamps.c
+@@ -16,9 +16,10 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+-#include <kernel-features.h>
++#include <bits/wordsize.h>
++#include <bits/timesize.h>
+
+-#ifndef __ASSUME_TIME64_SYSCALLS
++#if __TIMESIZE != 64
+ # include <stdint.h>
+ # include <string.h>
+ # include <sys/socket.h>
+--
+2.27.0
+
diff --git a/linux-Fix-mq_timereceive-check-for-32-bit-fallback-c.patch b/linux-Fix-mq_timereceive-check-for-32-bit-fallback-c.patch
new file mode 100644
index 0000000..ca1d348
--- /dev/null
+++ b/linux-Fix-mq_timereceive-check-for-32-bit-fallback-c.patch
@@ -0,0 +1,31 @@
+From 71d87d85bf54f6522813aec97c19bdd24997341e Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 30 Jun 2022 09:08:31 -0300
+Subject: [PATCH] linux: Fix mq_timereceive check for 32 bit fallback code (BZ
+ 29304)
+
+On success, mq_receive() and mq_timedreceive() return the number of
+bytes in the received message, so it requires to check if the value
+is larger than 0.
+
+Checked on i686-linux-gnu.
+---
+ sysdeps/unix/sysv/linux/mq_timedreceive.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/mq_timedreceive.c b/sysdeps/unix/sysv/linux/mq_timedreceive.c
+index 834cd7a..5bf1e0a 100644
+--- a/sysdeps/unix/sysv/linux/mq_timedreceive.c
++++ b/sysdeps/unix/sysv/linux/mq_timedreceive.c
+@@ -41,7 +41,7 @@ ___mq_timedreceive_time64 (mqd_t mqdes, char *__restrict msg_ptr, size_t msg_len
+ {
+ int r = SYSCALL_CANCEL (mq_timedreceive_time64, mqdes, msg_ptr, msg_len,
+ msg_prio, abs_timeout);
+- if (r == 0 || errno != ENOSYS)
++ if (r >= 0 || errno != ENOSYS)
+ return r;
+ __set_errno (EOVERFLOW);
+ return -1;
+--
+1.8.3.1
+
diff --git a/linux-Fix-posix_spawn-return-code-if-clone-fails-BZ-.patch b/linux-Fix-posix_spawn-return-code-if-clone-fails-BZ-.patch
new file mode 100644
index 0000000..d3bb233
--- /dev/null
+++ b/linux-Fix-posix_spawn-return-code-if-clone-fails-BZ-.patch
@@ -0,0 +1,28 @@
+From 71e2a681f18f617ab962bf8a139bd86d4d440e22 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 2 May 2022 12:39:43 -0300
+Subject: [PATCH] linux: Fix posix_spawn return code if clone fails (BZ#29109)
+
+The __clone_internal returns the error on errno.
+
+Checked on x86_64-linux-gnu.
+---
+ sysdeps/unix/sysv/linux/spawni.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/spawni.c b/sysdeps/unix/sysv/linux/spawni.c
+index d703485..d6f5ca8 100644
+--- a/sysdeps/unix/sysv/linux/spawni.c
++++ b/sysdeps/unix/sysv/linux/spawni.c
+@@ -409,7 +409,7 @@ __spawnix (pid_t * pid, const char *file,
+ __waitpid (new_pid, NULL, 0);
+ }
+ else
+- ec = -new_pid;
++ ec = errno;
+
+ __munmap (stack, stack_size);
+
+--
+1.8.3.1
+
diff --git a/linux-Only-build-fstatat-fallback-if-required.patch b/linux-Only-build-fstatat-fallback-if-required.patch
new file mode 100644
index 0000000..093d5b6
--- /dev/null
+++ b/linux-Only-build-fstatat-fallback-if-required.patch
@@ -0,0 +1,52 @@
+From c3b023a7822185c9176cfb96eeca4ada3d662c4b Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 24 Nov 2021 12:57:57 -0300
+Subject: [PATCH] linux: Only build fstatat fallback if required
+
+For 32-bit architecture with __ASSUME_STATX there is no need to
+build fstatat64_time64_stat.
+
+Checked on i686-linux-gnu.
+---
+ sysdeps/unix/sysv/linux/fstatat64.c | 18 +++++++++++-------
+ 1 file changed, 11 insertions(+), 7 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
+index f968e4ef05..50ae5ad748 100644
+--- a/sysdeps/unix/sysv/linux/fstatat64.c
++++ b/sysdeps/unix/sysv/linux/fstatat64.c
+@@ -74,6 +74,17 @@ fstatat64_time64_statx (int fd, const char *file, struct __stat64_t64 *buf,
+ return r;
+ }
+
++#if (__WORDSIZE == 32 \
++ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
++ || defined STAT_HAS_TIME32
++# define FSTATAT_USE_STATX 1
++#else
++# define FSTATAT_USE_STATX 0
++#endif
++
++/* Only statx supports 64-bit timestamps for 32-bit architectures with
++ __ASSUME_STATX, so there is no point in building the fallback. */
++#if !FSTATAT_USE_STATX || (FSTATAT_USE_STATX && !defined __ASSUME_STATX)
+ static inline int
+ fstatat64_time64_stat (int fd, const char *file, struct __stat64_t64 *buf,
+ int flag)
+@@ -134,13 +145,6 @@ fstatat64_time64_stat (int fd, const char *file, struct __stat64_t64 *buf,
+
+ return r;
+ }
+-
+-#if (__WORDSIZE == 32 \
+- && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+- || defined STAT_HAS_TIME32
+-# define FSTATAT_USE_STATX 1
+-#else
+-# define FSTATAT_USE_STATX 0
+ #endif
+
+ int
+--
+2.33.0
+
diff --git a/linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch b/linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch
new file mode 100644
index 0000000..17a7a5c
--- /dev/null
+++ b/linux-Revert-the-use-of-sched_getaffinity-on-get_npr.patch
@@ -0,0 +1,206 @@
+From 342298278eabc75baabcaced110a11a02c3d3580 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 6 Sep 2021 14:19:51 -0300
+Subject: [PATCH] linux: Revert the use of sched_getaffinity on get_nproc (BZ
+ #28310)
+
+The use of sched_getaffinity on get_nproc and
+sysconf (_SC_NPROCESSORS_ONLN) done in 903bc7dcc2acafc40 (BZ #27645)
+breaks the top command in common hypervisor configurations and also
+other monitoring tools.
+
+The main issue using sched_getaffinity changed the symbols semantic
+from system-wide scope of online CPUs to per-process one (which can
+be changed with kernel cpusets or book parameters in VM).
+
+This patch reverts mostly of the 903bc7dcc2acafc40, with the
+exceptions:
+
+ * No more cached values and atomic updates, since they are inherent
+ racy.
+
+ * No /proc/cpuinfo fallback, since /proc/stat is already used and
+ it would require to revert more arch-specific code.
+
+ * The alloca is replace with a static buffer of 1024 bytes.
+
+So the implementation first consult the sysfs, and fallbacks to procfs.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+---
+ sysdeps/unix/sysv/linux/getsysstats.c | 139 ++++++++++++++++++++++++++++++++--
+ 1 file changed, 134 insertions(+), 5 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
+index 1e3d886..15ad91c 100644
+--- a/sysdeps/unix/sysv/linux/getsysstats.c
++++ b/sysdeps/unix/sysv/linux/getsysstats.c
+@@ -17,6 +17,8 @@
+ <https://www.gnu.org/licenses/>. */
+
+ #include <array_length.h>
++#include <assert.h>
++#include <ctype.h>
+ #include <dirent.h>
+ #include <errno.h>
+ #include <ldsodefs.h>
+@@ -29,7 +31,7 @@
+ #include <sysdep.h>
+
+ int
+-__get_nprocs (void)
++__get_nprocs_sched (void)
+ {
+ enum
+ {
+@@ -52,14 +54,141 @@ __get_nprocs (void)
+ atomics are needed). */
+ return 2;
+ }
+-libc_hidden_def (__get_nprocs)
+-weak_alias (__get_nprocs, get_nprocs)
++
++static char *
++next_line (int fd, char *const buffer, char **cp, char **re,
++ char *const buffer_end)
++{
++ char *res = *cp;
++ char *nl = memchr (*cp, '\n', *re - *cp);
++ if (nl == NULL)
++ {
++ if (*cp != buffer)
++ {
++ if (*re == buffer_end)
++ {
++ memmove (buffer, *cp, *re - *cp);
++ *re = buffer + (*re - *cp);
++ *cp = buffer;
++
++ ssize_t n = __read_nocancel (fd, *re, buffer_end - *re);
++ if (n < 0)
++ return NULL;
++
++ *re += n;
++
++ nl = memchr (*cp, '\n', *re - *cp);
++ while (nl == NULL && *re == buffer_end)
++ {
++ /* Truncate too long lines. */
++ *re = buffer + 3 * (buffer_end - buffer) / 4;
++ n = __read_nocancel (fd, *re, buffer_end - *re);
++ if (n < 0)
++ return NULL;
++
++ nl = memchr (*re, '\n', n);
++ **re = '\n';
++ *re += n;
++ }
++ }
++ else
++ nl = memchr (*cp, '\n', *re - *cp);
++
++ res = *cp;
++ }
++
++ if (nl == NULL)
++ nl = *re - 1;
++ }
++
++ *cp = nl + 1;
++ assert (*cp <= *re);
++
++ return res == *re ? NULL : res;
++}
++
+
+ int
+-__get_nprocs_sched (void)
++__get_nprocs (void)
+ {
+- return __get_nprocs ();
++ enum { buffer_size = 1024 };
++ char buffer[buffer_size];
++ char *buffer_end = buffer + buffer_size;
++ char *cp = buffer_end;
++ char *re = buffer_end;
++
++ const int flags = O_RDONLY | O_CLOEXEC;
++ /* This file contains comma-separated ranges. */
++ int fd = __open_nocancel ("/sys/devices/system/cpu/online", flags);
++ char *l;
++ int result = 0;
++ if (fd != -1)
++ {
++ l = next_line (fd, buffer, &cp, &re, buffer_end);
++ if (l != NULL)
++ do
++ {
++ char *endp;
++ unsigned long int n = strtoul (l, &endp, 10);
++ if (l == endp)
++ {
++ result = 0;
++ break;
++ }
++
++ unsigned long int m = n;
++ if (*endp == '-')
++ {
++ l = endp + 1;
++ m = strtoul (l, &endp, 10);
++ if (l == endp)
++ {
++ result = 0;
++ break;
++ }
++ }
++
++ result += m - n + 1;
++
++ l = endp;
++ if (l < re && *l == ',')
++ ++l;
++ }
++ while (l < re && *l != '\n');
++
++ __close_nocancel_nostatus (fd);
++
++ if (result > 0)
++ return result;
++ }
++
++ cp = buffer_end;
++ re = buffer_end;
++
++ /* Default to an SMP system in case we cannot obtain an accurate
++ number. */
++ result = 2;
++
++ fd = __open_nocancel ("/proc/stat", flags);
++ if (fd != -1)
++ {
++ result = 0;
++
++ while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
++ /* The current format of /proc/stat has all the cpu* entries
++ at the front. We assume here that stays this way. */
++ if (strncmp (l, "cpu", 3) != 0)
++ break;
++ else if (isdigit (l[3]))
++ ++result;
++
++ __close_nocancel_nostatus (fd);
++ }
++
++ return result;
+ }
++libc_hidden_def (__get_nprocs)
++weak_alias (__get_nprocs, get_nprocs)
+
+
+ /* On some architectures it is possible to distinguish between configured
+--
+1.8.3.1
+
diff --git a/linux-Simplify-get_nprocs.patch b/linux-Simplify-get_nprocs.patch
new file mode 100644
index 0000000..55c49b2
--- /dev/null
+++ b/linux-Simplify-get_nprocs.patch
@@ -0,0 +1,216 @@
+From cda99af14e82b4bb6abaecd717ebe3b57c0aa534 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 6 Sep 2021 12:28:24 -0300
+Subject: [PATCH] linux: Simplify get_nprocs
+
+This patch simplifies the memory allocation code and uses the sched
+routines instead of reimplement it. This still uses a stack
+allocation buffer, so it can be used on malloc initialization code.
+
+Linux currently supports at maximum of 4096 cpus for most architectures:
+
+$ find -iname Kconfig | xargs git grep -A10 -w NR_CPUS | grep -w range
+arch/alpha/Kconfig- range 2 32
+arch/arc/Kconfig- range 2 4096
+arch/arm/Kconfig- range 2 16 if DEBUG_KMAP_LOCAL
+arch/arm/Kconfig- range 2 32 if !DEBUG_KMAP_LOCAL
+arch/arm64/Kconfig- range 2 4096
+arch/csky/Kconfig- range 2 32
+arch/hexagon/Kconfig- range 2 6 if SMP
+arch/ia64/Kconfig- range 2 4096
+arch/mips/Kconfig- range 2 256
+arch/openrisc/Kconfig- range 2 32
+arch/parisc/Kconfig- range 2 32
+arch/riscv/Kconfig- range 2 32
+arch/s390/Kconfig- range 2 512
+arch/sh/Kconfig- range 2 32
+arch/sparc/Kconfig- range 2 32 if SPARC32
+arch/sparc/Kconfig- range 2 4096 if SPARC64
+arch/um/Kconfig- range 1 1
+arch/x86/Kconfig-# [NR_CPUS_RANGE_BEGIN ... NR_CPUS_RANGE_END] range.
+arch/x86/Kconfig- range NR_CPUS_RANGE_BEGIN NR_CPUS_RANGE_END
+arch/xtensa/Kconfig- range 2 32
+
+With x86 supporting 8192:
+
+arch/x86/Kconfig
+ 976 config NR_CPUS_RANGE_END
+ 977 int
+ 978 depends on X86_64
+ 979 default 8192 if SMP && CPUMASK_OFFSTACK
+ 980 default 512 if SMP && !CPUMASK_OFFSTACK
+ 981 default 1 if !SMP
+
+So using a maximum of 32k cpu should cover all cases (and I would
+expect once we start to have many more CPUs that Linux would provide
+a more straightforward way to query for such information).
+
+A test is added to check if sched_getaffinity can successfully return
+with large buffers.
+
+Checked on x86_64-linux-gnu and i686-linux-gnu.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+(cherry picked from commit 33099d72e41cf8a129b362e9709eb2be9372d844)
+---
+ posix/Makefile | 3 +-
+ posix/tst-sched_getaffinity.c | 48 +++++++++++++++++++++++++
+ sysdeps/unix/sysv/linux/getsysstats.c | 68 ++++++++++-------------------------
+ 3 files changed, 68 insertions(+), 51 deletions(-)
+ create mode 100644 posix/tst-sched_getaffinity.c
+
+diff --git a/posix/Makefile b/posix/Makefile
+index 059efb3..09460a2 100644
+--- a/posix/Makefile
++++ b/posix/Makefile
+@@ -107,7 +107,8 @@ tests := test-errno tstgetopt testfnm runtests runptests \
+ tst-sysconf-empty-chroot tst-glob_symlinks tst-fexecve \
+ tst-glob-tilde test-ssize-max tst-spawn4 bug-regex37 \
+ bug-regex38 tst-regcomp-truncated tst-spawn-chdir \
+- tst-wordexp-nocmd tst-execveat tst-spawn5
++ tst-wordexp-nocmd tst-execveat tst-spawn5 \
++ tst-sched_getaffinity
+
+ # Test for the glob symbol version that was replaced in glibc 2.27.
+ ifeq ($(have-GLIBC_2.26)$(build-shared),yesyes)
+diff --git a/posix/tst-sched_getaffinity.c b/posix/tst-sched_getaffinity.c
+new file mode 100644
+index 0000000..db9d517
+--- /dev/null
++++ b/posix/tst-sched_getaffinity.c
+@@ -0,0 +1,48 @@
++/* Tests for sched_getaffinity with large buffers.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <array_length.h>
++#include <sched.h>
++#include <support/check.h>
++
++/* NB: this test may fail on system with more than 32k cpus. */
++
++static int
++do_test (void)
++{
++ /* The values are larger than the default cpu_set_t. */
++ const int bufsize[] = { 1<<11, 1<<12, 1<<13, 1<<14, 1<<15, 1<<16, 1<<17 };
++ int cpucount[array_length (bufsize)];
++
++ for (int i = 0; i < array_length (bufsize); i++)
++ {
++ cpu_set_t *cpuset = CPU_ALLOC (bufsize[i]);
++ TEST_VERIFY (cpuset != NULL);
++ size_t size = CPU_ALLOC_SIZE (bufsize[i]);
++ TEST_COMPARE (sched_getaffinity (0, size, cpuset), 0);
++ cpucount[i] = CPU_COUNT_S (size, cpuset);
++ CPU_FREE (cpuset);
++ }
++
++ for (int i = 0; i < array_length (cpucount) - 1; i++)
++ TEST_COMPARE (cpucount[i], cpucount[i + 1]);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
+index 120ce1b..61d20e7 100644
+--- a/sysdeps/unix/sysv/linux/getsysstats.c
++++ b/sysdeps/unix/sysv/linux/getsysstats.c
+@@ -29,61 +29,29 @@
+ #include <sys/sysinfo.h>
+ #include <sysdep.h>
+
+-/* Compute the population count of the entire array. */
+-static int
+-__get_nprocs_count (const unsigned long int *array, size_t length)
+-{
+- int count = 0;
+- for (size_t i = 0; i < length; ++i)
+- if (__builtin_add_overflow (count, __builtin_popcountl (array[i]),
+- &count))
+- return INT_MAX;
+- return count;
+-}
+-
+-/* __get_nprocs with a large buffer. */
+-static int
+-__get_nprocs_large (void)
+-{
+- /* This code cannot use scratch_buffer because it is used during
+- malloc initialization. */
+- size_t pagesize = GLRO (dl_pagesize);
+- unsigned long int *page = __mmap (0, pagesize, PROT_READ | PROT_WRITE,
+- MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
+- if (page == MAP_FAILED)
+- return 2;
+- int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, pagesize, page);
+- int count;
+- if (r > 0)
+- count = __get_nprocs_count (page, pagesize / sizeof (unsigned long int));
+- else if (r == -EINVAL)
+- /* One page is still not enough to store the bits. A more-or-less
+- arbitrary value. This assumes t hat such large systems never
+- happen in practice. */
+- count = GLRO (dl_pagesize) * CHAR_BIT;
+- else
+- count = 2;
+- __munmap (page, GLRO (dl_pagesize));
+- return count;
+-}
+-
+ int
+ __get_nprocs (void)
+ {
+- /* Fast path for most systems. The kernel expects a buffer size
+- that is a multiple of 8. */
+- unsigned long int small_buffer[1024 / CHAR_BIT / sizeof (unsigned long int)];
+- int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0,
+- sizeof (small_buffer), small_buffer);
++ enum
++ {
++ max_num_cpus = 32768,
++ cpu_bits_size = CPU_ALLOC_SIZE (32768)
++ };
++
++ /* This cannot use malloc because it is used on malloc initialization. */
++ __cpu_mask cpu_bits[cpu_bits_size / sizeof (__cpu_mask)];
++ int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size,
++ cpu_bits);
+ if (r > 0)
+- return __get_nprocs_count (small_buffer, r / sizeof (unsigned long int));
++ return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits);
+ else if (r == -EINVAL)
+- /* The kernel requests a larger buffer to store the data. */
+- return __get_nprocs_large ();
+- else
+- /* Some other error. 2 is conservative (not a uniprocessor
+- system, so atomics are needed). */
+- return 2;
++ /* The input buffer is still not enough to store the number of cpus. This
++ is an arbitrary values assuming such systems should be rare and there
++ is no offline cpus. */
++ return max_num_cpus;
++ /* Some other error. 2 is conservative (not a uniprocessor system, so
++ atomics are needed). */
++ return 2;
+ }
+ libc_hidden_def (__get_nprocs)
+ weak_alias (__get_nprocs, get_nprocs)
+--
+1.8.3.1
+
diff --git a/linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch b/linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch
new file mode 100644
index 0000000..57c9aa2
--- /dev/null
+++ b/linux-Use-proc-stat-fallback-for-__get_nprocs_conf-B.patch
@@ -0,0 +1,102 @@
+From 137ed5ac440a4d3cf4178ce97f349b349a9c2c66 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 25 Nov 2021 09:12:00 -0300
+Subject: [PATCH] linux: Use /proc/stat fallback for __get_nprocs_conf (BZ
+ #28624)
+
+The /proc/statm fallback was removed by f13fb81ad3159 if sysfs is
+not available, reinstate it.
+
+Checked on x86_64-linux-gnu.
+---
+ sysdeps/unix/sysv/linux/getsysstats.c | 60 ++++++++++++++++++++---------------
+ 1 file changed, 35 insertions(+), 25 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
+index 15ad91c..d376f05 100644
+--- a/sysdeps/unix/sysv/linux/getsysstats.c
++++ b/sysdeps/unix/sysv/linux/getsysstats.c
+@@ -107,6 +107,37 @@ next_line (int fd, char *const buffer, char **cp, char **re,
+ return res == *re ? NULL : res;
+ }
+
++static int
++get_nproc_stat (char *buffer, size_t buffer_size)
++{
++ char *buffer_end = buffer + buffer_size;
++ char *cp = buffer_end;
++ char *re = buffer_end;
++
++ /* Default to an SMP system in case we cannot obtain an accurate
++ number. */
++ int result = 2;
++
++ const int flags = O_RDONLY | O_CLOEXEC;
++ int fd = __open_nocancel ("/proc/stat", flags);
++ if (fd != -1)
++ {
++ result = 0;
++
++ char *l;
++ while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
++ /* The current format of /proc/stat has all the cpu* entries
++ at the front. We assume here that stays this way. */
++ if (strncmp (l, "cpu", 3) != 0)
++ break;
++ else if (isdigit (l[3]))
++ ++result;
++
++ __close_nocancel_nostatus (fd);
++ }
++
++ return result;
++}
+
+ int
+ __get_nprocs (void)
+@@ -162,30 +193,7 @@ __get_nprocs (void)
+ return result;
+ }
+
+- cp = buffer_end;
+- re = buffer_end;
+-
+- /* Default to an SMP system in case we cannot obtain an accurate
+- number. */
+- result = 2;
+-
+- fd = __open_nocancel ("/proc/stat", flags);
+- if (fd != -1)
+- {
+- result = 0;
+-
+- while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
+- /* The current format of /proc/stat has all the cpu* entries
+- at the front. We assume here that stays this way. */
+- if (strncmp (l, "cpu", 3) != 0)
+- break;
+- else if (isdigit (l[3]))
+- ++result;
+-
+- __close_nocancel_nostatus (fd);
+- }
+-
+- return result;
++ return get_nproc_stat (buffer, buffer_size);
+ }
+ libc_hidden_def (__get_nprocs)
+ weak_alias (__get_nprocs, get_nprocs)
+@@ -219,7 +227,9 @@ __get_nprocs_conf (void)
+ return count;
+ }
+
+- return 1;
++ enum { buffer_size = 1024 };
++ char buffer[buffer_size];
++ return get_nproc_stat (buffer, buffer_size);
+ }
+ libc_hidden_def (__get_nprocs_conf)
+ weak_alias (__get_nprocs_conf, get_nprocs_conf)
+--
+1.8.3.1
+
diff --git a/linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch b/linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch
new file mode 100644
index 0000000..0bf8f6d
--- /dev/null
+++ b/linux-__get_nprocs_sched-do-not-feed-CPU_COUNT_S-wit.patch
@@ -0,0 +1,30 @@
+From 97ba273b505763325efd802dc3a9562dbba79579 Mon Sep 17 00:00:00 2001
+From: Gleb Fotengauer-Malinovskiy <glebfm@altlinux.org>
+Date: Tue, 1 Feb 2022 22:39:02 +0000
+Subject: [PATCH] linux: __get_nprocs_sched: do not feed CPU_COUNT_S with
+ garbage [BZ #28850]
+
+Pass the actual number of bytes returned by the kernel.
+
+Fixes: 33099d72e41c ("linux: Simplify get_nprocs")
+Reviewed-by: Dmitry V. Levin <ldv@altlinux.org>
+---
+ sysdeps/unix/sysv/linux/getsysstats.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
+index 4798cc3..c98c8ce 100644
+--- a/sysdeps/unix/sysv/linux/getsysstats.c
++++ b/sysdeps/unix/sysv/linux/getsysstats.c
+@@ -44,7 +44,7 @@ __get_nprocs_sched (void)
+ int r = INTERNAL_SYSCALL_CALL (sched_getaffinity, 0, cpu_bits_size,
+ cpu_bits);
+ if (r > 0)
+- return CPU_COUNT_S (cpu_bits_size, (cpu_set_t*) cpu_bits);
++ return CPU_COUNT_S (r, (cpu_set_t*) cpu_bits);
+ else if (r == -EINVAL)
+ /* The input buffer is still not enough to store the number of cpus. This
+ is an arbitrary values assuming such systems should be rare and there
+--
+1.8.3.1
+
diff --git a/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch b/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch
new file mode 100644
index 0000000..d16fa75
--- /dev/null
+++ b/linux-fix-accuracy-of-get_nprocs-and-get_nprocs_conf.patch
@@ -0,0 +1,212 @@
+From 007e054d786be340699c634e3a3b30ab1fde1a7a Mon Sep 17 00:00:00 2001
+From: "Dmitry V. Levin" <ldv@altlinux.org>
+Date: Sat, 5 Feb 2022 08:00:00 +0000
+Subject: [PATCH] linux: fix accuracy of get_nprocs and get_nprocs_conf [BZ
+ #28865]
+
+get_nprocs() and get_nprocs_conf() use various methods to obtain an
+accurate number of processors. Re-introduce __get_nprocs_sched() as
+a source of information, and fix the order in which these methods are
+used to return the most accurate information. The primary source of
+information used in both functions remains unchanged.
+
+This also changes __get_nprocs_sched() error return value from 2 to 0,
+but all its users are already prepared to handle that.
+
+Old fallback order:
+ get_nprocs:
+ /sys/devices/system/cpu/online -> /proc/stat -> 2
+ get_nprocs_conf:
+ /sys/devices/system/cpu/ -> /proc/stat -> 2
+
+New fallback order:
+ get_nprocs:
+ /sys/devices/system/cpu/online -> /proc/stat -> sched_getaffinity -> 2
+ get_nprocs_conf:
+ /sys/devices/system/cpu/ -> /proc/stat -> sched_getaffinity -> 2
+
+Fixes: 342298278e ("linux: Revert the use of sched_getaffinity on get_nproc")
+Closes: BZ #28865
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+
+(cherry picked from commit e1d32b836410767270a3adf1f82b1a47e6e4cd51)
+---
+ NEWS | 2 +
+ sysdeps/unix/sysv/linux/getsysstats.c | 94 ++++++++++++++++++---------
+ 2 files changed, 65 insertions(+), 31 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 87c9517e1a..aef051122e 100644
+--- a/NEWS
++++ b/NEWS
+@@ -29,6 +29,8 @@ The following bugs are resolved with this release:
+ [28349] libc: Segfault for ping -R on qemux86 caused by recvmsg()
+ [28350] libc: ping receives SIGABRT on lib32-qemux86-64 caused by
+ recvmsg()
++ [28865] linux: _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are inaccurate
++ without /sys and /proc
+
+
+ Version 2.34
+diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
+index 7babd947aa..327802b14c 100644
+--- a/sysdeps/unix/sysv/linux/getsysstats.c
++++ b/sysdeps/unix/sysv/linux/getsysstats.c
+@@ -51,9 +51,8 @@ __get_nprocs_sched (void)
+ is an arbitrary values assuming such systems should be rare and there
+ is no offline cpus. */
+ return max_num_cpus;
+- /* Some other error. 2 is conservative (not a uniprocessor system, so
+- atomics are needed). */
+- return 2;
++ /* Some other error. */
++ return 0;
+ }
+
+ static char *
+@@ -109,22 +108,19 @@ next_line (int fd, char *const buffer, char **cp, char **re,
+ }
+
+ static int
+-get_nproc_stat (char *buffer, size_t buffer_size)
++get_nproc_stat (void)
+ {
++ enum { buffer_size = 1024 };
++ char buffer[buffer_size];
+ char *buffer_end = buffer + buffer_size;
+ char *cp = buffer_end;
+ char *re = buffer_end;
+-
+- /* Default to an SMP system in case we cannot obtain an accurate
+- number. */
+- int result = 2;
++ int result = 0;
+
+ const int flags = O_RDONLY | O_CLOEXEC;
+ int fd = __open_nocancel ("/proc/stat", flags);
+ if (fd != -1)
+ {
+- result = 0;
+-
+ char *l;
+ while ((l = next_line (fd, buffer, &cp, &re, buffer_end)) != NULL)
+ /* The current format of /proc/stat has all the cpu* entries
+@@ -140,8 +136,8 @@ get_nproc_stat (char *buffer, size_t buffer_size)
+ return result;
+ }
+
+-int
+-__get_nprocs (void)
++static int
++get_nprocs_cpu_online (void)
+ {
+ enum { buffer_size = 1024 };
+ char buffer[buffer_size];
+@@ -180,7 +176,8 @@ __get_nprocs (void)
+ }
+ }
+
+- result += m - n + 1;
++ if (m >= n)
++ result += m - n + 1;
+
+ l = endp;
+ if (l < re && *l == ',')
+@@ -189,28 +186,18 @@ __get_nprocs (void)
+ while (l < re && *l != '\n');
+
+ __close_nocancel_nostatus (fd);
+-
+- if (result > 0)
+- return result;
+ }
+
+- return get_nproc_stat (buffer, buffer_size);
++ return result;
+ }
+-libc_hidden_def (__get_nprocs)
+-weak_alias (__get_nprocs, get_nprocs)
+-
+
+-/* On some architectures it is possible to distinguish between configured
+- and active cpus. */
+-int
+-__get_nprocs_conf (void)
++static int
++get_nprocs_cpu (void)
+ {
+- /* Try to use the sysfs filesystem. It has actual information about
+- online processors. */
++ int count = 0;
+ DIR *dir = __opendir ("/sys/devices/system/cpu");
+ if (dir != NULL)
+ {
+- int count = 0;
+ struct dirent64 *d;
+
+ while ((d = __readdir64 (dir)) != NULL)
+@@ -225,12 +212,57 @@ __get_nprocs_conf (void)
+
+ __closedir (dir);
+
+- return count;
+ }
++ return count;
++}
+
+- enum { buffer_size = 1024 };
+- char buffer[buffer_size];
+- return get_nproc_stat (buffer, buffer_size);
++static int
++get_nprocs_fallback (void)
++{
++ int result;
++
++ /* Try /proc/stat first. */
++ result = get_nproc_stat ();
++ if (result != 0)
++ return result;
++
++ /* Try sched_getaffinity. */
++ result = __get_nprocs_sched ();
++ if (result != 0)
++ return result;
++
++ /* We failed to obtain an accurate number. Be conservative: return
++ the smallest number meaning that this is not a uniprocessor system,
++ so atomics are needed. */
++ return 2;
++}
++
++int
++__get_nprocs (void)
++{
++ /* Try /sys/devices/system/cpu/online first. */
++ int result = get_nprocs_cpu_online ();
++ if (result != 0)
++ return result;
++
++ /* Fall back to /proc/stat and sched_getaffinity. */
++ return get_nprocs_fallback ();
++}
++libc_hidden_def (__get_nprocs)
++weak_alias (__get_nprocs, get_nprocs)
++
++/* On some architectures it is possible to distinguish between configured
++ and active cpus. */
++int
++__get_nprocs_conf (void)
++{
++ /* Try /sys/devices/system/cpu/ first. */
++ int result = get_nprocs_cpu ();
++ if (result != 0)
++ return result;
++
++ /* Fall back to /proc/stat and sched_getaffinity. */
++ return get_nprocs_fallback ();
+ }
+ libc_hidden_def (__get_nprocs_conf)
+ weak_alias (__get_nprocs_conf, get_nprocs_conf)
+--
+2.27.0
+
diff --git a/linux-use-statx-for-fstat-if-neither-newfstatat-nor-.patch b/linux-use-statx-for-fstat-if-neither-newfstatat-nor-.patch
new file mode 100644
index 0000000..7d23c67
--- /dev/null
+++ b/linux-use-statx-for-fstat-if-neither-newfstatat-nor-.patch
@@ -0,0 +1,36 @@
+From e6547d635b991651600fab31f788ed5facd77610 Mon Sep 17 00:00:00 2001
+From: WANG Xuerui <git@xen0n.name>
+Date: Wed, 1 Jun 2022 10:12:28 +0800
+Subject: [PATCH] linux: use statx for fstat if neither newfstatat nor
+ fstatat64 is present
+
+LoongArch is going to be the first architecture supported by Linux that
+has neither fstat* nor newfstatat [1], instead exclusively relying on
+statx. So in fstatat64's implementation, we need to also enable statx
+usage if neither fstatat64 nor newfstatat is present, to prepare for
+this new case of kernel ABI.
+
+[1]: https://lore.kernel.org/all/20220518092619.1269111-1-chenhuacai@loongson.cn/
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ sysdeps/unix/sysv/linux/fstatat64.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/fstatat64.c b/sysdeps/unix/sysv/linux/fstatat64.c
+index 2ab914380d..8b1a1a290d 100644
+--- a/sysdeps/unix/sysv/linux/fstatat64.c
++++ b/sysdeps/unix/sysv/linux/fstatat64.c
+@@ -42,7 +42,8 @@ _Static_assert (sizeof (__blkcnt_t) == sizeof (__blkcnt64_t),
+
+ #if (__WORDSIZE == 32 \
+ && (!defined __SYSCALL_WORDSIZE || __SYSCALL_WORDSIZE == 32)) \
+- || defined STAT_HAS_TIME32
++ || defined STAT_HAS_TIME32 \
++ || (!defined __NR_newfstatat && !defined __NR_fstatat64)
+ # define FSTATAT_USE_STATX 1
+
+ static inline int
+--
+2.33.0
+
diff --git a/localedef-Handle-symbolic-links-when-generating-loca.patch b/localedef-Handle-symbolic-links-when-generating-loca.patch
new file mode 100644
index 0000000..a0e7825
--- /dev/null
+++ b/localedef-Handle-symbolic-links-when-generating-loca.patch
@@ -0,0 +1,33 @@
+From ea89d5bbd9e5e514b606045d909e6ab87d851c88 Mon Sep 17 00:00:00 2001
+From: Arjun Shankar <arjun@redhat.com>
+Date: Thu, 24 Feb 2022 21:43:09 +0100
+Subject: [PATCH] localedef: Handle symbolic links when generating
+ locale-archive
+
+Whenever locale data for any locale included symbolic links, localedef
+would throw the error "incomplete set of locale files" and exclude it
+from the generated locale archive. This commit fixes that.
+
+Co-authored-by: Florian Weimer <fweimer@redhat.com>
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ locale/programs/locarchive.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/locale/programs/locarchive.c b/locale/programs/locarchive.c
+index 45408c2..eeb2fa6 100644
+--- a/locale/programs/locarchive.c
++++ b/locale/programs/locarchive.c
+@@ -1397,7 +1397,7 @@ add_locales_to_archive (size_t nlist, char *list[], bool replace)
+ {
+ char fullname[fnamelen + 2 * strlen (d->d_name) + 7];
+
+- if (d_type == DT_UNKNOWN)
++ if (d_type == DT_UNKNOWN || d_type == DT_LNK)
+ {
+ strcpy (stpcpy (stpcpy (fullname, fname), "/"),
+ d->d_name);
+--
+1.8.3.1
+
diff --git a/login-Add-back-libutil-as-an-empty-library.patch b/login-Add-back-libutil-as-an-empty-library.patch
new file mode 100644
index 0000000..a6ea90b
--- /dev/null
+++ b/login-Add-back-libutil-as-an-empty-library.patch
@@ -0,0 +1,42 @@
+From b3cf94ef15f0bb6ff336907e31ab0064a0381916 Mon Sep 17 00:00:00 2001
+From: Stafford Horne <shorne@gmail.com>
+Date: Wed, 13 Oct 2021 21:43:50 +0900
+Subject: [PATCH] login: Add back libutil as an empty library
+
+There are several packages like sysvinit and buildroot that expect
+-lutil to work. Rather than impacting them with having to change
+the linker flags provide an empty libutil.a.
+
+Signed-off-by: wanghongliang <wanghongliang@loongson.cn>
+---
+ login/Makefile | 4 +++-
+ 1 file changed, 3 insertions(+), 1 deletion(-)
+
+diff --git a/login/Makefile b/login/Makefile
+index 4e6b97734d..e2bdcb1b0d 100644
+--- a/login/Makefile
++++ b/login/Makefile
+@@ -46,10 +46,10 @@ vpath %.c programs
+ tests := tst-utmp tst-utmpx tst-grantpt tst-ptsname tst-getlogin tst-updwtmpx \
+ tst-pututxline-lockfail tst-pututxline-cache
+
+-ifeq ($(have-GLIBC_2.33),yes)
+ # Empty compatibility library for old binaries.
+ extra-libs := libutil
+ extra-libs-others := $(extra-libs)
++ifeq ($(have-GLIBC_2.33),yes)
+ libutil-routines := libutil-compat
+ libutil-shared-only-routines := libutil-compat
+
+@@ -57,6 +57,8 @@ libutil-shared-only-routines := libutil-compat
+ # link is not installed.
+ install-lib-ldscripts = libutil.so
+ $(inst_libdir)/libutil.so:
++else # not $(have-GLIBC_2.33)
++libutil-inhibit-o = $(filter-out .o,$(object-suffixes))
+ endif # $(have-GLIBC_2.33)
+
+ include ../Rules
+--
+2.31.1
+
diff --git a/malloc-Fix-Wuse-after-free-warning-in-tst-mallocalig.patch b/malloc-Fix-Wuse-after-free-warning-in-tst-mallocalig.patch
new file mode 100644
index 0000000..bfa8163
--- /dev/null
+++ b/malloc-Fix-Wuse-after-free-warning-in-tst-mallocalig.patch
@@ -0,0 +1,89 @@
+From 6484ae5b8c4d4314f748e4d3c9a9baa5385e57c5 Mon Sep 17 00:00:00 2001
+From: Carlos O'Donell <carlos@redhat.com>
+Date: Fri, 28 Jan 2022 15:14:29 -0500
+Subject: [PATCH] malloc: Fix -Wuse-after-free warning in tst-mallocalign1 [BZ
+ #26779]
+
+The test leaks bits from the freed pointer via the return value
+in ret, and the compiler correctly identifies this issue.
+We switch the test to use TEST_VERIFY and terminate the test
+if any of the pointers return an unexpected alignment.
+
+This fixes another -Wuse-after-free error when compiling glibc
+with gcc 12.
+
+Tested on x86_64 and i686 without regression.
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit 3a7bed5f5a527dbd87412551f41e42e63aeef07a)
+---
+ malloc/tst-mallocalign1.c | 20 +++++++++++---------
+ 1 file changed, 11 insertions(+), 9 deletions(-)
+
+diff --git a/malloc/tst-mallocalign1.c b/malloc/tst-mallocalign1.c
+index 294e821afe..3e09ff30c4 100644
+--- a/malloc/tst-mallocalign1.c
++++ b/malloc/tst-mallocalign1.c
+@@ -20,6 +20,7 @@
+ #include <stdlib.h>
+ #include <inttypes.h>
+ #include <malloc-size.h>
++#include <support/check.h>
+
+ static void *
+ test (size_t s)
+@@ -31,41 +32,42 @@ test (size_t s)
+ return p;
+ }
+
++#define ALIGNED(p) (((uintptr_t )p & MALLOC_ALIGN_MASK) == 0)
++
+ static int
+ do_test (void)
+ {
+ void *p;
+- int ret = 0;
+
+ p = test (2);
+- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
++ TEST_VERIFY (ALIGNED (p));
+ free (p);
+
+ p = test (8);
+- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
++ TEST_VERIFY (ALIGNED (p));
+ free (p);
+
+ p = test (13);
+- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
++ TEST_VERIFY (ALIGNED (p));
+ free (p);
+
+ p = test (16);
+- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
++ TEST_VERIFY (ALIGNED (p));
+ free (p);
+
+ p = test (23);
+- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
++ TEST_VERIFY (ALIGNED (p));
+ free (p);
+
+ p = test (43);
+- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
++ TEST_VERIFY (ALIGNED (p));
+ free (p);
+
+ p = test (123);
+- ret |= (uintptr_t) p & MALLOC_ALIGN_MASK;
++ TEST_VERIFY (ALIGNED (p));
+ free (p);
+
+- return ret;
++ return 0;
+ }
+
+ #include <support/test-driver.c>
+--
+2.33.0
+
diff --git a/malloc-Fix-malloc-debug-for-2.35-onwards.patch b/malloc-Fix-malloc-debug-for-2.35-onwards.patch
new file mode 100644
index 0000000..e564280
--- /dev/null
+++ b/malloc-Fix-malloc-debug-for-2.35-onwards.patch
@@ -0,0 +1,57 @@
+From f1bcfde3a7b1b2606ff9f267e1e4a9cd7c65497a Mon Sep 17 00:00:00 2001
+From: Stafford Horne <shorne@gmail.com>
+Date: Wed, 13 Oct 2021 19:43:30 +0900
+Subject: [PATCH] malloc: Fix malloc debug for 2.35 onwards
+
+The change 1e5a5866cb ("Remove malloc hooks [BZ #23328]") has broken
+ports that are using GLIBC_2_35, like the new OpenRISC port I am working
+on.
+
+The libc_malloc_debug.so library used to bring in the debug
+infrastructure is currently essentially empty for GLIBC_2_35 ports like
+mine causing mtrace tests to fail:
+
+ cat sysdeps/unix/sysv/linux/or1k/shlib-versions
+ DEFAULT GLIBC_2.35
+ ld=ld-linux-or1k.so.1
+
+ FAIL: posix/bug-glob2-mem
+ FAIL: posix/bug-regex14-mem
+ FAIL: posix/bug-regex2-mem
+ FAIL: posix/bug-regex21-mem
+ FAIL: posix/bug-regex31-mem
+ FAIL: posix/bug-regex36-mem
+ FAIL: malloc/tst-mtrace.
+
+The issue seems to be with the ifdefs in malloc/malloc-debug.c. The
+ifdefs are currently essentially exluding all symbols for ports > 2.35.
+
+Removing the top level SHLIB_COMPAT ifdef allows things to just work.
+
+Fixes: 1e5a5866cb ("Remove malloc hooks [BZ #23328]")
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Signed-off-by: wanghongliang <wanghongliang@loongson.cn>
+---
+ malloc/malloc-debug.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/malloc/malloc-debug.c b/malloc/malloc-debug.c
+index 3d7e6d44fd..99aa95b145 100644
+--- a/malloc/malloc-debug.c
++++ b/malloc/malloc-debug.c
+@@ -24,7 +24,6 @@
+ #include <unistd.h>
+ #include <sys/param.h>
+
+-#if SHLIB_COMPAT (libc_malloc_debug, GLIBC_2_0, GLIBC_2_34)
+ /* Support only the glibc allocators. */
+ extern void *__libc_malloc (size_t);
+ extern void __libc_free (void *);
+@@ -669,4 +668,3 @@ compat_symbol (libc_malloc_debug, __free_hook, __free_hook, GLIBC_2_0);
+ compat_symbol (libc_malloc_debug, __malloc_hook, __malloc_hook, GLIBC_2_0);
+ compat_symbol (libc_malloc_debug, __realloc_hook, __realloc_hook, GLIBC_2_0);
+ compat_symbol (libc_malloc_debug, __memalign_hook, __memalign_hook, GLIBC_2_0);
+-#endif
+--
+2.31.1
+
diff --git a/malloc-Fix-transposed-arguments-in-sysmalloc_mmap_fa.patch b/malloc-Fix-transposed-arguments-in-sysmalloc_mmap_fa.patch
new file mode 100644
index 0000000..fbd1059
--- /dev/null
+++ b/malloc-Fix-transposed-arguments-in-sysmalloc_mmap_fa.patch
@@ -0,0 +1,37 @@
+From 6a734e62f1557de3449c689effd2b37066ea34eb Mon Sep 17 00:00:00 2001
+From: Robert Morell <rmorell@nvidia.com>
+Date: Tue, 7 Mar 2023 10:14:45 -0300
+Subject: [PATCH] malloc: Fix transposed arguments in sysmalloc_mmap_fallback
+ call
+
+git commit 0849eed45daa ("malloc: Move MORECORE fallback mmap to
+sysmalloc_mmap_fallback") moved a block of code from sysmalloc to a
+new helper function sysmalloc_mmap_fallback(), but 'pagesize' is used
+for the 'minsize' argument and 'MMAP_AS_MORECORE_SIZE' for the
+'pagesize' argument.
+
+Fixes: 0849eed45daa ("malloc: Move MORECORE fallback mmap to sysmalloc_mmap_fallback")
+Signed-off-by: Robert Morell <rmorell@nvidia.com>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ malloc/malloc.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 5829f3fa9b..76c50e3f58 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -2725,8 +2725,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ mp_.hp_flags, av);
+ #endif
+ if (mbrk == MAP_FAILED)
+- mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, pagesize,
+- MMAP_AS_MORECORE_SIZE, 0, av);
++ mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, MMAP_AS_MORECORE_SIZE,
++ pagesize, 0, av);
+ if (mbrk != MAP_FAILED)
+ {
+ /* We do not need, and cannot use, another sbrk call to find end */
+--
+2.33.0
+
diff --git a/malloc-Improve-MAP_HUGETLB-with-glibc.malloc.hugetlb.patch b/malloc-Improve-MAP_HUGETLB-with-glibc.malloc.hugetlb.patch
new file mode 100644
index 0000000..03a9044
--- /dev/null
+++ b/malloc-Improve-MAP_HUGETLB-with-glibc.malloc.hugetlb.patch
@@ -0,0 +1,50 @@
+From bc6d79f4ae99206e7ec7d6a8c5abf26cdefc8bff Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Thu, 23 Nov 2023 14:29:15 -0300
+Subject: [PATCH] malloc: Improve MAP_HUGETLB with glibc.malloc.hugetlb=2
+
+Even for explicit large page support, allocation might use mmap without
+the hugepage bit set if the requested size is smaller than
+mmap_threshold. For this case where mmap is issued, MAP_HUGETLB is set
+iff the allocation size is larger than the used large page.
+
+To force such allocations to use large pages, also tune the mmap_threhold
+(if it is not explicit set by a tunable). This forces allocation to
+follow the sbrk path, which will fall back to mmap (which will try large
+pages before galling back to default mmap).
+
+Checked on x86_64-linux-gnu.
+Reviewed-by: DJ Delorie <dj@redhat.com>
+Tested-by: Zhangfei Gao <zhangfei.gao@linaro.org>
+
+Conflict: this adapt the context from the origin commit.
+---
+ malloc/arena.c | 12 +++++++++---
+ 1 file changed, 9 insertions(+), 3 deletions(-)
+
+diff --git a/malloc/arena.c b/malloc/arena.c
+index f8e425e1..33dbc5ae 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -366,9 +366,15 @@ ptmalloc_init (void)
+ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast));
+ TUNABLE_GET (hugetlb, size_t, TUNABLE_CALLBACK (set_hugetlb));
+ if (mp_.hp_pagesize > 0)
+- /* Force mmap for main arena instead of sbrk, so hugepages are explicitly
+- used. */
+- __always_fail_morecore = true;
++ {
++ /* Force mmap for main arena instead of sbrk, so MAP_HUGETLB is always
++ tried. Also tune the mmap threshold, so allocation smaller than the
++ large page will also try to use large pages by falling back
++ to sysmalloc_mmap_fallback on sysmalloc. */
++ if (!TUNABLE_IS_INITIALIZED (mmap_threshold))
++ do_set_mmap_threshold (mp_.hp_pagesize);
++ __always_fail_morecore = true;
++ }
+ #else
+ if (__glibc_likely (_environ != NULL))
+ {
+--
+2.33.0
+
diff --git a/malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch b/malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch
new file mode 100644
index 0000000..1fc292a
--- /dev/null
+++ b/malloc-hugepage-0001-malloc-Add-madvise-support-for-Transparent-Huge-Page.patch
@@ -0,0 +1,532 @@
+From 5f6d8d97c69748180f0031dfa385aff75062c4d5 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Fri, 13 Aug 2021 08:36:29 -0300
+Subject: [PATCH 1/7] malloc: Add madvise support for Transparent Huge Pages
+
+Linux Transparent Huge Pages (THP) current supports three different
+states: 'never', 'madvise', and 'always'. The 'never' is
+self-explanatory and 'always' will enable THP for all anonymous
+pages. However, 'madvise' is still the default for some system and
+for such case THP will be only used if the memory range is explicity
+advertise by the program through a madvise(MADV_HUGEPAGE) call.
+
+To enable it a new tunable is provided, 'glibc.malloc.hugetlb',
+where setting to a value diffent than 0 enables the madvise call.
+
+This patch issues the madvise(MADV_HUGEPAGE) call after a successful
+mmap() call at sysmalloc() with sizes larger than the default huge
+page size. The madvise() call is disable is system does not support
+THP or if it has the mode set to "never" and on Linux only support
+one page size for THP, even if the architecture supports multiple
+sizes.
+
+To test is a new rule is added tests-malloc-hugetlb1, which run the
+addes tests with the required GLIBC_TUNABLE setting.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ NEWS | 5 ++
+ Rules | 19 ++++++
+ elf/dl-tunables.list | 5 ++
+ elf/tst-rtld-list-tunables.exp | 1 +
+ malloc/Makefile | 16 +++++
+ malloc/arena.c | 5 ++
+ malloc/malloc-internal.h | 1 +
+ malloc/malloc.c | 47 ++++++++++++++
+ manual/tunables.texi | 10 +++
+ sysdeps/generic/Makefile | 8 +++
+ sysdeps/generic/malloc-hugepages.c | 31 +++++++++
+ sysdeps/generic/malloc-hugepages.h | 37 +++++++++++
+ sysdeps/unix/sysv/linux/malloc-hugepages.c | 74 ++++++++++++++++++++++
+ 13 files changed, 259 insertions(+)
+ create mode 100644 sysdeps/generic/malloc-hugepages.c
+ create mode 100644 sysdeps/generic/malloc-hugepages.h
+ create mode 100644 sysdeps/unix/sysv/linux/malloc-hugepages.c
+
+diff --git a/NEWS b/NEWS
+index 2532565d77..3b94dd209c 100644
+--- a/NEWS
++++ b/NEWS
+@@ -92,6 +92,11 @@ Major new features:
+ variables. The GNU C Library manual has details on integration of
+ Restartable Sequences.
+
++* On Linux, a new tunable, glibc.malloc.hugetlb, can be used to
++ make malloc issue madvise plus MADV_HUGEPAGE on mmap and sbrk calls.
++ Setting this might improve performance with Transparent Huge Pages madvise
++ mode depending of the workload.
++
+ Deprecated and removed features, and other changes affecting compatibility:
+
+ * The function pthread_mutex_consistent_np has been deprecated; programs
+diff --git a/Rules b/Rules
+index b1137afe71..5f5d9ba4cc 100644
+--- a/Rules
++++ b/Rules
+@@ -157,6 +157,7 @@ tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \
+ $(tests-container:%=$(objpfx)%.out) \
+ $(tests-mcheck:%=$(objpfx)%-mcheck.out) \
+ $(tests-malloc-check:%=$(objpfx)%-malloc-check.out) \
++ $(tests-malloc-hugetlb1:%=$(objpfx)%-malloc-hugetlb1.out) \
+ $(tests-special) $(tests-printers-out)
+ xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special)
+ endif
+@@ -168,6 +169,7 @@ tests-expected =
+ else
+ tests-expected = $(tests) $(tests-internal) $(tests-printers) \
+ $(tests-container) $(tests-malloc-check:%=%-malloc-check) \
++ $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1) \
+ $(tests-mcheck:%=%-mcheck)
+ endif
+ tests:
+@@ -196,6 +198,7 @@ binaries-pie-notests =
+ endif
+ binaries-mcheck-tests = $(tests-mcheck:%=%-mcheck)
+ binaries-malloc-check-tests = $(tests-malloc-check:%=%-malloc-check)
++binaries-malloc-hugetlb1-tests = $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1)
+ else
+ binaries-all-notests =
+ binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs)
+@@ -207,6 +210,7 @@ binaries-pie-tests =
+ binaries-pie-notests =
+ binaries-mcheck-tests =
+ binaries-malloc-check-tests =
++binaries-malloc-hugetlb1-tests =
+ endif
+
+ binaries-pie = $(binaries-pie-tests) $(binaries-pie-notests)
+@@ -247,6 +251,14 @@ $(addprefix $(objpfx),$(binaries-malloc-check-tests)): %-malloc-check: %.o \
+ $(+link-tests)
+ endif
+
++ifneq "$(strip $(binaries-malloc-hugetlb1-tests))" ""
++$(addprefix $(objpfx),$(binaries-malloc-hugetlb1-tests)): %-malloc-hugetlb1: %.o \
++ $(link-extra-libs-tests) \
++ $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
++ $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
++ $(+link-tests)
++endif
++
+ ifneq "$(strip $(binaries-pie-tests))" ""
+ $(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \
+ $(link-extra-libs-tests) \
+@@ -284,6 +296,13 @@ $(1)-malloc-check-ENV = MALLOC_CHECK_=3 \
+ endef
+ $(foreach t,$(tests-malloc-check),$(eval $(call malloc-check-ENVS,$(t))))
+
++# All malloc-hugetlb1 tests will be run with GLIBC_TUNABLES=glibc.malloc.hugetlb=1
++define malloc-hugetlb1-ENVS
++$(1)-malloc-hugetlb1-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=1
++endef
++$(foreach t,$(tests-malloc-hugetlb1),$(eval $(call malloc-hugetlb1-ENVS,$(t))))
++
++
+ # mcheck tests need the debug DSO to support -lmcheck.
+ define mcheck-ENVS
+ $(1)-mcheck-ENV = LD_PRELOAD=$(common-objpfx)/malloc/libc_malloc_debug.so
+diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
+index ffcd7f18d4..d1fd3f3e91 100644
+--- a/elf/dl-tunables.list
++++ b/elf/dl-tunables.list
+@@ -92,6 +92,11 @@ glibc {
+ minval: 0
+ security_level: SXID_IGNORE
+ }
++ hugetlb {
++ type: INT_32
++ minval: 0
++ maxval: 1
++ }
+ }
+ cpu {
+ hwcap_mask {
+diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
+index 44e4834cfb..d8e363f2c5 100644
+--- a/elf/tst-rtld-list-tunables.exp
++++ b/elf/tst-rtld-list-tunables.exp
+@@ -1,6 +1,7 @@
+ glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0x[f]+)
+ glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0x[f]+)
+ glibc.malloc.check: 0 (min: 0, max: 3)
++glibc.malloc.hugetlb: 0 (min: 0, max: 1)
+ glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647)
+ glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0x[f]+)
+ glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0x[f]+)
+diff --git a/malloc/Makefile b/malloc/Makefile
+index 63cd7c0734..0137595e17 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -78,6 +78,22 @@ tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \
+ tests-malloc-check = $(filter-out $(tests-exclude-malloc-check) \
+ $(tests-static),$(tests))
+
++# Run all testes with GLIBC_TUNABLES=glibc.malloc.hugetlb=1 that check the
++# Transparent Huge Pages support. We need exclude some tests that define
++# the ENV vars.
++tests-exclude-hugetlb1 = \
++ tst-compathooks-off \
++ tst-compathooks-on \
++ tst-interpose-nothread \
++ tst-interpose-thread \
++ tst-interpose-static-nothread \
++ tst-interpose-static-thread \
++ tst-malloc-usable \
++ tst-malloc-usable-tunables \
++ tst-mallocstate
++tests-malloc-hugetlb1 = \
++ $(filter-out $(tests-exclude-hugetlb1), $(tests))
++
+ # -lmcheck needs __malloc_initialize_hook, which was deprecated in 2.24.
+ ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
+ # Tests that don't play well with mcheck. They are either bugs in mcheck or
+diff --git a/malloc/arena.c b/malloc/arena.c
+index 78ef4cf18c..cd00c7bef4 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -230,6 +230,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t)
+ TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t)
+ #endif
+ TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t)
++TUNABLE_CALLBACK_FNDECL (set_hugetlb, int32_t)
+ #else
+ /* Initialization routine. */
+ #include <string.h>
+@@ -330,6 +331,7 @@ ptmalloc_init (void)
+ TUNABLE_CALLBACK (set_tcache_unsorted_limit));
+ # endif
+ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast));
++ TUNABLE_GET (hugetlb, int32_t, TUNABLE_CALLBACK (set_hugetlb));
+ #else
+ if (__glibc_likely (_environ != NULL))
+ {
+@@ -508,6 +510,9 @@ new_heap (size_t size, size_t top_pad)
+ __munmap (p2, HEAP_MAX_SIZE);
+ return 0;
+ }
++
++ madvise_thp (p2, size);
++
+ h = (heap_info *) p2;
+ h->size = size;
+ h->mprotect_size = size;
+diff --git a/malloc/malloc-internal.h b/malloc/malloc-internal.h
+index 0c7b5a183c..7493e34d86 100644
+--- a/malloc/malloc-internal.h
++++ b/malloc/malloc-internal.h
+@@ -22,6 +22,7 @@
+ #include <malloc-machine.h>
+ #include <malloc-sysdep.h>
+ #include <malloc-size.h>
++#include <malloc-hugepages.h>
+
+ /* Called in the parent process before a fork. */
+ void __malloc_fork_lock_parent (void) attribute_hidden;
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 095d97a3be..c75841b841 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -1880,6 +1880,11 @@ struct malloc_par
+ INTERNAL_SIZE_T arena_test;
+ INTERNAL_SIZE_T arena_max;
+
++#if HAVE_TUNABLES
++ /* Transparent Large Page support. */
++ INTERNAL_SIZE_T thp_pagesize;
++#endif
++
+ /* Memory map support */
+ int n_mmaps;
+ int n_mmaps_max;
+@@ -2008,6 +2013,20 @@ free_perturb (char *p, size_t n)
+
+ #include <stap-probe.h>
+
++/* ----------- Routines dealing with transparent huge pages ----------- */
++
++static inline void
++madvise_thp (void *p, INTERNAL_SIZE_T size)
++{
++#if HAVE_TUNABLES && defined (MADV_HUGEPAGE)
++ /* Do not consider areas smaller than a huge page or if the tunable is
++ not active. */
++ if (mp_.thp_pagesize == 0 || size < mp_.thp_pagesize)
++ return;
++ __madvise (p, size, MADV_HUGEPAGE);
++#endif
++}
++
+ /* ------------------- Support for multiple arenas -------------------- */
+ #include "arena.c"
+
+@@ -2445,6 +2464,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+
+ if (mm != MAP_FAILED)
+ {
++ madvise_thp (mm, size);
++
+ /*
+ The offset to the start of the mmapped region is stored
+ in the prev_size field of the chunk. This allows us to adjust
+@@ -2606,6 +2627,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ if (size > 0)
+ {
+ brk = (char *) (MORECORE (size));
++ if (brk != (char *) (MORECORE_FAILURE))
++ madvise_thp (brk, size);
+ LIBC_PROBE (memory_sbrk_more, 2, brk, size);
+ }
+
+@@ -2637,6 +2660,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+
+ if (mbrk != MAP_FAILED)
+ {
++ madvise_thp (mbrk, size);
++
+ /* We do not need, and cannot use, another sbrk call to find end */
+ brk = mbrk;
+ snd_brk = brk + size;
+@@ -2748,6 +2773,8 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ correction = 0;
+ snd_brk = (char *) (MORECORE (0));
+ }
++ else
++ madvise_thp (snd_brk, correction);
+ }
+
+ /* handle non-contiguous cases */
+@@ -2988,6 +3015,8 @@ mremap_chunk (mchunkptr p, size_t new_size)
+ if (cp == MAP_FAILED)
+ return 0;
+
++ madvise_thp (cp, new_size);
++
+ p = (mchunkptr) (cp + offset);
+
+ assert (aligned_OK (chunk2mem (p)));
+@@ -5316,6 +5345,24 @@ do_set_mxfast (size_t value)
+ return 0;
+ }
+
++#if HAVE_TUNABLES
++static __always_inline int
++do_set_hugetlb (int32_t value)
++{
++ if (value == 1)
++ {
++ enum malloc_thp_mode_t thp_mode = __malloc_thp_mode ();
++ /*
++ Only enable THP madvise usage if system does support it and
++ has 'madvise' mode. Otherwise the madvise() call is wasteful.
++ */
++ if (thp_mode == malloc_thp_mode_madvise)
++ mp_.thp_pagesize = __malloc_default_thp_pagesize ();
++ }
++ return 0;
++}
++#endif
++
+ int
+ __libc_mallopt (int param_number, int value)
+ {
+diff --git a/manual/tunables.texi b/manual/tunables.texi
+index 28ff502990..9ca6e3f603 100644
+--- a/manual/tunables.texi
++++ b/manual/tunables.texi
+@@ -270,6 +270,16 @@ pointer, so add 4 on 32-bit systems or 8 on 64-bit systems to the size
+ passed to @code{malloc} for the largest bin size to enable.
+ @end deftp
+
++@deftp Tunable glibc.malloc.hugetlb
++This tunable controls the usage of Huge Pages on @code{malloc} calls. The
++default value is @code{0}, which disables any additional support on
++@code{malloc}.
++
++Setting its value to @code{1} enables the use of @code{madvise} with
++@code{MADV_HUGEPAGE} after memory allocation with @code{mmap}. It is enabled
++only if the system supports Transparent Huge Page (currently only on Linux).
++@end deftp
++
+ @node Dynamic Linking Tunables
+ @section Dynamic Linking Tunables
+ @cindex dynamic linking tunables
+diff --git a/sysdeps/generic/Makefile b/sysdeps/generic/Makefile
+index a209e85cc4..8eef83c94d 100644
+--- a/sysdeps/generic/Makefile
++++ b/sysdeps/generic/Makefile
+@@ -27,3 +27,11 @@ sysdep_routines += framestate unwind-pe
+ shared-only-routines += framestate unwind-pe
+ endif
+ endif
++
++ifeq ($(subdir),malloc)
++sysdep_malloc_debug_routines += malloc-hugepages
++endif
++
++ifeq ($(subdir),misc)
++sysdep_routines += malloc-hugepages
++endif
+diff --git a/sysdeps/generic/malloc-hugepages.c b/sysdeps/generic/malloc-hugepages.c
+new file mode 100644
+index 0000000000..8fb459a263
+--- /dev/null
++++ b/sysdeps/generic/malloc-hugepages.c
+@@ -0,0 +1,31 @@
++/* Huge Page support. Generic implementation.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public License as
++ published by the Free Software Foundation; either version 2.1 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; see the file COPYING.LIB. If
++ not, see <https://www.gnu.org/licenses/>. */
++
++#include <malloc-hugepages.h>
++
++unsigned long int
++__malloc_default_thp_pagesize (void)
++{
++ return 0;
++}
++
++enum malloc_thp_mode_t
++__malloc_thp_mode (void)
++{
++ return malloc_thp_mode_not_supported;
++}
+diff --git a/sysdeps/generic/malloc-hugepages.h b/sysdeps/generic/malloc-hugepages.h
+new file mode 100644
+index 0000000000..f5a442e328
+--- /dev/null
++++ b/sysdeps/generic/malloc-hugepages.h
+@@ -0,0 +1,37 @@
++/* Malloc huge page support. Generic implementation.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public License as
++ published by the Free Software Foundation; either version 2.1 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; see the file COPYING.LIB. If
++ not, see <https://www.gnu.org/licenses/>. */
++
++#ifndef _MALLOC_HUGEPAGES_H
++#define _MALLOC_HUGEPAGES_H
++
++#include <stddef.h>
++
++/* Return the default transparent huge page size. */
++unsigned long int __malloc_default_thp_pagesize (void) attribute_hidden;
++
++enum malloc_thp_mode_t
++{
++ malloc_thp_mode_always,
++ malloc_thp_mode_madvise,
++ malloc_thp_mode_never,
++ malloc_thp_mode_not_supported
++};
++
++enum malloc_thp_mode_t __malloc_thp_mode (void) attribute_hidden;
++
++#endif /* _MALLOC_HUGEPAGES_H */
+diff --git a/sysdeps/unix/sysv/linux/malloc-hugepages.c b/sysdeps/unix/sysv/linux/malloc-hugepages.c
+new file mode 100644
+index 0000000000..7497e07260
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/malloc-hugepages.c
+@@ -0,0 +1,74 @@
++/* Huge Page support. Linux implementation.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public License as
++ published by the Free Software Foundation; either version 2.1 of the
++ License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; see the file COPYING.LIB. If
++ not, see <https://www.gnu.org/licenses/>. */
++
++#include <intprops.h>
++#include <malloc-hugepages.h>
++#include <not-cancel.h>
++
++unsigned long int
++__malloc_default_thp_pagesize (void)
++{
++ int fd = __open64_nocancel (
++ "/sys/kernel/mm/transparent_hugepage/hpage_pmd_size", O_RDONLY);
++ if (fd == -1)
++ return 0;
++
++ char str[INT_BUFSIZE_BOUND (unsigned long int)];
++ ssize_t s = __read_nocancel (fd, str, sizeof (str));
++ __close_nocancel (fd);
++ if (s < 0)
++ return 0;
++
++ unsigned long int r = 0;
++ for (ssize_t i = 0; i < s; i++)
++ {
++ if (str[i] == '\n')
++ break;
++ r *= 10;
++ r += str[i] - '0';
++ }
++ return r;
++}
++
++enum malloc_thp_mode_t
++__malloc_thp_mode (void)
++{
++ int fd = __open64_nocancel ("/sys/kernel/mm/transparent_hugepage/enabled",
++ O_RDONLY);
++ if (fd == -1)
++ return malloc_thp_mode_not_supported;
++
++ static const char mode_always[] = "[always] madvise never\n";
++ static const char mode_madvise[] = "always [madvise] never\n";
++ static const char mode_never[] = "always madvise [never]\n";
++
++ char str[sizeof(mode_always)];
++ ssize_t s = __read_nocancel (fd, str, sizeof (str));
++ __close_nocancel (fd);
++
++ if (s == sizeof (mode_always) - 1)
++ {
++ if (strcmp (str, mode_always) == 0)
++ return malloc_thp_mode_always;
++ else if (strcmp (str, mode_madvise) == 0)
++ return malloc_thp_mode_madvise;
++ else if (strcmp (str, mode_never) == 0)
++ return malloc_thp_mode_never;
++ }
++ return malloc_thp_mode_not_supported;
++}
+--
+2.33.0
+
diff --git a/malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch b/malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch
new file mode 100644
index 0000000..58f2abf
--- /dev/null
+++ b/malloc-hugepage-0002-malloc-Add-THP-madvise-support-for-sbrk.patch
@@ -0,0 +1,111 @@
+From 7478c9959ae409f7b3d63146943575d6ee745352 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Fri, 13 Aug 2021 10:06:04 -0300
+Subject: [PATCH 2/7] malloc: Add THP/madvise support for sbrk
+
+To increase effectiveness with Transparent Huge Page with madvise, the
+large page size is use instead page size for sbrk increment for the
+main arena.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ include/libc-pointer-arith.h | 8 ++++++++
+ malloc/malloc.c | 34 +++++++++++++++++++++++++++++-----
+ 2 files changed, 37 insertions(+), 5 deletions(-)
+
+diff --git a/include/libc-pointer-arith.h b/include/libc-pointer-arith.h
+index 04ba537617..55dccc10ac 100644
+--- a/include/libc-pointer-arith.h
++++ b/include/libc-pointer-arith.h
+@@ -60,4 +60,12 @@
+ #define PTR_ALIGN_UP(base, size) \
+ ((__typeof__ (base)) ALIGN_UP ((uintptr_t) (base), (size)))
+
++/* Check if BASE is aligned on SIZE */
++#define PTR_IS_ALIGNED(base, size) \
++ ((((uintptr_t) (base)) & (size - 1)) == 0)
++
++/* Returns the ptrdiff_t diference between P1 and P2. */
++#define PTR_DIFF(p1, p2) \
++ ((ptrdiff_t)((uintptr_t)(p1) - (uintptr_t)(p2)))
++
+ #endif
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index c75841b841..57db4dd9a5 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -2023,6 +2023,16 @@ madvise_thp (void *p, INTERNAL_SIZE_T size)
+ not active. */
+ if (mp_.thp_pagesize == 0 || size < mp_.thp_pagesize)
+ return;
++
++ /* Linux requires the input address to be page-aligned, and unaligned
++ inputs happens only for initial data segment. */
++ if (__glibc_unlikely (!PTR_IS_ALIGNED (p, GLRO (dl_pagesize))))
++ {
++ void *q = PTR_ALIGN_DOWN (p, GLRO (dl_pagesize));
++ size += PTR_DIFF (p, q);
++ p = q;
++ }
++
+ __madvise (p, size, MADV_HUGEPAGE);
+ #endif
+ }
+@@ -2609,14 +2619,25 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ size -= old_size;
+
+ /*
+- Round to a multiple of page size.
++ Round to a multiple of page size or huge page size.
+ If MORECORE is not contiguous, this ensures that we only call it
+ with whole-page arguments. And if MORECORE is contiguous and
+ this is not first time through, this preserves page-alignment of
+ previous calls. Otherwise, we correct to page-align below.
+ */
+
+- size = ALIGN_UP (size, pagesize);
++#if HAVE_TUNABLES && defined (MADV_HUGEPAGE)
++ /* Defined in brk.c. */
++ extern void *__curbrk;
++ if (__glibc_unlikely (mp_.thp_pagesize != 0))
++ {
++ uintptr_t top = ALIGN_UP ((uintptr_t) __curbrk + size,
++ mp_.thp_pagesize);
++ size = top - (uintptr_t) __curbrk;
++ }
++ else
++#endif
++ size = ALIGN_UP (size, GLRO(dl_pagesize));
+
+ /*
+ Don't try to call MORECORE if argument is so big as to appear
+@@ -2899,10 +2920,8 @@ systrim (size_t pad, mstate av)
+ long released; /* Amount actually released */
+ char *current_brk; /* address returned by pre-check sbrk call */
+ char *new_brk; /* address returned by post-check sbrk call */
+- size_t pagesize;
+ long top_area;
+
+- pagesize = GLRO (dl_pagesize);
+ top_size = chunksize (av->top);
+
+ top_area = top_size - MINSIZE - 1;
+@@ -2910,7 +2929,12 @@ systrim (size_t pad, mstate av)
+ return 0;
+
+ /* Release in pagesize units and round down to the nearest page. */
+- extra = ALIGN_DOWN(top_area - pad, pagesize);
++#if HAVE_TUNABLES && defined (MADV_HUGEPAGE)
++ if (__glibc_unlikely (mp_.thp_pagesize != 0))
++ extra = ALIGN_DOWN (top_area - pad, mp_.thp_pagesize);
++ else
++#endif
++ extra = ALIGN_DOWN (top_area - pad, GLRO(dl_pagesize));
+
+ if (extra == 0)
+ return 0;
+--
+2.33.0
+
diff --git a/malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch b/malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch
new file mode 100644
index 0000000..5b1768b
--- /dev/null
+++ b/malloc-hugepage-0003-malloc-Move-mmap-logic-to-its-own-function.patch
@@ -0,0 +1,205 @@
+From 6cc3ccc67e0dda654fc839377af2818a296f0007 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 16 Aug 2021 11:14:20 -0300
+Subject: [PATCH 3/7] malloc: Move mmap logic to its own function
+
+So it can be used with different pagesize and flags.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ malloc/malloc.c | 164 ++++++++++++++++++++++++++----------------------
+ 1 file changed, 88 insertions(+), 76 deletions(-)
+
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 57db4dd9a5..6b6ec53db1 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -2412,6 +2412,85 @@ do_check_malloc_state (mstate av)
+ be extended or replaced.
+ */
+
++static void *
++sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
++{
++ long int size;
++
++ /*
++ Round up size to nearest page. For mmapped chunks, the overhead is one
++ SIZE_SZ unit larger than for normal chunks, because there is no
++ following chunk whose prev_size field could be used.
++
++ See the front_misalign handling below, for glibc there is no need for
++ further alignments unless we have have high alignment.
++ */
++ if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
++ size = ALIGN_UP (nb + SIZE_SZ, pagesize);
++ else
++ size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize);
++
++ /* Don't try if size wraps around 0. */
++ if ((unsigned long) (size) <= (unsigned long) (nb))
++ return MAP_FAILED;
++
++ char *mm = (char *) MMAP (0, size,
++ mtag_mmap_flags | PROT_READ | PROT_WRITE,
++ extra_flags);
++ if (mm == MAP_FAILED)
++ return mm;
++
++ madvise_thp (mm, size);
++
++ /*
++ The offset to the start of the mmapped region is stored in the prev_size
++ field of the chunk. This allows us to adjust returned start address to
++ meet alignment requirements here and in memalign(), and still be able to
++ compute proper address argument for later munmap in free() and realloc().
++ */
++
++ INTERNAL_SIZE_T front_misalign; /* unusable bytes at front of new space */
++
++ if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
++ {
++ /* For glibc, chunk2mem increases the address by CHUNK_HDR_SZ and
++ MALLOC_ALIGN_MASK is CHUNK_HDR_SZ-1. Each mmap'ed area is page
++ aligned and therefore definitely MALLOC_ALIGN_MASK-aligned. */
++ assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0);
++ front_misalign = 0;
++ }
++ else
++ front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK;
++
++ mchunkptr p; /* the allocated/returned chunk */
++
++ if (front_misalign > 0)
++ {
++ ptrdiff_t correction = MALLOC_ALIGNMENT - front_misalign;
++ p = (mchunkptr) (mm + correction);
++ set_prev_size (p, correction);
++ set_head (p, (size - correction) | IS_MMAPPED);
++ }
++ else
++ {
++ p = (mchunkptr) mm;
++ set_prev_size (p, 0);
++ set_head (p, size | IS_MMAPPED);
++ }
++
++ /* update statistics */
++ int new = atomic_exchange_and_add (&mp_.n_mmaps, 1) + 1;
++ atomic_max (&mp_.max_n_mmaps, new);
++
++ unsigned long sum;
++ sum = atomic_exchange_and_add (&mp_.mmapped_mem, size) + size;
++ atomic_max (&mp_.max_mmapped_mem, sum);
++
++ check_chunk (av, p);
++
++ return chunk2mem (p);
++}
++
+ static void *
+ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ {
+@@ -2449,81 +2528,10 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
+ && (mp_.n_mmaps < mp_.n_mmaps_max)))
+ {
+- char *mm; /* return value from mmap call*/
+-
+- try_mmap:
+- /*
+- Round up size to nearest page. For mmapped chunks, the overhead
+- is one SIZE_SZ unit larger than for normal chunks, because there
+- is no following chunk whose prev_size field could be used.
+-
+- See the front_misalign handling below, for glibc there is no
+- need for further alignments unless we have have high alignment.
+- */
+- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+- size = ALIGN_UP (nb + SIZE_SZ, pagesize);
+- else
+- size = ALIGN_UP (nb + SIZE_SZ + MALLOC_ALIGN_MASK, pagesize);
++ char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
++ if (mm != MAP_FAILED)
++ return mm;
+ tried_mmap = true;
+-
+- /* Don't try if size wraps around 0 */
+- if ((unsigned long) (size) > (unsigned long) (nb))
+- {
+- mm = (char *) (MMAP (0, size,
+- mtag_mmap_flags | PROT_READ | PROT_WRITE, 0));
+-
+- if (mm != MAP_FAILED)
+- {
+- madvise_thp (mm, size);
+-
+- /*
+- The offset to the start of the mmapped region is stored
+- in the prev_size field of the chunk. This allows us to adjust
+- returned start address to meet alignment requirements here
+- and in memalign(), and still be able to compute proper
+- address argument for later munmap in free() and realloc().
+- */
+-
+- if (MALLOC_ALIGNMENT == CHUNK_HDR_SZ)
+- {
+- /* For glibc, chunk2mem increases the address by
+- CHUNK_HDR_SZ and MALLOC_ALIGN_MASK is
+- CHUNK_HDR_SZ-1. Each mmap'ed area is page
+- aligned and therefore definitely
+- MALLOC_ALIGN_MASK-aligned. */
+- assert (((INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK) == 0);
+- front_misalign = 0;
+- }
+- else
+- front_misalign = (INTERNAL_SIZE_T) chunk2mem (mm) & MALLOC_ALIGN_MASK;
+- if (front_misalign > 0)
+- {
+- correction = MALLOC_ALIGNMENT - front_misalign;
+- p = (mchunkptr) (mm + correction);
+- set_prev_size (p, correction);
+- set_head (p, (size - correction) | IS_MMAPPED);
+- }
+- else
+- {
+- p = (mchunkptr) mm;
+- set_prev_size (p, 0);
+- set_head (p, size | IS_MMAPPED);
+- }
+-
+- /* update statistics */
+-
+- int new = atomic_exchange_and_add (&mp_.n_mmaps, 1) + 1;
+- atomic_max (&mp_.max_n_mmaps, new);
+-
+- unsigned long sum;
+- sum = atomic_exchange_and_add (&mp_.mmapped_mem, size) + size;
+- atomic_max (&mp_.max_mmapped_mem, sum);
+-
+- check_chunk (av, p);
+-
+- return chunk2mem (p);
+- }
+- }
+ }
+
+ /* There are no usable arenas and mmap also failed. */
+@@ -2600,8 +2608,12 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ }
+ }
+ else if (!tried_mmap)
+- /* We can at least try to use to mmap memory. */
+- goto try_mmap;
++ {
++ /* We can at least try to use to mmap memory. */
++ char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
++ if (mm != MAP_FAILED)
++ return mm;
++ }
+ }
+ else /* av == main_arena */
+
+--
+2.33.0
+
diff --git a/malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch b/malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch
new file mode 100644
index 0000000..1969a1f
--- /dev/null
+++ b/malloc-hugepage-0004-malloc-Add-Huge-Page-support-for-mmap.patch
@@ -0,0 +1,476 @@
+From 98d5fcb8d099a1a868e032c89891c395a2f365c5 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 16 Aug 2021 15:08:27 -0300
+Subject: [PATCH 4/7] malloc: Add Huge Page support for mmap
+
+With the morecore hook removed, there is not easy way to provide huge
+pages support on with glibc allocator without resorting to transparent
+huge pages. And some users and programs do prefer to use the huge pages
+directly instead of THP for multiple reasons: no splitting, re-merging
+by the VM, no TLB shootdowns for running processes, fast allocation
+from the reserve pool, no competition with the rest of the processes
+unlike THP, no swapping all, etc.
+
+This patch extends the 'glibc.malloc.hugetlb' tunable: the value
+'2' means to use huge pages directly with the system default size,
+while a positive value means and specific page size that is matched
+against the supported ones by the system.
+
+Currently only memory allocated on sysmalloc() is handled, the arenas
+still uses the default system page size.
+
+To test is a new rule is added tests-malloc-hugetlb2, which run the
+addes tests with the required GLIBC_TUNABLE setting. On systems without
+a reserved huge pages pool, is just stress the mmap(MAP_HUGETLB)
+allocation failure. To improve test coverage it is required to create
+a pool with some allocated pages.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ NEWS | 8 +-
+ Rules | 17 +++
+ elf/dl-tunables.list | 3 +-
+ elf/tst-rtld-list-tunables.exp | 2 +-
+ malloc/Makefile | 8 +-
+ malloc/arena.c | 4 +-
+ malloc/malloc.c | 31 ++++-
+ manual/tunables.texi | 7 ++
+ sysdeps/generic/malloc-hugepages.c | 8 ++
+ sysdeps/generic/malloc-hugepages.h | 7 ++
+ sysdeps/unix/sysv/linux/malloc-hugepages.c | 127 +++++++++++++++++++++
+ 11 files changed, 207 insertions(+), 15 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index 3b94dd209c..c7200cd4e8 100644
+--- a/NEWS
++++ b/NEWS
+@@ -93,9 +93,11 @@ Major new features:
+ Restartable Sequences.
+
+ * On Linux, a new tunable, glibc.malloc.hugetlb, can be used to
+- make malloc issue madvise plus MADV_HUGEPAGE on mmap and sbrk calls.
+- Setting this might improve performance with Transparent Huge Pages madvise
+- mode depending of the workload.
++ either make malloc issue madvise plus MADV_HUGEPAGE on mmap and sbrk
++ or to use huge pages directly with mmap calls with the MAP_HUGETLB
++ flags). The former can improve performance when Transparent Huge Pages
++ is set to 'madvise' mode while the latter uses the system reserved
++ huge pages.
+
+ Deprecated and removed features, and other changes affecting compatibility:
+
+diff --git a/Rules b/Rules
+index 5f5d9ba4cc..be34982daa 100644
+--- a/Rules
++++ b/Rules
+@@ -158,6 +158,7 @@ tests: $(tests:%=$(objpfx)%.out) $(tests-internal:%=$(objpfx)%.out) \
+ $(tests-mcheck:%=$(objpfx)%-mcheck.out) \
+ $(tests-malloc-check:%=$(objpfx)%-malloc-check.out) \
+ $(tests-malloc-hugetlb1:%=$(objpfx)%-malloc-hugetlb1.out) \
++ $(tests-malloc-hugetlb2:%=$(objpfx)%-malloc-hugetlb2.out) \
+ $(tests-special) $(tests-printers-out)
+ xtests: tests $(xtests:%=$(objpfx)%.out) $(xtests-special)
+ endif
+@@ -170,6 +171,7 @@ else
+ tests-expected = $(tests) $(tests-internal) $(tests-printers) \
+ $(tests-container) $(tests-malloc-check:%=%-malloc-check) \
+ $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1) \
++ $(tests-malloc-hugetlb2:%=%-malloc-hugetlb2) \
+ $(tests-mcheck:%=%-mcheck)
+ endif
+ tests:
+@@ -199,6 +201,7 @@ endif
+ binaries-mcheck-tests = $(tests-mcheck:%=%-mcheck)
+ binaries-malloc-check-tests = $(tests-malloc-check:%=%-malloc-check)
+ binaries-malloc-hugetlb1-tests = $(tests-malloc-hugetlb1:%=%-malloc-hugetlb1)
++binaries-malloc-hugetlb2-tests = $(tests-malloc-hugetlb2:%=%-malloc-hugetlb2)
+ else
+ binaries-all-notests =
+ binaries-all-tests = $(tests) $(tests-internal) $(xtests) $(test-srcs)
+@@ -211,6 +214,7 @@ binaries-pie-notests =
+ binaries-mcheck-tests =
+ binaries-malloc-check-tests =
+ binaries-malloc-hugetlb1-tests =
++binaries-malloc-hugetlb2-tests =
+ endif
+
+ binaries-pie = $(binaries-pie-tests) $(binaries-pie-notests)
+@@ -259,6 +263,14 @@ $(addprefix $(objpfx),$(binaries-malloc-hugetlb1-tests)): %-malloc-hugetlb1: %.o
+ $(+link-tests)
+ endif
+
++ifneq "$(strip $(binaries-malloc-hugetlb2-tests))" ""
++$(addprefix $(objpfx),$(binaries-malloc-hugetlb2-tests)): %-malloc-hugetlb2: %.o \
++ $(link-extra-libs-tests) \
++ $(sort $(filter $(common-objpfx)lib%,$(link-libc))) \
++ $(addprefix $(csu-objpfx),start.o) $(+preinit) $(+postinit)
++ $(+link-tests)
++endif
++
+ ifneq "$(strip $(binaries-pie-tests))" ""
+ $(addprefix $(objpfx),$(binaries-pie-tests)): %: %.o \
+ $(link-extra-libs-tests) \
+@@ -302,6 +314,11 @@ $(1)-malloc-hugetlb1-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=1
+ endef
+ $(foreach t,$(tests-malloc-hugetlb1),$(eval $(call malloc-hugetlb1-ENVS,$(t))))
+
++# All malloc-hugetlb2 tests will be run with GLIBC_TUNABLE=glibc.malloc.hugetlb=2
++define malloc-hugetlb2-ENVS
++$(1)-malloc-hugetlb2-ENV += GLIBC_TUNABLES=glibc.malloc.hugetlb=2
++endef
++$(foreach t,$(tests-malloc-hugetlb2),$(eval $(call malloc-hugetlb2-ENVS,$(t))))
+
+ # mcheck tests need the debug DSO to support -lmcheck.
+ define mcheck-ENVS
+diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list
+index d1fd3f3e91..845d521a43 100644
+--- a/elf/dl-tunables.list
++++ b/elf/dl-tunables.list
+@@ -93,9 +93,8 @@ glibc {
+ security_level: SXID_IGNORE
+ }
+ hugetlb {
+- type: INT_32
++ type: SIZE_T
+ minval: 0
+- maxval: 1
+ }
+ }
+ cpu {
+diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp
+index d8e363f2c5..cdfdb56a94 100644
+--- a/elf/tst-rtld-list-tunables.exp
++++ b/elf/tst-rtld-list-tunables.exp
+@@ -1,7 +1,7 @@
+ glibc.malloc.arena_max: 0x0 (min: 0x1, max: 0x[f]+)
+ glibc.malloc.arena_test: 0x0 (min: 0x1, max: 0x[f]+)
+ glibc.malloc.check: 0 (min: 0, max: 3)
+-glibc.malloc.hugetlb: 0 (min: 0, max: 1)
++glibc.malloc.hugetlb: 0x0 (min: 0x0, max: 0x[f]+)
+ glibc.malloc.mmap_max: 0 (min: 0, max: 2147483647)
+ glibc.malloc.mmap_threshold: 0x0 (min: 0x0, max: 0x[f]+)
+ glibc.malloc.mxfast: 0x0 (min: 0x0, max: 0x[f]+)
+diff --git a/malloc/Makefile b/malloc/Makefile
+index 0137595e17..e9a6666d22 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -78,9 +78,9 @@ tests-exclude-malloc-check = tst-malloc-check tst-malloc-usable \
+ tests-malloc-check = $(filter-out $(tests-exclude-malloc-check) \
+ $(tests-static),$(tests))
+
+-# Run all testes with GLIBC_TUNABLES=glibc.malloc.hugetlb=1 that check the
+-# Transparent Huge Pages support. We need exclude some tests that define
+-# the ENV vars.
++# Run all tests with GLIBC_TUNABLES=glibc.malloc.hugetlb={1,2} which check
++# the Transparent Huge Pages support (1) or automatic huge page support (2).
++# We need exclude some tests that define the ENV vars.
+ tests-exclude-hugetlb1 = \
+ tst-compathooks-off \
+ tst-compathooks-on \
+@@ -93,6 +93,8 @@ tests-exclude-hugetlb1 = \
+ tst-mallocstate
+ tests-malloc-hugetlb1 = \
+ $(filter-out $(tests-exclude-hugetlb1), $(tests))
++tests-malloc-hugetlb2 = \
++ $(filter-out $(tests-exclude-hugetlb1), $(tests))
+
+ # -lmcheck needs __malloc_initialize_hook, which was deprecated in 2.24.
+ ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
+diff --git a/malloc/arena.c b/malloc/arena.c
+index cd00c7bef4..9a6e1af2bd 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -230,7 +230,7 @@ TUNABLE_CALLBACK_FNDECL (set_tcache_count, size_t)
+ TUNABLE_CALLBACK_FNDECL (set_tcache_unsorted_limit, size_t)
+ #endif
+ TUNABLE_CALLBACK_FNDECL (set_mxfast, size_t)
+-TUNABLE_CALLBACK_FNDECL (set_hugetlb, int32_t)
++TUNABLE_CALLBACK_FNDECL (set_hugetlb, size_t)
+ #else
+ /* Initialization routine. */
+ #include <string.h>
+@@ -331,7 +331,7 @@ ptmalloc_init (void)
+ TUNABLE_CALLBACK (set_tcache_unsorted_limit));
+ # endif
+ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast));
+- TUNABLE_GET (hugetlb, int32_t, TUNABLE_CALLBACK (set_hugetlb));
++ TUNABLE_GET (hugetlb, size_t, TUNABLE_CALLBACK (set_hugetlb));
+ #else
+ if (__glibc_likely (_environ != NULL))
+ {
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 6b6ec53db1..75efdc2ee7 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -1883,6 +1883,10 @@ struct malloc_par
+ #if HAVE_TUNABLES
+ /* Transparent Large Page support. */
+ INTERNAL_SIZE_T thp_pagesize;
++ /* A value different than 0 means to align mmap allocation to hp_pagesize
++ add hp_flags on flags. */
++ INTERNAL_SIZE_T hp_pagesize;
++ int hp_flags;
+ #endif
+
+ /* Memory map support */
+@@ -2440,7 +2444,10 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
+ if (mm == MAP_FAILED)
+ return mm;
+
+- madvise_thp (mm, size);
++#ifdef MAP_HUGETLB
++ if (!(extra_flags & MAP_HUGETLB))
++ madvise_thp (mm, size);
++#endif
+
+ /*
+ The offset to the start of the mmapped region is stored in the prev_size
+@@ -2528,7 +2535,18 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ || ((unsigned long) (nb) >= (unsigned long) (mp_.mmap_threshold)
+ && (mp_.n_mmaps < mp_.n_mmaps_max)))
+ {
+- char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
++ char *mm;
++#if HAVE_TUNABLES
++ if (mp_.hp_pagesize > 0 && nb >= mp_.hp_pagesize)
++ {
++ /* There is no need to isse the THP madvise call if Huge Pages are
++ used directly. */
++ mm = sysmalloc_mmap (nb, mp_.hp_pagesize, mp_.hp_flags, av);
++ if (mm != MAP_FAILED)
++ return mm;
++ }
++#endif
++ mm = sysmalloc_mmap (nb, pagesize, 0, av);
+ if (mm != MAP_FAILED)
+ return mm;
+ tried_mmap = true;
+@@ -2609,7 +2627,9 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ }
+ else if (!tried_mmap)
+ {
+- /* We can at least try to use to mmap memory. */
++ /* We can at least try to use to mmap memory. If new_heap fails
++ it is unlikely that trying to allocate huge pages will
++ succeed. */
+ char *mm = sysmalloc_mmap (nb, pagesize, 0, av);
+ if (mm != MAP_FAILED)
+ return mm;
+@@ -5383,7 +5403,7 @@ do_set_mxfast (size_t value)
+
+ #if HAVE_TUNABLES
+ static __always_inline int
+-do_set_hugetlb (int32_t value)
++do_set_hugetlb (size_t value)
+ {
+ if (value == 1)
+ {
+@@ -5395,6 +5415,9 @@ do_set_hugetlb (int32_t value)
+ if (thp_mode == malloc_thp_mode_madvise)
+ mp_.thp_pagesize = __malloc_default_thp_pagesize ();
+ }
++ else if (value >= 2)
++ __malloc_hugepage_config (value == 2 ? 0 : value, &mp_.hp_pagesize,
++ &mp_.hp_flags);
+ return 0;
+ }
+ #endif
+diff --git a/manual/tunables.texi b/manual/tunables.texi
+index 9ca6e3f603..58a47b2e9b 100644
+--- a/manual/tunables.texi
++++ b/manual/tunables.texi
+@@ -278,6 +278,13 @@ default value is @code{0}, which disables any additional support on
+ Setting its value to @code{1} enables the use of @code{madvise} with
+ @code{MADV_HUGEPAGE} after memory allocation with @code{mmap}. It is enabled
+ only if the system supports Transparent Huge Page (currently only on Linux).
++
++Setting its value to @code{2} enables the use of Huge Page directly with
++@code{mmap} with the use of @code{MAP_HUGETLB} flag. The huge page size
++to use will be the default one provided by the system. A value larger than
++@code{2} specifies huge page size, which will be matched against the system
++supported ones. If provided value is invalid, @code{MAP_HUGETLB} will not
++be used.
+ @end deftp
+
+ @node Dynamic Linking Tunables
+diff --git a/sysdeps/generic/malloc-hugepages.c b/sysdeps/generic/malloc-hugepages.c
+index 8fb459a263..946284a33c 100644
+--- a/sysdeps/generic/malloc-hugepages.c
++++ b/sysdeps/generic/malloc-hugepages.c
+@@ -29,3 +29,11 @@ __malloc_thp_mode (void)
+ {
+ return malloc_thp_mode_not_supported;
+ }
++
++/* Return the default transparent huge page size. */
++void
++__malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags)
++{
++ *pagesize = 0;
++ *flags = 0;
++}
+diff --git a/sysdeps/generic/malloc-hugepages.h b/sysdeps/generic/malloc-hugepages.h
+index f5a442e328..75cda3796a 100644
+--- a/sysdeps/generic/malloc-hugepages.h
++++ b/sysdeps/generic/malloc-hugepages.h
+@@ -34,4 +34,11 @@ enum malloc_thp_mode_t
+
+ enum malloc_thp_mode_t __malloc_thp_mode (void) attribute_hidden;
+
++/* Return the supported huge page size from the REQUESTED sizes on PAGESIZE
++ along with the required extra mmap flags on FLAGS, Requesting the value
++ of 0 returns the default huge page size, otherwise the value will be
++ matched against the sizes supported by the system. */
++void __malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags)
++ attribute_hidden;
++
+ #endif /* _MALLOC_HUGEPAGES_H */
+diff --git a/sysdeps/unix/sysv/linux/malloc-hugepages.c b/sysdeps/unix/sysv/linux/malloc-hugepages.c
+index 7497e07260..0e05291d61 100644
+--- a/sysdeps/unix/sysv/linux/malloc-hugepages.c
++++ b/sysdeps/unix/sysv/linux/malloc-hugepages.c
+@@ -17,8 +17,10 @@
+ not, see <https://www.gnu.org/licenses/>. */
+
+ #include <intprops.h>
++#include <dirent.h>
+ #include <malloc-hugepages.h>
+ #include <not-cancel.h>
++#include <sys/mman.h>
+
+ unsigned long int
+ __malloc_default_thp_pagesize (void)
+@@ -72,3 +74,128 @@ __malloc_thp_mode (void)
+ }
+ return malloc_thp_mode_not_supported;
+ }
++
++static size_t
++malloc_default_hugepage_size (void)
++{
++ int fd = __open64_nocancel ("/proc/meminfo", O_RDONLY);
++ if (fd == -1)
++ return 0;
++
++ size_t hpsize = 0;
++
++ char buf[512];
++ off64_t off = 0;
++ while (1)
++ {
++ ssize_t r = __pread64_nocancel (fd, buf, sizeof (buf) - 1, off);
++ if (r < 0)
++ break;
++ buf[r] = '\0';
++
++ /* If the tag is not found, read the last line again. */
++ const char *s = strstr (buf, "Hugepagesize:");
++ if (s == NULL)
++ {
++ char *nl = strrchr (buf, '\n');
++ if (nl == NULL)
++ break;
++ off += (nl + 1) - buf;
++ continue;
++ }
++
++ /* The default huge page size is in the form:
++ Hugepagesize: NUMBER kB */
++ s += sizeof ("Hugepagesize: ") - 1;
++ for (int i = 0; (s[i] >= '0' && s[i] <= '9') || s[i] == ' '; i++)
++ {
++ if (s[i] == ' ')
++ continue;
++ hpsize *= 10;
++ hpsize += s[i] - '0';
++ }
++ hpsize *= 1024;
++ break;
++ }
++
++ __close_nocancel (fd);
++
++ return hpsize;
++}
++
++static inline int
++hugepage_flags (size_t pagesize)
++{
++ return MAP_HUGETLB | (__builtin_ctzll (pagesize) << MAP_HUGE_SHIFT);
++}
++
++void
++__malloc_hugepage_config (size_t requested, size_t *pagesize, int *flags)
++{
++ *pagesize = 0;
++ *flags = 0;
++
++ if (requested == 0)
++ {
++ *pagesize = malloc_default_hugepage_size ();
++ if (*pagesize != 0)
++ *flags = hugepage_flags (*pagesize);
++ return;
++ }
++
++ /* Each entry represents a supported huge page in the form of:
++ hugepages-<size>kB. */
++ int dirfd = __open64_nocancel ("/sys/kernel/mm/hugepages",
++ O_RDONLY | O_DIRECTORY, 0);
++ if (dirfd == -1)
++ return;
++
++ char buffer[1024];
++ while (true)
++ {
++#if !IS_IN(libc)
++# define __getdents64 getdents64
++#endif
++ ssize_t ret = __getdents64 (dirfd, buffer, sizeof (buffer));
++ if (ret == -1)
++ break;
++ else if (ret == 0)
++ break;
++
++ bool found = false;
++ char *begin = buffer, *end = buffer + ret;
++ while (begin != end)
++ {
++ unsigned short int d_reclen;
++ memcpy (&d_reclen, begin + offsetof (struct dirent64, d_reclen),
++ sizeof (d_reclen));
++ const char *dname = begin + offsetof (struct dirent64, d_name);
++ begin += d_reclen;
++
++ if (dname[0] == '.'
++ || strncmp (dname, "hugepages-", sizeof ("hugepages-") - 1) != 0)
++ continue;
++
++ size_t hpsize = 0;
++ const char *sizestr = dname + sizeof ("hugepages-") - 1;
++ for (int i = 0; sizestr[i] >= '0' && sizestr[i] <= '9'; i++)
++ {
++ hpsize *= 10;
++ hpsize += sizestr[i] - '0';
++ }
++ hpsize *= 1024;
++
++ if (hpsize == requested)
++ {
++ *pagesize = hpsize;
++ *flags = hugepage_flags (*pagesize);
++ found = true;
++ break;
++ }
++ }
++ if (found)
++ break;
++ }
++
++ __close_nocancel (dirfd);
++}
+--
+2.33.0
+
diff --git a/malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch b/malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch
new file mode 100644
index 0000000..f759588
--- /dev/null
+++ b/malloc-hugepage-0005-malloc-Add-Huge-Page-support-to-arenas.patch
@@ -0,0 +1,338 @@
+From c1beb51d08d3d7ec935b0a2419b4c6fad91d1969 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Fri, 20 Aug 2021 13:22:35 -0300
+Subject: [PATCH 5/7] malloc: Add Huge Page support to arenas
+
+It is enabled as default for glibc.malloc.hugetlb set to 2 or higher.
+It also uses a non configurable minimum value and maximum value,
+currently set respectively to 1 and 4 selected huge page size.
+
+The arena allocation with huge pages does not use MAP_NORESERVE. As
+indicate by kernel internal documentation [1], the flag might trigger
+a SIGBUS on soft page faults if at memory access there is no left
+pages in the pool.
+
+On systems without a reserved huge pages pool, is just stress the
+mmap(MAP_HUGETLB) allocation failure. To improve test coverage it is
+required to create a pool with some allocated pages.
+
+Checked on x86_64-linux-gnu with no reserved pages, 10 reserved pages
+(which trigger mmap(MAP_HUGETBL) failures) and with 256 reserved pages
+(which does not trigger mmap(MAP_HUGETLB) failures).
+
+[1] https://www.kernel.org/doc/html/v4.18/vm/hugetlbfs_reserv.html#resv-map-modifications
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ malloc/Makefile | 7 ++-
+ malloc/arena.c | 134 +++++++++++++++++++++++++++++++++---------------
+ malloc/malloc.c | 2 +-
+ 3 files changed, 99 insertions(+), 44 deletions(-)
+
+diff --git a/malloc/Makefile b/malloc/Makefile
+index e9a6666d22..451eb84612 100644
+--- a/malloc/Makefile
++++ b/malloc/Makefile
+@@ -91,10 +91,15 @@ tests-exclude-hugetlb1 = \
+ tst-malloc-usable \
+ tst-malloc-usable-tunables \
+ tst-mallocstate
++# The tst-free-errno relies on the used malloc page size to mmap an
++# overlapping region.
++tests-exclude-hugetlb2 = \
++ $(tests-exclude-hugetlb1) \
++ tst-free-errno
+ tests-malloc-hugetlb1 = \
+ $(filter-out $(tests-exclude-hugetlb1), $(tests))
+ tests-malloc-hugetlb2 = \
+- $(filter-out $(tests-exclude-hugetlb1), $(tests))
++ $(filter-out $(tests-exclude-hugetlb2), $(tests))
+
+ # -lmcheck needs __malloc_initialize_hook, which was deprecated in 2.24.
+ ifeq ($(have-GLIBC_2.23)$(build-shared),yesyes)
+diff --git a/malloc/arena.c b/malloc/arena.c
+index 9a6e1af2bd..e1852f8597 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -41,6 +41,29 @@
+ mmap threshold, so that requests with a size just below that
+ threshold can be fulfilled without creating too many heaps. */
+
++/* When huge pages are used to create new arenas, the maximum and minumum
++ size are based on the runtime defined huge page size. */
++
++static inline size_t
++heap_min_size (void)
++{
++#if HAVE_TUNABLES
++ return mp_.hp_pagesize == 0 ? HEAP_MIN_SIZE : mp_.hp_pagesize;
++#else
++ return HEAP_MIN_SIZE;
++#endif
++}
++
++static inline size_t
++heap_max_size (void)
++{
++#if HAVE_TUNABLES
++ return mp_.hp_pagesize == 0 ? HEAP_MAX_SIZE : mp_.hp_pagesize * 4;
++#else
++ return HEAP_MAX_SIZE;
++#endif
++}
++
+ /***************************************************************************/
+
+ #define top(ar_ptr) ((ar_ptr)->top)
+@@ -56,10 +79,11 @@ typedef struct _heap_info
+ size_t size; /* Current size in bytes. */
+ size_t mprotect_size; /* Size in bytes that has been mprotected
+ PROT_READ|PROT_WRITE. */
++ size_t pagesize; /* Page size used when allocating the arena. */
+ /* Make sure the following data is properly aligned, particularly
+ that sizeof (heap_info) + 2 * SIZE_SZ is a multiple of
+ MALLOC_ALIGNMENT. */
+- char pad[-6 * SIZE_SZ & MALLOC_ALIGN_MASK];
++ char pad[-3 * SIZE_SZ & MALLOC_ALIGN_MASK];
+ } heap_info;
+
+ /* Get a compile-time error if the heap_info padding is not correct
+@@ -125,10 +149,18 @@ static bool __malloc_initialized = false;
+
+ /* find the heap and corresponding arena for a given ptr */
+
+-#define heap_for_ptr(ptr) \
+- ((heap_info *) ((unsigned long) (ptr) & ~(HEAP_MAX_SIZE - 1)))
+-#define arena_for_chunk(ptr) \
+- (chunk_main_arena (ptr) ? &main_arena : heap_for_ptr (ptr)->ar_ptr)
++static inline heap_info *
++heap_for_ptr (void *ptr)
++{
++ size_t max_size = heap_max_size ();
++ return PTR_ALIGN_DOWN (ptr, max_size);
++}
++
++static inline struct malloc_state *
++arena_for_chunk (mchunkptr ptr)
++{
++ return chunk_main_arena (ptr) ? &main_arena : heap_for_ptr (ptr)->ar_ptr;
++}
+
+
+ /**************************************************************************/
+@@ -443,71 +475,72 @@ static char *aligned_heap_area;
+ of the page size. */
+
+ static heap_info *
+-new_heap (size_t size, size_t top_pad)
++alloc_new_heap (size_t size, size_t top_pad, size_t pagesize,
++ int mmap_flags)
+ {
+- size_t pagesize = GLRO (dl_pagesize);
+ char *p1, *p2;
+ unsigned long ul;
+ heap_info *h;
++ size_t min_size = heap_min_size ();
++ size_t max_size = heap_max_size ();
+
+- if (size + top_pad < HEAP_MIN_SIZE)
+- size = HEAP_MIN_SIZE;
+- else if (size + top_pad <= HEAP_MAX_SIZE)
++ if (size + top_pad < min_size)
++ size = min_size;
++ else if (size + top_pad <= max_size)
+ size += top_pad;
+- else if (size > HEAP_MAX_SIZE)
++ else if (size > max_size)
+ return 0;
+ else
+- size = HEAP_MAX_SIZE;
++ size = max_size;
+ size = ALIGN_UP (size, pagesize);
+
+- /* A memory region aligned to a multiple of HEAP_MAX_SIZE is needed.
++ /* A memory region aligned to a multiple of max_size is needed.
+ No swap space needs to be reserved for the following large
+ mapping (on Linux, this is the case for all non-writable mappings
+ anyway). */
+ p2 = MAP_FAILED;
+ if (aligned_heap_area)
+ {
+- p2 = (char *) MMAP (aligned_heap_area, HEAP_MAX_SIZE, PROT_NONE,
+- MAP_NORESERVE);
++ p2 = (char *) MMAP (aligned_heap_area, max_size, PROT_NONE, mmap_flags);
+ aligned_heap_area = NULL;
+- if (p2 != MAP_FAILED && ((unsigned long) p2 & (HEAP_MAX_SIZE - 1)))
++ if (p2 != MAP_FAILED && ((unsigned long) p2 & (max_size - 1)))
+ {
+- __munmap (p2, HEAP_MAX_SIZE);
++ __munmap (p2, max_size);
+ p2 = MAP_FAILED;
+ }
+ }
+ if (p2 == MAP_FAILED)
+ {
+- p1 = (char *) MMAP (0, HEAP_MAX_SIZE << 1, PROT_NONE, MAP_NORESERVE);
++ p1 = (char *) MMAP (0, max_size << 1, PROT_NONE, mmap_flags);
+ if (p1 != MAP_FAILED)
+ {
+- p2 = (char *) (((unsigned long) p1 + (HEAP_MAX_SIZE - 1))
+- & ~(HEAP_MAX_SIZE - 1));
++ p2 = (char *) (((unsigned long) p1 + (max_size - 1))
++ & ~(max_size - 1));
+ ul = p2 - p1;
+ if (ul)
+ __munmap (p1, ul);
+ else
+- aligned_heap_area = p2 + HEAP_MAX_SIZE;
+- __munmap (p2 + HEAP_MAX_SIZE, HEAP_MAX_SIZE - ul);
++ aligned_heap_area = p2 + max_size;
++ __munmap (p2 + max_size, max_size - ul);
+ }
+ else
+ {
+- /* Try to take the chance that an allocation of only HEAP_MAX_SIZE
++ /* Try to take the chance that an allocation of only max_size
+ is already aligned. */
+- p2 = (char *) MMAP (0, HEAP_MAX_SIZE, PROT_NONE, MAP_NORESERVE);
++ p2 = (char *) MMAP (0, max_size, PROT_NONE, mmap_flags);
+ if (p2 == MAP_FAILED)
+ return 0;
+
+- if ((unsigned long) p2 & (HEAP_MAX_SIZE - 1))
++ if ((unsigned long) p2 & (max_size - 1))
+ {
+- __munmap (p2, HEAP_MAX_SIZE);
++ __munmap (p2, max_size);
+ return 0;
+ }
+ }
+ }
+ if (__mprotect (p2, size, mtag_mmap_flags | PROT_READ | PROT_WRITE) != 0)
+ {
+- __munmap (p2, HEAP_MAX_SIZE);
++ __munmap (p2, max_size);
+ return 0;
+ }
+
+@@ -516,22 +549,42 @@ new_heap (size_t size, size_t top_pad)
+ h = (heap_info *) p2;
+ h->size = size;
+ h->mprotect_size = size;
++ h->pagesize = pagesize;
+ LIBC_PROBE (memory_heap_new, 2, h, h->size);
+ return h;
+ }
+
++static heap_info *
++new_heap (size_t size, size_t top_pad)
++{
++#if HAVE_TUNABLES
++ if (__glibc_unlikely (mp_.hp_pagesize != 0))
++ {
++ /* MAP_NORESERVE is not used for huge pages because some kernel may
++ not reserve the mmap region and a subsequent access may trigger
++ a SIGBUS if there is no free pages in the pool. */
++ heap_info *h = alloc_new_heap (size, top_pad, mp_.hp_pagesize,
++ mp_.hp_flags);
++ if (h != NULL)
++ return h;
++ }
++#endif
++ return alloc_new_heap (size, top_pad, GLRO (dl_pagesize), MAP_NORESERVE);
++}
++
+ /* Grow a heap. size is automatically rounded up to a
+ multiple of the page size. */
+
+ static int
+ grow_heap (heap_info *h, long diff)
+ {
+- size_t pagesize = GLRO (dl_pagesize);
++ size_t pagesize = h->pagesize;
++ size_t max_size = heap_max_size ();
+ long new_size;
+
+ diff = ALIGN_UP (diff, pagesize);
+ new_size = (long) h->size + diff;
+- if ((unsigned long) new_size > (unsigned long) HEAP_MAX_SIZE)
++ if ((unsigned long) new_size > (unsigned long) max_size)
+ return -1;
+
+ if ((unsigned long) new_size > h->mprotect_size)
+@@ -581,21 +634,14 @@ shrink_heap (heap_info *h, long diff)
+
+ /* Delete a heap. */
+
+-#define delete_heap(heap) \
+- do { \
+- if ((char *) (heap) + HEAP_MAX_SIZE == aligned_heap_area) \
+- aligned_heap_area = NULL; \
+- __munmap ((char *) (heap), HEAP_MAX_SIZE); \
+- } while (0)
+-
+ static int
+ heap_trim (heap_info *heap, size_t pad)
+ {
+ mstate ar_ptr = heap->ar_ptr;
+- unsigned long pagesz = GLRO (dl_pagesize);
+ mchunkptr top_chunk = top (ar_ptr), p;
+ heap_info *prev_heap;
+ long new_size, top_size, top_area, extra, prev_size, misalign;
++ size_t max_size = heap_max_size ();
+
+ /* Can this heap go away completely? */
+ while (top_chunk == chunk_at_offset (heap, sizeof (*heap)))
+@@ -612,19 +658,23 @@ heap_trim (heap_info *heap, size_t pad)
+ assert (new_size > 0 && new_size < (long) (2 * MINSIZE));
+ if (!prev_inuse (p))
+ new_size += prev_size (p);
+- assert (new_size > 0 && new_size < HEAP_MAX_SIZE);
+- if (new_size + (HEAP_MAX_SIZE - prev_heap->size) < pad + MINSIZE + pagesz)
++ assert (new_size > 0 && new_size < max_size);
++ if (new_size + (max_size - prev_heap->size) < pad + MINSIZE
++ + heap->pagesize)
+ break;
+ ar_ptr->system_mem -= heap->size;
+ LIBC_PROBE (memory_heap_free, 2, heap, heap->size);
+- delete_heap (heap);
++ if ((char *) heap + max_size == aligned_heap_area)
++ aligned_heap_area = NULL;
++ __munmap (heap, max_size);
+ heap = prev_heap;
+ if (!prev_inuse (p)) /* consolidate backward */
+ {
+ p = prev_chunk (p);
+ unlink_chunk (ar_ptr, p);
+ }
+- assert (((unsigned long) ((char *) p + new_size) & (pagesz - 1)) == 0);
++ assert (((unsigned long) ((char *) p + new_size) & (heap->pagesize - 1))
++ == 0);
+ assert (((char *) p + new_size) == ((char *) heap + heap->size));
+ top (ar_ptr) = top_chunk = p;
+ set_head (top_chunk, new_size | PREV_INUSE);
+@@ -644,7 +694,7 @@ heap_trim (heap_info *heap, size_t pad)
+ return 0;
+
+ /* Release in pagesize units and round down to the nearest page. */
+- extra = ALIGN_DOWN(top_area - pad, pagesz);
++ extra = ALIGN_DOWN(top_area - pad, heap->pagesize);
+ if (extra == 0)
+ return 0;
+
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 75efdc2ee7..1698d45d1e 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -5302,7 +5302,7 @@ static __always_inline int
+ do_set_mmap_threshold (size_t value)
+ {
+ /* Forbid setting the threshold too high. */
+- if (value <= HEAP_MAX_SIZE / 2)
++ if (value <= heap_max_size () / 2)
+ {
+ LIBC_PROBE (memory_mallopt_mmap_threshold, 3, value, mp_.mmap_threshold,
+ mp_.no_dyn_threshold);
+--
+2.33.0
+
diff --git a/malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch b/malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch
new file mode 100644
index 0000000..afc5650
--- /dev/null
+++ b/malloc-hugepage-0006-malloc-Move-MORECORE-fallback-mmap-to-sysmalloc_mmap.patch
@@ -0,0 +1,119 @@
+From 0849eed45daabf30a02c153695041597d6d43b2d Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 30 Aug 2021 10:56:55 -0300
+Subject: [PATCH 6/7] malloc: Move MORECORE fallback mmap to
+ sysmalloc_mmap_fallback
+
+So it can be used on hugepage code as well.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ malloc/malloc.c | 85 ++++++++++++++++++++++++++++++-------------------
+ 1 file changed, 53 insertions(+), 32 deletions(-)
+
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 1698d45d1e..32050be4cc 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -2498,6 +2498,51 @@ sysmalloc_mmap (INTERNAL_SIZE_T nb, size_t pagesize, int extra_flags, mstate av)
+ return chunk2mem (p);
+ }
+
++/*
++ Allocate memory using mmap() based on S and NB requested size, aligning to
++ PAGESIZE if required. The EXTRA_FLAGS is used on mmap() call. If the call
++ succeedes S is updated with the allocated size. This is used as a fallback
++ if MORECORE fails.
++ */
++static void *
++sysmalloc_mmap_fallback (long int *s, INTERNAL_SIZE_T nb,
++ INTERNAL_SIZE_T old_size, size_t minsize,
++ size_t pagesize, int extra_flags, mstate av)
++{
++ long int size = *s;
++
++ /* Cannot merge with old top, so add its size back in */
++ if (contiguous (av))
++ size = ALIGN_UP (size + old_size, pagesize);
++
++ /* If we are relying on mmap as backup, then use larger units */
++ if ((unsigned long) (size) < minsize)
++ size = minsize;
++
++ /* Don't try if size wraps around 0 */
++ if ((unsigned long) (size) <= (unsigned long) (nb))
++ return MORECORE_FAILURE;
++
++ char *mbrk = (char *) (MMAP (0, size,
++ mtag_mmap_flags | PROT_READ | PROT_WRITE,
++ extra_flags));
++ if (mbrk == MAP_FAILED)
++ return MAP_FAILED;
++
++#ifdef MAP_HUGETLB
++ if (!(extra_flags & MAP_HUGETLB))
++ madvise_thp (mbrk, size);
++#endif
++
++ /* Record that we no longer have a contiguous sbrk region. After the first
++ time mmap is used as backup, we do not ever rely on contiguous space
++ since this could incorrectly bridge regions. */
++ set_noncontiguous (av);
++
++ *s = size;
++ return mbrk;
++}
++
+ static void *
+ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ {
+@@ -2696,38 +2741,14 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ segregated mmap region.
+ */
+
+- /* Cannot merge with old top, so add its size back in */
+- if (contiguous (av))
+- size = ALIGN_UP (size + old_size, pagesize);
+-
+- /* If we are relying on mmap as backup, then use larger units */
+- if ((unsigned long) (size) < (unsigned long) (MMAP_AS_MORECORE_SIZE))
+- size = MMAP_AS_MORECORE_SIZE;
+-
+- /* Don't try if size wraps around 0 */
+- if ((unsigned long) (size) > (unsigned long) (nb))
+- {
+- char *mbrk = (char *) (MMAP (0, size,
+- mtag_mmap_flags | PROT_READ | PROT_WRITE,
+- 0));
+-
+- if (mbrk != MAP_FAILED)
+- {
+- madvise_thp (mbrk, size);
+-
+- /* We do not need, and cannot use, another sbrk call to find end */
+- brk = mbrk;
+- snd_brk = brk + size;
+-
+- /*
+- Record that we no longer have a contiguous sbrk region.
+- After the first time mmap is used as backup, we do not
+- ever rely on contiguous space since this could incorrectly
+- bridge regions.
+- */
+- set_noncontiguous (av);
+- }
+- }
++ char *mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, pagesize,
++ MMAP_AS_MORECORE_SIZE, 0, av);
++ if (mbrk != MAP_FAILED)
++ {
++ /* We do not need, and cannot use, another sbrk call to find end */
++ brk = mbrk;
++ snd_brk = brk + size;
++ }
+ }
+
+ if (brk != (char *) (MORECORE_FAILURE))
+--
+2.33.0
+
diff --git a/malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch b/malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch
new file mode 100644
index 0000000..fa5c9db
--- /dev/null
+++ b/malloc-hugepage-0007-malloc-Enable-huge-page-support-on-main-arena.patch
@@ -0,0 +1,86 @@
+From 0f982c182760bd7689769ee7590df592d0a132c0 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 30 Aug 2021 14:01:00 -0300
+Subject: [PATCH 7/7] malloc: Enable huge page support on main arena
+
+This patch adds support huge page support on main arena allocation,
+enable with tunable glibc.malloc.hugetlb=2. The patch essentially
+disable the __glibc_morecore() sbrk() call (similar when memory
+tag does when sbrk() call does not support it) and fallback to
+default page size if the memory allocation fails.
+
+Checked on x86_64-linux-gnu.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ malloc/arena.c | 4 ++++
+ malloc/malloc.c | 12 ++++++++++--
+ malloc/morecore.c | 4 ----
+ 3 files changed, 14 insertions(+), 6 deletions(-)
+
+diff --git a/malloc/arena.c b/malloc/arena.c
+index e1852f8597..3ed4ef3f05 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -364,6 +364,10 @@ ptmalloc_init (void)
+ # endif
+ TUNABLE_GET (mxfast, size_t, TUNABLE_CALLBACK (set_mxfast));
+ TUNABLE_GET (hugetlb, size_t, TUNABLE_CALLBACK (set_hugetlb));
++ if (mp_.hp_pagesize > 0)
++ /* Force mmap for main arena instead of sbrk, so hugepages are explicitly
++ used. */
++ __always_fail_morecore = true;
+ #else
+ if (__glibc_likely (_environ != NULL))
+ {
+diff --git a/malloc/malloc.c b/malloc/malloc.c
+index 32050be4cc..b67f2c84ee 100644
+--- a/malloc/malloc.c
++++ b/malloc/malloc.c
+@@ -2741,8 +2741,16 @@ sysmalloc (INTERNAL_SIZE_T nb, mstate av)
+ segregated mmap region.
+ */
+
+- char *mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, pagesize,
+- MMAP_AS_MORECORE_SIZE, 0, av);
++ char *mbrk = MAP_FAILED;
++#if HAVE_TUNABLES
++ if (mp_.hp_pagesize > 0)
++ mbrk = sysmalloc_mmap_fallback (&size, nb, old_size,
++ mp_.hp_pagesize, mp_.hp_pagesize,
++ mp_.hp_flags, av);
++#endif
++ if (mbrk == MAP_FAILED)
++ mbrk = sysmalloc_mmap_fallback (&size, nb, old_size, pagesize,
++ MMAP_AS_MORECORE_SIZE, 0, av);
+ if (mbrk != MAP_FAILED)
+ {
+ /* We do not need, and cannot use, another sbrk call to find end */
+diff --git a/malloc/morecore.c b/malloc/morecore.c
+index 8168ef158c..004cd3ead4 100644
+--- a/malloc/morecore.c
++++ b/malloc/morecore.c
+@@ -15,9 +15,7 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+-#if defined(SHARED) || defined(USE_MTAG)
+ static bool __always_fail_morecore = false;
+-#endif
+
+ /* Allocate INCREMENT more bytes of data space,
+ and return the start of data space, or NULL on errors.
+@@ -25,10 +23,8 @@ static bool __always_fail_morecore = false;
+ void *
+ __glibc_morecore (ptrdiff_t increment)
+ {
+-#if defined(SHARED) || defined(USE_MTAG)
+ if (__always_fail_morecore)
+ return NULL;
+-#endif
+
+ void *result = (void *) __sbrk (increment);
+ if (result == (void *) -1)
+--
+2.33.0
+
diff --git a/malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch b/malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch
new file mode 100644
index 0000000..d5aa111
--- /dev/null
+++ b/malloc-use-__get_nprocs-replace-__get_nprocs_sched.patch
@@ -0,0 +1,25 @@
+From f5545d74d6dc4d5036bee6a91cda14a51e2a0676 Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Sat, 12 Mar 2022 15:30:17 +0800
+Subject: [PATCH] malloc: use __get_nprocs replace __get_nprocs_sched.
+
+---
+ malloc/arena.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/malloc/arena.c b/malloc/arena.c
+index f1f0af86..66748463 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -879,7 +879,7 @@ arena_get2 (size_t size, mstate avoid_arena)
+ narenas_limit = mp_.arena_max;
+ else if (narenas > mp_.arena_test)
+ {
+- int n = __get_nprocs_sched ();
++ int n = __get_nprocs ();
+
+ if (n >= 1)
+ narenas_limit = NARENAS_FROM_NCORES (n);
+--
+2.33.0
+
diff --git a/math-Fix-asin-and-acos-invalid-exception-with-old-gc.patch b/math-Fix-asin-and-acos-invalid-exception-with-old-gc.patch
new file mode 100644
index 0000000..bdd129b
--- /dev/null
+++ b/math-Fix-asin-and-acos-invalid-exception-with-old-gc.patch
@@ -0,0 +1,64 @@
+From 672f05a903f2b3ef7144c8c92efdff5e766a0dba Mon Sep 17 00:00:00 2001
+From: XingLi <lixing@loongson.cn>
+Date: Thu, 2 Feb 2023 18:49:01 +0800
+Subject: [PATCH] math: Fix asin and acos invalid exception with old gcc
+
+ This works around a gcc issue where it const folded inf/inf into nan,
+ preventing the invalid exception to be signalled.
+
+ (x-x)/(x-x) is more robust against optimizations and works for all
+ out of bounds values including x==nan.
+
+ The gcc issue https://gcc.gnu.org/bugzilla/show_bug.cgi?id=95115
+ should be fixed on release branches starting from gcc-10, but it is
+ better to change the code in case glibc is built with older gcc.
+
+ Reviewed-by: Wilco Dijkstra <Wilco.Dijkstra@arm.com>
+
+ upstream commit 7363a9a9a097c455a7ddb9386b4c6f7bdf91065f
+ Author: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/ieee754/dbl-64/e_asin.c | 20 +++-----------------
+ 1 file changed, 3 insertions(+), 17 deletions(-)
+
+diff --git a/sysdeps/ieee754/dbl-64/e_asin.c b/sysdeps/ieee754/dbl-64/e_asin.c
+index 4473ae5d..b03a0a94 100644
+--- a/sysdeps/ieee754/dbl-64/e_asin.c
++++ b/sysdeps/ieee754/dbl-64/e_asin.c
+@@ -165,15 +165,8 @@ __ieee754_asin(double x){
+ /*---------------------------- |x|>=1 -------------------------------*/
+ else if (k==0x3ff00000 && u.i[LOW_HALF]==0) return (m>0)?hp0.x:-hp0.x;
+ else
+- if (k>0x7ff00000 || (k == 0x7ff00000 && u.i[LOW_HALF] != 0)) return x + x;
+- else {
+- u.i[HIGH_HALF]=0x7ff00000;
+- v.i[HIGH_HALF]=0x7ff00000;
+- u.i[LOW_HALF]=0;
+- v.i[LOW_HALF]=0;
+- return u.x/v.x; /* NaN */
+- }
+-}
++ return (x - x) / (x - x);
++ }
+ #ifndef __ieee754_asin
+ libm_alias_finite (__ieee754_asin, __asin)
+ #endif
+@@ -334,14 +327,7 @@ __ieee754_acos(double x)
+ else
+ if (k==0x3ff00000 && u.i[LOW_HALF]==0) return (m>0)?0:2.0*hp0.x;
+ else
+- if (k>0x7ff00000 || (k == 0x7ff00000 && u.i[LOW_HALF] != 0)) return x + x;
+- else {
+- u.i[HIGH_HALF]=0x7ff00000;
+- v.i[HIGH_HALF]=0x7ff00000;
+- u.i[LOW_HALF]=0;
+- v.i[LOW_HALF]=0;
+- return u.x/v.x;
+- }
++ return (x - x) / (x - x);
+ }
+ #ifndef __ieee754_acos
+ libm_alias_finite (__ieee754_acos, __acos)
+--
+2.33.0
+
diff --git a/misc-Add-__get_nprocs_sched.patch b/misc-Add-__get_nprocs_sched.patch
new file mode 100644
index 0000000..68e1208
--- /dev/null
+++ b/misc-Add-__get_nprocs_sched.patch
@@ -0,0 +1,110 @@
+From e870aac8974cda746157a5a3c9f452ccd70da29b Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 6 Sep 2021 12:22:54 -0300
+Subject: [PATCH] misc: Add __get_nprocs_sched
+
+This is an internal function meant to return the number of avaliable
+processor where the process can scheduled, different than the
+__get_nprocs which returns a the system available online CPU.
+
+The Linux implementation currently only calls __get_nprocs(), which
+in tuns calls sched_getaffinity.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+(cherry picked from commit 11a02b035b464ab6813676adfd19c4a59c36d907)
+---
+ include/sys/sysinfo.h | 7 ++++++-
+ malloc/arena.c | 2 +-
+ misc/getsysstats.c | 6 ++++++
+ sysdeps/mach/getsysstats.c | 6 ++++++
+ sysdeps/unix/sysv/linux/getsysstats.c | 6 ++++++
+ 5 files changed, 25 insertions(+), 2 deletions(-)
+
+diff --git a/include/sys/sysinfo.h b/include/sys/sysinfo.h
+index 7388356..c490561 100644
+--- a/include/sys/sysinfo.h
++++ b/include/sys/sysinfo.h
+@@ -9,10 +9,15 @@
+ extern int __get_nprocs_conf (void);
+ libc_hidden_proto (__get_nprocs_conf)
+
+-/* Return number of available processors. */
++/* Return number of available processors (not all of them will be
++ available to the caller process). */
+ extern int __get_nprocs (void);
+ libc_hidden_proto (__get_nprocs)
+
++/* Return the number of available processors which the process can
++ be scheduled. */
++extern int __get_nprocs_sched (void) attribute_hidden;
++
+ /* Return number of physical pages of memory in the system. */
+ extern long int __get_phys_pages (void);
+ libc_hidden_proto (__get_phys_pages)
+diff --git a/malloc/arena.c b/malloc/arena.c
+index 6674846..f1f0af8 100644
+--- a/malloc/arena.c
++++ b/malloc/arena.c
+@@ -879,7 +879,7 @@ arena_get2 (size_t size, mstate avoid_arena)
+ narenas_limit = mp_.arena_max;
+ else if (narenas > mp_.arena_test)
+ {
+- int n = __get_nprocs ();
++ int n = __get_nprocs_sched ();
+
+ if (n >= 1)
+ narenas_limit = NARENAS_FROM_NCORES (n);
+diff --git a/misc/getsysstats.c b/misc/getsysstats.c
+index 0eedfac..57d9360 100644
+--- a/misc/getsysstats.c
++++ b/misc/getsysstats.c
+@@ -45,6 +45,12 @@ weak_alias (__get_nprocs, get_nprocs)
+ link_warning (get_nprocs, "warning: get_nprocs will always return 1")
+
+
++int
++__get_nprocs_sched (void)
++{
++ return 1;
++}
++
+ long int
+ __get_phys_pages (void)
+ {
+diff --git a/sysdeps/mach/getsysstats.c b/sysdeps/mach/getsysstats.c
+index 1267f39..cc8023f 100644
+--- a/sysdeps/mach/getsysstats.c
++++ b/sysdeps/mach/getsysstats.c
+@@ -62,6 +62,12 @@ __get_nprocs (void)
+ libc_hidden_def (__get_nprocs)
+ weak_alias (__get_nprocs, get_nprocs)
+
++int
++__get_nprocs_sched (void)
++{
++ return __get_nprocs ();
++}
++
+ /* Return the number of physical pages on the system. */
+ long int
+ __get_phys_pages (void)
+diff --git a/sysdeps/unix/sysv/linux/getsysstats.c b/sysdeps/unix/sysv/linux/getsysstats.c
+index 1391e36..120ce1b 100644
+--- a/sysdeps/unix/sysv/linux/getsysstats.c
++++ b/sysdeps/unix/sysv/linux/getsysstats.c
+@@ -88,6 +88,12 @@ __get_nprocs (void)
+ libc_hidden_def (__get_nprocs)
+ weak_alias (__get_nprocs, get_nprocs)
+
++int
++__get_nprocs_sched (void)
++{
++ return __get_nprocs ();
++}
++
+
+ /* On some architectures it is possible to distinguish between configured
+ and active cpus. */
+--
+1.8.3.1
+
diff --git a/mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch b/mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch
new file mode 100644
index 0000000..10622da
--- /dev/null
+++ b/mtrace-Fix-output-with-PIE-and-ASLR-BZ-22716.patch
@@ -0,0 +1,77 @@
+From f2e33c3268db9adf8e57e991676ed0d5ac74e8a8 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Mon, 23 Aug 2021 08:11:54 +0530
+Subject: [PATCH] mtrace: Fix output with PIE and ASLR [BZ #22716]
+
+Record only the relative address of the caller in mtrace file. Use
+LD_TRACE_PRELINKING to get the executable as well as binary vs
+executable load offsets so that we may compute a base to add to the
+relative address in the mtrace file. This allows us to get a valid
+address to pass to addr2line in all cases.
+
+Fixes BZ #22716.
+
+Co-authored-by: John Ogness <john.ogness@linutronix.de>
+Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ malloc/mtrace-impl.c | 6 +++---
+ malloc/mtrace.pl | 15 +++++++--------
+ 2 files changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c
+index 83008ca..f5f19c2 100644
+--- a/malloc/mtrace-impl.c
++++ b/malloc/mtrace-impl.c
+@@ -65,9 +65,9 @@ tr_where (const void *caller, Dl_info *info)
+ offset);
+ }
+
+- fprintf (mallstream, "@ %s%s%s[%p] ", info->dli_fname ? : "",
+- info->dli_fname ? ":" : "",
+- buf, caller);
++ fprintf (mallstream, "@ %s%s%s[0x%" PRIxPTR "] ",
++ info->dli_fname ? : "", info->dli_fname ? ":" : "", buf,
++ caller - info->dli_fbase);
+ }
+ else
+ fprintf (mallstream, "@ [%p] ", caller);
+diff --git a/malloc/mtrace.pl b/malloc/mtrace.pl
+index 6f49c83..b1073a1 100644
+--- a/malloc/mtrace.pl
++++ b/malloc/mtrace.pl
+@@ -75,11 +75,15 @@ if ($#ARGV == 0) {
+ } else {
+ $prog = "./$binary";
+ }
+- if (open (LOCS, "env LD_TRACE_LOADED_OBJECTS=1 $prog |")) {
++ # Set the environment variable LD_TRACE_PRELINKING to an empty string so
++ # that we trigger tracing but do not match with the executable or any of
++ # its dependencies.
++ if (open (LOCS, "env LD_TRACE_PRELINKING= $prog |")) {
+ while (<LOCS>) {
+ chop;
+- if (/^.*=> (.*) .(0x[0123456789abcdef]*).$/) {
++ if (/^.*=> (.*) \((0x[0123456789abcdef]*), (0x[0123456789abcdef]*).*/) {
+ $locs{$1} = $2;
++ $rel{$1} = hex($2) - hex($3);
+ }
+ }
+ close (LOCS);
+@@ -110,12 +114,7 @@ sub location {
+ my $addr = $2;
+ my $searchaddr;
+ return $cache{$addr} if (exists $cache{$addr});
+- if ($locs{$prog} ne "") {
+- $searchaddr = sprintf "%#x", $addr - $locs{$prog};
+- } else {
+- $searchaddr = $addr;
+- $prog = $binary;
+- }
++ $searchaddr = sprintf "%#x", hex($addr) + $rel{$prog};
+ if ($binary ne "" && open (ADDR, "addr2line -e $prog $searchaddr|")) {
+ my $line = <ADDR>;
+ chomp $line;
+--
+1.8.3.1
+
diff --git a/mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch b/mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch
new file mode 100644
index 0000000..9c25d43
--- /dev/null
+++ b/mtrace-Use-a-static-buffer-for-printing-BZ-25947.patch
@@ -0,0 +1,61 @@
+From dc906e94f7033892dadbd91718349f19e1376391 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Thu, 12 Aug 2021 06:38:15 +0530
+Subject: [PATCH] mtrace: Use a static buffer for printing [BZ #25947]
+
+Use a static buffer for mtrace printing now that it no longer adds to
+default libc footprint.
+
+Reviewed-by: DJ Delorie <dj@redhat.com>
+---
+ malloc/mtrace-impl.c | 14 +++-----------
+ 1 file changed, 3 insertions(+), 11 deletions(-)
+
+diff --git a/malloc/mtrace-impl.c b/malloc/mtrace-impl.c
+index 0e10ab7..83008ca 100644
+--- a/malloc/mtrace-impl.c
++++ b/malloc/mtrace-impl.c
+@@ -34,11 +34,8 @@
+
+ #include <kernel-features.h>
+
+-#define TRACE_BUFFER_SIZE 512
+-
+ static FILE *mallstream;
+ static const char mallenv[] = "MALLOC_TRACE";
+-static char *malloc_trace_buffer;
+
+ static void
+ tr_where (const void *caller, Dl_info *info)
+@@ -184,16 +181,13 @@ do_mtrace (void)
+ mallfile = secure_getenv (mallenv);
+ if (mallfile != NULL)
+ {
+- char *mtb = malloc (TRACE_BUFFER_SIZE);
+- if (mtb == NULL)
+- return;
+-
+ mallstream = fopen (mallfile != NULL ? mallfile : "/dev/null", "wce");
+ if (mallstream != NULL)
+ {
+ /* Be sure it doesn't malloc its buffer! */
+- malloc_trace_buffer = mtb;
+- setvbuf (mallstream, malloc_trace_buffer, _IOFBF, TRACE_BUFFER_SIZE);
++ static char tracebuf [512];
++
++ setvbuf (mallstream, tracebuf, _IOFBF, sizeof (tracebuf));
+ fprintf (mallstream, "= Start\n");
+ if (!added_atexit_handler)
+ {
+@@ -203,8 +197,6 @@ do_mtrace (void)
+ }
+ __malloc_debug_enable (MALLOC_MTRACE_HOOK);
+ }
+- else
+- free (mtb);
+ }
+ }
+
+--
+1.8.3.1
+
diff --git a/nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch b/nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch
new file mode 100644
index 0000000..b72b474
--- /dev/null
+++ b/nis-Fix-leak-on-realloc-failure-in-nis_getnames-BZ-2.patch
@@ -0,0 +1,46 @@
+From 60698263122b7c54ded3f70a466176e17a529480 Mon Sep 17 00:00:00 2001
+From: Robbie Harwood <rharwood@redhat.com>
+Date: Wed, 28 Jul 2021 14:23:32 -0400
+Subject: [PATCH] nis: Fix leak on realloc failure in nis_getnames [BZ #28150]
+
+If pos >= count but realloc fails, tmp will not have been placed in
+getnames[pos] yet, and so will not be freed in free_null. Detected
+by Coverity.
+
+Also remove misleading comment from nis_getnames(), since it actually
+did properly release getnames when out of memory.
+
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ nis/nis_subr.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+diff --git a/nis/nis_subr.c b/nis/nis_subr.c
+index dd0e300..6784fc3 100644
+--- a/nis/nis_subr.c
++++ b/nis/nis_subr.c
+@@ -103,9 +103,6 @@ count_dots (const_nis_name str)
+ return count;
+ }
+
+-/* If we run out of memory, we don't give already allocated memory
+- free. The overhead for bringing getnames back in a safe state to
+- free it is to big. */
+ nis_name *
+ nis_getnames (const_nis_name name)
+ {
+@@ -271,7 +268,10 @@ nis_getnames (const_nis_name name)
+ nis_name *newp = realloc (getnames,
+ (count + 1) * sizeof (char *));
+ if (__glibc_unlikely (newp == NULL))
+- goto free_null;
++ {
++ free (tmp);
++ goto free_null;
++ }
+ getnames = newp;
+ }
+ getnames[pos] = tmp;
+--
+1.8.3.1
+
diff --git a/nptl-Add-one-more-barrier-to-nptl-tst-create1.patch b/nptl-Add-one-more-barrier-to-nptl-tst-create1.patch
new file mode 100644
index 0000000..e18a8bc
--- /dev/null
+++ b/nptl-Add-one-more-barrier-to-nptl-tst-create1.patch
@@ -0,0 +1,67 @@
+From 5cc338565479a620244c2f8ff35956629c4dbf81 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 10 Dec 2021 05:14:24 +0100
+Subject: [PATCH] nptl: Add one more barrier to nptl/tst-create1
+
+Without the bar_ctor_finish barrier, it was possible that thread2
+re-locked user_lock before ctor had a chance to lock it. ctor then
+blocked in its locking operation, xdlopen from the main thread
+did not return, and thread2 was stuck waiting in bar_dtor:
+
+thread 1: started.
+thread 2: started.
+thread 2: locked user_lock.
+constructor started: 0.
+thread 1: in ctor: started.
+thread 3: started.
+thread 3: done.
+thread 2: unlocked user_lock.
+thread 2: locked user_lock.
+
+Fixes the test in commit 83b5323261bb72313bffcf37476c1b8f0847c736
+("elf: Avoid deadlock between pthread_create and ctors [BZ #28357]").
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/pthread/tst-create1.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sysdeps/pthread/tst-create1.c b/sysdeps/pthread/tst-create1.c
+index 932586c..763ded8 100644
+--- a/sysdeps/pthread/tst-create1.c
++++ b/sysdeps/pthread/tst-create1.c
+@@ -33,6 +33,7 @@ thread 2: lock(user_lock) -> pthread_create
+ */
+
+ static pthread_barrier_t bar_ctor;
++static pthread_barrier_t bar_ctor_finish;
+ static pthread_barrier_t bar_dtor;
+ static pthread_mutex_t user_lock = PTHREAD_MUTEX_INITIALIZER;
+
+@@ -46,6 +47,7 @@ ctor (void)
+ xpthread_mutex_unlock (&user_lock);
+ dprintf (1, "thread 1: in ctor: unlocked user_lock.\n");
+ dprintf (1, "thread 1: in ctor: done.\n");
++ xpthread_barrier_wait (&bar_ctor_finish);
+ }
+
+ void
+@@ -81,6 +83,7 @@ thread2 (void *a)
+ xpthread_mutex_unlock (&user_lock);
+ dprintf (1, "thread 2: unlocked user_lock.\n");
+ xpthread_join (t3);
++ xpthread_barrier_wait (&bar_ctor_finish);
+
+ xpthread_mutex_lock (&user_lock);
+ dprintf (1, "thread 2: locked user_lock.\n");
+@@ -99,6 +102,7 @@ thread1 (void)
+ {
+ dprintf (1, "thread 1: started.\n");
+ xpthread_barrier_init (&bar_ctor, NULL, 2);
++ xpthread_barrier_init (&bar_ctor_finish, NULL, 2);
+ xpthread_barrier_init (&bar_dtor, NULL, 2);
+ pthread_t t2 = xpthread_create (0, thread2, 0);
+ void *p = xdlopen ("tst-create1mod.so", RTLD_NOW | RTLD_GLOBAL);
+--
+1.8.3.1
+
diff --git a/nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch b/nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch
new file mode 100644
index 0000000..e582b70
--- /dev/null
+++ b/nptl-Avoid-setxid-deadlock-with-blocked-signals-in-t.patch
@@ -0,0 +1,137 @@
+From 2849e2f53311b66853cb5159b64cba2bddbfb854 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 23 Sep 2021 09:55:54 +0200
+Subject: [PATCH] nptl: Avoid setxid deadlock with blocked signals in thread
+ exit [BZ #28361]
+
+As part of the fix for bug 12889, signals are blocked during
+thread exit, so that application code cannot run on the thread that
+is about to exit. This would cause problems if the application
+expected signals to be delivered after the signal handler revealed
+the thread to still exist, despite pthread_kill can no longer be used
+to send signals to it. However, glibc internally uses the SIGSETXID
+signal in a way that is incompatible with signal blocking, due to the
+way the setxid handshake delays thread exit until the setxid operation
+has completed. With a blocked SIGSETXID, the handshake can never
+complete, causing a deadlock.
+
+As a band-aid, restore the previous handshake protocol by not blocking
+SIGSETXID during thread exit.
+
+The new test sysdeps/pthread/tst-pthread-setuid-loop.c is based on
+a downstream test by Martin Osvald.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ nptl/pthread_create.c | 12 +++++-
+ sysdeps/pthread/Makefile | 1 +
+ sysdeps/pthread/tst-pthread-setuid-loop.c | 61 +++++++++++++++++++++++++++++++
+ 3 files changed, 72 insertions(+), 2 deletions(-)
+ create mode 100644 sysdeps/pthread/tst-pthread-setuid-loop.c
+
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index a559f86..d6ea43a 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -487,8 +487,16 @@ start_thread (void *arg)
+
+ /* This prevents sending a signal from this thread to itself during
+ its final stages. This must come after the exit call above
+- because atexit handlers must not run with signals blocked. */
+- __libc_signal_block_all (NULL);
++ because atexit handlers must not run with signals blocked.
++
++ Do not block SIGSETXID. The setxid handshake below expects the
++ signal to be delivered. (SIGSETXID cannot run application code,
++ nor does it use pthread_kill.) Reuse the pd->sigmask space for
++ computing the signal mask, to save stack space. */
++ __sigfillset (&pd->sigmask);
++ __sigdelset (&pd->sigmask, SIGSETXID);
++ INTERNAL_SYSCALL_CALL (rt_sigprocmask, SIG_BLOCK, &pd->sigmask, NULL,
++ __NSIG_BYTES);
+
+ /* Tell __pthread_kill_internal that this thread is about to exit.
+ If there is a __pthread_kill_internal in progress, this delays
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index 48dba71..d4bd2d4 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -118,6 +118,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-unload \
+ tst-unwind-thread \
+ tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
++ tst-pthread-setuid-loop \
+ tst-pthread_cancel-exited \
+ tst-pthread_cancel-select-loop \
+ tst-pthread_kill-exited \
+diff --git a/sysdeps/pthread/tst-pthread-setuid-loop.c b/sysdeps/pthread/tst-pthread-setuid-loop.c
+new file mode 100644
+index 0000000..fda2a49
+--- /dev/null
++++ b/sysdeps/pthread/tst-pthread-setuid-loop.c
+@@ -0,0 +1,61 @@
++/* Test that setuid, pthread_create, thread exit do not deadlock (bug 28361).
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <support/check.h>
++#include <support/xthread.h>
++#include <unistd.h>
++
++/* How many threads to launch during each iteration. */
++enum { threads = 4 };
++
++/* How many iterations to perform. This value seems to reproduce
++ bug 28361 in a bout one in three runs. */
++enum { iterations = 5000 };
++
++/* Cache of the real user ID used by setuid_thread. */
++static uid_t uid;
++
++/* Start routine for the threads. */
++static void *
++setuid_thread (void *closure)
++{
++ TEST_COMPARE (setuid (uid), 0);
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ /* The setxid machinery is still invoked even if the UID is
++ unchanged. (The kernel might reset other credentials as part of
++ the system call.) */
++ uid = getuid ();
++
++ for (int i = 0; i < iterations; ++i)
++ {
++ pthread_t thread_ids[threads];
++ for (int j = 0; j < threads; ++j)
++ thread_ids[j] = xpthread_create (NULL, setuid_thread, NULL);
++ for (int j = 0; j < threads; ++j)
++ xpthread_join (thread_ids[j]);
++ }
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch b/nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch
new file mode 100644
index 0000000..8f5a571
--- /dev/null
+++ b/nptl-Do-not-set-signal-mask-on-second-setjmp-return-.patch
@@ -0,0 +1,111 @@
+From bfe68fe3c475fe34bed4e017d6e63196c305c934 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Wed, 24 Nov 2021 08:59:54 +0100
+Subject: [PATCH] nptl: Do not set signal mask on second setjmp return [BZ
+ #28607]
+
+__libc_signal_restore_set was in the wrong place: It also ran
+when setjmp returned the second time (after pthread_exit or
+pthread_cancel). This is observable with blocked pending
+signals during thread exit.
+
+Fixes commit b3cae39dcbfa2432b3f3aa28854d8ac57f0de1b8
+("nptl: Start new threads with all signals blocked [BZ #25098]").
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+(cherry picked from commit e186fc5a31e46f2cbf5ea1a75223b4412907f3d8)
+---
+ nptl/pthread_create.c | 4 +--
+ sysdeps/pthread/Makefile | 1 +
+ sysdeps/pthread/tst-pthread-exit-signal.c | 45 +++++++++++++++++++++++++++++++
+ 3 files changed, 48 insertions(+), 2 deletions(-)
+ create mode 100644 sysdeps/pthread/tst-pthread-exit-signal.c
+
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index bc213f0..3db0c9f 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -407,8 +407,6 @@ start_thread (void *arg)
+ unwind_buf.priv.data.prev = NULL;
+ unwind_buf.priv.data.cleanup = NULL;
+
+- __libc_signal_restore_set (&pd->sigmask);
+-
+ /* Allow setxid from now onwards. */
+ if (__glibc_unlikely (atomic_exchange_acq (&pd->setxid_futex, 0) == -2))
+ futex_wake (&pd->setxid_futex, 1, FUTEX_PRIVATE);
+@@ -418,6 +416,8 @@ start_thread (void *arg)
+ /* Store the new cleanup handler info. */
+ THREAD_SETMEM (pd, cleanup_jmp_buf, &unwind_buf);
+
++ __libc_signal_restore_set (&pd->sigmask);
++
+ LIBC_PROBE (pthread_start, 3, (pthread_t) pd, pd->start_routine, pd->arg);
+
+ /* Run the code the user provided. */
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index df8943f..c657101 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -118,6 +118,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-unload \
+ tst-unwind-thread \
+ tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
++ tst-pthread-exit-signal \
+ tst-pthread-setuid-loop \
+ tst-pthread_cancel-exited \
+ tst-pthread_cancel-select-loop \
+diff --git a/sysdeps/pthread/tst-pthread-exit-signal.c b/sysdeps/pthread/tst-pthread-exit-signal.c
+new file mode 100644
+index 0000000..b4526fe
+--- /dev/null
++++ b/sysdeps/pthread/tst-pthread-exit-signal.c
+@@ -0,0 +1,45 @@
++/* Test that pending signals are not delivered on thread exit (bug 28607).
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Due to bug 28607, pthread_kill (or pthread_cancel) restored the
++ signal mask during during thread exit, triggering the delivery of a
++ blocked pending signal (SIGUSR1 in this test). */
++
++#include <support/xthread.h>
++#include <support/xsignal.h>
++
++static void *
++threadfunc (void *closure)
++{
++ sigset_t sigmask;
++ sigfillset (&sigmask);
++ xpthread_sigmask (SIG_SETMASK, &sigmask, NULL);
++ xpthread_kill (pthread_self (), SIGUSR1);
++ pthread_exit (NULL);
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ pthread_t thr = xpthread_create (NULL, threadfunc, NULL);
++ xpthread_join (thr);
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/nptl-Fix-___pthread_unregister_cancel_restore-asynch.patch b/nptl-Fix-___pthread_unregister_cancel_restore-asynch.patch
new file mode 100644
index 0000000..d1b891c
--- /dev/null
+++ b/nptl-Fix-___pthread_unregister_cancel_restore-asynch.patch
@@ -0,0 +1,29 @@
+From f27e5e21787abc9f719879af47687221aa1027b3 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 13 Jul 2022 10:37:32 -0300
+Subject: [PATCH] nptl: Fix ___pthread_unregister_cancel_restore asynchronous
+ restore
+
+This was due a wrong revert done on 404656009b459658.
+
+Checked on x86_64-linux-gnu and i686-linux-gnu.
+---
+ nptl/cleanup_defer.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c
+index eb0bc77..4e864ea 100644
+--- a/nptl/cleanup_defer.c
++++ b/nptl/cleanup_defer.c
+@@ -71,7 +71,7 @@ ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf)
+ return;
+
+ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
+- if (cancelhandling & CANCELTYPE_BITMASK)
++ if ((cancelhandling & CANCELTYPE_BITMASK) == 0)
+ {
+ int newval;
+ do
+--
+1.8.3.1
+
diff --git a/nptl-Fix-pthread_cancel-cancelhandling-atomic-operat.patch b/nptl-Fix-pthread_cancel-cancelhandling-atomic-operat.patch
new file mode 100644
index 0000000..e8c94b9
--- /dev/null
+++ b/nptl-Fix-pthread_cancel-cancelhandling-atomic-operat.patch
@@ -0,0 +1,38 @@
+From 62be9681677e7ce820db721c126909979382d379 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 20 Apr 2022 12:01:43 -0300
+Subject: [PATCH] nptl: Fix pthread_cancel cancelhandling atomic operations
+
+The 404656009b reversion did not setup the atomic loop to set the
+cancel bits correctly. The fix is essentially what pthread_cancel
+did prior 26cfbb7162ad.
+
+Checked on x86_64-linux-gnu and aarch64-linux-gnu.
+---
+ nptl/pthread_cancel.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
+index c76882e..e67b2df 100644
+--- a/nptl/pthread_cancel.c
++++ b/nptl/pthread_cancel.c
+@@ -121,6 +121,7 @@ __pthread_cancel (pthread_t th)
+ int newval;
+ do
+ {
++ again:
+ newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
+ if (oldval == newval)
+ break;
+@@ -134,7 +135,7 @@ __pthread_cancel (pthread_t th)
+ int newval2 = oldval | CANCELING_BITMASK;
+ if (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling,
+ &oldval, newval2))
+- continue;
++ goto again;
+
+ if (pd == THREAD_SELF)
+ /* This is not merely an optimization: An application may
+--
+1.8.3.1
+
diff --git a/nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch b/nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch
new file mode 100644
index 0000000..3acbe23
--- /dev/null
+++ b/nptl-Fix-race-between-pthread_kill-and-thread-exit-b.patch
@@ -0,0 +1,424 @@
+From 526c3cf11ee9367344b6b15d669e4c3cb461a2be Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 13 Sep 2021 11:06:08 +0200
+Subject: [PATCH] nptl: Fix race between pthread_kill and thread exit (bug
+ 12889)
+
+A new thread exit lock and flag are introduced. They are used to
+detect that the thread is about to exit or has exited in
+__pthread_kill_internal, and the signal is not sent in this case.
+
+The test sysdeps/pthread/tst-pthread_cancel-select-loop.c is derived
+from a downstream test originally written by Marek Polacek.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ nptl/allocatestack.c | 3 +
+ nptl/descr.h | 6 ++
+ nptl/pthread_create.c | 14 +++
+ nptl/pthread_kill.c | 65 +++++++-----
+ sysdeps/pthread/Makefile | 2 +
+ sysdeps/pthread/tst-pthread_cancel-select-loop.c | 87 ++++++++++++++++
+ sysdeps/pthread/tst-pthread_kill-exiting.c | 123 +++++++++++++++++++++++
+ 7 files changed, 275 insertions(+), 25 deletions(-)
+ create mode 100644 sysdeps/pthread/tst-pthread_cancel-select-loop.c
+ create mode 100644 sysdeps/pthread/tst-pthread_kill-exiting.c
+
+diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
+index 0356993..fa81007 100644
+--- a/nptl/allocatestack.c
++++ b/nptl/allocatestack.c
+@@ -31,6 +31,7 @@
+ #include <futex-internal.h>
+ #include <kernel-features.h>
+ #include <nptl-stack.h>
++#include <libc-lock.h>
+
+ /* Default alignment of stack. */
+ #ifndef STACK_ALIGN
+@@ -126,6 +127,8 @@ get_cached_stack (size_t *sizep, void **memp)
+ /* No pending event. */
+ result->nextevent = NULL;
+
++ result->exiting = false;
++ __libc_lock_init (result->exit_lock);
+ result->tls_state = (struct tls_internal_t) { 0 };
+
+ /* Clear the DTV. */
+diff --git a/nptl/descr.h b/nptl/descr.h
+index e1c8831..41ee56f 100644
+--- a/nptl/descr.h
++++ b/nptl/descr.h
+@@ -395,6 +395,12 @@ struct pthread
+ PTHREAD_CANCEL_ASYNCHRONOUS). */
+ unsigned char canceltype;
+
++ /* Used in __pthread_kill_internal to detected a thread that has
++ exited or is about to exit. exit_lock must only be acquired
++ after blocking signals. */
++ bool exiting;
++ int exit_lock; /* A low-level lock (for use with __libc_lock_init etc). */
++
+ /* Used on strsignal. */
+ struct tls_internal_t tls_state;
+
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index 7607f36..a559f86 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -36,6 +36,7 @@
+ #include <sys/single_threaded.h>
+ #include <version.h>
+ #include <clone_internal.h>
++#include <futex-internal.h>
+
+ #include <shlib-compat.h>
+
+@@ -484,6 +485,19 @@ start_thread (void *arg)
+ /* This was the last thread. */
+ exit (0);
+
++ /* This prevents sending a signal from this thread to itself during
++ its final stages. This must come after the exit call above
++ because atexit handlers must not run with signals blocked. */
++ __libc_signal_block_all (NULL);
++
++ /* Tell __pthread_kill_internal that this thread is about to exit.
++ If there is a __pthread_kill_internal in progress, this delays
++ the thread exit until the signal has been queued by the kernel
++ (so that the TID used to send it remains valid). */
++ __libc_lock_lock (pd->exit_lock);
++ pd->exiting = true;
++ __libc_lock_unlock (pd->exit_lock);
++
+ #ifndef __ASSUME_SET_ROBUST_LIST
+ /* If this thread has any robust mutexes locked, handle them now. */
+ # if __PTHREAD_MUTEX_HAVE_PREV
+diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c
+index 5d4c86f..fb7862e 100644
+--- a/nptl/pthread_kill.c
++++ b/nptl/pthread_kill.c
+@@ -16,6 +16,7 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
++#include <libc-lock.h>
+ #include <unistd.h>
+ #include <pthreadP.h>
+ #include <shlib-compat.h>
+@@ -23,37 +24,51 @@
+ int
+ __pthread_kill_internal (pthread_t threadid, int signo)
+ {
+- pid_t tid;
+ struct pthread *pd = (struct pthread *) threadid;
+-
+ if (pd == THREAD_SELF)
+- /* It is a special case to handle raise() implementation after a vfork
+- call (which does not update the PD tid field). */
+- tid = INLINE_SYSCALL_CALL (gettid);
+- else
+- /* Force load of pd->tid into local variable or register. Otherwise
+- if a thread exits between ESRCH test and tgkill, we might return
+- EINVAL, because pd->tid would be cleared by the kernel. */
+- tid = atomic_forced_read (pd->tid);
+-
+- int val;
+- if (__glibc_likely (tid > 0))
+ {
+- pid_t pid = __getpid ();
+-
+- val = INTERNAL_SYSCALL_CALL (tgkill, pid, tid, signo);
+- val = (INTERNAL_SYSCALL_ERROR_P (val)
+- ? INTERNAL_SYSCALL_ERRNO (val) : 0);
++ /* Use the actual TID from the kernel, so that it refers to the
++ current thread even if called after vfork. There is no
++ signal blocking in this case, so that the signal is delivered
++ immediately, before __pthread_kill_internal returns: a signal
++ sent to the thread itself needs to be delivered
++ synchronously. (It is unclear if Linux guarantees the
++ delivery of all pending signals after unblocking in the code
++ below. POSIX only guarantees delivery of a single signal,
++ which may not be the right one.) */
++ pid_t tid = INTERNAL_SYSCALL_CALL (gettid);
++ int ret = INTERNAL_SYSCALL_CALL (kill, tid, signo);
++ return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
+ }
++
++ /* Block all signals, as required by pd->exit_lock. */
++ sigset_t old_mask;
++ __libc_signal_block_all (&old_mask);
++ __libc_lock_lock (pd->exit_lock);
++
++ int ret;
++ if (pd->exiting)
++ /* The thread is about to exit (or has exited). Sending the
++ signal is either not observable (the target thread has already
++ blocked signals at this point), or it will fail, or it might be
++ delivered to a new, unrelated thread that has reused the TID.
++ So do not actually send the signal. Do not report an error
++ because the threadid argument is still valid (the thread ID
++ lifetime has not ended), and ESRCH (for example) would be
++ misleading. */
++ ret = 0;
+ else
+- /* The kernel reports that the thread has exited. POSIX specifies
+- the ESRCH error only for the case when the lifetime of a thread
+- ID has ended, but calling pthread_kill on such a thread ID is
+- undefined in glibc. Therefore, do not treat kernel thread exit
+- as an error. */
+- val = 0;
++ {
++ /* Using tgkill is a safety measure. pd->exit_lock ensures that
++ the target thread cannot exit. */
++ ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), pd->tid, signo);
++ ret = INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
++ }
++
++ __libc_lock_unlock (pd->exit_lock);
++ __libc_signal_restore_set (&old_mask);
+
+- return val;
++ return ret;
+ }
+
+ int
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index dedfa0d..48dba71 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -119,7 +119,9 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-unwind-thread \
+ tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
+ tst-pthread_cancel-exited \
++ tst-pthread_cancel-select-loop \
+ tst-pthread_kill-exited \
++ tst-pthread_kill-exiting \
+ # tests
+
+ tests-time64 := \
+diff --git a/sysdeps/pthread/tst-pthread_cancel-select-loop.c b/sysdeps/pthread/tst-pthread_cancel-select-loop.c
+new file mode 100644
+index 0000000..a620875
+--- /dev/null
++++ b/sysdeps/pthread/tst-pthread_cancel-select-loop.c
+@@ -0,0 +1,87 @@
++/* Test that pthread_cancel succeeds during thread exit.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* This test tries to trigger an internal race condition in
++ pthread_cancel, where the cancellation signal is sent after the
++ thread has begun the cancellation process. This can result in a
++ spurious ESRCH error. For the original bug 12889, the window is
++ quite small, so the bug was not reproduced in every run. */
++
++#include <stdbool.h>
++#include <stddef.h>
++#include <support/check.h>
++#include <support/xthread.h>
++#include <support/xunistd.h>
++#include <sys/select.h>
++#include <unistd.h>
++
++/* Set to true by timeout_thread_function when the test should
++ terminate. */
++static bool timeout;
++
++static void *
++timeout_thread_function (void *unused)
++{
++ usleep (5 * 1000 * 1000);
++ __atomic_store_n (&timeout, true, __ATOMIC_RELAXED);
++ return NULL;
++}
++
++/* Used for blocking the select function below. */
++static int pipe_fds[2];
++
++static void *
++canceled_thread_function (void *unused)
++{
++ while (true)
++ {
++ fd_set rfs;
++ fd_set wfs;
++ fd_set efs;
++ FD_ZERO (&rfs);
++ FD_ZERO (&wfs);
++ FD_ZERO (&efs);
++ FD_SET (pipe_fds[0], &rfs);
++
++ /* If the cancellation request is recognized early, the thread
++ begins exiting while the cancellation signal arrives. */
++ select (FD_SETSIZE, &rfs, &wfs, &efs, NULL);
++ }
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ xpipe (pipe_fds);
++ pthread_t thr_timeout = xpthread_create (NULL, timeout_thread_function, NULL);
++
++ while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED))
++ {
++ pthread_t thr = xpthread_create (NULL, canceled_thread_function, NULL);
++ xpthread_cancel (thr);
++ TEST_VERIFY (xpthread_join (thr) == PTHREAD_CANCELED);
++ }
++
++ xpthread_join (thr_timeout);
++ xclose (pipe_fds[0]);
++ xclose (pipe_fds[1]);
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/pthread/tst-pthread_kill-exiting.c b/sysdeps/pthread/tst-pthread_kill-exiting.c
+new file mode 100644
+index 0000000..f803e94
+--- /dev/null
++++ b/sysdeps/pthread/tst-pthread_kill-exiting.c
+@@ -0,0 +1,123 @@
++/* Test that pthread_kill succeeds during thread exit.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* This test verifies that pthread_kill for a thread that is exiting
++ succeeds (with or without actually delivering the signal). */
++
++#include <array_length.h>
++#include <stdbool.h>
++#include <stddef.h>
++#include <support/xsignal.h>
++#include <support/xthread.h>
++#include <unistd.h>
++
++/* Set to true by timeout_thread_function when the test should
++ terminate. */
++static bool timeout;
++
++static void *
++timeout_thread_function (void *unused)
++{
++ usleep (1000 * 1000);
++ __atomic_store_n (&timeout, true, __ATOMIC_RELAXED);
++ return NULL;
++}
++
++/* Used to synchronize the sending threads with the target thread and
++ main thread. */
++static pthread_barrier_t barrier_1;
++static pthread_barrier_t barrier_2;
++
++/* The target thread to which signals are to be sent. */
++static pthread_t target_thread;
++
++/* Set by the main thread to true after timeout has been set to
++ true. */
++static bool exiting;
++
++static void *
++sender_thread_function (void *unused)
++{
++ while (true)
++ {
++ /* Wait until target_thread has been initialized. The target
++ thread and main thread participate in this barrier. */
++ xpthread_barrier_wait (&barrier_1);
++
++ if (exiting)
++ break;
++
++ xpthread_kill (target_thread, SIGUSR1);
++
++ /* Communicate that the signal has been sent. The main thread
++ participates in this barrier. */
++ xpthread_barrier_wait (&barrier_2);
++ }
++ return NULL;
++}
++
++static void *
++target_thread_function (void *unused)
++{
++ target_thread = pthread_self ();
++ xpthread_barrier_wait (&barrier_1);
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ xsignal (SIGUSR1, SIG_IGN);
++
++ pthread_t thr_timeout = xpthread_create (NULL, timeout_thread_function, NULL);
++
++ pthread_t threads[4];
++ xpthread_barrier_init (&barrier_1, NULL, array_length (threads) + 2);
++ xpthread_barrier_init (&barrier_2, NULL, array_length (threads) + 1);
++
++ for (int i = 0; i < array_length (threads); ++i)
++ threads[i] = xpthread_create (NULL, sender_thread_function, NULL);
++
++ while (!__atomic_load_n (&timeout, __ATOMIC_RELAXED))
++ {
++ xpthread_create (NULL, target_thread_function, NULL);
++
++ /* Wait for the target thread to be set up and signal sending to
++ start. */
++ xpthread_barrier_wait (&barrier_1);
++
++ /* Wait for signal sending to complete. */
++ xpthread_barrier_wait (&barrier_2);
++
++ xpthread_join (target_thread);
++ }
++
++ exiting = true;
++
++ /* Signal the sending threads to exit. */
++ xpthread_create (NULL, target_thread_function, NULL);
++ xpthread_barrier_wait (&barrier_1);
++
++ for (int i = 0; i < array_length (threads); ++i)
++ xpthread_join (threads[i]);
++ xpthread_join (thr_timeout);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch b/nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch
new file mode 100644
index 0000000..b92e3c5
--- /dev/null
+++ b/nptl-Fix-type-of-pthread_mutexattr_getrobust_np-pthr.patch
@@ -0,0 +1,37 @@
+From f3e664563361dc17530113b3205998d1f19dc4d9 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Tue, 21 Sep 2021 07:12:56 +0200
+Subject: [PATCH] nptl: Fix type of pthread_mutexattr_getrobust_np,
+ pthread_mutexattr_setrobust_np (bug 28036)
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ sysdeps/nptl/pthread.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
+index f1b7f2b..43146e9 100644
+--- a/sysdeps/nptl/pthread.h
++++ b/sysdeps/nptl/pthread.h
+@@ -933,7 +933,7 @@ extern int pthread_mutexattr_getrobust (const pthread_mutexattr_t *__attr,
+ # ifdef __USE_GNU
+ # ifdef __REDIRECT_NTH
+ extern int __REDIRECT_NTH (pthread_mutexattr_getrobust_np,
+- (pthread_mutex_t *, int *),
++ (pthread_mutexattr_t *, int *),
+ pthread_mutexattr_getrobust) __nonnull ((1))
+ __attribute_deprecated_msg__ ("\
+ pthread_mutexattr_getrobust_np is deprecated, use pthread_mutexattr_getrobust");
+@@ -949,7 +949,7 @@ extern int pthread_mutexattr_setrobust (pthread_mutexattr_t *__attr,
+ # ifdef __USE_GNU
+ # ifdef __REDIRECT_NTH
+ extern int __REDIRECT_NTH (pthread_mutexattr_setrobust_np,
+- (pthread_mutex_t *, int),
++ (pthread_mutexattr_t *, int),
+ pthread_mutexattr_setrobust) __nonnull ((1))
+ __attribute_deprecated_msg__ ("\
+ pthread_mutexattr_setrobust_np is deprecated, use pthread_mutexattr_setrobust");
+--
+1.8.3.1
+
diff --git a/nptl-Handle-spurious-EINTR-when-thread-cancellation-.patch b/nptl-Handle-spurious-EINTR-when-thread-cancellation-.patch
new file mode 100644
index 0000000..1126181
--- /dev/null
+++ b/nptl-Handle-spurious-EINTR-when-thread-cancellation-.patch
@@ -0,0 +1,869 @@
+From 290db09546b260a30137d03ce97a857e6f15b648 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 6 Apr 2022 12:24:42 -0300
+Subject: [PATCH] nptl: Handle spurious EINTR when thread cancellation is
+ disabled (BZ#29029)
+
+Some Linux interfaces never restart after being interrupted by a signal
+handler, regardless of the use of SA_RESTART [1]. It means that for
+pthread cancellation, if the target thread disables cancellation with
+pthread_setcancelstate and calls such interfaces (like poll or select),
+it should not see spurious EINTR failures due the internal SIGCANCEL.
+
+However recent changes made pthread_cancel to always sent the internal
+signal, regardless of the target thread cancellation status or type.
+To fix it, the previous semantic is restored, where the cancel signal
+is only sent if the target thread has cancelation enabled in
+asynchronous mode.
+
+The cancel state and cancel type is moved back to cancelhandling
+and atomic operation are used to synchronize between threads. The
+patch essentially revert the following commits:
+
+ 8c1c0aae20 nptl: Move cancel type out of cancelhandling
+ 2b51742531 nptl: Move cancel state out of cancelhandling
+ 26cfbb7162 nptl: Remove CANCELING_BITMASK
+
+However I changed the atomic operation to follow the internal C11
+semantic and removed the MACRO usage, it simplifies a bit the
+resulting code (and removes another usage of the old atomic macros).
+
+Checked on x86_64-linux-gnu, i686-linux-gnu, aarch64-linux-gnu,
+and powerpc64-linux-gnu.
+
+[1] https://man7.org/linux/man-pages/man7/signal.7.html
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+Tested-by: Aurelien Jarno <aurelien@aurel32.net>
+
+(cherry-picked from commit 404656009b459658138ed1bd18f3c6cf3863e6a6)
+---
+ NEWS | 2 +
+ manual/process.texi | 3 +-
+ nptl/allocatestack.c | 2 -
+ nptl/cancellation.c | 50 +++++++---
+ nptl/cleanup_defer.c | 42 +++++++--
+ nptl/descr.h | 41 +++++---
+ nptl/libc-cleanup.c | 39 +++++++-
+ nptl/pthread_cancel.c | 110 ++++++++++++++++------
+ nptl/pthread_join_common.c | 7 +-
+ nptl/pthread_setcancelstate.c | 26 +++++-
+ nptl/pthread_setcanceltype.c | 31 +++++-
+ nptl/pthread_testcancel.c | 9 +-
+ sysdeps/nptl/dl-tls_init_tp.c | 3 -
+ sysdeps/nptl/pthreadP.h | 2 +-
+ sysdeps/pthread/Makefile | 1 +
+ sysdeps/pthread/tst-cancel29.c | 207 +++++++++++++++++++++++++++++++++++++++++
+ 16 files changed, 484 insertions(+), 91 deletions(-)
+ create mode 100644 sysdeps/pthread/tst-cancel29.c
+
+diff --git a/NEWS b/NEWS
+index 96e0589..55aea24 100644
+--- a/NEWS
++++ b/NEWS
+@@ -37,6 +37,8 @@ The following bugs are resolved with this release:
+ recvmsg()
+ [28865] linux: _SC_NPROCESSORS_CONF and _SC_NPROCESSORS_ONLN are inaccurate
+ without /sys and /proc
++ [29029] nptl: poll() spuriously returns EINTR during thread
++ cancellation and with cancellation disabled
+
+
+ Version 2.34
+diff --git a/manual/process.texi b/manual/process.texi
+index 28c9531..9307379 100644
+--- a/manual/process.texi
++++ b/manual/process.texi
+@@ -68,8 +68,7 @@ until the subprogram terminates before you can do anything else.
+ @c CLEANUP_HANDLER @ascuplugin @ascuheap @acsmem
+ @c libc_cleanup_region_start @ascuplugin @ascuheap @acsmem
+ @c pthread_cleanup_push_defer @ascuplugin @ascuheap @acsmem
+-@c __pthread_testcancel @ascuplugin @ascuheap @acsmem
+-@c CANCEL_ENABLED_AND_CANCELED ok
++@c cancel_enabled_and_canceled @ascuplugin @ascuheap @acsmem
+ @c do_cancel @ascuplugin @ascuheap @acsmem
+ @c cancel_handler ok
+ @c kill syscall ok
+diff --git a/nptl/allocatestack.c b/nptl/allocatestack.c
+index 554a721..9610175 100644
+--- a/nptl/allocatestack.c
++++ b/nptl/allocatestack.c
+@@ -120,8 +120,6 @@ get_cached_stack (size_t *sizep, void **memp)
+
+ /* Cancellation handling is back to the default. */
+ result->cancelhandling = 0;
+- result->cancelstate = PTHREAD_CANCEL_ENABLE;
+- result->canceltype = PTHREAD_CANCEL_DEFERRED;
+ result->cleanup = NULL;
+ result->setup_failed = 0;
+
+diff --git a/nptl/cancellation.c b/nptl/cancellation.c
+index 0596278..e97d56f 100644
+--- a/nptl/cancellation.c
++++ b/nptl/cancellation.c
+@@ -31,19 +31,26 @@ int
+ __pthread_enable_asynccancel (void)
+ {
+ struct pthread *self = THREAD_SELF;
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
+
+- int oldval = THREAD_GETMEM (self, canceltype);
+- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_ASYNCHRONOUS);
++ while (1)
++ {
++ int newval = oldval | CANCELTYPE_BITMASK;
+
+- int ch = THREAD_GETMEM (self, cancelhandling);
++ if (newval == oldval)
++ break;
+
+- if (self->cancelstate == PTHREAD_CANCEL_ENABLE
+- && (ch & CANCELED_BITMASK)
+- && !(ch & EXITING_BITMASK)
+- && !(ch & TERMINATED_BITMASK))
+- {
+- THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+- __do_cancel ();
++ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval))
++ {
++ if (cancel_enabled_and_canceled_and_async (newval))
++ {
++ self->result = PTHREAD_CANCELED;
++ __do_cancel ();
++ }
++
++ break;
++ }
+ }
+
+ return oldval;
+@@ -57,10 +64,29 @@ __pthread_disable_asynccancel (int oldtype)
+ {
+ /* If asynchronous cancellation was enabled before we do not have
+ anything to do. */
+- if (oldtype == PTHREAD_CANCEL_ASYNCHRONOUS)
++ if (oldtype & CANCELTYPE_BITMASK)
+ return;
+
+ struct pthread *self = THREAD_SELF;
+- self->canceltype = PTHREAD_CANCEL_DEFERRED;
++ int newval;
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
++ do
++ {
++ newval = oldval & ~CANCELTYPE_BITMASK;
++ }
++ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval));
++
++ /* We cannot return when we are being canceled. Upon return the
++ thread might be things which would have to be undone. The
++ following loop should loop until the cancellation signal is
++ delivered. */
++ while (__glibc_unlikely ((newval & (CANCELING_BITMASK | CANCELED_BITMASK))
++ == CANCELING_BITMASK))
++ {
++ futex_wait_simple ((unsigned int *) &self->cancelhandling, newval,
++ FUTEX_PRIVATE);
++ newval = atomic_load_relaxed (&self->cancelhandling);
++ }
+ }
+ libc_hidden_def (__pthread_disable_asynccancel)
+diff --git a/nptl/cleanup_defer.c b/nptl/cleanup_defer.c
+index 7e858d0..35ba40f 100644
+--- a/nptl/cleanup_defer.c
++++ b/nptl/cleanup_defer.c
+@@ -31,9 +31,22 @@ ___pthread_register_cancel_defer (__pthread_unwind_buf_t *buf)
+ ibuf->priv.data.prev = THREAD_GETMEM (self, cleanup_jmp_buf);
+ ibuf->priv.data.cleanup = THREAD_GETMEM (self, cleanup);
+
+- /* Disable asynchronous cancellation for now. */
+- ibuf->priv.data.canceltype = THREAD_GETMEM (self, canceltype);
+- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED);
++ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
++ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
++ {
++ int newval;
++ do
++ {
++ newval = cancelhandling & ~CANCELTYPE_BITMASK;
++ }
++ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &cancelhandling,
++ newval));
++ }
++
++ ibuf->priv.data.canceltype = (cancelhandling & CANCELTYPE_BITMASK
++ ? PTHREAD_CANCEL_ASYNCHRONOUS
++ : PTHREAD_CANCEL_DEFERRED);
+
+ /* Store the new cleanup handler info. */
+ THREAD_SETMEM (self, cleanup_jmp_buf, (struct pthread_unwind_buf *) buf);
+@@ -55,9 +68,26 @@ ___pthread_unregister_cancel_restore (__pthread_unwind_buf_t *buf)
+
+ THREAD_SETMEM (self, cleanup_jmp_buf, ibuf->priv.data.prev);
+
+- THREAD_SETMEM (self, canceltype, ibuf->priv.data.canceltype);
+- if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
+- __pthread_testcancel ();
++ if (ibuf->priv.data.canceltype == PTHREAD_CANCEL_DEFERRED)
++ return;
++
++ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
++ if (cancelhandling & CANCELTYPE_BITMASK)
++ {
++ int newval;
++ do
++ {
++ newval = cancelhandling | CANCELTYPE_BITMASK;
++ }
++ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &cancelhandling, newval));
++
++ if (cancel_enabled_and_canceled (cancelhandling))
++ {
++ self->result = PTHREAD_CANCELED;
++ __do_cancel ();
++ }
++ }
+ }
+ versioned_symbol (libc, ___pthread_unregister_cancel_restore,
+ __pthread_unregister_cancel_restore, GLIBC_2_34);
+diff --git a/nptl/descr.h b/nptl/descr.h
+index 4de8413..03a4358 100644
+--- a/nptl/descr.h
++++ b/nptl/descr.h
+@@ -277,18 +277,27 @@ struct pthread
+
+ /* Flags determining processing of cancellation. */
+ int cancelhandling;
++ /* Bit set if cancellation is disabled. */
++#define CANCELSTATE_BIT 0
++#define CANCELSTATE_BITMASK (1 << CANCELSTATE_BIT)
++ /* Bit set if asynchronous cancellation mode is selected. */
++#define CANCELTYPE_BIT 1
++#define CANCELTYPE_BITMASK (1 << CANCELTYPE_BIT)
++ /* Bit set if canceling has been initiated. */
++#define CANCELING_BIT 2
++#define CANCELING_BITMASK (1 << CANCELING_BIT)
+ /* Bit set if canceled. */
+ #define CANCELED_BIT 3
+-#define CANCELED_BITMASK (0x01 << CANCELED_BIT)
++#define CANCELED_BITMASK (1 << CANCELED_BIT)
+ /* Bit set if thread is exiting. */
+ #define EXITING_BIT 4
+-#define EXITING_BITMASK (0x01 << EXITING_BIT)
++#define EXITING_BITMASK (1 << EXITING_BIT)
+ /* Bit set if thread terminated and TCB is freed. */
+ #define TERMINATED_BIT 5
+-#define TERMINATED_BITMASK (0x01 << TERMINATED_BIT)
++#define TERMINATED_BITMASK (1 << TERMINATED_BIT)
+ /* Bit set if thread is supposed to change XID. */
+ #define SETXID_BIT 6
+-#define SETXID_BITMASK (0x01 << SETXID_BIT)
++#define SETXID_BITMASK (1 << SETXID_BIT)
+
+ /* Flags. Including those copied from the thread attribute. */
+ int flags;
+@@ -388,14 +397,6 @@ struct pthread
+ /* Indicates whether is a C11 thread created by thrd_creat. */
+ bool c11;
+
+- /* Thread cancel state (PTHREAD_CANCEL_ENABLE or
+- PTHREAD_CANCEL_DISABLE). */
+- unsigned char cancelstate;
+-
+- /* Thread cancel type (PTHREAD_CANCEL_DEFERRED or
+- PTHREAD_CANCEL_ASYNCHRONOUS). */
+- unsigned char canceltype;
+-
+ /* Used in __pthread_kill_internal to detected a thread that has
+ exited or is about to exit. exit_lock must only be acquired
+ after blocking signals. */
+@@ -412,6 +413,22 @@ struct pthread
+ (sizeof (struct pthread) - offsetof (struct pthread, end_padding))
+ } __attribute ((aligned (TCB_ALIGNMENT)));
+
++static inline bool
++cancel_enabled_and_canceled (int value)
++{
++ return (value & (CANCELSTATE_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
++ | TERMINATED_BITMASK))
++ == CANCELED_BITMASK;
++}
++
++static inline bool
++cancel_enabled_and_canceled_and_async (int value)
++{
++ return ((value) & (CANCELSTATE_BITMASK | CANCELTYPE_BITMASK | CANCELED_BITMASK
++ | EXITING_BITMASK | TERMINATED_BITMASK))
++ == (CANCELTYPE_BITMASK | CANCELED_BITMASK);
++}
++
+ /* This yields the pointer that TLS support code calls the thread pointer. */
+ #if TLS_TCB_AT_TP
+ # define TLS_TPADJ(pd) (pd)
+diff --git a/nptl/libc-cleanup.c b/nptl/libc-cleanup.c
+index 180d15b..fccb1ab 100644
+--- a/nptl/libc-cleanup.c
++++ b/nptl/libc-cleanup.c
+@@ -27,9 +27,24 @@ __libc_cleanup_push_defer (struct _pthread_cleanup_buffer *buffer)
+
+ buffer->__prev = THREAD_GETMEM (self, cleanup);
+
++ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
++
+ /* Disable asynchronous cancellation for now. */
+- buffer->__canceltype = THREAD_GETMEM (self, canceltype);
+- THREAD_SETMEM (self, canceltype, PTHREAD_CANCEL_DEFERRED);
++ if (__glibc_unlikely (cancelhandling & CANCELTYPE_BITMASK))
++ {
++ int newval;
++ do
++ {
++ newval = cancelhandling & ~CANCELTYPE_BITMASK;
++ }
++ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &cancelhandling,
++ newval));
++ }
++
++ buffer->__canceltype = (cancelhandling & CANCELTYPE_BITMASK
++ ? PTHREAD_CANCEL_ASYNCHRONOUS
++ : PTHREAD_CANCEL_DEFERRED);
+
+ THREAD_SETMEM (self, cleanup, buffer);
+ }
+@@ -42,8 +57,22 @@ __libc_cleanup_pop_restore (struct _pthread_cleanup_buffer *buffer)
+
+ THREAD_SETMEM (self, cleanup, buffer->__prev);
+
+- THREAD_SETMEM (self, canceltype, buffer->__canceltype);
+- if (buffer->__canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
+- __pthread_testcancel ();
++ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
++ if (cancelhandling & CANCELTYPE_BITMASK)
++ {
++ int newval;
++ do
++ {
++ newval = cancelhandling | CANCELTYPE_BITMASK;
++ }
++ while (!atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &cancelhandling, newval));
++
++ if (cancel_enabled_and_canceled (cancelhandling))
++ {
++ self->result = PTHREAD_CANCELED;
++ __do_cancel ();
++ }
++ }
+ }
+ libc_hidden_def (__libc_cleanup_pop_restore)
+diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
+index 9bac6e3..2680b55 100644
+--- a/nptl/pthread_cancel.c
++++ b/nptl/pthread_cancel.c
+@@ -43,18 +43,29 @@ sigcancel_handler (int sig, siginfo_t *si, void *ctx)
+
+ struct pthread *self = THREAD_SELF;
+
+- int ch = atomic_load_relaxed (&self->cancelhandling);
+- /* Cancelation not enabled, not cancelled, or already exitting. */
+- if (self->cancelstate == PTHREAD_CANCEL_DISABLE
+- || (ch & CANCELED_BITMASK) == 0
+- || (ch & EXITING_BITMASK) != 0)
+- return;
+-
+- /* Set the return value. */
+- THREAD_SETMEM (self, result, PTHREAD_CANCELED);
+- /* Make sure asynchronous cancellation is still enabled. */
+- if (self->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
+- __do_cancel ();
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
++ while (1)
++ {
++ /* We are canceled now. When canceled by another thread this flag
++ is already set but if the signal is directly send (internally or
++ from another process) is has to be done here. */
++ int newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
++
++ if (oldval == newval || (oldval & EXITING_BITMASK) != 0)
++ /* Already canceled or exiting. */
++ break;
++
++ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval))
++ {
++ self->result = PTHREAD_CANCELED;
++
++ /* Make sure asynchronous cancellation is still enabled. */
++ if ((oldval & CANCELTYPE_BITMASK) != 0)
++ /* Run the registered destructors and terminate the thread. */
++ __do_cancel ();
++ }
++ }
+ }
+
+ int
+@@ -93,29 +104,70 @@ __pthread_cancel (pthread_t th)
+ }
+ #endif
+
+- int oldch = atomic_fetch_or_acquire (&pd->cancelhandling, CANCELED_BITMASK);
+- if ((oldch & CANCELED_BITMASK) != 0)
+- return 0;
+-
+- if (pd == THREAD_SELF)
++ /* Some syscalls are never restarted after being interrupted by a signal
++ handler, regardless of the use of SA_RESTART (they always fail with
++ EINTR). So pthread_cancel cannot send SIGCANCEL unless the cancellation
++ is enabled and set as asynchronous (in this case the cancellation will
++ be acted in the cancellation handler instead by the syscall wrapper).
++ Otherwise the target thread is set as 'cancelling' (CANCELING_BITMASK)
++ by atomically setting 'cancelhandling' and the cancelation will be acted
++ upon on next cancellation entrypoing in the target thread.
++
++ It also requires to atomically check if cancellation is enabled and
++ asynchronous, so both cancellation state and type are tracked on
++ 'cancelhandling'. */
++
++ int result = 0;
++ int oldval = atomic_load_relaxed (&pd->cancelhandling);
++ int newval;
++ do
+ {
+- /* A single-threaded process should be able to kill itself, since there
+- is nothing in the POSIX specification that says that it cannot. So
+- we set multiple_threads to true so that cancellation points get
+- executed. */
+- THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
++ newval = oldval | CANCELING_BITMASK | CANCELED_BITMASK;
++ if (oldval == newval)
++ break;
++
++ /* If the cancellation is handled asynchronously just send a
++ signal. We avoid this if possible since it's more
++ expensive. */
++ if (cancel_enabled_and_canceled_and_async (newval))
++ {
++ /* Mark the cancellation as "in progress". */
++ int newval2 = oldval | CANCELING_BITMASK;
++ if (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling,
++ &oldval, newval2))
++ continue;
++
++ if (pd == THREAD_SELF)
++ /* This is not merely an optimization: An application may
++ call pthread_cancel (pthread_self ()) without calling
++ pthread_create, so the signal handler may not have been
++ set up for a self-cancel. */
++ {
++ pd->result = PTHREAD_CANCELED;
++ if ((newval & CANCELTYPE_BITMASK) != 0)
++ __do_cancel ();
++ }
++ else
++ /* The cancellation handler will take care of marking the
++ thread as canceled. */
++ result = __pthread_kill_internal (th, SIGCANCEL);
++
++ break;
++ }
++
++ /* A single-threaded process should be able to kill itself, since
++ there is nothing in the POSIX specification that says that it
++ cannot. So we set multiple_threads to true so that cancellation
++ points get executed. */
++ THREAD_SETMEM (THREAD_SELF, header.multiple_threads, 1);
+ #ifndef TLS_MULTIPLE_THREADS_IN_TCB
+ __libc_multiple_threads = 1;
+ #endif
+-
+- THREAD_SETMEM (pd, result, PTHREAD_CANCELED);
+- if (pd->cancelstate == PTHREAD_CANCEL_ENABLE
+- && pd->canceltype == PTHREAD_CANCEL_ASYNCHRONOUS)
+- __do_cancel ();
+- return 0;
+ }
++ while (!atomic_compare_exchange_weak_acquire (&pd->cancelhandling, &oldval,
++ newval));
+
+- return __pthread_kill_internal (th, SIGCANCEL);
++ return result;
+ }
+ versioned_symbol (libc, __pthread_cancel, pthread_cancel, GLIBC_2_34);
+
+diff --git a/nptl/pthread_join_common.c b/nptl/pthread_join_common.c
+index 7303069..617056e 100644
+--- a/nptl/pthread_join_common.c
++++ b/nptl/pthread_join_common.c
+@@ -57,12 +57,9 @@ __pthread_clockjoin_ex (pthread_t threadid, void **thread_return,
+ if ((pd == self
+ || (self->joinid == pd
+ && (pd->cancelhandling
+- & (CANCELED_BITMASK | EXITING_BITMASK
++ & (CANCELING_BITMASK | CANCELED_BITMASK | EXITING_BITMASK
+ | TERMINATED_BITMASK)) == 0))
+- && !(self->cancelstate == PTHREAD_CANCEL_ENABLE
+- && (pd->cancelhandling & (CANCELED_BITMASK | EXITING_BITMASK
+- | TERMINATED_BITMASK))
+- == CANCELED_BITMASK))
++ && !cancel_enabled_and_canceled (self->cancelhandling))
+ /* This is a deadlock situation. The threads are waiting for each
+ other to finish. Note that this is a "may" error. To be 100%
+ sure we catch this error we would have to lock the data
+diff --git a/nptl/pthread_setcancelstate.c b/nptl/pthread_setcancelstate.c
+index 7e2b6e4..cb567be 100644
+--- a/nptl/pthread_setcancelstate.c
++++ b/nptl/pthread_setcancelstate.c
+@@ -31,9 +31,29 @@ __pthread_setcancelstate (int state, int *oldstate)
+
+ self = THREAD_SELF;
+
+- if (oldstate != NULL)
+- *oldstate = self->cancelstate;
+- self->cancelstate = state;
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
++ while (1)
++ {
++ int newval = (state == PTHREAD_CANCEL_DISABLE
++ ? oldval | CANCELSTATE_BITMASK
++ : oldval & ~CANCELSTATE_BITMASK);
++
++ if (oldstate != NULL)
++ *oldstate = ((oldval & CANCELSTATE_BITMASK)
++ ? PTHREAD_CANCEL_DISABLE : PTHREAD_CANCEL_ENABLE);
++
++ if (oldval == newval)
++ break;
++
++ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval))
++ {
++ if (cancel_enabled_and_canceled_and_async (newval))
++ __do_cancel ();
++
++ break;
++ }
++ }
+
+ return 0;
+ }
+diff --git a/nptl/pthread_setcanceltype.c b/nptl/pthread_setcanceltype.c
+index e7b24ae..e08ff7b 100644
+--- a/nptl/pthread_setcanceltype.c
++++ b/nptl/pthread_setcanceltype.c
+@@ -29,11 +29,32 @@ __pthread_setcanceltype (int type, int *oldtype)
+
+ volatile struct pthread *self = THREAD_SELF;
+
+- if (oldtype != NULL)
+- *oldtype = self->canceltype;
+- self->canceltype = type;
+- if (type == PTHREAD_CANCEL_ASYNCHRONOUS)
+- __pthread_testcancel ();
++ int oldval = atomic_load_relaxed (&self->cancelhandling);
++ while (1)
++ {
++ int newval = (type == PTHREAD_CANCEL_ASYNCHRONOUS
++ ? oldval | CANCELTYPE_BITMASK
++ : oldval & ~CANCELTYPE_BITMASK);
++
++ if (oldtype != NULL)
++ *oldtype = ((oldval & CANCELTYPE_BITMASK)
++ ? PTHREAD_CANCEL_ASYNCHRONOUS : PTHREAD_CANCEL_DEFERRED);
++
++ if (oldval == newval)
++ break;
++
++ if (atomic_compare_exchange_weak_acquire (&self->cancelhandling,
++ &oldval, newval))
++ {
++ if (cancel_enabled_and_canceled_and_async (newval))
++ {
++ THREAD_SETMEM (self, result, PTHREAD_CANCELED);
++ __do_cancel ();
++ }
++
++ break;
++ }
++ }
+
+ return 0;
+ }
+diff --git a/nptl/pthread_testcancel.c b/nptl/pthread_testcancel.c
+index 31185d8..2523021 100644
+--- a/nptl/pthread_testcancel.c
++++ b/nptl/pthread_testcancel.c
+@@ -24,13 +24,10 @@ void
+ ___pthread_testcancel (void)
+ {
+ struct pthread *self = THREAD_SELF;
+- int cancelhandling = THREAD_GETMEM (self, cancelhandling);
+- if (self->cancelstate == PTHREAD_CANCEL_ENABLE
+- && (cancelhandling & CANCELED_BITMASK)
+- && !(cancelhandling & EXITING_BITMASK)
+- && !(cancelhandling & TERMINATED_BITMASK))
++ int cancelhandling = atomic_load_relaxed (&self->cancelhandling);
++ if (cancel_enabled_and_canceled (cancelhandling))
+ {
+- THREAD_SETMEM (self, result, PTHREAD_CANCELED);
++ self->result = PTHREAD_CANCELED;
+ __do_cancel ();
+ }
+ }
+diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
+index ca494dd..c2054f8 100644
+--- a/sysdeps/nptl/dl-tls_init_tp.c
++++ b/sysdeps/nptl/dl-tls_init_tp.c
+@@ -94,7 +94,4 @@ __tls_init_tp (void)
+ It will be bigger than it actually is, but for unwind.c/pt-longjmp.c
+ purposes this is good enough. */
+ THREAD_SETMEM (pd, stackblock_size, (size_t) __libc_stack_end);
+-
+- THREAD_SETMEM (pd, cancelstate, PTHREAD_CANCEL_ENABLE);
+- THREAD_SETMEM (pd, canceltype, PTHREAD_CANCEL_DEFERRED);
+ }
+diff --git a/sysdeps/nptl/pthreadP.h b/sysdeps/nptl/pthreadP.h
+index 374657a..b968afc 100644
+--- a/sysdeps/nptl/pthreadP.h
++++ b/sysdeps/nptl/pthreadP.h
+@@ -276,7 +276,7 @@ __do_cancel (void)
+ struct pthread *self = THREAD_SELF;
+
+ /* Make sure we get no more cancellations. */
+- THREAD_ATOMIC_BIT_SET (self, cancelhandling, EXITING_BIT);
++ atomic_bit_set (&self->cancelhandling, EXITING_BIT);
+
+ __pthread_unwind ((__pthread_unwind_buf_t *)
+ THREAD_GETMEM (self, cleanup_jmp_buf));
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index c657101..00419c4 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -69,6 +69,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-cancel12 tst-cancel13 tst-cancel14 tst-cancel15 tst-cancel16 \
+ tst-cancel18 tst-cancel19 tst-cancel20 tst-cancel21 \
+ tst-cancel22 tst-cancel23 tst-cancel26 tst-cancel27 tst-cancel28 \
++ tst-cancel29 \
+ tst-cleanup0 tst-cleanup1 tst-cleanup2 tst-cleanup3 \
+ tst-clock1 \
+ tst-cond-except \
+diff --git a/sysdeps/pthread/tst-cancel29.c b/sysdeps/pthread/tst-cancel29.c
+new file mode 100644
+index 0000000..4f0d99e
+--- /dev/null
++++ b/sysdeps/pthread/tst-cancel29.c
+@@ -0,0 +1,207 @@
++/* Check if a thread that disables cancellation and which call functions
++ that might be interrupted by a signal do not see the internal SIGCANCEL.
++
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <array_length.h>
++#include <errno.h>
++#include <inttypes.h>
++#include <poll.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/temp_file.h>
++#include <support/xthread.h>
++#include <sys/socket.h>
++#include <signal.h>
++#include <stdio.h>
++#include <unistd.h>
++
++/* On Linux some interfaces are never restarted after being interrupted by
++ a signal handler, regardless of the use of SA_RESTART. It means that
++ if asynchronous cancellation is not enabled, the pthread_cancel can not
++ set the internal SIGCANCEL otherwise the interface might see a spurious
++ EINTR failure. */
++
++static pthread_barrier_t b;
++
++/* Cleanup handling test. */
++static int cl_called;
++static void
++cl (void *arg)
++{
++ ++cl_called;
++}
++
++static void *
++tf_sigtimedwait (void *arg)
++{
++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
++ xpthread_barrier_wait (&b);
++
++ int r;
++ pthread_cleanup_push (cl, NULL);
++
++ sigset_t mask;
++ sigemptyset (&mask);
++ r = sigtimedwait (&mask, NULL, &(struct timespec) { 0, 250000000 });
++ if (r != -1)
++ return (void*) -1;
++ if (errno != EAGAIN)
++ return (void*) -2;
++
++ pthread_cleanup_pop (0);
++ return NULL;
++}
++
++static void *
++tf_poll (void *arg)
++{
++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
++ xpthread_barrier_wait (&b);
++
++ int r;
++ pthread_cleanup_push (cl, NULL);
++
++ r = poll (NULL, 0, 250);
++ if (r != 0)
++ return (void*) -1;
++
++ pthread_cleanup_pop (0);
++ return NULL;
++}
++
++static void *
++tf_ppoll (void *arg)
++{
++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
++
++ xpthread_barrier_wait (&b);
++
++ int r;
++ pthread_cleanup_push (cl, NULL);
++
++ r = ppoll (NULL, 0, &(struct timespec) { 0, 250000000 }, NULL);
++ if (r != 0)
++ return (void*) -1;
++
++ pthread_cleanup_pop (0);
++ return NULL;
++}
++
++static void *
++tf_select (void *arg)
++{
++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
++ xpthread_barrier_wait (&b);
++
++ int r;
++ pthread_cleanup_push (cl, NULL);
++
++ r = select (0, NULL, NULL, NULL, &(struct timeval) { 0, 250000 });
++ if (r != 0)
++ return (void*) -1;
++
++ pthread_cleanup_pop (0);
++ return NULL;
++}
++
++static void *
++tf_pselect (void *arg)
++{
++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
++ xpthread_barrier_wait (&b);
++
++ int r;
++ pthread_cleanup_push (cl, NULL);
++
++ r = pselect (0, NULL, NULL, NULL, &(struct timespec) { 0, 250000000 }, NULL);
++ if (r != 0)
++ return (void*) -1;
++
++ pthread_cleanup_pop (0);
++ return NULL;
++}
++
++static void *
++tf_clock_nanosleep (void *arg)
++{
++ pthread_setcancelstate (PTHREAD_CANCEL_DISABLE, NULL);
++ xpthread_barrier_wait (&b);
++
++ int r;
++ pthread_cleanup_push (cl, NULL);
++
++ r = clock_nanosleep (CLOCK_REALTIME, 0, &(struct timespec) { 0, 250000000 },
++ NULL);
++ if (r != 0)
++ return (void*) -1;
++
++ pthread_cleanup_pop (0);
++ return NULL;
++}
++
++struct cancel_test_t
++{
++ const char *name;
++ void * (*cf) (void *);
++} tests[] =
++{
++ { "sigtimedwait", tf_sigtimedwait, },
++ { "poll", tf_poll, },
++ { "ppoll", tf_ppoll, },
++ { "select", tf_select, },
++ { "pselect", tf_pselect , },
++ { "clock_nanosleep", tf_clock_nanosleep, },
++};
++
++static int
++do_test (void)
++{
++ for (int i = 0; i < array_length (tests); i++)
++ {
++ xpthread_barrier_init (&b, NULL, 2);
++
++ cl_called = 0;
++
++ pthread_t th = xpthread_create (NULL, tests[i].cf, NULL);
++
++ xpthread_barrier_wait (&b);
++
++ struct timespec ts = { .tv_sec = 0, .tv_nsec = 100000000 };
++ while (nanosleep (&ts, &ts) != 0)
++ continue;
++
++ xpthread_cancel (th);
++
++ void *status = xpthread_join (th);
++ if (status != NULL)
++ printf ("test '%s' failed: %" PRIdPTR "\n", tests[i].name,
++ (intptr_t) status);
++ TEST_VERIFY (status == NULL);
++
++ xpthread_barrier_destroy (&b);
++
++ TEST_COMPARE (cl_called, 0);
++
++ printf ("in-time cancel test of '%s' successful\n", tests[i].name);
++ }
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/nptl-pthread_kill-must-send-signals-to-a-specific-th.patch b/nptl-pthread_kill-must-send-signals-to-a-specific-th.patch
new file mode 100644
index 0000000..87683c3
--- /dev/null
+++ b/nptl-pthread_kill-must-send-signals-to-a-specific-th.patch
@@ -0,0 +1,162 @@
+From eae81d70574e923ce3c59078b8df857ae192efa6 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 1 Oct 2021 18:16:41 +0200
+Subject: [PATCH] nptl: pthread_kill must send signals to a specific thread [BZ
+ #28407]
+
+The choice between the kill vs tgkill system calls is not just about
+the TID reuse race, but also about whether the signal is sent to the
+whole process (and any thread in it) or to a specific thread.
+
+This was caught by the openposix test suite:
+
+ LTP: openposix test suite - FAIL: SIGUSR1 is member of new thread pendingset.
+ <https://gitlab.com/cki-project/kernel-tests/-/issues/764>
+
+Fixes commit 526c3cf11ee9367344b6b15d669e4c3cb461a2be ("nptl: Fix race
+between pthread_kill and thread exit (bug 12889)").
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ nptl/pthread_kill.c | 4 +-
+ sysdeps/pthread/Makefile | 1 +
+ sysdeps/pthread/tst-pthread-raise-blocked-self.c | 92 ++++++++++++++++++++++++
+ 3 files changed, 94 insertions(+), 3 deletions(-)
+ create mode 100644 sysdeps/pthread/tst-pthread-raise-blocked-self.c
+
+diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c
+index a44dc8f..35bf1f9 100644
+--- a/nptl/pthread_kill.c
++++ b/nptl/pthread_kill.c
+@@ -40,7 +40,7 @@ __pthread_kill_implementation (pthread_t threadid, int signo, int no_tid)
+ below. POSIX only guarantees delivery of a single signal,
+ which may not be the right one.) */
+ pid_t tid = INTERNAL_SYSCALL_CALL (gettid);
+- int ret = INTERNAL_SYSCALL_CALL (kill, tid, signo);
++ int ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), tid, signo);
+ return INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
+ }
+
+@@ -59,8 +59,6 @@ __pthread_kill_implementation (pthread_t threadid, int signo, int no_tid)
+ ret = no_tid;
+ else
+ {
+- /* Using tgkill is a safety measure. pd->exit_lock ensures that
+- the target thread cannot exit. */
+ ret = INTERNAL_SYSCALL_CALL (tgkill, __getpid (), pd->tid, signo);
+ ret = INTERNAL_SYSCALL_ERROR_P (ret) ? INTERNAL_SYSCALL_ERRNO (ret) : 0;
+ }
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index d4bd2d4..0af9c59 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -121,6 +121,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-pthread-setuid-loop \
+ tst-pthread_cancel-exited \
+ tst-pthread_cancel-select-loop \
++ tst-pthread-raise-blocked-self \
+ tst-pthread_kill-exited \
+ tst-pthread_kill-exiting \
+ # tests
+diff --git a/sysdeps/pthread/tst-pthread-raise-blocked-self.c b/sysdeps/pthread/tst-pthread-raise-blocked-self.c
+new file mode 100644
+index 0000000..128e1a6
+--- /dev/null
++++ b/sysdeps/pthread/tst-pthread-raise-blocked-self.c
+@@ -0,0 +1,92 @@
++/* Test that raise sends signal to current thread even if blocked.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <signal.h>
++#include <support/check.h>
++#include <support/xsignal.h>
++#include <support/xthread.h>
++#include <pthread.h>
++#include <unistd.h>
++
++/* Used to create a dummy thread ID distinct from all other thread
++ IDs. */
++static void *
++noop (void *ignored)
++{
++ return NULL;
++}
++
++static volatile pthread_t signal_thread;
++
++static void
++signal_handler (int signo)
++{
++ signal_thread = pthread_self ();
++}
++
++/* Used to ensure that waiting_thread has launched and can accept
++ signals. */
++static pthread_barrier_t barrier;
++
++static void *
++waiting_thread (void *ignored)
++{
++ xpthread_barrier_wait (&barrier);
++ pause ();
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ xsignal (SIGUSR1, signal_handler);
++ xpthread_barrier_init (&barrier, NULL, 2);
++
++ /* Distinct thread ID value to */
++ pthread_t dummy = xpthread_create (NULL, noop, NULL);
++ signal_thread = dummy;
++
++ pthread_t helper = xpthread_create (NULL, waiting_thread, NULL);
++
++ /* Make sure that the thread is running. */
++ xpthread_barrier_wait (&barrier);
++
++ /* Block signals on this thread. */
++ sigset_t set;
++ sigfillset (&set);
++ xpthread_sigmask (SIG_BLOCK, &set, NULL);
++
++ /* Send the signal to this thread. It must not be delivered. */
++ raise (SIGUSR1);
++ TEST_VERIFY (signal_thread == dummy);
++
++ /* Wait a bit to give a chance for signal delivery (increases
++ chances of failure with bug 28407). */
++ usleep (50 * 1000);
++
++ /* Unblocking should cause synchronous delivery of the signal. */
++ xpthread_sigmask (SIG_UNBLOCK, &set, NULL);
++ TEST_VERIFY (signal_thread == pthread_self ());
++
++ xpthread_cancel (helper);
++ xpthread_join (helper);
++ xpthread_join (dummy);
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch b/nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch
new file mode 100644
index 0000000..d52abb8
--- /dev/null
+++ b/nptl-pthread_kill-needs-to-return-ESRCH-for-old-prog.patch
@@ -0,0 +1,142 @@
+From 95dba35bf05e4a5d69dfae5e9c9d4df3646a7f93 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 20 Sep 2021 14:56:08 +0200
+Subject: [PATCH] nptl: pthread_kill needs to return ESRCH for old programs
+ (bug 19193)
+
+The fix for bug 19193 breaks some old applications which appear
+to use pthread_kill to probe if a thread is still running, something
+that is not supported by POSIX.
+---
+ nptl/pthread_kill.c | 37 ++++++++++++++++++++++++-------
+ sysdeps/pthread/tst-pthread_kill-exited.c | 21 ++++++++++++++++--
+ 2 files changed, 48 insertions(+), 10 deletions(-)
+
+diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c
+index fb7862e..a44dc8f 100644
+--- a/nptl/pthread_kill.c
++++ b/nptl/pthread_kill.c
+@@ -21,8 +21,11 @@
+ #include <pthreadP.h>
+ #include <shlib-compat.h>
+
+-int
+-__pthread_kill_internal (pthread_t threadid, int signo)
++/* Sends SIGNO to THREADID. If the thread is about to exit or has
++ already exited on the kernel side, return NO_TID. Otherwise return
++ 0 or an error code. */
++static int
++__pthread_kill_implementation (pthread_t threadid, int signo, int no_tid)
+ {
+ struct pthread *pd = (struct pthread *) threadid;
+ if (pd == THREAD_SELF)
+@@ -52,11 +55,8 @@ __pthread_kill_internal (pthread_t threadid, int signo)
+ signal is either not observable (the target thread has already
+ blocked signals at this point), or it will fail, or it might be
+ delivered to a new, unrelated thread that has reused the TID.
+- So do not actually send the signal. Do not report an error
+- because the threadid argument is still valid (the thread ID
+- lifetime has not ended), and ESRCH (for example) would be
+- misleading. */
+- ret = 0;
++ So do not actually send the signal. */
++ ret = no_tid;
+ else
+ {
+ /* Using tgkill is a safety measure. pd->exit_lock ensures that
+@@ -72,6 +72,15 @@ __pthread_kill_internal (pthread_t threadid, int signo)
+ }
+
+ int
++__pthread_kill_internal (pthread_t threadid, int signo)
++{
++ /* Do not report an error in the no-tid case because the threadid
++ argument is still valid (the thread ID lifetime has not ended),
++ and ESRCH (for example) would be misleading. */
++ return __pthread_kill_implementation (threadid, signo, 0);
++}
++
++int
+ __pthread_kill (pthread_t threadid, int signo)
+ {
+ /* Disallow sending the signal we use for cancellation, timers,
+@@ -81,6 +90,7 @@ __pthread_kill (pthread_t threadid, int signo)
+
+ return __pthread_kill_internal (threadid, signo);
+ }
++
+ /* Some architectures (for instance arm) might pull raise through libgcc, so
+ avoid the symbol version if it ends up being used on ld.so. */
+ #if !IS_IN(rtld)
+@@ -88,6 +98,17 @@ libc_hidden_def (__pthread_kill)
+ versioned_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_34);
+
+ # if OTHER_SHLIB_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34)
+-compat_symbol (libc, __pthread_kill, pthread_kill, GLIBC_2_0);
++/* Variant which returns ESRCH in the no-TID case, for backwards
++ compatibility. */
++int
++attribute_compat_text_section
++__pthread_kill_esrch (pthread_t threadid, int signo)
++{
++ if (__is_internal_signal (signo))
++ return EINVAL;
++
++ return __pthread_kill_implementation (threadid, signo, ESRCH);
++}
++compat_symbol (libc, __pthread_kill_esrch, pthread_kill, GLIBC_2_0);
+ # endif
+ #endif
+diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c
+index 7575fb6..a2fddad 100644
+--- a/sysdeps/pthread/tst-pthread_kill-exited.c
++++ b/sysdeps/pthread/tst-pthread_kill-exited.c
+@@ -16,11 +16,15 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+-/* This test verifies that pthread_kill returns 0 (and not ESRCH) for
+- a thread that has exited on the kernel side. */
++/* This test verifies that the default pthread_kill returns 0 (and not
++ ESRCH) for a thread that has exited on the kernel side. */
+
++#include <errno.h>
++#include <pthread.h>
++#include <shlib-compat.h>
+ #include <signal.h>
+ #include <stddef.h>
++#include <support/check.h>
+ #include <support/support.h>
+ #include <support/xthread.h>
+
+@@ -30,6 +34,12 @@ noop_thread (void *closure)
+ return NULL;
+ }
+
++#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC
++extern __typeof (pthread_kill) compat_pthread_kill;
++compat_symbol_reference (libpthread, compat_pthread_kill, pthread_kill,
++ GLIBC_2_0);
++#endif
++
+ static int
+ do_test (void)
+ {
+@@ -37,7 +47,14 @@ do_test (void)
+
+ support_wait_for_thread_exit ();
+
++ /* NB: Always uses the default symbol due to separate compilation. */
+ xpthread_kill (thr, SIGUSR1);
++
++#if TEST_COMPAT (libpthread, GLIBC_2_0, GLIBC_2_34) && PTHREAD_IN_LIBC
++ /* Old binaries need the non-conforming ESRCH error code. */
++ TEST_COMPARE (compat_pthread_kill (thr, SIGUSR1), ESRCH);
++#endif
++
+ xpthread_join (thr);
+
+ return 0;
+--
+1.8.3.1
+
diff --git a/nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch b/nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch
new file mode 100644
index 0000000..7d1bc81
--- /dev/null
+++ b/nptl-pthread_kill-pthread_cancel-should-not-fail-aft.patch
@@ -0,0 +1,292 @@
+From 8af8456004edbab71f8903a60a3cae442cf6fe69 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 13 Sep 2021 11:06:08 +0200
+Subject: [PATCH] nptl: pthread_kill, pthread_cancel should not fail after exit
+ (bug 19193)
+
+This closes one remaining race condition related to bug 12889: if
+the thread already exited on the kernel side, returning ESRCH
+is not correct because that error is reserved for the thread IDs
+(pthread_t values) whose lifetime has ended. In case of a
+kernel-side exit and a valid thread ID, no signal needs to be sent
+and cancellation does not have an effect, so just return 0.
+
+sysdeps/pthread/tst-kill4.c triggers undefined behavior and is
+removed with this commit.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ nptl/pthread_cancel.c | 9 +--
+ nptl/pthread_kill.c | 7 ++-
+ sysdeps/pthread/Makefile | 5 +-
+ sysdeps/pthread/tst-kill4.c | 90 -----------------------------
+ sysdeps/pthread/tst-pthread_cancel-exited.c | 45 +++++++++++++++
+ sysdeps/pthread/tst-pthread_kill-exited.c | 46 +++++++++++++++
+ 6 files changed, 106 insertions(+), 96 deletions(-)
+ delete mode 100644 sysdeps/pthread/tst-kill4.c
+ create mode 100644 sysdeps/pthread/tst-pthread_cancel-exited.c
+ create mode 100644 sysdeps/pthread/tst-pthread_kill-exited.c
+
+diff --git a/nptl/pthread_cancel.c b/nptl/pthread_cancel.c
+index 2bb523c..a8aa3b3 100644
+--- a/nptl/pthread_cancel.c
++++ b/nptl/pthread_cancel.c
+@@ -61,10 +61,11 @@ __pthread_cancel (pthread_t th)
+ {
+ volatile struct pthread *pd = (volatile struct pthread *) th;
+
+- /* Make sure the descriptor is valid. */
+- if (INVALID_TD_P (pd))
+- /* Not a valid thread handle. */
+- return ESRCH;
++ if (pd->tid == 0)
++ /* The thread has already exited on the kernel side. Its outcome
++ (regular exit, other cancelation) has already been
++ determined. */
++ return 0;
+
+ static int init_sigcancel = 0;
+ if (atomic_load_relaxed (&init_sigcancel) == 0)
+diff --git a/nptl/pthread_kill.c b/nptl/pthread_kill.c
+index f79a2b2..5d4c86f 100644
+--- a/nptl/pthread_kill.c
++++ b/nptl/pthread_kill.c
+@@ -46,7 +46,12 @@ __pthread_kill_internal (pthread_t threadid, int signo)
+ ? INTERNAL_SYSCALL_ERRNO (val) : 0);
+ }
+ else
+- val = ESRCH;
++ /* The kernel reports that the thread has exited. POSIX specifies
++ the ESRCH error only for the case when the lifetime of a thread
++ ID has ended, but calling pthread_kill on such a thread ID is
++ undefined in glibc. Therefore, do not treat kernel thread exit
++ as an error. */
++ val = 0;
+
+ return val;
+ }
+diff --git a/sysdeps/pthread/Makefile b/sysdeps/pthread/Makefile
+index 42f9fc5..dedfa0d 100644
+--- a/sysdeps/pthread/Makefile
++++ b/sysdeps/pthread/Makefile
+@@ -89,7 +89,7 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-join8 tst-join9 tst-join10 tst-join11 tst-join12 tst-join13 \
+ tst-join14 tst-join15 \
+ tst-key1 tst-key2 tst-key3 tst-key4 \
+- tst-kill1 tst-kill2 tst-kill3 tst-kill4 tst-kill5 tst-kill6 \
++ tst-kill1 tst-kill2 tst-kill3 tst-kill5 tst-kill6 \
+ tst-locale1 tst-locale2 \
+ tst-memstream \
+ tst-mutex-errorcheck tst-mutex1 tst-mutex2 tst-mutex3 tst-mutex4 \
+@@ -118,6 +118,9 @@ tests += tst-cnd-basic tst-mtx-trylock tst-cnd-broadcast \
+ tst-unload \
+ tst-unwind-thread \
+ tst-pt-vfork1 tst-pt-vfork2 tst-vfork1x tst-vfork2x \
++ tst-pthread_cancel-exited \
++ tst-pthread_kill-exited \
++ # tests
+
+ tests-time64 := \
+ tst-abstime-time64 \
+diff --git a/sysdeps/pthread/tst-kill4.c b/sysdeps/pthread/tst-kill4.c
+deleted file mode 100644
+index 222ceb7..0000000
+--- a/sysdeps/pthread/tst-kill4.c
++++ /dev/null
+@@ -1,90 +0,0 @@
+-/* Copyright (C) 2003-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+- Contributed by Ulrich Drepper <drepper@redhat.com>, 2003.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include <errno.h>
+-#include <pthread.h>
+-#include <signal.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <unistd.h>
+-
+-
+-static void *
+-tf (void *a)
+-{
+- return NULL;
+-}
+-
+-
+-int
+-do_test (void)
+-{
+- pthread_attr_t at;
+- if (pthread_attr_init (&at) != 0)
+- {
+- puts ("attr_create failed");
+- exit (1);
+- }
+-
+- /* Limit thread stack size, because if it is too large, pthread_join
+- will free it immediately rather than put it into stack cache. */
+- if (pthread_attr_setstacksize (&at, 2 * 1024 * 1024) != 0)
+- {
+- puts ("setstacksize failed");
+- exit (1);
+- }
+-
+- pthread_t th;
+- if (pthread_create (&th, &at, tf, NULL) != 0)
+- {
+- puts ("create failed");
+- exit (1);
+- }
+-
+- pthread_attr_destroy (&at);
+-
+- if (pthread_join (th, NULL) != 0)
+- {
+- puts ("join failed");
+- exit (1);
+- }
+-
+- /* The following only works because we assume here something about
+- the implementation. Namely, that the memory allocated for the
+- thread descriptor is not going away, that the TID field is
+- cleared and therefore the signal is sent to process 0, and that
+- we can savely assume there is no other process with this ID at
+- that time. */
+- int e = pthread_kill (th, 0);
+- if (e == 0)
+- {
+- puts ("pthread_kill succeeded");
+- exit (1);
+- }
+- if (e != ESRCH)
+- {
+- puts ("pthread_kill didn't return ESRCH");
+- exit (1);
+- }
+-
+- return 0;
+-}
+-
+-
+-#define TEST_FUNCTION do_test ()
+-#include "../test-skeleton.c"
+diff --git a/sysdeps/pthread/tst-pthread_cancel-exited.c b/sysdeps/pthread/tst-pthread_cancel-exited.c
+new file mode 100644
+index 0000000..811c9be
+--- /dev/null
++++ b/sysdeps/pthread/tst-pthread_cancel-exited.c
+@@ -0,0 +1,45 @@
++/* Test that pthread_kill succeeds for an exited thread.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* This test verifies that pthread_kill returns 0 (and not ESRCH) for
++ a thread that has exited on the kernel side. */
++
++#include <stddef.h>
++#include <support/support.h>
++#include <support/xthread.h>
++
++static void *
++noop_thread (void *closure)
++{
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ pthread_t thr = xpthread_create (NULL, noop_thread, NULL);
++
++ support_wait_for_thread_exit ();
++
++ xpthread_cancel (thr);
++ xpthread_join (thr);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/pthread/tst-pthread_kill-exited.c b/sysdeps/pthread/tst-pthread_kill-exited.c
+new file mode 100644
+index 0000000..7575fb6
+--- /dev/null
++++ b/sysdeps/pthread/tst-pthread_kill-exited.c
+@@ -0,0 +1,46 @@
++/* Test that pthread_kill succeeds for an exited thread.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* This test verifies that pthread_kill returns 0 (and not ESRCH) for
++ a thread that has exited on the kernel side. */
++
++#include <signal.h>
++#include <stddef.h>
++#include <support/support.h>
++#include <support/xthread.h>
++
++static void *
++noop_thread (void *closure)
++{
++ return NULL;
++}
++
++static int
++do_test (void)
++{
++ pthread_t thr = xpthread_create (NULL, noop_thread, NULL);
++
++ support_wait_for_thread_exit ();
++
++ xpthread_kill (thr, SIGUSR1);
++ xpthread_join (thr);
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/nscd.conf b/nscd.conf
new file mode 100644
index 0000000..8a24a78
--- /dev/null
+++ b/nscd.conf
@@ -0,0 +1 @@
+d /run/nscd 0755 root root
diff --git a/nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch b/nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch
new file mode 100644
index 0000000..28ff860
--- /dev/null
+++ b/nss-Use-files-dns-as-the-default-for-the-hosts-datab.patch
@@ -0,0 +1,81 @@
+From b99b0f93ee8762fe53ff65802deb6f00700b9924 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 17 Dec 2021 12:01:20 +0100
+Subject: [PATCH] nss: Use "files dns" as the default for the hosts database
+ (bug 28700)
+
+This matches what is currently in nss/nsswitch.conf. The new ordering
+matches what most distributions use in their installed configuration
+files.
+
+It is common to add localhost to /etc/hosts because the name does not
+exist in the DNS, but is commonly used as a host name.
+
+With the built-in "dns [!UNAVAIL=return] files" default, dns is
+searched first and provides an answer for "localhost" (NXDOMAIN).
+We never look at the files database as a result, so the contents of
+/etc/hosts is ignored. This means that "getent hosts localhost"
+fail without a /etc/nsswitch.conf file, even though the host name
+is listed in /etc/hosts.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ manual/nss.texi | 5 ++---
+ nss/XXX-lookup.c | 2 +-
+ nss/nss_database.c | 4 ++--
+ 3 files changed, 5 insertions(+), 6 deletions(-)
+
+diff --git a/manual/nss.texi b/manual/nss.texi
+index 3aaa778..524d22a 100644
+--- a/manual/nss.texi
++++ b/manual/nss.texi
+@@ -324,9 +324,8 @@ missing.
+
+ @cindex default value, and NSS
+ For the @code{hosts} and @code{networks} databases the default value is
+-@code{dns [!UNAVAIL=return] files}. I.e., the system is prepared for
+-the DNS service not to be available but if it is available the answer it
+-returns is definitive.
++@code{files dns}. I.e., local configuration will override the contents
++of the domain name system (DNS).
+
+ The @code{passwd}, @code{group}, and @code{shadow} databases was
+ traditionally handled in a special way. The appropriate files in the
+diff --git a/nss/XXX-lookup.c b/nss/XXX-lookup.c
+index 302c636..e129f69 100644
+--- a/nss/XXX-lookup.c
++++ b/nss/XXX-lookup.c
+@@ -28,7 +28,7 @@
+ |* ALTERNATE_NAME - name of another service which is examined in *|
+ |* case DATABASE_NAME is not found *|
+ |* *|
+-|* DEFAULT_CONFIG - string for default conf (e.g. "dns files") *|
++|* DEFAULT_CONFIG - string for default conf (e.g. "files dns") *|
+ |* *|
+ \*******************************************************************/
+
+diff --git a/nss/nss_database.c b/nss/nss_database.c
+index ab121cb..54561f0 100644
+--- a/nss/nss_database.c
++++ b/nss/nss_database.c
+@@ -80,7 +80,7 @@ enum nss_database_default
+ {
+ nss_database_default_defconfig = 0, /* "nis [NOTFOUND=return] files". */
+ nss_database_default_compat, /* "compat [NOTFOUND=return] files". */
+- nss_database_default_dns, /* "dns [!UNAVAIL=return] files". */
++ nss_database_default_dns, /* "files dns". */
+ nss_database_default_files, /* "files". */
+ nss_database_default_nis, /* "nis". */
+ nss_database_default_nis_nisplus, /* "nis nisplus". */
+@@ -133,7 +133,7 @@ nss_database_select_default (struct nss_database_default_cache *cache,
+ #endif
+
+ case nss_database_default_dns:
+- line = "dns [!UNAVAIL=return] files";
++ line = "files dns";
+ break;
+
+ case nss_database_default_files:
+--
+1.8.3.1
+
diff --git a/nsswitch.conf b/nsswitch.conf
new file mode 100644
index 0000000..b49a3b2
--- /dev/null
+++ b/nsswitch.conf
@@ -0,0 +1,56 @@
+#
+# /etc/nsswitch.conf
+#
+# An example Name Service Switch config file. This file should be
+# sorted with the most-used services at the beginning.
+#
+# The entry '[NOTFOUND=return]' means that the search for an
+# entry should stop if the search in the previous entry turned
+# up nothing. Note that if the search failed due to some other reason
+# (like no NIS server responding) then the search continues with the
+# next entry.
+#
+# Valid entries include:
+#
+# nisplus Use NIS+ (NIS version 3)
+# nis Use NIS (NIS version 2), also called YP
+# dns Use DNS (Domain Name Service)
+# files Use the local files in /etc
+# db Use the pre-processed /var/db files
+# compat Use /etc files plus *_compat pseudo-databases
+# hesiod Use Hesiod (DNS) for user lookups
+# sss Use sssd (System Security Services Daemon)
+# [NOTFOUND=return] Stop searching if not found so far
+#
+# 'sssd' performs its own 'files'-based caching, so it should
+# generally come before 'files'.
+
+# To use 'db', install the nss_db package, and put the 'db' in front
+# of 'files' for entries you want to be looked up first in the
+# databases, like this:
+#
+# passwd: db files
+# shadow: db files
+# group: db files
+
+passwd: sss files
+shadow: files sss
+group: sss files
+
+hosts: files dns myhostname
+
+bootparams: files
+
+ethers: files
+netmasks: files
+networks: files
+protocols: files
+rpc: files
+services: files sss
+
+netgroup: sss
+
+publickey: files
+
+automount: files sss
+aliases: files
diff --git a/posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch b/posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch
new file mode 100644
index 0000000..a9e8d26
--- /dev/null
+++ b/posix-Fix-attribute-access-mode-on-getcwd-BZ-27476.patch
@@ -0,0 +1,50 @@
+From 433ec4f14a5753c7689c83c20c9972915c53c204 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Fri, 10 Sep 2021 19:39:35 +0200
+Subject: [PATCH] posix: Fix attribute access mode on getcwd [BZ #27476]
+
+There is a GNU extension that allows to call getcwd(NULL, >0). It is
+described in the documentation, but also directly in the unistd.h
+header, just above the declaration.
+
+Therefore the attribute access mode added in commit 06febd8c6705
+is not correct. Drop it.
+---
+ posix/bits/unistd.h | 5 ++---
+ posix/unistd.h | 3 +--
+ 2 files changed, 3 insertions(+), 5 deletions(-)
+
+diff --git a/posix/bits/unistd.h b/posix/bits/unistd.h
+index f083138..622adeb 100644
+--- a/posix/bits/unistd.h
++++ b/posix/bits/unistd.h
+@@ -199,10 +199,9 @@ __NTH (readlinkat (int __fd, const char *__restrict __path,
+ #endif
+
+ extern char *__getcwd_chk (char *__buf, size_t __size, size_t __buflen)
+- __THROW __wur __attr_access ((__write_only__, 1, 2));
++ __THROW __wur;
+ extern char *__REDIRECT_NTH (__getcwd_alias,
+- (char *__buf, size_t __size), getcwd)
+- __wur __attr_access ((__write_only__, 1, 2));
++ (char *__buf, size_t __size), getcwd) __wur;
+ extern char *__REDIRECT_NTH (__getcwd_chk_warn,
+ (char *__buf, size_t __size, size_t __buflen),
+ __getcwd_chk)
+diff --git a/posix/unistd.h b/posix/unistd.h
+index 3dca657..8224c5f 100644
+--- a/posix/unistd.h
++++ b/posix/unistd.h
+@@ -528,8 +528,7 @@ extern int fchdir (int __fd) __THROW __wur;
+ an array is allocated with `malloc'; the array is SIZE
+ bytes long, unless SIZE == 0, in which case it is as
+ big as necessary. */
+-extern char *getcwd (char *__buf, size_t __size) __THROW __wur
+- __attr_access ((__write_only__, 1, 2));
++extern char *getcwd (char *__buf, size_t __size) __THROW __wur;
+
+ #ifdef __USE_GNU
+ /* Return a malloc'd string containing the current directory name.
+--
+1.8.3.1
+
diff --git a/posix-glob.c-update-from-gnulib.patch b/posix-glob.c-update-from-gnulib.patch
new file mode 100644
index 0000000..c15090a
--- /dev/null
+++ b/posix-glob.c-update-from-gnulib.patch
@@ -0,0 +1,195 @@
+From c66c92181ddbd82306537a608e8c0282587131de Mon Sep 17 00:00:00 2001
+From: DJ Delorie <dj@redhat.com>
+Date: Wed, 30 Mar 2022 17:44:02 -0400
+Subject: [PATCH] posix/glob.c: update from gnulib
+
+Copied from gnulib/lib/glob.c in order to fix rhbz 1982608
+Also fixes swbz 25659
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+(cherry picked from commit 7c477b57a31487eda516db02b9e04f22d1a6e6af)
+---
+ posix/glob.c | 70 +++++++++++++++++++++++++++------
+ sysdeps/unix/sysv/linux/glob64-time64.c | 1 +
+ 2 files changed, 59 insertions(+), 12 deletions(-)
+
+diff --git a/posix/glob.c b/posix/glob.c
+index 593a4c3..6af310a 100644
+--- a/posix/glob.c
++++ b/posix/glob.c
+@@ -21,13 +21,14 @@
+ optimizes away the pattern == NULL test below. */
+ # define _GL_ARG_NONNULL(params)
+
+-# include <config.h>
++# include <libc-config.h>
+
+ #endif
+
+ #include <glob.h>
+
+ #include <errno.h>
++#include <fcntl.h>
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdbool.h>
+@@ -56,6 +57,8 @@
+ # define sysconf(id) __sysconf (id)
+ # define closedir(dir) __closedir (dir)
+ # define opendir(name) __opendir (name)
++# undef dirfd
++# define dirfd(str) __dirfd (str)
+ # define readdir(str) __readdir64 (str)
+ # define getpwnam_r(name, bufp, buf, len, res) \
+ __getpwnam_r (name, bufp, buf, len, res)
+@@ -69,11 +72,8 @@
+ # ifndef GLOB_LSTAT
+ # define GLOB_LSTAT gl_lstat
+ # endif
+-# ifndef GLOB_STAT64
+-# define GLOB_STAT64 __stat64
+-# endif
+-# ifndef GLOB_LSTAT64
+-# define GLOB_LSTAT64 __lstat64
++# ifndef GLOB_FSTATAT64
++# define GLOB_FSTATAT64 __fstatat64
+ # endif
+ # include <shlib-compat.h>
+ #else /* !_LIBC */
+@@ -88,8 +88,7 @@
+ # define struct_stat struct stat
+ # define struct_stat64 struct stat
+ # define GLOB_LSTAT gl_lstat
+-# define GLOB_STAT64 stat
+-# define GLOB_LSTAT64 lstat
++# define GLOB_FSTATAT64 fstatat
+ #endif /* _LIBC */
+
+ #include <fnmatch.h>
+@@ -215,7 +214,8 @@ glob_lstat (glob_t *pglob, int flags, const char *fullname)
+ } ust;
+ return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
+ ? pglob->GLOB_LSTAT (fullname, &ust.st)
+- : GLOB_LSTAT64 (fullname, &ust.st64));
++ : GLOB_FSTATAT64 (AT_FDCWD, fullname, &ust.st64,
++ AT_SYMLINK_NOFOLLOW));
+ }
+
+ /* Set *R = A + B. Return true if the answer is mathematically
+@@ -257,7 +257,8 @@ is_dir (char const *filename, int flags, glob_t const *pglob)
+ struct_stat64 st64;
+ return (__glibc_unlikely (flags & GLOB_ALTDIRFUNC)
+ ? pglob->gl_stat (filename, &st) == 0 && S_ISDIR (st.st_mode)
+- : GLOB_STAT64 (filename, &st64) == 0 && S_ISDIR (st64.st_mode));
++ : (GLOB_FSTATAT64 (AT_FDCWD, filename, &st64, 0) == 0
++ && S_ISDIR (st64.st_mode)));
+ }
+
+ /* Find the end of the sub-pattern in a brace expression. */
+@@ -747,6 +748,8 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ else
+ {
+ #ifndef WINDOWS32
++ /* Recognize ~user as a shorthand for the specified user's home
++ directory. */
+ char *end_name = strchr (dirname, '/');
+ char *user_name;
+ int malloc_user_name = 0;
+@@ -885,7 +888,22 @@ __glob (const char *pattern, int flags, int (*errfunc) (const char *, int),
+ }
+ scratch_buffer_free (&pwtmpbuf);
+ }
+-#endif /* !WINDOWS32 */
++#else /* WINDOWS32 */
++ /* On native Windows, access to a user's home directory
++ (via GetUserProfileDirectory) or to a user's environment
++ variables (via ExpandEnvironmentStringsForUser) requires
++ the credentials of the user. Therefore we cannot support
++ the ~user syntax on this platform.
++ Handling ~user specially (and treat it like plain ~) if
++ user is getenv ("USERNAME") would not be a good idea,
++ since it would make people think that ~user is supported
++ in general. */
++ if (flags & GLOB_TILDE_CHECK)
++ {
++ retval = GLOB_NOMATCH;
++ goto out;
++ }
++#endif /* WINDOWS32 */
+ }
+ }
+
+@@ -1266,6 +1284,8 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ {
+ size_t dirlen = strlen (directory);
+ void *stream = NULL;
++ struct scratch_buffer s;
++ scratch_buffer_init (&s);
+ # define GLOBNAMES_MEMBERS(nnames) \
+ struct globnames *next; size_t count; char *name[nnames];
+ struct globnames { GLOBNAMES_MEMBERS (FLEXIBLE_ARRAY_MEMBER) };
+@@ -1337,6 +1357,7 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ }
+ else
+ {
++ int dfd = dirfd (stream);
+ int fnm_flags = ((!(flags & GLOB_PERIOD) ? FNM_PERIOD : 0)
+ | ((flags & GLOB_NOESCAPE) ? FNM_NOESCAPE : 0));
+ flags |= GLOB_MAGCHAR;
+@@ -1364,8 +1385,32 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ if (flags & GLOB_ONLYDIR)
+ switch (readdir_result_type (d))
+ {
+- case DT_DIR: case DT_LNK: case DT_UNKNOWN: break;
+ default: continue;
++ case DT_DIR: break;
++ case DT_LNK: case DT_UNKNOWN:
++ /* The filesystem was too lazy to give us a hint,
++ so we have to do it the hard way. */
++ if (__glibc_unlikely (dfd < 0 || flags & GLOB_ALTDIRFUNC))
++ {
++ size_t namelen = strlen (d.name);
++ size_t need = dirlen + 1 + namelen + 1;
++ if (s.length < need
++ && !scratch_buffer_set_array_size (&s, need, 1))
++ goto memory_error;
++ char *p = mempcpy (s.data, directory, dirlen);
++ *p = '/';
++ p += p[-1] != '/';
++ memcpy (p, d.name, namelen + 1);
++ if (! is_dir (s.data, flags, pglob))
++ continue;
++ }
++ else
++ {
++ struct_stat64 st64;
++ if (! (GLOB_FSTATAT64 (dfd, d.name, &st64, 0) == 0
++ && S_ISDIR (st64.st_mode)))
++ continue;
++ }
+ }
+
+ if (fnmatch (pattern, d.name, fnm_flags) == 0)
+@@ -1497,5 +1542,6 @@ glob_in_dir (const char *pattern, const char *directory, int flags,
+ __set_errno (save);
+ }
+
++ scratch_buffer_free (&s);
+ return result;
+ }
+diff --git a/sysdeps/unix/sysv/linux/glob64-time64.c b/sysdeps/unix/sysv/linux/glob64-time64.c
+index a465f70..95efe4c 100644
+--- a/sysdeps/unix/sysv/linux/glob64-time64.c
++++ b/sysdeps/unix/sysv/linux/glob64-time64.c
+@@ -37,6 +37,7 @@
+ # define GLOB_LSTAT gl_lstat
+ # define GLOB_STAT64 __stat64_time64
+ # define GLOB_LSTAT64 __lstat64_time64
++# define GLOB_FSTATAT64 __fstatat64_time64
+
+ # define COMPILE_GLOB64 1
+
+--
+1.8.3.1
+
diff --git a/pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch b/pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch
new file mode 100644
index 0000000..2088212
--- /dev/null
+++ b/pthread-tst-cancel28-Fix-barrier-re-init-race-condit.patch
@@ -0,0 +1,41 @@
+From 9874ca536b1d0662b1cea46af3ce09a4d42aeb32 Mon Sep 17 00:00:00 2001
+From: Stafford Horne <shorne@gmail.com>
+Date: Sat, 25 Sep 2021 17:02:06 +0900
+Subject: [PATCH] pthread/tst-cancel28: Fix barrier re-init race condition
+
+When running this test on the OpenRISC port I am working on this test
+fails with a timeout. The test passes when being straced or debugged.
+Looking at the code there seems to be a race condition in that:
+
+ 1 main thread: calls xpthread_cancel
+ 2 sub thread : receives cancel signal
+ 3 sub thread : cleanup routine waits on barrier
+ 4 main thread: re-inits barrier
+ 5 main thread: waits on barrier
+
+After getting to 5 the main thread and sub thread wait forever as the 2
+barriers are no longer the same.
+
+Removing the barrier re-init seems to fix this issue. Also, the barrier
+does not need to be reinitialized as that is done by default.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ sysdeps/pthread/tst-cancel28.c | 1 -
+ 1 file changed, 1 deletion(-)
+
+diff --git a/sysdeps/pthread/tst-cancel28.c b/sysdeps/pthread/tst-cancel28.c
+index 627cbc8..9286c15 100644
+--- a/sysdeps/pthread/tst-cancel28.c
++++ b/sysdeps/pthread/tst-cancel28.c
+@@ -69,7 +69,6 @@ do_test (void)
+
+ xpthread_cancel (timer_thread);
+
+- xpthread_barrier_init (&barrier, NULL, 2);
+ xpthread_barrier_wait (&barrier);
+
+ return 0;
+--
+1.8.3.1
+
diff --git a/realpath-Avoid-overwriting-preexisting-error-CVE-2021-3998.patch b/realpath-Avoid-overwriting-preexisting-error-CVE-2021-3998.patch
new file mode 100644
index 0000000..95c6bd6
--- /dev/null
+++ b/realpath-Avoid-overwriting-preexisting-error-CVE-2021-3998.patch
@@ -0,0 +1,33 @@
+From d084965adc7baa8ea804427cccf973cea556d697 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Mon, 24 Jan 2022 21:36:41 +0530
+Subject: [PATCH] realpath: Avoid overwriting preexisting error (CVE-2021-3998)
+
+Set errno and failure for paths that are too long only if no other error
+occurred earlier.
+
+Related: BZ #28770
+
+Reviewed-by: Andreas Schwab <schwab@linux-m68k.org>
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit 84d2d0fe20bdf94feed82b21b4d7d136db471f03)
+---
+ stdlib/canonicalize.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
+index 7a23a51..e2d4244 100644
+--- a/stdlib/canonicalize.c
++++ b/stdlib/canonicalize.c
+@@ -404,7 +404,7 @@ error:
+ {
+ if (dest - rname <= get_path_max ())
+ rname = strcpy (resolved, rname);
+- else
++ else if (!failed)
+ {
+ failed = true;
+ __set_errno (ENAMETOOLONG);
+--
+1.8.3.1
+
diff --git a/realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch b/realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch
new file mode 100644
index 0000000..c802dd9
--- /dev/null
+++ b/realpath-Set-errno-to-ENAMETOOLONG-for-result-larger.patch
@@ -0,0 +1,138 @@
+From f7a79879c0b2bef0dadd6caaaeeb0d26423e04e5 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Thu, 13 Jan 2022 11:28:36 +0530
+Subject: [PATCH] realpath: Set errno to ENAMETOOLONG for result larger than
+ PATH_MAX [BZ #28770]
+
+realpath returns an allocated string when the result exceeds PATH_MAX,
+which is unexpected when its second argument is not NULL. This results
+in the second argument (resolved) being uninitialized and also results
+in a memory leak since the caller expects resolved to be the same as the
+returned value.
+
+Return NULL and set errno to ENAMETOOLONG if the result exceeds
+PATH_MAX. This fixes [BZ #28770], which is CVE-2021-3998.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit ee8d5e33adb284601c00c94687bc907e10aec9bb)
+---
+ NEWS | 6 +++++
+ stdlib/Makefile | 1 +
+ stdlib/canonicalize.c | 12 +++++++++--
+ stdlib/tst-realpath-toolong.c | 49 +++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 65 insertions(+), 2 deletions(-)
+ create mode 100644 stdlib/tst-realpath-toolong.c
+
+diff --git a/NEWS b/NEWS
+index 711420cb..db50b2af 100644
+--- a/NEWS
++++ b/NEWS
+@@ -17,8 +17,14 @@ Security related changes:
+ CVE-2022-23218: Passing an overlong file name to the svcunix_create
+ legacy function could result in a stack-based buffer overflow.
+
++ CVE-2021-3998: Passing a path longer than PATH_MAX to the realpath
++ function could result in a memory leak and potential access of
++ uninitialized memory. Reported by Qualys.
++
+ The following bugs are resolved with this release:
+
++ [12889] nptl: Fix race between pthread_kill and thread exit
++ [19193] nptl: pthread_kill, pthread_cancel should not fail after exit
+ [22542] CVE-2022-23219: Buffer overflow in sunrpc clnt_create for "unix"
+
+
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index 9bb5c221..a4ac30d1 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -109,6 +109,7 @@ tests := \
+ tst-random \
+ tst-random2 \
+ tst-realpath \
++ tst-realpath-toolong \
+ tst-secure-getenv \
+ tst-setcontext \
+ tst-setcontext2 \
+diff --git a/stdlib/canonicalize.c b/stdlib/canonicalize.c
+index 698f9ede..7a23a51b 100644
+--- a/stdlib/canonicalize.c
++++ b/stdlib/canonicalize.c
+@@ -400,8 +400,16 @@ realpath_stk (const char *name, char *resolved,
+
+ error:
+ *dest++ = '\0';
+- if (resolved != NULL && dest - rname <= get_path_max ())
+- rname = strcpy (resolved, rname);
++ if (resolved != NULL)
++ {
++ if (dest - rname <= get_path_max ())
++ rname = strcpy (resolved, rname);
++ else
++ {
++ failed = true;
++ __set_errno (ENAMETOOLONG);
++ }
++ }
+
+ error_nomem:
+ scratch_buffer_free (&extra_buffer);
+diff --git a/stdlib/tst-realpath-toolong.c b/stdlib/tst-realpath-toolong.c
+new file mode 100644
+index 00000000..8bed7724
+--- /dev/null
++++ b/stdlib/tst-realpath-toolong.c
+@@ -0,0 +1,49 @@
++/* Verify that realpath returns NULL with ENAMETOOLONG if the result exceeds
++ NAME_MAX.
++ Copyright The GNU Toolchain Authors.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <limits.h>
++#include <stdlib.h>
++#include <string.h>
++#include <unistd.h>
++#include <support/check.h>
++#include <support/temp_file.h>
++#include <sys/types.h>
++#include <sys/stat.h>
++
++#define BASENAME "tst-realpath-toolong."
++
++int
++do_test (void)
++{
++ char *base = support_create_and_chdir_toolong_temp_directory (BASENAME);
++
++ char buf[PATH_MAX + 1];
++ const char *res = realpath (".", buf);
++
++ /* canonicalize.c states that if the real path is >= PATH_MAX, then
++ realpath returns NULL and sets ENAMETOOLONG. */
++ TEST_VERIFY (res == NULL);
++ TEST_VERIFY (errno == ENAMETOOLONG);
++
++ free (base);
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+2.27.0
+
diff --git a/replace_same_file_to_hard_link.py b/replace_same_file_to_hard_link.py
new file mode 100644
index 0000000..12829f0
--- /dev/null
+++ b/replace_same_file_to_hard_link.py
@@ -0,0 +1,98 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+function: This script resolves locales's BEP inconsistence,
+ it scans a specific path and replaces the same file
+ in that path with a hard link.Avoid different language
+ packs each time due to concurrent compilation.
+"""
+import os
+import sys
+import time
+
+all_file = {}
+
+def cmp_file(f1, f2):
+ """compare two files in bytes"""
+ st1 = os.stat(f1)
+ st2 = os.stat(f2)
+
+ bufsize = 8 * 1024
+ with open(f1, 'rb') as fp1, open(f2, 'rb') as fp2:
+ while True:
+ b1 = fp1.read(bufsize)
+ b2 = fp2.read(bufsize)
+ if b1 != b2:
+ return False
+ if not b1:
+ return True
+
+
+def search_all_inode(dir_path):
+ """recursively traverse the directory to group all"""
+ files = os.listdir(dir_path)
+
+ for fi in files:
+ fi_d = os.path.join(dir_path, fi)
+ if os.path.isdir(fi_d):
+ search_all_inode(fi_d)
+ else:
+ size = os.stat(fi_d).st_size
+ if size in all_file:
+ all_file[size].append(fi_d)
+ else:
+ all_file[size] = [fi_d]
+
+
+def deal_one(file_paths):
+ """traverse the file array, delete the same file and create a hard link"""
+ file_count = len(file_paths)
+ inode_files = {}
+
+ for i in range(0, file_count):
+ for j in range(i + 1, file_count):
+ file1 = file_paths[i]
+ file2 = file_paths[j]
+
+ file1_inode = os.stat(file1).st_ino
+ file2_inode = os.stat(file2).st_ino
+
+ if file1_inode not in inode_files:
+ inode_files[file1_inode] = file1
+
+ if file1_inode == file2_inode:
+ continue
+
+ if cmp_file(file1, file2):
+ print('deal same file:', file1, '==', file2)
+ os.remove(file2)
+ os.link(file1, file2)
+ else:
+ if file2_inode not in inode_files:
+ inode_files[file2_inode] = file2
+
+
+def deal_files():
+ """get file array and processed one by one"""
+ for size in all_file:
+ file_paths = all_file[size]
+ if len(file_paths) > 1:
+ deal_one(file_paths)
+
+
+def usage():
+ """print usage"""
+ print("""
+rm_same_file: Replace the same file with a hard link.
+
+rm_same_file.py [target path]
+
+ """)
+
+if __name__ == "__main__":
+ if len(sys.argv) == 2:
+ search_all_inode(sys.argv[1])
+ deal_files()
+ else:
+ usage()
+ sys.exit()
diff --git a/riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch b/riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch
new file mode 100644
index 0000000..a45f186
--- /dev/null
+++ b/riscv-Drop-reliance-on-_GLOBAL_OFFSET_TABLE_-0.patch
@@ -0,0 +1,60 @@
+From 34b4624b04fc8f038b2c329ca7560197320615b4 Mon Sep 17 00:00:00 2001
+From: Fangrui Song <maskray@google.com>
+Date: Wed, 18 Aug 2021 10:01:31 -0700
+Subject: [PATCH] riscv: Drop reliance on _GLOBAL_OFFSET_TABLE_[0]
+
+&__ehdr_start is a better way to get the load address.
+
+This is similar to commits b37b75d269883a2c553bb7019a813094eb4e2dd1
+(x86-64) and 43d06ed218fc8be58987bdfd00e21e5720f0b862 (aarch64).
+
+Reviewed-by: Palmer Dabbelt <palmerdabbelt@google.com>
+---
+ sysdeps/riscv/dl-machine.h | 21 ++++++++++-----------
+ 1 file changed, 10 insertions(+), 11 deletions(-)
+
+diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h
+index aedf69f..5b07461 100644
+--- a/sysdeps/riscv/dl-machine.h
++++ b/sysdeps/riscv/dl-machine.h
+@@ -76,27 +76,26 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
+ return 1;
+ }
+
++/* Return the run-time load address of the shared object. */
++static inline ElfW(Addr)
++elf_machine_load_address (void)
++{
++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
++ return (ElfW(Addr)) &__ehdr_start;
++}
++
+ /* Return the link-time address of _DYNAMIC. */
+ static inline ElfW(Addr)
+ elf_machine_dynamic (void)
+ {
+- extern ElfW(Addr) _GLOBAL_OFFSET_TABLE_ __attribute__ ((visibility ("hidden")));
+- return _GLOBAL_OFFSET_TABLE_;
++ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
+ }
+
+ #define STRINGXP(X) __STRING (X)
+ #define STRINGXV(X) STRINGV_ (X)
+ #define STRINGV_(...) # __VA_ARGS__
+
+-/* Return the run-time load address of the shared object. */
+-static inline ElfW(Addr)
+-elf_machine_load_address (void)
+-{
+- ElfW(Addr) load_addr;
+- asm ("lla %0, _DYNAMIC" : "=r" (load_addr));
+- return load_addr - elf_machine_dynamic ();
+-}
+-
+ /* Initial entry point code for the dynamic linker.
+ The C function `_dl_start' is the real entry point;
+ its return value is the user program's entry point. */
+--
+1.8.3.1
+
diff --git a/riscv-align-stack-in-clone-BZ-28702.patch b/riscv-align-stack-in-clone-BZ-28702.patch
new file mode 100644
index 0000000..866e409
--- /dev/null
+++ b/riscv-align-stack-in-clone-BZ-28702.patch
@@ -0,0 +1,35 @@
+From d2e594d71509faf36cf851a69370db34a4f5fa65 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Tue, 14 Dec 2021 22:44:35 +0100
+Subject: [PATCH] riscv: align stack in clone [BZ #28702]
+
+The RISC-V ABI [1] mandates that "the stack pointer shall be aligned to
+a 128-bit boundary upon procedure entry". This as not the case in clone.
+
+This fixes the misc/tst-misalign-clone-internal and
+misc/tst-misalign-clone tests.
+
+Fixes bug 28702.
+
+[1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc
+---
+ sysdeps/unix/sysv/linux/riscv/clone.S | 3 +++
+ 1 file changed, 3 insertions(+)
+
+diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S
+index 12f91a20d3..161e83c7e3 100644
+--- a/sysdeps/unix/sysv/linux/riscv/clone.S
++++ b/sysdeps/unix/sysv/linux/riscv/clone.S
+@@ -32,6 +32,9 @@
+ .text
+ LEAF (__clone)
+
++ /* Align stack to a 128-bit boundary as per RISC-V ABI. */
++ andi a1,a1,ALMASK
++
+ /* Sanity check arguments. */
+ beqz a0,L (invalid) /* No NULL function pointers. */
+ beqz a1,L (invalid) /* No NULL stack pointers. */
+--
+2.39.2
+
diff --git a/rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch b/rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch
new file mode 100644
index 0000000..1485892
--- /dev/null
+++ b/rseq-Linux-Use-ptrdiff_t-for-__rseq_offset.patch
@@ -0,0 +1,197 @@
+From 6cb5cc084432eba1f2215ec7c9816b748c32182a Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Wed, 2 Feb 2022 22:37:20 +0100
+Subject: [PATCH 9/9] Linux: Use ptrdiff_t for __rseq_offset
+
+This matches the data size initial-exec relocations use on most
+targets.
+
+Reviewed-by: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ manual/threads.texi | 2 +-
+ sysdeps/nptl/dl-tls_init_tp.c | 4 ++--
+ sysdeps/unix/sysv/linux/aarch64/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/alpha/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/ia64/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist | 2 +-
+ sysdeps/unix/sysv/linux/sys/rseq.h | 3 ++-
+ sysdeps/unix/sysv/linux/x86_64/64/ld.abilist | 2 +-
+ 13 files changed, 15 insertions(+), 14 deletions(-)
+
+diff --git a/manual/threads.texi b/manual/threads.texi
+index ab44a92c..4b9fc946 100644
+--- a/manual/threads.texi
++++ b/manual/threads.texi
+@@ -1004,7 +1004,7 @@ The manual for the @code{rseq} system call can be found
+ at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}.
+ @end deftp
+
+-@deftypevar {int} __rseq_offset
++@deftypevar {ptrdiff_t} __rseq_offset
+ @standards{Linux, sys/rseq.h}
+ This variable contains the offset between the thread pointer (as defined
+ by @code{__builtin_thread_pointer} or the thread pointer register for
+diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
+index 4a73927f..86e87c7d 100644
+--- a/sysdeps/nptl/dl-tls_init_tp.c
++++ b/sysdeps/nptl/dl-tls_init_tp.c
+@@ -46,7 +46,7 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
+
+ const unsigned int __rseq_flags;
+ const unsigned int __rseq_size attribute_relro;
+-const int __rseq_offset attribute_relro;
++const ptrdiff_t __rseq_offset attribute_relro;
+
+ void
+ __tls_pre_init_tp (void)
+@@ -119,7 +119,7 @@ __tls_init_tp (void)
+ all targets support __thread_pointer, so set __rseq_offset only
+ if thre rseq registration may have happened because RSEQ_SIG is
+ defined. */
+- extern int offset __asm__ ("__rseq_offset");
++ extern ptrdiff_t offset __asm__ ("__rseq_offset");
+ offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
+ #endif
+ }
+diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+index bf4d4f9b..5151c078 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+@@ -5,5 +5,5 @@ GLIBC_2.17 _dl_mcount F
+ GLIBC_2.17 _r_debug D 0x28
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist
+index a23325a5..3e296c54 100644
+--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist
++++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist
+@@ -4,6 +4,6 @@ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x8
+diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist
+index 8ccb5be9..5471b24d 100644
+--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist
+@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+index 37a47ebc..f26e594a 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+@@ -4,6 +4,6 @@ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x8
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+index da24dc7f..21f472e6 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+@@ -6,5 +6,5 @@ GLIBC_2.3 _dl_mcount F
+ GLIBC_2.3 _r_debug D 0x28
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+index b9ae89ae..9c9c4045 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+@@ -6,5 +6,5 @@ GLIBC_2.22 __tls_get_addr_opt F
+ GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+index 48431c91..a7758a0e 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+@@ -5,5 +5,5 @@ GLIBC_2.27 _dl_mcount F
+ GLIBC_2.27 _r_debug D 0x28
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+index 117d1430..78d07160 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_offset F
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+index 8ccb5be9..5471b24d 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+@@ -4,5 +4,5 @@ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
+index 1215b5d0..791ed831 100644
+--- a/sysdeps/unix/sysv/linux/sys/rseq.h
++++ b/sysdeps/unix/sysv/linux/sys/rseq.h
+@@ -21,6 +21,7 @@
+ /* Architecture-specific rseq signature. */
+ #include <bits/rseq.h>
+
++#include <stddef.h>
+ #include <stdint.h>
+ #include <sys/cdefs.h>
+ #include <bits/endian.h>
+@@ -172,7 +173,7 @@ struct rseq
+ #endif /* __GLIBC_HAVE_KERNEL_RSEQ */
+
+ /* Offset from the thread pointer to the rseq area. */
+-extern const int __rseq_offset;
++extern const ptrdiff_t __rseq_offset;
+
+ /* Size of the registered rseq area. 0 if the registration was
+ unsuccessful. */
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+index ae622bdf..5a8bd322 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+@@ -4,5 +4,5 @@ GLIBC_2.2.5 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
+ GLIBC_2.35 __rseq_flags D 0x4
+-GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_offset D 0x8
+ GLIBC_2.35 __rseq_size D 0x4
+--
+2.23.0
+
diff --git a/rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch b/rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch
new file mode 100644
index 0000000..3e7548c
--- /dev/null
+++ b/rseq-Linux-Use-rseq-to-accelerate-sched_getcpu.patch
@@ -0,0 +1,48 @@
+From 00bae0eb5212a1ec4e8b4b90294937903628e7ce Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 9 Dec 2021 09:49:32 +0100
+Subject: [PATCH 5/9] Linux: Use rseq to accelerate sched_getcpu
+
+Co-Authored-By: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/unix/sysv/linux/sched_getcpu.c | 19 +++++++++++++++++--
+ 1 file changed, 17 insertions(+), 2 deletions(-)
+
+diff --git a/sysdeps/unix/sysv/linux/sched_getcpu.c b/sysdeps/unix/sysv/linux/sched_getcpu.c
+index c41e986f..6f78edae 100644
+--- a/sysdeps/unix/sysv/linux/sched_getcpu.c
++++ b/sysdeps/unix/sysv/linux/sched_getcpu.c
+@@ -20,8 +20,8 @@
+ #include <sysdep.h>
+ #include <sysdep-vdso.h>
+
+-int
+-sched_getcpu (void)
++static int
++vsyscall_sched_getcpu (void)
+ {
+ unsigned int cpu;
+ int r = -1;
+@@ -32,3 +32,18 @@ sched_getcpu (void)
+ #endif
+ return r == -1 ? r : cpu;
+ }
++
++#ifdef RSEQ_SIG
++int
++sched_getcpu (void)
++{
++ int cpu_id = THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id);
++ return __glibc_likely (cpu_id >= 0) ? cpu_id : vsyscall_sched_getcpu ();
++}
++#else /* RSEQ_SIG */
++int
++sched_getcpu (void)
++{
++ return vsyscall_sched_getcpu ();
++}
++#endif /* RSEQ_SIG */
+--
+2.23.0
+
diff --git a/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch b/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch
new file mode 100644
index 0000000..8e5675d
--- /dev/null
+++ b/rseq-nptl-Add-glibc.pthread.rseq-tunable-to-control-rseq-.patch
@@ -0,0 +1,300 @@
+From ff1e1631665651ceb8b4b226ec725140c7420e8c Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 9 Dec 2021 09:49:32 +0100
+Subject: [PATCH 6/9] nptl: Add glibc.pthread.rseq tunable to control rseq
+ registration
+
+This tunable allows applications to register the rseq area instead
+of glibc.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+-----
+change:
+Since rseq is a big feature and have changed code behavior quite a lot,
+disable rseq by default to reduce potential conflicts.
+
+sysdeps/nptl/dl-tunables.list:
+ default: 1 -> default: 0
+
+---
+ manual/tunables.texi | 10 +++
+ nptl/pthread_create.c | 10 ++-
+ sysdeps/nptl/dl-tls_init_tp.c | 11 ++-
+ sysdeps/nptl/dl-tunables.list | 6 ++
+ sysdeps/nptl/internaltypes.h | 1 +
+ sysdeps/unix/sysv/linux/Makefile | 8 ++
+ sysdeps/unix/sysv/linux/rseq-internal.h | 19 +++--
+ sysdeps/unix/sysv/linux/tst-rseq-disable.c | 89 ++++++++++++++++++++++
+ 8 files changed, 145 insertions(+), 9 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-disable.c
+
+diff --git a/manual/tunables.texi b/manual/tunables.texi
+index 658547c6..1f5c4102 100644
+--- a/manual/tunables.texi
++++ b/manual/tunables.texi
+@@ -413,6 +413,16 @@ The value is measured in bytes. The default is @samp{41943040}
+ (fourty mibibytes).
+ @end deftp
+
++@deftp Tunable glibc.pthread.rseq
++The @code{glibc.pthread.rseq} tunable can be set to @samp{0}, to disable
++restartable sequences support in @theglibc{}. This enables applications
++to perform direct restartable sequence registration with the kernel.
++The default is @samp{1}, which means that @theglibc{} performs
++registration on behalf of the application.
++
++Restartable sequences are a Linux-specific extension.
++@end deftp
++
+ @node Hardware Capability Tunables
+ @section Hardware Capability Tunables
+ @cindex hardware capability tunables
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index d2b40924..f405fa35 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -369,7 +369,10 @@ start_thread (void *arg)
+ __ctype_init ();
+
+ /* Register rseq TLS to the kernel. */
+- rseq_register_current_thread (pd);
++ {
++ bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ;
++ rseq_register_current_thread (pd, do_rseq);
++ }
+
+ #ifndef __ASSUME_SET_ROBUST_LIST
+ if (__nptl_set_robust_list_avail)
+@@ -678,6 +681,11 @@ __pthread_create_2_1 (pthread_t *newthread, const pthread_attr_t *attr,
+ pd->flags = ((iattr->flags & ~(ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET))
+ | (self->flags & (ATTR_FLAG_SCHED_SET | ATTR_FLAG_POLICY_SET)));
+
++ /* Inherit rseq registration state. Without seccomp filters, rseq
++ registration will either always fail or always succeed. */
++ if ((int) THREAD_GETMEM_VOLATILE (self, rseq_area.cpu_id) >= 0)
++ pd->flags |= ATTR_FLAG_DO_RSEQ;
++
+ /* Initialize the field for the ID of the thread which is waiting
+ for us. This is a self-reference in case the thread is created
+ detached. */
+diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
+index fedb876f..b39dfbff 100644
+--- a/sysdeps/nptl/dl-tls_init_tp.c
++++ b/sysdeps/nptl/dl-tls_init_tp.c
+@@ -23,6 +23,9 @@
+ #include <tls.h>
+ #include <rseq-internal.h>
+
++#define TUNABLE_NAMESPACE pthread
++#include <dl-tunables.h>
++
+ #ifndef __ASSUME_SET_ROBUST_LIST
+ bool __nptl_set_robust_list_avail;
+ rtld_hidden_data_def (__nptl_set_robust_list_avail)
+@@ -92,7 +95,13 @@ __tls_init_tp (void)
+ }
+ }
+
+- rseq_register_current_thread (pd);
++ {
++ bool do_rseq = true;
++#if HAVE_TUNABLES
++ do_rseq = TUNABLE_GET (rseq, int, NULL);
++#endif
++ rseq_register_current_thread (pd, do_rseq);
++ }
+
+ /* Set initial thread's stack block from 0 up to __libc_stack_end.
+ It will be bigger than it actually is, but for unwind.c/pt-longjmp.c
+diff --git a/sysdeps/nptl/dl-tunables.list b/sysdeps/nptl/dl-tunables.list
+index ac5d0532..d24f4be0 100644
+--- a/sysdeps/nptl/dl-tunables.list
++++ b/sysdeps/nptl/dl-tunables.list
+@@ -27,5 +27,11 @@ glibc {
+ type: SIZE_T
+ default: 41943040
+ }
++ rseq {
++ type: INT_32
++ minval: 0
++ maxval: 1
++ default: 0
++ }
+ }
+ }
+diff --git a/sysdeps/nptl/internaltypes.h b/sysdeps/nptl/internaltypes.h
+index 50a2ad19..8205c6d1 100644
+--- a/sysdeps/nptl/internaltypes.h
++++ b/sysdeps/nptl/internaltypes.h
+@@ -49,6 +49,7 @@ struct pthread_attr
+ #define ATTR_FLAG_OLDATTR 0x0010
+ #define ATTR_FLAG_SCHED_SET 0x0020
+ #define ATTR_FLAG_POLICY_SET 0x0040
++#define ATTR_FLAG_DO_RSEQ 0x0080
+
+ /* Used to allocate a pthread_attr_t object which is also accessed
+ internally. */
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index f103a964..0657f400 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -135,6 +135,12 @@ tests-internal += \
+ tst-sigcontext-get_pc \
+ # tests-internal
+
++ifneq (no,$(have-tunables))
++tests-internal += \
++ tst-rseq-disable \
++ # tests-internal $(have-tunables)
++endif
++
+ tests-time64 += \
+ tst-adjtimex-time64 \
+ tst-clock_adjtime-time64 \
+@@ -226,6 +232,8 @@ $(objpfx)tst-mman-consts.out: ../sysdeps/unix/sysv/linux/tst-mman-consts.py
+ < /dev/null > $@ 2>&1; $(evaluate-test)
+ $(objpfx)tst-mman-consts.out: $(sysdeps-linux-python-deps)
+
++tst-rseq-disable-ENV = GLIBC_TUNABLES=glibc.pthread.rseq=0
++
+ endif # $(subdir) == misc
+
+ ifeq ($(subdir),time)
+diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
+index 909f5478..15bc7ffd 100644
+--- a/sysdeps/unix/sysv/linux/rseq-internal.h
++++ b/sysdeps/unix/sysv/linux/rseq-internal.h
+@@ -21,22 +21,27 @@
+ #include <sysdep.h>
+ #include <errno.h>
+ #include <kernel-features.h>
++#include <stdbool.h>
+ #include <stdio.h>
+ #include <sys/rseq.h>
+
+ #ifdef RSEQ_SIG
+ static inline void
+-rseq_register_current_thread (struct pthread *self)
++rseq_register_current_thread (struct pthread *self, bool do_rseq)
+ {
+- int ret = INTERNAL_SYSCALL_CALL (rseq,
+- &self->rseq_area, sizeof (self->rseq_area),
+- 0, RSEQ_SIG);
+- if (INTERNAL_SYSCALL_ERROR_P (ret))
+- THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
++ if (do_rseq)
++ {
++ int ret = INTERNAL_SYSCALL_CALL (rseq, &self->rseq_area,
++ sizeof (self->rseq_area),
++ 0, RSEQ_SIG);
++ if (!INTERNAL_SYSCALL_ERROR_P (ret))
++ return;
++ }
++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
+ }
+ #else /* RSEQ_SIG */
+ static inline void
+-rseq_register_current_thread (struct pthread *self)
++rseq_register_current_thread (struct pthread *self, bool do_rseq)
+ {
+ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
+ }
+diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
+new file mode 100644
+index 00000000..000e3518
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
+@@ -0,0 +1,89 @@
++/* Test disabling of rseq registration via tunable.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <stdio.h>
++#include <support/check.h>
++#include <support/namespace.h>
++#include <support/xthread.h>
++#include <sysdep.h>
++#include <unistd.h>
++
++#ifdef RSEQ_SIG
++
++/* Check that rseq can be registered and has not been taken by glibc. */
++static void
++check_rseq_disabled (void)
++{
++ struct pthread *pd = THREAD_SELF;
++ TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
++
++ int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area),
++ 0, RSEQ_SIG);
++ if (ret == 0)
++ {
++ ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area),
++ RSEQ_FLAG_UNREGISTER, RSEQ_SIG);
++ TEST_COMPARE (ret, 0);
++ pd->rseq_area.cpu_id = RSEQ_CPU_ID_REGISTRATION_FAILED;
++ }
++ else
++ {
++ TEST_VERIFY (errno != -EINVAL);
++ TEST_VERIFY (errno != -EBUSY);
++ }
++}
++
++static void *
++thread_func (void *ignored)
++{
++ check_rseq_disabled ();
++ return NULL;
++}
++
++static void
++proc_func (void *ignored)
++{
++ check_rseq_disabled ();
++}
++
++static int
++do_test (void)
++{
++ puts ("info: checking main thread");
++ check_rseq_disabled ();
++
++ puts ("info: checking main thread (2)");
++ check_rseq_disabled ();
++
++ puts ("info: checking new thread");
++ xpthread_join (xpthread_create (NULL, thread_func, NULL));
++
++ puts ("info: checking subprocess");
++ support_isolate_in_subprocess (proc_func, NULL);
++
++ return 0;
++}
++#else /* !RSEQ_SIG */
++static int
++do_test (void)
++{
++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test");
++}
++#endif
++
++#include <support/test-driver.c>
+--
+2.23.0
+
diff --git a/rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch b/rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch
new file mode 100644
index 0000000..f4311c5
--- /dev/null
+++ b/rseq-nptl-Add-public-rseq-symbols-and-sys-rseq.h.patch
@@ -0,0 +1,692 @@
+From e3291e074ff67a8cc2630ab6175976f875d61a14 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 17 Feb 2022 14:56:12 +0800
+Subject: [PATCH 7/9] nptl: Add public rseq symbols and <sys/rseq.h>
+
+The relationship between the thread pointer and the rseq area
+is made explicit. The constant offset can be used by JIT compilers
+to optimize rseq access (e.g., for really fast sched_getcpu).
+
+Extensibility is provided through __rseq_size and __rseq_flags.
+(In the future, the kernel could request a different rseq size
+via the auxiliary vector.)
+
+Co-Authored-By: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+-----
+conflicts:
+ context conflicts
+---
+ NEWS | 11 +++
+ manual/threads.texi | 81 +++++++++++++++++++
+ sysdeps/nptl/dl-tls_init_tp.c | 23 +++++-
+ sysdeps/unix/sysv/linux/Makefile | 3 +-
+ sysdeps/unix/sysv/linux/Versions | 5 ++
+ sysdeps/unix/sysv/linux/aarch64/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/alpha/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/arc/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/arm/be/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/arm/le/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/csky/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/hppa/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/i386/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/ia64/ld.abilist | 3 +
+ .../unix/sysv/linux/m68k/coldfire/ld.abilist | 3 +
+ .../unix/sysv/linux/m68k/m680x0/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/microblaze/ld.abilist | 3 +
+ .../unix/sysv/linux/mips/mips32/ld.abilist | 3 +
+ .../sysv/linux/mips/mips64/n32/ld.abilist | 3 +
+ .../sysv/linux/mips/mips64/n64/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/nios2/ld.abilist | 3 +
+ .../sysv/linux/powerpc/powerpc32/ld.abilist | 3 +
+ .../linux/powerpc/powerpc64/be/ld.abilist | 3 +
+ .../linux/powerpc/powerpc64/le/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/rseq-internal.h | 8 +-
+ .../unix/sysv/linux/s390/s390-32/ld.abilist | 3 +
+ .../unix/sysv/linux/s390/s390-64/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/sh/be/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/sh/le/ld.abilist | 3 +
+ .../unix/sysv/linux/sparc/sparc32/ld.abilist | 3 +
+ .../unix/sysv/linux/sparc/sparc64/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/sys/rseq.h | 10 +++
+ sysdeps/unix/sysv/linux/tst-rseq-disable.c | 6 ++
+ sysdeps/unix/sysv/linux/tst-rseq.c | 8 ++
+ sysdeps/unix/sysv/linux/x86_64/64/ld.abilist | 3 +
+ sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist | 3 +
+ 38 files changed, 237 insertions(+), 5 deletions(-)
+
+diff --git a/NEWS b/NEWS
+index ffae154a..1b0ee549 100644
+--- a/NEWS
++++ b/NEWS
+@@ -129,6 +129,17 @@ Major new features:
+ than or equal to a given integer. This function is a GNU extension,
+ although Solaris also provides a similar function.
+
++* Support for automatically registering threads with the Linux rseq
++ system call has been added. This system call is implemented starting
++ from Linux 4.18. The Restartable Sequences ABI accelerates user-space
++ operations on per-cpu data. It allows user-space to perform updates
++ on per-cpu data without requiring heavy-weight atomic operations.
++ Automatically registering threads allows all libraries, including
++ libc, to make immediate use of the rseq support by using the
++ documented ABI, via the __rseq_flags, __rseq_offset, and __rseq_size
++ variables. The GNU C Library manual has details on integration of
++ Restartable Sequences.
++
+ Deprecated and removed features, and other changes affecting compatibility:
+
+ * The function pthread_mutex_consistent_np has been deprecated; programs
+diff --git a/manual/threads.texi b/manual/threads.texi
+index 06b6b277..ab44a92c 100644
+--- a/manual/threads.texi
++++ b/manual/threads.texi
+@@ -629,6 +629,8 @@ the standard.
+ * Waiting with Explicit Clocks:: Functions for waiting with an
+ explicit clock specification.
+ * Single-Threaded:: Detecting single-threaded execution.
++* Restartable Sequences:: Linux-specific restartable sequences
++ integration.
+ @end menu
+
+ @node Default Thread Attributes
+@@ -958,6 +960,85 @@ application-created thread because future versions of @theglibc{} may
+ create background threads after the first thread has been created, and
+ the application has no way of knowning that these threads are present.
+
++@node Restartable Sequences
++@subsubsection Restartable Sequences
++
++This section describes restartable sequences integration for
++@theglibc{}. This functionality is only available on Linux.
++
++@deftp {Data Type} {struct rseq}
++@standards{Linux, sys/rseq.h}
++The type of the restartable sequences area. Future versions
++of Linux may add additional fields to the end of this structure.
++
++
++Users need to obtain the address of the restartable sequences area using
++the thread pointer and the @code{__rseq_offset} variable, described
++below.
++
++One use of the restartable sequences area is to read the current CPU
++number from its @code{cpu_id} field, as an inline version of
++@code{sched_getcpu}. @Theglibc{} sets the @code{cpu_id} field to
++@code{RSEQ_CPU_ID_REGISTRATION_FAILED} if registration failed or was
++explicitly disabled.
++
++Furthermore, users can store the address of a @code{struct rseq_cs}
++object into the @code{rseq_cs} field of @code{struct rseq}, thus
++informing the kernel that the thread enters a restartable sequence
++critical section. This pointer and the code areas it itself points to
++must not be left pointing to memory areas which are freed or re-used.
++Several approaches can guarantee this. If the application or library
++can guarantee that the memory used to hold the @code{struct rseq_cs} and
++the code areas it refers to are never freed or re-used, no special
++action must be taken. Else, before that memory is re-used of freed, the
++application is responsible for setting the @code{rseq_cs} field to
++@code{NULL} in each thread's restartable sequence area to guarantee that
++it does not leak dangling references. Because the application does not
++typically have knowledge of libraries' use of restartable sequences, it
++is recommended that libraries using restartable sequences which may end
++up freeing or re-using their memory set the @code{rseq_cs} field to
++@code{NULL} before returning from library functions which use
++restartable sequences.
++
++The manual for the @code{rseq} system call can be found
++at @uref{https://git.kernel.org/pub/scm/libs/librseq/librseq.git/tree/doc/man/rseq.2}.
++@end deftp
++
++@deftypevar {int} __rseq_offset
++@standards{Linux, sys/rseq.h}
++This variable contains the offset between the thread pointer (as defined
++by @code{__builtin_thread_pointer} or the thread pointer register for
++the architecture) and the restartable sequences area. This value is the
++same for all threads in the process. If the restartable sequences area
++is located at a lower address than the location to which the thread
++pointer points, the value is negative.
++@end deftypevar
++
++@deftypevar {unsigned int} __rseq_size
++@standards{Linux, sys/rseq.h}
++This variable is either zero (if restartable sequence registration
++failed or has been disabled) or the size of the restartable sequence
++registration. This can be different from the size of @code{struct rseq}
++if the kernel has extended the size of the registration. If
++registration is successful, @code{__rseq_size} is at least 32 (the
++initial size of @code{struct rseq}).
++@end deftypevar
++
++@deftypevar {unsigned int} __rseq_flags
++@standards{Linux, sys/rseq.h}
++The flags used during restartable sequence registration with the kernel.
++Currently zero.
++@end deftypevar
++
++@deftypevr Macro int RSEQ_SIG
++@standards{Linux, sys/rseq.h}
++Each supported architecture provides a @code{RSEQ_SIG} macro in
++@file{sys/rseq.h} which contains a signature. That signature is
++expected to be present in the code before each restartable sequences
++abort handler. Failure to provide the expected signature may terminate
++the process with a segmentation fault.
++@end deftypevr
++
+ @c FIXME these are undocumented:
+ @c pthread_atfork
+ @c pthread_attr_destroy
+diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
+index b39dfbff..4a73927f 100644
+--- a/sysdeps/nptl/dl-tls_init_tp.c
++++ b/sysdeps/nptl/dl-tls_init_tp.c
+@@ -22,6 +22,7 @@
+ #include <pthreadP.h>
+ #include <tls.h>
+ #include <rseq-internal.h>
++#include <thread_pointer.h>
+
+ #define TUNABLE_NAMESPACE pthread
+ #include <dl-tunables.h>
+@@ -43,6 +44,10 @@ rtld_mutex_dummy (pthread_mutex_t *lock)
+ }
+ #endif
+
++const unsigned int __rseq_flags;
++const unsigned int __rseq_size attribute_relro;
++const int __rseq_offset attribute_relro;
++
+ void
+ __tls_pre_init_tp (void)
+ {
+@@ -100,7 +105,23 @@ __tls_init_tp (void)
+ #if HAVE_TUNABLES
+ do_rseq = TUNABLE_GET (rseq, int, NULL);
+ #endif
+- rseq_register_current_thread (pd, do_rseq);
++ if (rseq_register_current_thread (pd, do_rseq))
++ {
++ /* We need a writable view of the variables. They are in
++ .data.relro and are not yet write-protected. */
++ extern unsigned int size __asm__ ("__rseq_size");
++ size = sizeof (pd->rseq_area);
++ }
++
++#ifdef RSEQ_SIG
++ /* This should be a compile-time constant, but the current
++ infrastructure makes it difficult to determine its value. Not
++ all targets support __thread_pointer, so set __rseq_offset only
++ if thre rseq registration may have happened because RSEQ_SIG is
++ defined. */
++ extern int offset __asm__ ("__rseq_offset");
++ offset = (char *) &pd->rseq_area - (char *) __thread_pointer ();
++#endif
+ }
+
+ /* Set initial thread's stack block from 0 up to __libc_stack_end.
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index 0657f400..856a9d58 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -110,7 +110,8 @@ sysdep_headers += sys/mount.h sys/acct.h \
+ bits/types/struct_semid64_ds_helper.h \
+ bits/types/struct_shmid64_ds.h \
+ bits/types/struct_shmid64_ds_helper.h \
+- bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h
++ bits/pthread_stack_min.h bits/pthread_stack_min-dynamic.h \
++ sys/rseq.h bits/rseq.h
+
+ tests += tst-clone tst-clone2 tst-clone3 tst-fanotify tst-personality \
+ tst-quota tst-sync_file_range tst-sysconf-iov_max tst-ttyname \
+diff --git a/sysdeps/unix/sysv/linux/Versions b/sysdeps/unix/sysv/linux/Versions
+index 26452f3f..3f8809a1 100644
+--- a/sysdeps/unix/sysv/linux/Versions
++++ b/sysdeps/unix/sysv/linux/Versions
+@@ -316,6 +316,11 @@ librt {
+ }
+
+ ld {
++ GLIBC_2.35 {
++ __rseq_flags;
++ __rseq_offset;
++ __rseq_size;
++ }
+ GLIBC_PRIVATE {
+ __nptl_change_stack_perm;
+ }
+diff --git a/sysdeps/unix/sysv/linux/aarch64/ld.abilist b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+index b7196a80..bf4d4f9b 100644
+--- a/sysdeps/unix/sysv/linux/aarch64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/aarch64/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.17 __tls_get_addr F
+ GLIBC_2.17 _dl_mcount F
+ GLIBC_2.17 _r_debug D 0x28
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/alpha/ld.abilist b/sysdeps/unix/sysv/linux/alpha/ld.abilist
+index 13f7fc74..a23325a5 100644
+--- a/sysdeps/unix/sysv/linux/alpha/ld.abilist
++++ b/sysdeps/unix/sysv/linux/alpha/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x8
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x8
+diff --git a/sysdeps/unix/sysv/linux/arc/ld.abilist b/sysdeps/unix/sysv/linux/arc/ld.abilist
+index 7284383a..55f0c2ab 100644
+--- a/sysdeps/unix/sysv/linux/arc/ld.abilist
++++ b/sysdeps/unix/sysv/linux/arc/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.32 __tls_get_addr F
+ GLIBC_2.32 _dl_mcount F
+ GLIBC_2.32 _r_debug D 0x14
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/arm/be/ld.abilist b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
+index 7987bbae..f1da2c63 100644
+--- a/sysdeps/unix/sysv/linux/arm/be/ld.abilist
++++ b/sysdeps/unix/sysv/linux/arm/be/ld.abilist
+@@ -1,4 +1,7 @@
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __libc_stack_end D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+ GLIBC_2.4 __tls_get_addr F
+diff --git a/sysdeps/unix/sysv/linux/arm/le/ld.abilist b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
+index 7987bbae..f1da2c63 100644
+--- a/sysdeps/unix/sysv/linux/arm/le/ld.abilist
++++ b/sysdeps/unix/sysv/linux/arm/le/ld.abilist
+@@ -1,4 +1,7 @@
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __libc_stack_end D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+ GLIBC_2.4 __tls_get_addr F
+diff --git a/sysdeps/unix/sysv/linux/csky/ld.abilist b/sysdeps/unix/sysv/linux/csky/ld.abilist
+index 4939b206..7f482276 100644
+--- a/sysdeps/unix/sysv/linux/csky/ld.abilist
++++ b/sysdeps/unix/sysv/linux/csky/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.29 __tls_get_addr F
+ GLIBC_2.29 _dl_mcount F
+ GLIBC_2.29 _r_debug D 0x14
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/hppa/ld.abilist b/sysdeps/unix/sysv/linux/hppa/ld.abilist
+index 7cc9ebd7..7f5527fb 100644
+--- a/sysdeps/unix/sysv/linux/hppa/ld.abilist
++++ b/sysdeps/unix/sysv/linux/hppa/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x14
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/i386/ld.abilist b/sysdeps/unix/sysv/linux/i386/ld.abilist
+index e8d187b1..9c4a45d8 100644
+--- a/sysdeps/unix/sysv/linux/i386/ld.abilist
++++ b/sysdeps/unix/sysv/linux/i386/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 ___tls_get_addr F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/ia64/ld.abilist b/sysdeps/unix/sysv/linux/ia64/ld.abilist
+index be512265..8ccb5be9 100644
+--- a/sysdeps/unix/sysv/linux/ia64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/ia64/ld.abilist
+@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
+index 7987bbae..f1da2c63 100644
+--- a/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
++++ b/sysdeps/unix/sysv/linux/m68k/coldfire/ld.abilist
+@@ -1,4 +1,7 @@
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __libc_stack_end D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+ GLIBC_2.4 __tls_get_addr F
+diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
+index 4f2854ed..dadbf852 100644
+--- a/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
++++ b/sysdeps/unix/sysv/linux/m68k/m680x0/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.1 __libc_stack_end D 0x4
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/microblaze/ld.abilist b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
+index 9f0fdeca..89a0b7e4 100644
+--- a/sysdeps/unix/sysv/linux/microblaze/ld.abilist
++++ b/sysdeps/unix/sysv/linux/microblaze/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.18 __tls_get_addr F
+ GLIBC_2.18 _dl_mcount F
+ GLIBC_2.18 _r_debug D 0x14
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
+index f750067d..e304d1bb 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/mips/mips32/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
+index f750067d..e304d1bb 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x4
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+index 2fba6a9b..37a47ebc 100644
+--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.2 __libc_stack_end D 0x8
+ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x8
+diff --git a/sysdeps/unix/sysv/linux/nios2/ld.abilist b/sysdeps/unix/sysv/linux/nios2/ld.abilist
+index 57dfad5a..811ae9da 100644
+--- a/sysdeps/unix/sysv/linux/nios2/ld.abilist
++++ b/sysdeps/unix/sysv/linux/nios2/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.21 __tls_get_addr F
+ GLIBC_2.21 _dl_mcount F
+ GLIBC_2.21 _r_debug D 0x14
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
+index e8966073..5a68aeb9 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/ld.abilist
+@@ -5,3 +5,6 @@ GLIBC_2.22 __tls_get_addr_opt F
+ GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+index ce0bc639..da24dc7f 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/be/ld.abilist
+@@ -5,3 +5,6 @@ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.3 _dl_mcount F
+ GLIBC_2.3 _r_debug D 0x28
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+index 65b22674..b9ae89ae 100644
+--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/le/ld.abilist
+@@ -5,3 +5,6 @@ GLIBC_2.17 _r_debug D 0x28
+ GLIBC_2.22 __tls_get_addr_opt F
+ GLIBC_2.23 __parse_hwcap_and_convert_at_platform F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
+index 5ad4c81d..06836887 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/riscv/rv32/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.33 __tls_get_addr F
+ GLIBC_2.33 _dl_mcount F
+ GLIBC_2.33 _r_debug D 0x14
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+index 479efdea..48431c91 100644
+--- a/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/riscv/rv64/ld.abilist
+@@ -4,3 +4,6 @@ GLIBC_2.27 __tls_get_addr F
+ GLIBC_2.27 _dl_mcount F
+ GLIBC_2.27 _r_debug D 0x28
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
+index 15bc7ffd..9e8f99fd 100644
+--- a/sysdeps/unix/sysv/linux/rseq-internal.h
++++ b/sysdeps/unix/sysv/linux/rseq-internal.h
+@@ -26,7 +26,7 @@
+ #include <sys/rseq.h>
+
+ #ifdef RSEQ_SIG
+-static inline void
++static inline bool
+ rseq_register_current_thread (struct pthread *self, bool do_rseq)
+ {
+ if (do_rseq)
+@@ -35,15 +35,17 @@ rseq_register_current_thread (struct pthread *self, bool do_rseq)
+ sizeof (self->rseq_area),
+ 0, RSEQ_SIG);
+ if (!INTERNAL_SYSCALL_ERROR_P (ret))
+- return;
++ return true;
+ }
+ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
++ return false;
+ }
+ #else /* RSEQ_SIG */
+-static inline void
++static inline bool
+ rseq_register_current_thread (struct pthread *self, bool do_rseq)
+ {
+ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
++ return false;
+ }
+ #endif /* RSEQ_SIG */
+
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
+index d5ecb636..c1528839 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/s390/s390-32/ld.abilist
+@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_offset F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+index 62a5e1d9..117d1430 100644
+--- a/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/s390/s390-64/ld.abilist
+@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_offset F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sh/be/ld.abilist b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
+index 7cc9ebd7..7f5527fb 100644
+--- a/sysdeps/unix/sysv/linux/sh/be/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sh/be/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x14
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sh/le/ld.abilist b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
+index 7cc9ebd7..7f5527fb 100644
+--- a/sysdeps/unix/sysv/linux/sh/le/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sh/le/ld.abilist
+@@ -3,4 +3,7 @@ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x14
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+ GLIBC_2.4 __stack_chk_guard D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
+index 2e605434..3aac73f3 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/ld.abilist
+@@ -3,3 +3,6 @@ GLIBC_2.1 __libc_stack_end D 0x4
+ GLIBC_2.1 _dl_mcount F
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+index be512265..8ccb5be9 100644
+--- a/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/ld.abilist
+@@ -3,3 +3,6 @@ GLIBC_2.2 _dl_mcount F
+ GLIBC_2.2 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
+index c8edff50..1215b5d0 100644
+--- a/sysdeps/unix/sysv/linux/sys/rseq.h
++++ b/sysdeps/unix/sysv/linux/sys/rseq.h
+@@ -171,4 +171,14 @@ struct rseq
+
+ #endif /* __GLIBC_HAVE_KERNEL_RSEQ */
+
++/* Offset from the thread pointer to the rseq area. */
++extern const int __rseq_offset;
++
++/* Size of the registered rseq area. 0 if the registration was
++ unsuccessful. */
++extern const unsigned int __rseq_size;
++
++/* Flags used during rseq registration. */
++extern const unsigned int __rseq_flags;
++
+ #endif /* sys/rseq.h */
+diff --git a/sysdeps/unix/sysv/linux/tst-rseq-disable.c b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
+index 000e3518..6d73f77e 100644
+--- a/sysdeps/unix/sysv/linux/tst-rseq-disable.c
++++ b/sysdeps/unix/sysv/linux/tst-rseq-disable.c
+@@ -21,6 +21,7 @@
+ #include <support/namespace.h>
+ #include <support/xthread.h>
+ #include <sysdep.h>
++#include <thread_pointer.h>
+ #include <unistd.h>
+
+ #ifdef RSEQ_SIG
+@@ -30,6 +31,11 @@ static void
+ check_rseq_disabled (void)
+ {
+ struct pthread *pd = THREAD_SELF;
++
++ TEST_COMPARE (__rseq_flags, 0);
++ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
++ == (char *) &pd->rseq_area);
++ TEST_COMPARE (__rseq_size, 0);
+ TEST_COMPARE ((int) pd->rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
+
+ int ret = syscall (__NR_rseq, &pd->rseq_area, sizeof (pd->rseq_area),
+diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
+index 926376b6..572c1116 100644
+--- a/sysdeps/unix/sysv/linux/tst-rseq.c
++++ b/sysdeps/unix/sysv/linux/tst-rseq.c
+@@ -29,12 +29,20 @@
+ # include <stdlib.h>
+ # include <string.h>
+ # include <syscall.h>
++# include <thread_pointer.h>
++# include <tls.h>
+ # include "tst-rseq.h"
+
+ static void
+ do_rseq_main_test (void)
+ {
++ struct pthread *pd = THREAD_SELF;
++
+ TEST_VERIFY_EXIT (rseq_thread_registered ());
++ TEST_COMPARE (__rseq_flags, 0);
++ TEST_VERIFY ((char *) __thread_pointer () + __rseq_offset
++ == (char *) &pd->rseq_area);
++ TEST_COMPARE (__rseq_size, sizeof (pd->rseq_area));
+ }
+
+ static void
+diff --git a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+index afddaec5..ae622bdf 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
++++ b/sysdeps/unix/sysv/linux/x86_64/64/ld.abilist
+@@ -3,3 +3,6 @@ GLIBC_2.2.5 _dl_mcount F
+ GLIBC_2.2.5 _r_debug D 0x28
+ GLIBC_2.3 __tls_get_addr F
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+index defc488d..e17496d1 100644
+--- a/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
++++ b/sysdeps/unix/sysv/linux/x86_64/x32/ld.abilist
+@@ -3,3 +3,6 @@ GLIBC_2.16 __tls_get_addr F
+ GLIBC_2.16 _dl_mcount F
+ GLIBC_2.16 _r_debug D 0x14
+ GLIBC_2.34 __rtld_version_placeholder F
++GLIBC_2.35 __rseq_flags D 0x4
++GLIBC_2.35 __rseq_offset D 0x4
++GLIBC_2.35 __rseq_size D 0x4
+--
+2.23.0
+
diff --git a/rseq-nptl-Add-rseq-registration.patch b/rseq-nptl-Add-rseq-registration.patch
new file mode 100644
index 0000000..1f76ab3
--- /dev/null
+++ b/rseq-nptl-Add-rseq-registration.patch
@@ -0,0 +1,1165 @@
+From 9394ca7ec895e284fcb7f5d7839feeb517acc249 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 21 Jan 2022 22:23:58 -0500
+Subject: [PATCH 4/9] nptl: Add rseq registration
+
+The rseq area is placed directly into struct pthread. rseq
+registration failure is not treated as an error, so it is possible
+that threads run with inconsistent registration status.
+
+<sys/rseq.h> is not yet installed as a public header.
+
+Co-Authored-By: Mathieu Desnoyers <mathieu.desnoyers@efficios.com>
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+------
+conflicts:
+ context conflict
+---
+ nptl/descr.h | 4 +
+ nptl/pthread_create.c | 13 +
+ sysdeps/nptl/dl-tls_init_tp.c | 8 +-
+ sysdeps/unix/sysv/linux/Makefile | 9 +-
+ sysdeps/unix/sysv/linux/aarch64/bits/rseq.h | 43 ++++
+ sysdeps/unix/sysv/linux/arm/bits/rseq.h | 83 +++++++
+ sysdeps/unix/sysv/linux/bits/rseq.h | 29 +++
+ sysdeps/unix/sysv/linux/mips/bits/rseq.h | 62 +++++
+ sysdeps/unix/sysv/linux/powerpc/bits/rseq.h | 37 +++
+ sysdeps/unix/sysv/linux/rseq-internal.h | 45 ++++
+ sysdeps/unix/sysv/linux/s390/bits/rseq.h | 37 +++
+ sysdeps/unix/sysv/linux/sys/rseq.h | 174 +++++++++++++
+ sysdeps/unix/sysv/linux/tst-rseq-nptl.c | 260 ++++++++++++++++++++
+ sysdeps/unix/sysv/linux/tst-rseq.c | 64 +++++
+ sysdeps/unix/sysv/linux/tst-rseq.h | 57 +++++
+ sysdeps/unix/sysv/linux/x86/bits/rseq.h | 30 +++
+ 16 files changed, 952 insertions(+), 3 deletions(-)
+ create mode 100644 sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/arm/bits/rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/bits/rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/mips/bits/rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/rseq-internal.h
+ create mode 100644 sysdeps/unix/sysv/linux/s390/bits/rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/sys/rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/tst-rseq-nptl.c
+ create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.c
+ create mode 100644 sysdeps/unix/sysv/linux/tst-rseq.h
+ create mode 100644 sysdeps/unix/sysv/linux/x86/bits/rseq.h
+
+diff --git a/nptl/descr.h b/nptl/descr.h
+index 4de84138..79362661 100644
+--- a/nptl/descr.h
++++ b/nptl/descr.h
+@@ -35,6 +35,7 @@
+ #include <bits/types/res_state.h>
+ #include <kernel-features.h>
+ #include <tls-internal-struct.h>
++#include <sys/rseq.h>
+
+ #ifndef TCB_ALIGNMENT
+ # define TCB_ALIGNMENT sizeof (double)
+@@ -405,6 +406,9 @@ struct pthread
+ /* Used on strsignal. */
+ struct tls_internal_t tls_state;
+
++ /* rseq area registered with the kernel. */
++ struct rseq rseq_area;
++
+ /* This member must be last. */
+ char end_padding[];
+
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index 3db0c9fd..d2b40924 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -33,6 +33,7 @@
+ #include <default-sched.h>
+ #include <futex-internal.h>
+ #include <tls-setup.h>
++#include <rseq-internal.h>
+ #include "libioP.h"
+ #include <sys/single_threaded.h>
+ #include <version.h>
+@@ -367,6 +368,9 @@ start_thread (void *arg)
+ /* Initialize pointers to locale data. */
+ __ctype_init ();
+
++ /* Register rseq TLS to the kernel. */
++ rseq_register_current_thread (pd);
++
+ #ifndef __ASSUME_SET_ROBUST_LIST
+ if (__nptl_set_robust_list_avail)
+ #endif
+@@ -572,6 +576,15 @@ out:
+ process is really dead since 'clone' got passed the CLONE_CHILD_CLEARTID
+ flag. The 'tid' field in the TCB will be set to zero.
+
++ rseq TLS is still registered at this point. Rely on implicit
++ unregistration performed by the kernel on thread teardown. This is not a
++ problem because the rseq TLS lives on the stack, and the stack outlives
++ the thread. If TCB allocation is ever changed, additional steps may be
++ required, such as performing explicit rseq unregistration before
++ reclaiming the rseq TLS area memory. It is NOT sufficient to block
++ signals because the kernel may write to the rseq area even without
++ signals.
++
+ The exit code is zero since in case all threads exit by calling
+ 'pthread_exit' the exit status must be 0 (zero). */
+ while (1)
+diff --git a/sysdeps/nptl/dl-tls_init_tp.c b/sysdeps/nptl/dl-tls_init_tp.c
+index ca494dd3..fedb876f 100644
+--- a/sysdeps/nptl/dl-tls_init_tp.c
++++ b/sysdeps/nptl/dl-tls_init_tp.c
+@@ -21,6 +21,7 @@
+ #include <list.h>
+ #include <pthreadP.h>
+ #include <tls.h>
++#include <rseq-internal.h>
+
+ #ifndef __ASSUME_SET_ROBUST_LIST
+ bool __nptl_set_robust_list_avail;
+@@ -57,11 +58,12 @@ __tls_pre_init_tp (void)
+ void
+ __tls_init_tp (void)
+ {
++ struct pthread *pd = THREAD_SELF;
++
+ /* Set up thread stack list management. */
+- list_add (&THREAD_SELF->list, &GL (dl_stack_user));
++ list_add (&pd->list, &GL (dl_stack_user));
+
+ /* Early initialization of the TCB. */
+- struct pthread *pd = THREAD_SELF;
+ pd->tid = INTERNAL_SYSCALL_CALL (set_tid_address, &pd->tid);
+ THREAD_SETMEM (pd, specific[0], &pd->specific_1stblock[0]);
+ THREAD_SETMEM (pd, user_stack, true);
+@@ -90,6 +92,8 @@ __tls_init_tp (void)
+ }
+ }
+
++ rseq_register_current_thread (pd);
++
+ /* Set initial thread's stack block from 0 up to __libc_stack_end.
+ It will be bigger than it actually is, but for unwind.c/pt-longjmp.c
+ purposes this is good enough. */
+diff --git a/sysdeps/unix/sysv/linux/Makefile b/sysdeps/unix/sysv/linux/Makefile
+index c3477480..f103a964 100644
+--- a/sysdeps/unix/sysv/linux/Makefile
++++ b/sysdeps/unix/sysv/linux/Makefile
+@@ -130,7 +130,10 @@ ifeq ($(have-GLIBC_2.27)$(build-shared),yesyes)
+ tests += tst-ofdlocks-compat
+ endif
+
+-tests-internal += tst-sigcontext-get_pc
++tests-internal += \
++ tst-rseq \
++ tst-sigcontext-get_pc \
++ # tests-internal
+
+ tests-time64 += \
+ tst-adjtimex-time64 \
+@@ -370,4 +373,8 @@ endif
+
+ ifeq ($(subdir),nptl)
+ tests += tst-align-clone tst-getpid1
++
++# tst-rseq-nptl is an internal test because it requires a definition of
++# __NR_rseq from the internal system call list.
++tests-internal += tst-rseq-nptl
+ endif
+diff --git a/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
+new file mode 100644
+index 00000000..9ba92725
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/aarch64/bits/rseq.h
+@@ -0,0 +1,43 @@
++/* Restartable Sequences Linux aarch64 architecture header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
++#endif
++
++/* RSEQ_SIG is a signature required before each abort handler code.
++
++ It is a 32-bit value that maps to actual architecture code compiled
++ into applications and libraries. It needs to be defined for each
++ architecture. When choosing this value, it needs to be taken into
++ account that generating invalid instructions may have ill effects on
++ tools like objdump, and may also have impact on the CPU speculative
++ execution efficiency in some cases.
++
++ aarch64 -mbig-endian generates mixed endianness code vs data:
++ little-endian code and big-endian data. Ensure the RSEQ_SIG signature
++ matches code endianness. */
++
++#define RSEQ_SIG_CODE 0xd428bc00 /* BRK #0x45E0. */
++
++#ifdef __AARCH64EB__
++# define RSEQ_SIG_DATA 0x00bc28d4 /* BRK #0x45E0. */
++#else
++# define RSEQ_SIG_DATA RSEQ_SIG_CODE
++#endif
++
++#define RSEQ_SIG RSEQ_SIG_DATA
+diff --git a/sysdeps/unix/sysv/linux/arm/bits/rseq.h b/sysdeps/unix/sysv/linux/arm/bits/rseq.h
+new file mode 100644
+index 00000000..0542b26f
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/arm/bits/rseq.h
+@@ -0,0 +1,83 @@
++/* Restartable Sequences Linux arm architecture header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
++#endif
++
++/*
++ RSEQ_SIG is a signature required before each abort handler code.
++
++ It is a 32-bit value that maps to actual architecture code compiled
++ into applications and libraries. It needs to be defined for each
++ architecture. When choosing this value, it needs to be taken into
++ account that generating invalid instructions may have ill effects on
++ tools like objdump, and may also have impact on the CPU speculative
++ execution efficiency in some cases.
++
++ - ARM little endian
++
++ RSEQ_SIG uses the udf A32 instruction with an uncommon immediate operand
++ value 0x5de3. This traps if user-space reaches this instruction by mistake,
++ and the uncommon operand ensures the kernel does not move the instruction
++ pointer to attacker-controlled code on rseq abort.
++
++ The instruction pattern in the A32 instruction set is:
++
++ e7f5def3 udf #24035 ; 0x5de3
++
++ This translates to the following instruction pattern in the T16 instruction
++ set:
++
++ little endian:
++ def3 udf #243 ; 0xf3
++ e7f5 b.n <7f5>
++
++ - ARMv6+ big endian (BE8):
++
++ ARMv6+ -mbig-endian generates mixed endianness code vs data: little-endian
++ code and big-endian data. The data value of the signature needs to have its
++ byte order reversed to generate the trap instruction:
++
++ Data: 0xf3def5e7
++
++ Translates to this A32 instruction pattern:
++
++ e7f5def3 udf #24035 ; 0x5de3
++
++ Translates to this T16 instruction pattern:
++
++ def3 udf #243 ; 0xf3
++ e7f5 b.n <7f5>
++
++ - Prior to ARMv6 big endian (BE32):
++
++ Prior to ARMv6, -mbig-endian generates big-endian code and data
++ (which match), so the endianness of the data representation of the
++ signature should not be reversed. However, the choice between BE32
++ and BE8 is done by the linker, so we cannot know whether code and
++ data endianness will be mixed before the linker is invoked. So rather
++ than try to play tricks with the linker, the rseq signature is simply
++ data (not a trap instruction) prior to ARMv6 on big endian. This is
++ why the signature is expressed as data (.word) rather than as
++ instruction (.inst) in assembler. */
++
++#ifdef __ARMEB__
++# define RSEQ_SIG 0xf3def5e7 /* udf #24035 ; 0x5de3 (ARMv6+) */
++#else
++# define RSEQ_SIG 0xe7f5def3 /* udf #24035 ; 0x5de3 */
++#endif
+diff --git a/sysdeps/unix/sysv/linux/bits/rseq.h b/sysdeps/unix/sysv/linux/bits/rseq.h
+new file mode 100644
+index 00000000..46cf5d1c
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/bits/rseq.h
+@@ -0,0 +1,29 @@
++/* Restartable Sequences architecture header. Stub version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
++#endif
++
++/* RSEQ_SIG is a signature required before each abort handler code.
++
++ It is a 32-bit value that maps to actual architecture code compiled
++ into applications and libraries. It needs to be defined for each
++ architecture. When choosing this value, it needs to be taken into
++ account that generating invalid instructions may have ill effects on
++ tools like objdump, and may also have impact on the CPU speculative
++ execution efficiency in some cases. */
+diff --git a/sysdeps/unix/sysv/linux/mips/bits/rseq.h b/sysdeps/unix/sysv/linux/mips/bits/rseq.h
+new file mode 100644
+index 00000000..a9defee5
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/mips/bits/rseq.h
+@@ -0,0 +1,62 @@
++/* Restartable Sequences Linux mips architecture header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
++#endif
++
++/* RSEQ_SIG is a signature required before each abort handler code.
++
++ It is a 32-bit value that maps to actual architecture code compiled
++ into applications and libraries. It needs to be defined for each
++ architecture. When choosing this value, it needs to be taken into
++ account that generating invalid instructions may have ill effects on
++ tools like objdump, and may also have impact on the CPU speculative
++ execution efficiency in some cases.
++
++ RSEQ_SIG uses the break instruction. The instruction pattern is:
++
++ On MIPS:
++ 0350000d break 0x350
++
++ On nanoMIPS:
++ 00100350 break 0x350
++
++ On microMIPS:
++ 0000d407 break 0x350
++
++ For nanoMIPS32 and microMIPS, the instruction stream is encoded as
++ 16-bit halfwords, so the signature halfwords need to be swapped
++ accordingly for little-endian. */
++
++#if defined (__nanomips__)
++# ifdef __MIPSEL__
++# define RSEQ_SIG 0x03500010
++# else
++# define RSEQ_SIG 0x00100350
++# endif
++#elif defined (__mips_micromips)
++# ifdef __MIPSEL__
++# define RSEQ_SIG 0xd4070000
++# else
++# define RSEQ_SIG 0x0000d407
++# endif
++#elif defined (__mips__)
++# define RSEQ_SIG 0x0350000d
++#else
++/* Unknown MIPS architecture. */
++#endif
+diff --git a/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
+new file mode 100644
+index 00000000..05b3cf7b
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/powerpc/bits/rseq.h
+@@ -0,0 +1,37 @@
++/* Restartable Sequences Linux powerpc architecture header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
++#endif
++
++/* RSEQ_SIG is a signature required before each abort handler code.
++
++ It is a 32-bit value that maps to actual architecture code compiled
++ into applications and libraries. It needs to be defined for each
++ architecture. When choosing this value, it needs to be taken into
++ account that generating invalid instructions may have ill effects on
++ tools like objdump, and may also have impact on the CPU speculative
++ execution efficiency in some cases.
++
++ RSEQ_SIG uses the following trap instruction:
++
++ powerpc-be: 0f e5 00 0b twui r5,11
++ powerpc64-le: 0b 00 e5 0f twui r5,11
++ powerpc64-be: 0f e5 00 0b twui r5,11 */
++
++#define RSEQ_SIG 0x0fe5000b
+diff --git a/sysdeps/unix/sysv/linux/rseq-internal.h b/sysdeps/unix/sysv/linux/rseq-internal.h
+new file mode 100644
+index 00000000..909f5478
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/rseq-internal.h
+@@ -0,0 +1,45 @@
++/* Restartable Sequences internal API. Linux implementation.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef RSEQ_INTERNAL_H
++#define RSEQ_INTERNAL_H
++
++#include <sysdep.h>
++#include <errno.h>
++#include <kernel-features.h>
++#include <stdio.h>
++#include <sys/rseq.h>
++
++#ifdef RSEQ_SIG
++static inline void
++rseq_register_current_thread (struct pthread *self)
++{
++ int ret = INTERNAL_SYSCALL_CALL (rseq,
++ &self->rseq_area, sizeof (self->rseq_area),
++ 0, RSEQ_SIG);
++ if (INTERNAL_SYSCALL_ERROR_P (ret))
++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
++}
++#else /* RSEQ_SIG */
++static inline void
++rseq_register_current_thread (struct pthread *self)
++{
++ THREAD_SETMEM (self, rseq_area.cpu_id, RSEQ_CPU_ID_REGISTRATION_FAILED);
++}
++#endif /* RSEQ_SIG */
++
++#endif /* rseq-internal.h */
+diff --git a/sysdeps/unix/sysv/linux/s390/bits/rseq.h b/sysdeps/unix/sysv/linux/s390/bits/rseq.h
+new file mode 100644
+index 00000000..3030e38f
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/s390/bits/rseq.h
+@@ -0,0 +1,37 @@
++/* Restartable Sequences Linux s390 architecture header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
++#endif
++
++/* RSEQ_SIG is a signature required before each abort handler code.
++
++ It is a 32-bit value that maps to actual architecture code compiled
++ into applications and libraries. It needs to be defined for each
++ architecture. When choosing this value, it needs to be taken into
++ account that generating invalid instructions may have ill effects on
++ tools like objdump, and may also have impact on the CPU speculative
++ execution efficiency in some cases.
++
++ RSEQ_SIG uses the trap4 instruction. As Linux does not make use of the
++ access-register mode nor the linkage stack this instruction will always
++ cause a special-operation exception (the trap-enabled bit in the DUCT
++ is and will stay 0). The instruction pattern is
++ b2 ff 0f ff trap4 4095(%r0) */
++
++#define RSEQ_SIG 0xB2FF0FFF
+diff --git a/sysdeps/unix/sysv/linux/sys/rseq.h b/sysdeps/unix/sysv/linux/sys/rseq.h
+new file mode 100644
+index 00000000..c8edff50
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/sys/rseq.h
+@@ -0,0 +1,174 @@
++/* Restartable Sequences exported symbols. Linux header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++#define _SYS_RSEQ_H 1
++
++/* Architecture-specific rseq signature. */
++#include <bits/rseq.h>
++
++#include <stdint.h>
++#include <sys/cdefs.h>
++#include <bits/endian.h>
++
++#ifdef __has_include
++# if __has_include ("linux/rseq.h")
++# define __GLIBC_HAVE_KERNEL_RSEQ
++# endif
++#else
++# include <linux/version.h>
++# if LINUX_VERSION_CODE >= KERNEL_VERSION (4, 18, 0)
++# define __GLIBC_HAVE_KERNEL_RSEQ
++# endif
++#endif
++
++#ifdef __GLIBC_HAVE_KERNEL_RSEQ
++/* We use the structures declarations from the kernel headers. */
++# include <linux/rseq.h>
++#else /* __GLIBC_HAVE_KERNEL_RSEQ */
++/* We use a copy of the include/uapi/linux/rseq.h kernel header. */
++
++enum rseq_cpu_id_state
++ {
++ RSEQ_CPU_ID_UNINITIALIZED = -1,
++ RSEQ_CPU_ID_REGISTRATION_FAILED = -2,
++ };
++
++enum rseq_flags
++ {
++ RSEQ_FLAG_UNREGISTER = (1 << 0),
++ };
++
++enum rseq_cs_flags_bit
++ {
++ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT = 0,
++ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT = 1,
++ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT = 2,
++ };
++
++enum rseq_cs_flags
++ {
++ RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT =
++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT_BIT),
++ RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL =
++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL_BIT),
++ RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE =
++ (1U << RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE_BIT),
++ };
++
++/* struct rseq_cs is aligned on 32 bytes to ensure it is always
++ contained within a single cache-line. It is usually declared as
++ link-time constant data. */
++struct rseq_cs
++ {
++ /* Version of this structure. */
++ uint32_t version;
++ /* enum rseq_cs_flags. */
++ uint32_t flags;
++ uint64_t start_ip;
++ /* Offset from start_ip. */
++ uint64_t post_commit_offset;
++ uint64_t abort_ip;
++ } __attribute__ ((__aligned__ (32)));
++
++/* struct rseq is aligned on 32 bytes to ensure it is always
++ contained within a single cache-line.
++
++ A single struct rseq per thread is allowed. */
++struct rseq
++ {
++ /* Restartable sequences cpu_id_start field. Updated by the
++ kernel. Read by user-space with single-copy atomicity
++ semantics. This field should only be read by the thread which
++ registered this data structure. Aligned on 32-bit. Always
++ contains a value in the range of possible CPUs, although the
++ value may not be the actual current CPU (e.g. if rseq is not
++ initialized). This CPU number value should always be compared
++ against the value of the cpu_id field before performing a rseq
++ commit or returning a value read from a data structure indexed
++ using the cpu_id_start value. */
++ uint32_t cpu_id_start;
++ /* Restartable sequences cpu_id field. Updated by the kernel.
++ Read by user-space with single-copy atomicity semantics. This
++ field should only be read by the thread which registered this
++ data structure. Aligned on 32-bit. Values
++ RSEQ_CPU_ID_UNINITIALIZED and RSEQ_CPU_ID_REGISTRATION_FAILED
++ have a special semantic: the former means "rseq uninitialized",
++ and latter means "rseq initialization failed". This value is
++ meant to be read within rseq critical sections and compared
++ with the cpu_id_start value previously read, before performing
++ the commit instruction, or read and compared with the
++ cpu_id_start value before returning a value loaded from a data
++ structure indexed using the cpu_id_start value. */
++ uint32_t cpu_id;
++ /* Restartable sequences rseq_cs field.
++
++ Contains NULL when no critical section is active for the current
++ thread, or holds a pointer to the currently active struct rseq_cs.
++
++ Updated by user-space, which sets the address of the currently
++ active rseq_cs at the beginning of assembly instruction sequence
++ block, and set to NULL by the kernel when it restarts an assembly
++ instruction sequence block, as well as when the kernel detects that
++ it is preempting or delivering a signal outside of the range
++ targeted by the rseq_cs. Also needs to be set to NULL by user-space
++ before reclaiming memory that contains the targeted struct rseq_cs.
++
++ Read and set by the kernel. Set by user-space with single-copy
++ atomicity semantics. This field should only be updated by the
++ thread which registered this data structure. Aligned on 64-bit. */
++ union
++ {
++ uint64_t ptr64;
++# ifdef __LP64__
++ uint64_t ptr;
++# else /* __LP64__ */
++ struct
++ {
++#if __BYTE_ORDER == __BIG_ENDIAN
++ uint32_t padding; /* Initialized to zero. */
++ uint32_t ptr32;
++# else /* LITTLE */
++ uint32_t ptr32;
++ uint32_t padding; /* Initialized to zero. */
++# endif /* ENDIAN */
++ } ptr;
++# endif /* __LP64__ */
++ } rseq_cs;
++
++ /* Restartable sequences flags field.
++
++ This field should only be updated by the thread which
++ registered this data structure. Read by the kernel.
++ Mainly used for single-stepping through rseq critical sections
++ with debuggers.
++
++ - RSEQ_CS_FLAG_NO_RESTART_ON_PREEMPT
++ Inhibit instruction sequence block restart on preemption
++ for this thread.
++ - RSEQ_CS_FLAG_NO_RESTART_ON_SIGNAL
++ Inhibit instruction sequence block restart on signal
++ delivery for this thread.
++ - RSEQ_CS_FLAG_NO_RESTART_ON_MIGRATE
++ Inhibit instruction sequence block restart on migration for
++ this thread. */
++ uint32_t flags;
++ } __attribute__ ((__aligned__ (32)));
++
++#endif /* __GLIBC_HAVE_KERNEL_RSEQ */
++
++#endif /* sys/rseq.h */
+diff --git a/sysdeps/unix/sysv/linux/tst-rseq-nptl.c b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c
+new file mode 100644
+index 00000000..d31d9444
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-rseq-nptl.c
+@@ -0,0 +1,260 @@
++/* Restartable Sequences NPTL test.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* These tests validate that rseq is registered from various execution
++ contexts (main thread, destructor, other threads, other threads created
++ from destructor, forked process (without exec), pthread_atfork handlers,
++ pthread setspecific destructors, signal handlers, atexit handlers).
++
++ See the Linux kernel selftests for extensive rseq stress-tests. */
++
++#include <stdio.h>
++#include <support/check.h>
++#include <support/xthread.h>
++#include <sys/rseq.h>
++#include <unistd.h>
++
++#ifdef RSEQ_SIG
++# include <array_length.h>
++# include <errno.h>
++# include <error.h>
++# include <pthread.h>
++# include <signal.h>
++# include <stdlib.h>
++# include <string.h>
++# include <support/namespace.h>
++# include <support/xsignal.h>
++# include <syscall.h>
++# include <sys/types.h>
++# include <sys/wait.h>
++# include "tst-rseq.h"
++
++static pthread_key_t rseq_test_key;
++
++static void
++atfork_prepare (void)
++{
++ if (!rseq_thread_registered ())
++ {
++ printf ("error: rseq not registered in pthread atfork prepare\n");
++ support_record_failure ();
++ }
++}
++
++static void
++atfork_parent (void)
++{
++ if (!rseq_thread_registered ())
++ {
++ printf ("error: rseq not registered in pthread atfork parent\n");
++ support_record_failure ();
++ }
++}
++
++static void
++atfork_child (void)
++{
++ if (!rseq_thread_registered ())
++ {
++ printf ("error: rseq not registered in pthread atfork child\n");
++ support_record_failure ();
++ }
++}
++
++static void
++rseq_key_destructor (void *arg)
++{
++ /* Cannot use deferred failure reporting after main returns. */
++ if (!rseq_thread_registered ())
++ FAIL_EXIT1 ("rseq not registered in pthread key destructor");
++}
++
++static void
++atexit_handler (void)
++{
++ /* Cannot use deferred failure reporting after main returns. */
++ if (!rseq_thread_registered ())
++ FAIL_EXIT1 ("rseq not registered in atexit handler");
++}
++
++/* Used to avoid -Werror=stringop-overread warning with
++ pthread_setspecific and GCC 11. */
++static char one = 1;
++
++static void
++do_rseq_main_test (void)
++{
++ TEST_COMPARE (atexit (atexit_handler), 0);
++ rseq_test_key = xpthread_key_create (rseq_key_destructor);
++ TEST_COMPARE (pthread_atfork (atfork_prepare, atfork_parent, atfork_child), 0);
++ xraise (SIGUSR1);
++ TEST_COMPARE (pthread_setspecific (rseq_test_key, &one), 0);
++ TEST_VERIFY_EXIT (rseq_thread_registered ());
++}
++
++static void
++cancel_routine (void *arg)
++{
++ if (!rseq_thread_registered ())
++ {
++ printf ("error: rseq not registered in cancel routine\n");
++ support_record_failure ();
++ }
++}
++
++static pthread_barrier_t cancel_thread_barrier;
++static pthread_cond_t cancel_thread_cond = PTHREAD_COND_INITIALIZER;
++static pthread_mutex_t cancel_thread_mutex = PTHREAD_MUTEX_INITIALIZER;
++
++static void
++test_cancel_thread (void)
++{
++ pthread_cleanup_push (cancel_routine, NULL);
++ (void) xpthread_barrier_wait (&cancel_thread_barrier);
++ /* Wait forever until cancellation. */
++ xpthread_cond_wait (&cancel_thread_cond, &cancel_thread_mutex);
++ pthread_cleanup_pop (0);
++}
++
++static void *
++thread_function (void * arg)
++{
++ int i = (int) (intptr_t) arg;
++
++ xraise (SIGUSR1);
++ if (i == 0)
++ test_cancel_thread ();
++ TEST_COMPARE (pthread_setspecific (rseq_test_key, &one), 0);
++ return rseq_thread_registered () ? NULL : (void *) 1l;
++}
++
++static void
++sighandler (int sig)
++{
++ if (!rseq_thread_registered ())
++ {
++ printf ("error: rseq not registered in signal handler\n");
++ support_record_failure ();
++ }
++}
++
++static void
++setup_signals (void)
++{
++ struct sigaction sa;
++
++ sigemptyset (&sa.sa_mask);
++ sigaddset (&sa.sa_mask, SIGUSR1);
++ sa.sa_flags = 0;
++ sa.sa_handler = sighandler;
++ xsigaction (SIGUSR1, &sa, NULL);
++}
++
++static int
++do_rseq_threads_test (int nr_threads)
++{
++ pthread_t th[nr_threads];
++ int i;
++ int result = 0;
++
++ xpthread_barrier_init (&cancel_thread_barrier, NULL, 2);
++
++ for (i = 0; i < nr_threads; ++i)
++ th[i] = xpthread_create (NULL, thread_function,
++ (void *) (intptr_t) i);
++
++ (void) xpthread_barrier_wait (&cancel_thread_barrier);
++
++ xpthread_cancel (th[0]);
++
++ for (i = 0; i < nr_threads; ++i)
++ {
++ void *v;
++
++ v = xpthread_join (th[i]);
++ if (i != 0 && v != NULL)
++ {
++ printf ("error: join %d successful, but child failed\n", i);
++ result = 1;
++ }
++ else if (i == 0 && v == NULL)
++ {
++ printf ("error: join %d successful, child did not fail as expected\n", i);
++ result = 1;
++ }
++ }
++
++ xpthread_barrier_destroy (&cancel_thread_barrier);
++
++ return result;
++}
++
++static void
++subprocess_callback (void *closure)
++{
++ do_rseq_main_test ();
++}
++
++static void
++do_rseq_fork_test (void)
++{
++ support_isolate_in_subprocess (subprocess_callback, NULL);
++}
++
++static int
++do_rseq_test (void)
++{
++ int t[] = { 1, 2, 6, 5, 4, 3, 50 };
++ int i, result = 0;
++
++ if (!rseq_available ())
++ FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
++ setup_signals ();
++ xraise (SIGUSR1);
++ do_rseq_main_test ();
++ for (i = 0; i < array_length (t); i++)
++ if (do_rseq_threads_test (t[i]))
++ result = 1;
++ do_rseq_fork_test ();
++ return result;
++}
++
++static void __attribute__ ((destructor))
++do_rseq_destructor_test (void)
++{
++ /* Cannot use deferred failure reporting after main returns. */
++ if (do_rseq_test ())
++ FAIL_EXIT1 ("rseq not registered within destructor");
++ xpthread_key_delete (rseq_test_key);
++}
++
++#else /* RSEQ_SIG */
++static int
++do_rseq_test (void)
++{
++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test");
++ return 0;
++}
++#endif /* RSEQ_SIG */
++
++static int
++do_test (void)
++{
++ return do_rseq_test ();
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/unix/sysv/linux/tst-rseq.c b/sysdeps/unix/sysv/linux/tst-rseq.c
+new file mode 100644
+index 00000000..926376b6
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-rseq.c
+@@ -0,0 +1,64 @@
++/* Restartable Sequences single-threaded tests.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* These tests validate that rseq is registered from main in an executable
++ not linked against libpthread. */
++
++#include <support/check.h>
++#include <stdio.h>
++#include <sys/rseq.h>
++#include <unistd.h>
++
++#ifdef RSEQ_SIG
++# include <errno.h>
++# include <error.h>
++# include <stdlib.h>
++# include <string.h>
++# include <syscall.h>
++# include "tst-rseq.h"
++
++static void
++do_rseq_main_test (void)
++{
++ TEST_VERIFY_EXIT (rseq_thread_registered ());
++}
++
++static void
++do_rseq_test (void)
++{
++ if (!rseq_available ())
++ {
++ FAIL_UNSUPPORTED ("kernel does not support rseq, skipping test");
++ }
++ do_rseq_main_test ();
++}
++#else /* RSEQ_SIG */
++static void
++do_rseq_test (void)
++{
++ FAIL_UNSUPPORTED ("glibc does not define RSEQ_SIG, skipping test");
++}
++#endif /* RSEQ_SIG */
++
++static int
++do_test (void)
++{
++ do_rseq_test ();
++ return 0;
++}
++
++#include <support/test-driver.c>
+diff --git a/sysdeps/unix/sysv/linux/tst-rseq.h b/sysdeps/unix/sysv/linux/tst-rseq.h
+new file mode 100644
+index 00000000..a476c316
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/tst-rseq.h
+@@ -0,0 +1,57 @@
++/* Restartable Sequences tests header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <error.h>
++#include <stdbool.h>
++#include <stdint.h>
++#include <support/check.h>
++#include <syscall.h>
++#include <sys/rseq.h>
++#include <tls.h>
++
++static inline bool
++rseq_thread_registered (void)
++{
++ return THREAD_GETMEM_VOLATILE (THREAD_SELF, rseq_area.cpu_id) >= 0;
++}
++
++static inline int
++sys_rseq (struct rseq *rseq_abi, uint32_t rseq_len, int flags, uint32_t sig)
++{
++ return syscall (__NR_rseq, rseq_abi, rseq_len, flags, sig);
++}
++
++static inline bool
++rseq_available (void)
++{
++ int rc;
++
++ rc = sys_rseq (NULL, 0, 0, 0);
++ if (rc != -1)
++ FAIL_EXIT1 ("Unexpected rseq return value %d", rc);
++ switch (errno)
++ {
++ case ENOSYS:
++ return false;
++ case EINVAL:
++ /* rseq is implemented, but detected an invalid rseq_len parameter. */
++ return true;
++ default:
++ FAIL_EXIT1 ("Unexpected rseq error %s", strerror (errno));
++ }
++}
+diff --git a/sysdeps/unix/sysv/linux/x86/bits/rseq.h b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
+new file mode 100644
+index 00000000..9fc909e7
+--- /dev/null
++++ b/sysdeps/unix/sysv/linux/x86/bits/rseq.h
+@@ -0,0 +1,30 @@
++/* Restartable Sequences Linux x86 architecture header.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_RSEQ_H
++# error "Never use <bits/rseq.h> directly; include <sys/rseq.h> instead."
++#endif
++
++/* RSEQ_SIG is a signature required before each abort handler code.
++
++ RSEQ_SIG is used with the following reserved undefined instructions, which
++ trap in user-space:
++
++ x86-32: 0f b9 3d 53 30 05 53 ud1 0x53053053,%edi
++ x86-64: 0f b9 3d 53 30 05 53 ud1 0x53053053(%rip),%edi */
++
++#define RSEQ_SIG 0x53053053
+--
+2.23.0
+
diff --git a/rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch b/rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch
new file mode 100644
index 0000000..39c25a0
--- /dev/null
+++ b/rseq-nptl-Add-thread_pointer.h-for-defining-__thread_poin.patch
@@ -0,0 +1,141 @@
+From c773e8d7fb0c7a97290bd889ba984411a1952e9e Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 9 Dec 2021 09:49:32 +0100
+Subject: [PATCH 1/9] nptl: Add <thread_pointer.h> for defining
+ __thread_pointer
+
+<tls.h> already contains a definition that is quite similar,
+but it is not consistent across architectures.
+
+Only architectures for which rseq support is added are covered.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/nptl/thread_pointer.h | 28 ++++++++++++++++++++
+ sysdeps/powerpc/nptl/thread_pointer.h | 33 +++++++++++++++++++++++
+ sysdeps/x86/nptl/thread_pointer.h | 38 +++++++++++++++++++++++++++
+ 3 files changed, 99 insertions(+)
+ create mode 100644 sysdeps/nptl/thread_pointer.h
+ create mode 100644 sysdeps/powerpc/nptl/thread_pointer.h
+ create mode 100644 sysdeps/x86/nptl/thread_pointer.h
+
+diff --git a/sysdeps/nptl/thread_pointer.h b/sysdeps/nptl/thread_pointer.h
+new file mode 100644
+index 00000000..92f2f309
+--- /dev/null
++++ b/sysdeps/nptl/thread_pointer.h
+@@ -0,0 +1,28 @@
++/* __thread_pointer definition. Generic version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_THREAD_POINTER_H
++#define _SYS_THREAD_POINTER_H
++
++static inline void *
++__thread_pointer (void)
++{
++ return __builtin_thread_pointer ();
++}
++
++#endif /* _SYS_THREAD_POINTER_H */
+diff --git a/sysdeps/powerpc/nptl/thread_pointer.h b/sysdeps/powerpc/nptl/thread_pointer.h
+new file mode 100644
+index 00000000..8fd5ba67
+--- /dev/null
++++ b/sysdeps/powerpc/nptl/thread_pointer.h
+@@ -0,0 +1,33 @@
++/* __thread_pointer definition. powerpc version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_THREAD_POINTER_H
++#define _SYS_THREAD_POINTER_H
++
++static inline void *
++__thread_pointer (void)
++{
++#ifdef __powerpc64__
++ register void *__result asm ("r13");
++#else
++ register void *__result asm ("r2");
++#endif
++ return __result;
++}
++
++#endif /* _SYS_THREAD_POINTER_H */
+diff --git a/sysdeps/x86/nptl/thread_pointer.h b/sysdeps/x86/nptl/thread_pointer.h
+new file mode 100644
+index 00000000..6b71b6f7
+--- /dev/null
++++ b/sysdeps/x86/nptl/thread_pointer.h
+@@ -0,0 +1,38 @@
++/* __thread_pointer definition. x86 version.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef _SYS_THREAD_POINTER_H
++#define _SYS_THREAD_POINTER_H
++
++static inline void *
++__thread_pointer (void)
++{
++#if __GNUC_PREREQ (11, 1)
++ return __builtin_thread_pointer ();
++#else
++ void *__result;
++# ifdef __x86_64__
++ __asm__ ("mov %%fs:0, %0" : "=r" (__result));
++# else
++ __asm__ ("mov %%gs:0, %0" : "=r" (__result));
++# endif
++ return __result;
++#endif /* !GCC 11 */
++}
++
++#endif /* _SYS_THREAD_POINTER_H */
+--
+2.23.0
+
diff --git a/rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch b/rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch
new file mode 100644
index 0000000..4ad2329
--- /dev/null
+++ b/rseq-nptl-Introduce-THREAD_GETMEM_VOLATILE.patch
@@ -0,0 +1,56 @@
+From 6a8628eca8c8b22ccfd1422f2eb27bb665cfd660 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 9 Dec 2021 09:49:32 +0100
+Subject: [PATCH 3/9] nptl: Introduce THREAD_GETMEM_VOLATILE
+
+This will be needed for rseq TCB access.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ sysdeps/i386/nptl/tcb-access.h | 2 ++
+ sysdeps/nptl/tcb-access.h | 2 ++
+ sysdeps/x86_64/nptl/tcb-access.h | 2 ++
+ 3 files changed, 6 insertions(+)
+
+diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h
+index 6c6d561e..5ddd8322 100644
+--- a/sysdeps/i386/nptl/tcb-access.h
++++ b/sysdeps/i386/nptl/tcb-access.h
+@@ -41,6 +41,8 @@
+ } \
+ __value; })
+
++/* THREAD_GETMEM already forces a read. */
++#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member)
+
+ /* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+ #define THREAD_GETMEM_NC(descr, member, idx) \
+diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h
+index b4137b8a..bbe20b72 100644
+--- a/sysdeps/nptl/tcb-access.h
++++ b/sysdeps/nptl/tcb-access.h
+@@ -22,6 +22,8 @@
+
+ #define THREAD_GETMEM(descr, member) \
+ descr->member
++#define THREAD_GETMEM_VOLATILE(descr, member) \
++ (*(volatile __typeof (descr->member) *)&descr->member)
+ #define THREAD_GETMEM_NC(descr, member, idx) \
+ descr->member[idx]
+ #define THREAD_SETMEM(descr, member, value) \
+diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h
+index 18848a72..e4d2d07a 100644
+--- a/sysdeps/x86_64/nptl/tcb-access.h
++++ b/sysdeps/x86_64/nptl/tcb-access.h
+@@ -39,6 +39,8 @@
+ } \
+ __value; })
+
++/* THREAD_GETMEM already forces a read. */
++#define THREAD_GETMEM_VOLATILE(descr, member) THREAD_GETMEM (descr, member)
+
+ /* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+ # define THREAD_GETMEM_NC(descr, member, idx) \
+--
+2.23.0
+
diff --git a/rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch b/rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch
new file mode 100644
index 0000000..0d54119
--- /dev/null
+++ b/rseq-nptl-Introduce-tcb-access.h-for-THREAD_-accessors.patch
@@ -0,0 +1,935 @@
+From da3869963c4039b583d011e5612c2546efe90ed3 Mon Sep 17 00:00:00 2001
+From: qinyu <qinyu16@huawei.com>
+Date: Fri, 25 Feb 2022 10:55:45 +0800
+Subject: [PATCH 2/9] nptl: Introduce <tcb-access.h> for THREAD_* accessors
+
+These are common between most architectures. Only the x86 targets
+are outliers.
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+------
+conflicts:
+ context conflicts
+---
+ sysdeps/aarch64/nptl/tls.h | 10 +--
+ sysdeps/alpha/nptl/tls.h | 10 +--
+ sysdeps/arc/nptl/tls.h | 10 +--
+ sysdeps/arm/nptl/tls.h | 10 +--
+ sysdeps/csky/nptl/tls.h | 10 +--
+ sysdeps/hppa/nptl/tls.h | 10 +--
+ sysdeps/i386/nptl/tcb-access.h | 123 +++++++++++++++++++++++++++++
+ sysdeps/i386/nptl/tls.h | 108 +------------------------
+ sysdeps/ia64/nptl/tls.h | 10 +--
+ sysdeps/m68k/nptl/tls.h | 10 +--
+ sysdeps/microblaze/nptl/tls.h | 15 +---
+ sysdeps/mips/nptl/tls.h | 9 +--
+ sysdeps/nios2/nptl/tls.h | 10 +--
+ sysdeps/nptl/tcb-access.h | 30 +++++++
+ sysdeps/powerpc/nptl/tls.h | 15 +---
+ sysdeps/riscv/nptl/tls.h | 9 +--
+ sysdeps/s390/nptl/tls.h | 10 +--
+ sysdeps/sh/nptl/tls.h | 14 +---
+ sysdeps/sparc/nptl/tls.h | 10 +--
+ sysdeps/x86_64/nptl/tcb-access.h | 130 +++++++++++++++++++++++++++++++
+ sysdeps/x86_64/nptl/tls.h | 114 +--------------------------
+ 21 files changed, 301 insertions(+), 376 deletions(-)
+ create mode 100644 sysdeps/i386/nptl/tcb-access.h
+ create mode 100644 sysdeps/nptl/tcb-access.h
+ create mode 100644 sysdeps/x86_64/nptl/tcb-access.h
+
+diff --git a/sysdeps/aarch64/nptl/tls.h b/sysdeps/aarch64/nptl/tls.h
+index 6e896207..cd9abb5d 100644
+--- a/sysdeps/aarch64/nptl/tls.h
++++ b/sysdeps/aarch64/nptl/tls.h
+@@ -98,15 +98,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ CONST_THREAD_AREA (64, sizeof (struct pthread))
+
+-/* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Get and set the global scope generation counter in struct pthread. */
+ # define THREAD_GSCOPE_IN_TCB 1
+diff --git a/sysdeps/alpha/nptl/tls.h b/sysdeps/alpha/nptl/tls.h
+index 4dbccc52..5f4843b2 100644
+--- a/sysdeps/alpha/nptl/tls.h
++++ b/sysdeps/alpha/nptl/tls.h
+@@ -92,15 +92,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ REGISTER (64, 64, 32 * 8, -sizeof (struct pthread))
+
+-/* Access to data in the thread descriptor is easy. */
+-#define THREAD_GETMEM(descr, member) \
+- descr->member
+-#define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-#define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-#define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Get and set the global scope generation counter in struct pthread. */
+ #define THREAD_GSCOPE_IN_TCB 1
+diff --git a/sysdeps/arc/nptl/tls.h b/sysdeps/arc/nptl/tls.h
+index 95300fdd..d9ada2f3 100644
+--- a/sysdeps/arc/nptl/tls.h
++++ b/sysdeps/arc/nptl/tls.h
+@@ -100,15 +100,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+-/* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Get and set the global scope generation counter in struct pthread. */
+ #define THREAD_GSCOPE_IN_TCB 1
+diff --git a/sysdeps/arm/nptl/tls.h b/sysdeps/arm/nptl/tls.h
+index 1bd11307..354aae33 100644
+--- a/sysdeps/arm/nptl/tls.h
++++ b/sysdeps/arm/nptl/tls.h
+@@ -89,15 +89,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+-/* Access to data in the thread descriptor is easy. */
+-#define THREAD_GETMEM(descr, member) \
+- descr->member
+-#define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-#define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-#define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Get and set the global scope generation counter in struct pthread. */
+ #define THREAD_GSCOPE_IN_TCB 1
+diff --git a/sysdeps/csky/nptl/tls.h b/sysdeps/csky/nptl/tls.h
+index 7a234041..f3fa3fcb 100644
+--- a/sysdeps/csky/nptl/tls.h
++++ b/sysdeps/csky/nptl/tls.h
+@@ -116,15 +116,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+-/* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Get and set the global scope generation counter in struct pthread. */
+ # define THREAD_GSCOPE_IN_TCB 1
+diff --git a/sysdeps/hppa/nptl/tls.h b/sysdeps/hppa/nptl/tls.h
+index 857003a7..f0e274c4 100644
+--- a/sysdeps/hppa/nptl/tls.h
++++ b/sysdeps/hppa/nptl/tls.h
+@@ -107,15 +107,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ REGISTER (32, 32, 53 * 4, -sizeof (struct pthread))
+
+-/* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ static inline struct pthread *__get_cr27(void)
+ {
+diff --git a/sysdeps/i386/nptl/tcb-access.h b/sysdeps/i386/nptl/tcb-access.h
+new file mode 100644
+index 00000000..6c6d561e
+--- /dev/null
++++ b/sysdeps/i386/nptl/tcb-access.h
+@@ -0,0 +1,123 @@
++/* THREAD_* accessors. i386 version.
++ Copyright (C) 2002-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Read member of the thread descriptor directly. */
++#define THREAD_GETMEM(descr, member) \
++ ({ __typeof (descr->member) __value; \
++ _Static_assert (sizeof (__value) == 1 \
++ || sizeof (__value) == 4 \
++ || sizeof (__value) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (__value) == 1) \
++ asm volatile ("movb %%gs:%P2,%b0" \
++ : "=q" (__value) \
++ : "0" (0), "i" (offsetof (struct pthread, member))); \
++ else if (sizeof (__value) == 4) \
++ asm volatile ("movl %%gs:%P1,%0" \
++ : "=r" (__value) \
++ : "i" (offsetof (struct pthread, member))); \
++ else /* 8 */ \
++ { \
++ asm volatile ("movl %%gs:%P1,%%eax\n\t" \
++ "movl %%gs:%P2,%%edx" \
++ : "=A" (__value) \
++ : "i" (offsetof (struct pthread, member)), \
++ "i" (offsetof (struct pthread, member) + 4)); \
++ } \
++ __value; })
++
++
++/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
++#define THREAD_GETMEM_NC(descr, member, idx) \
++ ({ __typeof (descr->member[0]) __value; \
++ _Static_assert (sizeof (__value) == 1 \
++ || sizeof (__value) == 4 \
++ || sizeof (__value) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (__value) == 1) \
++ asm volatile ("movb %%gs:%P2(%3),%b0" \
++ : "=q" (__value) \
++ : "0" (0), "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ else if (sizeof (__value) == 4) \
++ asm volatile ("movl %%gs:%P1(,%2,4),%0" \
++ : "=r" (__value) \
++ : "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ else /* 8 */ \
++ { \
++ asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \
++ "movl %%gs:4+%P1(,%2,8),%%edx" \
++ : "=&A" (__value) \
++ : "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ } \
++ __value; })
++
++
++
++/* Set member of the thread descriptor directly. */
++#define THREAD_SETMEM(descr, member, value) \
++ ({ \
++ _Static_assert (sizeof (descr->member) == 1 \
++ || sizeof (descr->member) == 4 \
++ || sizeof (descr->member) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (descr->member) == 1) \
++ asm volatile ("movb %b0,%%gs:%P1" : \
++ : "iq" (value), \
++ "i" (offsetof (struct pthread, member))); \
++ else if (sizeof (descr->member) == 4) \
++ asm volatile ("movl %0,%%gs:%P1" : \
++ : "ir" (value), \
++ "i" (offsetof (struct pthread, member))); \
++ else /* 8 */ \
++ { \
++ asm volatile ("movl %%eax,%%gs:%P1\n\t" \
++ "movl %%edx,%%gs:%P2" : \
++ : "A" ((uint64_t) cast_to_integer (value)), \
++ "i" (offsetof (struct pthread, member)), \
++ "i" (offsetof (struct pthread, member) + 4)); \
++ }})
++
++
++/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
++#define THREAD_SETMEM_NC(descr, member, idx, value) \
++ ({ \
++ _Static_assert (sizeof (descr->member[0]) == 1 \
++ || sizeof (descr->member[0]) == 4 \
++ || sizeof (descr->member[0]) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (descr->member[0]) == 1) \
++ asm volatile ("movb %b0,%%gs:%P1(%2)" : \
++ : "iq" (value), \
++ "i" (offsetof (struct pthread, member)), \
++ "r" (idx)); \
++ else if (sizeof (descr->member[0]) == 4) \
++ asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \
++ : "ir" (value), \
++ "i" (offsetof (struct pthread, member)), \
++ "r" (idx)); \
++ else /* 8 */ \
++ { \
++ asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \
++ "movl %%edx,%%gs:4+%P1(,%2,8)" : \
++ : "A" ((uint64_t) cast_to_integer (value)), \
++ "i" (offsetof (struct pthread, member)), \
++ "r" (idx)); \
++ }})
+diff --git a/sysdeps/i386/nptl/tls.h b/sysdeps/i386/nptl/tls.h
+index 86ee1ef3..111c9ee5 100644
+--- a/sysdeps/i386/nptl/tls.h
++++ b/sysdeps/i386/nptl/tls.h
+@@ -250,113 +250,7 @@ tls_fill_user_desc (union user_desc_init *desc,
+ REGISTER_THREAD_AREA (32, offsetof (struct user_regs_struct, xgs), 3) \
+ REGISTER_THREAD_AREA (64, 26 * 8, 3) /* x86-64's user_regs_struct->gs */
+
+-
+-/* Read member of the thread descriptor directly. */
+-# define THREAD_GETMEM(descr, member) \
+- ({ __typeof (descr->member) __value; \
+- _Static_assert (sizeof (__value) == 1 \
+- || sizeof (__value) == 4 \
+- || sizeof (__value) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (__value) == 1) \
+- asm volatile ("movb %%gs:%P2,%b0" \
+- : "=q" (__value) \
+- : "0" (0), "i" (offsetof (struct pthread, member))); \
+- else if (sizeof (__value) == 4) \
+- asm volatile ("movl %%gs:%P1,%0" \
+- : "=r" (__value) \
+- : "i" (offsetof (struct pthread, member))); \
+- else /* 8 */ \
+- { \
+- asm volatile ("movl %%gs:%P1,%%eax\n\t" \
+- "movl %%gs:%P2,%%edx" \
+- : "=A" (__value) \
+- : "i" (offsetof (struct pthread, member)), \
+- "i" (offsetof (struct pthread, member) + 4)); \
+- } \
+- __value; })
+-
+-
+-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- ({ __typeof (descr->member[0]) __value; \
+- _Static_assert (sizeof (__value) == 1 \
+- || sizeof (__value) == 4 \
+- || sizeof (__value) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (__value) == 1) \
+- asm volatile ("movb %%gs:%P2(%3),%b0" \
+- : "=q" (__value) \
+- : "0" (0), "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- else if (sizeof (__value) == 4) \
+- asm volatile ("movl %%gs:%P1(,%2,4),%0" \
+- : "=r" (__value) \
+- : "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- else /* 8 */ \
+- { \
+- asm volatile ("movl %%gs:%P1(,%2,8),%%eax\n\t" \
+- "movl %%gs:4+%P1(,%2,8),%%edx" \
+- : "=&A" (__value) \
+- : "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- } \
+- __value; })
+-
+-
+-
+-/* Set member of the thread descriptor directly. */
+-# define THREAD_SETMEM(descr, member, value) \
+- ({ \
+- _Static_assert (sizeof (descr->member) == 1 \
+- || sizeof (descr->member) == 4 \
+- || sizeof (descr->member) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (descr->member) == 1) \
+- asm volatile ("movb %b0,%%gs:%P1" : \
+- : "iq" (value), \
+- "i" (offsetof (struct pthread, member))); \
+- else if (sizeof (descr->member) == 4) \
+- asm volatile ("movl %0,%%gs:%P1" : \
+- : "ir" (value), \
+- "i" (offsetof (struct pthread, member))); \
+- else /* 8 */ \
+- { \
+- asm volatile ("movl %%eax,%%gs:%P1\n\t" \
+- "movl %%edx,%%gs:%P2" : \
+- : "A" ((uint64_t) cast_to_integer (value)), \
+- "i" (offsetof (struct pthread, member)), \
+- "i" (offsetof (struct pthread, member) + 4)); \
+- }})
+-
+-
+-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- ({ \
+- _Static_assert (sizeof (descr->member[0]) == 1 \
+- || sizeof (descr->member[0]) == 4 \
+- || sizeof (descr->member[0]) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (descr->member[0]) == 1) \
+- asm volatile ("movb %b0,%%gs:%P1(%2)" : \
+- : "iq" (value), \
+- "i" (offsetof (struct pthread, member)), \
+- "r" (idx)); \
+- else if (sizeof (descr->member[0]) == 4) \
+- asm volatile ("movl %0,%%gs:%P1(,%2,4)" : \
+- : "ir" (value), \
+- "i" (offsetof (struct pthread, member)), \
+- "r" (idx)); \
+- else /* 8 */ \
+- { \
+- asm volatile ("movl %%eax,%%gs:%P1(,%2,8)\n\t" \
+- "movl %%edx,%%gs:4+%P1(,%2,8)" : \
+- : "A" ((uint64_t) cast_to_integer (value)), \
+- "i" (offsetof (struct pthread, member)), \
+- "r" (idx)); \
+- }})
+-
++# include <tcb-access.h>
+
+ /* Set the stack guard field in TCB head. */
+ #define THREAD_SET_STACK_GUARD(value) \
+diff --git a/sysdeps/ia64/nptl/tls.h b/sysdeps/ia64/nptl/tls.h
+index 66d9bf31..26fe555c 100644
+--- a/sysdeps/ia64/nptl/tls.h
++++ b/sysdeps/ia64/nptl/tls.h
+@@ -128,15 +128,7 @@ register struct pthread *__thread_self __asm__("r13");
+ /* Magic for libthread_db to know how to do THREAD_SELF. */
+ # define DB_THREAD_SELF REGISTER (64, 64, 13 * 8, -TLS_PRE_TCB_SIZE)
+
+-/* Access to data in the thread descriptor is easy. */
+-#define THREAD_GETMEM(descr, member) \
+- descr->member
+-#define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-#define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-#define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Set the stack guard field in TCB head. */
+ #define THREAD_SET_STACK_GUARD(value) \
+diff --git a/sysdeps/m68k/nptl/tls.h b/sysdeps/m68k/nptl/tls.h
+index cfcd6d2b..9f562c38 100644
+--- a/sysdeps/m68k/nptl/tls.h
++++ b/sysdeps/m68k/nptl/tls.h
+@@ -118,15 +118,7 @@ extern void * __m68k_read_tp (void);
+ # define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+
+-/* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* l_tls_offset == 0 is perfectly valid on M68K, so we have to use some
+ different value to mean unset l_tls_offset. */
+diff --git a/sysdeps/microblaze/nptl/tls.h b/sysdeps/microblaze/nptl/tls.h
+index c93d90b1..bfa6efa7 100644
+--- a/sysdeps/microblaze/nptl/tls.h
++++ b/sysdeps/microblaze/nptl/tls.h
+@@ -100,20 +100,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ CONST_THREAD_AREA (32, sizeof (struct pthread))
+
+-/* Read member of the thread descriptor directly. */
+-# define THREAD_GETMEM(descr, member) (descr->member)
+-
+-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- (descr->member[idx])
+-
+-/* Set member of the thread descriptor directly. */
+-# define THREAD_SETMEM(descr, member, value) \
+- (descr->member = (value))
+-
+-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- (descr->member[idx] = (value))
++# include <tcb-access.h>
+
+ /* Get and set the global scope generation counter in struct pthread. */
+ # define THREAD_GSCOPE_IN_TCB 1
+diff --git a/sysdeps/mips/nptl/tls.h b/sysdeps/mips/nptl/tls.h
+index c09f4907..ef99aa64 100644
+--- a/sysdeps/mips/nptl/tls.h
++++ b/sysdeps/mips/nptl/tls.h
+@@ -144,14 +144,7 @@ typedef struct
+ CONST_THREAD_AREA (32, TLS_TCB_OFFSET + TLS_PRE_TCB_SIZE)
+
+ /* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* l_tls_offset == 0 is perfectly valid on MIPS, so we have to use some
+ different value to mean unset l_tls_offset. */
+diff --git a/sysdeps/nios2/nptl/tls.h b/sysdeps/nios2/nptl/tls.h
+index 02a05b4e..7110cfcc 100644
+--- a/sysdeps/nios2/nptl/tls.h
++++ b/sysdeps/nios2/nptl/tls.h
+@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("r23");
+ # define DB_THREAD_SELF \
+ REGISTER (32, 32, 23 * 4, -TLS_PRE_TCB_SIZE - TLS_TCB_OFFSET)
+
+-/* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ # define THREAD_GET_POINTER_GUARD() \
+ (((tcbhead_t *) (READ_THREAD_POINTER () \
+diff --git a/sysdeps/nptl/tcb-access.h b/sysdeps/nptl/tcb-access.h
+new file mode 100644
+index 00000000..b4137b8a
+--- /dev/null
++++ b/sysdeps/nptl/tcb-access.h
+@@ -0,0 +1,30 @@
++/* THREAD_* accessors. Generic version based on struct pthread pointers.
++ Copyright (C) 2002-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Note: These are for accessing the TCB of the *current* thread.
++ descr can be disregarded on some targets as an optimization. See
++ i386 for an example. */
++
++#define THREAD_GETMEM(descr, member) \
++ descr->member
++#define THREAD_GETMEM_NC(descr, member, idx) \
++ descr->member[idx]
++#define THREAD_SETMEM(descr, member, value) \
++ descr->member = (value)
++#define THREAD_SETMEM_NC(descr, member, idx, value) \
++ descr->member[idx] = (value)
+diff --git a/sysdeps/powerpc/nptl/tls.h b/sysdeps/powerpc/nptl/tls.h
+index 6c779b66..110d085d 100644
+--- a/sysdeps/powerpc/nptl/tls.h
++++ b/sysdeps/powerpc/nptl/tls.h
+@@ -176,20 +176,7 @@ typedef struct
+ REGISTER (64, 64, PT_THREAD_POINTER * 8, \
+ - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+-/* Read member of the thread descriptor directly. */
+-# define THREAD_GETMEM(descr, member) ((void)(descr), (THREAD_SELF)->member)
+-
+-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- ((void)(descr), (THREAD_SELF)->member[idx])
+-
+-/* Set member of the thread descriptor directly. */
+-# define THREAD_SETMEM(descr, member, value) \
+- ((void)(descr), (THREAD_SELF)->member = (value))
+-
+-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- ((void)(descr), (THREAD_SELF)->member[idx] = (value))
++# include <tcb-access.h>
+
+ /* Set the stack guard field in TCB head. */
+ # define THREAD_SET_STACK_GUARD(value) \
+diff --git a/sysdeps/riscv/nptl/tls.h b/sysdeps/riscv/nptl/tls.h
+index 5350bcc0..bdc0a3a6 100644
+--- a/sysdeps/riscv/nptl/tls.h
++++ b/sysdeps/riscv/nptl/tls.h
+@@ -105,14 +105,7 @@ typedef struct
+ REGISTER (64, 64, 4 * 8, - TLS_TCB_OFFSET - TLS_PRE_TCB_SIZE)
+
+ /* Access to data in the thread descriptor is easy. */
+-# define THREAD_GETMEM(descr, member) \
+- descr->member
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* l_tls_offset == 0 is perfectly valid, so we have to use some different
+ value to mean unset l_tls_offset. */
+diff --git a/sysdeps/s390/nptl/tls.h b/sysdeps/s390/nptl/tls.h
+index efb52515..2cdd18eb 100644
+--- a/sysdeps/s390/nptl/tls.h
++++ b/sysdeps/s390/nptl/tls.h
+@@ -135,15 +135,7 @@ typedef struct
+ # define DB_THREAD_SELF REGISTER (32, 32, 18 * 4, 0) \
+ REGISTER (64, __WORDSIZE, 18 * 8, 0)
+
+-/* Access to data in the thread descriptor is easy. */
+-#define THREAD_GETMEM(descr, member) \
+- descr->member
+-#define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-#define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-#define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Set the stack guard field in TCB head. */
+ #define THREAD_SET_STACK_GUARD(value) \
+diff --git a/sysdeps/sh/nptl/tls.h b/sysdeps/sh/nptl/tls.h
+index ac3c9a9e..39064002 100644
+--- a/sysdeps/sh/nptl/tls.h
++++ b/sysdeps/sh/nptl/tls.h
+@@ -113,19 +113,7 @@ typedef struct
+ # define DB_THREAD_SELF \
+ REGISTER (32, 32, REG_GBR * 4, -sizeof (struct pthread))
+
+-/* Read member of the thread descriptor directly. */
+-# define THREAD_GETMEM(descr, member) (descr->member)
+-
+-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+-# define THREAD_GETMEM_NC(descr, member, idx) (descr->member[idx])
+-
+-/* Set member of the thread descriptor directly. */
+-# define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-
+-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ #define THREAD_GET_POINTER_GUARD() \
+ ({ tcbhead_t *__tcbp; \
+diff --git a/sysdeps/sparc/nptl/tls.h b/sysdeps/sparc/nptl/tls.h
+index dd1eb82a..376d7299 100644
+--- a/sysdeps/sparc/nptl/tls.h
++++ b/sysdeps/sparc/nptl/tls.h
+@@ -112,15 +112,7 @@ register struct pthread *__thread_self __asm__("%g7");
+ REGISTER (32, 32, 10 * 4, 0) \
+ REGISTER (64, __WORDSIZE, (6 * 8) + (__WORDSIZE==64?0:4), 0)
+
+-/* Access to data in the thread descriptor is easy. */
+-#define THREAD_GETMEM(descr, member) \
+- descr->member
+-#define THREAD_GETMEM_NC(descr, member, idx) \
+- descr->member[idx]
+-#define THREAD_SETMEM(descr, member, value) \
+- descr->member = (value)
+-#define THREAD_SETMEM_NC(descr, member, idx, value) \
+- descr->member[idx] = (value)
++# include <tcb-access.h>
+
+ /* Set the stack guard field in TCB head. */
+ #define THREAD_SET_STACK_GUARD(value) \
+diff --git a/sysdeps/x86_64/nptl/tcb-access.h b/sysdeps/x86_64/nptl/tcb-access.h
+new file mode 100644
+index 00000000..18848a72
+--- /dev/null
++++ b/sysdeps/x86_64/nptl/tcb-access.h
+@@ -0,0 +1,130 @@
++/* THREAD_* accessors. x86_64 version.
++ Copyright (C) 2002-2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Read member of the thread descriptor directly. */
++# define THREAD_GETMEM(descr, member) \
++ ({ __typeof (descr->member) __value; \
++ _Static_assert (sizeof (__value) == 1 \
++ || sizeof (__value) == 4 \
++ || sizeof (__value) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (__value) == 1) \
++ asm volatile ("movb %%fs:%P2,%b0" \
++ : "=q" (__value) \
++ : "0" (0), "i" (offsetof (struct pthread, member))); \
++ else if (sizeof (__value) == 4) \
++ asm volatile ("movl %%fs:%P1,%0" \
++ : "=r" (__value) \
++ : "i" (offsetof (struct pthread, member))); \
++ else /* 8 */ \
++ { \
++ asm volatile ("movq %%fs:%P1,%q0" \
++ : "=r" (__value) \
++ : "i" (offsetof (struct pthread, member))); \
++ } \
++ __value; })
++
++
++/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
++# define THREAD_GETMEM_NC(descr, member, idx) \
++ ({ __typeof (descr->member[0]) __value; \
++ _Static_assert (sizeof (__value) == 1 \
++ || sizeof (__value) == 4 \
++ || sizeof (__value) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (__value) == 1) \
++ asm volatile ("movb %%fs:%P2(%q3),%b0" \
++ : "=q" (__value) \
++ : "0" (0), "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ else if (sizeof (__value) == 4) \
++ asm volatile ("movl %%fs:%P1(,%q2,4),%0" \
++ : "=r" (__value) \
++ : "i" (offsetof (struct pthread, member[0])), "r" (idx));\
++ else /* 8 */ \
++ { \
++ asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \
++ : "=r" (__value) \
++ : "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ } \
++ __value; })
++
++
++/* Loading addresses of objects on x86-64 needs to be treated special
++ when generating PIC code. */
++#ifdef __pic__
++# define IMM_MODE "nr"
++#else
++# define IMM_MODE "ir"
++#endif
++
++
++/* Set member of the thread descriptor directly. */
++# define THREAD_SETMEM(descr, member, value) \
++ ({ \
++ _Static_assert (sizeof (descr->member) == 1 \
++ || sizeof (descr->member) == 4 \
++ || sizeof (descr->member) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (descr->member) == 1) \
++ asm volatile ("movb %b0,%%fs:%P1" : \
++ : "iq" (value), \
++ "i" (offsetof (struct pthread, member))); \
++ else if (sizeof (descr->member) == 4) \
++ asm volatile ("movl %0,%%fs:%P1" : \
++ : IMM_MODE (value), \
++ "i" (offsetof (struct pthread, member))); \
++ else /* 8 */ \
++ { \
++ /* Since movq takes a signed 32-bit immediate or a register source \
++ operand, use "er" constraint for 32-bit signed integer constant \
++ or register. */ \
++ asm volatile ("movq %q0,%%fs:%P1" : \
++ : "er" ((uint64_t) cast_to_integer (value)), \
++ "i" (offsetof (struct pthread, member))); \
++ }})
++
++
++/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
++# define THREAD_SETMEM_NC(descr, member, idx, value) \
++ ({ \
++ _Static_assert (sizeof (descr->member[0]) == 1 \
++ || sizeof (descr->member[0]) == 4 \
++ || sizeof (descr->member[0]) == 8, \
++ "size of per-thread data"); \
++ if (sizeof (descr->member[0]) == 1) \
++ asm volatile ("movb %b0,%%fs:%P1(%q2)" : \
++ : "iq" (value), \
++ "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ else if (sizeof (descr->member[0]) == 4) \
++ asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \
++ : IMM_MODE (value), \
++ "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ else /* 8 */ \
++ { \
++ /* Since movq takes a signed 32-bit immediate or a register source \
++ operand, use "er" constraint for 32-bit signed integer constant \
++ or register. */ \
++ asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \
++ : "er" ((uint64_t) cast_to_integer (value)), \
++ "i" (offsetof (struct pthread, member[0])), \
++ "r" (idx)); \
++ }})
+diff --git a/sysdeps/x86_64/nptl/tls.h b/sysdeps/x86_64/nptl/tls.h
+index a78c4f4d..3af1836e 100644
+--- a/sysdeps/x86_64/nptl/tls.h
++++ b/sysdeps/x86_64/nptl/tls.h
+@@ -195,119 +195,7 @@ _Static_assert (offsetof (tcbhead_t, __glibc_unused2) == 0x80,
+ # define DB_THREAD_SELF_INCLUDE <sys/reg.h> /* For the FS constant. */
+ # define DB_THREAD_SELF CONST_THREAD_AREA (64, FS)
+
+-/* Read member of the thread descriptor directly. */
+-# define THREAD_GETMEM(descr, member) \
+- ({ __typeof (descr->member) __value; \
+- _Static_assert (sizeof (__value) == 1 \
+- || sizeof (__value) == 4 \
+- || sizeof (__value) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (__value) == 1) \
+- asm volatile ("movb %%fs:%P2,%b0" \
+- : "=q" (__value) \
+- : "0" (0), "i" (offsetof (struct pthread, member))); \
+- else if (sizeof (__value) == 4) \
+- asm volatile ("movl %%fs:%P1,%0" \
+- : "=r" (__value) \
+- : "i" (offsetof (struct pthread, member))); \
+- else /* 8 */ \
+- { \
+- asm volatile ("movq %%fs:%P1,%q0" \
+- : "=r" (__value) \
+- : "i" (offsetof (struct pthread, member))); \
+- } \
+- __value; })
+-
+-
+-/* Same as THREAD_GETMEM, but the member offset can be non-constant. */
+-# define THREAD_GETMEM_NC(descr, member, idx) \
+- ({ __typeof (descr->member[0]) __value; \
+- _Static_assert (sizeof (__value) == 1 \
+- || sizeof (__value) == 4 \
+- || sizeof (__value) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (__value) == 1) \
+- asm volatile ("movb %%fs:%P2(%q3),%b0" \
+- : "=q" (__value) \
+- : "0" (0), "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- else if (sizeof (__value) == 4) \
+- asm volatile ("movl %%fs:%P1(,%q2,4),%0" \
+- : "=r" (__value) \
+- : "i" (offsetof (struct pthread, member[0])), "r" (idx));\
+- else /* 8 */ \
+- { \
+- asm volatile ("movq %%fs:%P1(,%q2,8),%q0" \
+- : "=r" (__value) \
+- : "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- } \
+- __value; })
+-
+-
+-/* Loading addresses of objects on x86-64 needs to be treated special
+- when generating PIC code. */
+-#ifdef __pic__
+-# define IMM_MODE "nr"
+-#else
+-# define IMM_MODE "ir"
+-#endif
+-
+-
+-/* Set member of the thread descriptor directly. */
+-# define THREAD_SETMEM(descr, member, value) \
+- ({ \
+- _Static_assert (sizeof (descr->member) == 1 \
+- || sizeof (descr->member) == 4 \
+- || sizeof (descr->member) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (descr->member) == 1) \
+- asm volatile ("movb %b0,%%fs:%P1" : \
+- : "iq" (value), \
+- "i" (offsetof (struct pthread, member))); \
+- else if (sizeof (descr->member) == 4) \
+- asm volatile ("movl %0,%%fs:%P1" : \
+- : IMM_MODE (value), \
+- "i" (offsetof (struct pthread, member))); \
+- else /* 8 */ \
+- { \
+- /* Since movq takes a signed 32-bit immediate or a register source \
+- operand, use "er" constraint for 32-bit signed integer constant \
+- or register. */ \
+- asm volatile ("movq %q0,%%fs:%P1" : \
+- : "er" ((uint64_t) cast_to_integer (value)), \
+- "i" (offsetof (struct pthread, member))); \
+- }})
+-
+-
+-/* Same as THREAD_SETMEM, but the member offset can be non-constant. */
+-# define THREAD_SETMEM_NC(descr, member, idx, value) \
+- ({ \
+- _Static_assert (sizeof (descr->member[0]) == 1 \
+- || sizeof (descr->member[0]) == 4 \
+- || sizeof (descr->member[0]) == 8, \
+- "size of per-thread data"); \
+- if (sizeof (descr->member[0]) == 1) \
+- asm volatile ("movb %b0,%%fs:%P1(%q2)" : \
+- : "iq" (value), \
+- "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- else if (sizeof (descr->member[0]) == 4) \
+- asm volatile ("movl %0,%%fs:%P1(,%q2,4)" : \
+- : IMM_MODE (value), \
+- "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- else /* 8 */ \
+- { \
+- /* Since movq takes a signed 32-bit immediate or a register source \
+- operand, use "er" constraint for 32-bit signed integer constant \
+- or register. */ \
+- asm volatile ("movq %q0,%%fs:%P1(,%q2,8)" : \
+- : "er" ((uint64_t) cast_to_integer (value)), \
+- "i" (offsetof (struct pthread, member[0])), \
+- "r" (idx)); \
+- }})
+-
++# include <tcb-access.h>
+
+ /* Set the stack guard field in TCB head. */
+ # define THREAD_SET_STACK_GUARD(value) \
+--
+2.23.0
+
diff --git a/rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch b/rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch
new file mode 100644
index 0000000..7fd271a
--- /dev/null
+++ b/rseq-nptl-rseq-failure-after-registration-on-main-thread-.patch
@@ -0,0 +1,44 @@
+From 210967ce32172eb7356747ed0b655e1fc37d0c57 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Thu, 9 Dec 2021 09:49:32 +0100
+Subject: [PATCH 8/9] nptl: rseq failure after registration on main thread is
+ fatal
+
+This simplifies the application programming model.
+
+Browser sandboxes have already been fixed:
+
+ Sandbox is incompatible with rseq registration
+ <https://bugzilla.mozilla.org/show_bug.cgi?id=1651701>
+
+ Allow rseq in the Linux sandboxes. r=gcp
+ <https://hg.mozilla.org/mozilla-central/rev/042425712eb1>
+
+ Sandbox needs to support rseq system call
+ <https://bugs.chromium.org/p/chromium/issues/detail?id=1104160>
+
+ Linux sandbox: Allow rseq(2)
+ <https://chromium.googlesource.com/chromium/src.git/+/230675d9ac8f1>
+
+Reviewed-by: Szabolcs Nagy <szabolcs.nagy@arm.com>
+---
+ nptl/pthread_create.c | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/nptl/pthread_create.c b/nptl/pthread_create.c
+index f405fa35..109c5e3d 100644
+--- a/nptl/pthread_create.c
++++ b/nptl/pthread_create.c
+@@ -371,7 +371,8 @@ start_thread (void *arg)
+ /* Register rseq TLS to the kernel. */
+ {
+ bool do_rseq = THREAD_GETMEM (pd, flags) & ATTR_FLAG_DO_RSEQ;
+- rseq_register_current_thread (pd, do_rseq);
++ if (!rseq_register_current_thread (pd, do_rseq) && do_rseq)
++ __libc_fatal ("Fatal glibc error: rseq registration failed\n");
+ }
+
+ #ifndef __ASSUME_SET_ROBUST_LIST
+--
+2.23.0
+
diff --git a/rt-Set-the-correct-message-queue-for-tst-mqueue10.patch b/rt-Set-the-correct-message-queue-for-tst-mqueue10.patch
new file mode 100644
index 0000000..700045a
--- /dev/null
+++ b/rt-Set-the-correct-message-queue-for-tst-mqueue10.patch
@@ -0,0 +1,35 @@
+From 3d9a539ee66165148b2b9e08b46e03a5f58f65d2 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Wed, 4 Aug 2021 17:14:46 -0300
+Subject: [PATCH] rt: Set the correct message queue for tst-mqueue10
+
+Checked on x86_64-linux-gnu.
+---
+ rt/tst-mqueue10.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/rt/tst-mqueue10.c b/rt/tst-mqueue10.c
+index 1879580..0bf64d7 100644
+--- a/rt/tst-mqueue10.c
++++ b/rt/tst-mqueue10.c
+@@ -25,7 +25,7 @@
+ #include <support/temp_file.h>
+ #include <unistd.h>
+
+-static char name[sizeof "/tst-mqueue2-" + INT_BUFSIZE_BOUND (pid_t)];
++static char name[sizeof "/tst-mqueue10-" + INT_BUFSIZE_BOUND (pid_t)];
+
+ static void
+ do_cleanup (void)
+@@ -37,7 +37,7 @@ do_cleanup (void)
+ static int
+ do_test (void)
+ {
+- snprintf (name, sizeof (name), "/tst-mqueue2-%u", getpid ());
++ snprintf (name, sizeof (name), "/tst-mqueue10-%u", getpid ());
+
+ char msg[8] = { 0x55 };
+
+--
+1.8.3.1
+
diff --git a/rtld-Remove-DL_ARGV_NOT_RELRO-and-make-_dl_skip_args.patch b/rtld-Remove-DL_ARGV_NOT_RELRO-and-make-_dl_skip_args.patch
new file mode 100644
index 0000000..5b139ba
--- /dev/null
+++ b/rtld-Remove-DL_ARGV_NOT_RELRO-and-make-_dl_skip_args.patch
@@ -0,0 +1,299 @@
+From 86147bbeec25624cb26bb7646cdbc3a49bc56bf5 Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Tue, 3 May 2021 17:01:44 +0100
+Subject: [PATCH 2/4] rtld: Remove DL_ARGV_NOT_RELRO and make _dl_skip_args
+ const
+
+Conflict:adapt 2022 to 2021
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=86147bbeec25624cb26bb7646cdbc3a49bc56bf5
+
+_dl_skip_args is always 0, so the target specific code that modifies
+argv after relro protection is applied is no longer used.
+
+After the patch relro protection is applied to _dl_argv consistently
+on all targets.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ elf/rtld.c | 10 ++--------
+ sysdeps/aarch64/dl-sysdep.h | 4 ----
+ sysdeps/alpha/dl-sysdep.h | 23 -----------------------
+ sysdeps/arc/dl-sysdep.h | 4 ----
+ sysdeps/arm/dl-sysdep.h | 4 ----
+ sysdeps/csky/dl-sysdep.h | 23 -----------------------
+ sysdeps/generic/ldsodefs.h | 13 +++----------
+ sysdeps/ia64/dl-sysdep.h | 23 -----------------------
+ sysdeps/nios2/dl-sysdep.h | 4 ----
+ sysdeps/s390/s390-32/dl-sysdep.h | 23 -----------------------
+ sysdeps/sparc/dl-sysdep.h | 23 -----------------------
+ sysdeps/unix/sysv/linux/ia64/dl-sysdep.h | 4 ----
+ 12 files changed, 5 insertions(+), 153 deletions(-)
+ delete mode 100644 sysdeps/alpha/dl-sysdep.h
+ delete mode 100644 sysdeps/csky/dl-sysdep.h
+ delete mode 100644 sysdeps/ia64/dl-sysdep.h
+ delete mode 100644 sysdeps/s390/s390-32/dl-sysdep.h
+ delete mode 100644 sysdeps/sparc/dl-sysdep.h
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 6e8ed430e2..069940d73f 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -156,16 +156,10 @@ static void dl_main_state_init (struct dl_main_state *state);
+ extern char **_environ attribute_hidden;
+ static void process_envvars (struct dl_main_state *state);
+
+-#ifdef DL_ARGV_NOT_RELRO
+-int _dl_argc attribute_hidden;
+-char **_dl_argv = NULL;
+-/* Nonzero if we were run directly. */
+-unsigned int _dl_skip_args attribute_hidden;
+-#else
+ int _dl_argc attribute_relro attribute_hidden;
+ char **_dl_argv attribute_relro = NULL;
+-unsigned int _dl_skip_args attribute_relro attribute_hidden;
+-#endif
++/* Always 0, only kept for not-yet-updated target start code. */
++const unsigned int _dl_skip_args attribute_hidden;
+ rtld_hidden_data_def (_dl_argv)
+
+ #ifndef THREAD_SET_STACK_GUARD
+diff --git a/sysdeps/aarch64/dl-sysdep.h b/sysdeps/aarch64/dl-sysdep.h
+index 667786671c..1516dd7d3f 100644
+--- a/sysdeps/aarch64/dl-sysdep.h
++++ b/sysdeps/aarch64/dl-sysdep.h
+@@ -18,8 +18,4 @@
+
+ #include_next <dl-sysdep.h>
+
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+-
+ #define DL_EXTERN_PROTECTED_DATA
+diff --git a/sysdeps/alpha/dl-sysdep.h b/sysdeps/alpha/dl-sysdep.h
+deleted file mode 100644
+index 3099ee419f..0000000000
+--- a/sysdeps/alpha/dl-sysdep.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* System-specific settings for dynamic linker code. Alpha version.
+- Copyright (C) 2002-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include_next <dl-sysdep.h>
+-
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+diff --git a/sysdeps/arc/dl-sysdep.h b/sysdeps/arc/dl-sysdep.h
+index da060ceeee..cf4d160a73 100644
+--- a/sysdeps/arc/dl-sysdep.h
++++ b/sysdeps/arc/dl-sysdep.h
+@@ -18,8 +18,4 @@
+
+ #include_next <dl-sysdep.h>
+
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+-
+ #define DL_EXTERN_PROTECTED_DATA
+diff --git a/sysdeps/arm/dl-sysdep.h b/sysdeps/arm/dl-sysdep.h
+index ce7a84a7de..7a99107436 100644
+--- a/sysdeps/arm/dl-sysdep.h
++++ b/sysdeps/arm/dl-sysdep.h
+@@ -18,8 +18,4 @@
+
+ #include_next <dl-sysdep.h>
+
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+-
+ #define DL_EXTERN_PROTECTED_DATA
+diff --git a/sysdeps/csky/dl-sysdep.h b/sysdeps/csky/dl-sysdep.h
+deleted file mode 100644
+index fc8a58b94c..0000000000
+--- a/sysdeps/csky/dl-sysdep.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* System-specific settings for dynamic linker code. C-SKY version.
+- Copyright (C) 2018-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include_next <dl-sysdep.h>
+-
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h
+index b69ea2caeb..6716e1f382 100644
+--- a/sysdeps/generic/ldsodefs.h
++++ b/sysdeps/generic/ldsodefs.h
+@@ -753,18 +753,11 @@ rtld_hidden_proto (__libc_stack_end)
+
+ /* Parameters passed to the dynamic linker. */
+ extern int _dl_argc attribute_hidden attribute_relro;
+-extern char **_dl_argv
+-#ifndef DL_ARGV_NOT_RELRO
+- attribute_relro
+-#endif
+- ;
++extern char **_dl_argv attribute_relro;
+ rtld_hidden_proto (_dl_argv)
+ #if IS_IN (rtld)
+-extern unsigned int _dl_skip_args attribute_hidden
+-# ifndef DL_ARGV_NOT_RELRO
+- attribute_relro
+-# endif
+- ;
++/* Always 0, only kept for not-yet-updated target start code. */
++extern const unsigned int _dl_skip_args attribute_hidden;
+ #endif
+ #define rtld_progname _dl_argv[0]
+
+diff --git a/sysdeps/ia64/dl-sysdep.h b/sysdeps/ia64/dl-sysdep.h
+deleted file mode 100644
+index e3a58bec24..0000000000
+--- a/sysdeps/ia64/dl-sysdep.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* System-specific settings for dynamic linker code. IA-64 version.
+- Copyright (C) 2002-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include_next <dl-sysdep.h>
+-
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+diff --git a/sysdeps/nios2/dl-sysdep.h b/sysdeps/nios2/dl-sysdep.h
+index 0354650042..257b37c258 100644
+--- a/sysdeps/nios2/dl-sysdep.h
++++ b/sysdeps/nios2/dl-sysdep.h
+@@ -18,8 +18,4 @@
+
+ #include_next <dl-sysdep.h>
+
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+-
+ #define DL_EXTERN_PROTECTED_DATA
+diff --git a/sysdeps/s390/s390-32/dl-sysdep.h b/sysdeps/s390/s390-32/dl-sysdep.h
+deleted file mode 100644
+index 699b50f156..0000000000
+--- a/sysdeps/s390/s390-32/dl-sysdep.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* System-specific settings for dynamic linker code. S/390 version.
+- Copyright (C) 2014-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library. If not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include_next <dl-sysdep.h>
+-
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+diff --git a/sysdeps/sparc/dl-sysdep.h b/sysdeps/sparc/dl-sysdep.h
+deleted file mode 100644
+index f32f16a107..0000000000
+--- a/sysdeps/sparc/dl-sysdep.h
++++ /dev/null
+@@ -1,23 +0,0 @@
+-/* System-specific settings for dynamic linker code. SPARC version.
+- Copyright (C) 2002-2021 Free Software Foundation, Inc.
+- This file is part of the GNU C Library.
+-
+- The GNU C Library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- The GNU C Library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with the GNU C Library; if not, see
+- <https://www.gnu.org/licenses/>. */
+-
+-#include_next <dl-sysdep.h>
+-
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+diff --git a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
+index 0d2a1d093a..aa1de6b361 100644
+--- a/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
++++ b/sysdeps/unix/sysv/linux/ia64/dl-sysdep.h
+@@ -48,8 +48,4 @@ extern int _dl_sysinfo_break attribute_hidden;
+ ".previous");
+ #endif
+
+-/* _dl_argv cannot be attribute_relro, because _dl_start_user
+- might write into it after _dl_start returns. */
+-#define DL_ARGV_NOT_RELRO 1
+-
+ #endif /* dl-sysdep.h */
+--
+2.27.0
+
diff --git a/rtld-Use-generic-argv-adjustment-in-ld.so-BZ-23293.patch b/rtld-Use-generic-argv-adjustment-in-ld.so-BZ-23293.patch
new file mode 100644
index 0000000..ced5c29
--- /dev/null
+++ b/rtld-Use-generic-argv-adjustment-in-ld.so-BZ-23293.patch
@@ -0,0 +1,305 @@
+From ad43cac44a6860eaefcadadfb2acb349921e96bf Mon Sep 17 00:00:00 2001
+From: Szabolcs Nagy <szabolcs.nagy@arm.com>
+Date: Fri, 15 Jun 2018 16:14:58 +0100
+Subject: [PATCH 1/4] rtld: Use generic argv adjustment in ld.so [BZ #23293]
+
+Conflict:adapt rtld.c:1031 context
+Reference:https://sourceware.org/git/?p=glibc.git;a=commitdiff;h=ad43cac44a6860eaefcadadfb2acb349921e96bf
+
+When an executable is invoked as
+
+ ./ld.so [ld.so-args] ./exe [exe-args]
+
+then the argv is adujusted in ld.so before calling the entry point of
+the executable so ld.so args are not visible to it. On most targets
+this requires moving argv, env and auxv on the stack to ensure correct
+stack alignment at the entry point. This had several issues:
+
+- The code for this adjustment on the stack is written in asm as part
+ of the target specific ld.so _start code which is hard to maintain.
+
+- The adjustment is done after _dl_start returns, where it's too late
+ to update GLRO(dl_auxv), as it is already readonly, so it points to
+ memory that was clobbered by the adjustment. This is bug 23293.
+
+- _environ is also wrong in ld.so after the adjustment, but it is
+ likely not used after _dl_start returns so this is not user visible.
+
+- _dl_argv was updated, but for this it was moved out of relro, which
+ changes security properties across targets unnecessarily.
+
+This patch introduces a generic _dl_start_args_adjust function that
+handles the argument adjustments after ld.so processed its own args
+and before relro protection is applied.
+
+The same algorithm is used on all targets, _dl_skip_args is now 0, so
+existing target specific adjustment code is no longer used. The bug
+affects aarch64, alpha, arc, arm, csky, ia64, nios2, s390-32 and sparc,
+other targets don't need the change in principle, only for consistency.
+
+The GNU Hurd start code relied on _dl_skip_args after dl_main returned,
+now it checks directly if args were adjusted and fixes the Hurd startup
+data accordingly.
+
+Follow up patches can remove _dl_skip_args and DL_ARGV_NOT_RELRO.
+
+Tested on aarch64-linux-gnu and cross tested on i686-gnu.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ elf/rtld.c | 73 ++++++++++++++++++++++++++++-------
+ sysdeps/mach/hurd/dl-sysdep.c | 30 +++++++-------
+ 2 files changed, 73 insertions(+), 30 deletions(-)
+
+diff --git a/elf/rtld.c b/elf/rtld.c
+index 578fc14cdb..6e8ed430e2 100644
+--- a/elf/rtld.c
++++ b/elf/rtld.c
+@@ -1301,6 +1301,62 @@ rtld_setup_main_map (struct link_map *main_map)
+ }
+ }
+
++/* Adjusts the contents of the stack and related globals for the user
++ entry point. The ld.so processed skip_args arguments and bumped
++ _dl_argv and _dl_argc accordingly. Those arguments are removed from
++ argv here. */
++static void
++_dl_start_args_adjust (int skip_args)
++{
++ void **sp = (void **) (_dl_argv - skip_args - 1);
++ void **p = sp + skip_args;
++
++ if (skip_args == 0)
++ return;
++
++ /* Sanity check. */
++ intptr_t argc = (intptr_t) sp[0] - skip_args;
++ assert (argc == _dl_argc);
++
++ /* Adjust argc on stack. */
++ sp[0] = (void *) (intptr_t) _dl_argc;
++
++ /* Update globals in rtld. */
++ _dl_argv -= skip_args;
++ _environ -= skip_args;
++
++ /* Shuffle argv down. */
++ do
++ *++sp = *++p;
++ while (*p != NULL);
++
++ assert (_environ == (char **) (sp + 1));
++
++ /* Shuffle envp down. */
++ do
++ *++sp = *++p;
++ while (*p != NULL);
++
++#ifdef HAVE_AUX_VECTOR
++ void **auxv = (void **) GLRO(dl_auxv) - skip_args;
++ GLRO(dl_auxv) = (ElfW(auxv_t) *) auxv; /* Aliasing violation. */
++ assert (auxv == sp + 1);
++
++ /* Shuffle auxv down. */
++ ElfW(auxv_t) ax;
++ char *oldp = (char *) (p + 1);
++ char *newp = (char *) (sp + 1);
++ do
++ {
++ memcpy (&ax, oldp, sizeof (ax));
++ memcpy (newp, &ax, sizeof (ax));
++ oldp += sizeof (ax);
++ newp += sizeof (ax);
++ }
++ while (ax.a_type != AT_NULL);
++#endif
++}
++
+ static void
+ dl_main (const ElfW(Phdr) *phdr,
+ ElfW(Word) phnum,
+@@ -1354,6 +1410,7 @@ dl_main (const ElfW(Phdr) *phdr,
+ rtld_is_main = true;
+
+ char *argv0 = NULL;
++ char **orig_argv = _dl_argv;
+
+ /* Note the place where the dynamic linker actually came from. */
+ GL(dl_rtld_map).l_name = rtld_progname;
+@@ -1368,7 +1425,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ GLRO(dl_lazy) = -1;
+ }
+
+- ++_dl_skip_args;
+ --_dl_argc;
+ ++_dl_argv;
+ }
+@@ -1377,14 +1433,12 @@ dl_main (const ElfW(Phdr) *phdr,
+ if (state.mode != rtld_mode_help)
+ state.mode = rtld_mode_verify;
+
+- ++_dl_skip_args;
+ --_dl_argc;
+ ++_dl_argv;
+ }
+ else if (! strcmp (_dl_argv[1], "--inhibit-cache"))
+ {
+ GLRO(dl_inhibit_cache) = 1;
+- ++_dl_skip_args;
+ --_dl_argc;
+ ++_dl_argv;
+ }
+@@ -1394,7 +1448,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ state.library_path = _dl_argv[2];
+ state.library_path_source = "--library-path";
+
+- _dl_skip_args += 2;
+ _dl_argc -= 2;
+ _dl_argv += 2;
+ }
+@@ -1403,7 +1456,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ {
+ GLRO(dl_inhibit_rpath) = _dl_argv[2];
+
+- _dl_skip_args += 2;
+ _dl_argc -= 2;
+ _dl_argv += 2;
+ }
+@@ -1411,14 +1463,12 @@ dl_main (const ElfW(Phdr) *phdr,
+ {
+ audit_list_add_string (&state.audit_list, _dl_argv[2]);
+
+- _dl_skip_args += 2;
+ _dl_argc -= 2;
+ _dl_argv += 2;
+ }
+ else if (! strcmp (_dl_argv[1], "--preload") && _dl_argc > 2)
+ {
+ state.preloadarg = _dl_argv[2];
+- _dl_skip_args += 2;
+ _dl_argc -= 2;
+ _dl_argv += 2;
+ }
+@@ -1426,7 +1476,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ {
+ argv0 = _dl_argv[2];
+
+- _dl_skip_args += 2;
+ _dl_argc -= 2;
+ _dl_argv += 2;
+ }
+@@ -1434,7 +1483,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ && _dl_argc > 2)
+ {
+ state.glibc_hwcaps_prepend = _dl_argv[2];
+- _dl_skip_args += 2;
+ _dl_argc -= 2;
+ _dl_argv += 2;
+ }
+@@ -1442,7 +1490,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ && _dl_argc > 2)
+ {
+ state.glibc_hwcaps_mask = _dl_argv[2];
+- _dl_skip_args += 2;
+ _dl_argc -= 2;
+ _dl_argv += 2;
+ }
+@@ -1451,7 +1498,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ {
+ state.mode = rtld_mode_list_tunables;
+
+- ++_dl_skip_args;
+ --_dl_argc;
+ ++_dl_argv;
+ }
+@@ -1460,7 +1506,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ {
+ state.mode = rtld_mode_list_diagnostics;
+
+- ++_dl_skip_args;
+ --_dl_argc;
+ ++_dl_argv;
+ }
+@@ -1506,7 +1551,6 @@ dl_main (const ElfW(Phdr) *phdr,
+ _dl_usage (ld_so_name, NULL);
+ }
+
+- ++_dl_skip_args;
+ --_dl_argc;
+ ++_dl_argv;
+
+@@ -1605,6 +1649,9 @@ dl_main (const ElfW(Phdr) *phdr,
+ /* Set the argv[0] string now that we've processed the executable. */
+ if (argv0 != NULL)
+ _dl_argv[0] = argv0;
++
++ /* Adjust arguments for the application entry point. */
++ _dl_start_args_adjust (_dl_argv - orig_argv);
+ }
+ else
+ {
+diff --git a/sysdeps/mach/hurd/dl-sysdep.c b/sysdeps/mach/hurd/dl-sysdep.c
+index 3cbe075615..8373962e62 100644
+--- a/sysdeps/mach/hurd/dl-sysdep.c
++++ b/sysdeps/mach/hurd/dl-sysdep.c
+@@ -76,6 +76,7 @@ _dl_sysdep_start (void **start_argptr,
+ {
+ void go (intptr_t *argdata)
+ {
++ char *orig_argv0;
+ char **p;
+
+ /* Cache the information in various global variables. */
+@@ -84,6 +85,8 @@ _dl_sysdep_start (void **start_argptr,
+ _environ = &_dl_argv[_dl_argc + 1];
+ for (p = _environ; *p++;); /* Skip environ pointers and terminator. */
+
++ orig_argv0 = _dl_argv[0];
++
+ if ((void *) p == _dl_argv[0])
+ {
+ static struct hurd_startup_data nodata;
+@@ -173,30 +176,23 @@ _dl_sysdep_start (void **start_argptr,
+
+ /* The call above might screw a few things up.
+
+- First of all, if _dl_skip_args is nonzero, we are ignoring
+- the first few arguments. However, if we have no Hurd startup
+- data, it is the magical convention that ARGV[0] == P. The
++ P is the location after the terminating NULL of the list of
++ environment variables. It has to point to the Hurd startup
++ data or if that's missing then P == ARGV[0] must hold. The
+ startup code in init-first.c will get confused if this is not
+ the case, so we must rearrange things to make it so. We'll
+- overwrite the origional ARGV[0] at P with ARGV[_dl_skip_args].
++ recompute P and move the Hurd data or the new ARGV[0] there.
+
+- Secondly, if we need to be secure, it removes some dangerous
+- environment variables. If we have no Hurd startup date this
+- changes P (since that's the location after the terminating
+- NULL in the list of environment variables). We do the same
+- thing as in the first case but make sure we recalculate P.
+- If we do have Hurd startup data, we have to move the data
+- such that it starts just after the terminating NULL in the
+- environment list.
++ Note: directly invoked ld.so can move arguments and env vars.
+
+ We use memmove, since the locations might overlap. */
+- if (__libc_enable_secure || _dl_skip_args)
+- {
+- char **newp;
+
+- for (newp = _environ; *newp++;);
++ char **newp;
++ for (newp = _environ; *newp++;);
+
+- if (_dl_argv[-_dl_skip_args] == (char *) p)
++ if (newp != p || _dl_argv[0] != orig_argv0)
++ {
++ if (orig_argv0 == (char *) p)
+ {
+ if ((char *) newp != _dl_argv[0])
+ {
+--
+2.27.0
+
diff --git a/rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch b/rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch
new file mode 100644
index 0000000..6f73106
--- /dev/null
+++ b/rtld-copy-terminating-null-in-tunables_strdup-bug-28.patch
@@ -0,0 +1,28 @@
+From a4f5a3103fc3e7974dbe35b411cba9f670807cde Mon Sep 17 00:00:00 2001
+From: Andreas Schwab <schwab@linux-m68k.org>
+Date: Mon, 23 Aug 2021 10:19:52 +0200
+Subject: [PATCH] rtld: copy terminating null in tunables_strdup (bug 28256)
+
+Avoid triggering a false positive from valgrind by copying the terminating
+null in tunables_strdup. At this point the heap is still clean, but
+valgrind is stricter here.
+---
+ elf/dl-tunables.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/elf/dl-tunables.c b/elf/dl-tunables.c
+index 8009e54..1666736 100644
+--- a/elf/dl-tunables.c
++++ b/elf/dl-tunables.c
+@@ -56,8 +56,6 @@ tunables_strdup (const char *in)
+ if (out == (void *)-1)
+ _dl_fatal_printf ("sbrk() failure while processing tunables\n");
+
+- i--;
+-
+ while (i-- > 0)
+ out[i] = in[i];
+
+--
+1.8.3.1
+
diff --git a/socket-Add-the-__sockaddr_un_set-function.patch b/socket-Add-the-__sockaddr_un_set-function.patch
new file mode 100644
index 0000000..0b0997b
--- /dev/null
+++ b/socket-Add-the-__sockaddr_un_set-function.patch
@@ -0,0 +1,174 @@
+From e368b12f6c16b6888dda99ba641e999b9c9643c8 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 17 Jan 2022 10:21:34 +0100
+Subject: [PATCH] socket: Add the __sockaddr_un_set function
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ include/sys/un.h | 12 +++++++++
+ socket/Makefile | 6 ++++-
+ socket/sockaddr_un_set.c | 41 +++++++++++++++++++++++++++++
+ socket/tst-sockaddr_un_set.c | 62 ++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 120 insertions(+), 1 deletion(-)
+ create mode 100644 socket/sockaddr_un_set.c
+ create mode 100644 socket/tst-sockaddr_un_set.c
+
+diff --git a/include/sys/un.h b/include/sys/un.h
+index bdbee99..152afd9 100644
+--- a/include/sys/un.h
++++ b/include/sys/un.h
+@@ -1 +1,13 @@
+ #include <socket/sys/un.h>
++
++#ifndef _ISOMAC
++
++/* Set ADDR->sun_family to AF_UNIX and ADDR->sun_path to PATHNAME.
++ Return 0 on success or -1 on failure (due to overlong PATHNAME).
++ The caller should always use sizeof (struct sockaddr_un) as the
++ socket address length, disregaring the length of PATHNAME.
++ Only concrete (non-abstract) pathnames are supported. */
++int __sockaddr_un_set (struct sockaddr_un *addr, const char *pathname)
++ attribute_hidden;
++
++#endif /* _ISOMAC */
+diff --git a/socket/Makefile b/socket/Makefile
+index 39333e1..156eec6 100644
+--- a/socket/Makefile
++++ b/socket/Makefile
+@@ -29,13 +29,17 @@ headers := sys/socket.h sys/un.h bits/sockaddr.h bits/socket.h \
+ routines := accept bind connect getpeername getsockname getsockopt \
+ listen recv recvfrom recvmsg send sendmsg sendto \
+ setsockopt shutdown socket socketpair isfdtype opensock \
+- sockatmark accept4 recvmmsg sendmmsg
++ sockatmark accept4 recvmmsg sendmmsg sockaddr_un_set
+
+ tests := \
+ tst-accept4 \
+ tst-sockopt \
+ # tests
+
++tests-internal := \
++ tst-sockaddr_un_set \
++ # tests-internal
++
+ tests-time64 := \
+ tst-sockopt-time64 \
+ # tests
+diff --git a/socket/sockaddr_un_set.c b/socket/sockaddr_un_set.c
+new file mode 100644
+index 0000000..0bd40dc
+--- /dev/null
++++ b/socket/sockaddr_un_set.c
+@@ -0,0 +1,41 @@
++/* Set the sun_path member of struct sockaddr_un.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <string.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++
++int
++__sockaddr_un_set (struct sockaddr_un *addr, const char *pathname)
++{
++ size_t name_length = strlen (pathname);
++
++ /* The kernel supports names of exactly sizeof (addr->sun_path)
++ bytes, without a null terminator, but userspace does not; see the
++ SUN_LEN macro. */
++ if (name_length >= sizeof (addr->sun_path))
++ {
++ __set_errno (EINVAL); /* Error code used by the kernel. */
++ return -1;
++ }
++
++ addr->sun_family = AF_UNIX;
++ memcpy (addr->sun_path, pathname, name_length + 1);
++ return 0;
++}
+diff --git a/socket/tst-sockaddr_un_set.c b/socket/tst-sockaddr_un_set.c
+new file mode 100644
+index 0000000..29c2a81
+--- /dev/null
++++ b/socket/tst-sockaddr_un_set.c
+@@ -0,0 +1,62 @@
++/* Test the __sockaddr_un_set function.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++/* Re-compile the function because the version in libc is not
++ exported. */
++#include "sockaddr_un_set.c"
++
++#include <support/check.h>
++
++static int
++do_test (void)
++{
++ struct sockaddr_un sun;
++
++ memset (&sun, 0xcc, sizeof (sun));
++ __sockaddr_un_set (&sun, "");
++ TEST_COMPARE (sun.sun_family, AF_UNIX);
++ TEST_COMPARE (__sockaddr_un_set (&sun, ""), 0);
++
++ memset (&sun, 0xcc, sizeof (sun));
++ TEST_COMPARE (__sockaddr_un_set (&sun, "/example"), 0);
++ TEST_COMPARE_STRING (sun.sun_path, "/example");
++
++ {
++ char pathname[108]; /* Length of sun_path (ABI constant). */
++ memset (pathname, 'x', sizeof (pathname));
++ pathname[sizeof (pathname) - 1] = '\0';
++ memset (&sun, 0xcc, sizeof (sun));
++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), 0);
++ TEST_COMPARE (sun.sun_family, AF_UNIX);
++ TEST_COMPARE_STRING (sun.sun_path, pathname);
++ }
++
++ {
++ char pathname[109];
++ memset (pathname, 'x', sizeof (pathname));
++ pathname[sizeof (pathname) - 1] = '\0';
++ memset (&sun, 0xcc, sizeof (sun));
++ errno = 0;
++ TEST_COMPARE (__sockaddr_un_set (&sun, pathname), -1);
++ TEST_COMPARE (errno, EINVAL);
++ }
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/socket-Do-not-use-AF_NETLINK-in-__opensock.patch b/socket-Do-not-use-AF_NETLINK-in-__opensock.patch
new file mode 100644
index 0000000..d78b010
--- /dev/null
+++ b/socket-Do-not-use-AF_NETLINK-in-__opensock.patch
@@ -0,0 +1,40 @@
+From 6eaf10cbb78d22eae7999d9de55f6b93999e0860 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 22 Nov 2021 14:41:14 +0100
+Subject: [PATCH] socket: Do not use AF_NETLINK in __opensock
+
+It is not possible to use interface ioctls with netlink sockets
+on all Linux kernels.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+(cherry picked from commit 3d981795cd00cc9b73c3ee5087c308361acd62e5)
+---
+ socket/opensock.c | 9 +--------
+ 1 file changed, 1 insertion(+), 8 deletions(-)
+
+diff --git a/socket/opensock.c b/socket/opensock.c
+index ff94d27a61..3e35821f91 100644
+--- a/socket/opensock.c
++++ b/socket/opensock.c
+@@ -24,17 +24,10 @@
+ int
+ __opensock (void)
+ {
+- /* SOCK_DGRAM is supported by all address families. (Netlink does
+- not support SOCK_STREAM.) */
++ /* SOCK_DGRAM is supported by all address families. */
+ int type = SOCK_DGRAM | SOCK_CLOEXEC;
+ int fd;
+
+-#ifdef AF_NETLINK
+- fd = __socket (AF_NETLINK, type, 0);
+- if (fd >= 0)
+- return fd;
+-#endif
+-
+ fd = __socket (AF_UNIX, type, 0);
+ if (fd >= 0)
+ return fd;
+--
+2.27.0
+
diff --git a/socket-Fix-mistyped-define-statement-in-socket-sys-s.patch b/socket-Fix-mistyped-define-statement-in-socket-sys-s.patch
new file mode 100644
index 0000000..5828aa8
--- /dev/null
+++ b/socket-Fix-mistyped-define-statement-in-socket-sys-s.patch
@@ -0,0 +1,26 @@
+From 999835533bc60fbd0b0b65d2412a6742e5a54b9d Mon Sep 17 00:00:00 2001
+From: Dmitriy Fedchenko <xfedch@gmail.com>
+Date: Mon, 6 Jun 2022 12:46:14 -0300
+Subject: [PATCH] socket: Fix mistyped define statement in socket/sys/socket.h
+ (BZ #29225)
+
+---
+ socket/sys/socket.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/socket/sys/socket.h b/socket/sys/socket.h
+index 7d5b21a2c4..0abfb5dd03 100644
+--- a/socket/sys/socket.h
++++ b/socket/sys/socket.h
+@@ -181,7 +181,7 @@ extern ssize_t __REDIRECT (sendmsg, (int __fd, const struct msghdr *__message,
+ # else
+ extern ssize_t __sendmsg64 (int __fd, const struct msghdr *__message,
+ int __flags);
+-# defien sendmsg __sendmsg64
++# define sendmsg __sendmsg64
+ # endif
+ #endif
+
+--
+2.23.0
+
diff --git a/sources b/sources
new file mode 100644
index 0000000..edfbc8f
--- /dev/null
+++ b/sources
@@ -0,0 +1,2 @@
+86e07edd97a3a8ce37c0c4e78845f849 backport-Add-generic-C.UTF-8-locale-Bug-17318.patch
+31998b53fb39cb946e96abc310af1c89 glibc-2.34.tar.xz
diff --git a/stdlib-Fix-formatting-of-tests-list-in-Makefile.patch b/stdlib-Fix-formatting-of-tests-list-in-Makefile.patch
new file mode 100644
index 0000000..db49888
--- /dev/null
+++ b/stdlib-Fix-formatting-of-tests-list-in-Makefile.patch
@@ -0,0 +1,178 @@
+From 73c362840c4efde45125a6c27bf41726397f4038 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Thu, 13 Jan 2022 18:50:55 +0530
+Subject: [PATCH] stdlib: Fix formatting of tests list in Makefile
+
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+(cherry picked from commit f9dab1b5f23d0fb008a56c7c6c8919adb49d3611)
+---
+ stdlib/Makefile | 152 ++++++++++++++++++++++++++++----------------------------
+ 1 file changed, 77 insertions(+), 75 deletions(-)
+
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index 6a1c358..9bb5c22 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -65,81 +65,83 @@ aux = grouping groupingwc tens_in_limb
+ static-only-routines = atexit at_quick_exit
+
+ test-srcs := tst-fmtmsg
+-tests := bug-fmtmsg1 \
+- bug-getcontext \
+- bug-strtod \
+- bug-strtod2 \
+- test-a64l \
+- test-at_quick_exit-race \
+- test-atexit-race \
+- test-bz22786 \
+- test-canon \
+- test-canon2 \
+- test-cxa_atexit-race \
+- test-cxa_atexit-race2 \
+- test-dlclose-exit-race \
+- test-on_exit-race \
+- testdiv \
+- testmb \
+- testmb2 \
+- testrand \
+- testsort \
+- tst-at_quick_exit \
+- tst-atexit \
+- tst-atof1 \
+- tst-atof2 \
+- tst-bsearch \
+- tst-bz20544 \
+- tst-canon-bz26341 \
+- tst-cxa_atexit \
+- tst-environ \
+- tst-getrandom \
+- tst-limits \
+- tst-makecontext \
+- tst-makecontext-align \
+- tst-makecontext2 \
+- tst-makecontext3 \
+- tst-on_exit \
+- tst-qsort \
+- tst-qsort2 \
+- tst-quick_exit \
+- tst-rand48 \
+- tst-rand48-2 \
+- tst-random \
+- tst-random2 \
+- tst-realpath \
+- tst-secure-getenv \
+- tst-setcontext \
+- tst-setcontext2 \
+- tst-setcontext3 \
+- tst-setcontext4 \
+- tst-setcontext5 \
+- tst-setcontext6 \
+- tst-setcontext7 \
+- tst-setcontext8 \
+- tst-setcontext9 \
+- tst-strfmon_l \
+- tst-strfrom \
+- tst-strfrom-locale \
+- tst-strtod \
+- tst-strtod-nan-locale \
+- tst-strtod-nan-sign \
+- tst-strtod-overflow \
+- tst-strtod-round \
+- tst-strtod-underflow \
+- tst-strtod2 \
+- tst-strtod5 \
+- tst-strtod6 \
+- tst-strtol \
+- tst-strtol-locale \
+- tst-strtoll \
+- tst-swapcontext1 \
+- tst-thread-quick_exit \
+- tst-tininess \
+- tst-unsetenv1 \
+- tst-width \
+- tst-width-stdint \
+- tst-xpg-basename
++tests := \
++ bug-fmtmsg1 \
++ bug-getcontext \
++ bug-strtod \
++ bug-strtod2 \
++ test-a64l \
++ test-at_quick_exit-race \
++ test-atexit-race \
++ test-bz22786 \
++ test-canon \
++ test-canon2 \
++ test-cxa_atexit-race \
++ test-cxa_atexit-race2 \
++ test-dlclose-exit-race \
++ test-on_exit-race \
++ testdiv \
++ testmb \
++ testmb2 \
++ testrand \
++ testsort \
++ tst-at_quick_exit \
++ tst-atexit \
++ tst-atof1 \
++ tst-atof2 \
++ tst-bsearch \
++ tst-bz20544 \
++ tst-canon-bz26341 \
++ tst-cxa_atexit \
++ tst-environ \
++ tst-getrandom \
++ tst-limits \
++ tst-makecontext \
++ tst-makecontext-align \
++ tst-makecontext2 \
++ tst-makecontext3 \
++ tst-on_exit \
++ tst-qsort \
++ tst-qsort2 \
++ tst-quick_exit \
++ tst-rand48 \
++ tst-rand48-2 \
++ tst-random \
++ tst-random2 \
++ tst-realpath \
++ tst-secure-getenv \
++ tst-setcontext \
++ tst-setcontext2 \
++ tst-setcontext3 \
++ tst-setcontext4 \
++ tst-setcontext5 \
++ tst-setcontext6 \
++ tst-setcontext7 \
++ tst-setcontext8 \
++ tst-setcontext9 \
++ tst-strfmon_l \
++ tst-strfrom \
++ tst-strfrom-locale \
++ tst-strtod \
++ tst-strtod-nan-locale \
++ tst-strtod-nan-sign \
++ tst-strtod-overflow \
++ tst-strtod-round \
++ tst-strtod-underflow \
++ tst-strtod2 \
++ tst-strtod5 \
++ tst-strtod6 \
++ tst-strtol \
++ tst-strtol-locale \
++ tst-strtoll \
++ tst-swapcontext1 \
++ tst-thread-quick_exit \
++ tst-tininess \
++ tst-unsetenv1 \
++ tst-width \
++ tst-width-stdint \
++ tst-xpg-basename \
++# tests
+
+ tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
+ tst-tls-atexit tst-tls-atexit-nodelete
+--
+1.8.3.1
+
diff --git a/stdlib-Sort-tests-in-Makefile.patch b/stdlib-Sort-tests-in-Makefile.patch
new file mode 100644
index 0000000..2e1cdf1
--- /dev/null
+++ b/stdlib-Sort-tests-in-Makefile.patch
@@ -0,0 +1,126 @@
+From 269eb9d930546ce57e83b56c44c430f154684a23 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Thu, 13 Jan 2022 10:34:37 +0530
+Subject: [PATCH] stdlib: Sort tests in Makefile
+
+Put one test per line and sort them.
+
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit 5b766603efa727c236a5f0cdcf09b71ff60b7584)
+---
+ stdlib/Makefile | 99 +++++++++++++++++++++++++++++++++++++++++++--------------
+ 1 file changed, 75 insertions(+), 24 deletions(-)
+
+diff --git a/stdlib/Makefile b/stdlib/Makefile
+index 7c15549..6a1c358 100644
+--- a/stdlib/Makefile
++++ b/stdlib/Makefile
+@@ -65,30 +65,81 @@ aux = grouping groupingwc tens_in_limb
+ static-only-routines = atexit at_quick_exit
+
+ test-srcs := tst-fmtmsg
+-tests := tst-strtol tst-strtod testmb testrand testsort testdiv \
+- test-canon test-canon2 tst-strtoll tst-environ \
+- tst-xpg-basename tst-random tst-random2 tst-bsearch \
+- tst-limits tst-rand48 bug-strtod tst-setcontext \
+- tst-setcontext2 test-a64l tst-qsort testmb2 \
+- bug-strtod2 tst-atof1 tst-atof2 tst-strtod2 \
+- tst-rand48-2 tst-makecontext tst-strtod5 \
+- tst-qsort2 tst-makecontext2 tst-strtod6 tst-unsetenv1 \
+- tst-makecontext3 bug-getcontext bug-fmtmsg1 \
+- tst-secure-getenv tst-strtod-overflow tst-strtod-round \
+- tst-tininess tst-strtod-underflow tst-setcontext3 \
+- tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l \
+- tst-quick_exit tst-thread-quick_exit tst-width \
+- tst-width-stdint tst-strfrom tst-strfrom-locale \
+- tst-getrandom tst-atexit tst-at_quick_exit \
+- tst-cxa_atexit tst-on_exit test-atexit-race \
+- test-at_quick_exit-race test-cxa_atexit-race \
+- test-cxa_atexit-race2 \
+- test-on_exit-race test-dlclose-exit-race \
+- tst-makecontext-align test-bz22786 tst-strtod-nan-sign \
+- tst-swapcontext1 tst-setcontext4 tst-setcontext5 \
+- tst-setcontext6 tst-setcontext7 tst-setcontext8 \
+- tst-setcontext9 tst-bz20544 tst-canon-bz26341 \
+- tst-realpath
++tests := bug-fmtmsg1 \
++ bug-getcontext \
++ bug-strtod \
++ bug-strtod2 \
++ test-a64l \
++ test-at_quick_exit-race \
++ test-atexit-race \
++ test-bz22786 \
++ test-canon \
++ test-canon2 \
++ test-cxa_atexit-race \
++ test-cxa_atexit-race2 \
++ test-dlclose-exit-race \
++ test-on_exit-race \
++ testdiv \
++ testmb \
++ testmb2 \
++ testrand \
++ testsort \
++ tst-at_quick_exit \
++ tst-atexit \
++ tst-atof1 \
++ tst-atof2 \
++ tst-bsearch \
++ tst-bz20544 \
++ tst-canon-bz26341 \
++ tst-cxa_atexit \
++ tst-environ \
++ tst-getrandom \
++ tst-limits \
++ tst-makecontext \
++ tst-makecontext-align \
++ tst-makecontext2 \
++ tst-makecontext3 \
++ tst-on_exit \
++ tst-qsort \
++ tst-qsort2 \
++ tst-quick_exit \
++ tst-rand48 \
++ tst-rand48-2 \
++ tst-random \
++ tst-random2 \
++ tst-realpath \
++ tst-secure-getenv \
++ tst-setcontext \
++ tst-setcontext2 \
++ tst-setcontext3 \
++ tst-setcontext4 \
++ tst-setcontext5 \
++ tst-setcontext6 \
++ tst-setcontext7 \
++ tst-setcontext8 \
++ tst-setcontext9 \
++ tst-strfmon_l \
++ tst-strfrom \
++ tst-strfrom-locale \
++ tst-strtod \
++ tst-strtod-nan-locale \
++ tst-strtod-nan-sign \
++ tst-strtod-overflow \
++ tst-strtod-round \
++ tst-strtod-underflow \
++ tst-strtod2 \
++ tst-strtod5 \
++ tst-strtod6 \
++ tst-strtol \
++ tst-strtol-locale \
++ tst-strtoll \
++ tst-swapcontext1 \
++ tst-thread-quick_exit \
++ tst-tininess \
++ tst-unsetenv1 \
++ tst-width \
++ tst-width-stdint \
++ tst-xpg-basename
+
+ tests-internal := tst-strtod1i tst-strtod3 tst-strtod4 tst-strtod5i \
+ tst-tls-atexit tst-tls-atexit-nodelete
+--
+1.8.3.1
+
diff --git a/stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch b/stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch
new file mode 100644
index 0000000..baaeb5e
--- /dev/null
+++ b/stdlib-strfrom-Add-copysign-to-fix-NAN-issue-on-risc.patch
@@ -0,0 +1,176 @@
+From 0cc0033ef19bd3378445c2b851e53d7255cb1b1e Mon Sep 17 00:00:00 2001
+From: Letu Ren <fantasquex@gmail.com>
+Date: Fri, 21 Oct 2022 22:54:50 +0800
+Subject: [PATCH] stdlib/strfrom: Add copysign to fix NAN issue on riscv (BZ
+ #29501)
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+According to the specification of ISO/IEC TS 18661-1:2014,
+
+The strfromd, strfromf, and strfroml functions are equivalent to
+snprintf(s, n, format, fp) (7.21.6.5), except the format string contains only
+the character %, an optional precision that does not contain an asterisk *, and
+one of the conversion specifiers a, A, e, E, f, F, g, or G, which applies to
+the type (double, float, or long double) indicated by the function suffix
+(rather than by a length modifier). Use of these functions with any other 20
+format string results in undefined behavior.
+
+strfromf will convert the arguement with type float to double first.
+
+According to the latest version of IEEE754 which is published in 2019,
+
+Conversion of a quiet NaN from a narrower format to a wider format in the same
+radix, and then back to the same narrower format, should not change the quiet
+NaN payload in any way except to make it canonical.
+
+When either an input or result is a NaN, this standard does not interpret the
+sign of a NaN. However, operations on bit strings—copy, negate, abs,
+copySign—specify the sign bit of a NaN result, sometimes based upon the sign
+bit of a NaN operand. The logical predicates totalOrder and isSignMinus are
+also affected by the sign bit of a NaN operand. For all other operations, this
+standard does not specify the sign bit of a NaN result, even when there is only
+one input NaN, or when the NaN is produced from an invalid operation.
+
+converting NAN or -NAN with type float to double doesn't need to keep
+the signbit. As a result, this test case isn't mandatory.
+
+The problem is that according to RISC-V ISA manual in chapter 11.3 of
+riscv-isa-20191213,
+
+Except when otherwise stated, if the result of a floating-point operation is
+NaN, it is the canonical NaN. The canonical NaN has a positive sign and all
+significand bits clear except the MSB, a.k.a. the quiet bit. For
+single-precision floating-point, this corresponds to the pattern 0x7fc00000.
+
+which means that conversion -NAN from float to double won't keep the signbit.
+
+Since glibc ought to be consistent here between types and architectures, this
+patch adds copysign to fix this problem if the string is NAN. This patch
+adds two different functions under sysdeps directory to work around the
+issue.
+
+This patch has been tested on x86_64 and riscv64.
+
+Resolves: BZ #29501
+
+v2: Change from macros to different inline functions.
+v3: Add unlikely check to isnan.
+v4: Fix wrong commit message header.
+v5: Fix style: add space before parentheses.
+v6: Add copyright.
+Signed-off-by: Letu Ren <fantasquex@gmail.com>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ stdlib/strfrom-skeleton.c | 3 +-
+ .../generic/fix-float-double-convert-nan.h | 31 ++++++++++++++++
+ .../riscv/rvd/fix-float-double-convert-nan.h | 37 +++++++++++++++++++
+ 3 files changed, 70 insertions(+), 1 deletion(-)
+ create mode 100644 sysdeps/generic/fix-float-double-convert-nan.h
+ create mode 100644 sysdeps/riscv/rvd/fix-float-double-convert-nan.h
+
+diff --git a/stdlib/strfrom-skeleton.c b/stdlib/strfrom-skeleton.c
+index 1fba04bf6a..36e9adcad5 100644
+--- a/stdlib/strfrom-skeleton.c
++++ b/stdlib/strfrom-skeleton.c
+@@ -27,6 +27,7 @@
+ #include <printf.h>
+ #include <string.h>
+ #include <locale/localeinfo.h>
++#include <fix-float-double-convert-nan.h>
+
+ #define UCHAR_T char
+ #define L_(Str) Str
+@@ -61,7 +62,7 @@ STRFROM (char *dest, size_t size, const char *format, FLOAT f)
+ because __printf_fp and __printf_fphex only accept double and long double
+ as the floating-point argument. */
+ if (__builtin_types_compatible_p (FLOAT, float))
+- fpnum.flt = f;
++ fpnum.flt = keep_sign_conversion (f);
+ else
+ fpnum.value = f;
+
+diff --git a/sysdeps/generic/fix-float-double-convert-nan.h b/sysdeps/generic/fix-float-double-convert-nan.h
+new file mode 100644
+index 0000000000..66692262fc
+--- /dev/null
++++ b/sysdeps/generic/fix-float-double-convert-nan.h
+@@ -0,0 +1,31 @@
++/* Fix for conversion of float NAN to double. Generic version.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef FIX_FLOAT_DOUBLE_CONVERT_NAN_H
++#define FIX_FLOAT_DOUBLE_CONVERT_NAN_H
++
++/* This function aims to work around conversions of float -NAN
++ to double returning NAN instead of the correct -NAN in some
++ architectures. */
++static inline double __attribute__ ((always_inline))
++keep_sign_conversion (float flt)
++{
++ return flt;
++}
++
++#endif
+diff --git a/sysdeps/riscv/rvd/fix-float-double-convert-nan.h b/sysdeps/riscv/rvd/fix-float-double-convert-nan.h
+new file mode 100644
+index 0000000000..cab003f3c1
+--- /dev/null
++++ b/sysdeps/riscv/rvd/fix-float-double-convert-nan.h
+@@ -0,0 +1,37 @@
++/* Fix for conversion of float NAN to double. RISC-V version..
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library. If not, see
++ <https://www.gnu.org/licenses/>. */
++
++#ifndef FIX_FLOAT_DOUBLE_CONVERT_NAN_H
++#define FIX_FLOAT_DOUBLE_CONVERT_NAN_H
++
++#include <math.h>
++
++/* RISC-V rvd instructions do not preserve the signbit of NAN
++ when converting from float to double. */
++static inline double
++keep_sign_conversion (float flt)
++{
++ if (__glibc_unlikely (isnan (flt)))
++ {
++ float x = copysignf (1.f, flt);
++ return copysign ((double) flt, (double) x);
++ }
++ return flt;
++}
++
++#endif
+--
+2.39.2
+
diff --git a/strcmp-delete-align-for-loop_aligned.patch b/strcmp-delete-align-for-loop_aligned.patch
new file mode 100644
index 0000000..cf5b15a
--- /dev/null
+++ b/strcmp-delete-align-for-loop_aligned.patch
@@ -0,0 +1,32 @@
+From 9bbffed83b93f633b272368fc536a4f24e9942e6 Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Mon, 21 Feb 2022 14:25:25 +0800
+Subject: [PATCH] strcmp: delete align for loop_aligned
+
+In Kunpeng-920, the performance of strcmp deteriorates only
+when the 16 to 23 characters are different.Or the string is
+only 16-23 characters.That shows 2 misses per iteration which
+means this is a branch predictor issue indeed.
+In the preceding scenario, strcmp performance is 300% worse than expected.
+
+Fortunately, this problem can be solved by modifying the alignment of the functions.
+---
+ sysdeps/aarch64/strcmp.S | 2 --
+ 1 file changed, 2 deletions(-)
+
+diff --git a/sysdeps/aarch64/strcmp.S b/sysdeps/aarch64/strcmp.S
+index f225d718..7a048b66 100644
+--- a/sysdeps/aarch64/strcmp.S
++++ b/sysdeps/aarch64/strcmp.S
+@@ -71,8 +71,6 @@ ENTRY(strcmp)
+ b.ne L(misaligned8)
+ cbnz tmp, L(mutual_align)
+
+- .p2align 4
+-
+ L(loop_aligned):
+ ldr data2, [src1, off2]
+ ldr data1, [src1], 8
+--
+2.33.0
+
diff --git a/sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch b/sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch
new file mode 100644
index 0000000..8d2bec4
--- /dev/null
+++ b/sunrpc-Test-case-for-clnt_create-unix-buffer-overflo.patch
@@ -0,0 +1,89 @@
+From ef972a4c50014a16132b5c75571cfb6b30bef136 Mon Sep 17 00:00:00 2001
+From: Martin Sebor <msebor@redhat.com>
+Date: Mon, 17 Jan 2022 10:21:34 +0100
+Subject: [PATCH] sunrpc: Test case for clnt_create "unix" buffer overflow (bug
+ 22542)
+
+Reviewed-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+---
+ sunrpc/Makefile | 5 ++++-
+ sunrpc/tst-bug22542.c | 44 ++++++++++++++++++++++++++++++++++++++++++++
+ 2 files changed, 48 insertions(+), 1 deletion(-)
+ create mode 100644 sunrpc/tst-bug22542.c
+
+diff --git a/sunrpc/Makefile b/sunrpc/Makefile
+index 9a31fe4..183ef3d 100644
+--- a/sunrpc/Makefile
++++ b/sunrpc/Makefile
+@@ -65,7 +65,8 @@ shared-only-routines = $(routines)
+ endif
+
+ tests = tst-xdrmem tst-xdrmem2 test-rpcent tst-udp-error tst-udp-timeout \
+- tst-udp-nonblocking
++ tst-udp-nonblocking tst-bug22542
++
+ xtests := tst-getmyaddr
+
+ ifeq ($(have-thread-library),yes)
+@@ -110,6 +111,8 @@ $(objpfx)tst-udp-nonblocking: $(common-objpfx)linkobj/libc.so
+ $(objpfx)tst-udp-garbage: \
+ $(common-objpfx)linkobj/libc.so $(shared-thread-library)
+
++$(objpfx)tst-bug22542: $(common-objpfx)linkobj/libc.so
++
+ else # !have-GLIBC_2.31
+
+ routines = $(routines-for-nss)
+diff --git a/sunrpc/tst-bug22542.c b/sunrpc/tst-bug22542.c
+new file mode 100644
+index 0000000..d6cd797
+--- /dev/null
++++ b/sunrpc/tst-bug22542.c
+@@ -0,0 +1,44 @@
++/* Test to verify that overlong hostname is rejected by clnt_create
++ and doesn't cause a buffer overflow (bug 22542).
++
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <http://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <rpc/clnt.h>
++#include <string.h>
++#include <support/check.h>
++#include <sys/socket.h>
++#include <sys/un.h>
++
++static int
++do_test (void)
++{
++ /* Create an arbitrary hostname that's longer than fits in sun_path. */
++ char name [sizeof ((struct sockaddr_un*)0)->sun_path * 2];
++ memset (name, 'x', sizeof name - 1);
++ name [sizeof name - 1] = '\0';
++
++ errno = 0;
++ CLIENT *clnt = clnt_create (name, 0, 0, "unix");
++
++ TEST_VERIFY (clnt == NULL);
++ TEST_COMPARE (errno, EINVAL);
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/support-Add-check-for-TID-zero-in-support_wait_for_t.patch b/support-Add-check-for-TID-zero-in-support_wait_for_t.patch
new file mode 100644
index 0000000..faccebf
--- /dev/null
+++ b/support-Add-check-for-TID-zero-in-support_wait_for_t.patch
@@ -0,0 +1,42 @@
+From 176c88f5214d8107d330971cbbfbbba5186a111f Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Fri, 1 Oct 2021 18:16:41 +0200
+Subject: [PATCH] support: Add check for TID zero in
+ support_wait_for_thread_exit
+
+Some kernel versions (observed with kernel 5.14 and earlier) can list
+"0" entries in /proc/self/task. This happens when a thread exits
+while the task list is being constructed. Treat this entry as not
+present, like the proposed kernel patch does:
+
+[PATCH] procfs: Do not list TID 0 in /proc/<pid>/task
+<https://lore.kernel.org/all/8735pn5dx7.fsf@oldenburg.str.redhat.com/>
+
+Fixes commit 032d74eaf6179100048a5bf0ce942e97dc8b9a60 ("support: Add
+support_wait_for_thread_exit").
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+Tested-by: Carlos O'Donell <carlos@redhat.com>
+---
+ support/support_wait_for_thread_exit.c | 5 ++++-
+ 1 file changed, 4 insertions(+), 1 deletion(-)
+
+diff --git a/support/support_wait_for_thread_exit.c b/support/support_wait_for_thread_exit.c
+index 658a813..5e3be42 100644
+--- a/support/support_wait_for_thread_exit.c
++++ b/support/support_wait_for_thread_exit.c
+@@ -43,7 +43,10 @@ support_wait_for_thread_exit (void)
+ return;
+ }
+
+- if (strcmp (e->d_name, ".") == 0 || strcmp (e->d_name, "..") == 0)
++ /* In some kernels, "0" entries denote a thread that has just
++ exited. */
++ if (strcmp (e->d_name, ".") == 0 || strcmp (e->d_name, "..") == 0
++ || strcmp (e->d_name, "0") == 0)
+ continue;
+
+ int task_tid = atoi (e->d_name);
+--
+1.8.3.1
+
diff --git a/support-Add-helpers-to-create-paths-longer-than-PATH.patch b/support-Add-helpers-to-create-paths-longer-than-PATH.patch
new file mode 100644
index 0000000..4d4e737
--- /dev/null
+++ b/support-Add-helpers-to-create-paths-longer-than-PATH.patch
@@ -0,0 +1,282 @@
+From 062ff490c1467059f6cd64bb9c3d85f6cc6cf97a Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Tue, 18 Jan 2022 13:29:36 +0530
+Subject: [PATCH] support: Add helpers to create paths longer than PATH_MAX
+
+Add new helpers support_create_and_chdir_toolong_temp_directory and
+support_chdir_toolong_temp_directory to create and descend into
+directory trees longer than PATH_MAX.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit fb7bff12e81c677a6622f724edd4d4987dd9d971)
+---
+ support/temp_file.c | 161 ++++++++++++++++++++++++++++++++++++++++++++++++----
+ support/temp_file.h | 9 +++
+ 2 files changed, 160 insertions(+), 10 deletions(-)
+
+diff --git a/support/temp_file.c b/support/temp_file.c
+index c6df641..e41128c 100644
+--- a/support/temp_file.c
++++ b/support/temp_file.c
+@@ -1,5 +1,6 @@
+ /* Temporary file handling for tests.
+- Copyright (C) 1998-2021 Free Software Foundation, Inc.
++ Copyright (C) 1998-2022 Free Software Foundation, Inc.
++ Copyright The GNU Tools Authors.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+@@ -20,15 +21,17 @@
+ some 32-bit platforms. */
+ #define _FILE_OFFSET_BITS 64
+
++#include <support/check.h>
+ #include <support/temp_file.h>
+ #include <support/temp_file-internal.h>
+ #include <support/support.h>
+
++#include <errno.h>
+ #include <paths.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <string.h>
+-#include <unistd.h>
++#include <xunistd.h>
+
+ /* List of temporary files. */
+ static struct temp_name_list
+@@ -36,14 +39,20 @@ static struct temp_name_list
+ struct temp_name_list *next;
+ char *name;
+ pid_t owner;
++ bool toolong;
+ } *temp_name_list;
+
+ /* Location of the temporary files. Set by the test skeleton via
+ support_set_test_dir. The string is not be freed. */
+ static const char *test_dir = _PATH_TMP;
+
+-void
+-add_temp_file (const char *name)
++/* Name of subdirectories in a too long temporary directory tree. */
++static char toolong_subdir[NAME_MAX + 1];
++static bool toolong_initialized;
++static size_t toolong_path_max;
++
++static void
++add_temp_file_internal (const char *name, bool toolong)
+ {
+ struct temp_name_list *newp
+ = (struct temp_name_list *) xcalloc (sizeof (*newp), 1);
+@@ -53,12 +62,19 @@ add_temp_file (const char *name)
+ newp->name = newname;
+ newp->next = temp_name_list;
+ newp->owner = getpid ();
++ newp->toolong = toolong;
+ temp_name_list = newp;
+ }
+ else
+ free (newp);
+ }
+
++void
++add_temp_file (const char *name)
++{
++ add_temp_file_internal (name, false);
++}
++
+ int
+ create_temp_file_in_dir (const char *base, const char *dir, char **filename)
+ {
+@@ -90,8 +106,8 @@ create_temp_file (const char *base, char **filename)
+ return create_temp_file_in_dir (base, test_dir, filename);
+ }
+
+-char *
+-support_create_temp_directory (const char *base)
++static char *
++create_temp_directory_internal (const char *base, bool toolong)
+ {
+ char *path = xasprintf ("%s/%sXXXXXX", test_dir, base);
+ if (mkdtemp (path) == NULL)
+@@ -99,16 +115,132 @@ support_create_temp_directory (const char *base)
+ printf ("error: mkdtemp (\"%s\"): %m", path);
+ exit (1);
+ }
+- add_temp_file (path);
++ add_temp_file_internal (path, toolong);
+ return path;
+ }
+
+-/* Helper functions called by the test skeleton follow. */
++char *
++support_create_temp_directory (const char *base)
++{
++ return create_temp_directory_internal (base, false);
++}
++
++static void
++ensure_toolong_initialized (void)
++{
++ if (!toolong_initialized)
++ FAIL_EXIT1 ("uninitialized toolong directory tree\n");
++}
++
++static void
++initialize_toolong (const char *base)
++{
++ long name_max = pathconf (base, _PC_NAME_MAX);
++ name_max = (name_max < 0 ? 64
++ : (name_max < sizeof (toolong_subdir) ? name_max
++ : sizeof (toolong_subdir) - 1));
++
++ long path_max = pathconf (base, _PC_PATH_MAX);
++ path_max = (path_max < 0 ? 1024
++ : path_max <= PTRDIFF_MAX ? path_max : PTRDIFF_MAX);
++
++ /* Sanity check to ensure that the test does not create temporary directories
++ in different filesystems because this API doesn't support it. */
++ if (toolong_initialized)
++ {
++ if (name_max != strlen (toolong_subdir))
++ FAIL_UNSUPPORTED ("name_max: Temporary directories in different"
++ " filesystems not supported yet\n");
++ if (path_max != toolong_path_max)
++ FAIL_UNSUPPORTED ("path_max: Temporary directories in different"
++ " filesystems not supported yet\n");
++ return;
++ }
++
++ toolong_path_max = path_max;
++
++ size_t len = name_max;
++ memset (toolong_subdir, 'X', len);
++ toolong_initialized = true;
++}
++
++char *
++support_create_and_chdir_toolong_temp_directory (const char *basename)
++{
++ char *base = create_temp_directory_internal (basename, true);
++ xchdir (base);
++
++ initialize_toolong (base);
++
++ size_t sz = strlen (toolong_subdir);
++
++ /* Create directories and descend into them so that the final path is larger
++ than PATH_MAX. */
++ for (size_t i = 0; i <= toolong_path_max / sz; i++)
++ {
++ int ret = mkdir (toolong_subdir, S_IRWXU);
++ if (ret != 0 && errno == ENAMETOOLONG)
++ FAIL_UNSUPPORTED ("Filesystem does not support creating too long "
++ "directory trees\n");
++ else if (ret != 0)
++ FAIL_EXIT1 ("Failed to create directory tree: %m\n");
++ xchdir (toolong_subdir);
++ }
++ return base;
++}
+
+ void
+-support_set_test_dir (const char *path)
++support_chdir_toolong_temp_directory (const char *base)
+ {
+- test_dir = path;
++ ensure_toolong_initialized ();
++
++ xchdir (base);
++
++ size_t sz = strlen (toolong_subdir);
++ for (size_t i = 0; i <= toolong_path_max / sz; i++)
++ xchdir (toolong_subdir);
++}
++
++/* Helper functions called by the test skeleton follow. */
++
++static void
++remove_toolong_subdirs (const char *base)
++{
++ ensure_toolong_initialized ();
++
++ if (chdir (base) != 0)
++ {
++ printf ("warning: toolong cleanup base failed: chdir (\"%s\"): %m\n",
++ base);
++ return;
++ }
++
++ /* Descend. */
++ int levels = 0;
++ size_t sz = strlen (toolong_subdir);
++ for (levels = 0; levels <= toolong_path_max / sz; levels++)
++ if (chdir (toolong_subdir) != 0)
++ {
++ printf ("warning: toolong cleanup failed: chdir (\"%s\"): %m\n",
++ toolong_subdir);
++ break;
++ }
++
++ /* Ascend and remove. */
++ while (--levels >= 0)
++ {
++ if (chdir ("..") != 0)
++ {
++ printf ("warning: toolong cleanup failed: chdir (\"..\"): %m\n");
++ return;
++ }
++ if (remove (toolong_subdir) != 0)
++ {
++ printf ("warning: could not remove subdirectory: %s: %m\n",
++ toolong_subdir);
++ return;
++ }
++ }
+ }
+
+ void
+@@ -123,6 +255,9 @@ support_delete_temp_files (void)
+ around, to prevent PID reuse.) */
+ if (temp_name_list->owner == pid)
+ {
++ if (temp_name_list->toolong)
++ remove_toolong_subdirs (temp_name_list->name);
++
+ if (remove (temp_name_list->name) != 0)
+ printf ("warning: could not remove temporary file: %s: %m\n",
+ temp_name_list->name);
+@@ -147,3 +282,9 @@ support_print_temp_files (FILE *f)
+ fprintf (f, ")\n");
+ }
+ }
++
++void
++support_set_test_dir (const char *path)
++{
++ test_dir = path;
++}
+diff --git a/support/temp_file.h b/support/temp_file.h
+index f3a7fb6..a22964c 100644
+--- a/support/temp_file.h
++++ b/support/temp_file.h
+@@ -44,6 +44,15 @@ int create_temp_file_in_dir (const char *base, const char *dir,
+ returns. The caller should free this string. */
+ char *support_create_temp_directory (const char *base);
+
++/* Create a temporary directory tree that is longer than PATH_MAX and schedule
++ it for deletion. BASENAME is used as a prefix for the unique directory
++ name, which the function returns. The caller should free this string. */
++char *support_create_and_chdir_toolong_temp_directory (const char *basename);
++
++/* Change into the innermost directory of the directory tree BASE, which was
++ created using support_create_and_chdir_toolong_temp_directory. */
++void support_chdir_toolong_temp_directory (const char *base);
++
+ __END_DECLS
+
+ #endif /* SUPPORT_TEMP_FILE_H */
+--
+1.8.3.1
+
diff --git a/support-Add-support_open_dev_null_range.patch b/support-Add-support_open_dev_null_range.patch
new file mode 100644
index 0000000..0b78f8c
--- /dev/null
+++ b/support-Add-support_open_dev_null_range.patch
@@ -0,0 +1,363 @@
+From e814f4b04ee413a7bb3dfa43e74c8fb4abf58359 Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Tue, 24 Aug 2021 16:12:24 -0300
+Subject: [PATCH] support: Add support_open_dev_null_range
+
+It returns a range of file descriptor referring to the '/dev/null'
+pathname. The function takes care of restarting the open range
+if a file descriptor is found within the specified range and
+also increases RLIMIT_NOFILE if required.
+
+Checked on x86_64-linux-gnu.
+---
+ support/Makefile | 2 +
+ support/support-open-dev-null-range.c | 134 ++++++++++++++++++++++++++
+ support/support.h | 8 ++
+ support/tst-support-open-dev-null-range.c | 155 ++++++++++++++++++++++++++++++
+ 4 files changed, 299 insertions(+)
+ create mode 100644 support/support-open-dev-null-range.c
+ create mode 100644 support/tst-support-open-dev-null-range.c
+
+diff --git a/support/Makefile b/support/Makefile
+index a462781..6332e7b 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -66,6 +66,7 @@ libsupport-routines = \
+ support_path_support_time64 \
+ support_process_state \
+ support_ptrace \
++ support-open-dev-null-range \
+ support_openpty \
+ support_paths \
+ support_quote_blob \
+@@ -264,6 +265,7 @@ tests = \
+ tst-support_capture_subprocess \
+ tst-support_descriptors \
+ tst-support_format_dns_packet \
++ tst-support-open-dev-null-range \
+ tst-support-process_state \
+ tst-support_quote_blob \
+ tst-support_quote_string \
+diff --git a/support/support-open-dev-null-range.c b/support/support-open-dev-null-range.c
+new file mode 100644
+index 0000000..80d9dba
+--- /dev/null
++++ b/support/support-open-dev-null-range.c
+@@ -0,0 +1,134 @@
++/* Return a range of open file descriptors.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <fcntl.h>
++#include <support/support.h>
++#include <support/check.h>
++#include <support/xunistd.h>
++#include <stdlib.h>
++#include <sys/resource.h>
++
++static void
++increase_nofile (void)
++{
++ struct rlimit rl;
++ if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
++ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
++
++ rl.rlim_cur += 128;
++
++ if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
++ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
++}
++
++static int
++open_dev_null (int flags, mode_t mode)
++{
++ int fd = open64 ("/dev/null", flags, mode);
++ if (fd > 0)
++ return fd;
++
++ if (fd < 0 && errno != EMFILE)
++ FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode);
++
++ increase_nofile ();
++
++ return xopen ("/dev/null", flags, mode);
++}
++
++struct range
++{
++ int lowfd;
++ size_t len;
++};
++
++struct range_list
++{
++ size_t total;
++ size_t used;
++ struct range *ranges;
++};
++
++static void
++range_init (struct range_list *r)
++{
++ r->total = 8;
++ r->used = 0;
++ r->ranges = xmalloc (r->total * sizeof (struct range));
++}
++
++static void
++range_add (struct range_list *r, int lowfd, size_t len)
++{
++ if (r->used == r->total)
++ {
++ r->total *= 2;
++ r->ranges = xrealloc (r->ranges, r->total * sizeof (struct range));
++ }
++ r->ranges[r->used].lowfd = lowfd;
++ r->ranges[r->used].len = len;
++ r->used++;
++}
++
++static void
++range_close (struct range_list *r)
++{
++ for (size_t i = 0; i < r->used; i++)
++ {
++ int minfd = r->ranges[i].lowfd;
++ int maxfd = r->ranges[i].lowfd + r->ranges[i].len;
++ for (int fd = minfd; fd < maxfd; fd++)
++ xclose (fd);
++ }
++ free (r->ranges);
++}
++
++int
++support_open_dev_null_range (int num, int flags, mode_t mode)
++{
++ /* We keep track of the ranges that hit an already opened descriptor, so
++ we close them after we get a working range. */
++ struct range_list rl;
++ range_init (&rl);
++
++ int lowfd = open_dev_null (flags, mode);
++ int prevfd = lowfd;
++ while (true)
++ {
++ int i = 1;
++ for (; i < num; i++)
++ {
++ int fd = open_dev_null (flags, mode);
++ if (fd != lowfd + i)
++ {
++ range_add (&rl, lowfd, prevfd - lowfd + 1);
++
++ prevfd = lowfd = fd;
++ break;
++ }
++ prevfd = fd;
++ }
++ if (i == num)
++ break;
++ }
++
++ range_close (&rl);
++
++ return lowfd;
++}
+diff --git a/support/support.h b/support/support.h
+index 834dba9..e6911e1 100644
+--- a/support/support.h
++++ b/support/support.h
+@@ -193,6 +193,14 @@ struct support_stack support_stack_alloc (size_t size);
+ /* Deallocate the STACK. */
+ void support_stack_free (struct support_stack *stack);
+
++
++/* Create a range of NUM opened '/dev/null' file descriptors using FLAGS and
++ MODE. The function takes care of restarting the open range if a file
++ descriptor is found within the specified range and also increases
++ RLIMIT_NOFILE if required.
++ The returned value is the lowest file descriptor number. */
++int support_open_dev_null_range (int num, int flags, mode_t mode);
++
+ __END_DECLS
+
+ #endif /* SUPPORT_H */
+diff --git a/support/tst-support-open-dev-null-range.c b/support/tst-support-open-dev-null-range.c
+new file mode 100644
+index 0000000..8e29def
+--- /dev/null
++++ b/support/tst-support-open-dev-null-range.c
+@@ -0,0 +1,155 @@
++/* Tests for support_open_dev_null_range.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <dirent.h>
++#include <fcntl.h>
++#include <limits.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <support/xunistd.h>
++#include <sys/resource.h>
++#include <stdlib.h>
++
++#ifndef PATH_MAX
++# define PATH_MAX 1024
++#endif
++
++#include <stdio.h>
++
++static void
++check_path (int fd)
++{
++ char *proc_fd_path = xasprintf ("/proc/self/fd/%d", fd);
++ char file_path[PATH_MAX];
++ ssize_t file_path_length
++ = readlink (proc_fd_path, file_path, sizeof (file_path));
++ free (proc_fd_path);
++ if (file_path_length < 0)
++ FAIL_EXIT1 ("readlink (%s, %p, %zu)", proc_fd_path, file_path,
++ sizeof (file_path));
++ file_path[file_path_length] = '\0';
++ TEST_COMPARE_STRING (file_path, "/dev/null");
++}
++
++static int
++number_of_opened_files (void)
++{
++ DIR *fds = opendir ("/proc/self/fd");
++ if (fds == NULL)
++ FAIL_EXIT1 ("opendir (\"/proc/self/fd\"): %m");
++
++ int r = 0;
++ while (true)
++ {
++ errno = 0;
++ struct dirent64 *e = readdir64 (fds);
++ if (e == NULL)
++ {
++ if (errno != 0)
++ FAIL_EXIT1 ("readdir: %m");
++ break;
++ }
++
++ if (e->d_name[0] == '.')
++ continue;
++
++ char *endptr;
++ long int fd = strtol (e->d_name, &endptr, 10);
++ if (*endptr != '\0' || fd < 0 || fd > INT_MAX)
++ FAIL_EXIT1 ("readdir: invalid file descriptor name: /proc/self/fd/%s",
++ e->d_name);
++
++ /* Skip the descriptor which is used to enumerate the
++ descriptors. */
++ if (fd == dirfd (fds))
++ continue;
++
++ r = r + 1;
++ }
++
++ closedir (fds);
++
++ return r;
++}
++
++static int
++do_test (void)
++{
++ const int nfds1 = 8;
++ int lowfd = support_open_dev_null_range (nfds1, O_RDONLY, 0600);
++ for (int i = 0; i < nfds1; i++)
++ {
++ TEST_VERIFY (fcntl (lowfd + i, F_GETFL) > -1);
++ check_path (lowfd + i);
++ }
++
++ /* create some gaps. */
++ xclose (lowfd + 1);
++ xclose (lowfd + 5);
++ xclose (lowfd + 6);
++
++ const int nfds2 = 16;
++ int lowfd2 = support_open_dev_null_range (nfds2, O_RDONLY, 0600);
++ for (int i = 0; i < nfds2; i++)
++ {
++ TEST_VERIFY (fcntl (lowfd2 + i, F_GETFL) > -1);
++ check_path (lowfd2 + i);
++ }
++
++ /* Decrease the maximum number of files. */
++ {
++ struct rlimit rl;
++ if (getrlimit (RLIMIT_NOFILE, &rl) == -1)
++ FAIL_EXIT1 ("getrlimit (RLIMIT_NOFILE): %m");
++
++ rl.rlim_cur = number_of_opened_files ();
++
++ if (setrlimit (RLIMIT_NOFILE, &rl) == 1)
++ FAIL_EXIT1 ("setrlimit (RLIMIT_NOFILE): %m");
++ }
++
++ const int nfds3 = 16;
++ int lowfd3 = support_open_dev_null_range (nfds3, O_RDONLY, 0600);
++ for (int i = 0; i < nfds3; i++)
++ {
++ TEST_VERIFY (fcntl (lowfd3 + i, F_GETFL) > -1);
++ check_path (lowfd3 + i);
++ }
++
++ /* create a lot of gaps to trigger the range extension. */
++ xclose (lowfd3 + 1);
++ xclose (lowfd3 + 3);
++ xclose (lowfd3 + 5);
++ xclose (lowfd3 + 7);
++ xclose (lowfd3 + 9);
++ xclose (lowfd3 + 11);
++ xclose (lowfd3 + 13);
++
++ const int nfds4 = 16;
++ int lowfd4 = support_open_dev_null_range (nfds4, O_RDONLY, 0600);
++ for (int i = 0; i < nfds4; i++)
++ {
++ TEST_VERIFY (fcntl (lowfd4 + i, F_GETFL) > -1);
++ check_path (lowfd4 + i);
++ }
++
++ return 0;
++}
++
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/support-Add-support_socket_so_timestamp_time64.patch b/support-Add-support_socket_so_timestamp_time64.patch
new file mode 100644
index 0000000..e6f9922
--- /dev/null
+++ b/support-Add-support_socket_so_timestamp_time64.patch
@@ -0,0 +1,103 @@
+From e09e7b1492b2d5c2f68ddf81f8f58e093dd4df6d Mon Sep 17 00:00:00 2001
+From: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+Date: Mon, 13 Dec 2021 11:36:42 -0300
+Subject: [PATCH] support: Add support_socket_so_timestamp_time64
+
+Check if the socket support 64-bit network packages timestamps
+(SO_TIMESTAMP and SO_TIMESTAMPNS). This will be used on recvmsg
+and recvmmsg tests to check if the timestamp should be generated.
+
+Reviewed-by: Florian Weimer <fweimer@redhat.com>
+
+(cherry picked from 38bc0f4e78934aab455b31af05cefcbf3c22bece)
+---
+ support/Makefile | 1 +
+ support/support.h | 4 ++
+ support/support_socket_so_timestamp_time64.c | 48 ++++++++++++++++++++
+ 3 files changed, 53 insertions(+)
+ create mode 100644 support/support_socket_so_timestamp_time64.c
+
+diff --git a/support/Makefile b/support/Makefile
+index 2a0731796f..724ae6d712 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -78,6 +78,7 @@ libsupport-routines = \
+ support_set_small_thread_stack_size \
+ support_shared_allocate \
+ support_small_stack_thread_attribute \
++ support_socket_so_timestamp_time64 \
+ support_stat_nanoseconds \
+ support_subprocess \
+ support_test_compare_blob \
+diff --git a/support/support.h b/support/support.h
+index c219e0d9d1..309be85b09 100644
+--- a/support/support.h
++++ b/support/support.h
+@@ -164,6 +164,10 @@ extern bool support_select_modifies_timeout (void);
+ tv_usec larger than 1000000. */
+ extern bool support_select_normalizes_timeout (void);
+
++/* Return true if socket FD supports 64-bit timestamps with the SOL_SOCKET
++ and SO_TIMESTAMP/SO_TIMESTAMPNS. */
++extern bool support_socket_so_timestamp_time64 (int fd);
++
+ /* Create a timer that trigger after SEC seconds and NSEC nanoseconds. If
+ REPEAT is true the timer will repeat indefinitely. If CALLBACK is not
+ NULL, the function will be called when the timer expires; otherwise a
+diff --git a/support/support_socket_so_timestamp_time64.c b/support/support_socket_so_timestamp_time64.c
+new file mode 100644
+index 0000000000..54bf3f4272
+--- /dev/null
++++ b/support/support_socket_so_timestamp_time64.c
+@@ -0,0 +1,48 @@
++/* Return whether socket supports 64-bit timestamps.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <errno.h>
++#include <unistd.h>
++#include <sys/syscall.h>
++#include <sys/socket.h>
++#include <support/support.h>
++#ifdef __linux__
++# include <socket-constants-time64.h>
++#endif
++
++bool
++support_socket_so_timestamp_time64 (int fd)
++{
++#ifdef __linux__
++# if __LINUX_KERNEL_VERSION >= 0x050100 \
++ || __WORDSIZE == 64 \
++ || (defined __SYSCALL_WORDSIZE && __SYSCALL_WORDSIZE == 64)
++ return true;
++# else
++ int level = SOL_SOCKET;
++ int optname = COMPAT_SO_TIMESTAMP_NEW;
++ int optval;
++ socklen_t len = sizeof (optval);
++
++ int r = syscall (__NR_getsockopt, fd, level, optname, &optval, &len);
++ return r != -1;
++# endif
++#else
++ return false;
++#endif
++}
+--
+2.27.0
+
diff --git a/support-Add-support_wait_for_thread_exit.patch b/support-Add-support_wait_for_thread_exit.patch
new file mode 100644
index 0000000..97ca806
--- /dev/null
+++ b/support-Add-support_wait_for_thread_exit.patch
@@ -0,0 +1,124 @@
+From 032d74eaf6179100048a5bf0ce942e97dc8b9a60 Mon Sep 17 00:00:00 2001
+From: Florian Weimer <fweimer@redhat.com>
+Date: Mon, 30 Aug 2021 13:43:56 +0200
+Subject: [PATCH] support: Add support_wait_for_thread_exit
+
+---
+ support/Makefile | 3 +-
+ support/support.h | 4 ++
+ support/support_wait_for_thread_exit.c | 72 ++++++++++++++++++++++++++++++++++
+ 3 files changed, 78 insertions(+), 1 deletion(-)
+ create mode 100644 support/support_wait_for_thread_exit.c
+
+diff --git a/support/Makefile b/support/Makefile
+index 6332e7b..2a07317 100644
+--- a/support/Makefile
++++ b/support/Makefile
+@@ -83,9 +83,10 @@ libsupport-routines = \
+ support_test_compare_blob \
+ support_test_compare_failure \
+ support_test_compare_string \
+- support_write_file_string \
+ support_test_main \
+ support_test_verify_impl \
++ support_wait_for_thread_exit \
++ support_write_file_string \
+ temp_file \
+ timespec \
+ timespec-time64 \
+diff --git a/support/support.h b/support/support.h
+index e6911e1..c219e0d 100644
+--- a/support/support.h
++++ b/support/support.h
+@@ -174,6 +174,10 @@ timer_t support_create_timer (uint64_t sec, long int nsec, bool repeat,
+ /* Disable the timer TIMER. */
+ void support_delete_timer (timer_t timer);
+
++/* Wait until all threads except the current thread have exited (as
++ far as the kernel is concerned). */
++void support_wait_for_thread_exit (void);
++
+ struct support_stack
+ {
+ void *stack;
+diff --git a/support/support_wait_for_thread_exit.c b/support/support_wait_for_thread_exit.c
+new file mode 100644
+index 0000000..658a813
+--- /dev/null
++++ b/support/support_wait_for_thread_exit.c
+@@ -0,0 +1,72 @@
++/* Wait until all threads except the current thread has exited.
++ Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <dirent.h>
++#include <errno.h>
++#include <string.h>
++#include <support/check.h>
++#include <support/support.h>
++#include <unistd.h>
++
++void
++support_wait_for_thread_exit (void)
++{
++#ifdef __linux__
++ DIR *proc_self_task = opendir ("/proc/self/task");
++ TEST_VERIFY_EXIT (proc_self_task != NULL);
++
++ while (true)
++ {
++ errno = 0;
++ struct dirent *e = readdir (proc_self_task);
++ if (e == NULL && errno != 0)
++ FAIL_EXIT1 ("readdir: %m");
++ if (e == NULL)
++ {
++ /* Only the main thread remains. Testing may continue. */
++ closedir (proc_self_task);
++ return;
++ }
++
++ if (strcmp (e->d_name, ".") == 0 || strcmp (e->d_name, "..") == 0)
++ continue;
++
++ int task_tid = atoi (e->d_name);
++ if (task_tid <= 0)
++ FAIL_EXIT1 ("Invalid /proc/self/task entry: %s", e->d_name);
++
++ if (task_tid == gettid ())
++ /* The current thread. Keep scanning for other
++ threads. */
++ continue;
++
++ /* task_tid does not refer to this thread here, i.e., there is
++ another running thread. */
++
++ /* Small timeout to give the thread a chance to exit. */
++ usleep (50 * 1000);
++
++ /* Start scanning the directory from the start. */
++ rewinddir (proc_self_task);
++ }
++#else
++ /* Use a large timeout because we cannot verify that the thread has
++ exited. */
++ usleep (5 * 1000 * 1000);
++#endif
++}
+--
+1.8.3.1
+
diff --git a/support-Also-return-fd-when-it-is-0.patch b/support-Also-return-fd-when-it-is-0.patch
new file mode 100644
index 0000000..150b4c3
--- /dev/null
+++ b/support-Also-return-fd-when-it-is-0.patch
@@ -0,0 +1,45 @@
+From 27b6edbb090f736b101f569620d8ad0e7217ddf8 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Wed, 6 Oct 2021 21:48:35 +0530
+Subject: [PATCH] support: Also return fd when it is 0
+
+The fd validity check in open_dev_null checks if fd > 0, which would
+lead to a leaked fd if it is == 0.
+
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ support/support-open-dev-null-range.c | 14 +++++++-------
+ 1 file changed, 7 insertions(+), 7 deletions(-)
+
+diff --git a/support/support-open-dev-null-range.c b/support/support-open-dev-null-range.c
+index 80d9dba..66a8504 100644
+--- a/support/support-open-dev-null-range.c
++++ b/support/support-open-dev-null-range.c
+@@ -40,16 +40,16 @@ increase_nofile (void)
+ static int
+ open_dev_null (int flags, mode_t mode)
+ {
+- int fd = open64 ("/dev/null", flags, mode);
+- if (fd > 0)
+- return fd;
++ int fd = open64 ("/dev/null", flags, mode);
++ if (fd >= 0)
++ return fd;
+
+- if (fd < 0 && errno != EMFILE)
+- FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode);
++ if (fd < 0 && errno != EMFILE)
++ FAIL_EXIT1 ("open64 (\"/dev/null\", 0x%x, 0%o): %m", flags, mode);
+
+- increase_nofile ();
++ increase_nofile ();
+
+- return xopen ("/dev/null", flags, mode);
++ return xopen ("/dev/null", flags, mode);
+ }
+
+ struct range
+--
+1.8.3.1
+
diff --git a/testsuite_whitelist b/testsuite_whitelist
new file mode 100644
index 0000000..4017bfe
--- /dev/null
+++ b/testsuite_whitelist
@@ -0,0 +1,138 @@
+# USAGE:
+# If it's a generic error:
+# testsuite
+# If the test case fails on part of the architecture:
+# testsuite:arch1,arch2
+
+# These test cases failed due to gcc_secure
+conform/ISO/setjmp.h/conform
+conform/ISO/stdlib.h/conform
+conform/ISO/stdlib.h/linknamespace
+conform/ISO/string.h/conform
+conform/ISO11/setjmp.h/conform
+conform/ISO11/stdio.h/conform
+conform/ISO11/stdlib.h/conform
+conform/ISO11/stdlib.h/linknamespace
+conform/ISO11/string.h/conform
+conform/ISO11/wchar.h/conform
+conform/ISO99/setjmp.h/conform
+conform/ISO99/stdio.h/conform
+conform/ISO99/stdlib.h/conform
+conform/ISO99/stdlib.h/linknamespace
+conform/ISO99/string.h/conform
+conform/ISO99/wchar.h/conform
+conform/POSIX/stdlib.h/conform
+conform/POSIX/stdlib.h/linknamespace
+conform/POSIX/string.h/conform
+conform/POSIX2008/fcntl.h/conform
+conform/POSIX2008/mqueue.h/conform
+conform/POSIX2008/stdio.h/conform
+conform/POSIX2008/stdlib.h/conform
+conform/POSIX2008/stdlib.h/linknamespace
+conform/POSIX2008/wchar.h/conform
+conform/UNIX98/stdlib.h/conform
+conform/UNIX98/string.h/conform
+conform/UNIX98/unistd.h/conform
+conform/UNIX98/unistd.h/linknamespace
+conform/UNIX98/wchar.h/conform
+conform/XOPEN2K/fcntl.h/conform
+conform/XOPEN2K/mqueue.h/conform
+conform/XOPEN2K/stdio.h/conform
+conform/XOPEN2K/stdlib.h/conform
+conform/XOPEN2K/string.h/conform
+conform/XOPEN2K/syslog.h/conform
+conform/XOPEN2K/unistd.h/conform
+conform/XOPEN2K/unistd.h/linknamespace
+conform/XOPEN2K/wchar.h/conform
+conform/XOPEN2K8/fcntl.h/conform
+conform/XOPEN2K8/mqueue.h/conform
+conform/XOPEN2K8/stdio.h/conform
+conform/XOPEN2K8/stdlib.h/conform
+conform/XOPEN2K8/syslog.h/conform
+conform/XOPEN2K8/unistd.h/conform
+conform/XOPEN2K8/unistd.h/linknamespace
+conform/XOPEN2K8/wchar.h/conform
+conform/XPG4/stdlib.h/conform
+conform/XPG4/stdlib.h/linknamespace
+conform/XPG4/string.h/conform
+conform/XPG4/unistd.h/conform
+conform/XPG42/stdlib.h/conform
+conform/XPG42/string.h/conform
+conform/XPG42/unistd.h/conform
+elf/circleload1
+elf/constload1
+elf/dblload
+elf/dblunload
+elf/ifuncmain6pie:x86_64
+elf/lateglobal
+elf/reldep6
+elf/resolvfail
+elf/tst-global1
+elf/tst-tls20
+nptl/tst-execstack
+
+# GCC no longer implements <varargs.h>
+conform/UNIX98/varargs.h/conform
+conform/UNIX98/varargs.h/linknamespace
+conform/XPG4/varargs.h/conform
+conform/XPG4/varargs.h/linknamespace
+conform/XPG42/varargs.h/conform
+conform/XPG42/varargs.h/linknamespace
+
+# These cases depend on gdbm-devel
+conform/UNIX98/ndbm.h/conform
+conform/UNIX98/ndbm.h/linknamespace
+conform/XOPEN2K/ndbm.h/conform
+conform/XOPEN2K/ndbm.h/linknamespace
+conform/XOPEN2K8/ndbm.h/conform
+conform/XOPEN2K8/ndbm.h/linknamespace
+conform/XPG42/ndbm.h/conform
+conform/XPG42/ndbm.h/linknamespace
+
+# Test whether the date/time is correct under different
+# language libraries, use case problems, and see that
+# the compiled language library itself has no errors
+# https://sourceware.org/bugzilla/show_bug.cgi?id=23164
+localedata/tst-langinfo-newlocale-static
+
+# The use case itself passed but because
+# test-xfail-tst-protected1a/test-xfail-tst-protected1b was added
+elf/tst-protected1a
+elf/tst-protected1b
+
+# the test case is due to check whether a macro is defined
+# in the header files. As GLIBC evolves, the position of the
+# macro changes, causing the use case to fail
+posix/annexc
+
+# Check whether sys/mman.h is consistent with linux/mman.h.
+# kernel has a self-developed macro that does not require glibc adaptation
+# https://gitee.com/src-openeuler/kernel/issues/I4BZ9T?from=project-issue
+misc/tst-mman-consts
+
+# It need to build GliBC on a platform that supports CET
+elf/check-cet:x86_64
+
+# Add the tst-nss-files-hosts-long.root/etc/hosts of glibc to
+# the /etc/hosts directory of the system, and then run sucess
+nss/tst-nss-files-hosts-long
+
+# The test case fails due to OBS machine restrictions which can be passed locally.
+elf/tst-debug1:aarch64
+
+# This test case often fails in CI which is the high-pressure environment.
+# No better solution is available. This test case is shielded.
+rt/tst-cpuclock2
+
+# These testcase fails because rseq is disabled by default
+misc/tst-rseq-nptl
+misc/tst-rseq
+
+# These testcase fails as left problems.
+elf/tst-ifunc-fault-bindnow:loongarch64
+elf/tst-ifunc-fault-lazy:loongarch64
+locale/tst-localedef-path-norm:loongarch64
+misc/tst-glibcsyscalls:loongarch64
+# Failed for environment, remove it later.
+resolv/tst-resolv-res_init-multi:loongarch64
+elf/check-localplt
diff --git a/time-Fix-overflow-itimer-tests-on-32-bit-systems.patch b/time-Fix-overflow-itimer-tests-on-32-bit-systems.patch
new file mode 100644
index 0000000..939e816
--- /dev/null
+++ b/time-Fix-overflow-itimer-tests-on-32-bit-systems.patch
@@ -0,0 +1,90 @@
+From 6e8a0aac2f883a23efb1683b120499138f9e6021 Mon Sep 17 00:00:00 2001
+From: Stafford Horne <shorne@gmail.com>
+Date: Mon, 7 Jun 2021 22:10:19 +0900
+Subject: [PATCH] time: Fix overflow itimer tests on 32-bit systems
+
+On the port of OpenRISC I am working on and it appears the rv32 port
+we have sets __TIMESIZE == 64 && __WORDSIZE == 32. This causes the
+size of time_t to be 8 bytes, but the tv_sec in the kernel is still 32-bit
+causing truncation.
+
+The truncations are unavoidable on these systems so skip the
+testing/failures by guarding with __KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64.
+
+Also, futher in the tests and in other parts of code checking for time_t
+overflow does not work on 32-bit systems when time_t is 64-bit. As
+suggested by Adhemerval, update the in_time_t_range function to assume
+32-bits by using int32_t.
+
+This also brings in the header for stdint.h so we can update other
+usages of __int32_t to int32_t as suggested by Adhemerval.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ include/time.h | 10 ++++++----
+ time/tst-itimer.c | 4 ++--
+ 2 files changed, 8 insertions(+), 6 deletions(-)
+
+diff --git a/include/time.h b/include/time.h
+index 22b29ca..127347e 100644
+--- a/include/time.h
++++ b/include/time.h
+@@ -11,6 +11,7 @@
+ # include <sys/time.h>
+ # include <time-clockid.h>
+ # include <sys/time.h>
++# include <stdint.h>
+
+ extern __typeof (strftime_l) __strftime_l;
+ libc_hidden_proto (__strftime_l)
+@@ -342,11 +343,12 @@ libc_hidden_proto (__time64)
+ actual clock ID. */
+ #define CLOCK_IDFIELD_SIZE 3
+
+-/* Check whether T fits in time_t. */
++/* Check whether T fits in int32_t, assume all usages are for
++ sizeof(time_t) == 32. */
+ static inline bool
+ in_time_t_range (__time64_t t)
+ {
+- time_t s = t;
++ int32_t s = t;
+ return s == t;
+ }
+
+@@ -453,8 +455,8 @@ timespec64_to_timeval64 (const struct __timespec64 ts64)
+ and suseconds_t. */
+ struct __timeval32
+ {
+- __int32_t tv_sec; /* Seconds. */
+- __int32_t tv_usec; /* Microseconds. */
++ int32_t tv_sec; /* Seconds. */
++ int32_t tv_usec; /* Microseconds. */
+ };
+
+ /* Conversion functions for converting to/from __timeval32 */
+diff --git a/time/tst-itimer.c b/time/tst-itimer.c
+index 929c2b7..bd7d7af 100644
+--- a/time/tst-itimer.c
++++ b/time/tst-itimer.c
+@@ -100,7 +100,7 @@ do_test (void)
+
+ /* Linux does not provide 64 bit time_t support for getitimer and
+ setitimer on architectures with 32 bit time_t support. */
+- if (sizeof (__time_t) == 8)
++ if (__KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64)
+ {
+ TEST_COMPARE (setitimer (timers[i], &it, NULL), 0);
+ TEST_COMPARE (setitimer (timers[i], &(struct itimerval) { 0 },
+@@ -131,7 +131,7 @@ do_test (void)
+ it.it_interval.tv_usec = 20;
+ it.it_value.tv_sec = 30;
+ it.it_value.tv_usec = 40;
+- if (sizeof (__time_t) == 8)
++ if (__KERNEL_OLD_TIMEVAL_MATCHES_TIMEVAL64)
+ {
+ TEST_COMPARE (setitimer (timers[i], &it, NULL), 0);
+
+--
+1.8.3.1
+
diff --git a/time-Fix-use-after-free-in-getdate.patch b/time-Fix-use-after-free-in-getdate.patch
new file mode 100644
index 0000000..c007d80
--- /dev/null
+++ b/time-Fix-use-after-free-in-getdate.patch
@@ -0,0 +1,48 @@
+From 85e6d8b4175fcb195011a0a1bad37d6f3b2355db Mon Sep 17 00:00:00 2001
+From: Arjun Shankar <arjun@redhat.com>
+Date: Tue, 6 Jun 2023 19:20:31 +0200
+Subject: [PATCH] time: Fix use-after-free in getdate
+
+getdate would free the buffer pointed to by the result of its call to
+strptime, then reference the same buffer later on -- leading to a
+use-after-free. This commit fixes that.
+
+Reported-by: Martin Coufal <mcoufal@redhat.com>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ time/getdate.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+diff --git a/time/getdate.c b/time/getdate.c
+index 1dcbd77188..ca058394a3 100644
+--- a/time/getdate.c
++++ b/time/getdate.c
+@@ -114,6 +114,7 @@ __getdate_r (const char *string, struct tm *tp)
+ struct tm tm;
+ struct __stat64_t64 st;
+ bool mday_ok = false;
++ bool found = false;
+
+ datemsk = getenv ("DATEMSK");
+ if (datemsk == NULL || *datemsk == '\0')
+@@ -181,7 +182,7 @@ __getdate_r (const char *string, struct tm *tp)
+ tp->tm_gmtoff = 0;
+ tp->tm_zone = NULL;
+ result = strptime (string, line, tp);
+- if (result && *result == '\0')
++ if ((found = (result && *result == '\0')))
+ break;
+ }
+ while (!__feof_unlocked (fp));
+@@ -201,7 +202,7 @@ __getdate_r (const char *string, struct tm *tp)
+ /* Close template file. */
+ fclose (fp);
+
+- if (result == NULL || *result != '\0')
++ if (!found)
+ return 7;
+
+ /* Get current time. */
+--
+2.33.0
+
diff --git a/time-strftime_l-Avoid-an-unbounded-alloca.patch b/time-strftime_l-Avoid-an-unbounded-alloca.patch
new file mode 100644
index 0000000..b88f026
--- /dev/null
+++ b/time-strftime_l-Avoid-an-unbounded-alloca.patch
@@ -0,0 +1,75 @@
+From 79b2667d1eb06c6503c22f2f323c1c574ac5917b Mon Sep 17 00:00:00 2001
+From: Joe Simmons-Talbott <josimmon@redhat.com>
+Date: Tue, 23 May 2023 15:41:29 -0400
+Subject: [PATCH] time: strftime_l: Avoid an unbounded alloca.
+
+Avoid possible stack overflow by removing alloca() and converting to
+wide characters within the buffer.
+
+Conflict: NA
+Reference: https://sourceware.org/git/?p=glibc.git;a=commit;h=79b2667d1eb06c6503c22f2f323c1c574ac5917b
+
+Suggested-by: Paul Eggert <eggert@cs.ucla.edu>
+---
+ time/strftime_l.c | 39 +++++++++++++++++++++++++--------------
+ 1 file changed, 25 insertions(+), 14 deletions(-)
+
+diff --git a/time/strftime_l.c b/time/strftime_l.c
+index 402c6c4111..3901bd79da 100644
+--- a/time/strftime_l.c
++++ b/time/strftime_l.c
+@@ -267,15 +267,6 @@ static const CHAR_T zeroes[16] = /* "0000000000000000" */
+ # undef __mbsrtowcs_l
+ # define __mbsrtowcs_l(d, s, l, st, loc) __mbsrtowcs (d, s, l, st)
+ # endif
+-# define widen(os, ws, l) \
+- { \
+- mbstate_t __st; \
+- const char *__s = os; \
+- memset (&__st, '\0', sizeof (__st)); \
+- l = __mbsrtowcs_l (NULL, &__s, 0, &__st, loc); \
+- ws = alloca ((l + 1) * sizeof (wchar_t)); \
+- (void) __mbsrtowcs_l (ws, &__s, l, &__st, loc); \
+- }
+ #endif
+
+
+@@ -1342,11 +1333,31 @@ __strftime_internal (CHAR_T *s, size_t maxsize, const CHAR_T *format,
+ #ifdef COMPILE_WIDE
+ {
+ /* The zone string is always given in multibyte form. We have
+- to transform it first. */
+- wchar_t *wczone;
+- size_t len;
+- widen (zone, wczone, len);
+- cpy (len, wczone);
++ to convert it to wide character. */
++ size_t w = pad == L_('-') || width < 0 ? 0 : width;
++ char const *z = zone;
++ mbstate_t st = {0};
++ size_t len = __mbsrtowcs_l (p, &z, maxsize - i, &st, loc);
++ if (len == (size_t) -1)
++ return 0;
++ size_t incr = len < w ? w : len;
++ if (incr >= maxsize - i)
++ {
++ errno = ERANGE;
++ return 0;
++ }
++ if (p)
++ {
++ if (len < w)
++ {
++ size_t delta = w - len;
++ __wmemmove (p + delta, p, len);
++ wchar_t wc = pad == L_('0') || pad == L_('+') ? L'0' : L' ';
++ wmemset (p, wc, delta);
++ }
++ p += incr;
++ }
++ i += incr;
+ }
+ #else
+ cpy (strlen (zone), zone);
+--
+2.23.0
diff --git a/timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch b/timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch
new file mode 100644
index 0000000..3c6d72b
--- /dev/null
+++ b/timex-Use-64-bit-fields-on-32-bit-TIMESIZE-64-system.patch
@@ -0,0 +1,45 @@
+From 1d550265a75b412cea4889a50b101395f6a8e025 Mon Sep 17 00:00:00 2001
+From: Stafford Horne <shorne@gmail.com>
+Date: Fri, 15 Oct 2021 06:17:41 +0900
+Subject: [PATCH] timex: Use 64-bit fields on 32-bit TIMESIZE=64 systems (BZ
+ #28469)
+
+This was found when testing the OpenRISC port I am working on. These
+two tests fail with SIGSEGV:
+
+ FAIL: misc/tst-ntp_gettime
+ FAIL: misc/tst-ntp_gettimex
+
+This was found to be due to the kernel overwriting the stack space
+allocated by the timex structure. The reason for the overwrite being
+that the kernel timex has 64-bit fields and user space code only
+allocates enough stack space for timex with 32-bit fields.
+
+On 32-bit systems with TIMESIZE=64 __USE_TIME_BITS64 is not defined.
+This causes the timex structure to use 32-bit fields with type
+__syscall_slong_t.
+
+This patch adjusts the ifdef condition to allow 32-bit systems with
+TIMESIZE=64 to use the 64-bit long long timex definition.
+
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ sysdeps/unix/sysv/linux/bits/timex.h | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/bits/timex.h b/sysdeps/unix/sysv/linux/bits/timex.h
+index ee37694..4a5db6d 100644
+--- a/sysdeps/unix/sysv/linux/bits/timex.h
++++ b/sysdeps/unix/sysv/linux/bits/timex.h
+@@ -25,7 +25,7 @@
+
+ struct timex
+ {
+-# ifdef __USE_TIME_BITS64
++# if defined __USE_TIME_BITS64 || (__TIMESIZE == 64 && __WORDSIZE == 32)
+ unsigned int modes; /* mode selector */
+ int :32; /* pad */
+ long long offset; /* time offset (usec) */
+--
+1.8.3.1
+
diff --git a/timezone-handle-truncated-timezones-from-tzcode-2021.patch b/timezone-handle-truncated-timezones-from-tzcode-2021.patch
new file mode 100644
index 0000000..10ef9e8
--- /dev/null
+++ b/timezone-handle-truncated-timezones-from-tzcode-2021.patch
@@ -0,0 +1,57 @@
+From c36f64aa6dff13b12a1e03a185e75a50fa9f6a4c Mon Sep 17 00:00:00 2001
+From: Hans-Peter Nilsson <hp@axis.com>
+Date: Fri, 17 Dec 2021 21:38:00 +0100
+Subject: [PATCH] timezone: handle truncated timezones from tzcode-2021d and
+ later (BZ #28707)
+
+When using a timezone file with a truncated starting time,
+generated by the zic in IANA tzcode-2021d a.k.a. tzlib-2021d
+(also in tzlib-2021e; current as of this writing), glibc
+asserts in __tzfile_read (on e.g. tzset() for this file) and
+you may find lines matching "tzfile.c:435: __tzfile_read:
+Assertion `num_types == 1' failed" in your syslog.
+
+One example of such a file is the tzfile for Asuncion
+generated by tzlib-2021e as follows, using the tzlib-2021e zic:
+"zic -d DEST -r @1546300800 -L /dev/null -b slim
+SOURCE/southamerica". Note that in its type 2 header, it has
+two entries in its "time-types" array (types), but only one
+entry in its "transition types" array (type_idxs).
+
+This is valid and expected already in the published RFC8536, and
+not even frowned upon: "Local time for timestamps before the
+first transition is specified by the first time type (time type
+0)" ... "every nonzero local time type index SHOULD appear at
+least once in the transition type array". Note the "nonzero ...
+index". Until the 2021d zic, index 0 has been shared by the
+first valid transition but with 2021d it's separate, set apart
+as a placeholder and only "implicitly" indexed. (A draft update
+of the RFC mandates that the entry at index 0 is a placeholder
+in this case, hence can no longer be shared.)
+
+ * time/tzfile.c (__tzfile_read): Don't assert when no transitions
+ are found.
+
+Co-authored-by: Christopher Wong <Christopher.Wong@axis.com>
+---
+ time/tzfile.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/time/tzfile.c b/time/tzfile.c
+index 190a777..8668392 100644
+--- a/time/tzfile.c
++++ b/time/tzfile.c
+@@ -431,8 +431,8 @@ __tzfile_read (const char *file, size_t extra, char **extrap)
+ if (__tzname[0] == NULL)
+ {
+ /* This should only happen if there are no transition rules.
+- In this case there should be only one single type. */
+- assert (num_types == 1);
++ In this case there's usually only one single type, unless
++ e.g. the data file has a truncated time-range. */
+ __tzname[0] = __tzstring (zone_names);
+ }
+ if (__tzname[1] == NULL)
+--
+1.8.3.1
+
diff --git a/timezone-test-case-for-BZ-28707.patch b/timezone-test-case-for-BZ-28707.patch
new file mode 100644
index 0000000..2b0b3fe
--- /dev/null
+++ b/timezone-test-case-for-BZ-28707.patch
@@ -0,0 +1,138 @@
+From ebe899af0dc3215159a9c896ac6f35b72a18cb6e Mon Sep 17 00:00:00 2001
+From: Hans-Peter Nilsson <hp@axis.com>
+Date: Fri, 17 Dec 2021 21:45:54 +0100
+Subject: [PATCH] timezone: test-case for BZ #28707
+
+This test-case is the tzfile for Asuncion generated by
+tzlib-2021e as follows, using the tzlib-2021e zic: "zic -d
+DEST -r @1546300800 -L /dev/null -b slim
+SOURCE/southamerica". Note that in its type 2 header, it
+has two entries in its "time-types" array (types), but only
+one entry in its "transition types" array (type_idxs).
+
+ * timezone/Makefile, timezone/tst-pr28707.c,
+ timezone/testdata/gen-XT5.sh: New test.
+
+Co-authored-by: Christopher Wong <Christopher.Wong@axis.com>
+---
+ timezone/Makefile | 8 +++++++-
+ timezone/testdata/gen-XT5.sh | 16 +++++++++++++++
+ timezone/tst-bz28707.c | 46 ++++++++++++++++++++++++++++++++++++++++++++
+ 3 files changed, 69 insertions(+), 1 deletion(-)
+ create mode 100755 timezone/testdata/gen-XT5.sh
+ create mode 100644 timezone/tst-bz28707.c
+
+diff --git a/timezone/Makefile b/timezone/Makefile
+index c624a18..f091663 100644
+--- a/timezone/Makefile
++++ b/timezone/Makefile
+@@ -23,7 +23,7 @@ subdir := timezone
+ include ../Makeconfig
+
+ others := zdump zic
+-tests := test-tz tst-timezone tst-tzset
++tests := test-tz tst-timezone tst-tzset tst-bz28707
+
+ generated-dirs += testdata
+
+@@ -85,10 +85,12 @@ $(objpfx)tst-timezone.out: $(addprefix $(testdata)/, \
+ America/Sao_Paulo Asia/Tokyo \
+ Europe/London)
+ $(objpfx)tst-tzset.out: $(addprefix $(testdata)/XT, 1 2 3 4)
++$(objpfx)tst-bz28707.out: $(testdata)/XT5
+
+ test-tz-ENV = TZDIR=$(testdata)
+ tst-timezone-ENV = TZDIR=$(testdata)
+ tst-tzset-ENV = TZDIR=$(testdata)
++tst-bz28707-ENV = TZDIR=$(testdata)
+
+ # Note this must come second in the deps list for $(built-program-cmd) to work.
+ zic-deps = $(objpfx)zic $(leapseconds) yearistype
+@@ -122,6 +124,10 @@ $(testdata)/XT%: testdata/XT%
+ $(make-target-directory)
+ cp $< $@
+
++$(testdata)/XT%: testdata/gen-XT%.sh
++ $(SHELL) $< > $@.tmp
++ mv $@.tmp $@
++
+ $(objpfx)tzselect: tzselect.ksh $(common-objpfx)config.make
+ sed -e 's|TZDIR=[^}]*|TZDIR=$(zonedir)|' \
+ -e '/TZVERSION=/s|see_Makefile|"$(version)"|' \
+diff --git a/timezone/testdata/gen-XT5.sh b/timezone/testdata/gen-XT5.sh
+new file mode 100755
+index 0000000..3cea056
+--- /dev/null
++++ b/timezone/testdata/gen-XT5.sh
+@@ -0,0 +1,16 @@
++#! /bin/sh
++
++# This test-case is the tzfile for America/Asuncion
++# generated by tzlib-2021e as follows, using the tzlib-2021e
++# zic: "zic -d DEST -r @1546300800 -L /dev/null -b slim
++# SOURCE/southamerica". Note that in its type 2 header, it
++# has two entries in its "time-types" array (types), but
++# only one entry in its "transition types" array
++# (type_idxs).
++
++printf \
++'TZif2\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0'\
++'\0\0\0\0\0\0\0\1\0\0\0\1\0\0\0\0\0\0\0TZif2\0\0\0\0\0\0\0\0'\
++'\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\1\0\0\0\2\0\0\0\b\0'\
++'\0\0\0\*\255\200\1\0\0\0\0\0\0\377\377\325\320\1\4-00\0-03\0\n'\
++'<-04>4<-03>,M10.1.0/0,M3.4.0/0\n'
+diff --git a/timezone/tst-bz28707.c b/timezone/tst-bz28707.c
+new file mode 100644
+index 0000000..0a9df1e
+--- /dev/null
++++ b/timezone/tst-bz28707.c
+@@ -0,0 +1,46 @@
++/* Copyright (C) 2021 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#include <time.h>
++#include <stdio.h>
++#include <stdlib.h>
++#include <string.h>
++
++/* Test that we can use a truncated timezone-file, where the time-type
++ at index 0 is not indexed by the transition-types array (and the
++ transition-types array does not contain at least both one DST and one
++ normal time members). */
++
++static int
++do_test (void)
++{
++ if (setenv ("TZ", "XT5", 1))
++ {
++ puts ("setenv failed.");
++ return 1;
++ }
++
++ tzset ();
++
++ return
++ /* Sanity-check that we got the right timezone-name for DST. For
++ normal time, we're likely to get "-00" (the "unspecified" marker),
++ even though the POSIX timezone string says "-04". Let's not test
++ that. */
++ !(strcmp (tzname[1], "-03") == 0);
++}
++#include <support/test-driver.c>
+--
+1.8.3.1
+
diff --git a/tst-realpath-toolong-Fix-hurd-build.patch b/tst-realpath-toolong-Fix-hurd-build.patch
new file mode 100644
index 0000000..6445782
--- /dev/null
+++ b/tst-realpath-toolong-Fix-hurd-build.patch
@@ -0,0 +1,31 @@
+From 8c8a71c85f2ed5cc90d08d82ce645513fc907cb6 Mon Sep 17 00:00:00 2001
+From: Siddhesh Poyarekar <siddhesh@sourceware.org>
+Date: Mon, 24 Jan 2022 10:57:09 +0530
+Subject: [PATCH] tst-realpath-toolong: Fix hurd build
+
+Define PATH_MAX to a constant if it isn't already defined, like in hurd.
+
+Signed-off-by: Siddhesh Poyarekar <siddhesh@sourceware.org>
+(cherry picked from commit 976db046bc3a3738f69255ae00b0a09b8e77fd9c)
+---
+ stdlib/tst-realpath-toolong.c | 4 ++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/stdlib/tst-realpath-toolong.c b/stdlib/tst-realpath-toolong.c
+index 8bed772..4388890 100644
+--- a/stdlib/tst-realpath-toolong.c
++++ b/stdlib/tst-realpath-toolong.c
+@@ -29,6 +29,10 @@
+
+ #define BASENAME "tst-realpath-toolong."
+
++#ifndef PATH_MAX
++# define PATH_MAX 1024
++#endif
++
+ int
+ do_test (void)
+ {
+--
+1.8.3.1
+
diff --git a/tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch b/tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch
new file mode 100644
index 0000000..eeab0ad
--- /dev/null
+++ b/tst-socket-timestamp-compat.c-Check-__TIMESIZE-BZ-28.patch
@@ -0,0 +1,29 @@
+From 008003dc6e83439c5e04a744b7fd8197df19096e Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sat, 29 Jan 2022 05:22:31 -0800
+Subject: [PATCH] tst-socket-timestamp-compat.c: Check __TIMESIZE [BZ #28837]
+
+time_t size is defined by __TIMESIZE, not __WORDSIZE. Check __TIMESIZE,
+instead of __WORDSIZE, for time_t size. This fixes BZ #28837.
+
+(cherry pick from commit 77a602ebb0769e7ccc5f9f8e06f7fffe66f69dfc)
+---
+ sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
+index de261dae5a..0ff1a214e6 100644
+--- a/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
++++ b/sysdeps/unix/sysv/linux/tst-socket-timestamp-compat.c
+@@ -237,7 +237,7 @@ do_test (void)
+ {
+ /* This test only make sense for ABIs that support 32 bit time_t socket
+ timestampss. */
+- if (sizeof (time_t) > 4 && __WORDSIZE == 64)
++ if (sizeof (time_t) > 4 && __TIMESIZE == 64)
+ return 0;
+
+ srv = xsocket (AF_INET, SOCK_DGRAM, 0);
+--
+2.27.0
+
diff --git a/turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch b/turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
new file mode 100644
index 0000000..e9e053d
--- /dev/null
+++ b/turn-default-value-of-x86_rep_stosb_threshold_form_2K_to_1M.patch
@@ -0,0 +1,29 @@
+From 4dee2794b8c78ccd540e3f72bc07585828e0143b Mon Sep 17 00:00:00 2001
+From: Yang Yanchao <yangyanchao6@huawei.com>
+Date: Thu, 2 Dec 2021 19:56:20 +0800
+Subject: [PATCH] turn the default value of x86_rep_stosb_threshold from 2k to 1M
+
+x86_rep_stosb_threshold is designed to choose vec mov or stosb.
+For the libMicro, after set this x86_rep_stosb_threshold to 1 MB.
+The performance of memset_256_u, memset_4k_uc, and memset_1m is improved.
+The performance deteriorates in the memset_4k and memset_10k scenarios.
+---
+ sysdeps/x86/dl-tunables.list | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/x86/dl-tunables.list b/sysdeps/x86/dl-tunables.list
+index dd6e1d65..a4c3af69 100644
+--- a/sysdeps/x86/dl-tunables.list
++++ b/sysdeps/x86/dl-tunables.list
+@@ -54,7 +54,7 @@ glibc {
+ # stored value is fixed, larger register size has minimal impact
+ # on threshold.
+ minval: 1
+- default: 2048
++ default: 1048576
+ }
+ x86_data_cache_size {
+ type: SIZE_T
+--
+2.30.0
+
diff --git a/use-region-to-instead-of-country-for-extract-timezon.patch b/use-region-to-instead-of-country-for-extract-timezon.patch
new file mode 100644
index 0000000..7e8eb07
--- /dev/null
+++ b/use-region-to-instead-of-country-for-extract-timezon.patch
@@ -0,0 +1,152 @@
+From 1c20cf491471a4a70f103a9d052fcca993eaa341 Mon Sep 17 00:00:00 2001
+From: Qingqing Li <liqingqing3@huawei.com>
+Date: Tue, 22 Feb 2022 15:00:55 +0800
+Subject: [PATCH] use region to instead of country for extract timezone
+ selection.
+Co-authored-by: liusirui <liusirui@huawei.com>
+---
+ timezone/tzselect.ksh | 97 +++++++++----------------------------------
+ 1 file changed, 20 insertions(+), 77 deletions(-)
+
+diff --git a/timezone/tzselect.ksh b/timezone/tzselect.ksh
+index 18fce27e..414bfa2a 100755
+--- a/timezone/tzselect.ksh
++++ b/timezone/tzselect.ksh
+@@ -51,7 +51,7 @@ say() {
+
+ coord=
+ location_limit=10
+-zonetabtype=zone1970
++zonetabtype=zone
+
+ usage="Usage: tzselect [--version] [--help] [-c COORD] [-n LIMIT]
+ Select a timezone interactively.
+@@ -398,94 +398,38 @@ while
+ '`
+ ;;
+ *)
+- # Get list of names of countries in the continent or ocean.
+- countries=`$AWK \
++ # Get list of regions in the continent or ocean.
++ timezones=`$AWK \
+ -v continent="$continent" \
+ -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
+ '
+ BEGIN { FS = "\t" }
+ /^#/ { next }
+ $3 ~ ("^" continent "/") {
+- ncc = split($1, cc, /,/)
++ ncc = split($3, cc, /,/)
+ for (i = 1; i <= ncc; i++)
+ if (!cc_seen[cc[i]]++) cc_list[++ccs] = cc[i]
+ }
+ END {
+- while (getline <TZ_COUNTRY_TABLE) {
+- if ($0 !~ /^#/) cc_name[$1] = $2
+- }
+ for (i = 1; i <= ccs; i++) {
+- country = cc_list[i]
+- if (cc_name[country]) {
+- country = cc_name[country]
+- }
+- print country
++ print cc_list[i]
+ }
+ }
+ ' <"$TZ_ZONE_TABLE" | sort -f`
+
+-
+- # If there's more than one country, ask the user which one.
+- case $countries in
+- *"$newline"*)
+- echo >&2 'Please select a country' \
+- 'whose clocks agree with yours.'
+- doselect $countries
+- country=$select_result;;
+- *)
+- country=$countries
+- esac
+-
+-
+- # Get list of timezones in the country.
+- regions=`$AWK \
+- -v country="$country" \
+- -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
+- '
+- BEGIN {
+- FS = "\t"
+- cc = country
+- while (getline <TZ_COUNTRY_TABLE) {
+- if ($0 !~ /^#/ && country == $2) {
+- cc = $1
+- break
+- }
+- }
+- }
+- /^#/ { next }
+- $1 ~ cc { print $4 }
+- ' <"$TZ_ZONE_TABLE"`
+-
+-
+- # If there's more than one region, ask the user which one.
+- case $regions in
+- *"$newline"*)
+- echo >&2 'Please select one of the following timezones.'
+- doselect $regions
+- region=$select_result;;
+- *)
+- region=$regions
+- esac
++ regions=[]
++ index=0
++ for item in $timezones; do
++ regions[$index]=`echo $item | awk -F '/' '{print $2}'`
++ index=$(($index+1))
++ done
++ echo >&2 'Please select a timezone' \
++ 'whose clocks agree with yours.'
++ doselect ${regions[@]}
++ region=$select_result
+
+ # Determine TZ from country and region.
+- TZ=`$AWK \
+- -v country="$country" \
+- -v region="$region" \
+- -v TZ_COUNTRY_TABLE="$TZ_COUNTRY_TABLE" \
+- '
+- BEGIN {
+- FS = "\t"
+- cc = country
+- while (getline <TZ_COUNTRY_TABLE) {
+- if ($0 !~ /^#/ && country == $2) {
+- cc = $1
+- break
+- }
+- }
+- }
+- /^#/ { next }
+- $1 ~ cc && $4 == region { print $3 }
+- ' <"$TZ_ZONE_TABLE"`
++ TZ=$continent/$region
+ esac
+
+ # Make sure the corresponding zoneinfo file exists.
+@@ -523,11 +467,10 @@ Universal Time is now: $UTdate."
+ echo >&2 ""
+ echo >&2 "The following information has been given:"
+ echo >&2 ""
+- case $country%$region%$coord in
+- ?*%?*%) say >&2 " $country$newline $region";;
+- ?*%%) say >&2 " $country";;
+- %?*%?*) say >&2 " coord $coord$newline $region";;
+- %%?*) say >&2 " coord $coord";;
++ case $region%$coord in
++ ?*%) say >&2 " $region";;
++ ?*%?*) say >&2 " coord $coord$newline $region";;
++ %?*) say >&2 " coord $coord";;
+ *) say >&2 " TZ='$TZ'"
+ esac
+ say >&2 ""
+--
+2.27.0
+
diff --git a/x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch b/x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch
new file mode 100644
index 0000000..924e63c
--- /dev/null
+++ b/x86-64-Optimize-load-of-all-bits-set-into-ZMM-regist.patch
@@ -0,0 +1,267 @@
+From 78c9ec9000f873abe7a15a91b87080a2e4308260 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Fri, 20 Aug 2021 06:42:24 -0700
+Subject: [PATCH] x86-64: Optimize load of all bits set into ZMM register [BZ
+ #28252]
+
+Optimize loads of all bits set into ZMM register in AVX512 SVML codes
+by replacing
+
+ vpbroadcastq .L_2il0floatpacket.16(%rip), %zmmX
+
+and
+
+ vmovups .L_2il0floatpacket.13(%rip), %zmmX
+
+with
+ vpternlogd $0xff, %zmmX, %zmmX, %zmmX
+
+This fixes BZ #28252.
+---
+ sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S | 12 ++----------
+ sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S | 7 +------
+ sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S | 7 +------
+ 10 files changed, 11 insertions(+), 64 deletions(-)
+
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S
+index e68fcdb..58e588a 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_cos8_core_avx512.S
+@@ -265,7 +265,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_cos
+ vmovaps %zmm0, %zmm8
+
+ /* Check for large arguments path */
+- vpbroadcastq .L_2il0floatpacket.16(%rip), %zmm2
++ vpternlogd $0xff, %zmm2, %zmm2, %zmm2
+
+ /*
+ ARGUMENT RANGE REDUCTION:
+@@ -456,8 +456,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_cos
+ jmp .LBL_2_7
+ #endif
+ END (_ZGVeN8v_cos_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.16:
+- .long 0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.16,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S
+index dfa2aca..f5f117d 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_log8_core_avx512.S
+@@ -274,7 +274,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_log
+
+ /* preserve mantissa, set input exponent to 2^(-10) */
+ vpternlogq $248, _ExpMask(%rax), %zmm3, %zmm2
+- vpbroadcastq .L_2il0floatpacket.12(%rip), %zmm1
++ vpternlogd $0xff, %zmm1, %zmm1, %zmm1
+ vpsrlq $32, %zmm4, %zmm6
+
+ /* reciprocal approximation good to at least 11 bits */
+@@ -461,8 +461,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_log
+ jmp .LBL_2_7
+ #endif
+ END (_ZGVeN8v_log_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.12:
+- .long 0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.12,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S
+index be8ab7c..48d251d 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sin8_core_avx512.S
+@@ -261,7 +261,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_sin
+ andq $-64, %rsp
+ subq $1280, %rsp
+ movq __svml_d_trig_data@GOTPCREL(%rip), %rax
+- vpbroadcastq .L_2il0floatpacket.14(%rip), %zmm14
++ vpternlogd $0xff, %zmm1, %zmm1, %zmm14
+ vmovups __dAbsMask(%rax), %zmm7
+ vmovups __dInvPI(%rax), %zmm2
+ vmovups __dRShifter(%rax), %zmm1
+@@ -458,8 +458,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN4v_sin
+ jmp .LBL_2_7
+ #endif
+ END (_ZGVeN8v_sin_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.14:
+- .long 0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.14,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S
+index 6118870..a4944a4 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_d_sincos8_core_avx512.S
+@@ -430,7 +430,7 @@ WRAPPER_IMPL_AVX512_fFF _ZGVdN4vl8l8_sincos
+
+ /* SinPoly = SinR*SinPoly */
+ vfmadd213pd %zmm5, %zmm5, %zmm4
+- vpbroadcastq .L_2il0floatpacket.15(%rip), %zmm3
++ vpternlogd $0xff, %zmm3, %zmm3, %zmm3
+
+ /* Update Cos result's sign */
+ vxorpd %zmm2, %zmm1, %zmm1
+@@ -741,8 +741,3 @@ END (_ZGVeN8vvv_sincos_knl)
+ ENTRY (_ZGVeN8vvv_sincos_skx)
+ WRAPPER_AVX512_vvv_vl8l8 _ZGVeN8vl8l8_sincos_skx
+ END (_ZGVeN8vvv_sincos_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.15:
+- .long 0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.15,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S
+index f671d60..fe8474f 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_cosf16_core_avx512.S
+@@ -278,7 +278,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_cosf
+ X = X - Y*PI1 - Y*PI2 - Y*PI3
+ */
+ vmovaps %zmm0, %zmm6
+- vmovups .L_2il0floatpacket.13(%rip), %zmm12
++ vpternlogd $0xff, %zmm12, %zmm12, %zmm12
+ vmovups __sRShifter(%rax), %zmm3
+ vmovups __sPI1_FMA(%rax), %zmm5
+ vmovups __sA9_FMA(%rax), %zmm9
+@@ -453,8 +453,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_cosf
+ jmp .LBL_2_7
+ #endif
+ END (_ZGVeN16v_cosf_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.13:
+- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.13,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S
+index 637bfe3..229b782 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_expf16_core_avx512.S
+@@ -264,7 +264,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_expf
+ vmovaps %zmm0, %zmm7
+
+ /* compare against threshold */
+- vmovups .L_2il0floatpacket.13(%rip), %zmm3
++ vpternlogd $0xff, %zmm3, %zmm3, %zmm3
+ vmovups __sInvLn2(%rax), %zmm4
+ vmovups __sShifter(%rax), %zmm1
+ vmovups __sLn2hi(%rax), %zmm6
+@@ -440,8 +440,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_expf
+
+ #endif
+ END (_ZGVeN16v_expf_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.13:
+- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.13,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S
+index 9d790fb..fa2aae9 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_logf16_core_avx512.S
+@@ -235,7 +235,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_logf
+ andq $-64, %rsp
+ subq $1280, %rsp
+ movq __svml_slog_data@GOTPCREL(%rip), %rax
+- vmovups .L_2il0floatpacket.7(%rip), %zmm6
++ vpternlogd $0xff, %zmm6, %zmm6, %zmm6
+ vmovups _iBrkValue(%rax), %zmm4
+ vmovups _sPoly_7(%rax), %zmm8
+
+@@ -409,8 +409,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_logf
+
+ #endif
+ END (_ZGVeN16v_logf_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.7:
+- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.7,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S
+index c5c43c4..6aea2a4 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_powf16_core_avx512.S
+@@ -385,7 +385,7 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf
+ vpsrlq $32, %zmm3, %zmm2
+ vpmovqd %zmm2, %ymm11
+ vcvtps2pd %ymm14, %zmm13
+- vmovups .L_2il0floatpacket.23(%rip), %zmm14
++ vpternlogd $0xff, %zmm14, %zmm14, %zmm14
+ vmovaps %zmm14, %zmm26
+ vpandd _ABSMASK(%rax), %zmm1, %zmm8
+ vpcmpd $1, _INF(%rax), %zmm8, %k2
+@@ -427,7 +427,7 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf
+ vpmovqd %zmm11, %ymm5
+ vpxord %zmm10, %zmm10, %zmm10
+ vgatherdpd _Log2Rcp_lookup(%rax,%ymm4), %zmm10{%k3}
+- vpbroadcastq .L_2il0floatpacket.24(%rip), %zmm4
++ vpternlogd $0xff, %zmm4, %zmm4, %zmm4
+ vpxord %zmm11, %zmm11, %zmm11
+ vcvtdq2pd %ymm7, %zmm7
+ vgatherdpd _Log2Rcp_lookup(%rax,%ymm5), %zmm11{%k1}
+@@ -643,11 +643,3 @@ WRAPPER_IMPL_AVX512_ff _ZGVdN8vv_powf
+ jmp .LBL_2_7
+ #endif
+ END (_ZGVeN16vv_powf_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.23:
+- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.23,@object
+-.L_2il0floatpacket.24:
+- .long 0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.24,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S
+index 9cf359c..a446c50 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_sincosf16_core_avx512.S
+@@ -317,7 +317,7 @@ WRAPPER_IMPL_AVX512_fFF _ZGVdN8vvv_sincosf
+
+ /* Result sign calculations */
+ vpternlogd $150, %zmm0, %zmm14, %zmm1
+- vmovups .L_2il0floatpacket.13(%rip), %zmm14
++ vpternlogd $0xff, %zmm14, %zmm14, %zmm14
+
+ /* Add correction term 0.5 for cos() part */
+ vaddps %zmm8, %zmm5, %zmm15
+@@ -748,8 +748,3 @@ END (_ZGVeN16vvv_sincosf_knl)
+ ENTRY (_ZGVeN16vvv_sincosf_skx)
+ WRAPPER_AVX512_vvv_vl4l4 _ZGVeN16vl4l4_sincosf_skx
+ END (_ZGVeN16vvv_sincosf_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.13:
+- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.13,@object
+diff --git a/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S b/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S
+index bd05109..c1b352d 100644
+--- a/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S
++++ b/sysdeps/x86_64/fpu/multiarch/svml_s_sinf16_core_avx512.S
+@@ -280,7 +280,7 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_sinf
+ movq __svml_s_trig_data@GOTPCREL(%rip), %rax
+
+ /* Check for large and special values */
+- vmovups .L_2il0floatpacket.11(%rip), %zmm14
++ vpternlogd $0xff, %zmm14, %zmm14, %zmm14
+ vmovups __sAbsMask(%rax), %zmm5
+ vmovups __sInvPI(%rax), %zmm1
+ vmovups __sRShifter(%rax), %zmm2
+@@ -472,8 +472,3 @@ WRAPPER_IMPL_AVX512 _ZGVdN8v_sinf
+ jmp .LBL_2_7
+ #endif
+ END (_ZGVeN16v_sinf_skx)
+-
+- .section .rodata, "a"
+-.L_2il0floatpacket.11:
+- .long 0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff,0xffffffff
+- .type .L_2il0floatpacket.11,@object
+--
+1.8.3.1
+
diff --git a/x86-64-Use-testl-to-check-__x86_string_control.patch b/x86-64-Use-testl-to-check-__x86_string_control.patch
new file mode 100644
index 0000000..363930e
--- /dev/null
+++ b/x86-64-Use-testl-to-check-__x86_string_control.patch
@@ -0,0 +1,38 @@
+From 3c8b9879cab6d41787bc5b14c1748f62fd6d0e5f Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Sat, 28 Aug 2021 06:10:38 -0700
+Subject: [PATCH] x86-64: Use testl to check __x86_string_control
+
+Use testl, instead of andl, to check __x86_string_control to avoid
+updating __x86_string_control.
+
+Reviewed-by: Carlos O'Donell <carlos@redhat.com>
+---
+ sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
+index 9f02624..abde843 100644
+--- a/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
++++ b/sysdeps/x86_64/multiarch/memmove-vec-unaligned-erms.S
+@@ -325,7 +325,7 @@ L(movsb):
+ /* Avoid slow backward REP MOVSB. */
+ jb L(more_8x_vec_backward)
+ # if AVOID_SHORT_DISTANCE_REP_MOVSB
+- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
++ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
+ jz 3f
+ movq %rdi, %rcx
+ subq %rsi, %rcx
+@@ -333,7 +333,7 @@ L(movsb):
+ # endif
+ 1:
+ # if AVOID_SHORT_DISTANCE_REP_MOVSB
+- andl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
++ testl $X86_STRING_CONTROL_AVOID_SHORT_DISTANCE_REP_MOVSB, __x86_string_control(%rip)
+ jz 3f
+ movq %rsi, %rcx
+ subq %rdi, %rcx
+--
+1.8.3.1
+
diff --git a/x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch b/x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch
new file mode 100644
index 0000000..67704e0
--- /dev/null
+++ b/x86-Black-list-more-Intel-CPUs-for-TSX-BZ-27398.patch
@@ -0,0 +1,67 @@
+From b952c25dc7adf0684c53ad72d1d667da0348c929 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Fri, 14 Jan 2022 14:48:01 -0800
+Subject: [PATCH] x86: Black list more Intel CPUs for TSX [BZ #27398]
+
+Disable TSX and enable RTM_ALWAYS_ABORT for Intel CPUs listed in:
+
+https://www.intel.com/content/www/us/en/support/articles/000059422/processors.html
+
+This fixes BZ #27398.
+
+Reviewed-by: Noah Goldstein <goldstein.w.n@gmail.com>
+(cherry picked from commit 1e000d3d33211d5a954300e2a69b90f93f18a1a1)
+---
+ sysdeps/x86/cpu-features.c | 34 +++++++++++++++++++++++++++++++---
+ 1 file changed, 31 insertions(+), 3 deletions(-)
+
+diff --git a/sysdeps/x86/cpu-features.c b/sysdeps/x86/cpu-features.c
+index 645bba6314..de4e3c3b72 100644
+--- a/sysdeps/x86/cpu-features.c
++++ b/sysdeps/x86/cpu-features.c
+@@ -507,11 +507,39 @@ init_cpu_features (struct cpu_features *cpu_features)
+ break;
+ }
+
+- /* Disable TSX on some Haswell processors to avoid TSX on kernels that
+- weren't updated with the latest microcode package (which disables
+- broken feature by default). */
++ /* Disable TSX on some processors to avoid TSX on kernels that
++ weren't updated with the latest microcode package (which
++ disables broken feature by default). */
+ switch (model)
+ {
++ case 0x55:
++ if (stepping <= 5)
++ goto disable_tsx;
++ break;
++ case 0x8e:
++ /* NB: Although the errata documents that for model == 0x8e,
++ only 0xb stepping or lower are impacted, the intention of
++ the errata was to disable TSX on all client processors on
++ all steppings. Include 0xc stepping which is an Intel
++ Core i7-8665U, a client mobile processor. */
++ case 0x9e:
++ if (stepping > 0xc)
++ break;
++ /* Fall through. */
++ case 0x4e:
++ case 0x5e:
++ {
++ /* Disable Intel TSX and enable RTM_ALWAYS_ABORT for
++ processors listed in:
++
++https://www.intel.com/content/www/us/en/support/articles/000059422/processors.html
++ */
++disable_tsx:
++ CPU_FEATURE_UNSET (cpu_features, HLE);
++ CPU_FEATURE_UNSET (cpu_features, RTM);
++ CPU_FEATURE_SET (cpu_features, RTM_ALWAYS_ABORT);
++ }
++ break;
+ case 0x3f:
+ /* Xeon E7 v3 with stepping >= 4 has working TSX. */
+ if (stepping >= 4)
+--
+2.27.0
+
diff --git a/x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch b/x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch
new file mode 100644
index 0000000..6bfbc68
--- /dev/null
+++ b/x86-Fallback-str-wcs-cmp-RTM-in-the-ncmp-overflow-ca.patch
@@ -0,0 +1,132 @@
+From 38e0d2479413ccdbc02b4c9e9e246eca31e956c9 Mon Sep 17 00:00:00 2001
+From: Noah Goldstein <goldstein.w.n@gmail.com>
+Date: Tue, 15 Feb 2022 08:18:15 -0600
+Subject: [PATCH] x86: Fallback {str|wcs}cmp RTM in the ncmp overflow case [BZ
+ #28896]
+
+In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
+call strcmp-avx2 and wcscmp-avx2 respectively. This would have
+not checks around vzeroupper and would trigger spurious
+aborts. This commit fixes that.
+
+test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
+AVX2 machines with and without RTM.
+
+Co-authored-by: H.J. Lu <hjl.tools@gmail.com>
+
+(cherry picked from commit c6272098323153db373f2986c67786ea8c85f1cf)
+---
+ sysdeps/x86/Makefile | 2 +-
+ sysdeps/x86/tst-strncmp-rtm.c | 17 ++++++++++++++++-
+ sysdeps/x86_64/multiarch/strcmp-avx2.S | 2 +-
+ sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S | 1 +
+ sysdeps/x86_64/multiarch/strncmp-avx2.S | 1 +
+ sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S | 2 +-
+ sysdeps/x86_64/multiarch/wcsncmp-avx2.S | 2 +-
+ 7 files changed, 22 insertions(+), 5 deletions(-)
+
+diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
+index 5ee06f9473..6c3e08a3d7 100644
+--- a/sysdeps/x86/Makefile
++++ b/sysdeps/x86/Makefile
+@@ -104,7 +104,7 @@ CFLAGS-tst-memset-rtm.c += -mrtm
+ CFLAGS-tst-strchr-rtm.c += -mrtm
+ CFLAGS-tst-strcpy-rtm.c += -mrtm
+ CFLAGS-tst-strlen-rtm.c += -mrtm
+-CFLAGS-tst-strncmp-rtm.c += -mrtm
++CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error
+ CFLAGS-tst-strrchr-rtm.c += -mrtm
+ endif
+
+diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c
+index 236ad951b5..4d0004b58a 100644
+--- a/sysdeps/x86/tst-strncmp-rtm.c
++++ b/sysdeps/x86/tst-strncmp-rtm.c
+@@ -16,6 +16,7 @@
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
++#include <stdint.h>
+ #include <tst-string-rtm.h>
+
+ #define LOOP 3000
+@@ -45,8 +46,22 @@ function (void)
+ return 1;
+ }
+
++__attribute__ ((noinline, noclone))
++static int
++function_overflow (void)
++{
++ if (strncmp (string1, string2, SIZE_MAX) == 0)
++ return 0;
++ else
++ return 1;
++}
++
+ static int
+ do_test (void)
+ {
+- return do_test_1 ("strncmp", LOOP, prepare, function);
++ int status = do_test_1 ("strncmp", LOOP, prepare, function);
++ if (status != EXIT_SUCCESS)
++ return status;
++ status = do_test_1 ("strncmp", LOOP, prepare, function_overflow);
++ return status;
+ }
+diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S
+index 3dfcb1bf80..fa70c994fc 100644
+--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S
++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S
+@@ -95,7 +95,7 @@ ENTRY (STRCMP)
+ length to bound a valid memory region. In these cases just use
+ 'wcscmp'. */
+ shrq $56, %rcx
+- jnz __wcscmp_avx2
++ jnz OVERFLOW_STRCMP
+ # endif
+ /* Convert units: from wide to byte char. */
+ shl $2, %RDX_LP
+diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
+index 37d1224bb9..68bad365ba 100644
+--- a/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
++++ b/sysdeps/x86_64/multiarch/strncmp-avx2-rtm.S
+@@ -1,3 +1,4 @@
+ #define STRCMP __strncmp_avx2_rtm
+ #define USE_AS_STRNCMP 1
++#define OVERFLOW_STRCMP __strcmp_avx2_rtm
+ #include "strcmp-avx2-rtm.S"
+diff --git a/sysdeps/x86_64/multiarch/strncmp-avx2.S b/sysdeps/x86_64/multiarch/strncmp-avx2.S
+index 1678bcc235..f138e9f1fd 100644
+--- a/sysdeps/x86_64/multiarch/strncmp-avx2.S
++++ b/sysdeps/x86_64/multiarch/strncmp-avx2.S
+@@ -1,3 +1,4 @@
+ #define STRCMP __strncmp_avx2
+ #define USE_AS_STRNCMP 1
++#define OVERFLOW_STRCMP __strcmp_avx2
+ #include "strcmp-avx2.S"
+diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
+index 4e88c70cc6..f467582cbe 100644
+--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
++++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2-rtm.S
+@@ -1,5 +1,5 @@
+ #define STRCMP __wcsncmp_avx2_rtm
+ #define USE_AS_STRNCMP 1
+ #define USE_AS_WCSCMP 1
+-
++#define OVERFLOW_STRCMP __wcscmp_avx2_rtm
+ #include "strcmp-avx2-rtm.S"
+diff --git a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
+index 4fa1de4d3f..e9ede522b8 100644
+--- a/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
++++ b/sysdeps/x86_64/multiarch/wcsncmp-avx2.S
+@@ -1,5 +1,5 @@
+ #define STRCMP __wcsncmp_avx2
+ #define USE_AS_STRNCMP 1
+ #define USE_AS_WCSCMP 1
+-
++#define OVERFLOW_STRCMP __wcscmp_avx2
+ #include "strcmp-avx2.S"
+--
+2.27.0
+
diff --git a/x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch b/x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch
new file mode 100644
index 0000000..2b231d1
--- /dev/null
+++ b/x86-Fix-TEST_NAME-to-make-it-a-string-in-tst-strncmp.patch
@@ -0,0 +1,37 @@
+From 15b00d2af0e56dcc8c244a36d6872d301b0c7185 Mon Sep 17 00:00:00 2001
+From: Noah Goldstein <goldstein.w.n@gmail.com>
+Date: Fri, 18 Feb 2022 17:00:25 -0600
+Subject: [PATCH] x86: Fix TEST_NAME to make it a string in tst-strncmp-rtm.c
+
+Previously TEST_NAME was passing a function pointer. This didn't fail
+because of the -Wno-error flag (to allow for overflow sizes passed
+to strncmp/wcsncmp)
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+(cherry picked from commit b98d0bbf747f39770e0caba7e984ce9f8f900330)
+---
+ sysdeps/x86/tst-strncmp-rtm.c | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c
+index 4e9f094f39..aef9866cf2 100644
+--- a/sysdeps/x86/tst-strncmp-rtm.c
++++ b/sysdeps/x86/tst-strncmp-rtm.c
+@@ -23,12 +23,12 @@
+ # define CHAR wchar_t
+ # define MEMSET wmemset
+ # define STRNCMP wcsncmp
+-# define TEST_NAME wcsncmp
++# define TEST_NAME "wcsncmp"
+ #else /* !WIDE */
+ # define CHAR char
+ # define MEMSET memset
+ # define STRNCMP strncmp
+-# define TEST_NAME strncmp
++# define TEST_NAME "strncmp"
+ #endif /* !WIDE */
+
+
+--
+2.27.0
+
diff --git a/x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch b/x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch
new file mode 100644
index 0000000..7b8597b
--- /dev/null
+++ b/x86-Fix-__wcsncmp_avx2-in-strcmp-avx2.S-BZ-28755.patch
@@ -0,0 +1,40 @@
+From ddf0992cf57a93200e0c782e2a94d0733a5a0b87 Mon Sep 17 00:00:00 2001
+From: Noah Goldstein <goldstein.w.n@gmail.com>
+Date: Sun, 9 Jan 2022 16:02:21 -0600
+Subject: [PATCH] x86: Fix __wcsncmp_avx2 in strcmp-avx2.S [BZ# 28755]
+
+Fixes [BZ# 28755] for wcsncmp by redirecting length >= 2^56 to
+__wcscmp_avx2. For x86_64 this covers the entire address range so any
+length larger could not possibly be used to bound `s1` or `s2`.
+
+test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass.
+
+Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
+---
+ sysdeps/x86_64/multiarch/strcmp-avx2.S | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/sysdeps/x86_64/multiarch/strcmp-avx2.S b/sysdeps/x86_64/multiarch/strcmp-avx2.S
+index a45f9d2..9c73b58 100644
+--- a/sysdeps/x86_64/multiarch/strcmp-avx2.S
++++ b/sysdeps/x86_64/multiarch/strcmp-avx2.S
+@@ -87,6 +87,16 @@ ENTRY (STRCMP)
+ je L(char0)
+ jb L(zero)
+ # ifdef USE_AS_WCSCMP
++# ifndef __ILP32__
++ movq %rdx, %rcx
++ /* Check if length could overflow when multiplied by
++ sizeof(wchar_t). Checking top 8 bits will cover all potential
++ overflow cases as well as redirect cases where its impossible to
++ length to bound a valid memory region. In these cases just use
++ 'wcscmp'. */
++ shrq $56, %rcx
++ jnz __wcscmp_avx2
++# endif
+ /* Convert units: from wide to byte char. */
+ shl $2, %RDX_LP
+ # endif
+--
+1.8.3.1
+
diff --git a/x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch b/x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch
new file mode 100644
index 0000000..2b5227e
--- /dev/null
+++ b/x86-Fix-__wcsncmp_evex-in-strcmp-evex.S-BZ-28755.patch
@@ -0,0 +1,40 @@
+From 7e08db3359c86c94918feb33a1182cd0ff3bb10b Mon Sep 17 00:00:00 2001
+From: Noah Goldstein <goldstein.w.n@gmail.com>
+Date: Sun, 9 Jan 2022 16:02:28 -0600
+Subject: [PATCH] x86: Fix __wcsncmp_evex in strcmp-evex.S [BZ# 28755]
+
+Fixes [BZ# 28755] for wcsncmp by redirecting length >= 2^56 to
+__wcscmp_evex. For x86_64 this covers the entire address range so any
+length larger could not possibly be used to bound `s1` or `s2`.
+
+test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass.
+
+Signed-off-by: Noah Goldstein <goldstein.w.n@gmail.com>
+---
+ sysdeps/x86_64/multiarch/strcmp-evex.S | 10 ++++++++++
+ 1 file changed, 10 insertions(+)
+
+diff --git a/sysdeps/x86_64/multiarch/strcmp-evex.S b/sysdeps/x86_64/multiarch/strcmp-evex.S
+index 1d971f3..0cd939d 100644
+--- a/sysdeps/x86_64/multiarch/strcmp-evex.S
++++ b/sysdeps/x86_64/multiarch/strcmp-evex.S
+@@ -104,6 +104,16 @@ ENTRY (STRCMP)
+ je L(char0)
+ jb L(zero)
+ # ifdef USE_AS_WCSCMP
++# ifndef __ILP32__
++ movq %rdx, %rcx
++ /* Check if length could overflow when multiplied by
++ sizeof(wchar_t). Checking top 8 bits will cover all potential
++ overflow cases as well as redirect cases where its impossible to
++ length to bound a valid memory region. In these cases just use
++ 'wcscmp'. */
++ shrq $56, %rcx
++ jnz __wcscmp_evex
++# endif
+ /* Convert units: from wide to byte char. */
+ shl $2, %RDX_LP
+ # endif
+--
+1.8.3.1
+
diff --git a/x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch b/x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch
new file mode 100644
index 0000000..6d7469b
--- /dev/null
+++ b/x86-Test-wcscmp-RTM-in-the-wcsncmp-overflow-case-BZ-.patch
@@ -0,0 +1,147 @@
+From d093b677c36ef4b360bf30483b68b95d9f0ad1d2 Mon Sep 17 00:00:00 2001
+From: Noah Goldstein <goldstein.w.n@gmail.com>
+Date: Fri, 18 Feb 2022 14:19:15 -0600
+Subject: [PATCH] x86: Test wcscmp RTM in the wcsncmp overflow case [BZ #28896]
+
+In the overflow fallback strncmp-avx2-rtm and wcsncmp-avx2-rtm would
+call strcmp-avx2 and wcscmp-avx2 respectively. This would have
+not checks around vzeroupper and would trigger spurious
+aborts. This commit fixes that.
+
+test-strcmp, test-strncmp, test-wcscmp, and test-wcsncmp all pass on
+AVX2 machines with and without RTM.
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+
+(cherry picked from commit 7835d611af0854e69a0c71e3806f8fe379282d6f)
+---
+ sysdeps/x86/Makefile | 5 ++++-
+ sysdeps/x86/tst-strncmp-rtm.c | 32 +++++++++++++++++++++++---------
+ sysdeps/x86/tst-wcsncmp-rtm.c | 21 +++++++++++++++++++++
+ 3 files changed, 48 insertions(+), 10 deletions(-)
+ create mode 100644 sysdeps/x86/tst-wcsncmp-rtm.c
+
+diff --git a/sysdeps/x86/Makefile b/sysdeps/x86/Makefile
+index 6c3e08a3d7..d7fe68609f 100644
+--- a/sysdeps/x86/Makefile
++++ b/sysdeps/x86/Makefile
+@@ -94,7 +94,9 @@ tests += \
+ tst-strcpy-rtm \
+ tst-strlen-rtm \
+ tst-strncmp-rtm \
+- tst-strrchr-rtm
++ tst-strrchr-rtm \
++ tst-wcsncmp-rtm \
++# tests
+
+ CFLAGS-tst-memchr-rtm.c += -mrtm
+ CFLAGS-tst-memcmp-rtm.c += -mrtm
+@@ -106,6 +108,7 @@ CFLAGS-tst-strcpy-rtm.c += -mrtm
+ CFLAGS-tst-strlen-rtm.c += -mrtm
+ CFLAGS-tst-strncmp-rtm.c += -mrtm -Wno-error
+ CFLAGS-tst-strrchr-rtm.c += -mrtm
++CFLAGS-tst-wcsncmp-rtm.c += -mrtm -Wno-error
+ endif
+
+ ifneq ($(enable-cet),no)
+diff --git a/sysdeps/x86/tst-strncmp-rtm.c b/sysdeps/x86/tst-strncmp-rtm.c
+index 4d0004b58a..4e9f094f39 100644
+--- a/sysdeps/x86/tst-strncmp-rtm.c
++++ b/sysdeps/x86/tst-strncmp-rtm.c
+@@ -19,18 +19,32 @@
+ #include <stdint.h>
+ #include <tst-string-rtm.h>
+
++#ifdef WIDE
++# define CHAR wchar_t
++# define MEMSET wmemset
++# define STRNCMP wcsncmp
++# define TEST_NAME wcsncmp
++#else /* !WIDE */
++# define CHAR char
++# define MEMSET memset
++# define STRNCMP strncmp
++# define TEST_NAME strncmp
++#endif /* !WIDE */
++
++
++
+ #define LOOP 3000
+ #define STRING_SIZE 1024
+-char string1[STRING_SIZE];
+-char string2[STRING_SIZE];
++CHAR string1[STRING_SIZE];
++CHAR string2[STRING_SIZE];
+
+ __attribute__ ((noinline, noclone))
+ static int
+ prepare (void)
+ {
+- memset (string1, 'a', STRING_SIZE - 1);
+- memset (string2, 'a', STRING_SIZE - 1);
+- if (strncmp (string1, string2, STRING_SIZE) == 0)
++ MEMSET (string1, 'a', STRING_SIZE - 1);
++ MEMSET (string2, 'a', STRING_SIZE - 1);
++ if (STRNCMP (string1, string2, STRING_SIZE) == 0)
+ return EXIT_SUCCESS;
+ else
+ return EXIT_FAILURE;
+@@ -40,7 +54,7 @@ __attribute__ ((noinline, noclone))
+ static int
+ function (void)
+ {
+- if (strncmp (string1, string2, STRING_SIZE) == 0)
++ if (STRNCMP (string1, string2, STRING_SIZE) == 0)
+ return 0;
+ else
+ return 1;
+@@ -50,7 +64,7 @@ __attribute__ ((noinline, noclone))
+ static int
+ function_overflow (void)
+ {
+- if (strncmp (string1, string2, SIZE_MAX) == 0)
++ if (STRNCMP (string1, string2, SIZE_MAX) == 0)
+ return 0;
+ else
+ return 1;
+@@ -59,9 +73,9 @@ function_overflow (void)
+ static int
+ do_test (void)
+ {
+- int status = do_test_1 ("strncmp", LOOP, prepare, function);
++ int status = do_test_1 (TEST_NAME, LOOP, prepare, function);
+ if (status != EXIT_SUCCESS)
+ return status;
+- status = do_test_1 ("strncmp", LOOP, prepare, function_overflow);
++ status = do_test_1 (TEST_NAME, LOOP, prepare, function_overflow);
+ return status;
+ }
+diff --git a/sysdeps/x86/tst-wcsncmp-rtm.c b/sysdeps/x86/tst-wcsncmp-rtm.c
+new file mode 100644
+index 0000000000..bad3b86378
+--- /dev/null
++++ b/sysdeps/x86/tst-wcsncmp-rtm.c
+@@ -0,0 +1,21 @@
++/* Test case for wcsncmp inside a transactionally executing RTM region.
++ Copyright (C) 2022 Free Software Foundation, Inc.
++ This file is part of the GNU C Library.
++
++ The GNU C Library is free software; you can redistribute it and/or
++ modify it under the terms of the GNU Lesser General Public
++ License as published by the Free Software Foundation; either
++ version 2.1 of the License, or (at your option) any later version.
++
++ The GNU C Library is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ Lesser General Public License for more details.
++
++ You should have received a copy of the GNU Lesser General Public
++ License along with the GNU C Library; if not, see
++ <https://www.gnu.org/licenses/>. */
++
++#define WIDE 1
++#include <wchar.h>
++#include "tst-strncmp-rtm.c"
+--
+2.27.0
+
diff --git a/x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch b/x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch
new file mode 100644
index 0000000..ecd4a42
--- /dev/null
+++ b/x86-Use-CHECK_FEATURE_PRESENT-to-check-HLE-BZ-27398.patch
@@ -0,0 +1,29 @@
+From aa601d024424c40ae9a69b0c4e394a70ea0570c8 Mon Sep 17 00:00:00 2001
+From: "H.J. Lu" <hjl.tools@gmail.com>
+Date: Mon, 24 Jan 2022 19:33:43 -0800
+Subject: [PATCH] x86: Use CHECK_FEATURE_PRESENT to check HLE [BZ #27398]
+
+HLE is disabled on blacklisted CPUs. Use CHECK_FEATURE_PRESENT, instead
+of CHECK_FEATURE_ACTIVE, to check HLE.
+
+(cherry picked from commit 501246c5e2dfcc278f0ebbdb72345cdd239521c7)
+---
+ sysdeps/x86/tst-cpu-features-supports.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+diff --git a/sysdeps/x86/tst-cpu-features-supports.c b/sysdeps/x86/tst-cpu-features-supports.c
+index 9d76e6bd3f..faa5091b78 100644
+--- a/sysdeps/x86/tst-cpu-features-supports.c
++++ b/sysdeps/x86/tst-cpu-features-supports.c
+@@ -130,7 +130,7 @@ do_test (int argc, char **argv)
+ fails += CHECK_FEATURE_ACTIVE (gfni, GFNI);
+ #endif
+ #if __GNUC_PREREQ (11, 0)
+- fails += CHECK_FEATURE_ACTIVE (hle, HLE);
++ fails += CHECK_FEATURE_PRESENT (hle, HLE);
+ fails += CHECK_FEATURE_PRESENT (ibt, IBT);
+ fails += CHECK_FEATURE_ACTIVE (lahf_lm, LAHF64_SAHF64);
+ fails += CHECK_FEATURE_PRESENT (lm, LM);
+--
+2.27.0
+
diff --git a/x86-fix-Autoconf-caching-of-instruction-support-chec.patch b/x86-fix-Autoconf-caching-of-instruction-support-chec.patch
new file mode 100644
index 0000000..d4117fa
--- /dev/null
+++ b/x86-fix-Autoconf-caching-of-instruction-support-chec.patch
@@ -0,0 +1,178 @@
+From 0835c0f0bad351117154b815f34f8af19ea7e325 Mon Sep 17 00:00:00 2001
+From: Matt Whitlock <sourceware@mattwhitlock.name>
+Date: Wed, 16 Jun 2021 23:40:47 -0400
+Subject: [PATCH] x86: fix Autoconf caching of instruction support checks [BZ
+ #27991]
+
+The Autoconf documentation for the AC_CACHE_CHECK macro states:
+
+ The commands-to-set-it must have no side effects except for setting
+ the variable cache-id, see below.
+
+However, the tests for support of -msahf and -mmovbe were embedded in
+the commands-to-set-it for lib_cv_include_x86_isa_level. This had the
+consequence that libc_cv_have_x86_lahf_sahf and libc_cv_have_x86_movbe
+were not defined whenever lib_cv_include_x86_isa_level was read from
+cache. These variables' being undefined meant that their unquoted use
+in later test expressions led to the 'test' built-in's misparsing its
+arguments and emitting errors like "test: =: unexpected operator" or
+"test: =: unary operator expected", depending on the particular shell.
+
+This commit refactors the tests for LAHF/SAHF and MOVBE instruction
+support into their own AC_CACHE_CHECK macro invocations to obey the
+rule that the commands-to-set-it must have no side effects other than
+setting the variable named by cache-id.
+
+Signed-off-by: Matt Whitlock <sourceware@mattwhitlock.name>
+Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
+---
+ sysdeps/x86/configure | 56 ++++++++++++++++++++++++++++++------------------
+ sysdeps/x86/configure.ac | 34 +++++++++++++++--------------
+ 2 files changed, 53 insertions(+), 37 deletions(-)
+
+diff --git a/sysdeps/x86/configure b/sysdeps/x86/configure
+index ead1295..62676bb 100644
+--- a/sysdeps/x86/configure
++++ b/sysdeps/x86/configure
+@@ -126,8 +126,6 @@ cat > conftest2.S <<EOF
+ 4:
+ EOF
+ libc_cv_include_x86_isa_level=no
+-libc_cv_have_x86_lahf_sahf=no
+-libc_cv_have_x86_movbe=no
+ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+@@ -137,9 +135,22 @@ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest c
+ count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
+ if test "$count" = 1; then
+ libc_cv_include_x86_isa_level=yes
+- cat > conftest.c <<EOF
+-EOF
+- if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c'
++ fi
++fi
++rm -f conftest*
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_include_x86_isa_level" >&5
++$as_echo "$libc_cv_include_x86_isa_level" >&6; }
++if test $libc_cv_include_x86_isa_level = yes; then
++ $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h
++
++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for LAHF/SAHF instruction support" >&5
++$as_echo_n "checking for LAHF/SAHF instruction support... " >&6; }
++if ${libc_cv_have_x86_lahf_sahf+:} false; then :
++ $as_echo_n "(cached) " >&6
++else
++ libc_cv_have_x86_lahf_sahf=no
++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -147,7 +158,20 @@ EOF
+ test $ac_status = 0; }; } | grep -q "\-msahf"; then
+ libc_cv_have_x86_lahf_sahf=yes
+ fi
+- if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c'
++fi
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_have_x86_lahf_sahf" >&5
++$as_echo "$libc_cv_have_x86_lahf_sahf" >&6; }
++ if test $libc_cv_have_x86_lahf_sahf = yes; then
++ $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h
++
++ fi
++ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for MOVBE instruction support" >&5
++$as_echo_n "checking for MOVBE instruction support... " >&6; }
++if ${libc_cv_have_x86_movbe+:} false; then :
++ $as_echo_n "(cached) " >&6
++else
++ libc_cv_have_x86_movbe=no
++ if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null'
+ { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5
+ (eval $ac_try) 2>&5
+ ac_status=$?
+@@ -155,23 +179,13 @@ EOF
+ test $ac_status = 0; }; } | grep -q "\-mmovbe"; then
+ libc_cv_have_x86_movbe=yes
+ fi
+- fi
+-fi
+-rm -f conftest*
+-fi
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_include_x86_isa_level" >&5
+-$as_echo "$libc_cv_include_x86_isa_level" >&6; }
+-if test $libc_cv_include_x86_isa_level = yes; then
+- $as_echo "#define INCLUDE_X86_ISA_LEVEL 1" >>confdefs.h
+-
+ fi
+-if test $libc_cv_have_x86_lahf_sahf = yes; then
+- $as_echo "#define HAVE_X86_LAHF_SAHF 1" >>confdefs.h
+-
+-fi
+-if test $libc_cv_have_x86_movbe = yes; then
+- $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h
++{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_cv_have_x86_movbe" >&5
++$as_echo "$libc_cv_have_x86_movbe" >&6; }
++ if test $libc_cv_have_x86_movbe = yes; then
++ $as_echo "#define HAVE_X86_MOVBE 1" >>confdefs.h
+
++ fi
+ fi
+ config_vars="$config_vars
+ enable-x86-isa-level = $libc_cv_include_x86_isa_level"
+diff --git a/sysdeps/x86/configure.ac b/sysdeps/x86/configure.ac
+index bca97fd..04a12ab 100644
+--- a/sysdeps/x86/configure.ac
++++ b/sysdeps/x86/configure.ac
+@@ -98,30 +98,32 @@ cat > conftest2.S <<EOF
+ 4:
+ EOF
+ libc_cv_include_x86_isa_level=no
+-libc_cv_have_x86_lahf_sahf=no
+-libc_cv_have_x86_movbe=no
+ if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -nostartfiles -nostdlib -r -o conftest conftest1.S conftest2.S); then
+ count=`LC_ALL=C $READELF -n conftest | grep NT_GNU_PROPERTY_TYPE_0 | wc -l`
+ if test "$count" = 1; then
+ libc_cv_include_x86_isa_level=yes
+- cat > conftest.c <<EOF
+-EOF
+- if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c) | grep -q "\-msahf"; then
+- libc_cv_have_x86_lahf_sahf=yes
+- fi
+- if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - conftest.c) | grep -q "\-mmovbe"; then
+- libc_cv_have_x86_movbe=yes
+- fi
+ fi
+ fi
+ rm -f conftest*])
+ if test $libc_cv_include_x86_isa_level = yes; then
+ AC_DEFINE(INCLUDE_X86_ISA_LEVEL)
+-fi
+-if test $libc_cv_have_x86_lahf_sahf = yes; then
+- AC_DEFINE(HAVE_X86_LAHF_SAHF)
+-fi
+-if test $libc_cv_have_x86_movbe = yes; then
+- AC_DEFINE(HAVE_X86_MOVBE)
++ AC_CACHE_CHECK([for LAHF/SAHF instruction support],
++ libc_cv_have_x86_lahf_sahf, [dnl
++ libc_cv_have_x86_lahf_sahf=no
++ if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -q "\-msahf"; then
++ libc_cv_have_x86_lahf_sahf=yes
++ fi])
++ if test $libc_cv_have_x86_lahf_sahf = yes; then
++ AC_DEFINE(HAVE_X86_LAHF_SAHF)
++ fi
++ AC_CACHE_CHECK([for MOVBE instruction support],
++ libc_cv_have_x86_movbe, [dnl
++ libc_cv_have_x86_movbe=no
++ if AC_TRY_COMMAND(${CC-cc} $CFLAGS $CPPFLAGS -fverbose-asm -S -o - -x c /dev/null) | grep -q "\-mmovbe"; then
++ libc_cv_have_x86_movbe=yes
++ fi])
++ if test $libc_cv_have_x86_movbe = yes; then
++ AC_DEFINE(HAVE_X86_MOVBE)
++ fi
+ fi
+ LIBC_CONFIG_VAR([enable-x86-isa-level], [$libc_cv_include_x86_isa_level])
+--
+1.8.3.1
+
diff --git a/x86-use-default-cache-size-if-it-cannot-be-determine.patch b/x86-use-default-cache-size-if-it-cannot-be-determine.patch
new file mode 100644
index 0000000..7eeae68
--- /dev/null
+++ b/x86-use-default-cache-size-if-it-cannot-be-determine.patch
@@ -0,0 +1,61 @@
+From c242fcce06e3102ca663b2f992611d0bda4f2668 Mon Sep 17 00:00:00 2001
+From: Aurelien Jarno <aurelien@aurel32.net>
+Date: Mon, 17 Jan 2022 19:41:40 +0100
+Subject: [PATCH] x86: use default cache size if it cannot be determined [BZ
+ #28784]
+
+In some cases (e.g QEMU, non-Intel/AMD CPU) the cache information can
+not be retrieved and the corresponding values are set to 0.
+
+Commit 2d651eb9265d ("x86: Move x86 processor cache info to
+cpu_features") changed the behaviour in such case by defining the
+__x86_shared_cache_size and __x86_data_cache_size variables to 0 instead
+of using the default values. This cause an issue with the i686 SSE2
+optimized bzero/routine which assumes that the cache size is at least
+128 bytes, and otherwise tries to zero/set the whole address space minus
+128 bytes.
+
+Fix that by restoring the original code to only update
+__x86_shared_cache_size and __x86_data_cache_size variables if the
+corresponding cache sizes are not zero.
+
+Fixes bug 28784
+Fixes commit 2d651eb9265d
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+---
+ sysdeps/x86/cacheinfo.h | 14 ++++++++++----
+ 1 file changed, 10 insertions(+), 4 deletions(-)
+
+diff --git a/sysdeps/x86/cacheinfo.h b/sysdeps/x86/cacheinfo.h
+index 4f91a1e98d..65132a9d19 100644
+--- a/sysdeps/x86/cacheinfo.h
++++ b/sysdeps/x86/cacheinfo.h
+@@ -61,14 +61,20 @@ init_cacheinfo (void)
+ long int data = cpu_features->data_cache_size;
+ /* Round data cache size to multiple of 256 bytes. */
+ data = data & ~255L;
+- __x86_data_cache_size_half = data / 2;
+- __x86_data_cache_size = data;
++ if (data > 0)
++ {
++ __x86_data_cache_size_half = data / 2;
++ __x86_data_cache_size = data;
++ }
+
+ long int shared = cpu_features->shared_cache_size;
+ /* Round shared cache size to multiple of 256 bytes. */
+ shared = shared & ~255L;
+- __x86_shared_cache_size_half = shared / 2;
+- __x86_shared_cache_size = shared;
++ if (shared > 0)
++ {
++ __x86_shared_cache_size_half = shared / 2;
++ __x86_shared_cache_size = shared;
++ }
+
+ __x86_shared_non_temporal_threshold
+ = cpu_features->non_temporal_threshold;
+--
+2.27.0
+
diff --git a/x86-use-total-l3cache-for-non_temporal_threshold.patch b/x86-use-total-l3cache-for-non_temporal_threshold.patch
new file mode 100644
index 0000000..a5eb85c
--- /dev/null
+++ b/x86-use-total-l3cache-for-non_temporal_threshold.patch
@@ -0,0 +1,74 @@
+From af0606f5d626b92d6e59da3a797548e9daab5580 Mon Sep 17 00:00:00 2001
+From: Qingqing Li <liqingqing3@huawei.com>
+Date: Sat, 25 Jun 2022 15:36:44 +0800
+Subject: [PATCH] x86: use total l3cache for non_temporal_threshold
+
+Below glibc upstream patch modified the default behavoir for large size of memcpy,
+such as 1M~10M. revert it and use GLIBC_TUNABLES="glibc.cpu.x86_non_temporal_threshold=xxx"
+to tune the application when needed.
+
+d3c57027470b78dba79c6d931e4e409b1fecfc80
+Author: Patrick McGehearty <patrick.mcgehearty@oracle.com>
+Date: Mon Sep 28 20:11:28 2020 +0000
+
+ Reversing calculation of __x86_shared_non_temporal_threshold
+
+ The __x86_shared_non_temporal_threshold determines when memcpy on x86
+ uses non_temporal stores to avoid pushing other data out of the last
+ level cache.
+ uses non_temporal stores to avoid pushing other data out of the last
+ level cache.
+
+ This patch proposes to revert the calculation change made by H.J. Lu's
+ patch of June 2, 2017.
+
+ H.J. Lu's patch selected a threshold suitable for a single thread
+ getting maximum performance. It was tuned using the single threaded
+ large memcpy micro benchmark on an 8 core processor. The last change
+ changes the threshold from using 3/4 of one thread's share of the
+ cache to using 3/4 of the entire cache of a multi-threaded system
+ before switching to non-temporal stores. Multi-threaded systems with
+ more than a few threads are server-class and typically have many
+ active threads. If one thread consumes 3/4 of the available cache for
+ all threads, it will cause other active threads to have data removed
+ from the cache. Two examples show the range of the effect. John
+ McCalpin's widely parallel Stream benchmark, which runs in parallel
+ and fetches data sequentially, saw a 20% slowdown with this patch on
+ an internal system test of 128 threads. This regression was discovered
+ when comparing OL8 performance to OL7. An example that compares
+ normal stores to non-temporal stores may be found at
+ https://vgatherps.github.io/2018-09-02-nontemporal/. A simple test
+ shows performance loss of 400 to 500% due to a failure to use
+ nontemporal stores. These performance losses are most likely to occur
+ when the system load is heaviest and good performance is critical.
+
+ The tunable x86_non_temporal_threshold can be used to override the
+ default for the knowledgable user who really wants maximum cache
+ allocation to a single thread in a multi-threaded system.
+ The manual entry for the tunable has been expanded to provide
+ more information about its purpose.
+
+ modified: sysdeps/x86/cacheinfo.c
+ modified: manual/tunables.texi
+---
+ sysdeps/x86/dl-cacheinfo.h | 4 ++++++
+ 1 file changed, 4 insertions(+)
+
+diff --git a/sysdeps/x86/dl-cacheinfo.h b/sysdeps/x86/dl-cacheinfo.h
+index e6c94dfd..c5e8deb3 100644
+--- a/sysdeps/x86/dl-cacheinfo.h
++++ b/sysdeps/x86/dl-cacheinfo.h
+@@ -924,6 +924,10 @@ dl_init_cacheinfo (struct cpu_features *cpu_features)
+ if (tunable_size != 0)
+ shared = tunable_size;
+
++ /* keep x86 to use the same non_temporal_threshold like glibc2.28 */
++ if (threads != 0)
++ non_temporal_threshold *= threads;
++
+ tunable_size = TUNABLE_GET (x86_non_temporal_threshold, long int, NULL);
+ /* NB: Ignore the default value 0. */
+ if (tunable_size != 0)
+--
+2.30.0
+
diff --git a/x86_64-Simplify-elf_machine_-load_address-dynamic.patch b/x86_64-Simplify-elf_machine_-load_address-dynamic.patch
new file mode 100644
index 0000000..b411a64
--- /dev/null
+++ b/x86_64-Simplify-elf_machine_-load_address-dynamic.patch
@@ -0,0 +1,55 @@
+From b37b75d269883a2c553bb7019a813094eb4e2dd1 Mon Sep 17 00:00:00 2001
+From: Fangrui Song <maskray@google.com>
+Date: Tue, 17 Aug 2021 10:45:57 -0700
+Subject: [PATCH] x86_64: Simplify elf_machine_{load_address,dynamic}
+
+and drop reliance on _GLOBAL_OFFSET_TABLE_[0] being the link-time
+address of _DYNAMIC. &__ehdr_start is a better way to get the load address.
+
+Reviewed-by: H.J. Lu <hjl.tools@gmail.com>
+---
+ sysdeps/x86_64/dl-machine.h | 21 +++++++--------------
+ 1 file changed, 7 insertions(+), 14 deletions(-)
+
+diff --git a/sysdeps/x86_64/dl-machine.h b/sysdeps/x86_64/dl-machine.h
+index a8596aa..ceee507 100644
+--- a/sysdeps/x86_64/dl-machine.h
++++ b/sysdeps/x86_64/dl-machine.h
+@@ -35,27 +35,20 @@ elf_machine_matches_host (const ElfW(Ehdr) *ehdr)
+ }
+
+
+-/* Return the link-time address of _DYNAMIC. Conveniently, this is the
+- first element of the GOT. This must be inlined in a function which
+- uses global data. */
++/* Return the run-time load address of the shared object. */
+ static inline ElfW(Addr) __attribute__ ((unused))
+-elf_machine_dynamic (void)
++elf_machine_load_address (void)
+ {
+- /* This produces an IP-relative reloc which is resolved at link time. */
+- extern const ElfW(Addr) _GLOBAL_OFFSET_TABLE_[] attribute_hidden;
+- return _GLOBAL_OFFSET_TABLE_[0];
++ extern const ElfW(Ehdr) __ehdr_start attribute_hidden;
++ return (ElfW(Addr)) &__ehdr_start;
+ }
+
+-
+-/* Return the run-time load address of the shared object. */
++/* Return the link-time address of _DYNAMIC. */
+ static inline ElfW(Addr) __attribute__ ((unused))
+-elf_machine_load_address (void)
++elf_machine_dynamic (void)
+ {
+- /* Compute the difference between the runtime address of _DYNAMIC as seen
+- by an IP-relative reference, and the link-time address found in the
+- special unrelocated first GOT entry. */
+ extern ElfW(Dyn) _DYNAMIC[] attribute_hidden;
+- return (ElfW(Addr)) &_DYNAMIC - elf_machine_dynamic ();
++ return (ElfW(Addr)) _DYNAMIC - elf_machine_load_address ();
+ }
+
+ /* Set up the loaded object described by L so its unrelocated PLT
+--
+1.8.3.1
+