diff options
-rwxr-xr-x | configure | 75 | ||||
-rw-r--r-- | configure.ac | 5 | ||||
-rw-r--r-- | elf/Makefile | 91 | ||||
-rw-r--r-- | elf/Versions | 5 | ||||
-rw-r--r-- | elf/dynamic-link.h | 42 | ||||
-rw-r--r-- | elf/elf.h | 15 | ||||
-rw-r--r-- | elf/get-dynamic-info.h | 26 | ||||
-rw-r--r-- | elf/tst-relr-mod2.c | 46 | ||||
-rw-r--r-- | elf/tst-relr-mod3a.c | 49 | ||||
-rw-r--r-- | elf/tst-relr-mod3b.c | 22 | ||||
-rw-r--r-- | elf/tst-relr-mod4a.c | 19 | ||||
-rw-r--r-- | elf/tst-relr-mod4b.c | 19 | ||||
-rw-r--r-- | elf/tst-relr-mod4b.map | 3 | ||||
-rw-r--r-- | elf/tst-relr-pie.c | 1 | ||||
-rw-r--r-- | elf/tst-relr.c | 65 | ||||
-rw-r--r-- | elf/tst-relr2.c | 27 | ||||
-rw-r--r-- | elf/tst-relr3.c | 27 | ||||
-rw-r--r-- | elf/tst-relr4.c | 1 | ||||
-rw-r--r-- | scripts/versions.awk | 7 |
19 files changed, 511 insertions, 34 deletions
@@ -730,7 +730,6 @@ infodir docdir oldincludedir includedir -runstatedir localstatedir sharedstatedir sysconfdir @@ -844,7 +843,6 @@ datadir='${datarootdir}' sysconfdir='${prefix}/etc' sharedstatedir='${prefix}/com' localstatedir='${prefix}/var' -runstatedir='${localstatedir}/run' includedir='${prefix}/include' oldincludedir='/usr/include' docdir='${datarootdir}/doc/${PACKAGE_TARNAME}' @@ -1097,15 +1095,6 @@ do | -silent | --silent | --silen | --sile | --sil) silent=yes ;; - -runstatedir | --runstatedir | --runstatedi | --runstated \ - | --runstate | --runstat | --runsta | --runst | --runs \ - | --run | --ru | --r) - ac_prev=runstatedir ;; - -runstatedir=* | --runstatedir=* | --runstatedi=* | --runstated=* \ - | --runstate=* | --runstat=* | --runsta=* | --runst=* | --runs=* \ - | --run=* | --ru=* | --r=*) - runstatedir=$ac_optarg ;; - -sbindir | --sbindir | --sbindi | --sbind | --sbin | --sbi | --sb) ac_prev=sbindir ;; -sbindir=* | --sbindir=* | --sbindi=* | --sbind=* | --sbin=* \ @@ -1243,7 +1232,7 @@ fi for ac_var in exec_prefix prefix bindir sbindir libexecdir datarootdir \ datadir sysconfdir sharedstatedir localstatedir includedir \ oldincludedir docdir infodir htmldir dvidir pdfdir psdir \ - libdir localedir mandir runstatedir + libdir localedir mandir do eval ac_val=\$$ac_var # Remove trailing slashes. @@ -1396,7 +1385,6 @@ Fine tuning of the installation directories: --sysconfdir=DIR read-only single-machine data [PREFIX/etc] --sharedstatedir=DIR modifiable architecture-independent data [PREFIX/com] --localstatedir=DIR modifiable single-machine data [PREFIX/var] - --runstatedir=DIR modifiable per-process data [LOCALSTATEDIR/run] --libdir=DIR object code libraries [EPREFIX/lib] --includedir=DIR C header files [PREFIX/include] --oldincludedir=DIR C header files for non-gcc [/usr/include] @@ -5879,22 +5867,25 @@ fi $as_echo_n "checking for linker that supports -z execstack... " >&6; } libc_linker_feature=no if test x"$gnu_ld" = x"yes"; then - cat > conftest.c <<EOF + libc_linker_check=`$LD -v --help 2>/dev/null | grep "\-z execstack"` + if test -n "$libc_linker_check"; then + cat > conftest.c <<EOF int _start (void) { return 42; } EOF - if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp - -Wl,-z,execstack -nostdlib -nostartfiles - -fPIC -shared -o conftest.so conftest.c - 1>&5' + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,-z,execstack -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 (eval $ac_try) 2>&5 ac_status=$? $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 test $ac_status = 0; }; } - then - libc_linker_feature=yes + then + libc_linker_feature=yes + fi + rm -f conftest* fi - rm -f conftest* fi if test $libc_linker_feature = yes; then libc_cv_z_execstack=yes @@ -5909,11 +5900,45 @@ $as_echo "$libc_linker_feature" >&6; } $as_echo_n "checking for linker that supports -z start-stop-gc... " >&6; } libc_linker_feature=no if test x"$gnu_ld" = x"yes"; then + libc_linker_check=`$LD -v --help 2>/dev/null | grep "\-z start-stop-gc"` + if test -n "$libc_linker_check"; then + cat > conftest.c <<EOF +int _start (void) { return 42; } +EOF + if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp + -Wl,-z,start-stop-gc -nostdlib -nostartfiles + -fPIC -shared -o conftest.so conftest.c + 1>&5' + { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 + (eval $ac_try) 2>&5 + ac_status=$? + $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5 + test $ac_status = 0; }; } + then + libc_linker_feature=yes + fi + rm -f conftest* + fi +fi +if test $libc_linker_feature = yes; then + libc_cv_z_start_stop_gc=yes +else + libc_cv_z_start_stop_gc=no +fi +{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 +$as_echo "$libc_linker_feature" >&6; } +config_vars="$config_vars +have-z-start-stop-gc = $libc_cv_z_start_stop_gc" + +{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z pack-relative-relocs" >&5 +$as_echo_n "checking for linker that supports -z pack-relative-relocs... " >&6; } +libc_linker_feature=no +if test x"$gnu_ld" = x"yes"; then cat > conftest.c <<EOF int _start (void) { return 42; } EOF if { ac_try='${CC-cc} $CFLAGS $CPPFLAGS $LDFLAGS $no_ssp - -Wl,-z,start-stop-gc -nostdlib -nostartfiles + -Wl,-z,pack-relative-relocs -nostdlib -nostartfiles -fPIC -shared -o conftest.so conftest.c 1>&5' { { eval echo "\"\$as_me\":${as_lineno-$LINENO}: \"$ac_try\""; } >&5 @@ -5927,14 +5952,14 @@ EOF rm -f conftest* fi if test $libc_linker_feature = yes; then - libc_cv_z_start_stop_gc=yes + libc_cv_dt_relr=yes else - libc_cv_z_start_stop_gc=no + libc_cv_dt_relr=no fi { $as_echo "$as_me:${as_lineno-$LINENO}: result: $libc_linker_feature" >&5 $as_echo "$libc_linker_feature" >&6; } config_vars="$config_vars -have-z-start-stop-gc = $libc_cv_z_start_stop_gc" +have-dt-relr = $libc_cv_dt_relr" { $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports --no-dynamic-linker" >&5 $as_echo_n "checking for linker that supports --no-dynamic-linker... " >&6; } diff --git a/configure.ac b/configure.ac index b3505fc..b1a1530 100644 --- a/configure.ac +++ b/configure.ac @@ -1354,6 +1354,11 @@ LIBC_LINKER_FEATURE([-z start-stop-gc], [-Wl,-z,start-stop-gc], [libc_cv_z_start_stop_gc=yes], [libc_cv_z_start_stop_gc=no]) LIBC_CONFIG_VAR([have-z-start-stop-gc], [$libc_cv_z_start_stop_gc]) +LIBC_LINKER_FEATURE([-z pack-relative-relocs], + [-Wl,-z,pack-relative-relocs], + [libc_cv_dt_relr=yes], [libc_cv_dt_relr=no]) +LIBC_CONFIG_VAR([have-dt-relr], [$libc_cv_dt_relr]) + LIBC_LINKER_FEATURE([--no-dynamic-linker], [-Wl,--no-dynamic-linker], [libc_cv_no_dynamic_linker=yes], diff --git a/elf/Makefile b/elf/Makefile index 1b9acb5..7b44740 100644 --- a/elf/Makefile +++ b/elf/Makefile @@ -209,6 +209,44 @@ tests-execstack-yes = tst-execstack tst-execstack-needed tst-execstack-prog endif endif endif +ifeq ($(have-dt-relr),yes) +tests += \ + tst-relr \ + tst-relr2 \ + tst-relr3 \ + tst-relr4 \ +# tests +modules-names-dt-relr = \ + tst-relr-mod2 \ + tst-relr-mod3a \ + tst-relr-mod3b \ + tst-relr-mod4a \ + tst-relr-mod4b \ +# modules-names-dt-relr +modules-names += $(modules-names-dt-relr) +# These shared libraries have special build rules. +modules-names-nobuild += $(modules-names-dt-relr) +ifeq ($(have-fpie),yes) +tests += \ + tst-relr-pie \ +# tests +tests-pie += \ + tst-relr-pie \ +# tests-pie +tests-special += \ + $(objpfx)check-tst-relr-pie.out \ +# tests-special +endif +CFLAGS-tst-relr-pie.c += $(pie-ccflag) +LDFLAGS-tst-relr += -Wl,-z,pack-relative-relocs +LDFLAGS-tst-relr-pie += -Wl,-z,pack-relative-relocs +LDFLAGS-tst-relr2 += -Wl,--allow-shlib-undefined +CFLAGS-tst-relr-mod2.c += $(no-stack-protector) +CFLAGS-tst-relr-mod3a.c += $(no-stack-protector) +CFLAGS-tst-relr-mod3b.c += $(no-stack-protector) +CFLAGS-tst-relr-mod4a.c += $(no-stack-protector) +CFLAGS-tst-relr-mod4b.c += $(no-stack-protector) +endif ifeq ($(run-built-tests),yes) tests-special += $(objpfx)tst-leaks1-mem.out \ $(objpfx)tst-leaks1-static-mem.out $(objpfx)noload-mem.out \ @@ -1482,3 +1520,56 @@ $(objpfx)tst-dlopen-offset-comb.so: $(objpfx)tst-dlopen-offset-mod1.so $(objpfx) dd if=$(objpfx)tst-dlopen-offset-mod3.so of=$(objpfx)tst-dlopen-offset-comb.so bs=1024 seek=192 $(objpfx)tst-big-note: $(objpfx)tst-big-note-lib.so + +$(objpfx)check-tst-relr-pie.out: $(objpfx)tst-relr-pie + LC_ALL=C $(OBJDUMP) -p $< \ + | sed -ne '/required from libc.so/,$$ p' \ + | grep GLIBC_ABI_DT_RELR > $@; \ + $(evaluate-test) + +# The test checks if a DT_RELR shared library without DT_NEEDED works as +# intended, so it uses an explicit link rule. +$(objpfx)tst-relr2: $(objpfx)tst-relr-mod2.so +$(objpfx)tst-relr-mod2.so: $(objpfx)tst-relr-mod2.os + $(LINK.o) -nostdlib -nostartfiles -Wl,-z,pack-relative-relocs \ + $(LDFLAGS-soname-fname) \ + -shared -o $@.new $(filter-out $(map-file),$^) + $(call after-link,$@.new) + mv -f $@.new $@ + +# The test checks if a DT_RELR shared library without DT_VERNEED works as +# intended, so it uses an explicit link rule. +$(objpfx)tst-relr3: $(objpfx)tst-relr-mod3a.so +$(objpfx)tst-relr-mod3b.so: $(objpfx)tst-relr-mod3b.os + $(LINK.o) -nostdlib -nostartfiles -Wl,-z,pack-relative-relocs \ + $(LDFLAGS-soname-fname) \ + -shared -o $@.new $(filter-out $(map-file),$^) + $(call after-link,$@.new) + mv -f $@.new $@ + +$(objpfx)tst-relr-mod3a.so: $(objpfx)tst-relr-mod3a.os \ + $(objpfx)tst-relr-mod3b.so + $(LINK.o) -nostdlib -nostartfiles -Wl,-z,pack-relative-relocs \ + $(LDFLAGS-soname-fname) \ + -shared -o $@.new $(filter-out $(map-file),$^) + $(call after-link,$@.new) + mv -f $@.new $@ + +# The test checks if a DT_RELR shared library without libc.so on DT_NEEDED +# works as intended, so it uses an explicit link rule. +$(objpfx)tst-relr4: $(objpfx)tst-relr-mod4a.so +$(objpfx)tst-relr-mod4b.so: $(objpfx)tst-relr-mod4b.os + $(LINK.o) -nostdlib -nostartfiles -Wl,-z,pack-relative-relocs \ + $(LDFLAGS-soname-fname) \ + -Wl,--version-script=tst-relr-mod4b.map \ + -shared -o $@.new $(filter-out $(map-file),$^) + $(call after-link,$@.new) + mv -f $@.new $@ + +$(objpfx)tst-relr-mod4a.so: $(objpfx)tst-relr-mod4a.os \ + $(objpfx)tst-relr-mod4b.so + $(LINK.o) -nostdlib -nostartfiles -Wl,-z,pack-relative-relocs \ + $(LDFLAGS-soname-fname) \ + -shared -o $@.new $(filter-out $(map-file),$^) + $(call after-link,$@.new) + mv -f $@.new $@ diff --git a/elf/Versions b/elf/Versions index 05eba2a..7fa8f67 100644 --- a/elf/Versions +++ b/elf/Versions @@ -20,6 +20,11 @@ libc { __register_frame_info_table_bases; _Unwind_Find_FDE; } %endif + GLIBC_ABI_DT_RELR { + # This symbol is used only for empty version map and will be removed + # by scripts/versions.awk. + __placeholder_only_for_empty_version_map; + } GLIBC_PRIVATE { # functions used in other libraries _dl_addr; diff --git a/elf/dynamic-link.h b/elf/dynamic-link.h index f576d78..e9d7fac 100644 --- a/elf/dynamic-link.h +++ b/elf/dynamic-link.h @@ -128,7 +128,9 @@ elf_machine_lazy_rel (struct link_map *map, __typeof (((ElfW(Dyn) *) 0)->d_un.d_val) nrelative; int lazy; } \ ranges[2] = { { 0, 0, 0, 0 }, { 0, 0, 0, 0 } }; \ \ - if ((map)->l_info[DT_##RELOC]) \ + /* With DT_RELR, DT_RELA/DT_REL can have zero value. */ \ + if ((map)->l_info[DT_##RELOC] != NULL \ + && (map)->l_info[DT_##RELOC]->d_un.d_ptr != 0) \ { \ ranges[0].start = D_PTR ((map), l_info[DT_##RELOC]); \ ranges[0].size = (map)->l_info[DT_##RELOC##SZ]->d_un.d_val; \ @@ -142,6 +144,8 @@ elf_machine_lazy_rel (struct link_map *map, ElfW(Addr) start = D_PTR ((map), l_info[DT_JMPREL]); \ ElfW(Addr) size = (map)->l_info[DT_PLTRELSZ]->d_un.d_val; \ \ + if (ranges[0].start == 0) \ + ranges[0].start = start; \ if (ranges[0].start + ranges[0].size == (start + size)) \ ranges[0].size -= size; \ if (ELF_DURING_STARTUP \ @@ -253,12 +257,48 @@ elf_machine_lazy_rel (struct link_map *map, # define ELF_DYNAMIC_DO_RELA(map, lazy, skip_ifunc, boot_map) /* Nothing to do. */ # endif +/* Google-local: b/208156916. To not bump DT_NUM, use DT_VERSYM+1 for DT_RELR + and DT_VERSYM+2 for DT_RELRSZ. */ +# define ELF_DYNAMIC_DO_RELR(map) \ + do { \ + ElfW(Addr) l_addr = (map)->l_addr, *where = 0; \ + const ElfW(Relr) *r, *end; \ + if (!(map)->l_info[VERSYMIDX (DT_VERSYM + 1)]) \ + break; \ + r = (const ElfW(Relr) *)D_PTR((map), l_info[VERSYMIDX (DT_VERSYM + 1)]); \ + end = (const ElfW(Relr) *)((const char *)r + \ + (map)->l_info[VERSYMIDX (DT_VERSYM + 2)]->d_un.d_val); \ + for (; r < end; r++) \ + { \ + ElfW(Relr) entry = *r; \ + if ((entry & 1) == 0) \ + { \ + where = (ElfW(Addr) *)(l_addr + entry); \ + *where++ += l_addr; \ + } \ + else \ + { \ + for (long i = 0; (entry >>= 1) != 0; i++) \ + if ((entry & 1) != 0) \ + where[i] += l_addr; \ + where += CHAR_BIT * sizeof(ElfW(Relr)) - 1; \ + } \ + } \ + } while (0); + /* This can't just be an inline function because GCC is too dumb to inline functions containing inlines themselves. */ +# ifdef RTLD_BOOTSTRAP +# define DO_RTLD_BOOTSTRAP 1 +# else +# define DO_RTLD_BOOTSTRAP 0 +# endif # define ELF_DYNAMIC_RELOCATE(map, lazy, consider_profile, skip_ifunc, boot_map) \ do { \ int edr_lazy = elf_machine_runtime_setup ((map), (lazy), \ (consider_profile)); \ + if (((map) != &GL(dl_rtld_map) || DO_RTLD_BOOTSTRAP)) \ + ELF_DYNAMIC_DO_RELR (map); \ ELF_DYNAMIC_DO_REL ((map), edr_lazy, skip_ifunc, boot_map); \ ELF_DYNAMIC_DO_RELA ((map), edr_lazy, skip_ifunc, boot_map); \ } while (0) @@ -444,8 +444,9 @@ typedef struct #define SHT_FINI_ARRAY 15 /* Array of destructors */ #define SHT_PREINIT_ARRAY 16 /* Array of pre-constructors */ #define SHT_GROUP 17 /* Section group */ -#define SHT_SYMTAB_SHNDX 18 /* Extended section indeces */ -#define SHT_NUM 19 /* Number of defined types. */ +#define SHT_SYMTAB_SHNDX 18 /* Extended section indices */ +#define SHT_RELR 19 /* RELR relative relocations */ +#define SHT_NUM 20 /* Number of defined types. */ #define SHT_LOOS 0x60000000 /* Start OS-specific. */ #define SHT_GNU_ATTRIBUTES 0x6ffffff5 /* Object attributes. */ #define SHT_GNU_HASH 0x6ffffff6 /* GNU-style hash table. */ @@ -663,6 +664,11 @@ typedef struct Elf64_Sxword r_addend; /* Addend */ } Elf64_Rela; +/* RELR relocation table entry */ + +typedef Elf32_Word Elf32_Relr; +typedef Elf64_Xword Elf64_Relr; + /* How to extract and insert information held in the r_info field. */ #define ELF32_R_SYM(val) ((val) >> 8) @@ -861,6 +867,11 @@ typedef struct #define DT_ENCODING 32 /* Start of encoded range */ #define DT_PREINIT_ARRAY 32 /* Array with addresses of preinit fct*/ #define DT_PREINIT_ARRAYSZ 33 /* size in bytes of DT_PREINIT_ARRAY */ +#define DT_SYMTAB_SHNDX 34 /* Address of SYMTAB_SHNDX section */ +#define DT_RELRSZ 35 /* Total size of RELR relative relocations */ +#define DT_RELR 36 /* Address of RELR relative relocations */ +#define DT_RELRENT 37 /* Size of one RELR relative relocaction */ +/* Google-local: b/208156916. Don't bump DT_NUM. */ #define DT_NUM 34 /* Number used */ #define DT_LOOS 0x6000000d /* Start of OS-specific */ #define DT_HIOS 0x6ffff000 /* End of OS-specific */ diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h index f9c5b84..02ba549 100644 --- a/elf/get-dynamic-info.h +++ b/elf/get-dynamic-info.h @@ -49,7 +49,12 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) while (dyn->d_tag != DT_NULL) { - if ((d_tag_utype) dyn->d_tag < DT_NUM) + /* Google-local: b/208156916. See ELF_DYNAMIC_DO_RELR. */ + if (dyn->d_tag == DT_RELR) + info[VERSYMIDX (DT_VERSYM + 1)] = dyn; + else if (dyn->d_tag == DT_RELRSZ) + info[VERSYMIDX (DT_VERSYM + 2)] = dyn; + else if ((d_tag_utype) dyn->d_tag < DT_NUM) info[dyn->d_tag] = dyn; else if (dyn->d_tag >= DT_LOPROC && dyn->d_tag < DT_LOPROC + DT_THISPROCNUM) @@ -104,16 +109,27 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp) ADJUST_DYN_INFO (DT_PLTGOT); ADJUST_DYN_INFO (DT_STRTAB); ADJUST_DYN_INFO (DT_SYMTAB); + ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM + 1)); /* DT_RELR */ + ADJUST_DYN_INFO (DT_JMPREL); + ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); + ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM + + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM); +# undef ADJUST_DYN_INFO + + /* DT_RELA/DT_REL are mandatory. But they may have zero value if + there is DT_RELR. Don't relocate them if they are zero. */ +# define ADJUST_DYN_INFO(tag) \ + do \ + if (info[tag] != NULL && info[tag]->d_un.d_ptr != 0) \ + info[tag]->d_un.d_ptr += l_addr; \ + while (0) + # if ! ELF_MACHINE_NO_RELA ADJUST_DYN_INFO (DT_RELA); # endif # if ! ELF_MACHINE_NO_REL ADJUST_DYN_INFO (DT_REL); # endif - ADJUST_DYN_INFO (DT_JMPREL); - ADJUST_DYN_INFO (VERSYMIDX (DT_VERSYM)); - ADJUST_DYN_INFO (DT_ADDRTAGIDX (DT_GNU_HASH) + DT_NUM + DT_THISPROCNUM - + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM); # undef ADJUST_DYN_INFO assert (cnt <= DL_RO_DYN_TEMP_CNT); } diff --git a/elf/tst-relr-mod2.c b/elf/tst-relr-mod2.c new file mode 100644 index 0000000..dc0a633 --- /dev/null +++ b/elf/tst-relr-mod2.c @@ -0,0 +1,46 @@ +/* Test for DT_RELR in a shared library without DT_NEEDED. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <array_length.h> + +static int o, x; + +#define ELEMS O O O O O O O O X X X X X X X O O X O O X X X E X E E O X O E +#define E 0, + +#define O &o, +#define X &x, +void *arr[] = { ELEMS }; +#undef O +#undef X + +#define O 1, +#define X 2, +static char val[] = { ELEMS }; + +int +foo (void) +{ + int err = 0; + for (int i = 0; i < array_length (arr); i++) + if (!((arr[i] == 0 && val[i] == 0) + || (arr[i] == &o && val[i] == 1) + || (arr[i] == &x && val[i] == 2))) + err++; + return err; +} diff --git a/elf/tst-relr-mod3a.c b/elf/tst-relr-mod3a.c new file mode 100644 index 0000000..d1621c9 --- /dev/null +++ b/elf/tst-relr-mod3a.c @@ -0,0 +1,49 @@ +/* Test for DT_RELR in a shared library without DT_VERNEED. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <array_length.h> + +static int o, x; + +#define ELEMS O O O O O O O O X X X X X X X O O X O O X X X E X E E O X O E +#define E 0, + +#define O &o, +#define X &x, +void *arr[] = { ELEMS }; +#undef O +#undef X + +#define O 1, +#define X 2, +static char val[] = { ELEMS }; + +extern void bar (void); + +int +foo (void) +{ + int err = 0; + for (int i = 0; i < array_length (arr); i++) + if (!((arr[i] == 0 && val[i] == 0) + || (arr[i] == &o && val[i] == 1) + || (arr[i] == &x && val[i] == 2))) + err++; + bar (); + return err; +} diff --git a/elf/tst-relr-mod3b.c b/elf/tst-relr-mod3b.c new file mode 100644 index 0000000..544cb4b --- /dev/null +++ b/elf/tst-relr-mod3b.c @@ -0,0 +1,22 @@ +/* Test for DT_RELR in a shared library without DT_VERNEED. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +void +bar (void) +{ +} diff --git a/elf/tst-relr-mod4a.c b/elf/tst-relr-mod4a.c new file mode 100644 index 0000000..e1bfebd --- /dev/null +++ b/elf/tst-relr-mod4a.c @@ -0,0 +1,19 @@ +/* Test for DT_RELR in a shared library without libc.so on DT_NEEDED. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include "tst-relr-mod3a.c" diff --git a/elf/tst-relr-mod4b.c b/elf/tst-relr-mod4b.c new file mode 100644 index 0000000..617dff7 --- /dev/null +++ b/elf/tst-relr-mod4b.c @@ -0,0 +1,19 @@ +/* Test for DT_RELR in a shared library without libc.so on DT_NEEDED. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include "tst-relr-mod3b.c" diff --git a/elf/tst-relr-mod4b.map b/elf/tst-relr-mod4b.map new file mode 100644 index 0000000..7f02247 --- /dev/null +++ b/elf/tst-relr-mod4b.map @@ -0,0 +1,3 @@ +DT_RELR { + global: bar; +}; diff --git a/elf/tst-relr-pie.c b/elf/tst-relr-pie.c new file mode 100644 index 0000000..7df0cdb --- /dev/null +++ b/elf/tst-relr-pie.c @@ -0,0 +1 @@ +#include "tst-relr.c" diff --git a/elf/tst-relr.c b/elf/tst-relr.c new file mode 100644 index 0000000..c634ce0 --- /dev/null +++ b/elf/tst-relr.c @@ -0,0 +1,65 @@ +/* Basic tests for DT_RELR. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +#include <link.h> +#include <stdbool.h> +#include <array_length.h> +#include <support/check.h> + +static int o, x; + +#define ELEMS O O O O O O O O X X X X X X X O O X O O X X X E X E E O X O E +#define E 0, + +#define O &o, +#define X &x, +void *arr[] = { ELEMS }; +#undef O +#undef X + +#define O 1, +#define X 2, +static char val[] = { ELEMS }; + +static int +do_test (void) +{ + ElfW(Dyn) *d = _DYNAMIC; + if (d) + { + bool has_relr = false; + for (; d->d_tag != DT_NULL; d++) + if (d->d_tag == DT_RELR) + has_relr = true; + +#if defined __PIE__ || defined __pie__ || defined PIE || defined pie + TEST_VERIFY (has_relr); +#else + TEST_VERIFY (!has_relr); +#endif + } + + for (int i = 0; i < array_length (arr); i++) + TEST_VERIFY ((arr[i] == 0 && val[i] == 0) + || (arr[i] == &o && val[i] == 1) + || (arr[i] == &x && val[i] == 2)); + + return 0; +} + +#include <support/test-driver.c> diff --git a/elf/tst-relr2.c b/elf/tst-relr2.c new file mode 100644 index 0000000..10d77f1 --- /dev/null +++ b/elf/tst-relr2.c @@ -0,0 +1,27 @@ +/* Test for DT_RELR in a shared library without DT_NEEDED. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +extern int foo (void); + +static int +do_test (void) +{ + return foo (); +} + +#include <support/test-driver.c> diff --git a/elf/tst-relr3.c b/elf/tst-relr3.c new file mode 100644 index 0000000..69106cf --- /dev/null +++ b/elf/tst-relr3.c @@ -0,0 +1,27 @@ +/* Test for DT_RELR in a shared library without libc.so on DT_NEEDED. + Copyright (C) 2022 Free Software Foundation, Inc. + This file is part of the GNU C Library. + + The GNU C Library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + The GNU C Library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with the GNU C Library; if not, see + <https://www.gnu.org/licenses/>. */ + +extern int foo (void); + +static int +do_test (void) +{ + return foo (); +} + +#include <support/test-driver.c> diff --git a/elf/tst-relr4.c b/elf/tst-relr4.c new file mode 100644 index 0000000..19a7501 --- /dev/null +++ b/elf/tst-relr4.c @@ -0,0 +1 @@ +#include "tst-relr3.c" diff --git a/scripts/versions.awk b/scripts/versions.awk index a3df316..f4a63f3 100644 --- a/scripts/versions.awk +++ b/scripts/versions.awk @@ -132,8 +132,13 @@ END { closeversion(oldver, veryoldver); veryoldver = oldver; } - printf("%s {\n global:\n", $2) > outfile; oldver = $2; + # Skip the placeholder symbol used only for empty version map. + if ($3 == "__placeholder_only_for_empty_version_map;") { + printf("%s {\n", $2) > outfile; + continue; + } + printf("%s {\n global:\n", $2) > outfile; } printf(" ") > outfile; for (n = 3; n <= NF; ++n) { |