This is what the System V ABI specifies:
R_X86_64_64 | S + A (ie Symbol value + Addend)
I assembled this shared object and PIE executable:
; PIE executable
global _start
extern msg
section .text
_start:
mov rdi, 1 ; stdout fd
mov rsi, msg
mov rdx, 9 ; 8 chars + newline
mov rax, 1 ; write syscall
syscall
xor rdi, rdi ; return code 0
mov rax, 60 ; exit syscall
syscall
; shared object
global msg:data msg.end-msg
section .data
msg: db "hi there", 10
.end:
When performing readelf
on the PIE executable, in the .rela.dyn
I get these relocation entries:
000000001007 000100000001 R_X86_64_64 0000000000003000 msg + 0
000000003000 000100000005 R_X86_64_COPY 0000000000003000 msg + 00
As I understand it:
R_X86_64_64
performs the relocation inside the.text
section – it changes the operand (which is located at offset0x1007
in mem) to the value of the specified symbol (in this case,0x3000
)R_X86_64_COPY
tells the dynamic linker to look for the dynamic symbol in the shared object, and then copy the value of the dynamic symbol to address specified by the symbol (in this case 0x3000) + the base address the object was loaded at
Now if I apply the R_X86_64_64
relocation the way the ABI specified, I will just get 0x3000
as msg
‘s address which is obviously incorrect! Shouldn’t I add load base address here too?
Is there something I’m missing?
Thanks in advance
I did not really understand what you mean by adding the base address to the symbol value. You want to somehow reconstruct what things may look like on memory ? The Symbol value (S
) is defined by the dynamic linker when relocating your module; so 0x3000
is the offset added to the image’s base address to make the new symbol’s value when relocating.
Anyway, whenever the dynamic linker finds a R_X86_64_COPY
, it copies the object’s data into an uninitialized address, belonging to an uninitialized section like .BSS in the main module. Your R_X86_64_64
reference is then relocated by setting it to the uninitialized address within your main module, which has been already initialized by the linker; therefore, your R_X86_64_64
is NOT going to be directly set to the object’s address in the other module, but to copied version; it will be set to the absolute address of the copied object.
6