@@ -, +, @@ 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; ... [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;; DYNAMIC RELOCATION RECORDS OFFSET TYPE VALUE ... 0000000000052910 REL64LSB *ABS*+0x0000000380052a60 info[DT_ADDRTAGIDX (dyn->d_tag) + DT_NUM + DT_THISPROCNUM + DT_VERSIONTAGNUM + DT_EXTRANUM + DT_VALNUM] = dyn; _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 --- elf/get-dynamic-info.h | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) --- a/elf/get-dynamic-info.h +++ a/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; } --