在用 GDB 调试 CSAPP bomblab 时,当反汇编代码稍微具备点规模,例如超过10行,直接翻译为C语言的难度就增加了,此时考虑先找到调用的函数,然后再梳理 if/else/for循环 的执行流。函数体内调用了其他函数,也就是找到带有 call
的汇编指令,人工找还是有点繁琐了。
GDB 支持 Python 扩展, 通过和 ChatGPT 的结对编程, 可以写出函数来实现这一功能:默认仅列出 call 语句,bing保持高亮; 如果带有第二个参数 True
, 则显示全部的反汇编代码,并且 call
之外的汇编不要有高亮。效果如下:
~/.gdbinit
中对应的配置:
python
import gdb
import subprocess
import os
import re
# 定义 ANSI 颜色代码
ANSI_COLOR_BLUE = "\033[34m"
ANSI_COLOR_GREEN = "\033[32m"
ANSI_COLOR_RED = "\033[31m"
ANSI_COLOR_RESET = "\033[0m"
# 定义一个新的GDB命令 filter-calls
class FilterCalls(gdb.Command):
def __init__(self):
super(FilterCalls, self).__init__("filter-calls", gdb.COMMAND_USER)
def invoke(self, arg, from_tty):
# 解析参数
args = gdb.string_to_argv(arg)
if len(args) not in [1, 2]:
raise gdb.GdbError('Usage: filter-calls <function> [True/False]')
# 设置参数
function_name = args[0]
show_all_lines = False
if len(args) == 2:
show_all_lines = args[1].lower() == 'true'
# 创建一个临时文件
tmp_file = subprocess.check_output(["mktemp", "/tmp/gdb-XXXXXX.txt"]).decode('utf-8').strip()
# 重定向GDB的输出到临时文件
gdb.execute("set logging overwrite on")
gdb.execute("set logging file " + tmp_file)
gdb.execute("set logging redirect on")
gdb.execute("set logging on")
gdb.execute("disassemble " + function_name)
gdb.execute("set logging off")
# 读取临时文件并过滤出包含 'call' 的行
with open(tmp_file, 'r') as f:
for line in f:
if 'call' in line:
# 为地址、'call'关键字和函数名添加颜色
colored_line = re.sub(r'(0x[0-9a-f]+)', ANSI_COLOR_BLUE + r'\1' + ANSI_COLOR_RESET, line)
colored_line = re.sub(r'(\bcall\b)', ANSI_COLOR_GREEN + r'\1' + ANSI_COLOR_RESET, colored_line)
colored_line = re.sub(r'(<.*?>)', ANSI_COLOR_RED + r'\1' + ANSI_COLOR_RESET, colored_line)
print(colored_line.strip())
elif show_all_lines:
print(line.strip())
# 删除临时文件
os.remove(tmp_file)
# 注册这个新命令
FilterCalls()
end
为了说明效果,再看一个: