无法从汇编(yasm)代码调用64位Linux上的C标准库函数
我有一个用汇编编写的函数foo,并在
Linux(Ubuntu)64位上用yasm和GCC编译.它只是使用puts()向stdout输出一条消息,它的外观如下:
bits 64 extern puts global foo section .data message: db 'foo() called',0 section .text foo: 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.asm gcc -c foo_main.c -o foo_main.o gcc foo_64_unix.o foo_main.o -o foo ./foo 这是问题所在: 运行程序时,它会打印一条错误消息,并在调用puts期间立即发生段错误: ./foo: Symbol `puts' causes overflow in R_X86_64_PC32 relocation Segmentation 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参考) (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |
- linux-查看服务器内存使用情况(free top)
- Qt中关于QMouseEventbuttons()和QMouseEventbutton()的使用
- linux – ICMP Host Unreachable消息导致火星源数据包
- 在Redhat Enterprise Server上安装python-ldap时解决GCC错误
- linux – 创建heapdumps的替代方案,性能比jmap更高?
- linux – Unix shell的比较
- 杨建:网站加速--Cache为王篇
- linux – 什么会导致“设备未准备好(errno = -16),强制硬复
- c – 使用手册页获取结构定义
- 任务1:Linux Kernel提权(50分)[2019年信息安全管理与评估