Page 1 of 1

elf64 (x86-64) relocation questions

Posted: Fri Feb 20, 2015 12:08 am
by bradbobak
Hi all. So I've started my elf64 relocatable loader. (just loads output files from gcc -c somefile -o load_this.o).
I have a few questions regarding relocation.

This is the reference i've been using.
https://docs.oracle.com/cd/E19120-01/op ... index.html

All entries are of the 'rela' type.

A refers to the addend,
S refers to the location of the symbol being applied.
P refers to the memory location of the relocation (what we are modifying).
P32 is a 32-bit pointer to P
P64 is a 64-bit pointer to P.

Code: Select all

...
{ // R_AMD64_64
  *P64 = S + A;
}
...
{ // R_AMD64_PC32
  *P32 = S + A - P;
}
...
{ // R_AMD64_32
  *P32 = S + A;
}
...
{ // R_AMD64_32S
  *P32 = S + A;
}
Now, these all seem to work, but I know I'm doing something wrong.
R_AMD64_32
The computed value is truncated to 32–bits. The link-editor verifies that the generated value for the relocation zero-extends to the original 64–bit value.

R_AMD64_32S
The computed value is truncated to 32–bits. The link-editor verifies that the generated value for the relocation sign-extends to the original 64–bit value.
I'm just not understanding those 2 relocations. Am I supposed to add (S + A) as a 64-bit value, then shove the bottom 32 bits into *P32 ?
It just doesn't seem right, with the sign-extending and all. Maybe i'm supposed to use a 64-bit value, manipulate, then shove that value into *P64? (where manipulate is result & 0x00000000ffffffff for the R_AMD64_32) and if (result & (1 << 31)) then result |= 0xffffffff00000000 for R_AMD64_32S ?

Any help would be appreciated.

Re: elf64 (x86-64) relocation questions

Posted: Fri Feb 20, 2015 12:30 am
by jnc100
For 32/32S, essentially you do as it says - calculate S + A as a 64 bit value and then truncate it and store it at the location of the relocation. If the relocation is a 32S relocation, the truncated value needs to sign extend to the original 64 bit value. If it is a 32 relocation it needs to zero extend, otherwise you throw an error at load time (the equivalent for the static library technique is for ld to emit an error like 'relocation truncated to fit ...').

The reason there are two different relocation types is to support the way amd64 register loads work. The mov r/m64, imm32 instruction (and others e.g. add/sub/and etc that use 32 bit immediates) zero extend the value loaded, whereas 32 bit displacements following ModR/M bytes sign extend the value. This is important when compiling with the kernel code model, for example, which makes heavy use of the -2GiB to 0 portion of the address space (and allows constructs like mov rax, [-0x1000]).

I suggest you reference the official ELF docs though (rather than the oracle web site - they define some extensions which are not universally supported). Particularly you would want the ELF64 generic document and the SysV ABI amd64 processor supplement (and possibly the original 32 bit ELF one too just for a general overview).

Regards,
John.

Re: elf64 (x86-64) relocation questions

Posted: Fri Feb 20, 2015 12:53 am
by bradbobak
Thank you. My elf loader now verifies.