gccassembly64-bitx86-64addressing

Absolute addressing for runtime code replacement in x86_64


I'm currently using some code replace scheme in 32 bit where the code which is moved to another position, reads variables and a class pointer. Since x86_64 does not support absolute addressing I have trouble getting the correct addresses for the variables at the new position of the code. The problem in detail is, that because of rip relative addressing the instruction pointer address is different than at compile time.

So is there a way to use absolute addressing in x86_64 or another way to get addresses of variables not instruction pointer relative?

Something like: leaq variable(%%rax), %%rbx would also help. I only want to have no dependency on the instruction pointer.


Solution

  • Try using the large code model for x86_64. In gcc this can be selected with -mcmodel=large. The compiler will use 64 bit absolute addressing for both code and data.

    You could also add -fno-pic to disallow the generation of position independent code.

    Edit: I built a small test app with -mcmodel=large and the resulting binary contains sequences like

    400b81:       48 b9 f0 30 60 00 00    movabs $0x6030f0,%rcx
    400b88:       00 00 00 
    400b8b:       49 b9 d0 09 40 00 00    movabs $0x4009d0,%r9
    400b92:       00 00 00 
    400b95:       48 8b 39                mov    (%rcx),%rdi
    400b98:       41 ff d1                callq  *%r9
    

    which is a load of an absolute 64 bit immediate (in this case an address) followed by an indirect call or an indirect load. The instruction sequence

    moveabs $variable, %rbx
    addq %rax, %rbx
    

    is the equivalent to a "leaq offset64bit(%rax), %rbx" (which doesn't exist), with some side effects like flag changing etc.