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.

Reply via email to