功能为,打印变量的值,包括链表结构体的结构、内容、地址

注册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