diff --git a/glibc-rh2032647-1.patch b/glibc-rh2032647-1.patch new file mode 100644 index 0000000..ebc11b1 --- /dev/null +++ b/glibc-rh2032647-1.patch @@ -0,0 +1,2024 @@ +commit e6fd79f3795d46dfb583e124be49fc063bc3d58b +Author: Chung-Lin Tang +Date: Thu Oct 21 21:41:21 2021 +0800 + + elf: Testing infrastructure for ld.so DSO sorting (BZ #17645) + + This is the first of a 2-part patch set that fixes slow DSO sorting behavior in + the dynamic loader, as reported in BZ #17645. In order to facilitate such a + large modification to the dynamic loader, this first patch implements a testing + framework for validating shared object sorting behavior, to enable comparison + between old/new sorting algorithms, and any later enhancements. + + This testing infrastructure consists of a Python script + scripts/dso-ordering-test.py' which takes in a description language, consisting + of strings that describe a set of link dependency relations between DSOs, and + generates testcase programs and Makefile fragments to automatically test the + described situation, for example: + + a->b->c->d # four objects linked one after another + + a->[bc]->d;b->c # a depends on b and c, which both depend on d, + # b depends on c (b,c linked to object a in fixed order) + + a->b->c;{+a;%a;-a} # a, b, c serially dependent, main program uses + # dlopen/dlsym/dlclose on object a + + a->b->c;{}!->[abc] # a, b, c serially dependent; multiple tests generated + # to test all permutations of a, b, c ordering linked + # to main program + + (Above is just a short description of what the script can do, more + documentation is in the script comments.) + + Two files containing several new tests, elf/dso-sort-tests-[12].def are added, + including test scenarios for BZ #15311 and Redhat issue #1162810 [1]. + + Due to the nature of dynamic loader tests, where the sorting behavior and test + output occurs before/after main(), generating testcases to use + support/test-driver.c does not suffice to control meaningful timeout for ld.so. + Therefore a new utility program 'support/test-run-command', based on + test-driver.c/support_test_main.c has been added. This does the same testcase + control, but for a program specified through a command-line rather than at the + source code level. This utility is used to run the dynamic loader testcases + generated by dso-ordering-test.py. + + [1] https://bugzilla.redhat.com/show_bug.cgi?id=1162810 + + Signed-off-by: Chung-Lin Tang + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index 3e7debdd81baafe0..8dd2b24328113536 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -471,6 +471,21 @@ tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \ + $(objpfx)tst-unused-dep-cmp.out + endif + ++# DSO sorting tests: ++# The dso-ordering-test.py script generates testcase source files in $(objpfx), ++# creating a $(objpfx)-dir for each testcase, and creates a ++# Makefile fragment to be included. ++define include_dsosort_tests ++$(objpfx)$(1).generated-makefile: $(1) ++ $(PYTHON) $(..)scripts/dso-ordering-test.py \ ++ --description-file $$< --objpfx $(objpfx) --output-makefile $$@ ++include $(objpfx)$(1).generated-makefile ++endef ++ ++# Generate from each testcase description file ++$(eval $(call include_dsosort_tests,dso-sort-tests-1.def)) ++$(eval $(call include_dsosort_tests,dso-sort-tests-2.def)) ++ + check-abi: $(objpfx)check-abi-ld.out + tests-special += $(objpfx)check-abi-ld.out + update-abi: update-abi-ld +diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def +new file mode 100644 +index 0000000000000000..873ddf55d91155c6 +--- /dev/null ++++ b/elf/dso-sort-tests-1.def +@@ -0,0 +1,66 @@ ++# DSO sorting test descriptions. ++# This file is to be processed by ../scripts/dso-ordering-test.py, see usage ++# in elf/Makefile for how it is executed. ++ ++# We test both dynamic loader sorting algorithms ++tunable_option: glibc.rtld.dynamic_sort=1 ++tunable_option: glibc.rtld.dynamic_sort=2 ++ ++# Sequence of single dependencies with no cycles. ++tst-dso-ordering1: a->b->c ++output: c>b>a>{}b->[cd]->e ++output: e>d>c>b>a>{}[bc]->[def]->[gh]->i ++output: i>h>g>f>e>d>c>b>a>{}b->[de];a->c->d->e ++output: e>d>c>b>a>{}c cross link is respected correctly ++tst-dso-ordering5: a!->[bc]->d;b->c ++output: d>c>b>a>{}[bcde]->f ++output: f>e>d>c>b>a>{}[bc];b->[cde];e->f ++output: f>e>d>c>b>a>{}b->c=>a;{}->[ba] ++output: c>b>a>{}b->c->d->e;{}!->[abcde] ++output: e>d>c>b>a>{}a->b->c;soname({})=c ++output: b>a>{}b->c->d order). ++# The older dynamic_sort=1 algorithm does not achieve this, while the DFS-based ++# dynamic_sort=2 algorithm does, although it is still arguable whether going ++# beyond spec to do this is the right thing to do. ++# The below expected outputs are what the two algorithms currently produce ++# respectively, for regression testing purposes. ++tst-bz15311: {+a;+e;+f;+g;+d;%d;-d;-g;-f;-e;-a};a->b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c ++xfail_output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[A101 ++{}->* ++A101->(B101 B163 B122 B181) ++A102->(B102 B140 B199 B158) ++A103->(B103 B117 B176 B135) ++A104->(B104 B194 B153 B112) ++A105->(B105 B171 B130 B189) ++A106->(B106 B148 B107 B166) ++A107->(B107 B125 B184 B143) ++A108->(B108 B102 B161 B120) ++A109->(B109 B179 B138 B197) ++A110->(B110 B156 B115 B174) ++A111->(B111 B133 B192 B151) ++A112->(B112 B110 B169 B128) ++A113->(B113 B187 B146 B105) ++A114->(B114 B164 B123 B182) ++A115->(B115 B141 B200 B159) ++A116->(B116 B118 B177 B136) ++A117->(B117 B195 B154 B113) ++A118->(B118 B172 B131 B190) ++A119->(B119 B149 B108 B167) ++A120->(B120 B126 B185 B144) ++A121->(B121 B103 B162) ++A122->(B122 B180 B139 B198) ++A123->(B123 B157 B116 B175) ++A124->(B124 B134 B193 B152) ++A125->(B125 B111 B170 B129) ++A126->(B126 B188 B147 B106) ++A127->(B127 B165 B124 B183) ++A128->(B128 B142 B101 B160) ++A129->(B129 B119 B178 B137) ++A130->(B130 B196 B155 B114) ++A131->(B131 B173 B132 B191) ++A132->(B132 B150 B109 B168) ++A133->(B133 B127 B186 B145) ++A134->(B134 B104 B163 B122) ++A135->(B135 B181 B140 B199) ++A136->(B136 B158 B117 B176) ++A137->(B137 B135 B194 B153) ++A138->(B138 B112 B171 B130) ++A139->(B139 B189 B148 B107) ++A140->(B140 B166 B125 B184) ++A141->(B141 B143 B102 B161) ++A142->(B142 B120 B179 B138) ++A143->(B143 B197 B156 B115) ++A144->(B144 B174 B133 B192) ++A145->(B145 B151 B110 B169) ++A146->(B146 B128 B187) ++A147->(B147 B105 B164 B123) ++A148->(B148 B182 B141 B200) ++A149->(B149 B159 B118 B177) ++A150->(B150 B136 B195 B154) ++A151->(B151 B113 B172 B131) ++A152->(B152 B190 B149 B108) ++A153->(B153 B167 B126 B185) ++A154->(B154 B144 B103 B162) ++A155->(B155 B121 B180 B139) ++A156->(B156 B198 B157 B116) ++A157->(B157 B175 B134 B193) ++A158->(B158 B152 B111 B170) ++A159->(B159 B129 B188 B147) ++A160->(B160 B106 B165 B124) ++A161->(B161 B183 B142 B101) ++A162->(B162 B160 B119 B178) ++A163->(B163 B137 B196 B155) ++A164->(B164 B114 B173 B132) ++A165->(B165 B191 B150 B109) ++A166->(B166 B168 B127 B186) ++A167->(B167 B145 B104 B163) ++A168->(B168 B122 B181 B140) ++A169->(B169 B199 B158 B117) ++A170->(B170 B176 B135 B194) ++A171->(B171 B153 B112) ++A172->(B172 B130 B189 B148) ++A173->(B173 B107 B166 B125) ++A174->(B174 B184 B143 B102) ++A175->(B175 B161 B120 B179) ++A176->(B176 B138 B197 B156) ++A177->(B177 B115 B174 B133) ++A178->(B178 B192 B151 B110) ++A179->(B179 B169 B128 B187) ++A180->(B180 B146 B105 B164) ++A181->(B181 B123 B182 B141) ++A182->(B182 B200 B159 B118) ++A183->(B183 B177 B136 B195) ++A184->(B184 B154 B113 B172) ++A185->(B185 B131 B190 B149) ++A186->(B186 B108 B167 B126) ++A187->(B187 B185 B144 B103) ++A188->(B188 B162 B121 B180) ++A189->(B189 B139 B198 B157) ++A190->(B190 B116 B175 B134) ++A191->(B191 B193 B152 B111) ++A192->(B192 B170 B129 B188) ++A193->(B193 B147 B106 B165) ++A194->(B194 B124 B183 B142) ++A195->(B195 B101 B160 B119) ++A196->(B196 B178 B137) ++A197->(B197 B155 B114 B173) ++A198->(B198 B132 B191 B150) ++A199->(B199 B109 B168 B127) ++A200->(B200 B186 B145 B104) ++B101->(C101 C164 C123 C182) ++B102->(C102 C141 C200 C159) ++B103->(C103 C118 C177 C136) ++B104->(C104 C195 C154 C113) ++B105->(C105 C172 C131 C190) ++B106->(C106 C149 C108 C167) ++B107->(C107 C126 C185 C144) ++B108->(C108 C103 C162 C121) ++B109->(C109 C180 C139 C198) ++B110->(C110 C157 C116 C175) ++B111->(C111 C134 C193 C152) ++B112->(C112 C111 C170 C129) ++B113->(C113 C188 C147 C106) ++B114->(C114 C165 C124 C183) ++B115->(C115 C142 C101 C160) ++B116->(C116 C119 C178 C137) ++B117->(C117 C196 C155 C114) ++B118->(C118 C173 C132 C191) ++B119->(C119 C150 C109 C168) ++B120->(C120 C127 C186 C145) ++B121->(C121 C104 C163 C122) ++B122->(C122 C181 C140 C199) ++B123->(C123 C158 C117 C176) ++B124->(C124 C135 C194 C153) ++B125->(C125 C112 C171 C130) ++B126->(C126 C189 C148 C107) ++B127->(C127 C166 C125 C184) ++B128->(C128 C143 C102 C161) ++B129->(C129 C120 C179 C138) ++B130->(C130 C197 C156 C115) ++B131->(C131 C174 C133 C192) ++B132->(C132 C151 C110 C169) ++B133->(C133 C128 C187 C146) ++B134->(C134 C105 C164 C123) ++B135->(C135 C182 C141 C200) ++B136->(C136 C159 C118 C177) ++B137->(C137 C136 C195 C154) ++B138->(C138 C113 C172 C131) ++B139->(C139 C190 C149 C108) ++B140->(C140 C167 C126 C185) ++B141->(C141 C144 C103 C162) ++B142->(C142 C121 C180 C139) ++B143->(C143 C198 C157 C116) ++B144->(C144 C175 C134 C193) ++B145->(C145 C152 C111 C170) ++B146->(C146 C129 C188 C147) ++B147->(C147 C106 C165 C124) ++B148->(C148 C183 C142 C101) ++B149->(C149 C160 C119 C178) ++B150->(C150 C137 C196 C155) ++B151->(C151 C114 C173 C132) ++B152->(C152 C191 C150 C109) ++B153->(C153 C168 C127 C186) ++B154->(C154 C145 C104 C163) ++B155->(C155 C122 C181 C140) ++B156->(C156 C199 C158 C117) ++B157->(C157 C176 C135 C194) ++B158->(C158 C153 C112 C171) ++B159->(C159 C130 C189 C148) ++B160->(C160 C107 C166 C125) ++B161->(C161 C184 C143 C102) ++B162->(C162 C161 C120 C179) ++B163->(C163 C138 C197 C156) ++B164->(C164 C115 C174 C133) ++B165->(C165 C192 C151 C110) ++B166->(C166 C169 C128 C187) ++B167->(C167 C146 C105 C164) ++B168->(C168 C123 C182 C141) ++B169->(C169 C200 C159 C118) ++B170->(C170 C177 C136 C195) ++B171->(C171 C154 C113 C172) ++B172->(C172 C131 C190 C149) ++B173->(C173 C108 C167 C126) ++B174->(C174 C185 C144 C103) ++B175->(C175 C162 C121 C180) ++B176->(C176 C139 C198 C157) ++B177->(C177 C116 C175 C134) ++B178->(C178 C193 C152 C111) ++B179->(C179 C170 C129 C188) ++B180->(C180 C147 C106 C165) ++B181->(C181 C124 C183 C142) ++B182->(C182 C101 C160 C119) ++B183->(C183 C178 C137 C196) ++B184->(C184 C155 C114 C173) ++B185->(C185 C132 C191 C150) ++B186->(C186 C109 C168 C127) ++B187->(C187 C186 C145 C104) ++B188->(C188 C163 C122 C181) ++B189->(C189 C140 C199 C158) ++B190->(C190 C117 C176 C135) ++B191->(C191 C194 C153 C112) ++B192->(C192 C171 C130 C189) ++B193->(C193 C148 C107 C166) ++B194->(C194 C125 C184 C143) ++B195->(C195 C102 C161 C120) ++B196->(C196 C179 C138 C197) ++B197->(C197 C156 C115 C174) ++B198->(C198 C133 C192 C151) ++B199->(C199 C110 C169 C128) ++B200->(C200 C187 C146 C105) ++C101->(A165 A124) ++C102->(A183 A142) ++C103->(A101 A160) ++C104->(A119 A178) ++C105->(A137 A196) ++C106->(A155 A114) ++C107->(A173 A132) ++C108->(A191 A150) ++C109->(A109 A168) ++C110->(A127 A186) ++C111->(A145 A104) ++C112->(A163 A122) ++C113->(A181 A140) ++C114->(A199 A158) ++C115->(A117 A176) ++C116->(A135 A194) ++C117->(A153 A112) ++C118->(A171 A130) ++C119->(A189 A148) ++C120->(A107 A166) ++C121->(A125 A184) ++C122->(A143 A102) ++C123->(A161 A120) ++C124->(A179 A138) ++C125->(A197 A156) ++C126->(A115 A174) ++C127->(A133 A192) ++C128->(A151 A110) ++C129->(A169 A128) ++C130->(A187 A146) ++C131->(A105 A164) ++C132->(A123 A182) ++C133->(A141 A200) ++C134->(A159 A118) ++C135->(A177 A136) ++C136->(A195 A154) ++C137->(A113 A172) ++C138->(A131 A190) ++C139->(A149 A108) ++C140->(A167 A126) ++C141->(A185 A144) ++C142->(A103 A162) ++C143->(A121 A180) ++C144->(A139 A198) ++C145->(A157 A116) ++C146->(A175 A134) ++C147->(A193 A152) ++C148->(A111 A170) ++C149->(A129 A188) ++C150->(A147 A106) ++C151->(A165 A124) ++C152->(A183 A142) ++C153->(A101 A160) ++C154->(A119 A178) ++C155->(A137 A196) ++C156->(A155 A114) ++C157->(A173 A132) ++C158->(A191 A150) ++C159->(A109 A168) ++C160->(A127 A186) ++C161->(A145 A104) ++C162->(A163 A122) ++C163->(A181 A140) ++C164->(A199 A158) ++C165->(A117 A176) ++C166->(A135 A194) ++C167->(A153 A112) ++C168->(A171 A130) ++C169->(A189 A148) ++C170->(A107 A166) ++C171->(A125 A184) ++C172->(A143 A102) ++C173->(A161 A120) ++C174->(A179 A138) ++C175->(A197 A156) ++C176->(A115 A174) ++C177->(A133 A192) ++C178->(A151 A110) ++C179->(A169 A128) ++C180->(A187 A146) ++C181->(A105 A164) ++C182->(A123 A182) ++C183->(A141 A200) ++C184->(A159 A118) ++C185->(A177 A136) ++C186->(A195 A154) ++C187->(A113 A172) ++C188->(A131 A190) ++C189->(A149 A108) ++C190->(A167 A126) ++C191->(A185 A144) ++C192->(A103 A162) ++C193->(A121 A180) ++C194->(A139 A198) ++C195->(A157 A116) ++C196->(A175 A134) ++C197->(A193 A152) ++C198->(A111 A170) ++C199->(A129 A188) ++C200->(A147 A106) ++M11X11->(M13X14 M12X13 M12X12 M12X11) ++M11X12->(M13X25 M12X24 M12X23 M12X22) ++M11X13->(M13X21 M12X20 M12X19 M12X18) ++M11X14->(M13X17 M12X16 M12X15 M12X14) ++M11X15->(M13X13 M12X12 M12X11 M12X25) ++M11X16->(M13X24 M12X23 M12X22 M12X21) ++M11X17->(M13X20 M12X19 M12X18 M12X17) ++M11X18->(M13X16 M12X15 M12X14 M12X13) ++M11X19->(M13X12 M12X11 M12X25 M12X24) ++M11X20->(M13X23 M12X22 M12X21 M12X20) ++M11X21->(M13X19 M12X18 M12X17 M12X16) ++M11X22->(M13X15 M12X14 M12X13 M12X12) ++M11X23->(M13X11 M12X25 M12X24 M12X23) ++M11X24->(M13X22 M12X21 M12X20 M12X19) ++M11X25->(M13X18 M12X17 M12X16 M12X15) ++M12X11->(M14X14 M13X13 M13X12 M13X11) ++M12X12->(M14X25 M13X24 M13X23 M13X22) ++M12X13->(M14X21 M13X20 M13X19 M13X18) ++M12X14->(M14X17 M13X16 M13X15 M13X14) ++M12X15->(M14X13 M13X12 M13X11 M13X25) ++M12X16->(M14X24 M13X23 M13X22 M13X21) ++M12X17->(M14X20 M13X19 M13X18 M13X17) ++M12X18->(M14X16 M13X15 M13X14 M13X13) ++M12X19->(M14X12 M13X11 M13X25 M13X24) ++M12X20->(M14X23 M13X22 M13X21 M13X20) ++M12X21->(M14X19 M13X18 M13X17 M13X16) ++M12X22->(M14X15 M13X14 M13X13 M13X12) ++M12X23->(M14X11 M13X25 M13X24 M13X23) ++M12X24->(M14X22 M13X21 M13X20 M13X19) ++M12X25->(M14X18 M13X17 M13X16 M13X15) ++M13X11->(M15X14 M14X13 M14X12 M14X11) ++M13X12->(M15X25 M14X24 M14X23 M14X22) ++M13X13->(M15X21 M14X20 M14X19 M14X18) ++M13X14->(M15X17 M14X16 M14X15 M14X14) ++M13X15->(M15X13 M14X12 M14X11 M14X25) ++M13X16->(M15X24 M14X23 M14X22 M14X21) ++M13X17->(M15X20 M14X19 M14X18 M14X17) ++M13X18->(M15X16 M14X15 M14X14 M14X13) ++M13X19->(M15X12 M14X11 M14X25 M14X24) ++M13X20->(M15X23 M14X22 M14X21 M14X20) ++M13X21->(M15X19 M14X18 M14X17 M14X16) ++M13X22->(M15X15 M14X14 M14X13 M14X12) ++M13X23->(M15X11 M14X25 M14X24 M14X23) ++M13X24->(M15X22 M14X21 M14X20 M14X19) ++M13X25->(M15X18 M14X17 M14X16 M14X15) ++M14X11->(M16X14 M15X13 M15X12 M15X11) ++M14X12->(M16X25 M15X24 M15X23 M15X22) ++M14X13->(M16X21 M15X20 M15X19 M15X18) ++M14X14->(M16X17 M15X16 M15X15 M15X14) ++M14X15->(M16X13 M15X12 M15X11 M15X25) ++M14X16->(M16X24 M15X23 M15X22 M15X21) ++M14X17->(M16X20 M15X19 M15X18 M15X17) ++M14X18->(M16X16 M15X15 M15X14 M15X13) ++M14X19->(M16X12 M15X11 M15X25 M15X24) ++M14X20->(M16X23 M15X22 M15X21 M15X20) ++M14X21->(M16X19 M15X18 M15X17 M15X16) ++M14X22->(M16X15 M15X14 M15X13 M15X12) ++M14X23->(M16X11 M15X25 M15X24 M15X23) ++M14X24->(M16X22 M15X21 M15X20 M15X19) ++M14X25->(M16X18 M15X17 M15X16 M15X15) ++M15X11->(M17X14 M16X13 M16X12 M16X11) ++M15X12->(M17X25 M16X24 M16X23 M16X22) ++M15X13->(M17X21 M16X20 M16X19 M16X18) ++M15X14->(M17X17 M16X16 M16X15 M16X14) ++M15X15->(M17X13 M16X12 M16X11 M16X25) ++M15X16->(M17X24 M16X23 M16X22 M16X21) ++M15X17->(M17X20 M16X19 M16X18 M16X17) ++M15X18->(M17X16 M16X15 M16X14 M16X13) ++M15X19->(M17X12 M16X11 M16X25 M16X24) ++M15X20->(M17X23 M16X22 M16X21 M16X20) ++M15X21->(M17X19 M16X18 M16X17 M16X16) ++M15X22->(M17X15 M16X14 M16X13 M16X12) ++M15X23->(M17X11 M16X25 M16X24 M16X23) ++M15X24->(M17X22 M16X21 M16X20 M16X19) ++M15X25->(M17X18 M16X17 M16X16 M16X15) ++M16X11->(M18X14 M17X13 M17X12 M17X11) ++M16X12->(M18X25 M17X24 M17X23 M17X22) ++M16X13->(M18X21 M17X20 M17X19 M17X18) ++M16X14->(M18X17 M17X16 M17X15 M17X14) ++M16X15->(M18X13 M17X12 M17X11 M17X25) ++M16X16->(M18X24 M17X23 M17X22 M17X21) ++M16X17->(M18X20 M17X19 M17X18 M17X17) ++M16X18->(M18X16 M17X15 M17X14 M17X13) ++M16X19->(M18X12 M17X11 M17X25 M17X24) ++M16X20->(M18X23 M17X22 M17X21 M17X20) ++M16X21->(M18X19 M17X18 M17X17 M17X16) ++M16X22->(M18X15 M17X14 M17X13 M17X12) ++M16X23->(M18X11 M17X25 M17X24 M17X23) ++M16X24->(M18X22 M17X21 M17X20 M17X19) ++M16X25->(M18X18 M17X17 M17X16 M17X15) ++M17X11->(M19X14 M18X13 M18X12 M18X11) ++M17X12->(M19X25 M18X24 M18X23 M18X22) ++M17X13->(M19X21 M18X20 M18X19 M18X18) ++M17X14->(M19X17 M18X16 M18X15 M18X14) ++M17X15->(M19X13 M18X12 M18X11 M18X25) ++M17X16->(M19X24 M18X23 M18X22 M18X21) ++M17X17->(M19X20 M18X19 M18X18 M18X17) ++M17X18->(M19X16 M18X15 M18X14 M18X13) ++M17X19->(M19X12 M18X11 M18X25 M18X24) ++M17X20->(M19X23 M18X22 M18X21 M18X20) ++M17X21->(M19X19 M18X18 M18X17 M18X16) ++M17X22->(M19X15 M18X14 M18X13 M18X12) ++M17X23->(M19X11 M18X25 M18X24 M18X23) ++M17X24->(M19X22 M18X21 M18X20 M18X19) ++M17X25->(M19X18 M18X17 M18X16 M18X15) ++M18X11->(M20X14 M19X13 M19X12 M19X11) ++M18X12->(M20X25 M19X24 M19X23 M19X22) ++M18X13->(M20X21 M19X20 M19X19 M19X18) ++M18X14->(M20X17 M19X16 M19X15 M19X14) ++M18X15->(M20X13 M19X12 M19X11 M19X25) ++M18X16->(M20X24 M19X23 M19X22 M19X21) ++M18X17->(M20X20 M19X19 M19X18 M19X17) ++M18X18->(M20X16 M19X15 M19X14 M19X13) ++M18X19->(M20X12 M19X11 M19X25 M19X24) ++M18X20->(M20X23 M19X22 M19X21 M19X20) ++M18X21->(M20X19 M19X18 M19X17 M19X16) ++M18X22->(M20X15 M19X14 M19X13 M19X12) ++M18X23->(M20X11 M19X25 M19X24 M19X23) ++M18X24->(M20X22 M19X21 M19X20 M19X19) ++M18X25->(M20X18 M19X17 M19X16 M19X15) ++M19X11->(M21X14 M20X13 M20X12 M20X11) ++M19X12->(M21X25 M20X24 M20X23 M20X22) ++M19X13->(M21X21 M20X20 M20X19 M20X18) ++M19X14->(M21X17 M20X16 M20X15 M20X14) ++M19X15->(M21X13 M20X12 M20X11 M20X25) ++M19X16->(M21X24 M20X23 M20X22 M20X21) ++M19X17->(M21X20 M20X19 M20X18 M20X17) ++M19X18->(M21X16 M20X15 M20X14 M20X13) ++M19X19->(M21X12 M20X11 M20X25 M20X24) ++M19X20->(M21X23 M20X22 M20X21 M20X20) ++M19X21->(M21X19 M20X18 M20X17 M20X16) ++M19X22->(M21X15 M20X14 M20X13 M20X12) ++M19X23->(M21X11 M20X25 M20X24 M20X23) ++M19X24->(M21X22 M20X21 M20X20 M20X19) ++M19X25->(M21X18 M20X17 M20X16 M20X15) ++M20X11->(M22X14 M21X13 M21X12 M21X11) ++M20X12->(M22X25 M21X24 M21X23 M21X22) ++M20X13->(M22X21 M21X20 M21X19 M21X18) ++M20X14->(M22X17 M21X16 M21X15 M21X14) ++M20X15->(M22X13 M21X12 M21X11 M21X25) ++M20X16->(M22X24 M21X23 M21X22 M21X21) ++M20X17->(M22X20 M21X19 M21X18 M21X17) ++M20X18->(M22X16 M21X15 M21X14 M21X13) ++M20X19->(M22X12 M21X11 M21X25 M21X24) ++M20X20->(M22X23 M21X22 M21X21 M21X20) ++M20X21->(M22X19 M21X18 M21X17 M21X16) ++M20X22->(M22X15 M21X14 M21X13 M21X12) ++M20X23->(M22X11 M21X25 M21X24 M21X23) ++M20X24->(M22X22 M21X21 M21X20 M21X19) ++M20X25->(M22X18 M21X17 M21X16 M21X15) ++M21X11->(M23X15 M22X14 M22X13 M22X12) ++M21X12->(M11X11 M23X25 M22X24 M22X23 M22X22) ++M21X13->(M23X21 M22X20 M22X19 M22X18) ++M21X14->(M23X17 M22X16 M22X15 M22X14) ++M21X15->(M23X13 M22X12 M22X11 M22X25) ++M21X16->(M23X24 M22X23 M22X22 M22X21) ++M21X17->(M23X20 M22X19 M22X18 M22X17) ++M21X18->(M23X16 M22X15 M22X14 M22X13) ++M21X19->(M23X12 M22X11 M22X25 M22X24) ++M21X20->(M23X23 M22X22 M22X21 M22X20) ++M21X21->(M23X19 M22X18 M22X17 M22X16) ++M21X22->(M23X15 M22X14 M22X13 M22X12) ++M21X23->(M23X11 M22X25 M22X24 M22X23) ++M21X24->(M23X22 M22X21 M22X20 M22X19) ++M21X25->(M23X18 M22X17 M22X16 M22X15) ++M22X11->(M24X16 M23X15 M23X14 M23X13) ++M22X12->(M12X12 M24X11 M23X25 M23X24 M23X23) ++M22X13->(M24X22 M23X21 M23X20 M23X19) ++M22X14->(M24X18 M23X17 M23X16 M23X15) ++M22X15->(M24X14 M23X13 M23X12 M23X11) ++M22X16->(M24X25 M23X24 M23X23 M23X22) ++M22X17->(M24X21 M23X20 M23X19 M23X18) ++M22X18->(M24X17 M23X16 M23X15 M23X14) ++M22X19->(M24X13 M23X12 M23X11 M23X25) ++M22X20->(M24X24 M23X23 M23X22 M23X21) ++M22X21->(M24X20 M23X19 M23X18 M23X17) ++M22X22->(M24X16 M23X15 M23X14 M23X13) ++M22X23->(M24X12 M23X11 M23X25 M23X24) ++M22X24->(M24X23 M23X22 M23X21 M23X20) ++M22X25->(M24X19 M23X18 M23X17 M23X16) ++M23X11->(M25X17 M24X16 M24X15 M24X14) ++M23X12->(M13X13 M25X12 M24X11 M24X25 M24X24) ++M23X13->(M25X23 M24X22 M24X21 M24X20) ++M23X14->(M25X19 M24X18 M24X17 M24X16) ++M23X15->(M25X15 M24X14 M24X13 M24X12) ++M23X16->(M25X11 M24X25 M24X24 M24X23) ++M23X17->(M25X22 M24X21 M24X20 M24X19) ++M23X18->(M25X18 M24X17 M24X16 M24X15) ++M23X19->(M25X14 M24X13 M24X12 M24X11) ++M23X20->(M25X25 M24X24 M24X23 M24X22) ++M23X21->(M25X21 M24X20 M24X19 M24X18) ++M23X22->(M25X17 M24X16 M24X15 M24X14) ++M23X23->(M25X13 M24X12 M24X11 M24X25) ++M23X24->(M25X24 M24X23 M24X22 M24X21) ++M23X25->(M25X20 M24X19 M24X18 M24X17) ++M24X11->(M26X18 M25X17 M25X16 M25X15) ++M24X12->(M14X14 M26X13 M25X12 M25X11 M25X25) ++M24X13->(M26X24 M25X23 M25X22 M25X21) ++M24X14->(M26X20 M25X19 M25X18 M25X17) ++M24X15->(M26X16 M25X15 M25X14 M25X13) ++M24X16->(M26X12 M25X11 M25X25 M25X24) ++M24X17->(M26X23 M25X22 M25X21 M25X20) ++M24X18->(M26X19 M25X18 M25X17 M25X16) ++M24X19->(M26X15 M25X14 M25X13 M25X12) ++M24X20->(M26X11 M25X25 M25X24 M25X23) ++M24X21->(M26X22 M25X21 M25X20 M25X19) ++M24X22->(M26X18 M25X17 M25X16 M25X15) ++M24X23->(M26X14 M25X13 M25X12 M25X11) ++M24X24->(M26X25 M25X24 M25X23 M25X22) ++M24X25->(M26X21 M25X20 M25X19 M25X18) ++M25X11->(M27X19 M26X18 M26X17 M26X16) ++M25X12->(M15X15 M27X14 M26X13 M26X12 M26X11) ++M25X13->(M27X25 M26X24 M26X23 M26X22) ++M25X14->(M27X21 M26X20 M26X19 M26X18) ++M25X15->(M27X17 M26X16 M26X15 M26X14) ++M25X16->(M27X13 M26X12 M26X11 M26X25) ++M25X17->(M27X24 M26X23 M26X22 M26X21) ++M25X18->(M27X20 M26X19 M26X18 M26X17) ++M25X19->(M27X16 M26X15 M26X14 M26X13) ++M25X20->(M27X12 M26X11 M26X25 M26X24) ++M25X21->(M27X23 M26X22 M26X21 M26X20) ++M25X22->(M27X19 M26X18 M26X17 M26X16) ++M25X23->(M27X15 M26X14 M26X13 M26X12) ++M25X24->(M27X11 M26X25 M26X24 M26X23) ++M25X25->(M27X22 M26X21 M26X20 M26X19) ++M26X11->(M28X20 M27X19 M27X18 M27X17) ++M26X12->(M16X16 M28X15 M27X14 M27X13 M27X12) ++M26X13->(M28X11 M27X25 M27X24 M27X23) ++M26X14->(M28X22 M27X21 M27X20 M27X19) ++M26X15->(M28X18 M27X17 M27X16 M27X15) ++M26X16->(M28X14 M27X13 M27X12 M27X11) ++M26X17->(M28X25 M27X24 M27X23 M27X22) ++M26X18->(M28X21 M27X20 M27X19 M27X18) ++M26X19->(M28X17 M27X16 M27X15 M27X14) ++M26X20->(M28X13 M27X12 M27X11 M27X25) ++M26X21->(M28X24 M27X23 M27X22 M27X21) ++M26X22->(M28X20 M27X19 M27X18 M27X17) ++M26X23->(M28X16 M27X15 M27X14 M27X13) ++M26X24->(M28X12 M27X11 M27X25 M27X24) ++M26X25->(M28X23 M27X22 M27X21 M27X20) ++M27X11->(M29X21 M28X20 M28X19 M28X18) ++M27X12->(M17X17 M29X16 M28X15 M28X14 M28X13) ++M27X13->(M29X12 M28X11 M28X25 M28X24) ++M27X14->(M29X23 M28X22 M28X21 M28X20) ++M27X15->(M29X19 M28X18 M28X17 M28X16) ++M27X16->(M29X15 M28X14 M28X13 M28X12) ++M27X17->(M29X11 M28X25 M28X24 M28X23) ++M27X18->(M29X22 M28X21 M28X20 M28X19) ++M27X19->(M29X18 M28X17 M28X16 M28X15) ++M27X20->(M29X14 M28X13 M28X12 M28X11) ++M27X21->(M29X25 M28X24 M28X23 M28X22) ++M27X22->(M29X21 M28X20 M28X19 M28X18) ++M27X23->(M29X17 M28X16 M28X15 M28X14) ++M27X24->(M29X13 M28X12 M28X11 M28X25) ++M27X25->(M29X24 M28X23 M28X22 M28X21) ++M28X11->(M30X22 M29X21 M29X20 M29X19) ++M28X12->(M18X18 M30X17 M29X16 M29X15 M29X14) ++M28X13->(M30X13 M29X12 M29X11 M29X25) ++M28X14->(M30X24 M29X23 M29X22 M29X21) ++M28X15->(M30X20 M29X19 M29X18 M29X17) ++M28X16->(M30X16 M29X15 M29X14 M29X13) ++M28X17->(M30X12 M29X11 M29X25 M29X24) ++M28X18->(M30X23 M29X22 M29X21 M29X20) ++M28X19->(M30X19 M29X18 M29X17 M29X16) ++M28X20->(M30X15 M29X14 M29X13 M29X12) ++M28X21->(M30X11 M29X25 M29X24 M29X23) ++M28X22->(M30X22 M29X21 M29X20 M29X19) ++M28X23->(M30X18 M29X17 M29X16 M29X15) ++M28X24->(M30X14 M29X13 M29X12 M29X11) ++M28X25->(M30X25 M29X24 M29X23 M29X22) ++M29X11->(M30X22 M30X21 M30X20) ++M29X12->(M30X17 M30X16 M30X15) ++M29X13->(M30X13 M30X12 M30X11) ++M29X14->(M30X24 M30X23 M30X22) ++M29X15->(M30X20 M30X19 M30X18) ++M29X16->(M30X16 M30X15 M30X14) ++M29X17->(M30X12 M30X11 M30X25) ++M29X18->(M30X23 M30X22 M30X21) ++M29X19->(M30X19 M30X18 M30X17) ++M29X20->(M30X15 M30X14 M30X13) ++M29X21->(M30X11 M30X25 M30X24) ++M29X22->(M30X22 M30X21 M30X20) ++M29X23->(M30X18 M30X17 M30X16) ++M29X24->(M30X14 M30X13 M30X12) ++M29X25->(M30X25 M30X24 M30X23) ++M30X11 ++M30X12 ++M30X13 ++M30X14 ++M30X15 ++M30X16 ++M30X17 ++M30X18 ++M30X19 ++M30X20 ++M30X21 ++M30X22 ++M30X23 ++M30X24 ++M30X25 ++xfail_output(glibc.rtld.dynamic_sort=1): M30X19>M30X15>M30X16>M30X11>M30X12>M30X17>M30X13>M30X14>M29X20>M30X23>M30X24>M30X20>M30X18>M29X15>M29X12>M30X22>M30X21>M29X22>M30X25>M29X19>M29X23>M29X16>M29X24>M29X13>M29X17>M29X18>M28X19>M29X21>M29X25>M29X14>M28X20>M28X15>M28X16>M28X21>M27X18>M29X11>M28X17>M28X11>M28X22>M27X14>M28X18>M27X15>M28X13>M27X11>M28X23>M27X25>M28X14>M28X25>M27X23>M27X22>M28X24>M27X21>M27X13>M27X19>M27X17>M26X11>M26X23>M26X21>M26X22>M26X20>M26X16>M25X21>M17X22>M15X15>M20X14>M20X16>M18X18>M28X12>M27X24>M25X17>M27X20>M26X18>M26X17>M27X16>M26X19>M25X18>M26X24>M25X20>M24X17>M23X18>M25X13>M26X13>M17X23>M16X16>M26X12>M25X12>M26X15>M24X19>M25X23>M25X24>M25X25>M24X20>M25X19>M24X21>M23X17>M22X21>M24X14>M23X22>M24X24>M22X20>M24X13>M25X11>M24X12>M25X15>M23X15>M25X16>M24X22>M23X13>M24X18>M23X14>M22X22>M21X20>M24X25>M23X16>M22X25>M21X19>M22X14>M23X11>M22X15>M21X18>M22X19>M21X17>M20X17>M19X17>M21X24>M21X12>M20X22>M19X16>M18X25>M19X21>M19X20>M18X24>M20X12>M19X11>M23X20>M22X24>M22X16>M21X21>M25X14>M23X19>M23X24>M20X24>M19X12>M18X15>M17X14>M16X18>M14X25>M16X22>M16X20>M17X17>M22X12>M21X11>M20X15>M18X22>M19X24>M19X18>M18X21>M17X16>M17X18>M16X21>M15X20>M19X22>M18X20>M18X11>M17X19>M16X17>M15X21>M16X14>M16X13>M15X22>M14X20>M17X25>M16X19>M14X21>M13X24>M12X12>M16X24>M15X23>M14X16>M16X15>M15X25>M15X11>M15X12>M14X15>M13X14>M14X22>M13X20>M12X13>M11X11>M22X23>M21X15>M21X16>M20X21>M20X20>M18X17>M19X25>M18X23>M21X13>M15X17>M15X18>M18X19>M17X24>M16X12>M17X13>M20X25>M19X23>M15X19>M14X13>M13X18>M15X13>M17X12>M16X11>M18X13>M18X12>M14X11>M14X24>M13X19>M15X14>M17X20>M20X11>M20X13>M21X14>M15X24>M14X12>M13X22>M14X23>M13X23>M14X19>M17X15>M16X25>M17X11>M18X14>M19X19>M21X25>M13X12>M13X11>M14X18>M13X13>M12X11>M15X16>M14X14>M27X12>M17X21>M20X23>M22X13>M21X22>M24X16>M24X15>M26X25>M23X25>M26X14>M23X12>M22X18>M24X11>M16X23>M19X14>M19X13>M21X23>M22X17>M23X23>M23X21>M25X22>M18X16>M19X15>M20X18>M20X19>M22X11>M24X23>C156>C118>C143>C137>C147>C106>C168>C113>C163>C155>C105>C146>C187>A150>C139>C180>C164>C193>C157>A191>C158>B188>A159>C184>C121>C154>B171>A105>C131>C104>B104>C161>C111>B145>C160>B155>A163>C112>C142>B148>C133>B198>A198>A115>C114>B157>A156>C175>B144>A120>C173>B184>A174>C126>B107>A139>C194>B194>A194>C116>B116>C166>B160>B110>A110>C128>B128>A128>C179>B162>A154>C186>B187>A179>C124>B181>A101>C153>B158>A136>C135>C176>A192>B133>A133>C177>B177>A177>C185>C103>B141>A141>C183>A162>C192>C129>B179>C144>B124>B183>C127>B127>A127>B108>A112>B153>A153>C167>B167>A186>A122>C162>A144>B149>C174>B131>A185>C141>B106>A126>A167>C140>B122>A170>C198>B143>C117>C123>B123>A147>A106>C200>B169>C191>B175>A123>B118>A182>C132>B151>A145>A104>A109>C159>C150>B119>A119>A178>B164>B114>A164>C181>A102>C122>B134>A157>A116>C195>B191>B111>C172>B172>A118>B129>A129>C149>A107>C170>B197>A197>A173>B168>A132>C107>B165>A160>A131>C188>A168>B109>C178>A189>A148>C119>C190>C120>B166>B176>C108>B135>B139>A103>B178>A169>B132>C125>C138>B163>A111>B170>C110>A165>C151>C169>C199>A138>C182>A135>B101>B142>C101>C148>B193>B152>A158>A199>C136>B137>A161>B120>A108>A149>A125>B113>A184>C171>A134>A175>A124>B150>B161>B102>A146>A187>C130>B192>B200>A200>A142>A183>C102>B105>B156>A176>C165>B147>A137>A196>B190>A190>B125>C134>C189>B126>B186>A166>B136>B195>A195>B154>B138>B112>B173>A117>B159>B182>A181>A140>C145>B117>A152>A193>C197>B130>A172>A113>A151>B115>A143>B140>B185>B103>A121>A180>A130>A171>B199>C196>B146>B180>C115>B174>B121>A188>B196>B189>C152>C109>A155>A114>M14X17>M13X15>M13X16>M13X17>M12X17>M12X21>M12X25>M12X14>M13X25>M12X15>M13X21>M12X16>M12X18>M12X19>M12X20>M12X22>M12X23>M12X24>M11X25>M11X24>M11X23>M11X22>M11X21>M11X20>M11X19>M11X18>M11X17>M11X16>M11X15>M11X14>M11X13>M11X12>{}M30X15>M30X16>M30X11>M30X12>M30X17>M30X13>M30X14>M29X20>M30X23>M30X24>M30X20>M30X18>M29X15>M29X12>M30X22>M30X21>M29X22>M30X25>M29X19>M29X23>M29X16>M29X24>M29X13>M29X17>M29X18>M28X19>M29X21>M29X25>M29X14>M28X20>M28X15>M28X16>M28X21>M27X18>M29X11>M28X17>M28X11>M28X22>M28X24>M28X23>M27X21>M28X13>M27X20>M27X19>M26X14>M27X25>M28X18>M27X11>M28X25>M27X24>M26X24>M27X15>M27X14>M27X13>M26X23>M27X17>M26X22>M25X13>M28X14>M27X16>M26X19>M26X18>M27X23>M27X22>M26X17>M25X18>M26X21>M25X17>M26X20>M26X15>M26X13>M25X19>M24X14>M25X23>M26X11>M26X25>M25X16>M25X15>M24X22>M25X21>M25X20>M24X21>M25X25>M25X24>M24X20>M23X13>M22X15>M25X14>M24X19>M23X17>M24X25>M23X24>M24X13>M23X15>M24X18>M23X14>M22X11>M24X15>M23X22>M24X11>M23X19>M22X21>M24X24>M23X21>M22X20>M23X25>M22X19>M21X24>M20X23>M22X22>M25X11>M23X16>M22X18>M23X20>M22X17>M21X21>M21X20>M20X24>M22X14>M22X13>M21X11>M21X17>M22X23>M21X16>M20X25>M19X23>M18X16>M21X22>M20X20>M20X19>M21X13>M20X18>M19X13>M21X18>M20X21>M19X24>M18X12>M20X14>M20X13>M22X25>M20X12>M20X15>M19X14>M18X22>M19X18>M20X17>M19X17>M19X16>M18X21>M17X20>M19X19>M18X13>M17X11>M18X17>M19X25>M18X15>M17X25>M18X19>M17X24>M16X19>M15X17>M17X21>M16X24>M18X23>M17X16>M16X25>M19X15>M18X25>M17X23>M16X23>M15X23>M18X14>M17X14>M16X14>M17X18>M16X13>M17X22>M16X12>M15X22>M14X16>M17X12>M16X22>M15X12>M16X11>M15X11>M16X15>M15X25>M14X15>M13X14>M15X18>M16X21>M15X16>M14X21>M15X14>M16X20>M15X13>M14X22>M15X20>M14X20>M13X20>M14X11>M15X19>M14X24>M13X19>M14X13>M13X18>M12X13>M15X24>M14X23>M13X12>M14X12>M13X11>M12X11>M11X11>M21X12>M20X11>M19X11>M18X11>M17X15>M16X18>M14X25>M14X19>M13X24>M13X23>M13X22>M12X12>M22X12>M21X15>M19X22>M18X20>M16X17>M14X14>M24X12>M23X23>M22X16>M21X14>M20X22>M18X24>M16X16>M26X12>M24X16>M23X11>M21X23>M19X20>M17X17>M27X12>M26X16>M25X22>M24X17>M23X18>M21X25>M19X12>M17X19>M15X21>M14X18>M13X13>M23X12>M21X19>M19X21>M17X13>M15X15>M25X12>M24X23>M22X24>M20X16>M18X18>M28X12>A150>C158>B112>A112>C167>B146>A146>C180>B180>A180>C143>B143>A115>C126>B126>A126>C190>B190>A190>C138>B138>A138>C174>B174>A102>C122>B122>A122>C162>B162>A162>C142>B142>A142>C102>B102>A174>C176>B176>A176>C115>B115>A143>C172>B172>A172>C187>B187>A187>C130>B130>A130>C118>B118>A118>C184>B184>A184>C171>B171>A171>C168>B182>A182>C182>B168>A168>C109>B109>A109>C159>B159>A159>C134>B134>A134>C146>B167>A167>C140>B140>A140>C163>B163>A163>C112>B158>A158>C164>B164>A164>C131>B131>A131>C188>B188>A188>C199>B199>A199>C114>B114>A114>C106>B106>A106>C200>B200>A200>C183>B183>A183>C152>B152>A152>C147>B147>A147>C150>B150>A198>C144>B144>A144>C191>B191>A191>C108>B108>A108>C139>B139>A139>C194>B194>A194>C166>B166>A166>C120>B120>A120>C123>B123>A123>C132>B132>A132>C107>B107>A107>C170>B170>A170>C198>B198>A156>C125>B125>A125>C121>B121>A121>C193>B193>A193>C197>B197>A197>C175>B175>A175>C196>B196>A196>C105>B105>A105>C181>B181>A181>C113>B113>A113>C137>B137>A137>C155>B155>A155>C156>B156>A110>C128>B128>A128>C179>B179>A179>C124>B124>A124>C151>B151>A151>C178>B178>A178>C104>B104>A104>C111>B111>A111>C148>B148>A148>C169>B169>A169>C129>B129>A129>C149>B149>A149>C189>B189>A189>C119>B119>A119>C154>B154>A154>C136>B136>A136>C135>B135>A135>C116>B116>A116>C145>B145>A145>C161>B161>A161>C173>B173>A173>C157>B157>A157>C195>B195>A195>C186>B186>A186>C160>B160>A160>C153>B153>A153>C117>B117>A117>C165>B165>A165>C101>B101>A101>C103>B103>A103>C192>B192>A192>C177>B177>A177>C185>B185>A185>C141>B141>A141>C133>B133>A133>C127>B127>A127>C110>B110>M14X17>M13X15>M13X16>M13X17>M12X17>M12X21>M12X25>M12X14>M13X25>M12X15>M13X21>M12X16>M12X18>M12X19>M12X20>M12X22>M12X23>M12X24>M11X25>M11X24>M11X23>M11X22>M11X21>M11X20>M11X19>M11X18>M11X17>M11X16>M11X15>M11X14>M11X13>M11X12>{}. ++ ++"""Generate testcase files and Makefile fragments for DSO sorting test ++ ++This script takes a small description string language, and generates ++testcases for displaying the ELF dynamic linker's dependency sorting ++behavior, allowing verification. ++ ++Testcase descriptions are semicolon-separated description strings, and ++this tool generates a testcase from the description, including main program, ++associated modules, and Makefile fragments for including into elf/Makefile. ++ ++This allows automation of what otherwise would be very laborous manual ++construction of complex dependency cases, however it must be noted that this ++is only a tool to speed up testcase construction, and thus the generation ++features are largely mechanical in nature; inconsistencies or errors may occur ++if the input description was itself erroneous or have unforeseen interactions. ++ ++The format of the input test description files are: ++ ++ # Each test description has a name, lines of description, ++ # and an expected output specification. Comments use '#'. ++ testname1: ++ output: ++ ++ # Tests can be marked to be XFAIL by using 'xfail_output' instead ++ testname2: ++ xfail_output: ++ ++ # A default set of GLIBC_TUNABLES tunables can be specified, for which ++ # all following tests will run multiple times, once for each of the ++ # GLIBC_TUNABLES=... strings set by the 'tunable_option' command. ++ tunable_option: ++ tunable_option: ++ ++ # Test descriptions can use multiple lines, which will all be merged ++ # together, so order is not important. ++ testname3: ++ ++ ++ ... ++ output: ++ ++ # 'testname3' will be run and compared two times, for both ++ # GLIBC_TUNABLES= and ++ # GLIBC_TUNABLES=. This can be cleared and reset by the ++ # 'clear_tunables' command: ++ clear_tunables ++ ++ # Multiple expected outputs can also be specified, with an associated ++ # tunable option in (), which multiple tests will be run with each ++ # GLIBC_TUNABLES=... option tried. ++ testname4: ++ ++ ... ++ output(): ++ output(): ++ # Individual tunable output cases can be XFAILed, though note that ++ # this will have the effect of XFAILing the entire 'testname4' test ++ # in the final top-level tests.sum summary. ++ xfail_output(): ++ ++ # When multiple outputs (with specific tunable strings) are specified, ++ # these take priority over any active 'tunable_option' settings. ++ ++ # When a test is meant to be placed under 'xtests' (not run under ++ # "make check", but only when "make xtests" is used), the testcase name can be ++ # declared using 'xtest()': ++ ... ++ xtest(test-too-big1): ++ output: ++ ... ++ ++ # Do note that under current elf/Makefile organization, for such a xtest case, ++ # while the test execution is only run under 'make xtests', the associated ++ # DSOs are always built even under 'make check'. ++ ++On the description language used, an example description line string: ++ ++ a->b!->[cdef];c=>g=>h;{+c;%c;-c}->a ++ ++Each identifier represents a shared object module, currently sequences of ++letters/digits are allowed, case-sensitive. ++ ++All such shared objects have a constructor/destructor generated for them ++that emits its name followed by a '>' for constructors, and '<' followed by ++its name for destructors, e.g. if the name is 'obj1', then "obj1>" and " operator specifies a link time dependency, these can be chained for ++convenience (e.g. a->b->c->d). ++ ++The => operator creates a call-reference, e.g. for a=>b, an fn_a() function ++is created inside module 'a', which calls fn_b() in module 'b'. ++These module functions emit 'name()' output in nested form, ++e.g. a=>b emits 'a(b())' ++ ++For single character object names, square brackets [] in the description ++allows specifying multiple objects; e.g. a->[bcd]->e is equivalent to ++ a->b->e;a->c->e;a->d->e ++ ++The () parenthesis construct with space separated names is also allowed for ++specifying objects. For names with integer suffixes a range can also be used, ++e.g. (foo1 bar2-5), specifies DSOs foo1, bar2, bar2, bar3, bar4, bar5. ++ ++A {} construct specifies the main test program, and its link dependencies ++are also specified using ->. Inside {}, a few ;-separated constructs are ++allowed: ++ +a Loads module a using dlopen(RTLD_LAZY|RTLD_GLOBAL) ++ ^a Loads module a using dlopen(RTLD_LAZY) ++ %a Use dlsym() to load and call fn_a() ++ @a Calls fn_a() directly. ++ -a Unloads module a using dlclose() ++ ++The generated main program outputs '{' '}' with all output from above ++constructs in between. The other output before/after {} are the ordered ++constructor/destructor output. ++ ++If no {} construct is present, a default empty main program is linked ++against all objects which have no dependency linked to it. e.g. for ++'[ab]->c;d->e', the default main program is equivalent to '{}->[abd]' ++ ++Sometimes for very complex or large testcases, besides specifying a ++few explicit dependencies from main{}, the above default dependency ++behavior is still useful to automatically have, but is turned off ++upon specifying a single explicit {}->dso_name. ++In this case, add {}->* to explicitly add this generation behavior: ++ ++ # Main program links to 'foo', and all other objects which have no ++ # dependency linked to it. ++ {}->foo,{}->* ++ ++Note that '*' works not only on main{}, but can be used as the ++dependency target of any object. Note that it only works as a target, ++not a dependency source. ++ ++The '!' operator after object names turns on permutation of its ++dependencies, e.g. while a->[bcd] only generates one set of objects, ++with 'a.so' built with a link line of "b.so c.so d.so", for a!->[bcd] ++permutations of a's dependencies creates multiple testcases with ++different link line orders: "b.so c.so d.so", "c.so b.so d.so", ++"b.so d.so c.so", etc. Note that for a specified on ++the script command-line, multiple , , etc. ++tests will be generated (e.g. for a!->[bc]!->[de], eight tests with ++different link orders for a, b, and c will be generated) ++ ++It is possible to specify the ELF soname field for an object or the ++main program: ++ # DSO 'a' will be linked with the appropriate -Wl,-soname=x setting ++ a->b->c;soname(a)=x ++ # The the main program can also have a soname specified ++ soname({})=y ++ ++This can be used to test how ld.so behaves when objects and/or the ++main program have such a field set. ++ ++ ++Strings Output by Generated Testcase Programs ++ ++The text output produced by a generated testcase consists of three main ++parts: ++ 1. The constructors' output ++ 2. Output from the main program ++ 3. Destructors' output ++ ++To see by example, a simple test description "a->b->c" generates a testcase ++that when run, outputs: "c>b>a>{}' character, ++and the "c>b>a" part above is the full constructor output by all DSOs, the ++order indicating that DSO 'c', which does not depend on any other DSO, has ++its constructor run first, followed by 'b' and then 'a'. ++ ++Destructor output for each DSO is a '<' character followed by its name, ++reflecting its reverse nature of constructors. In the above example, the ++destructor output part is "g=>h;{+c;%c;-c}->a->h ++ ++This produces a testcase, that when executed outputs: ++ h>a>{+c[g>c>];%c();-c[h dependency as expected. ++Inside the main program, the "+c" action triggers a dlopen() of DSO 'c', ++causing another chain of constructors "g>c>" to be triggered. Here it is ++displayed inside [] brackets for each dlopen call. The same is done for "-c", ++a dlclose() of 'c'. ++ ++The "%c" output is due to calling to fn_c() inside DSO 'c', this comprises ++of two parts: the '%' character is printed by the caller, here it is the main ++program. The 'c' character is printed from inside fn_c(). The '%' character ++indicates that this is called by a dlsym() of "fn_c". A '@' character would ++mean a direct call (with a symbol reference). These can all be controlled ++by the main test program constructs documented earlier. ++ ++The output strings described here is the exact same form placed in ++test description files' "output: " line. ++""" ++ ++import sys ++import re ++import os ++import subprocess ++import argparse ++from collections import OrderedDict ++import itertools ++ ++# BUILD_GCC is only used under the --build option, ++# which builds the generated testcase, including DSOs using BUILD_GCC. ++# Mainly for testing purposes, especially debugging of this script, ++# and can be changed here to another toolchain path if needed. ++build_gcc = "gcc" ++ ++def get_parser(): ++ parser = argparse.ArgumentParser("") ++ parser.add_argument("description", ++ help="Description string of DSO dependency test to be " ++ "generated (see script source for documentation of " ++ "description language), either specified here as " ++ "command line argument, or by input file using " ++ "-f/--description-file option", ++ nargs="?", default="") ++ parser.add_argument("test_name", ++ help="Identifier for testcase being generated", ++ nargs="?", default="") ++ parser.add_argument("--objpfx", ++ help="Path to place generated files, defaults to " ++ "current directory if none specified", ++ nargs="?", default="./") ++ parser.add_argument("-m", "--output-makefile", ++ help="File to write Makefile fragment to, defaults to " ++ "stdout when option not present", ++ nargs="?", default="") ++ parser.add_argument("-f", "--description-file", ++ help="Input file containing testcase descriptions", ++ nargs="?", default="") ++ parser.add_argument("--build", help="After C testcase generated, build it " ++ "using gcc (for manual testing purposes)", ++ action="store_true") ++ parser.add_argument("--debug-output", ++ help="Prints some internal data " ++ "structures; used for debugging of this script", ++ action="store_true") ++ return parser ++ ++# Main script starts here. ++cmdlineargs = get_parser().parse_args() ++test_name = cmdlineargs.test_name ++description = cmdlineargs.description ++objpfx = cmdlineargs.objpfx ++description_file = cmdlineargs.description_file ++output_makefile = cmdlineargs.output_makefile ++makefile = "" ++default_tunable_options = [] ++ ++current_input_lineno = 0 ++def error(msg): ++ global current_input_lineno ++ print("Error: %s%s" % ((("Line %d, " % current_input_lineno) ++ if current_input_lineno != 0 else ""), ++ msg)) ++ exit(1) ++ ++if(test_name or description) and description_file: ++ error("both command-line testcase and input file specified") ++if test_name and not description: ++ error("command-line testcase name without description string") ++ ++# Main class type describing a testcase. ++class TestDescr: ++ def __init__(self): ++ self.objs = [] # list of all DSO objects ++ self.deps = OrderedDict() # map of DSO object -> list of dependencies ++ ++ # map of DSO object -> list of call refs ++ self.callrefs = OrderedDict() ++ ++ # map of DSO object -> list of permutations of dependencies ++ self.dep_permutations = OrderedDict() ++ ++ # map of DSO object -> SONAME of object (if one is specified) ++ self.soname_map = OrderedDict() ++ ++ # list of main program operations ++ self.main_program = [] ++ # set if default dependencies added to main ++ self.main_program_default_deps = True ++ ++ self.test_name = "" # name of testcase ++ self.expected_outputs = OrderedDict() # expected outputs of testcase ++ self.xfail = False # set if this is a XFAIL testcase ++ self.xtest = False # set if this is put under 'xtests' ++ ++ # Add 'object -> [object, object, ...]' relations to CURR_MAP ++ def __add_deps_internal(self, src_objs, dst_objs, curr_map): ++ for src in src_objs: ++ for dst in dst_objs: ++ if not src in curr_map: ++ curr_map[src] = [] ++ if not dst in curr_map[src]: ++ curr_map[src].append(dst) ++ def add_deps(self, src_objs, dst_objs): ++ self.__add_deps_internal(src_objs, dst_objs, self.deps) ++ def add_callrefs(self, src_objs, dst_objs): ++ self.__add_deps_internal(src_objs, dst_objs, self.callrefs) ++ ++# Process commands inside the {} construct. ++# Note that throughout this script, the main program object is represented ++# by the '#' string. ++def process_main_program(test_descr, mainprog_str): ++ if mainprog_str: ++ test_descr.main_program = mainprog_str.split(';') ++ for s in test_descr.main_program: ++ m = re.match(r"^([+\-%^@])([0-9a-zA-Z]+)$", s) ++ if not m: ++ error("'%s' is not recognized main program operation" % (s)) ++ opr = m.group(1) ++ obj = m.group(2) ++ if not obj in test_descr.objs: ++ test_descr.objs.append(obj) ++ if opr == '%' or opr == '@': ++ test_descr.add_callrefs(['#'], [obj]) ++ # We have a main program specified, turn this off ++ test_descr.main_program_default_deps = False ++ ++# For(a1 a2 b1-12) object set descriptions, expand into an object list ++def expand_object_set_string(descr_str): ++ obj_list = [] ++ descr_list = descr_str.split() ++ for descr in descr_list: ++ m = re.match(r"^([a-zA-Z][0-9a-zA-Z]*)(-[0-9]+)?$", descr) ++ if not m: ++ error("'%s' is not a valid object set description" % (descr)) ++ obj = m.group(1) ++ idx_end = m.group(2) ++ if not idx_end: ++ if not obj in obj_list: ++ obj_list.append(obj) ++ else: ++ idx_end = int(idx_end[1:]) ++ m = re.match(r"^([0-9a-zA-Z][a-zA-Z]*)([0-9]+)$", obj) ++ if not m: ++ error("object description '%s' is malformed" % (obj)) ++ obj_name = m.group(1) ++ idx_start = int(m.group (2)) ++ if idx_start > idx_end: ++ error("index range %s-%s invalid" % (idx_start, idx_end)) ++ for i in range(idx_start, idx_end + 1): ++ o = obj_name + str(i) ++ if not o in obj_list: ++ obj_list.append(o) ++ return obj_list ++ ++# Lexer for tokens ++tokenspec = [ ("SONAME", r"soname\(([0-9a-zA-Z{}]+)\)=([0-9a-zA-Z]+)"), ++ ("OBJ", r"([0-9a-zA-Z]+)"), ++ ("DEP", r"->"), ++ ("CALLREF", r"=>"), ++ ("OBJSET", r"\[([0-9a-zA-Z]+)\]"), ++ ("OBJSET2", r"\(([0-9a-zA-Z \-]+)\)"), ++ ("OBJSET3", r"\*"), ++ ("PROG", r"{([0-9a-zA-Z;+^\-%@]*)}"), ++ ("PERMUTE", r"!"), ++ ("SEMICOL", r";"), ++ ("ERROR", r".") ] ++tok_re = '|'.join('(?P<%s>%s)' % pair for pair in tokenspec) ++ ++# Main line parser of description language ++def parse_description_string(t, descr_str): ++ # State used when parsing dependencies ++ curr_objs = [] ++ in_dep = False ++ in_callref = False ++ def clear_dep_state(): ++ nonlocal in_dep, in_callref ++ in_dep = in_callref = False ++ ++ for m in re.finditer(tok_re, descr_str): ++ kind = m.lastgroup ++ value = m.group() ++ if kind == "SONAME": ++ s = re.match(r"soname\(([0-9a-zA-Z{}]+)\)=([0-9a-zA-Z]+)", value) ++ obj = s.group(1) ++ val = s.group(2) ++ if obj == "{}": ++ if '#' in t.soname_map: ++ error("soname of main program already set") ++ # Adjust to internal name ++ obj = '#' ++ else: ++ if re.match(r"[{}]", obj): ++ error("invalid object name '%s'" % (obj)) ++ if not obj in t.objs: ++ error("'%s' is not name of already defined object" % (obj)) ++ if obj in t.soname_map: ++ error("'%s' already has soname of '%s' set" ++ % (obj, t.soname_map[obj])) ++ t.soname_map[obj] = val ++ ++ elif kind == "OBJ": ++ if in_dep: ++ t.add_deps(curr_objs, [value]) ++ elif in_callref: ++ t.add_callrefs(curr_objs, [value]) ++ clear_dep_state() ++ curr_objs = [value] ++ if not value in t.objs: ++ t.objs.append(value) ++ ++ elif kind == "OBJSET": ++ objset = value[1:len(value)-1] ++ if in_dep: ++ t.add_deps(curr_objs, list (objset)) ++ elif in_callref: ++ t.add_callrefs(curr_objs, list (objset)) ++ clear_dep_state() ++ curr_objs = list(objset) ++ for o in list(objset): ++ if not o in t.objs: ++ t.objs.append(o) ++ ++ elif kind == "OBJSET2": ++ descr_str = value[1:len(value)-1] ++ descr_str.strip() ++ objs = expand_object_set_string(descr_str) ++ if not objs: ++ error("empty object set '%s'" % (value)) ++ if in_dep: ++ t.add_deps(curr_objs, objs) ++ elif in_callref: ++ t.add_callrefs(curr_objs, objs) ++ clear_dep_state() ++ curr_objs = objs ++ for o in objs: ++ if not o in t.objs: ++ t.objs.append(o) ++ ++ elif kind == "OBJSET3": ++ if in_dep: ++ t.add_deps(curr_objs, ['*']) ++ elif in_callref: ++ t.add_callrefs(curr_objs, ['*']) ++ else: ++ error("non-dependence target set '*' can only be used " ++ "as target of ->/=> operations") ++ clear_dep_state() ++ curr_objs = ['*'] ++ ++ elif kind == "PERMUTE": ++ if in_dep or in_callref: ++ error("syntax error, permute operation invalid here") ++ if not curr_objs: ++ error("syntax error, no objects to permute here") ++ ++ for obj in curr_objs: ++ if not obj in t.dep_permutations: ++ # Signal this object has permuted dependencies ++ t.dep_permutations[obj] = [] ++ ++ elif kind == "PROG": ++ if t.main_program: ++ error("cannot have more than one main program") ++ if in_dep: ++ error("objects cannot have dependency on main program") ++ if in_callref: ++ # TODO: A DSO can resolve to a symbol in the main binary, ++ # which we syntactically allow here, but haven't yet ++ # implemented. ++ t.add_callrefs(curr_objs, ["#"]) ++ process_main_program(t, value[1:len(value)-1]) ++ clear_dep_state() ++ curr_objs = ["#"] ++ ++ elif kind == "DEP": ++ if in_dep or in_callref: ++ error("syntax error, multiple contiguous ->,=> operations") ++ if '*' in curr_objs: ++ error("non-dependence target set '*' can only be used " ++ "as target of ->/=> operations") ++ in_dep = True ++ ++ elif kind == "CALLREF": ++ if in_dep or in_callref: ++ error("syntax error, multiple contiguous ->,=> operations") ++ if '*' in curr_objs: ++ error("non-dependence target set '*' can only be used " ++ "as target of ->/=> operations") ++ in_callref = True ++ ++ elif kind == "SEMICOL": ++ curr_objs = [] ++ clear_dep_state() ++ ++ else: ++ error("unknown token '%s'" % (value)) ++ return t ++ ++# Main routine to process each testcase description ++def process_testcase(t): ++ global objpfx ++ assert t.test_name ++ ++ base_test_name = t.test_name ++ test_subdir = base_test_name + "-dir" ++ testpfx = objpfx + test_subdir + "/" ++ ++ if not os.path.exists(testpfx): ++ os.mkdir(testpfx) ++ ++ def find_objs_not_depended_on(t): ++ objs_not_depended_on = [] ++ for obj in t.objs: ++ skip = False ++ for r in t.deps.items(): ++ if obj in r[1]: ++ skip = True ++ break ++ if not skip: ++ objs_not_depended_on.append(obj) ++ return objs_not_depended_on ++ ++ non_dep_tgt_objs = find_objs_not_depended_on(t) ++ for obj in t.objs: ++ if obj in t.deps: ++ deps = t.deps[obj] ++ if '*' in deps: ++ t.deps[obj].remove('*') ++ t.add_deps([obj], non_dep_tgt_objs) ++ if obj in t.callrefs: ++ deps = t.callrefs[obj] ++ if '*' in deps: ++ t.deps[obj].remove('*') ++ t.add_callrefs([obj], non_dep_tgt_objs) ++ if "#" in t.deps: ++ deps = t.deps["#"] ++ if '*' in deps: ++ t.deps["#"].remove('*') ++ t.add_deps(["#"], non_dep_tgt_objs) ++ ++ # If no main program was specified in dependency description, make a ++ # default main program with deps pointing to all DSOs which are not ++ # depended by another DSO. ++ if t.main_program_default_deps: ++ main_deps = non_dep_tgt_objs ++ if not main_deps: ++ error("no objects for default main program to point " ++ "dependency to(all objects strongly connected?)") ++ t.add_deps(["#"], main_deps) ++ ++ # Some debug output ++ if cmdlineargs.debug_output: ++ print("Testcase: %s" % (t.test_name)) ++ print("All objects: %s" % (t.objs)) ++ print("--- Static link dependencies ---") ++ for r in t.deps.items(): ++ print("%s -> %s" % (r[0], r[1])) ++ print("--- Objects whose dependencies are to be permuted ---") ++ for r in t.dep_permutations.items(): ++ print("%s" % (r[0])) ++ print("--- Call reference dependencies ---") ++ for r in t.callrefs.items(): ++ print("%s => %s" % (r[0], r[1])) ++ print("--- main program ---") ++ print(t.main_program) ++ ++ # Main testcase generation routine, does Makefile fragment generation, ++ # testcase source generation, and if --build specified builds testcase. ++ def generate_testcase(test_descr, test_suffix): ++ ++ test_name = test_descr.test_name + test_suffix ++ ++ # Print out needed Makefile fragments for use in glibc/elf/Makefile. ++ module_names = "" ++ for o in test_descr.objs: ++ module_names += " " + test_subdir + "/" + test_name + "-" + o ++ makefile.write("modules-names +=%s\n" % (module_names)) ++ ++ # Depth-first traversal, executing FN(OBJ) in post-order ++ def dfs(t, fn): ++ def dfs_rec(obj, fn, obj_visited): ++ if obj in obj_visited: ++ return ++ obj_visited[obj] = True ++ if obj in t.deps: ++ for dep in t.deps[obj]: ++ dfs_rec(dep, fn, obj_visited) ++ fn(obj) ++ ++ obj_visited = {} ++ for obj in t.objs: ++ dfs_rec(obj, fn, obj_visited) ++ ++ # Generate link dependencies for all DSOs, done in a DFS fashion. ++ # Usually this doesn't need to be this complex, just listing the direct ++ # dependencies is enough. However to support creating circular ++ # dependency situations, traversing it by DFS and tracking processing ++ # status is the natural way to do it. ++ obj_processed = {} ++ fake_created = {} ++ def gen_link_deps(obj): ++ if obj in test_descr.deps: ++ dso = test_subdir + "/" + test_name + "-" + obj + ".so" ++ dependencies = "" ++ for dep in test_descr.deps[obj]: ++ if dep in obj_processed: ++ depstr = (" $(objpfx)" + test_subdir + "/" ++ + test_name + "-" + dep + ".so") ++ else: ++ # A circular dependency is satisfied by making a ++ # fake DSO tagged with the correct SONAME ++ depstr = (" $(objpfx)" + test_subdir + "/" ++ + test_name + "-" + dep + ".FAKE.so") ++ # Create empty C file and Makefile fragments for fake ++ # object. This only needs to be done at most once for ++ # an object name. ++ if not dep in fake_created: ++ f = open(testpfx + test_name + "-" + dep ++ + ".FAKE.c", "w") ++ f.write(" \n") ++ f.close() ++ # Generate rule to create fake object ++ makefile.write \ ++ ("LDFLAGS-%s = -Wl,--no-as-needed " ++ "-Wl,-soname=%s\n" ++ % (test_name + "-" + dep + ".FAKE.so", ++ ("$(objpfx)" + test_subdir + "/" ++ + test_name + "-" + dep + ".so"))) ++ makefile.write \ ++ ("modules-names += %s\n" ++ % (test_subdir + "/" ++ + test_name + "-" + dep + ".FAKE")) ++ fake_created[dep] = True ++ dependencies += depstr ++ makefile.write("$(objpfx)%s:%s\n" % (dso, dependencies)) ++ # Mark obj as processed ++ obj_processed[obj] = True ++ ++ dfs(test_descr, gen_link_deps) ++ ++ # Print LDFLAGS-* and *-no-z-defs ++ for o in test_descr.objs: ++ dso = test_name + "-" + o + ".so" ++ ldflags = "-Wl,--no-as-needed" ++ if o in test_descr.soname_map: ++ soname = ("$(objpfx)" + test_subdir + "/" ++ + test_name + "-" ++ + test_descr.soname_map[o] + ".so") ++ ldflags += (" -Wl,-soname=" + soname) ++ makefile.write("LDFLAGS-%s = %s\n" % (dso, ldflags)) ++ if o in test_descr.callrefs: ++ makefile.write("%s-no-z-defs = yes\n" % (dso)) ++ ++ # Print dependencies for main test program. ++ depstr = "" ++ if '#' in test_descr.deps: ++ for o in test_descr.deps['#']: ++ depstr += (" $(objpfx)" + test_subdir + "/" ++ + test_name + "-" + o + ".so") ++ makefile.write("$(objpfx)%s/%s:%s\n" % (test_subdir, test_name, depstr)) ++ ldflags = "-Wl,--no-as-needed" ++ if '#' in test_descr.soname_map: ++ soname = ("$(objpfx)" + test_subdir + "/" ++ + test_name + "-" ++ + test_descr.soname_map['#'] + ".so") ++ ldflags += (" -Wl,-soname=" + soname) ++ makefile.write("LDFLAGS-%s = %s\n" % (test_name, ldflags)) ++ ++ not_depended_objs = find_objs_not_depended_on(test_descr) ++ if not_depended_objs: ++ depstr = "" ++ for dep in not_depended_objs: ++ depstr += (" $(objpfx)" + test_subdir + "/" ++ + test_name + "-" + dep + ".so") ++ makefile.write("$(objpfx)%s.out:%s\n" % (base_test_name, depstr)) ++ ++ # Add main executable to test-srcs ++ makefile.write("test-srcs += %s/%s\n" % (test_subdir, test_name)) ++ # Add dependency on main executable of test ++ makefile.write("$(objpfx)%s.out: $(objpfx)%s/%s\n" ++ % (base_test_name, test_subdir, test_name)) ++ ++ for r in test_descr.expected_outputs.items(): ++ tunable_options = [] ++ specific_tunable = r[0] ++ xfail = r[1][1] ++ if specific_tunable != "": ++ tunable_options = [specific_tunable] ++ else: ++ tunable_options = default_tunable_options ++ if not tunable_options: ++ tunable_options = [""] ++ ++ for tunable in tunable_options: ++ tunable_env = "" ++ tunable_sfx = "" ++ exp_tunable_sfx = "" ++ if tunable: ++ tunable_env = "GLIBC_TUNABLES=%s " % tunable ++ tunable_sfx = "-" + tunable.replace("=","_") ++ if specific_tunable: ++ tunable_sfx = "-" + specific_tunable.replace("=","_") ++ exp_tunable_sfx = tunable_sfx ++ tunable_descr = ("(%s)" % tunable_env.strip() ++ if tunable_env else "") ++ # Write out fragment of shell script for this single test. ++ test_descr.sh.write \ ++ ("%s${test_wrapper_env} ${run_program_env} \\\n" ++ "${common_objpfx}support/test-run-command \\\n" ++ "${common_objpfx}elf/ld.so \\\n" ++ "--library-path ${common_objpfx}elf/%s:" ++ "${common_objpfx}elf:${common_objpfx}.:" ++ "${common_objpfx}dlfcn \\\n" ++ "${common_objpfx}elf/%s/%s > \\\n" ++ " ${common_objpfx}elf/%s/%s%s.output\n" ++ % (tunable_env ,test_subdir, ++ test_subdir, test_name, test_subdir, test_name, ++ tunable_sfx)) ++ # Generate a run of each test and compare with expected out ++ test_descr.sh.write \ ++ ("if [ $? -ne 0 ]; then\n" ++ " echo '%sFAIL: %s%s execution test'\n" ++ " something_failed=true\n" ++ "else\n" ++ " diff -wu ${common_objpfx}elf/%s/%s%s.output \\\n" ++ " ${common_objpfx}elf/%s/%s%s.exp\n" ++ " if [ $? -ne 0 ]; then\n" ++ " echo '%sFAIL: %s%s expected output comparison'\n" ++ " something_failed=true\n" ++ " fi\n" ++ "fi\n" ++ % (("X" if xfail else ""), test_name, tunable_descr, ++ test_subdir, test_name, tunable_sfx, ++ test_subdir, base_test_name, exp_tunable_sfx, ++ ("X" if xfail else ""), test_name, tunable_descr)) ++ ++ # Generate C files according to dependency and calling relations from ++ # description string. ++ for obj in test_descr.objs: ++ src_name = test_name + "-" + obj + ".c" ++ f = open(testpfx + src_name, "w") ++ if obj in test_descr.callrefs: ++ called_objs = test_descr.callrefs[obj] ++ for callee in called_objs: ++ f.write("extern void fn_%s (void);\n" % (callee)) ++ if len(obj) == 1: ++ f.write("extern int putchar(int);\n") ++ f.write("static void __attribute__((constructor)) " + ++ "init(void){putchar('%s');putchar('>');}\n" % (obj)) ++ f.write("static void __attribute__((destructor)) " + ++ "fini(void){putchar('<');putchar('%s');}\n" % (obj)) ++ else: ++ f.write('extern int printf(const char *, ...);\n') ++ f.write('static void __attribute__((constructor)) ' + ++ 'init(void){printf("%s>");}\n' % (obj)) ++ f.write('static void __attribute__((destructor)) ' + ++ 'fini(void){printf("<%s");}\n' % (obj)) ++ if obj in test_descr.callrefs: ++ called_objs = test_descr.callrefs[obj] ++ if len(obj) != 1: ++ f.write("extern int putchar(int);\n") ++ f.write("void fn_%s (void) {\n" % (obj)) ++ if len(obj) == 1: ++ f.write(" putchar ('%s');\n" % (obj)); ++ f.write(" putchar ('(');\n"); ++ else: ++ f.write(' printf ("%s(");\n' % (obj)); ++ for callee in called_objs: ++ f.write(" fn_%s ();\n" % (callee)) ++ f.write(" putchar (')');\n"); ++ f.write("}\n") ++ else: ++ for callref in test_descr.callrefs.items(): ++ if obj in callref[1]: ++ if len(obj) == 1: ++ # We need to declare printf here in this case. ++ f.write('extern int printf(const char *, ...);\n') ++ f.write("void fn_%s (void) {\n" % (obj)) ++ f.write(' printf ("%s()");\n' % (obj)) ++ f.write("}\n") ++ break ++ f.close() ++ ++ # Open C file for writing main program ++ f = open(testpfx + test_name + ".c", "w") ++ ++ # if there are some operations in main(), it means we need -ldl ++ f.write("#include \n") ++ f.write("#include \n") ++ f.write("#include \n") ++ for s in test_descr.main_program: ++ if s[0] == '@': ++ f.write("extern void fn_%s (void);\n" % (s[1:])); ++ f.write("int main (void) {\n") ++ f.write(" putchar('{');\n") ++ ++ # Helper routine for generating sanity checking code. ++ def put_fail_check(fail_cond, action_desc): ++ f.write(' if (%s) { printf ("\\n%s failed: %%s\\n", ' ++ 'dlerror()); exit (1);}\n' % (fail_cond, action_desc)) ++ i = 0 ++ while i < len(test_descr.main_program): ++ s = test_descr.main_program[i] ++ obj = s[1:] ++ dso = test_name + "-" + obj ++ if s[0] == '+' or s[0] == '^': ++ if s[0] == '+': ++ dlopen_flags = "RTLD_LAZY|RTLD_GLOBAL" ++ f.write(" putchar('+');\n"); ++ else: ++ dlopen_flags = "RTLD_LAZY" ++ f.write(" putchar(':');\n"); ++ if len(obj) == 1: ++ f.write(" putchar('%s');\n" % (obj)); ++ else: ++ f.write(' printf("%s");\n' % (obj)); ++ f.write(" putchar('[');\n"); ++ f.write(' void *%s = dlopen ("%s.so", %s);\n' ++ % (obj, dso, dlopen_flags)) ++ put_fail_check("!%s" % (obj), ++ "%s.so dlopen" % (dso)) ++ f.write(" putchar(']');\n"); ++ elif s[0] == '-': ++ f.write(" putchar('-');\n"); ++ if len(obj) == 1: ++ f.write(" putchar('%s');\n" % (obj)); ++ else: ++ f.write(' printf("%s");\n' % (obj)); ++ f.write(" putchar('[');\n"); ++ put_fail_check("dlclose (%s) != 0" % (obj), ++ "%s.so dlclose" % (dso)) ++ f.write(" putchar(']');\n"); ++ elif s[0] == '%': ++ f.write(" putchar('%');\n"); ++ f.write(' void (*fn_%s)(void) = dlsym (%s, "fn_%s");\n' ++ % (obj, obj, obj)) ++ put_fail_check("!fn_%s" % (obj), ++ "dlsym(fn_%s) from %s.so" % (obj, dso)) ++ f.write(" fn_%s ();\n" % (obj)) ++ elif s[0] == '@': ++ f.write(" putchar('@');\n"); ++ f.write(" fn_%s ();\n" % (obj)) ++ f.write(" putchar(';');\n"); ++ i += 1 ++ f.write(" putchar('}');\n") ++ f.write(" return 0;\n") ++ f.write("}\n") ++ f.close() ++ ++ # --build option processing: build generated sources using 'build_gcc' ++ if cmdlineargs.build: ++ # Helper routine to run a shell command, for running GCC below ++ def run_cmd(args): ++ cmd = str.join(' ', args) ++ if cmdlineargs.debug_output: ++ print(cmd) ++ p = subprocess.Popen(args) ++ p.wait() ++ if p.returncode != 0: ++ error("error running command: %s" % (cmd)) ++ ++ # Compile individual .os files ++ for obj in test_descr.objs: ++ src_name = test_name + "-" + obj + ".c" ++ obj_name = test_name + "-" + obj + ".os" ++ run_cmd([build_gcc, "-c", "-fPIC", testpfx + src_name, ++ "-o", testpfx + obj_name]) ++ ++ obj_processed = {} ++ fake_created = {} ++ # Function to create -.so ++ def build_dso(obj): ++ obj_name = test_name + "-" + obj + ".os" ++ dso_name = test_name + "-" + obj + ".so" ++ deps = [] ++ if obj in test_descr.deps: ++ for dep in test_descr.deps[obj]: ++ if dep in obj_processed: ++ deps.append(dep) ++ else: ++ deps.append(dep + ".FAKE") ++ if not dep in fake_created: ++ base_name = testpfx + test_name + "-" + dep ++ cmd = [build_gcc, "-Wl,--no-as-needed", ++ ("-Wl,-soname=" + base_name + ".so"), ++ "-shared", base_name + ".FAKE.c", ++ "-o", base_name + ".FAKE.so"] ++ run_cmd(cmd) ++ fake_created[dep] = True ++ dso_deps = map(lambda d: testpfx + test_name + "-" + d + ".so", ++ deps) ++ cmd = [build_gcc, "-shared", "-o", testpfx + dso_name, ++ testpfx + obj_name, "-Wl,--no-as-needed"] ++ if obj in test_descr.soname_map: ++ soname = ("-Wl,-soname=" + testpfx + test_name + "-" ++ + test_descr.soname_map[obj] + ".so") ++ cmd += [soname] ++ cmd += list(dso_deps) ++ run_cmd(cmd) ++ obj_processed[obj] = True ++ ++ # Build all DSOs, this needs to be in topological dependency order, ++ # or link will fail ++ dfs(test_descr, build_dso) ++ ++ # Build main program ++ deps = [] ++ if '#' in test_descr.deps: ++ deps = test_descr.deps['#'] ++ main_deps = map(lambda d: testpfx + test_name + "-" + d + ".so", ++ deps) ++ cmd = [build_gcc, "-Wl,--no-as-needed", "-o", testpfx + test_name, ++ testpfx + test_name + ".c", "-L%s" % (os.getcwd()), ++ "-Wl,-rpath-link=%s" % (os.getcwd())] ++ if '#' in test_descr.soname_map: ++ soname = ("-Wl,-soname=" + testpfx + test_name + "-" ++ + test_descr.soname_map['#'] + ".so") ++ cmd += [soname] ++ cmd += list(main_deps) ++ run_cmd(cmd) ++ ++ # Check if we need to enumerate permutations of dependencies ++ need_permutation_processing = False ++ if t.dep_permutations: ++ # Adjust dep_permutations into map of object -> dependency permutations ++ for r in t.dep_permutations.items(): ++ obj = r[0] ++ if obj in t.deps and len(t.deps[obj]) > 1: ++ deps = t.deps[obj] ++ t.dep_permutations[obj] = list(itertools.permutations (deps)) ++ need_permutation_processing = True ++ ++ def enum_permutations(t, perm_list): ++ test_subindex = 1 ++ curr_perms = [] ++ def enum_permutations_rec(t, perm_list): ++ nonlocal test_subindex, curr_perms ++ if len(perm_list) >= 1: ++ curr = perm_list[0] ++ obj = curr[0] ++ perms = curr[1] ++ if not perms: ++ # This may be an empty list if no multiple dependencies to ++ # permute were found, skip to next in this case ++ enum_permutations_rec(t, perm_list[1:]) ++ else: ++ for deps in perms: ++ t.deps[obj] = deps ++ permstr = "" if obj == "#" else obj + "_" ++ permstr += str.join('', deps) ++ curr_perms.append(permstr) ++ enum_permutations_rec(t, perm_list[1:]) ++ curr_perms = curr_perms[0:len(curr_perms)-1] ++ else: ++ # t.deps is now instantiated with one dependency order ++ # permutation(across all objects that have multiple ++ # permutations), now process a testcase ++ generate_testcase(t, ("_" + str (test_subindex) ++ + "-" + str.join('-', curr_perms))) ++ test_subindex += 1 ++ enum_permutations_rec(t, perm_list) ++ ++ # Create *.exp files with expected outputs ++ for r in t.expected_outputs.items(): ++ sfx = "" ++ if r[0] != "": ++ sfx = "-" + r[0].replace("=","_") ++ f = open(testpfx + t.test_name + sfx + ".exp", "w") ++ (output, xfail) = r[1] ++ f.write('%s' % output) ++ f.close() ++ ++ # Create header part of top-level testcase shell script, to wrap execution ++ # and output comparison together. ++ t.sh = open(testpfx + t.test_name + ".sh", "w") ++ t.sh.write("#!/bin/sh\n") ++ t.sh.write("# Test driver for %s, generated by " ++ "dso-ordering-test.py\n" % (t.test_name)) ++ t.sh.write("common_objpfx=$1\n") ++ t.sh.write("test_wrapper_env=$2\n") ++ t.sh.write("run_program_env=$3\n") ++ t.sh.write("something_failed=false\n") ++ ++ # Starting part of Makefile fragment ++ makefile.write("ifeq (yes,$(build-shared))\n") ++ ++ if need_permutation_processing: ++ enum_permutations(t, list (t.dep_permutations.items())) ++ else: ++ # We have no permutations to enumerate, just process testcase normally ++ generate_testcase(t, "") ++ ++ # If testcase is XFAIL, indicate so ++ if t.xfail: ++ makefile.write("test-xfail-%s = yes\n" % t.test_name) ++ ++ # Output end part of Makefile fragment ++ expected_output_files = "" ++ for r in t.expected_outputs.items(): ++ sfx = "" ++ if r[0] != "": ++ sfx = "-" + r[0].replace("=","_") ++ expected_output_files += " $(objpfx)%s/%s%s.exp" % (test_subdir, ++ t.test_name, sfx) ++ makefile.write \ ++ ("$(objpfx)%s.out: $(objpfx)%s/%s.sh%s " ++ "$(common-objpfx)support/test-run-command\n" ++ % (t.test_name, test_subdir, t.test_name, ++ expected_output_files)) ++ makefile.write("\t$(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' " ++ "'$(run-program-env)' > $@; $(evaluate-test)\n") ++ makefile.write("ifeq ($(run-built-tests),yes)\n") ++ if t.xtest: ++ makefile.write("xtests-special += $(objpfx)%s.out\n" % (t.test_name)) ++ else: ++ makefile.write("tests-special += $(objpfx)%s.out\n" % (t.test_name)) ++ makefile.write("endif\n") ++ makefile.write("endif\n") ++ ++ # Write ending part of shell script generation ++ t.sh.write("if $something_failed; then\n" ++ " exit 1\n" ++ "else\n" ++ " echo '%sPASS: all tests for %s succeeded'\n" ++ " exit 0\n" ++ "fi\n" % (("X" if t.xfail else ""), ++ t.test_name)) ++ t.sh.close() ++ ++# Decription file parsing ++def parse_description_file(filename): ++ global default_tunable_options ++ global current_input_lineno ++ f = open(filename) ++ if not f: ++ error("cannot open description file %s" % (filename)) ++ descrfile_lines = f.readlines() ++ t = None ++ for line in descrfile_lines: ++ p = re.compile(r"#.*$") ++ line = p.sub("", line) # Filter out comments ++ line = line.strip() # Remove excess whitespace ++ current_input_lineno += 1 ++ ++ m = re.match(r"^tunable_option:\s*(.*)$", line) ++ if m: ++ if m.group(1) == "": ++ error("tunable option cannot be empty") ++ default_tunable_options.append(m.group (1)) ++ continue ++ ++ m = re.match(r"^clear_tunables$", line) ++ if m: ++ default_tunable_options = [] ++ continue ++ ++ m = re.match(r"^([^:]+):\s*(.*)$", line) ++ if m: ++ lhs = m.group(1) ++ o = re.match(r"^output(.*)$", lhs) ++ xfail = False ++ if not o: ++ o = re.match(r"^xfail_output(.*)$", lhs) ++ if o: ++ xfail = True; ++ if o: ++ if not t: ++ error("output specification without testcase description") ++ tsstr = "" ++ if o.group(1): ++ ts = re.match(r"^\(([a-zA-Z0-9_.=]*)\)$", o.group (1)) ++ if not ts: ++ error("tunable option malformed '%s'" % o.group(1)) ++ tsstr = ts.group(1) ++ t.expected_outputs[tsstr] = (m.group(2), xfail) ++ # Any tunable option XFAILed means entire testcase ++ # is XFAIL/XPASS ++ t.xfail |= xfail ++ else: ++ if t: ++ # Starting a new test description, end and process ++ # current one. ++ process_testcase(t) ++ t = TestDescr() ++ x = re.match(r"^xtest\((.*)\)$", lhs) ++ if x: ++ t.xtest = True ++ t.test_name = x.group(1) ++ else: ++ t.test_name = lhs ++ descr_string = m.group(2) ++ parse_description_string(t, descr_string) ++ continue ++ else: ++ if line: ++ if not t: ++ error("no active testcase description") ++ parse_description_string(t, line) ++ # Process last completed test description ++ if t: ++ process_testcase(t) ++ ++# Setup Makefile output to file or stdout as selected ++if output_makefile: ++ output_makefile_dir = os.path.dirname(output_makefile) ++ if output_makefile_dir: ++ os.makedirs(output_makefile_dir, exist_ok = True) ++ makefile = open(output_makefile, "w") ++else: ++ makefile = open(sys.stdout.fileno (), "w") ++ ++# Finally, the main top-level calling of above parsing routines. ++if description_file: ++ parse_description_file(description_file) ++else: ++ t = TestDescr() ++ t.test_name = test_name ++ parse_description_string(t, description) ++ process_testcase(t) ++ ++# Close Makefile fragment output ++makefile.close() +diff --git a/support/Depend b/support/Depend +new file mode 100644 +index 0000000000000000..7e7d5dc67c13e669 +--- /dev/null ++++ b/support/Depend +@@ -0,0 +1 @@ ++elf +diff --git a/support/Makefile b/support/Makefile +index 2a0731796fdb3f2d..75bad6715ac3d08c 100644 +--- a/support/Makefile ++++ b/support/Makefile +@@ -254,10 +254,16 @@ others-noinstall += shell-container echo-container true-container + others += $(LINKS_DSO_PROGRAM) + others-noinstall += $(LINKS_DSO_PROGRAM) + ++others += test-run-command ++others-static += test-run-command ++others-noinstall += test-run-command ++LDLIBS-test-run-command = $(libsupport) ++ + $(objpfx)test-container : $(libsupport) + $(objpfx)shell-container : $(libsupport) + $(objpfx)echo-container : $(libsupport) + $(objpfx)true-container : $(libsupport) ++$(objpfx)test-run-command : $(libsupport) $(common-objpfx)elf/static-stubs.o + + tests = \ + README-testing \ +diff --git a/support/support_test_main.c b/support/support_test_main.c +index 07e3cdd173cecfc0..66a754b84fbb79ad 100644 +--- a/support/support_test_main.c ++++ b/support/support_test_main.c +@@ -228,6 +228,18 @@ run_test_function (int argc, char **argv, const struct test_config *config) + while (wait_for_debugger) + usleep (1000); + ++ if (config->run_command_mode) ++ { ++ /* In run-command-mode, the child process executes the command line ++ arguments as a new program. */ ++ char **argv_ = xmalloc (sizeof (char *) * argc); ++ memcpy (argv_, &argv[1], sizeof (char *) * (argc - 1)); ++ argv_[argc - 1] = NULL; ++ execv (argv_[0], argv_); ++ printf ("error: should not return here\n"); ++ exit (1); ++ } ++ + if (config->test_function != NULL) + return config->test_function (); + else if (config->test_function_argv != NULL) +diff --git a/support/test-driver.c b/support/test-driver.c +index b0bea46deeb41b3b..1552f62c9b5d0f7b 100644 +--- a/support/test-driver.c ++++ b/support/test-driver.c +@@ -116,7 +116,9 @@ main (int argc, char **argv) + #if defined (TEST_FUNCTION) && defined (TEST_FUNCTON_ARGV) + # error TEST_FUNCTION and TEST_FUNCTION_ARGV cannot be defined at the same time + #endif +-#if defined (TEST_FUNCTION) ++#ifdef RUN_COMMAND_MODE ++ test_config.run_command_mode = 1; ++#elif defined (TEST_FUNCTION) + test_config.test_function = TEST_FUNCTION; + #elif defined (TEST_FUNCTION_ARGV) + test_config.test_function_argv = TEST_FUNCTION_ARGV; +diff --git a/support/test-driver.h b/support/test-driver.h +index 8d4f38275d219de0..b44c0ff03326fca4 100644 +--- a/support/test-driver.h ++++ b/support/test-driver.h +@@ -36,6 +36,7 @@ struct test_config + int expected_signal; /* If non-zero, expect termination by signal. */ + char no_mallopt; /* Boolean flag to disable mallopt. */ + char no_setvbuf; /* Boolean flag to disable setvbuf. */ ++ char run_command_mode; /* Boolean flag to indicate run-command-mode. */ + const char *optstring; /* Short command line options. */ + }; + +diff --git a/support/test-run-command.c b/support/test-run-command.c +new file mode 100644 +index 0000000000000000..61560d7bfb1686a8 +--- /dev/null ++++ b/support/test-run-command.c +@@ -0,0 +1,22 @@ ++/* Main program for test-run-command support utility. ++ 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 ++ . */ ++ ++/* This is basically a configuration of test-driver.c into a general ++ command-line program runner. */ ++#define RUN_COMMAND_MODE ++#include diff --git a/glibc-rh2032647-2.patch b/glibc-rh2032647-2.patch new file mode 100644 index 0000000..4ac1d1a --- /dev/null +++ b/glibc-rh2032647-2.patch @@ -0,0 +1,585 @@ +commit 15a0c5730d1d5aeb95f50c9ec7470640084feae8 +Author: Chung-Lin Tang +Date: Thu Oct 21 21:41:22 2021 +0800 + + elf: Fix slow DSO sorting behavior in dynamic loader (BZ #17645) + + This second patch contains the actual implementation of a new sorting algorithm + for shared objects in the dynamic loader, which solves the slow behavior that + the current "old" algorithm falls into when the DSO set contains circular + dependencies. + + The new algorithm implemented here is simply depth-first search (DFS) to obtain + the Reverse-Post Order (RPO) sequence, a topological sort. A new l_visited:1 + bitfield is added to struct link_map to more elegantly facilitate such a search. + + The DFS algorithm is applied to the input maps[nmap-1] backwards towards + maps[0]. This has the effect of a more "shallow" recursion depth in general + since the input is in BFS. Also, when combined with the natural order of + processing l_initfini[] at each node, this creates a resulting output sorting + closer to the intuitive "left-to-right" order in most cases. + + Another notable implementation adjustment related to this _dl_sort_maps change + is the removing of two char arrays 'used' and 'done' in _dl_close_worker to + represent two per-map attributes. This has been changed to simply use two new + bit-fields l_map_used:1, l_map_done:1 added to struct link_map. This also allows + discarding the clunky 'used' array sorting that _dl_sort_maps had to sometimes + do along the way. + + Tunable support for switching between different sorting algorithms at runtime is + also added. A new tunable 'glibc.rtld.dynamic_sort' with current valid values 1 + (old algorithm) and 2 (new DFS algorithm) has been added. At time of commit + of this patch, the default setting is 1 (old algorithm). + + Signed-off-by: Chung-Lin Tang + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-close.c b/elf/dl-close.c +index cd7b9c9fe83a1a44..f6fbf9de7d78555b 100644 +--- a/elf/dl-close.c ++++ b/elf/dl-close.c +@@ -167,8 +167,6 @@ _dl_close_worker (struct link_map *map, bool force) + + bool any_tls = false; + const unsigned int nloaded = ns->_ns_nloaded; +- char used[nloaded]; +- char done[nloaded]; + struct link_map *maps[nloaded]; + + /* Run over the list and assign indexes to the link maps and enter +@@ -176,24 +174,21 @@ _dl_close_worker (struct link_map *map, bool force) + int idx = 0; + for (struct link_map *l = ns->_ns_loaded; l != NULL; l = l->l_next) + { ++ l->l_map_used = 0; ++ l->l_map_done = 0; + l->l_idx = idx; + maps[idx] = l; + ++idx; +- + } + assert (idx == nloaded); + +- /* Prepare the bitmaps. */ +- memset (used, '\0', sizeof (used)); +- memset (done, '\0', sizeof (done)); +- + /* Keep track of the lowest index link map we have covered already. */ + int done_index = -1; + while (++done_index < nloaded) + { + struct link_map *l = maps[done_index]; + +- if (done[done_index]) ++ if (l->l_map_done) + /* Already handled. */ + continue; + +@@ -204,12 +199,12 @@ _dl_close_worker (struct link_map *map, bool force) + /* See CONCURRENCY NOTES in cxa_thread_atexit_impl.c to know why + acquire is sufficient and correct. */ + && atomic_load_acquire (&l->l_tls_dtor_count) == 0 +- && !used[done_index]) ++ && !l->l_map_used) + continue; + + /* We need this object and we handle it now. */ +- done[done_index] = 1; +- used[done_index] = 1; ++ l->l_map_used = 1; ++ l->l_map_done = 1; + /* Signal the object is still needed. */ + l->l_idx = IDX_STILL_USED; + +@@ -225,9 +220,9 @@ _dl_close_worker (struct link_map *map, bool force) + { + assert ((*lp)->l_idx >= 0 && (*lp)->l_idx < nloaded); + +- if (!used[(*lp)->l_idx]) ++ if (!(*lp)->l_map_used) + { +- used[(*lp)->l_idx] = 1; ++ (*lp)->l_map_used = 1; + /* If we marked a new object as used, and we've + already processed it, then we need to go back + and process again from that point forward to +@@ -250,9 +245,9 @@ _dl_close_worker (struct link_map *map, bool force) + { + assert (jmap->l_idx >= 0 && jmap->l_idx < nloaded); + +- if (!used[jmap->l_idx]) ++ if (!jmap->l_map_used) + { +- used[jmap->l_idx] = 1; ++ jmap->l_map_used = 1; + if (jmap->l_idx - 1 < done_index) + done_index = jmap->l_idx - 1; + } +@@ -262,8 +257,7 @@ _dl_close_worker (struct link_map *map, bool force) + + /* Sort the entries. We can skip looking for the binary itself which is + at the front of the search list for the main namespace. */ +- _dl_sort_maps (maps + (nsid == LM_ID_BASE), nloaded - (nsid == LM_ID_BASE), +- used + (nsid == LM_ID_BASE), true); ++ _dl_sort_maps (maps, nloaded, (nsid == LM_ID_BASE), true); + + /* Call all termination functions at once. */ + #ifdef SHARED +@@ -280,7 +274,7 @@ _dl_close_worker (struct link_map *map, bool force) + /* All elements must be in the same namespace. */ + assert (imap->l_ns == nsid); + +- if (!used[i]) ++ if (!imap->l_map_used) + { + assert (imap->l_type == lt_loaded && !imap->l_nodelete_active); + +@@ -333,7 +327,7 @@ _dl_close_worker (struct link_map *map, bool force) + if (i < first_loaded) + first_loaded = i; + } +- /* Else used[i]. */ ++ /* Else imap->l_map_used. */ + else if (imap->l_type == lt_loaded) + { + struct r_scope_elem *new_list = NULL; +@@ -560,7 +554,7 @@ _dl_close_worker (struct link_map *map, bool force) + for (unsigned int i = first_loaded; i < nloaded; ++i) + { + struct link_map *imap = maps[i]; +- if (!used[i]) ++ if (!imap->l_map_used) + { + assert (imap->l_type == lt_loaded); + +diff --git a/elf/dl-deps.c b/elf/dl-deps.c +index 087a49b212a96920..237d9636c5be780c 100644 +--- a/elf/dl-deps.c ++++ b/elf/dl-deps.c +@@ -613,10 +613,9 @@ Filters not supported with LD_TRACE_PRELINKING")); + + /* If libc.so.6 is the main map, it participates in the sort, so + that the relocation order is correct regarding libc.so.6. */ +- if (l_initfini[0] == GL (dl_ns)[l_initfini[0]->l_ns].libc_map) +- _dl_sort_maps (l_initfini, nlist, NULL, false); +- else +- _dl_sort_maps (&l_initfini[1], nlist - 1, NULL, false); ++ _dl_sort_maps (l_initfini, nlist, ++ (l_initfini[0] != GL (dl_ns)[l_initfini[0]->l_ns].libc_map), ++ false); + + /* Terminate the list of dependencies. */ + l_initfini[nlist] = NULL; +diff --git a/elf/dl-fini.c b/elf/dl-fini.c +index 6dbdfe4b3ebbeb89..c683884c355dfd52 100644 +--- a/elf/dl-fini.c ++++ b/elf/dl-fini.c +@@ -92,8 +92,7 @@ _dl_fini (void) + /* Now we have to do the sorting. We can skip looking for the + binary itself which is at the front of the search list for + the main namespace. */ +- _dl_sort_maps (maps + (ns == LM_ID_BASE), nmaps - (ns == LM_ID_BASE), +- NULL, true); ++ _dl_sort_maps (maps, nmaps, (ns == LM_ID_BASE), true); + + /* We do not rely on the linked list of loaded object anymore + from this point on. We have our own list here (maps). The +diff --git a/elf/dl-sort-maps.c b/elf/dl-sort-maps.c +index d21770267a37e128..a274ed66cc987735 100644 +--- a/elf/dl-sort-maps.c ++++ b/elf/dl-sort-maps.c +@@ -16,16 +16,24 @@ + License along with the GNU C Library; if not, see + . */ + ++#include + #include ++#include + ++/* Note: this is the older, "original" sorting algorithm, being used as ++ default up to 2.35. + +-/* Sort array MAPS according to dependencies of the contained objects. +- Array USED, if non-NULL, is permutated along MAPS. If FOR_FINI this is +- called for finishing an object. */ +-void +-_dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used, +- bool for_fini) ++ Sort array MAPS according to dependencies of the contained objects. ++ If FOR_FINI is true, this is called for finishing an object. */ ++static void ++_dl_sort_maps_original (struct link_map **maps, unsigned int nmaps, ++ unsigned int skip, bool for_fini) + { ++ /* Allows caller to do the common optimization of skipping the first map, ++ usually the main binary. */ ++ maps += skip; ++ nmaps -= skip; ++ + /* A list of one element need not be sorted. */ + if (nmaps <= 1) + return; +@@ -66,14 +74,6 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used, + (k - i) * sizeof (maps[0])); + maps[k] = thisp; + +- if (used != NULL) +- { +- char here_used = used[i]; +- memmove (&used[i], &used[i + 1], +- (k - i) * sizeof (used[0])); +- used[k] = here_used; +- } +- + if (seen[i + 1] > nmaps - i) + { + ++i; +@@ -120,3 +120,183 @@ _dl_sort_maps (struct link_map **maps, unsigned int nmaps, char *used, + next:; + } + } ++ ++#if !HAVE_TUNABLES ++/* In this case, just default to the original algorithm. */ ++strong_alias (_dl_sort_maps_original, _dl_sort_maps); ++#else ++ ++/* We use a recursive function due to its better clarity and ease of ++ implementation, as well as faster execution speed. We already use ++ alloca() for list allocation during the breadth-first search of ++ dependencies in _dl_map_object_deps(), and this should be on the ++ same order of worst-case stack usage. ++ ++ Note: the '*rpo' parameter is supposed to point to one past the ++ last element of the array where we save the sort results, and is ++ decremented before storing the current map at each level. */ ++ ++static void ++dfs_traversal (struct link_map ***rpo, struct link_map *map, ++ bool *do_reldeps) ++{ ++ if (map->l_visited) ++ return; ++ ++ map->l_visited = 1; ++ ++ if (map->l_initfini) ++ { ++ for (int i = 0; map->l_initfini[i] != NULL; i++) ++ { ++ struct link_map *dep = map->l_initfini[i]; ++ if (dep->l_visited == 0 ++ && dep->l_main_map == 0) ++ dfs_traversal (rpo, dep, do_reldeps); ++ } ++ } ++ ++ if (__glibc_unlikely (do_reldeps != NULL && map->l_reldeps != NULL)) ++ { ++ /* Indicate that we encountered relocation dependencies during ++ traversal. */ ++ *do_reldeps = true; ++ ++ for (int m = map->l_reldeps->act - 1; m >= 0; m--) ++ { ++ struct link_map *dep = map->l_reldeps->list[m]; ++ if (dep->l_visited == 0 ++ && dep->l_main_map == 0) ++ dfs_traversal (rpo, dep, do_reldeps); ++ } ++ } ++ ++ *rpo -= 1; ++ **rpo = map; ++} ++ ++/* Topologically sort array MAPS according to dependencies of the contained ++ objects. */ ++ ++static void ++_dl_sort_maps_dfs (struct link_map **maps, unsigned int nmaps, ++ unsigned int skip __attribute__ ((unused)), bool for_fini) ++{ ++ for (int i = nmaps - 1; i >= 0; i--) ++ maps[i]->l_visited = 0; ++ ++ /* We apply DFS traversal for each of maps[i] until the whole total order ++ is found and we're at the start of the Reverse-Postorder (RPO) sequence, ++ which is a topological sort. ++ ++ We go from maps[nmaps - 1] backwards towards maps[0] at this level. ++ Due to the breadth-first search (BFS) ordering we receive, going ++ backwards usually gives a more shallow depth-first recursion depth, ++ adding more stack usage safety. Also, combined with the natural ++ processing order of l_initfini[] at each node during DFS, this maintains ++ an ordering closer to the original link ordering in the sorting results ++ under most simpler cases. ++ ++ Another reason we order the top level backwards, it that maps[0] is ++ usually exactly the main object of which we're in the midst of ++ _dl_map_object_deps() processing, and maps[0]->l_initfini[] is still ++ blank. If we start the traversal from maps[0], since having no ++ dependencies yet filled in, maps[0] will always be immediately ++ incorrectly placed at the last place in the order (first in reverse). ++ Adjusting the order so that maps[0] is last traversed naturally avoids ++ this problem. ++ ++ Further, the old "optimization" of skipping the main object at maps[0] ++ from the call-site (i.e. _dl_sort_maps(maps+1,nmaps-1)) is in general ++ no longer valid, since traversing along object dependency-links ++ may "find" the main object even when it is not included in the initial ++ order (e.g. a dlopen()'ed shared object can have circular dependencies ++ linked back to itself). In such a case, traversing N-1 objects will ++ create a N-object result, and raise problems. ++ ++ To summarize, just passing in the full list, and iterating from back ++ to front makes things much more straightforward. */ ++ ++ /* Array to hold RPO sorting results, before we copy back to maps[]. */ ++ struct link_map *rpo[nmaps]; ++ ++ /* The 'head' position during each DFS iteration. Note that we start at ++ one past the last element due to first-decrement-then-store (see the ++ bottom of above dfs_traversal() routine). */ ++ struct link_map **rpo_head = &rpo[nmaps]; ++ ++ bool do_reldeps = false; ++ bool *do_reldeps_ref = (for_fini ? &do_reldeps : NULL); ++ ++ for (int i = nmaps - 1; i >= 0; i--) ++ { ++ dfs_traversal (&rpo_head, maps[i], do_reldeps_ref); ++ ++ /* We can break early if all objects are already placed. */ ++ if (rpo_head == rpo) ++ goto end; ++ } ++ assert (rpo_head == rpo); ++ ++ end: ++ /* Here we may do a second pass of sorting, using only l_initfini[] ++ static dependency links. This is avoided if !FOR_FINI or if we didn't ++ find any reldeps in the first DFS traversal. ++ ++ The reason we do this is: while it is unspecified how circular ++ dependencies should be handled, the presumed reasonable behavior is to ++ have destructors to respect static dependency links as much as possible, ++ overriding reldeps if needed. And the first sorting pass, which takes ++ l_initfini/l_reldeps links equally, may not preserve this priority. ++ ++ Hence we do a 2nd sorting pass, taking only DT_NEEDED links into account ++ (see how the do_reldeps argument to dfs_traversal() is NULL below). */ ++ if (do_reldeps) ++ { ++ for (int i = nmaps - 1; i >= 0; i--) ++ rpo[i]->l_visited = 0; ++ ++ struct link_map **maps_head = &maps[nmaps]; ++ for (int i = nmaps - 1; i >= 0; i--) ++ { ++ dfs_traversal (&maps_head, rpo[i], NULL); ++ ++ /* We can break early if all objects are already placed. ++ The below memcpy is not needed in the do_reldeps case here, ++ since we wrote back to maps[] during DFS traversal. */ ++ if (maps_head == maps) ++ return; ++ } ++ assert (maps_head == maps); ++ return; ++ } ++ ++ memcpy (maps, rpo, sizeof (struct link_map *) * nmaps); ++} ++ ++void ++_dl_sort_maps_init (void) ++{ ++ int32_t algorithm = TUNABLE_GET (glibc, rtld, dynamic_sort, int32_t, NULL); ++ GLRO(dl_dso_sort_algo) = algorithm == 1 ? dso_sort_algorithm_original ++ : dso_sort_algorithm_dfs; ++} ++ ++void ++_dl_sort_maps (struct link_map **maps, unsigned int nmaps, ++ unsigned int skip, bool for_fini) ++{ ++ /* It can be tempting to use a static function pointer to store and call ++ the current selected sorting algorithm routine, but experimentation ++ shows that current processors still do not handle indirect branches ++ that efficiently, plus a static function pointer will involve ++ PTR_MANGLE/DEMANGLE, further impairing performance of small, common ++ input cases. A simple if-case with direct function calls appears to ++ be the fastest. */ ++ if (__glibc_likely (GLRO(dl_dso_sort_algo) == dso_sort_algorithm_original)) ++ _dl_sort_maps_original (maps, nmaps, skip, for_fini); ++ else ++ _dl_sort_maps_dfs (maps, nmaps, skip, for_fini); ++} ++ ++#endif /* HAVE_TUNABLES. */ +diff --git a/elf/dl-support.c b/elf/dl-support.c +index d8c06ba7eb4c76ea..c5ee5d33aa7e1d65 100644 +--- a/elf/dl-support.c ++++ b/elf/dl-support.c +@@ -166,6 +166,8 @@ size_t _dl_phnum; + uint64_t _dl_hwcap; + uint64_t _dl_hwcap2; + ++enum dso_sort_algorithm _dl_dso_sort_algo; ++ + /* 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/dl-sysdep.c b/elf/dl-sysdep.c +index 2c684c2db2a1f59b..4dc366eea445e974 100644 +--- a/elf/dl-sysdep.c ++++ b/elf/dl-sysdep.c +@@ -231,6 +231,9 @@ _dl_sysdep_start (void **start_argptr, + + __tunables_init (_environ); + ++ /* Initialize DSO sorting algorithm after tunables. */ ++ _dl_sort_maps_init (); ++ + #ifdef DL_SYSDEP_INIT + DL_SYSDEP_INIT; + #endif +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index 8ddd4a23142a941b..46ffb2378416f90f 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -156,4 +156,13 @@ glibc { + security_level: SXID_IGNORE + } + } ++ ++ rtld { ++ dynamic_sort { ++ type: INT_32 ++ minval: 1 ++ maxval: 2 ++ default: 1 ++ } ++ } + } +diff --git a/elf/dso-sort-tests-1.def b/elf/dso-sort-tests-1.def +index 873ddf55d91155c6..5f7f18ef270bc12d 100644 +--- a/elf/dso-sort-tests-1.def ++++ b/elf/dso-sort-tests-1.def +@@ -62,5 +62,5 @@ output: b>a>{}b->c->d;d=>[ba];c=>a;b=>e=>a;c=>f=>b;d=>g=>c +-xfail_output(glibc.rtld.dynamic_sort=1): {+a[d>c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[c>b>a>];+e[e>];+f[f>];+g[g>];+d[];%d(b(e(a()))a()g(c(a()f(b(e(a()))))));-d[];-g[];-f[];-e[];-a[l_name = (char *) ""; + *user_entry = main_map->l_entry; + ++ /* Set bit indicating this is the main program map. */ ++ main_map->l_main_map = 1; ++ + #ifdef HAVE_AUX_VECTOR + /* Adjust the on-stack auxiliary vector so that it looks like the + binary was executed directly. */ +diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp +index 9f66c528855fb21d..9bf572715f996ca6 100644 +--- a/elf/tst-rtld-list-tunables.exp ++++ b/elf/tst-rtld-list-tunables.exp +@@ -10,5 +10,6 @@ glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+) ++glibc.rtld.dynamic_sort: 1 (min: 1, max: 2) + glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10) + glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+) +diff --git a/include/link.h b/include/link.h +index c46aced9f7b43ba0..4dcf01d8aea90bc2 100644 +--- a/include/link.h ++++ b/include/link.h +@@ -181,6 +181,11 @@ struct link_map + unsigned int l_init_called:1; /* Nonzero if DT_INIT function called. */ + unsigned int l_global:1; /* Nonzero if object in _dl_global_scope. */ + unsigned int l_reserved:2; /* Reserved for internal use. */ ++ unsigned int l_main_map:1; /* Nonzero for the map of the main program. */ ++ unsigned int l_visited:1; /* Used internally for map dependency ++ graph traversal. */ ++ unsigned int l_map_used:1; /* These two bits are used during traversal */ ++ unsigned int l_map_done:1; /* of maps in _dl_close_worker. */ + unsigned int l_phdr_allocated:1; /* Nonzero if the data structure pointed + to by `l_phdr' is allocated. */ + unsigned int l_soname_added:1; /* Nonzero if the SONAME is for sure in +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 658547c6137bf177..10f4d75993f9940f 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -309,6 +309,17 @@ changed once allocated at process startup. The default allocation of + optional static TLS is 512 bytes and is allocated in every thread. + @end deftp + ++@deftp Tunable glibc.rtld.dynamic_sort ++Sets the algorithm to use for DSO sorting, valid values are @samp{1} and ++@samp{2}. For value of @samp{1}, an older O(n^3) algorithm is used, which is ++long time tested, but may have performance issues when dependencies between ++shared objects contain cycles due to circular dependencies. When set to the ++value of @samp{2}, a different algorithm is used, which implements a ++topological sort through depth-first search, and does not exhibit the ++performance issues of @samp{1}. ++ ++The default value of this tunable is @samp{1}. ++@end deftp + + @node Elision Tunables + @section Elision Tunables +diff --git a/sysdeps/generic/ldsodefs.h b/sysdeps/generic/ldsodefs.h +index fcbbf6974827cdf1..bcf1f199c5985c65 100644 +--- a/sysdeps/generic/ldsodefs.h ++++ b/sysdeps/generic/ldsodefs.h +@@ -245,6 +245,13 @@ enum allowmask + }; + + ++/* DSO sort algorithm to use (check dl-sort-maps.c). */ ++enum dso_sort_algorithm ++ { ++ dso_sort_algorithm_original, ++ dso_sort_algorithm_dfs ++ }; ++ + struct audit_ifaces + { + void (*activity) (uintptr_t *, unsigned int); +@@ -672,6 +679,8 @@ struct rtld_global_ro + platforms. */ + EXTERN uint64_t _dl_hwcap2; + ++ EXTERN enum dso_sort_algorithm _dl_dso_sort_algo; ++ + #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 +@@ -1098,7 +1107,7 @@ extern void _dl_fini (void) attribute_hidden; + + /* Sort array MAPS according to dependencies of the contained objects. */ + extern void _dl_sort_maps (struct link_map **maps, unsigned int nmaps, +- char *used, bool for_fini) attribute_hidden; ++ unsigned int skip, bool for_fini) attribute_hidden; + + /* The dynamic linker calls this function before and having changing + any shared object mappings. The `r_state' member of `struct r_debug' +@@ -1225,6 +1234,9 @@ extern struct link_map * _dl_get_dl_main_map (void) + # endif + #endif + ++/* Initialize the DSO sort algorithm to use. */ ++extern void _dl_sort_maps_init (void) attribute_hidden; ++ + /* Initialization of libpthread for statically linked applications. + If libpthread is not linked in, this is an empty function. */ + void __pthread_initialize_minimal (void) weak_function; diff --git a/glibc-rh2032647-3.patch b/glibc-rh2032647-3.patch new file mode 100644 index 0000000..789e644 --- /dev/null +++ b/glibc-rh2032647-3.patch @@ -0,0 +1,25 @@ +commit d3bf2f5927d51258a51ac7fde04f4805f8ee294a +Author: Adhemerval Zanella +Date: Wed Nov 3 09:19:30 2021 -0300 + + elf: Do not run DSO sorting if tunables is not enabled + + Since the argorithm selection requires tunables. + + Checked on x86_64-linux-gnu with --enable-tunables=no. + +diff --git a/elf/Makefile b/elf/Makefile +index 8dd2b24328113536..02ee834fdaf00a26 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -483,8 +483,10 @@ include $(objpfx)$(1).generated-makefile + endef + + # Generate from each testcase description file ++ifeq (yes,$(have-tunables)) + $(eval $(call include_dsosort_tests,dso-sort-tests-1.def)) + $(eval $(call include_dsosort_tests,dso-sort-tests-2.def)) ++endif + + check-abi: $(objpfx)check-abi-ld.out + tests-special += $(objpfx)check-abi-ld.out diff --git a/glibc-rh2032647-4.patch b/glibc-rh2032647-4.patch new file mode 100644 index 0000000..1c415d4 --- /dev/null +++ b/glibc-rh2032647-4.patch @@ -0,0 +1,189 @@ +commit b4bbedb1e75737a80bcc3d53d6eef1fbe0b5f4d5 +Author: H.J. Lu +Date: Sat Nov 6 14:13:27 2021 -0700 + + dso-ordering-test.py: Put all sources in one directory [BZ #28550] + + Put all sources for DSO sorting tests in the dso-sort-tests-src directory + and compile test relocatable objects with + + $(objpfx)tst-dso-ordering1-dir/tst-dso-ordering1-a.os: $(objpfx)dso-sort-tests-src/tst-dso-ordering1-a.c + $(compile.c) $(OUTPUT_OPTION) + + to avoid random $< values from $(before-compile) when compiling test + relocatable objects with + + $(objpfx)%$o: $(objpfx)%.c $(before-compile); $$(compile-command.c) + compile-command.c = $(compile.c) $(OUTPUT_OPTION) $(compile-mkdep-flags) + compile.c = $(CC) $< -c $(CFLAGS) $(CPPFLAGS) + + for 3 "make -j 28" parallel builds on a machine with 112 cores at the + same time. + + This partially fixes BZ #28550. + + Reviewed-by: Adhemerval Zanella + +diff --git a/scripts/dso-ordering-test.py b/scripts/dso-ordering-test.py +index 944ee740527d60fd..bde0406be9da14fc 100644 +--- a/scripts/dso-ordering-test.py ++++ b/scripts/dso-ordering-test.py +@@ -526,9 +526,13 @@ def process_testcase(t): + base_test_name = t.test_name + test_subdir = base_test_name + "-dir" + testpfx = objpfx + test_subdir + "/" ++ test_srcdir = "dso-sort-tests-src/" ++ testpfx_src = objpfx + test_srcdir + + if not os.path.exists(testpfx): + os.mkdir(testpfx) ++ if not os.path.exists(testpfx_src): ++ os.mkdir(testpfx_src) + + def find_objs_not_depended_on(t): + objs_not_depended_on = [] +@@ -595,6 +599,11 @@ def process_testcase(t): + # Print out needed Makefile fragments for use in glibc/elf/Makefile. + module_names = "" + for o in test_descr.objs: ++ rule = ("$(objpfx)" + test_subdir + "/" + test_name ++ + "-" + o + ".os: $(objpfx)" + test_srcdir ++ + test_name + "-" + o + ".c\n" ++ "\t$(compile.c) $(OUTPUT_OPTION)\n") ++ makefile.write (rule) + module_names += " " + test_subdir + "/" + test_name + "-" + o + makefile.write("modules-names +=%s\n" % (module_names)) + +@@ -637,7 +646,7 @@ def process_testcase(t): + # object. This only needs to be done at most once for + # an object name. + if not dep in fake_created: +- f = open(testpfx + test_name + "-" + dep ++ f = open(testpfx_src + test_name + "-" + dep + + ".FAKE.c", "w") + f.write(" \n") + f.close() +@@ -648,6 +657,12 @@ def process_testcase(t): + % (test_name + "-" + dep + ".FAKE.so", + ("$(objpfx)" + test_subdir + "/" + + test_name + "-" + dep + ".so"))) ++ rule = ("$(objpfx)" + test_subdir + "/" ++ + test_name + "-" + dep + ".FAKE.os: " ++ "$(objpfx)" + test_srcdir ++ + test_name + "-" + dep + ".FAKE.c\n" ++ "\t$(compile.c) $(OUTPUT_OPTION)\n") ++ makefile.write (rule) + makefile.write \ + ("modules-names += %s\n" + % (test_subdir + "/" +@@ -687,6 +702,10 @@ def process_testcase(t): + + test_descr.soname_map['#'] + ".so") + ldflags += (" -Wl,-soname=" + soname) + makefile.write("LDFLAGS-%s = %s\n" % (test_name, ldflags)) ++ rule = ("$(objpfx)" + test_subdir + "/" + test_name + ".o: " ++ "$(objpfx)" + test_srcdir + test_name + ".c\n" ++ "\t$(compile.c) $(OUTPUT_OPTION)\n") ++ makefile.write (rule) + + not_depended_objs = find_objs_not_depended_on(test_descr) + if not_depended_objs: +@@ -745,7 +764,7 @@ def process_testcase(t): + " something_failed=true\n" + "else\n" + " diff -wu ${common_objpfx}elf/%s/%s%s.output \\\n" +- " ${common_objpfx}elf/%s/%s%s.exp\n" ++ " ${common_objpfx}elf/%s%s%s.exp\n" + " if [ $? -ne 0 ]; then\n" + " echo '%sFAIL: %s%s expected output comparison'\n" + " something_failed=true\n" +@@ -753,14 +772,14 @@ def process_testcase(t): + "fi\n" + % (("X" if xfail else ""), test_name, tunable_descr, + test_subdir, test_name, tunable_sfx, +- test_subdir, base_test_name, exp_tunable_sfx, ++ test_srcdir, base_test_name, exp_tunable_sfx, + ("X" if xfail else ""), test_name, tunable_descr)) + + # Generate C files according to dependency and calling relations from + # description string. + for obj in test_descr.objs: + src_name = test_name + "-" + obj + ".c" +- f = open(testpfx + src_name, "w") ++ f = open(testpfx_src + src_name, "w") + if obj in test_descr.callrefs: + called_objs = test_descr.callrefs[obj] + for callee in called_objs: +@@ -804,7 +823,7 @@ def process_testcase(t): + f.close() + + # Open C file for writing main program +- f = open(testpfx + test_name + ".c", "w") ++ f = open(testpfx_src + test_name + ".c", "w") + + # if there are some operations in main(), it means we need -ldl + f.write("#include \n") +@@ -885,7 +904,7 @@ def process_testcase(t): + for obj in test_descr.objs: + src_name = test_name + "-" + obj + ".c" + obj_name = test_name + "-" + obj + ".os" +- run_cmd([build_gcc, "-c", "-fPIC", testpfx + src_name, ++ run_cmd([build_gcc, "-c", "-fPIC", testpfx_src + src_name, + "-o", testpfx + obj_name]) + + obj_processed = {} +@@ -903,10 +922,12 @@ def process_testcase(t): + deps.append(dep + ".FAKE") + if not dep in fake_created: + base_name = testpfx + test_name + "-" + dep ++ src_base_name = (testpfx_src + test_name ++ + "-" + dep) + cmd = [build_gcc, "-Wl,--no-as-needed", + ("-Wl,-soname=" + base_name + ".so"), + "-shared", base_name + ".FAKE.c", +- "-o", base_name + ".FAKE.so"] ++ "-o", src_base_name + ".FAKE.so"] + run_cmd(cmd) + fake_created[dep] = True + dso_deps = map(lambda d: testpfx + test_name + "-" + d + ".so", +@@ -932,7 +953,7 @@ def process_testcase(t): + main_deps = map(lambda d: testpfx + test_name + "-" + d + ".so", + deps) + cmd = [build_gcc, "-Wl,--no-as-needed", "-o", testpfx + test_name, +- testpfx + test_name + ".c", "-L%s" % (os.getcwd()), ++ testpfx_src + test_name + ".c", "-L%s" % (os.getcwd()), + "-Wl,-rpath-link=%s" % (os.getcwd())] + if '#' in test_descr.soname_map: + soname = ("-Wl,-soname=" + testpfx + test_name + "-" +@@ -987,14 +1008,14 @@ def process_testcase(t): + sfx = "" + if r[0] != "": + sfx = "-" + r[0].replace("=","_") +- f = open(testpfx + t.test_name + sfx + ".exp", "w") ++ f = open(testpfx_src + t.test_name + sfx + ".exp", "w") + (output, xfail) = r[1] + f.write('%s' % output) + f.close() + + # Create header part of top-level testcase shell script, to wrap execution + # and output comparison together. +- t.sh = open(testpfx + t.test_name + ".sh", "w") ++ t.sh = open(testpfx_src + t.test_name + ".sh", "w") + t.sh.write("#!/bin/sh\n") + t.sh.write("# Test driver for %s, generated by " + "dso-ordering-test.py\n" % (t.test_name)) +@@ -1022,12 +1043,12 @@ def process_testcase(t): + sfx = "" + if r[0] != "": + sfx = "-" + r[0].replace("=","_") +- expected_output_files += " $(objpfx)%s/%s%s.exp" % (test_subdir, ++ expected_output_files += " $(objpfx)%s%s%s.exp" % (test_srcdir, + t.test_name, sfx) + makefile.write \ +- ("$(objpfx)%s.out: $(objpfx)%s/%s.sh%s " ++ ("$(objpfx)%s.out: $(objpfx)%s%s.sh%s " + "$(common-objpfx)support/test-run-command\n" +- % (t.test_name, test_subdir, t.test_name, ++ % (t.test_name, test_srcdir, t.test_name, + expected_output_files)) + makefile.write("\t$(SHELL) $< $(common-objpfx) '$(test-wrapper-env)' " + "'$(run-program-env)' > $@; $(evaluate-test)\n") diff --git a/glibc-rh2032647-5.patch b/glibc-rh2032647-5.patch new file mode 100644 index 0000000..308d831 --- /dev/null +++ b/glibc-rh2032647-5.patch @@ -0,0 +1,45 @@ +commit 1f67d8286b5da9266a138198ef1f15c27cbb0010 +Author: H.J. Lu +Date: Mon Nov 15 16:28:39 2021 -0800 + + elf: Use a temporary file to generate Makefile fragments [BZ #28550] + + 1. Use a temporary file to generate Makefile fragments for DSO sorting + tests and use -include on them. + 2. Add Makefile fragments to postclean-generated so that a "make clean" + removes the autogenerated fragments and a subsequent "make" regenerates + them. + + This partially fixes BZ #28550. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/Makefile b/elf/Makefile +index 02ee834fdaf00a26..535ba4260fb98e64 100644 +--- a/elf/Makefile ++++ b/elf/Makefile +@@ -471,6 +471,7 @@ tests-special += $(objpfx)order-cmp.out $(objpfx)tst-array1-cmp.out \ + $(objpfx)tst-unused-dep-cmp.out + endif + ++ifndef avoid-generated + # DSO sorting tests: + # The dso-ordering-test.py script generates testcase source files in $(objpfx), + # creating a $(objpfx)-dir for each testcase, and creates a +@@ -478,9 +479,14 @@ endif + define include_dsosort_tests + $(objpfx)$(1).generated-makefile: $(1) + $(PYTHON) $(..)scripts/dso-ordering-test.py \ +- --description-file $$< --objpfx $(objpfx) --output-makefile $$@ +-include $(objpfx)$(1).generated-makefile ++ --description-file $$< --objpfx $(objpfx) --output-makefile $$@T ++ mv $$@T $$@ ++-include $(objpfx)$(1).generated-makefile + endef ++endif ++ ++postclean-generated += $(objpfx)/dso-sort-tests-2.generated-makefile \ ++ $(objpfx)/dso-sort-tests-2.generated-makefile + + # Generate from each testcase description file + ifeq (yes,$(have-tunables)) diff --git a/glibc-rh2032647-6.patch b/glibc-rh2032647-6.patch new file mode 100644 index 0000000..6dcaccd --- /dev/null +++ b/glibc-rh2032647-6.patch @@ -0,0 +1,49 @@ +commit 0884724a95b60452ad483dbe086d237d02ba624d +Author: Florian Weimer +Date: Tue Dec 14 12:37:44 2021 +0100 + + elf: Use new dependency sorting algorithm by default + + The default has to change eventually, and there are no known failures + that require a delay. + + Reviewed-by: Adhemerval Zanella + +diff --git a/elf/dl-tunables.list b/elf/dl-tunables.list +index 46ffb2378416f90f..ffcd7f18d4fafb91 100644 +--- a/elf/dl-tunables.list ++++ b/elf/dl-tunables.list +@@ -162,7 +162,7 @@ glibc { + type: INT_32 + minval: 1 + maxval: 2 +- default: 1 ++ default: 2 + } + } + } +diff --git a/elf/tst-rtld-list-tunables.exp b/elf/tst-rtld-list-tunables.exp +index 9bf572715f996ca6..44e4834cfb431633 100644 +--- a/elf/tst-rtld-list-tunables.exp ++++ b/elf/tst-rtld-list-tunables.exp +@@ -10,6 +10,6 @@ glibc.malloc.tcache_max: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.tcache_unsorted_limit: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.top_pad: 0x0 (min: 0x0, max: 0x[f]+) + glibc.malloc.trim_threshold: 0x0 (min: 0x0, max: 0x[f]+) +-glibc.rtld.dynamic_sort: 1 (min: 1, max: 2) ++glibc.rtld.dynamic_sort: 2 (min: 1, max: 2) + glibc.rtld.nns: 0x4 (min: 0x1, max: 0x10) + glibc.rtld.optional_static_tls: 0x200 (min: 0x0, max: 0x[f]+) +diff --git a/manual/tunables.texi b/manual/tunables.texi +index 10f4d75993f9940f..7c3b28d029410a6f 100644 +--- a/manual/tunables.texi ++++ b/manual/tunables.texi +@@ -318,7 +318,7 @@ value of @samp{2}, a different algorithm is used, which implements a + topological sort through depth-first search, and does not exhibit the + performance issues of @samp{1}. + +-The default value of this tunable is @samp{1}. ++The default value of this tunable is @samp{2}. + @end deftp + + @node Elision Tunables diff --git a/glibc-upstream-2.34-54.patch b/glibc-upstream-2.34-54.patch new file mode 100644 index 0000000..fec14bf --- /dev/null +++ b/glibc-upstream-2.34-54.patch @@ -0,0 +1,32 @@ +commit 7af07fe795f43e53d31be1c6f9adba7e05f87b0b +Author: Xi Ruoyao +Date: Thu Aug 12 20:31:59 2021 +0000 + + mips: align stack in clone [BZ #28223] + + The MIPS O32 ABI requires 4 byte aligned stack, and the MIPS N64 and N32 + ABI require 8 byte aligned stack. Previously if the caller passed an + unaligned stack to clone the the child misbehaved. + + Fixes bug 28223. + + (cherry picked from commit 1f51cd9a860ee45eee8a56fb2ba925267a2a7bfe) + +diff --git a/sysdeps/unix/sysv/linux/mips/clone.S b/sysdeps/unix/sysv/linux/mips/clone.S +index 71d9dba8bd9e8f9e..43a5ad3a400d9504 100644 +--- a/sysdeps/unix/sysv/linux/mips/clone.S ++++ b/sysdeps/unix/sysv/linux/mips/clone.S +@@ -55,6 +55,13 @@ NESTED(__clone,4*SZREG,sp) + .set at + #endif + ++ /* Align stack to 4/8 bytes per the ABI. */ ++#if _MIPS_SIM == _ABIO32 ++ li t0,-4 ++#else ++ li t0,-8 ++#endif ++ and a1,a1,t0 + + /* Sanity check arguments. */ + li v0,EINVAL diff --git a/glibc-upstream-2.34-55.patch b/glibc-upstream-2.34-55.patch new file mode 100644 index 0000000..9746705 --- /dev/null +++ b/glibc-upstream-2.34-55.patch @@ -0,0 +1,37 @@ +commit 4db172a54d43f9b7fd17e66fc44a34efb3cab1e1 +Author: Xi Ruoyao +Date: Fri Aug 13 16:01:14 2021 +0000 + + mips: increase stack alignment in clone to match the ABI + + In "mips: align stack in clone [BZ #28223]" + (commit 1f51cd9a860ee45eee8a56fb2ba925267a2a7bfe) I made a mistake: I + misbelieved one "word" was 2-byte and "doubleword" should be 4-byte. + But in MIPS ABI one "word" is defined 32-bit (4-byte), so "doubleword" is + 8-byte [1], and "quadword" is 16-byte [2]. + + [1]: "System V Application Binary Interface: MIPS(R) RISC Processor + Supplement, 3rd edition", page 3-31 + [2]: "MIPSpro(TM) 64-Bit Porting and Transition Guide", page 23 + + (cherry picked from commit 0f62fe053273ff6c62ac95c59b7687c964737b00) + +diff --git a/sysdeps/unix/sysv/linux/mips/clone.S b/sysdeps/unix/sysv/linux/mips/clone.S +index 43a5ad3a400d9504..fd71b5ca2eb86089 100644 +--- a/sysdeps/unix/sysv/linux/mips/clone.S ++++ b/sysdeps/unix/sysv/linux/mips/clone.S +@@ -55,11 +55,11 @@ NESTED(__clone,4*SZREG,sp) + .set at + #endif + +- /* Align stack to 4/8 bytes per the ABI. */ ++ /* Align stack to 8/16 bytes per the ABI. */ + #if _MIPS_SIM == _ABIO32 +- li t0,-4 +-#else + li t0,-8 ++#else ++ li t0,-16 + #endif + and a1,a1,t0 + diff --git a/glibc-upstream-2.34-56.patch b/glibc-upstream-2.34-56.patch new file mode 100644 index 0000000..ee2ad63 --- /dev/null +++ b/glibc-upstream-2.34-56.patch @@ -0,0 +1,65 @@ +commit 93aabf891e96e93f100081ee07989c23d7107d17 +Author: Florian Weimer +Date: Fri Dec 17 11:48:41 2021 +0100 + + arm: Guard ucontext _rtld_global_ro access by SHARED, not PIC macro + + Due to PIE-by-default, PIC is now defined in more cases. libc.a + does not have _rtld_global_ro, and statically linking setcontext + fails. SHARED is the right condition to use, so that libc.a + references _dl_hwcap instead of _rtld_global_ro. + + For static PIE support, the !SHARED case would still have to be made + PIC. This patch does not achieve that. + + Fixes commit 23645707f12f2dd9d80b51effb2d9618a7b65565 + ("Replace --enable-static-pie with --disable-default-pie"). + + Reviewed-by: Siddhesh Poyarekar + Reviewed-by: Szabolcs Nagy + (cherry picked from commit ce1e5b11229f19820b86f8b19d651f16009552b0) + +diff --git a/sysdeps/unix/sysv/linux/arm/getcontext.S b/sysdeps/unix/sysv/linux/arm/getcontext.S +index 3aa581c4da6d1166..11bfcbe5f53afc6e 100644 +--- a/sysdeps/unix/sysv/linux/arm/getcontext.S ++++ b/sysdeps/unix/sysv/linux/arm/getcontext.S +@@ -50,7 +50,7 @@ ENTRY(__getcontext) + + /* Store FP regs. Much of the FP code is copied from arm/setjmp.S. */ + +-#ifdef PIC ++#ifdef SHARED + ldr r2, 1f + ldr r1, .Lrtld_global_ro + 0: add r2, pc, r2 +@@ -102,7 +102,7 @@ ENTRY(__getcontext) + + END(__getcontext) + +-#ifdef PIC ++#ifdef SHARED + 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS + .Lrtld_global_ro: + .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) +diff --git a/sysdeps/unix/sysv/linux/arm/setcontext.S b/sysdeps/unix/sysv/linux/arm/setcontext.S +index 8be8beefea13883e..4c7c6e550944138c 100644 +--- a/sysdeps/unix/sysv/linux/arm/setcontext.S ++++ b/sysdeps/unix/sysv/linux/arm/setcontext.S +@@ -32,7 +32,7 @@ ENTRY(__setcontext) + add r0, r0, #UCONTEXT_REGSPACE + + /* Restore the VFP registers. Copied from arm/__longjmp.S. */ +-#ifdef PIC ++#ifdef SHARED + ldr r2, 1f + ldr r1, .Lrtld_global_ro + 0: add r2, pc, r2 +@@ -101,7 +101,7 @@ ENTRY(__startcontext) + .fnend + END(__startcontext) + +-#ifdef PIC ++#ifdef SHARED + 1: .long _GLOBAL_OFFSET_TABLE_ - 0b - PC_OFS + .Lrtld_global_ro: + .long C_SYMBOL_NAME(_rtld_global_ro)(GOT) diff --git a/glibc-upstream-2.34-57.patch b/glibc-upstream-2.34-57.patch new file mode 100644 index 0000000..c8523f9 --- /dev/null +++ b/glibc-upstream-2.34-57.patch @@ -0,0 +1,74 @@ +commit dc9b69d5331dcdca4547c0490cb9fefbd89e40f6 +Author: Florian Weimer +Date: Fri Dec 17 12:01:20 2021 +0100 + + 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 + (cherry picked from commit b99b0f93ee8762fe53ff65802deb6f00700b9924) + +diff --git a/manual/nss.texi b/manual/nss.texi +index 3aaa7786f8cf3168..524d22ad1e7f8ca0 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 f1c97f7c8e9d7378..dbc87868dd408d9f 100644 +--- a/nss/XXX-lookup.c ++++ b/nss/XXX-lookup.c +@@ -29,7 +29,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 ab121cb371c087e9..54561f03287db2e4 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: diff --git a/glibc-upstream-2.34-58.patch b/glibc-upstream-2.34-58.patch new file mode 100644 index 0000000..d95112e --- /dev/null +++ b/glibc-upstream-2.34-58.patch @@ -0,0 +1,35 @@ +commit 03de6917bd11c0591867607ce74ef658f76eabb9 +Author: Aurelien Jarno +Date: Wed Dec 15 23:46:19 2021 +0100 + + elf: Fix tst-cpu-features-cpuinfo for KVM guests on some AMD systems [BZ #28704] + + On KVM guests running on some AMD systems, the IBRS feature is reported + as a synthetic feature using the Intel feature, while the cpuinfo entry + keeps the same. Handle that by first checking the presence of the Intel + feature on AMD systems. + + Fixes bug 28704. + + (cherry picked from commit 94058f6cde8b887178885954740ac6c866d25eab) + +diff --git a/sysdeps/x86/tst-cpu-features-cpuinfo.c b/sysdeps/x86/tst-cpu-features-cpuinfo.c +index 2d4927f5e52dc260..830aaca2ecae971b 100644 +--- a/sysdeps/x86/tst-cpu-features-cpuinfo.c ++++ b/sysdeps/x86/tst-cpu-features-cpuinfo.c +@@ -169,7 +169,14 @@ do_test (int argc, char **argv) + else if (cpu_features->basic.kind == arch_kind_amd) + { + fails += CHECK_PROC (ibpb, AMD_IBPB); +- fails += CHECK_PROC (ibrs, AMD_IBRS); ++ ++ /* The IBRS feature on AMD processors is reported using the Intel feature ++ * on KVM guests (synthetic bit). In both cases the cpuinfo entry is the ++ * same. */ ++ if (HAS_CPU_FEATURE (IBRS_IBPB)) ++ fails += CHECK_PROC (ibrs, IBRS_IBPB); ++ else ++ fails += CHECK_PROC (ibrs, AMD_IBRS); + fails += CHECK_PROC (stibp, AMD_STIBP); + } + fails += CHECK_PROC (ibt, IBT); diff --git a/glibc-upstream-2.34-59.patch b/glibc-upstream-2.34-59.patch new file mode 100644 index 0000000..b0ea00c --- /dev/null +++ b/glibc-upstream-2.34-59.patch @@ -0,0 +1,35 @@ +commit 5daf13b1e637eec0f7a2de05b177cb0d76479aa2 +Author: Matheus Castanho +Date: Wed Dec 1 11:14:40 2021 -0300 + + powerpc64[le]: Allocate extra stack frame on syscall.S + + The syscall function does not allocate the extra stack frame for scv like other + assembly syscalls using DO_CALL_SCV. So after commit d120fb9941 changed the + offset that is used to save LR, syscall ended up using an invalid offset, + causing regressions on powerpc64. So make sure the extra stack frame is + allocated in syscall.S as well to make it consistent with other uses of + DO_CALL_SCV and avoid similar issues in the future. + + Tested on powerpc, powerpc64, and powerpc64le (with and without scv) + + Reviewed-by: Raphael M Zinsly + + (cherry picked from commit ae91d3df24a4a1b1f264d101a71a298bff310d14) + +diff --git a/sysdeps/unix/sysv/linux/powerpc/syscall.S b/sysdeps/unix/sysv/linux/powerpc/syscall.S +index a29652feaf6764cf..a5497c8370982fe3 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/syscall.S ++++ b/sysdeps/unix/sysv/linux/powerpc/syscall.S +@@ -27,7 +27,11 @@ ENTRY (syscall) + mr r8,r9 + #if defined(USE_PPC_SCV) && !IS_IN(rtld) && (defined(__PPC64__) || defined(__powerpc64__)) + CHECK_SCV_SUPPORT r9 0f ++ stdu r1,-SCV_FRAME_SIZE(r1) ++ cfi_adjust_cfa_offset(SCV_FRAME_SIZE) + DO_CALL_SCV ++ addi r1,r1,SCV_FRAME_SIZE ++ cfi_adjust_cfa_offset(-SCV_FRAME_SIZE) + RET_SCV + b 1f + #endif diff --git a/glibc-upstream-2.34-60.patch b/glibc-upstream-2.34-60.patch new file mode 100644 index 0000000..60d2765 --- /dev/null +++ b/glibc-upstream-2.34-60.patch @@ -0,0 +1,32 @@ +commit 9de8011c328021f10588a8acb418daf5121d5f3d +Author: Aurelien Jarno +Date: Tue Dec 14 22:44:35 2021 +0100 + + 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 + + (cherry picked from commit d2e594d71509faf36cf851a69370db34a4f5fa65) + +diff --git a/sysdeps/unix/sysv/linux/riscv/clone.S b/sysdeps/unix/sysv/linux/riscv/clone.S +index 12f91a20d3bb34f5..161e83c7e3786b8d 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. */ diff --git a/glibc-upstream-2.34-61.patch b/glibc-upstream-2.34-61.patch new file mode 100644 index 0000000..82214de --- /dev/null +++ b/glibc-upstream-2.34-61.patch @@ -0,0 +1,34 @@ +commit aa3a97496c82a8443039248ebee650322c9480f4 +Author: Aurelien Jarno +Date: Thu Dec 16 00:06:28 2021 +0100 + + riscv: align stack before calling _dl_init [BZ #28703] + + Align the stack pointer to 128 bits during the call to _dl_init() as + specified by the RISC-V ABI [1]. This fixes the elf/tst-align2 test. + + Fixes bug 28703. + + [1] https://github.com/riscv-non-isa/riscv-elf-psabi-doc + + (cherry picked from commit 225da459cebef1037dcd78b56471edc0721e1c41) + +diff --git a/sysdeps/riscv/dl-machine.h b/sysdeps/riscv/dl-machine.h +index aedf69fcdd8aff50..951268923da26a37 100644 +--- a/sysdeps/riscv/dl-machine.h ++++ b/sysdeps/riscv/dl-machine.h +@@ -127,8 +127,14 @@ elf_machine_load_address (void) + sll a3, a1, " STRINGXP (PTRLOG) "\n\ + add a3, a3, a2\n\ + add a3, a3, " STRINGXP (SZREG) "\n\ ++ # Stash the stack pointer in s1.\n\ ++ mv s1, sp\n\ ++ # Align stack to 128 bits for the _dl_init call.\n\ ++ andi sp, sp,-16\n\ + # Call the function to run the initializers.\n\ + jal _dl_init\n\ ++ # Restore the stack pointer for _start.\n\ ++ mv sp, s1\n\ + # Pass our finalizer function to _start.\n\ + lla a0, _dl_fini\n\ + # Jump to the user entry point.\n\ diff --git a/glibc-upstream-2.34-62.patch b/glibc-upstream-2.34-62.patch new file mode 100644 index 0000000..656bcfb --- /dev/null +++ b/glibc-upstream-2.34-62.patch @@ -0,0 +1,21 @@ +commit 4029747c592cb2d59805b3a4e7a8963fcdcdbeb1 +Author: John David Anglin +Date: Mon Sep 6 17:37:29 2021 +0000 + + Update hppa libm-test-ulps + + (cherry picked from commit d8cf84ac7e504663dfeb2bb45d8d48ae81effe05) + +diff --git a/sysdeps/hppa/fpu/libm-test-ulps b/sysdeps/hppa/fpu/libm-test-ulps +index 90e16a72692e9199..3d60fc25a14d053f 100644 +--- a/sysdeps/hppa/fpu/libm-test-ulps ++++ b/sysdeps/hppa/fpu/libm-test-ulps +@@ -1104,7 +1104,7 @@ float: 8 + ldouble: 1 + + Function: "tgamma_downward": +-double: 8 ++double: 9 + float: 7 + + Function: "tgamma_towardzero": diff --git a/glibc-upstream-2.34-63.patch b/glibc-upstream-2.34-63.patch new file mode 100644 index 0000000..e0944e1 --- /dev/null +++ b/glibc-upstream-2.34-63.patch @@ -0,0 +1,21 @@ +commit e94544c82f4ac37017589d8d83156d72388fc4af +Author: Adhemerval Zanella +Date: Wed Aug 4 21:40:32 2021 +0300 + + Update sparc libm-test-ulps + + (cherry picked from commit c52eb066bc634a79e4194457362384abe5b43b3a) + +diff --git a/sysdeps/sparc/fpu/libm-test-ulps b/sysdeps/sparc/fpu/libm-test-ulps +index c2e4649524aa3a44..f34bbe6c592814d0 100644 +--- a/sysdeps/sparc/fpu/libm-test-ulps ++++ b/sysdeps/sparc/fpu/libm-test-ulps +@@ -1346,7 +1346,7 @@ float: 8 + ldouble: 4 + + Function: "tgamma_downward": +-double: 8 ++double: 9 + float: 7 + ldouble: 5 + diff --git a/glibc-upstream-2.34-64.patch b/glibc-upstream-2.34-64.patch new file mode 100644 index 0000000..54ae960 --- /dev/null +++ b/glibc-upstream-2.34-64.patch @@ -0,0 +1,81 @@ +commit 1d9764aba8c00754fbf8299e48afbe222245ee3e +Author: Adhemerval Zanella +Date: Wed Aug 4 21:34:12 2021 +0300 + + linux: Add sparck brk implementation + + It turned that the generic implementation of brk() does not work + for sparc, since on failure kernel will just return the previous + input value without setting the conditional register. + + This patches adds back a sparc32 and sparc64 implementation removed + by 720480934ab9107. + + Checked on sparc64-linux-gnu and sparcv9-linux-gnu. + + (cherry picked from commit 5b86241a032c50462988bdd1439e078384690d34) + +diff --git a/sysdeps/unix/sysv/linux/sparc/brk.c b/sysdeps/unix/sysv/linux/sparc/brk.c +new file mode 100644 +index 0000000000000000..aafe9673e3062cf8 +--- /dev/null ++++ b/sysdeps/unix/sysv/linux/sparc/brk.c +@@ -0,0 +1,58 @@ ++/* Change data segment. Linux SPARC 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 ++ . */ ++ ++#include ++#include ++#include ++ ++/* This must be initialized data because commons can't have aliases. */ ++void *__curbrk = 0; ++ ++#if HAVE_INTERNAL_BRK_ADDR_SYMBOL ++/* Old braindamage in GCC's crtstuff.c requires this symbol in an attempt ++ to work around different old braindamage in the old Linux ELF dynamic ++ linker. */ ++weak_alias (__curbrk, ___brk_addr) ++#endif ++ ++#ifdef __arch64__ ++# define SYSCALL_NUM "0x6d" ++#else ++# define SYSCALL_NUM "0x10" ++#endif ++ ++int ++__brk (void *addr) ++{ ++ register long int g1 asm ("g1") = __NR_brk; ++ register long int o0 asm ("o0") = (long int) addr; ++ asm volatile ("ta " SYSCALL_NUM ++ : "=r"(o0) ++ : "r"(g1), "0"(o0) ++ : "cc"); ++ __curbrk = (void *) o0; ++ ++ if (__curbrk < addr) ++ { ++ __set_errno (ENOMEM); ++ return -1; ++ } ++ ++ return 0; ++} ++weak_alias (__brk, brk) diff --git a/glibc-upstream-2.34-65.patch b/glibc-upstream-2.34-65.patch new file mode 100644 index 0000000..6644c9d --- /dev/null +++ b/glibc-upstream-2.34-65.patch @@ -0,0 +1,33 @@ +commit 8ad6d6d8ed33631bd2ca5d1112e6da2f92731432 +Author: maminjie +Date: Mon Dec 20 19:36:32 2021 +0800 + + Linux: Fix 32-bit vDSO for clock_gettime on powerpc32 + + When the clock_id is CLOCK_PROCESS_CPUTIME_ID or CLOCK_THREAD_CPUTIME_ID, + on the 5.10 kernel powerpc 32-bit, the 32-bit vDSO is executed successfully ( + because the __kernel_clock_gettime in arch/powerpc/kernel/vdso32/gettimeofday.S + does not support these two IDs, the 32-bit time_t syscall will be used), + but tp32.tv_sec is equal to 0, causing the 64-bit time_t syscall to continue to be used, + resulting in two system calls. + + Fix commit 72e84d1db22203e01a43268de71ea8669eca2863. + + Signed-off-by: maminjie + Reviewed-by: Adhemerval Zanella + + (cherry picked from commit e0fc721ce600038dd390e77cfe52440707ef574d) + +diff --git a/sysdeps/unix/sysv/linux/clock_gettime.c b/sysdeps/unix/sysv/linux/clock_gettime.c +index 91df6b3d967bf945..9c7d9073254843c7 100644 +--- a/sysdeps/unix/sysv/linux/clock_gettime.c ++++ b/sysdeps/unix/sysv/linux/clock_gettime.c +@@ -53,7 +53,7 @@ __clock_gettime64 (clockid_t clock_id, struct __timespec64 *tp) + { + struct timespec tp32; + r = INTERNAL_VSYSCALL_CALL (vdso_time, 2, clock_id, &tp32); +- if (r == 0 && tp32.tv_sec > 0) ++ if (r == 0 && tp32.tv_sec >= 0) + { + *tp = valid_timespec_to_timespec64 (tp32); + return 0; diff --git a/glibc-upstream-2.34-66.patch b/glibc-upstream-2.34-66.patch new file mode 100644 index 0000000..9619100 --- /dev/null +++ b/glibc-upstream-2.34-66.patch @@ -0,0 +1,37 @@ +commit 41fddc064ded5c9a36d8ffaad59a85407a22a535 +Author: Andrea Monaco +Date: Sun Dec 12 10:24:28 2021 +0100 + + 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 + (cherry picked from commit c6d7d6312c21bbcfb236d48bb7c11cedb234389f) + +diff --git a/intl/plural.y b/intl/plural.y +index e02e74541c4574eb..2ee128ba01b5820d 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} diff --git a/glibc-upstream-2.34-67.patch b/glibc-upstream-2.34-67.patch new file mode 100644 index 0000000..2ee0841 --- /dev/null +++ b/glibc-upstream-2.34-67.patch @@ -0,0 +1,50 @@ +commit 217b84127b3a6590afcc7e198e6c3f665935e8f4 +Author: Wilco Dijkstra +Date: Thu Jan 6 14:36:28 2022 +0000 + + 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. + + (cherry picked from commit e5fa62b8db546f8792ec9e5c61e6419f4f8e3f4d) + +diff --git a/sysdeps/aarch64/multiarch/memcpy.c b/sysdeps/aarch64/multiarch/memcpy.c +index 25e0081eeb51727c..b6703af44b3f1a3d 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 d0adefc547f60030..d2339ff34ff7b3e5 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 d7d9bbbda095e051..3d839bc02e96380d 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 diff --git a/glibc-upstream-2.34-68.patch b/glibc-upstream-2.34-68.patch new file mode 100644 index 0000000..935e4f0 --- /dev/null +++ b/glibc-upstream-2.34-68.patch @@ -0,0 +1,27 @@ +commit 515a6f53cd984d5e6e374fbee52772f967fc3c73 +Author: Paul Eggert +Date: Mon Sep 13 22:49:45 2021 -0700 + + 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 + (cherry picked from commit 645277434a42efc547d2cac8bfede4da10b4049f) + +diff --git a/time/tzfile.c b/time/tzfile.c +index 4377018a55936389..190a777152b31cee 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 diff --git a/glibc-upstream-2.34-69.patch b/glibc-upstream-2.34-69.patch new file mode 100644 index 0000000..1346263 --- /dev/null +++ b/glibc-upstream-2.34-69.patch @@ -0,0 +1,52 @@ +commit 85b24f9694e21f1d2f2d8b80d3bf690687723347 +Author: Hans-Peter Nilsson +Date: Fri Dec 17 21:38:00 2021 +0100 + + 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 + (cherry picked from commit c36f64aa6dff13b12a1e03a185e75a50fa9f6a4c) + +diff --git a/time/tzfile.c b/time/tzfile.c +index 190a777152b31cee..8668392ad387af05 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) diff --git a/glibc-upstream-2.34-70.patch b/glibc-upstream-2.34-70.patch new file mode 100644 index 0000000..b83ae03 --- /dev/null +++ b/glibc-upstream-2.34-70.patch @@ -0,0 +1,130 @@ +commit d5ba02f67dd62a63e29c29eebd6c543722aa6b5b +Author: Hans-Peter Nilsson +Date: Fri Dec 17 21:45:54 2021 +0100 + + 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 + (cherry picked from commit ebe899af0dc3215159a9c896ac6f35b72a18cb6e) + +diff --git a/timezone/Makefile b/timezone/Makefile +index c624a189b322cb5f..f091663b8bbbceda 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 0000000000000000..3cea0569eb5a6a57 +--- /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 0000000000000000..0a9df1e9a094f1e9 +--- /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 ++ . */ ++ ++#include ++#include ++#include ++#include ++ ++/* 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 diff --git a/glibc-upstream-2.34-71.patch b/glibc-upstream-2.34-71.patch new file mode 100644 index 0000000..4e534ed --- /dev/null +++ b/glibc-upstream-2.34-71.patch @@ -0,0 +1,39 @@ +commit e64235ff4266e87b20505101877fe57350ab69ab +Author: Paul A. Clarke +Date: Tue Sep 14 13:13:33 2021 -0500 + + powerpc: Fix unrecognized instruction errors with recent GCC + + Recent binutils commit b25f942e18d6ecd7ec3e2d2e9930eb4f996c258a + changes the behavior of `.machine` directives to override, rather + than augment, the base CPU. This can result in _reduced_ functionality + when, for example, compiling for default machine "power8", but explicitly + asking for ".machine power5", which loses Altivec instructions. + + In tst-ucontext-ppc64-vscr.c, while the instructions provoking the new + error messages are bracketed by ".machine power5", which is ostensibly + Power ISA 2.03 (POWER5), the POWER5 processor did not support the + VSX subset, so these instructions are not recognized as "power5". + + Error: unrecognized opcode: `vspltisb' + Error: unrecognized opcode: `vpkuwus' + Error: unrecognized opcode: `mfvscr' + Error: unrecognized opcode: `stvx' + + Manually adding the VSX subset via ".machine altivec" is sufficient. + + Reviewed-by: Tulio Magno Quites Machado Filho + (cherry picked from commit 064b475a2e5662b6b3973fabf505eade86e61510) + +diff --git a/sysdeps/powerpc/powerpc64/tst-ucontext-ppc64-vscr.c b/sysdeps/powerpc/powerpc64/tst-ucontext-ppc64-vscr.c +index 28c87fcef72bded6..d3fc4ab589f4752a 100644 +--- a/sysdeps/powerpc/powerpc64/tst-ucontext-ppc64-vscr.c ++++ b/sysdeps/powerpc/powerpc64/tst-ucontext-ppc64-vscr.c +@@ -50,6 +50,7 @@ do_test (void) + /* Set SAT bit in VSCR register. */ + asm volatile (".machine push;\n" + ".machine \"power5\";\n" ++ ".machine altivec;\n" + "vspltisb %0,0;\n" + "vspltisb %1,-1;\n" + "vpkuwus %0,%0,%1;\n" diff --git a/glibc-upstream-2.34-72.patch b/glibc-upstream-2.34-72.patch new file mode 100644 index 0000000..548e54e --- /dev/null +++ b/glibc-upstream-2.34-72.patch @@ -0,0 +1,377 @@ +commit 73558ffe841cf4c60ccb4c71cf6dcebf84f2b736 +Author: Joseph Myers +Date: Wed Nov 10 15:21:19 2021 +0000 + + Update syscall lists for Linux 5.15 + + Linux 5.15 has one new syscall, process_mrelease (and also enables the + clone3 syscall for RV32). It also has a macro __NR_SYSCALL_MASK for + Arm, which is not a syscall but matches the pattern used for syscall + macro names. + + Add __NR_SYSCALL_MASK to the names filtered out in the code dealing + with syscall lists, update syscall-names.list for the new syscall and + regenerate the arch-syscall.h headers with build-many-glibcs.py + update-syscalls. + + Tested with build-many-glibcs.py. + + (cherry picked from commit 3387c40a8bbad5faf85b1feb56429cb20feaa640) + +diff --git a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h +index bedab1abbac7f6c1..74a809561a45edc4 100644 +--- a/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/aarch64/arch-syscall.h +@@ -180,6 +180,7 @@ + #define __NR_preadv2 286 + #define __NR_prlimit64 261 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 270 + #define __NR_process_vm_writev 271 + #define __NR_pselect6 72 +diff --git a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h +index 91354ed9e29b8d15..6fc0a23504c3b53d 100644 +--- a/sysdeps/unix/sysv/linux/alpha/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/alpha/arch-syscall.h +@@ -328,6 +328,7 @@ + #define __NR_preadv2 520 + #define __NR_prlimit64 496 + #define __NR_process_madvise 550 ++#define __NR_process_mrelease 558 + #define __NR_process_vm_readv 504 + #define __NR_process_vm_writev 505 + #define __NR_pselect6 463 +diff --git a/sysdeps/unix/sysv/linux/arc/arch-syscall.h b/sysdeps/unix/sysv/linux/arc/arch-syscall.h +index ff5c7eb36db89494..0c66762bf868a992 100644 +--- a/sysdeps/unix/sysv/linux/arc/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/arc/arch-syscall.h +@@ -182,6 +182,7 @@ + #define __NR_preadv2 286 + #define __NR_prlimit64 261 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 270 + #define __NR_process_vm_writev 271 + #define __NR_pselect6_time64 413 +diff --git a/sysdeps/unix/sysv/linux/arm/arch-syscall.h b/sysdeps/unix/sysv/linux/arm/arch-syscall.h +index 5772333ceef6ce59..c41a864c6d530eb0 100644 +--- a/sysdeps/unix/sysv/linux/arm/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/arm/arch-syscall.h +@@ -235,6 +235,7 @@ + #define __NR_preadv2 392 + #define __NR_prlimit64 369 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 376 + #define __NR_process_vm_writev 377 + #define __NR_pselect6 335 +diff --git a/sysdeps/unix/sysv/linux/csky/arch-syscall.h b/sysdeps/unix/sysv/linux/csky/arch-syscall.h +index 4af6d6202f6df7ae..863ffa3e0cd34d3e 100644 +--- a/sysdeps/unix/sysv/linux/csky/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/csky/arch-syscall.h +@@ -190,6 +190,7 @@ + #define __NR_preadv2 286 + #define __NR_prlimit64 261 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 270 + #define __NR_process_vm_writev 271 + #define __NR_pselect6 72 +diff --git a/sysdeps/unix/sysv/linux/filter-nr-syscalls.awk b/sysdeps/unix/sysv/linux/filter-nr-syscalls.awk +index dddfd517471e5cc9..85b017918ef20736 100644 +--- a/sysdeps/unix/sysv/linux/filter-nr-syscalls.awk ++++ b/sysdeps/unix/sysv/linux/filter-nr-syscalls.awk +@@ -22,7 +22,7 @@ + } + + # Skip pseudo-system calls which describe ranges. +-/^#define __NR_(syscalls|arch_specific_syscall|(OABI_)?SYSCALL_BASE) / { ++/^#define __NR_(syscalls|arch_specific_syscall|(OABI_)?SYSCALL_BASE|SYSCALL_MASK) / { + next; + } + /^#define __NR_(|64_|[NO]32_)Linux(_syscalls)? / { +diff --git a/sysdeps/unix/sysv/linux/glibcsyscalls.py b/sysdeps/unix/sysv/linux/glibcsyscalls.py +index 621a202ed75cd725..fe7896eebe74cdf4 100644 +--- a/sysdeps/unix/sysv/linux/glibcsyscalls.py ++++ b/sysdeps/unix/sysv/linux/glibcsyscalls.py +@@ -41,7 +41,7 @@ RE_PSEUDO_SYSCALL = re.compile(r"""__NR_( + (unused|reserved)[0-9]+ + + # Pseudo-system call which describes a range. +- |(syscalls|arch_specific_syscall|(OABI_)?SYSCALL_BASE) ++ |(syscalls|arch_specific_syscall|(OABI_)?SYSCALL_BASE|SYSCALL_MASK) + |(|64_|[NO]32_)Linux(_syscalls)? + )""", re.X) + +diff --git a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h +index b07fc8549de34157..6cf27cd17c1ad0c0 100644 +--- a/sysdeps/unix/sysv/linux/hppa/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/hppa/arch-syscall.h +@@ -222,6 +222,7 @@ + #define __NR_preadv2 347 + #define __NR_prlimit64 321 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 330 + #define __NR_process_vm_writev 331 + #define __NR_pselect6 273 +diff --git a/sysdeps/unix/sysv/linux/i386/arch-syscall.h b/sysdeps/unix/sysv/linux/i386/arch-syscall.h +index 6e4264698b5ce480..2512508b7daa8ed2 100644 +--- a/sysdeps/unix/sysv/linux/i386/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/i386/arch-syscall.h +@@ -254,6 +254,7 @@ + #define __NR_preadv2 378 + #define __NR_prlimit64 340 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 347 + #define __NR_process_vm_writev 348 + #define __NR_prof 44 +diff --git a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h +index 1ca706d7216a3902..4a0c737369217367 100644 +--- a/sysdeps/unix/sysv/linux/ia64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/ia64/arch-syscall.h +@@ -209,6 +209,7 @@ + #define __NR_preadv2 1348 + #define __NR_prlimit64 1325 + #define __NR_process_madvise 1464 ++#define __NR_process_mrelease 1472 + #define __NR_process_vm_readv 1332 + #define __NR_process_vm_writev 1333 + #define __NR_pselect6 1294 +diff --git a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h +index 2f10f71f90d225ff..e310eb5075fb22d8 100644 +--- a/sysdeps/unix/sysv/linux/m68k/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/m68k/arch-syscall.h +@@ -243,6 +243,7 @@ + #define __NR_preadv2 377 + #define __NR_prlimit64 339 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 345 + #define __NR_process_vm_writev 346 + #define __NR_pselect6 301 +diff --git a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h +index 0607a4dfa6adaa23..b4ecad010c2a6abf 100644 +--- a/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/microblaze/arch-syscall.h +@@ -253,6 +253,7 @@ + #define __NR_preadv2 393 + #define __NR_prlimit64 370 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 377 + #define __NR_process_vm_writev 378 + #define __NR_prof 44 +diff --git a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h +index 0055eec0b169ba96..7e3d138ba969c57b 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/mips/mips32/arch-syscall.h +@@ -238,6 +238,7 @@ + #define __NR_preadv2 4361 + #define __NR_prlimit64 4338 + #define __NR_process_madvise 4440 ++#define __NR_process_mrelease 4448 + #define __NR_process_vm_readv 4345 + #define __NR_process_vm_writev 4346 + #define __NR_prof 4044 +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h +index 8e8e9f91ccfebfab..7e9e232e5256bc89 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/arch-syscall.h +@@ -221,6 +221,7 @@ + #define __NR_preadv2 6325 + #define __NR_prlimit64 6302 + #define __NR_process_madvise 6440 ++#define __NR_process_mrelease 6448 + #define __NR_process_vm_readv 6309 + #define __NR_process_vm_writev 6310 + #define __NR_pselect6 6264 +diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h +index ebd1545f806564bb..f9e7ef72b0aa1749 100644 +--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/arch-syscall.h +@@ -209,6 +209,7 @@ + #define __NR_preadv2 5321 + #define __NR_prlimit64 5297 + #define __NR_process_madvise 5440 ++#define __NR_process_mrelease 5448 + #define __NR_process_vm_readv 5304 + #define __NR_process_vm_writev 5305 + #define __NR_pselect6 5260 +diff --git a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h +index 2b530b1f88e4c52a..afd73fc1daca1fb4 100644 +--- a/sysdeps/unix/sysv/linux/nios2/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/nios2/arch-syscall.h +@@ -189,6 +189,7 @@ + #define __NR_preadv2 286 + #define __NR_prlimit64 261 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 270 + #define __NR_process_vm_writev 271 + #define __NR_pselect6 72 +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h +index a32984a9c17315ee..0ac2992028eda27e 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/arch-syscall.h +@@ -247,6 +247,7 @@ + #define __NR_preadv2 380 + #define __NR_prlimit64 325 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 351 + #define __NR_process_vm_writev 352 + #define __NR_prof 44 +diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h +index b01e464fb906d632..c890bc644e14fe06 100644 +--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/arch-syscall.h +@@ -231,6 +231,7 @@ + #define __NR_preadv2 380 + #define __NR_prlimit64 325 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 351 + #define __NR_process_vm_writev 352 + #define __NR_prof 44 +diff --git a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h +index 24d0a2c455caa630..cd336d755a42598a 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/riscv/rv32/arch-syscall.h +@@ -16,6 +16,7 @@ + #define __NR_clock_nanosleep_time64 407 + #define __NR_clock_settime64 404 + #define __NR_clone 220 ++#define __NR_clone3 435 + #define __NR_close 57 + #define __NR_close_range 436 + #define __NR_connect 203 +@@ -171,6 +172,7 @@ + #define __NR_preadv2 286 + #define __NR_prlimit64 261 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 270 + #define __NR_process_vm_writev 271 + #define __NR_pselect6_time64 413 +diff --git a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h +index e526c89ae7b285cc..8edd21620bb4ef64 100644 +--- a/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/riscv/rv64/arch-syscall.h +@@ -179,6 +179,7 @@ + #define __NR_preadv2 286 + #define __NR_prlimit64 261 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 270 + #define __NR_process_vm_writev 271 + #define __NR_pselect6 72 +diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h +index d4c7b101b64c010f..1a4873f505765617 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/s390/s390-32/arch-syscall.h +@@ -240,6 +240,7 @@ + #define __NR_preadv2 376 + #define __NR_prlimit64 334 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 340 + #define __NR_process_vm_writev 341 + #define __NR_pselect6 301 +diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h +index bd8c78d7059a0f31..2af4607c1d36d173 100644 +--- a/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/s390/s390-64/arch-syscall.h +@@ -211,6 +211,7 @@ + #define __NR_preadv2 376 + #define __NR_prlimit64 334 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 340 + #define __NR_process_vm_writev 341 + #define __NR_pselect6 301 +diff --git a/sysdeps/unix/sysv/linux/sh/arch-syscall.h b/sysdeps/unix/sysv/linux/sh/arch-syscall.h +index 3b6ac3d084d74638..7b422ce268ba14d0 100644 +--- a/sysdeps/unix/sysv/linux/sh/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/sh/arch-syscall.h +@@ -237,6 +237,7 @@ + #define __NR_preadv2 381 + #define __NR_prlimit64 339 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 365 + #define __NR_process_vm_writev 366 + #define __NR_pselect6 308 +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h +index 35221a707e4d4a7c..77c3cc64f95ea7f3 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/sparc/sparc32/arch-syscall.h +@@ -242,6 +242,7 @@ + #define __NR_preadv2 358 + #define __NR_prlimit64 331 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 338 + #define __NR_process_vm_writev 339 + #define __NR_pselect6 297 +diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h +index 5ba2b2050924df1c..7ad50bc4ad6cef04 100644 +--- a/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/sparc/sparc64/arch-syscall.h +@@ -222,6 +222,7 @@ + #define __NR_preadv2 358 + #define __NR_prlimit64 331 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 338 + #define __NR_process_vm_writev 339 + #define __NR_pselect6 297 +diff --git a/sysdeps/unix/sysv/linux/syscall-names.list b/sysdeps/unix/sysv/linux/syscall-names.list +index fd98893b0e44a606..1a74d090b72f4d61 100644 +--- a/sysdeps/unix/sysv/linux/syscall-names.list ++++ b/sysdeps/unix/sysv/linux/syscall-names.list +@@ -21,8 +21,8 @@ + # This file can list all potential system calls. The names are only + # used if the installed kernel headers also provide them. + +-# The list of system calls is current as of Linux 5.14. +-kernel 5.14 ++# The list of system calls is current as of Linux 5.15. ++kernel 5.15 + + FAST_atomic_update + FAST_cmpxchg +@@ -440,6 +440,7 @@ preadv + preadv2 + prlimit64 + process_madvise ++process_mrelease + process_vm_readv + process_vm_writev + prof +diff --git a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h +index 26d6ac68a651ec98..3ce2a1fcfc1c15f2 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/x86_64/64/arch-syscall.h +@@ -215,6 +215,7 @@ + #define __NR_preadv2 327 + #define __NR_prlimit64 302 + #define __NR_process_madvise 440 ++#define __NR_process_mrelease 448 + #define __NR_process_vm_readv 310 + #define __NR_process_vm_writev 311 + #define __NR_pselect6 270 +diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h +index 36847783f6b91d5e..9e87e89baccc397c 100644 +--- a/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h ++++ b/sysdeps/unix/sysv/linux/x86_64/x32/arch-syscall.h +@@ -208,6 +208,7 @@ + #define __NR_preadv2 1073742370 + #define __NR_prlimit64 1073742126 + #define __NR_process_madvise 1073742264 ++#define __NR_process_mrelease 1073742272 + #define __NR_process_vm_readv 1073742363 + #define __NR_process_vm_writev 1073742364 + #define __NR_pselect6 1073742094 diff --git a/glibc-upstream-2.34-73.patch b/glibc-upstream-2.34-73.patch new file mode 100644 index 0000000..5081674 --- /dev/null +++ b/glibc-upstream-2.34-73.patch @@ -0,0 +1,442 @@ +commit 2fe2af88abd13ae5636881da2e26f461ecb7dfb5 +Author: Florian Weimer +Date: Thu Jan 13 14:59:29 2022 +0100 + + 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 + (cherry picked from commit a78e6a10d0b50d0ca80309775980fc99944b1727) + +diff --git a/config.h.in b/config.h.in +index 458342887e4e9380..790038fec60eb049 100644 +--- a/config.h.in ++++ b/config.h.in +@@ -286,10 +286,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 0327590486c80777..f119e62fc31903b3 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 9e980784bb826463..64ab2cc2c8f9deec 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 8a9911b7acd9e692..39d6a3c13427abb5 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__ diff --git a/glibc.spec b/glibc.spec index 110f94e..00649b0 100644 --- a/glibc.spec +++ b/glibc.spec @@ -148,7 +148,7 @@ end \ Summary: The GNU libc libraries Name: glibc Version: %{glibcversion} -Release: 16%{?dist} +Release: 18%{?dist} # In general, GPLv2+ is used by programs, LGPLv2+ is used for # libraries. @@ -287,6 +287,32 @@ Patch87: glibc-upstream-2.34-51.patch Patch88: glibc-upstream-2.34-52.patch Patch89: glibc-upstream-2.34-53.patch Patch90: glibc-rh1988382.patch +Patch91: glibc-upstream-2.34-54.patch +Patch92: glibc-upstream-2.34-55.patch +Patch93: glibc-upstream-2.34-56.patch +Patch94: glibc-upstream-2.34-57.patch +Patch95: glibc-upstream-2.34-58.patch +Patch96: glibc-upstream-2.34-59.patch +Patch97: glibc-upstream-2.34-60.patch +Patch98: glibc-upstream-2.34-61.patch +Patch99: glibc-upstream-2.34-62.patch +Patch100: glibc-upstream-2.34-63.patch +Patch101: glibc-upstream-2.34-64.patch +Patch102: glibc-upstream-2.34-65.patch +Patch103: glibc-upstream-2.34-66.patch +Patch104: glibc-upstream-2.34-67.patch +Patch105: glibc-upstream-2.34-68.patch +Patch106: glibc-upstream-2.34-69.patch +Patch107: glibc-upstream-2.34-70.patch +Patch108: glibc-upstream-2.34-71.patch +Patch109: glibc-upstream-2.34-72.patch +Patch110: glibc-upstream-2.34-73.patch +Patch111: glibc-rh2032647-1.patch +Patch112: glibc-rh2032647-2.patch +Patch113: glibc-rh2032647-3.patch +Patch114: glibc-rh2032647-4.patch +Patch115: glibc-rh2032647-5.patch +Patch116: glibc-rh2032647-6.patch ############################################################################## # Continued list of core "glibc" package information: @@ -2315,6 +2341,33 @@ fi %files -f compat-libpthread-nonshared.filelist -n compat-libpthread-nonshared %changelog +* Thu Jan 13 2022 Florian Weimer - 2.34-18 +- Backport optimized ELF dependency sorting algorithm (#2032647) + +* Thu Jan 13 2022 Florian Weimer - 2.34-17 +- Sync with upstream branch release/2.34/master, + commit 2fe2af88abd13ae5636881da2e26f461ecb7dfb5 +- i386: Remove broken CAN_USE_REGISTER_ASM_EBP (bug 28771) +- Update syscall lists for Linux 5.15 +- powerpc: Fix unrecognized instruction errors with recent GCC +- timezone: test-case for BZ #28707 +- timezone: handle truncated timezones from tzcode-2021d and later (BZ #28707) +- Fix subscript error with odd TZif file [BZ #28338] +- AArch64: Check for SVE in ifuncs [BZ #28744] +- intl/plural.y: Avoid conflicting declarations of yyerror and yylex +- Linux: Fix 32-bit vDSO for clock_gettime on powerpc32 +- linux: Add sparck brk implementation +- Update sparc libm-test-ulps +- Update hppa libm-test-ulps +- riscv: align stack before calling _dl_init [BZ #28703] +- riscv: align stack in clone [BZ #28702] +- powerpc64[le]: Allocate extra stack frame on syscall.S +- elf: Fix tst-cpu-features-cpuinfo for KVM guests on some AMD systems [BZ #28704] +- nss: Use "files dns" as the default for the hosts database (bug 28700) +- arm: Guard ucontext _rtld_global_ro access by SHARED, not PIC macro +- mips: increase stack alignment in clone to match the ABI +- mips: align stack in clone [BZ #28223] + * Tue Dec 14 2021 Siddhesh Poyarekar - 2.34-16 - Enable PIE by default on all architectures (#1988382)