assemblylinkerx86-64elfposition-independent-code

ASLR and hard-coded addresses


I wrote the following assembly program (for x86-64 on Linux):

.intel_syntax noprefix
.global _start

.section .text
_start:
    mov rax, offset _start
    ret

I assembled it using GNU as, and in the generated object file, there was a relocation entry in place of offset start.

The type of the relocation entry was R_X86_64_32S with an addend of 0. According to documentation the relocation entry should be replaced with 32-bit value S + A, where S is the symbol value, and A is the addend.

I used GNU ld to produce an executable from the object file. After linking, the relocation entry was resolved (there are no relocation entries in the executable). And in the symbol table of the executable, value of the symbol _start, was the same as vaddr for the text segment in the Program Header Table.

My question is: given ASLR (Address Space Layout Randomization), how can the value of any symbol be known at link-time?


Solution

  • The binary you have built is position-dependent as you have observed. Its memory image is not subject to ASLR, but other mappings such as those of shared libraries loaded into the same process are.

    If you want to build a position-independent executable that can be loaded at any address, replace mov with lea as such:

    lea rax, [rip + _start]
    

    This generates a rip-relative (i.e. position-independent) addressing mode. Then link with -pie to build a position-independent executable.

    See also How to load address of function or label into register