在 Linux 下通过反汇编(disassembly)定位 bug,通常用于:
下面按实战流程讲,而不是只列工具。
gcc -g -O2 -o app app.c
即使没有 -g,也能反汇编,只是可读性差。
ulimit -c unlimited
./app
# 生成 core 文件
或用 gdb 直接跑:
gdb ./app
run
bt
示例:
#0 0x0000000000401145 in func ()
#1 0x0000000000401180 in main ()
disassemble
或只看附近:
disassemble $pc-20, $pc+20
info registers
重点关注:
rip:当前指令rsp / rbp:栈rax / rdi / rsi:参数和返回值常见汇编模式:
mov (%rax), %rdx ; 读 rax 指向的内存
如果:
p/x $rax
是 0x0 或非法地址 → 空指针解引用
特征:
ret 后跳到奇怪地址rbp 明显不对查看:
x/10x $rsp
反汇编:
leave
ret
leave 相当于:
mov rsp, rbp
pop rbp
如果 rbp 被覆盖 → 栈溢出
x86-64 参数顺序:
rdi, rsi, rdx, rcx, r8, r9
反汇编中如果:
mov $0x1, %edi
call foo
但 foo 期望指针 → 参数类型错误
反汇编中:
mov 0x10(%rbp), %eax
而该位置从没被写 → 未初始化
info line *0x401145
或:
addr2line -e app 0x401145
objdump -d app > app.asm
objdump -d -j .text app | grep -A50 "<func>:"
objdump -S app
gdb ./app core
然后:
bt
disassemble
info registers
| 工具 | 用途 |
|---|---|
| gdb | 动态调试 + 反汇编 |
| objdump | 静态反汇编 |
| nm | 符号表 |
| addr2line | 地址 → 源码行 |
| strace | 系统调用 |
| valgrind | 内存错误 |
如果你有:
可以直接贴出来,我可以逐条帮你分析是哪一行出的问题。