问题
I was trying to make a basic printf
example in x86-64 assembly code for OSX, here's my first version:
section .data
msg db 'hello', 0Ah
section .text
extern _printf
global _main
_main:
sub rsp, 8
mov rdi, msg
mov rax, 0
call _printf
add rsp, 8
ret
So this code is moving the absolute address of msg
into rdi
for the first argument to _printf
, and gcc then complains about the lack of position-independent code. The binary still works though:
→ nasm -f macho64 new.asm && gcc -m64 -o new new.o && ./new
ld: warning: PIE disabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _main from new.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
hello
So when I change the code to use RIP-relative addressing, using the [rel ...]
nasm syntax, the warning disappears but the executable now seg faults:
section .data
msg db 'hello', 0Ah
section .text
extern _printf
global _main
_main:
sub rsp, 8
mov rdi, [rel msg]
mov rax, 0
call _printf
add rsp, 8
ret
And when I compile and run it:
→ nasm -f macho64 new.asm && gcc -m64 -o new new.o && ./new
zsh: segmentation fault ./new
Does anyone know what's going wrong?
回答1:
The problem is that the original mov rdi, msg
loaded the memory address of msg
into rdi
at assemble time.
When it was changed to mov rdi, [rel msg]
, this produced code which used the value in msg
as the relative address, as seen when debugging:
Program received signal EXC_BAD_ACCESS, Could not access memory.
Reason: KERN_INVALID_ADDRESS at address: 0x00000a6f6c6c6568
Notice how the address contains the bytes from msg
, 0x00000a<olleh>
.
The correct solution is to use the lea
instruction to load the effective RIP-relative address of msg
at runtime, like so:
lea rdi, [rel msg]
来源:https://stackoverflow.com/questions/12339972/using-rip-relative-addressing-in-osx-x64-assembly