https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60465
--- Comment #30 from Sergei Trofimovich <slyfox at inbox dot ru> ---
Aha, got it.
I've factored out GNU_HASH section setup crash into separate
very simple function:
void __attribute__ ((unused, noinline))
do_it_again (struct link_map *l, ElfW(Dyn) *dyn)
{
ElfW(Dyn) **info = l->l_info;
info[1879047935 - dyn->d_tag + 66] = dyn;
}
gcc -O2 specialises this function on 'l=_rtld_local._dl_rtld_map' argument.
Broken code looks as:
Program received signal SIGSEGV, Segmentation fault.
0x200000080000a9f0 in do_it_again (dyn=0x200000080004e710,
l=0x20000008000533f8 <_rtld_local+2456>) at get-dynamic-info.h:42
42 info[1879047935 - dyn->d_tag + 66] = dyn;
(gdb) disassemble
Dump of assembler code for function do_it_again:
0x200000080000a9c0 <+0>: [MMI] ld8 r14=[r32];;
0x200000080000a9c1 <+1>: shladd r15=r14,3,r0
0x200000080000a9c2 <+2>: addl r14=163312,r1;;
0x200000080000a9d0 <+16>: [MMI] ld8 r14=[r14];;
0x200000080000a9d1 <+17>: adds r14=992,r14
0x200000080000a9d2 <+18>: nop.i 0x0;;
0x200000080000a9e0 <+32>: [MMI] nop.m 0x0
0x200000080000a9e1 <+33>: sub r14=r14,r15
0x200000080000a9e2 <+34>: nop.i 0x0;;
=> 0x200000080000a9f0 <+48>: [MIB] st8 [r14]=r32
0x200000080000a9f1 <+49>: nop.i 0x0
0x200000080000a9f2 <+50>: br.ret.sptk.many b0;;
End of assembler dump.
It's a very early setup phase:
(gdb) bt
#0 0x200000080000a9f0 in do_it_again (dyn=0x200000080004e710,
l=0x20000008000533f8 <_rtld_local+2456>)
at get-dynamic-info.h:42
#1 0x200000080000abd0 in do_it (l=0x20000008000533f8 <_rtld_local+2456>) at
get-dynamic-info.h:78
#2 0x200000080000ac20 in elf_get_dynamic_info (temp=0x0,
l=0x20000008000533f8 <_rtld_local+2456>) at get-dynamic-info.h:104
#3 0x200000080000b2a0 in _dl_start (arg=0x60000fffffffb350) at rtld.c:391
#4 0x2000000800001b10 in _start ()
What I don't like here:
'ld' is a static relocatable binary but the specialised code
attempts to write by absolute address stored in ld's memory image:
MEM[ MEM[r1 + 163312]
+ 992
- dyn->d_tag /* absolute address, not r1 relative!*/
] = dyn;
I would expect something in '_start:'
https://sourceware.org/git/?p=glibc.git;a=blob;f=sysdeps/ia64/dl-machine.h;h=57d761e48732cfa5de370e7022eef83ae74a9c65;hb=HEAD#l159
to store current gp(r1) address to make code above work. Or PIC
code not to rely on any relocations like that:
MEM[ r1 /* real PIC */
+ MEM[r1 + 163312]
+ 992
- dyn->d_tag
] = dyn;
Who is expected to setup that 'r1 + 163312' location?