mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-27 03:33:33 +08:00
elf: work around a gcc bug in elf_get_dynamic_info
Since commit 2f056e8a5d
"aarch64: define PI_STATIC_AND_HIDDEN",
building glibc with gcc-8 on aarch64 fails with
/BLD/elf/librtld.os: in function `elf_get_dynamic_info':
/SRC/elf/get-dynamic-info.h:70:(.text+0xad8): relocation truncated to
fit: R_AARCH64_ADR_PREL_PG_HI21 against symbol `_rtld_local' defined
in .data section in /BLD/elf/librtld.os
This is a gcc bug:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=98618
The bug is fixed on gcc-10 and not yet backported. gcc-9 is affected,
but the issue happens to not trigger in glibc, gcc-8 and older seems
to miscompile rtld.os.
Rewriting the affected code in elf_get_dynamic_info seems to make the
issue go away on <= gcc-9.
The change makes the logic a bit clearer too (by separating the index
computation and array update) and drops an older gcc workaround (since
gcc 4.6 is no longer supported).
Reviewed-by: Adhemerval Zanella <adhemerval.zanella@linaro.org>
This commit is contained in:
parent
2ef23b5205
commit
86a4d3fa7d
@ -30,8 +30,6 @@ auto
|
||||
inline void __attribute__ ((unused, always_inline))
|
||||
elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
{
|
||||
ElfW(Dyn) *dyn = l->l_ld;
|
||||
ElfW(Dyn) **info;
|
||||
#if __ELF_NATIVE_CLASS == 32
|
||||
typedef Elf32_Word d_tag_utype;
|
||||
#elif __ELF_NATIVE_CLASS == 64
|
||||
@ -39,39 +37,36 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
|
||||
#endif
|
||||
|
||||
#if !defined RTLD_BOOTSTRAP && !defined STATIC_PIE_BOOTSTRAP
|
||||
if (dyn == NULL)
|
||||
if (l->l_ld == NULL)
|
||||
return;
|
||||
#endif
|
||||
|
||||
info = l->l_info;
|
||||
ElfW(Dyn) **info = l->l_info;
|
||||
|
||||
while (dyn->d_tag != DT_NULL)
|
||||
for (ElfW(Dyn) *dyn = l->l_ld; dyn->d_tag != DT_NULL; dyn++)
|
||||
{
|
||||
d_tag_utype i;
|
||||
|
||||
if ((d_tag_utype) dyn->d_tag < DT_NUM)
|
||||
info[dyn->d_tag] = dyn;
|
||||
i = dyn->d_tag;
|
||||
else if (dyn->d_tag >= DT_LOPROC
|
||||
&& dyn->d_tag < DT_LOPROC + DT_THISPROCNUM)
|
||||
{
|
||||
/* This does not violate the array bounds of l->l_info, but
|
||||
gcc 4.6 on sparc somehow does not see this. */
|
||||
DIAG_PUSH_NEEDS_COMMENT;
|
||||
DIAG_IGNORE_NEEDS_COMMENT (4.6,
|
||||
"-Warray-bounds");
|
||||
info[dyn->d_tag - DT_LOPROC + DT_NUM] = dyn;
|
||||
DIAG_POP_NEEDS_COMMENT;
|
||||
}
|
||||
i = dyn->d_tag - DT_LOPROC + DT_NUM;
|
||||
else if ((d_tag_utype) DT_VERSIONTAGIDX (dyn->d_tag) < DT_VERSIONTAGNUM)
|
||||
info[VERSYMIDX (dyn->d_tag)] = dyn;
|
||||
i = VERSYMIDX (dyn->d_tag);
|
||||
else if ((d_tag_utype) DT_EXTRATAGIDX (dyn->d_tag) < DT_EXTRANUM)
|
||||
info[DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM] = dyn;
|
||||
i = DT_EXTRATAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM;
|
||||
else if ((d_tag_utype) DT_VALTAGIDX (dyn->d_tag) < DT_VALNUM)
|
||||
info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn;
|
||||
i = DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM + DT_EXTRANUM;
|
||||
else if ((d_tag_utype) DT_ADDRTAGIDX (dyn->d_tag) < DT_ADDRNUM)
|
||||
info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
|
||||
++dyn;
|
||||
i = DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
|
||||
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM;
|
||||
else
|
||||
continue;
|
||||
|
||||
info[i] = dyn;
|
||||
}
|
||||
|
||||
#define DL_RO_DYN_TEMP_CNT 8
|
||||
|
Loading…
Reference in New Issue
Block a user