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.