功能为,打印变量的值,包括链表结构体的结构、内容、地址
注册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