温馨提示×

linux反汇编怎样定位bug

小樊
45
2026-09-03 09:23:59
栏目: 智能运维

在 Linux 下通过反汇编(disassembly)定位 bug,通常用于:

  • 程序崩溃(segfault / abort)
  • 没有源码或优化后源码不可信
  • 怀疑编译器、内存破坏、栈溢出、调用约定问题

下面按实战流程讲,而不是只列工具。


一、先拿到“案发现场”

1. 确保有调试信息(最好)

gcc -g -O2 -o app app.c

即使没有 -g,也能反汇编,只是可读性差。

2. 崩溃时保存现场

ulimit -c unlimited
./app
# 生成 core 文件

或用 gdb 直接跑:

gdb ./app
run

二、用 gdb 反汇编定位崩溃点

1. 查看崩溃位置

bt

示例:

#0  0x0000000000401145 in func ()
#1  0x0000000000401180 in main ()

2. 反汇编当前函数

disassemble

或只看附近:

disassemble $pc-20, $pc+20

3. 查看寄存器

info registers

重点关注:

  • rip:当前指令
  • rsp / rbp:栈
  • rax / rdi / rsi:参数和返回值

三、典型 bug 的反汇编特征

1. 段错误(SIGSEGV)

常见汇编模式:

mov    (%rax), %rdx   ; 读 rax 指向的内存

如果:

p/x $rax

0x0 或非法地址 → 空指针解引用


2. 栈被破坏(stack corruption)

特征:

  • ret 后跳到奇怪地址
  • rbp 明显不对

查看:

x/10x $rsp

反汇编:

leave
ret

leave 相当于:

mov rsp, rbp
pop rbp

如果 rbp 被覆盖 → 栈溢出


3. 调用约定错误(ABI)

x86-64 参数顺序:

rdi, rsi, rdx, rcx, r8, r9

反汇编中如果:

mov $0x1, %edi
call foo

foo 期望指针 → 参数类型错误


4. 未初始化变量

反汇编中:

mov 0x10(%rbp), %eax

而该位置从没被写 → 未初始化


四、从地址反推源码行(有调试信息)

info line *0x401145

或:

addr2line -e app 0x401145

五、没有 gdb 时:objdump

反汇编整个程序

objdump -d app > app.asm

只反汇编某个函数

objdump -d -j .text app | grep -A50 "<func>:"

混合源码(有 -g)

objdump -S app

六、结合核心转储分析

gdb ./app core

然后:

bt
disassemble
info registers

七、实战定位套路(总结)

  1. 拿到 crash 地址
  2. bt 看调用栈
  3. disassemble 看崩溃指令
  4. 看寄存器 / 内存
  5. 判断是哪种 bug
    • 空指针
    • 越界
    • 栈破坏
    • ABI 错
  6. 回源码确认

八、常见工具清单

工具 用途
gdb 动态调试 + 反汇编
objdump 静态反汇编
nm 符号表
addr2line 地址 → 源码行
strace 系统调用
valgrind 内存错误

如果你有:

  • 具体崩溃信息
  • 某段反汇编代码
  • C 源码

可以直接贴出来,我可以逐条帮你分析是哪一行出的问题

0