This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
[PATCH] elf/get-dynamic-info.h: fix early GNU_HASH processing on ia64
- From: slyich at gmail dot com
- To: libc-alpha at sourceware dot org, Andreas Schwab <schwab at suse dot de>, Mike Frysinger <vapier at gentoo dot org>, Richard Biener <rguenth at gcc dot gnu dot org>
- Cc: Eric Botcazou <ebotcazou at gcc dot gnu dot org>, Dennis Schridde <devurandom at gmx dot net>, Sergei Trofimovich <siarheit at google dot com>
- Date: Sat, 26 Dec 2015 19:32:05 +0000
- Subject: [PATCH] elf/get-dynamic-info.h: fix early GNU_HASH processing on ia64
- Authentication-results: sourceware.org; auth=none
From: Sergei Trofimovich <siarheit@google.com>
The following code when being
called with l = _rtld_local._dl_rtld_map
info = l->l_info
elf_get_dynamic_info(struct link_map *l,ElfW(Dyn) *dyn) {
...
info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
...
led to generation of the follwoing assembly code:
[MMI] ld8 r14=[r32];; # r14 = dyn->d_tag
shladd r15=r14,3,r0 # r15 = dyn->d_tag * 8
addl r14=163312,r1;; # r14 = gp + @ltoffx(_rtld_local#+0x380000000)
[MMI] ld8 r14=[r14];;
adds r14=992,r14 # r14 = [abs_reloc] + 992
nop.i 0x0;;
[MMI] nop.m 0x0
sub r14=r14,r15
nop.i 0x0;;
[MIB] st8 [r14]=r32 # [[abs_reloc] + 992] = dyn
nop.i 0x0
br.ret.sptk.many b0;;
This 'abs_reloc' is a relocation of R_IA64_REL64LSB type.
objdump -r -R ld.so:
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
...
0000000000052910 REL64LSB *ABS*+0x0000000380052a60
After gcc's preprocessor and constant propagation phase
the code
info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+ DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn;
became equivalent equivalent to:
_rtld_local._dl_rtld_map.l_info[(0x6ffffeff - dyn->d_tag) + 66]
(0x6ffffeff + 66) * 8 + 2520 = 0x3800003e0
# 2520 is offset of '_rtld_local._dl_rtld_map.l_info'
# 0x3e0 = 992
To workaround generation of that huge offset and relocation
I've moved index computation into a separate variable to trick
gcc into simpler code.
Bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60465#c32
Signed-off-by: Sergei Trofimovich <siarheit@google.com>
---
elf/get-dynamic-info.h | 15 +++++++++++++--
1 file changed, 13 insertions(+), 2 deletions(-)
diff --git a/elf/get-dynamic-info.h b/elf/get-dynamic-info.h
index dc8359d..45c51aa 100644
--- a/elf/get-dynamic-info.h
+++ b/elf/get-dynamic-info.h
@@ -66,8 +66,19 @@ elf_get_dynamic_info (struct link_map *l, ElfW(Dyn) *temp)
info[DT_VALTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+ DT_VERSIONTAGNUM + DT_EXTRANUM] = dyn;
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;
+ {
+ /* Use local 'tag_ix' to avoid gcc picking large offset:
+ DT_ADDRTAGIDX (x) = 0x6ffffeff - x
+ which leads gcc to use R_IA64_REL64LSB relocation.
+ We cannot allow it as 'elf_get_dynamic_info' is called
+ before relocations are processed by 'ld.so'.
+ https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60465#c32.
+ */
+ d_tag_utype tag_ix =
+ DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM
+ + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM;
+ info[tag_ix] = dyn;
+ }
++dyn;
}
--
2.6.4