美文网首页个人收藏
利用gdb python extention学习内核

利用gdb python extention学习内核

作者: 独孤求真007 | 来源:发表于2018-04-16 13:11 被阅读0次

    上一篇介绍了通过利用GDB和VBoxDBG很轻松的定位到了缺页(Page fault)中断处理函数,本篇将要介绍一个更灵活的工具,那就是GDB Python extension.

    内核本身提供了几个GDB Python extension,位于script/gdb目录下。继续引用上一篇的例子。对x86平台来说,linux内核256个中断向量表是定义如下:

    struct gate_struct {
            u16             offset_low;
            u16             segment;
            struct idt_bits bits;
            u16             offset_middle;
    #ifdef CONFIG_X86_64
            u32             offset_high;
            u32             reserved;
    #endif
    } __attribute__((packed));
    
    gate_desc idt_table[IDT_ENTRIES] __page_aligned_bss;
    

    这个结构是和根据CPU手册定义的,我们可以通过gdb命令查看具体内容:

    root@derek-test1:~/vagrant/kernel/obj/x86_64# gdb vmlinux
    
    (gdb) target remote :1234
    Remote debugging using :1234
    kgdb_breakpoint () at /root/vagrant/linux/kernel/debug/debug_core.c:1073
    1073            wmb(); /* Sync point after breakpoint */
    (gdb) p/x idt_table[14]
    $1 ={offset_low = 0x12c0, segment = 0x10, bits = {ist = 0x0, zero = 0x0, type = 0xe, dpl = 0x0, p = 0x1}, offset_middle = 0x8180, offset_high = 0xffffffff,
      reserved = 0x0}
    

    上一篇我们是通过VBoxGDB的DI命令直接获取到中断处理函数的地址的。通过GDB打印,则需要手工计算。
    计算方法是: (offset_high<<32) | (offset_middle<<16) | offset_low,在这个例子中,我们可以得到处理函数地址是:0xffffffff818012c0. 现在我们可以用GDB找到源代码的位置:

    (gdb) info symbol 0xffffffff818012c0
    page_fault in section .text
    (gdb) info line page_fault
    Line 1158 of "/root/vagrant/linux/arch/x86/entry/entry_64.S" starts at address 0xffffffff81801273 <general_protection+3>
       and ends at 0xffffffff818012c3 <page_fault+3>.
    

    每次手工计算太麻烦,我们可以写一个GDB Python extension,然后一个命令就得到类似上面的输出。我们要实现的命令是lx-idt,用法如下:

    (gdb) source /root/vagrant/linux/scripts/gdb/linux/idt.py
    (gdb) lx-idt idt_table 14
    interrupt: 0x0e: handler: page_fault @ 0xffffffff818012c0
    symbol and line for /root/vagrant/linux/arch/x86/entry/entry_64.S, line 1158
    (gdb) info line 0xffffffff818012c0
    

    lx-idt接受2个参数,第一参数是中断向量表的名字,第二个是中断向量,这样我们就不用手工计算了。这个extension文件名为idt.py,第一行通过source命令加载它,现在来看看它的实现吧:

    import gdb
    from linux import  utils
    
    def x86_dump_idt(name, nr):
        try:
            idt=gdb.parse_and_eval(name)
        except:
            raise gdb.GdbError("symbol {} not found".format(name))
        h = idt[nr]['offset_high'].cast(gdb.lookup_type('long'))
        m = idt[nr]['offset_middle'].cast(gdb.lookup_type('long'))
        l = idt[nr]['offset_low'].cast(gdb.lookup_type('long'))
        addr = (m<<16) | l
        sym = gdb.execute("info symbol 0x{:08x}{:08x}".format(int(h), int(addr)), True, True).split(" ")[0]
        gdb.write("interrupt: 0x{:02x}: ".format(int(nr)))
        gdb.write("handler: {} ".format(sym))
        gdb.write('@ 0x{:08x}'.format(int(h)))
        gdb.write('{:08x}'.format(int(addr)))
        addr = (h<<32)|(m<<16) | l
        gdb.write('\n')
        r=gdb.find_pc_line(int(addr))
        print(r)
    
    class LxIDT(gdb.Command):
        def __init__(self):
            super(LxIDT, self).__init__("lx-idt", gdb.COMMAND_DATA)
    
        def invoke(self, arg, from_tty):
            if not utils.is_target_arch("x86"):
                return
            argv = gdb.string_to_argv(arg)
            if len(argv) != 2:
                raise gdb.GdbError("lx-idt takes 2 argument")
            x86_dump_idt(argv[0], gdb.parse_and_eval(argv[1]))
    
    LxIDT()
    

    GDB Python extension的格式是固定的,

    1. class名LxIDT可以任意命名,但必须继承gdb.Command。
    2. 构造函数必须调用super(LxIDT, self).init("lx-idt", gdb.COMMAND_DATA), "lx-idt"就是命令。当在gdb中敲入lx-idt时,就会调用下面的invoke函数。
    3. invoke函数,参数保存在arg里面,lx-idx接受2个参数,这里做一些检查,然后调用x86_dump_idt,
    4. x86_dump_idt,接受2个参数,id_table是内核代码中,中断向量表的名字,nr是要查看的中断向量。
    5. 调用gdb.parse_and_eval(name)得到id_table的地址,保存在idt中。
    6. 访问idt[nr]['offset_high'], idt[nr]['offset_middle'], idt[nr]['offset_low'],并计算中断向量处理函数的地址。
    7. 调用gdb python API, gdb.execute和gdb.find_pc_line.

    相关文章

      网友评论

        本文标题:利用gdb python extention学习内核

        本文链接:https://www.haomeiwen.com/subject/ncddkftx.html