https://gcc.gnu.org/bugzilla/show_bug.cgi?id=60465
--- Comment #32 from Sergei Trofimovich <slyfox at inbox dot ru> ---
(In reply to Andreas Schwab from comment #31)
> @ltoffx on symbol+addend doesn't make any sense. This computes an offset
> into the GOT, so any addend needs to be added _after_ loading the actual
> symbol address from the GOT.
Aha. That +addend seems to be some sort of hint to assembler how large addend
must be.
The real addend is 992.
The address '$r1 + 163312' points to a relocation of type R_IA64_REL64LSB
itself:
(gdb) print *(void**)($r1 + 163312)
$1 = (void *) 0x380052a60
readelf -a ld.so
...
Relocation section '.rela.dyn' at offset 0xdd0 contains 51 entries:
Offset Info Type Sym. Value Sym. Name +
Addend
...
000000052910 00000000006f R_IA64_REL64LSB 380052a60
(or how objdump shows the same) objdump -r -R ld.so:
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
...
0000000000052910 REL64LSB *ABS*+0x0000000380052a60
That dynamic relocation is expected to be fixed after ld reads all elf header
types, not before (we see crash exactly at elf header read time):
https://sourceware.org/git/?p=glibc.git;a=blob;f=elf/rtld.c;h=52160dfde6be42eba000c4e8136de0d190617270;hb=HEAD
377 /* Figure out the run-time load address of the dynamic linker itself.
*/
378 bootstrap_map.l_addr = elf_machine_load_address ();
379
380 /* Read our own dynamic section and fill in the info array. */
381 bootstrap_map.l_ld = (void *) bootstrap_map.l_addr + elf_machine_dynamic
();
382 elf_get_dynamic_info (&bootstrap_map, NULL);
383
...
392 if (bootstrap_map.l_addr || !
bootstrap_map.l_info[VALIDX(DT_GNU_PRELINKED)])
393 {
394 /* Relocate ourselves so we can do normal function calls and
395 data access using the global offset table. */
396
397 ELF_DYNAMIC_RELOCATE (&bootstrap_map, 0, 0, 0);
398 }
399 bootstrap_map.l_relocated = 1;
400
401 /* Please note that we don't allow profiling of this object and
402 therefore need not test whether we have to allocate the array
403 for the relocation results (as done in dl-reloc.c). */
404
405 /* Now life is sane; we can call functions and access global data.
406 Set up to use the operating system facilities, and find out from
407 the operating system's program loader where to find the program
408 header table in core. Put the rest of _dl_start into a separate
409 function, that way the compiler cannot put accesses to the GOT
410 before ELF_DYNAMIC_RELOCATE. */
Note we crash at line 378 while relocations are processed later(!): at line
397. That's why writing simple selfcontained examples does not make the samples
crash: running the example already has relocations adjusted correctly.
Behaviour started exhibiting itself as constant propagation got smarter and
managed to specialise 'elf_get_dynamic_info ()' for 'elf_get_dynamic_info
(&_rtld_local, ...)' where
_rtld_local._dl_rtld_map.l_info[(0x6ffffeff - dyn->d_tag) + 66]
specialises it to:
addl r14=163312,r1;;
ld8 r14=[r14];;
adds r14=992,r14
Numbers explanation:
printf "0x%x\n" $(( (0x6ffffeff + 66) * 8 + 2520))
# 2520 is offset of '_rtld_local._dl_rtld_map.l_info'
0x3800003e0
# 0x3e0 = 992
large offset to an imm overflowing ${something} and pushes it (+ip offset?) out
to a separate relocation:
DYNAMIC RELOCATION RECORDS
OFFSET TYPE VALUE
...
0000000000052910 REL64LSB *ABS*+0x0000000380052a60
Sounds plausible?
Thus I'd say it's not a gcc/binutils bug and can/should be worked around in
glibc.