3

https://docs.oracle.com/cd/E23824_01/html/819-0690/chapter6-54839.html#chapter7-2 states:

64–bit SPARC and 64–bit x86 use only Elf64_Rela relocation entries. Thus, the r_addend member serves as the relocation addend. x86 uses only Elf32_Rel relocation entries. The field to be relocated holds the addend.

There exists an Elf64_Rel struct, so why isn't it being used on 64-bit x86 targets? Doesn't using Elf64_Rela only waste space here as the pre-relocation addresses are just ignored (or at least are always 0 from what I've seen in testing)?

Note: r_addend is omitted in Elf64_Rel, not simply unused.

Peter Cordes
  • 328,167
  • 45
  • 605
  • 847
the4naves
  • 333
  • 2
  • 9

1 Answers1

3

There exists an Elf64_Rel struct, so why isn't it being used on 64-bit x86 targets?

On x86_64, there are several possible memory models. By default, the small memory model is used, which doesn't need any 64-bit relocations.

If you compile with -mcmodel=large, then 64-bit relocations will be used.

Employed Russian
  • 199,314
  • 34
  • 295
  • 362
  • 2
    Can you clarify how that explains why `mov eax, [rel foo + 12]` can't use the `rel32` in the machine code in the object file to hold the `+12`, instead using a relocation type that keeps that metadata separately? Is it trying to handle a case like `mov eax, [rel foo + huge_offset]`, where the code is in range of the end of the array, but not of the `foo` symbol itself, so the rel32 field wouldn't be big enough? – Peter Cordes Jun 09 '21 at 00:20
  • 2
    @PeterCordes From what I can tell you're right about the why. Assembling `mov eax, [rel symbol + 0x1122334455667788]` gives `8b 05 00 00 00 00`, disassembled to `mov eax, dword [rip+0x0]` with a relocation entry of `2: symbol+0x1122334455667784`, which clearly can't be put into the rel32. It does seem weird to me that the assembler doesn't do so when possible however. I feel like a bit of space could be saved by storing a list of Elf64_Rela's and a separate list of Elf64_Rel's. – the4naves Jun 09 '21 at 01:15
  • @the4naves: Yeah. It's very rare to ever link an executable (or library) where the symbol+offset is in range (for rel32 or abs32) but the symbol wouldn't be. That would probably only happen with a linker script to put a large-data section before `.text`, and probably with hand-written asm that took advantage of the knowledge that `symbol+2G` would be in range even though `symbol` can't be assumed to be. `gcc -mcmodel=medium` will just assume that any large arrays need to be referenced with 64-bit absolute addresses. – Peter Cordes Jun 09 '21 at 01:25