gdb调试python扩展示例
功能为,打印变量的值,包括链表结构体的结构、内容、地址
注册gdb中的command命令
import gdb import gdb.types # gettype &xxxxxx LOGFILE = 'gettype.log' def write_log(msg): f = open(LOGFILE, "a") f.write(msg+'\n') # print(msg) f.close() class GetType(gdb.Command): def __init__(self): super(self.__class__, self).__init__("gettype", gdb.COMMAND_USER) # 注册gettype命令,必须要的 self.address_list = [] def invoke(self, args, from_tty): # python的command命令,必须重写的方法 ''' argv[0] must be a porinter ''' argv = gdb.string_to_argv(args) # 转换gettype命令后跟的参数,以空格为分割从字符串转换成列表 root_varibale_value = gdb.parse_and_eval(argv[0]).dereference() # 上面方法列表的元素只是字符串,这里的才更有意义,返回为gdb.Value的类 self._parse_variable(0, argv[0], root_varibale_value) # 调用我自写的方法 def _parse_variable(self, depth, v_name, v_value): # for write_log space1 = " "*2*depth depth += 1 space2 = " "*2*depth+'-' # process varibale v_type = v_value.type # 功能与get_basic_type差不多,可以自行观察 v_basic_type = gdb.types.get_basic_type(v_type) v_address = v_value.address # write_log to stdout write_log("%s%s:" % (space1, v_name)) write_log("%stype=%s" % (space2, v_type)) write_log("%sbasic_type=%s" % (space2, v_basic_type)) write_log("%saddress=%s" % (space2, v_address)) write_log("%svalue=%s" % (space2, v_value)) if '*' in str(v_basic_type): # The value of the pointer is the address # write_log("debug%svalue=%s" % (space2, v_value)) # write_log("debug%self.address_list=%s" % (space2, self.address_list)) if v_value in self.address_list or v_value == None: # 不知道在python中,c的空指针是否可以用None表示,我这里意思意思而已,没有做具体调试 return None self.address_list.append(v_value) # 我这里的address_list是为了防止有循环链表而做的,有点浪费资源,不过若如果知道大体结构,可以自行记录头指针 v_name = '*' + v_name vv_value = v_value.dereference() # 获得指针所指向的变量 self._parse_variable(depth, v_name, vv_value) elif 'struct' in str(v_basic_type): v_fields = v_value.type.fields() # 结构体的话,遍历结构体中的字段 for i, v_filed in enumerate(v_fields): v_name = v_filed.name vv_value = v_value[v_name] # 结构体中的子元素,可以像这种类似字典的形式被引用 self._parse_variable(depth, v_name, vv_value) GetType()
(gdb) source gettype.py
(gdb) gettype &ppp # 即可,我这里默认输入指针,按照上述代码,结果会在gettype.log中显示
get_basic_type