mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-23 09:43:32 +08:00
elf: Support DT_RELR relative relocation format
Adapted from https://sourceware.org/pipermail/libc-alpha/2022-April/138085.html ([PATCH v11 0/7] Support DT_RELR relative relocation format), which is expected to be included in glibc 2.36. glibc 2.35 has a fair amount of rtld changes to avoid nested functions (https://sourceware.org/PR27220). This patch is carefully crafted to make the minimal changes. Notebly, this commit * works around b/208156916 by not bumping DT_NUM. DT_RELR and DT_RELRSZ take the l_info slots at DT_VERSYM+1 and DT_VERSYM+2. * avoids changes to include/link.h * removes the time travel compatibility check (error if DT_RELR is used without GLIBC_ABI_DT_RELR version need). This needs link.h change and the detected case cannot happen if we correctly use -Wl,-z,pack-relative-relocs.
This commit is contained in:
parent
d3c732cb43
commit
da683b1f10
75
configure
vendored
75
configure
vendored
@ -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
|
||||
@ -5908,12 +5899,46 @@ $as_echo "$libc_linker_feature" >&6; }
|
||||
{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for linker that supports -z start-stop-gc" >&5
|
||||
$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; }
|
||||
|
@ -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],
|
||||
|
91
elf/Makefile
91
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 $@
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
15
elf/elf.h
15
elf/elf.h
@ -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 */
|
||||
|
@ -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);
|
||||
}
|
||||
|
46
elf/tst-relr-mod2.c
Normal file
46
elf/tst-relr-mod2.c
Normal file
@ -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;
|
||||
}
|
49
elf/tst-relr-mod3a.c
Normal file
49
elf/tst-relr-mod3a.c
Normal file
@ -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;
|
||||
}
|
22
elf/tst-relr-mod3b.c
Normal file
22
elf/tst-relr-mod3b.c
Normal file
@ -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)
|
||||
{
|
||||
}
|
19
elf/tst-relr-mod4a.c
Normal file
19
elf/tst-relr-mod4a.c
Normal file
@ -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"
|
19
elf/tst-relr-mod4b.c
Normal file
19
elf/tst-relr-mod4b.c
Normal file
@ -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"
|
3
elf/tst-relr-mod4b.map
Normal file
3
elf/tst-relr-mod4b.map
Normal file
@ -0,0 +1,3 @@
|
||||
DT_RELR {
|
||||
global: bar;
|
||||
};
|
1
elf/tst-relr-pie.c
Normal file
1
elf/tst-relr-pie.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-relr.c"
|
65
elf/tst-relr.c
Normal file
65
elf/tst-relr.c
Normal file
@ -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>
|
27
elf/tst-relr2.c
Normal file
27
elf/tst-relr2.c
Normal file
@ -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>
|
27
elf/tst-relr3.c
Normal file
27
elf/tst-relr3.c
Normal file
@ -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>
|
1
elf/tst-relr4.c
Normal file
1
elf/tst-relr4.c
Normal file
@ -0,0 +1 @@
|
||||
#include "tst-relr3.c"
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user