zoukankan      html  css  js  c++  java
  • 如何生成干净可阅读的汇编代码

    转载:如何生成干净可阅读的汇编代码 - 泰晓科技 (tinylab.org)

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

    以如下代码为例:

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

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

    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
    6. main:
    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
    7. main:
    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…。现在无论是否用到这些功能,gcc 都加了 .eh_frame,所以不用的时候直接删除掉也无妨。

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

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

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

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

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

    用 gdb 分析 coredump:

    1. $ gdb demo core
    2. [New LWP 89783]
    3. Core was generated by `./demo'.
    4. Program terminated with signal SIGABRT, Aborted.
    5. #0 0x00007f76507fc428 in __GI_raise (sig=sig@entry=6) at ../sysdeps/unix/sysv/linux/raise.c:54
    6. 54 ../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 ") at ../sysdeps/posix/libc_fatal.c:175
    12. #3 0x00007f76508e015c in __GI___fortify_fail (msg=&lt;optimized out&gt;, msg@entry=0x7f7650956481 "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 的函数,但不能定位到具体哪一行踩了数据。

    参考:gcc栈溢出保护机制:stack-protector - ArnoldLu - 博客园 (cnblogs.com)

  • 相关阅读:
    nmake不是内部或外部命令,也不是可运行的程序
    MinGW下载和安装教程
    Qt接单
    C++ web 框架
    原型链
    ssh: Could not resolve hostname的一种解决方案
    oracle客户端安装配置
    linux安装go
    golang 为什么结构体方法要写成指针传递
    traceback模块
  • 原文地址:https://www.cnblogs.com/zhiminyu/p/14451157.html
Copyright © 2011-2022 走看看