汇编 rbp_如何生成干净可阅读的汇编代码

欢迎点击上方蓝色“泰晓科技”关注我们5f1442a0ccf565be5e6cb0c2daec94ec.png

80d8bbd068337da0e5a371a3309a3acc.png

图片来源自网络

新版 gcc 默认开启了几个选项,导致学习汇编语言,尤其是对刚入门的同学,感觉很难。

以如下代码为例:

 1$ cat demo.c
2#include 
3
4int main(void) 5{
6    int i;
7    char buffer[64];
8
9    i = 1;
10    buffer[0] = 'a';
11
12    return 0;
13}

下面这条指令可以生成比较干净简洁的代码:

1$ gcc -fno-stack-protector -fomit-frame-pointer -fno-asynchronous-unwind-tables -S demo.c

结果如下:

 1$ cat demo.s
2    .file   "demo.c"
3    .text
4    .globl  main
5    .type   main, @function
6main:
7    movl    $1, -4(%rsp)
8    movb    $97, -80(%rsp)
9    movl    $0, %eax
10    ret
11    .size   main, .-main
12    .ident  "GCC: (Ubuntu 8.3.0-16ubuntu3~16.04) 8.3.0"
13    .section    .note.GNU-stack,"",@progbits

加个 -m32 参数就可以生成 32 位的:

 1$ gcc -fno-stack-protector -fomit-frame-pointer -fno-asynchronous-unwind-tables -m32 -S demo.c
2$ cat demo.s
3    .file   "demo.c"
4    .text
5    .globl  main
6    .type   main, @function
7main:
8    subl    $80, %esp
9    movl    $1, 76(%esp)
10    movb    $97, 12(%esp)
11    movl    $0, %eax
12    addl    $80, %esp
13    ret
14    .size   main, .-main
15    .ident  "GCC: (Ubuntu 8.3.0-16ubuntu3~16.04) 8.3.0"
16    .section    .note.GNU-stack,"",@progbits

稍微做个解释:

  • -fno-stack-protector:去掉 stack 保护,stack protector 用于检查 stack 是否被踩

  • -fomit-frame-pointer:不用 fp 寄存器 rbp/ebp,直接用 stack 寄存器 rsp/esp 就好了

  • -fno-asynchronous-unwind-tables:消除 .eh_frame section

.eh_frame 是 DWARF-based unwinding 用来实现 backtrace(), __attribute__((__cleanup__(f))), __buildtin_return_address(n), pthread_cleanup_push 等,具体请参考 “assembly - Why GCC compiled C program needs .eh_frame…”(https://stackoverflow.com/questions/26300819/why-gcc-compiled-c-program-needs-eh-frame-section)。现在无论是否用到这些功能,gcc 都加了 .eh_frame,所以不用的时候直接删除掉也无妨。

另外,Stack Protector 不是看上去的那么强大,从原理上看,如果刚好跳过了预设了值的位置去踩的话,Stack Protector 其实是检测不出来的,当然,有总比没有好。

下面这种是可以检测出来的:

 1$ cat demo.c
2#include 
3
4int main(void) 5{
6    char buffer[2];
7    int i;
8
9    i = 1;
10    buffer[0] = 'a';
11
12    buffer[3] = 'b';
13
14    printf("hello.world");
15
16    return 0;
17}

编译和运行,确保可以生成 coredump:

1$ gcc -o demo demo.c
2$ ulimit -c unlimited
3$ ./demo
4*** stack smashing detected ***: ./demo terminated
5hello.worldAborted (core dumped)

用 gdb 分析 coredump:

 1$ gdb demo core
2[New LWP 89783]
3Core was generated by `./demo'.
4Program terminated with signal SIGABRT, Aborted.
5#0  0x00007f76507fc428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
654    ../sysdeps/unix/sysv/linux/raise.c: No such file or directory.
7(gdb) bt
8#0  0x00007f76507fc428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
9#1  0x00007f76507fe02a in __GI_abort () at abort.c:89
10#2  0x00007f765083e7ea in __libc_message (do_abort=do_abort@entry=1,
11    fmt=fmt@entry=0x7f765095649f "*** %s ***: %s terminated\n") at ../sysdeps/posix/libc_fatal.c:175
12#3  0x00007f76508e015c in __GI___fortify_fail (msg=>optimized out"stack smashing detected")
13    at fortify_fail.c:37
14#4  0x00007f76508e0100 in __stack_chk_fail () at stack_chk_fail.c:28
15#5  0x00000000004005c0 in main ()
16(gdb)

可以粗略定位到有 Stack Overflow 的函数,但不能定位到具体哪一行踩了数据。

本文的例子汇整在 Linux Lab: examples/c/hello(https://gitee.com/tinylab/linux-lab/tree/master/examples/c/hello)。

注:由于微信公众号无法在正文中嵌入外部链接,所以这里的文章为增强阅读体验移去了部分外部链接。如果您希望获取正文中的外部链接请移步本文文末左下方点击 “”。


4dcd10a365794b439355a284cb51020e.png

上课啦!上课啦!

近日,泰晓科技与阅码场强强联合,首度推出程序员自我修养之 「360° 剖析 Linux ELF」在线视频课程。如果您想进一步提升自己的实力,掌握更多有关 Linux 环境下和程序编译、链接、运行的底层奥秘,欢迎点击  "课程介绍"  进入相关页面了解更多讯息。

b94d1a360fff566f6a938e9e8730084b.png


5f1442a0ccf565be5e6cb0c2daec94ec.png文末有红包5f1442a0ccf565be5e6cb0c2daec94ec.png

632a268501eac7878c2b7f494b9a9501.png

“泰晓科技”开通“Linux 知识星球”啦!  为答谢读者的关心,星主奉上免费体验卡一张,可以多人使用,也欢迎转赠给周边的朋友。

bdacf0cecf6fde598797eb72f229f37f.png


0e9f20c8553b3cd637043fb5e0120843.png

045ad0ae2ad0bd08648e7d68c21be1be.png关注“泰晓科技”!点“在看”

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值