bits 64extern putsglobal foosection .datamessage: db 'foo() called',0section .textfoo: push rbp mov rbp,rsp lea rdi,[rel message] call puts pop rbp ret
它由GCC编译的C程序调用:
extern voID foo();int main() { foo(); return 0;}
构建命令:
yasm -f elf64 foo_64_unix.asmgcc -c foo_main.c -o foo_main.ogcc foo_64_unix.o foo_main.o -o foo./foo
这是问题所在:
运行程序时,它会打印一条错误消息,并在调用puts期间立即发生段错误:
./foo: Symbol `puts' causes overflow in R_X86_64_PC32 relocationSegmentation fault
用objdump反汇编后,我看到调用的地址错误:
0000000000000660 <foo>: 660: 90 nop 661: 55 push %rbp 662: 48 89 e5 mov %rsp,%rbp 665: 48 8d 3d a4 09 20 00 lea 0x2009a4(%rip),%rdi 66c: e8 00 00 00 00 callq 671 <foo+0x11> <-- here 671: 5d pop %rbp 672: c3 retq
(671是下一条指令的地址,不是put的地址)
但是,如果我在C中重写相同的代码,则调用方式会有所不同:
645: e8 c6 fe ff ff callq 510 <puts@plt>
即它引用了plt的投注.
有可能告诉yasm生成类似的代码吗?
解决方法 已删除注释的已清理版本在IIRC中,0xe8 *** 作码后面跟着一个有符号的偏移量,该偏移量将被应用于PC(此时已经前进到下一条指令)以计算分支目标.因此objdump将分支目标解释为0x671.
Yasm正在渲染零,因为它可能会在该偏移上放置一个重定位,这就是它要求加载器在加载期间填充正确的放置偏移量.加载程序在计算reloc时遇到溢出,这可能表示puts与调用的距离比在32位有符号偏移量中表示的更远.因此,加载程序无法修复此指令,并且您会崩溃.
66c:e8 00 00 00 00显示未填充的地址.如果你查看你的reloc表,你应该在0x66d上看到一个reloc.汇编程序使用relocs填充地址/偏移量作为全零值并不罕见.
This page表明YASM有一个WRT指令可以控制.got,.plt等的使用.
根据this page的S9.2.5看起来你可以说CALL把WRT ..plt(假设Yasm使用相同的语法,因为这是一个NASM参考)
总结以上是内存溢出为你收集整理的无法从汇编(yasm)代码调用64位Linux上的C标准库函数全部内容,希望文章能够帮你解决无法从汇编(yasm)代码调用64位Linux上的C标准库函数所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)