扩展 GDB – 高亮显示反汇编中的 call 语句

在用 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 = "33[34m"
ANSI_COLOR_GREEN = "33[32m"
ANSI_COLOR_RED = "33[31m"
ANSI_COLOR_RESET = "33[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'(call)', 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

为了说明效果,再看一个:
在这里插入图片描述