指向错误地址的位置无关代码
Position Independent Code pointing to wrong address
我有一个用 NASM(2.11.08) 编写的针对 macho64 架构的小示例程序。我是 运行 OSX 10.10.3:
bits 64
section .data
msg1 db 'Message One', 10, 0
msg1len equ $-msg1
msg2 db 'Message Two', 10, 0
msg2len equ $-msg2
section .text
global _main
extern _printf
_main:
sub rsp, 8 ; align
lea rdi, [rel msg1]
xor rax, rax
call _printf
lea rdi, [rel msg2]
xor rax, rax
call _printf
add rsp, 8
ret
我正在使用以下命令行进行编译和链接:
/usr/local/bin/nasm -f macho64 test2.s
ld -macosx_version_min 10.10.0 -lSystem -o test2 test2.o
当我在 test2 可执行文件上进行对象转储时,这是相关的片段(如果我错了,我可以 post 更多!):
0000000000001fb7 <_main>:
1fb7: 48 83 ec 08 sub [=12=]x8,%rsp
1fbb: 48 8d 3d 56 01 00 00 lea 0x156(%rip),%rdi # 2118 <msg2+0xf3>
1fc2: 48 31 c0 xor %rax,%rax
1fc5: e8 14 00 00 00 callq 1fde <_printf$stub>
1fca: 48 8d 3d 54 00 00 00 lea 0x54(%rip),%rdi # 2025 <msg2>
1fd1: 48 31 c0 xor %rax,%rax
1fd4: e8 05 00 00 00 callq 1fde <_printf$stub>
1fd9: 48 83 c4 08 add [=12=]x8,%rsp
1fdd: c3 retq
...
0000000000002018 <msg1>:
0000000000002025 <msg2>:
最后,输出:
$ ./test2
Message Two
$
我的问题是,msg1 怎么了?
我假设未打印 msg1,因为 0x14f(%rip)
不是正确的地址(只是空值)。
为什么 lea edi, [rel msg2]
指向正确的地址,而 lea edi, [rel msg1]
指向 msg2 之后的 NULL?
看起来 0x14f(%rip)
偏移正好超出 msg1 在内存中的位置 0x100(在这个问题的许多测试中都是如此)。
我在这里错过了什么?
编辑:最后出现在 .data 部分的消息(msg1 或 msg2)是唯一打印的消息。
关于 Mach-o ABI 的 IDK,但如果它与 SystemV x86-64 ABI GNU/Linux 使用的相同,那么我认为你的问题是你需要清除 eax
来告诉可变参数函数,如 printf
,FP 为零。
另外,lea rdi, [rel msg1]
会是更好的选择。就目前而言,您的代码仅在虚拟地址 space 的低 32 位内与位置无关,因为您正在截断指向 32 位的指针。
看来 NASM 有一个错误。同样的问题再次出现:。在那里,OP 确认数据存在,但标签错误,并希望向上游报告。
我有一个用 NASM(2.11.08) 编写的针对 macho64 架构的小示例程序。我是 运行 OSX 10.10.3:
bits 64
section .data
msg1 db 'Message One', 10, 0
msg1len equ $-msg1
msg2 db 'Message Two', 10, 0
msg2len equ $-msg2
section .text
global _main
extern _printf
_main:
sub rsp, 8 ; align
lea rdi, [rel msg1]
xor rax, rax
call _printf
lea rdi, [rel msg2]
xor rax, rax
call _printf
add rsp, 8
ret
我正在使用以下命令行进行编译和链接:
/usr/local/bin/nasm -f macho64 test2.s
ld -macosx_version_min 10.10.0 -lSystem -o test2 test2.o
当我在 test2 可执行文件上进行对象转储时,这是相关的片段(如果我错了,我可以 post 更多!):
0000000000001fb7 <_main>:
1fb7: 48 83 ec 08 sub [=12=]x8,%rsp
1fbb: 48 8d 3d 56 01 00 00 lea 0x156(%rip),%rdi # 2118 <msg2+0xf3>
1fc2: 48 31 c0 xor %rax,%rax
1fc5: e8 14 00 00 00 callq 1fde <_printf$stub>
1fca: 48 8d 3d 54 00 00 00 lea 0x54(%rip),%rdi # 2025 <msg2>
1fd1: 48 31 c0 xor %rax,%rax
1fd4: e8 05 00 00 00 callq 1fde <_printf$stub>
1fd9: 48 83 c4 08 add [=12=]x8,%rsp
1fdd: c3 retq
...
0000000000002018 <msg1>:
0000000000002025 <msg2>:
最后,输出:
$ ./test2
Message Two
$
我的问题是,msg1 怎么了?
我假设未打印 msg1,因为 0x14f(%rip)
不是正确的地址(只是空值)。
为什么 lea edi, [rel msg2]
指向正确的地址,而 lea edi, [rel msg1]
指向 msg2 之后的 NULL?
看起来 0x14f(%rip)
偏移正好超出 msg1 在内存中的位置 0x100(在这个问题的许多测试中都是如此)。
我在这里错过了什么?
编辑:最后出现在 .data 部分的消息(msg1 或 msg2)是唯一打印的消息。
关于 Mach-o ABI 的 IDK,但如果它与 SystemV x86-64 ABI GNU/Linux 使用的相同,那么我认为你的问题是你需要清除 eax
来告诉可变参数函数,如 printf
,FP 为零。
另外,lea rdi, [rel msg1]
会是更好的选择。就目前而言,您的代码仅在虚拟地址 space 的低 32 位内与位置无关,因为您正在截断指向 32 位的指针。
看来 NASM 有一个错误。同样的问题再次出现: