Memory leaks 用gdb分析kmemleak扫描结果

Memory leaks 用gdb分析kmemleak扫描结果,memory-leaks,linux-kernel,linux-device-driver,Memory Leaks,Linux Kernel,Linux Device Driver,我读过这个链接,但似乎没有给出最终答案 通过kmemleak扫描内存泄漏后。我可以导出未引用对象地址的结果,比如0xffff880060bb3060[在更新中] 我使用下面的gdb命令查看这个地址的位置。 注意:我在/sys/module/hello/session/.text中找到了.text_地址,其值为0xFFFFFFFF038C000 sudo insmod hello.ko gdb hello.ko /proc/kcore add-symbol-file hello.

我读过这个链接,但似乎没有给出最终答案

通过kmemleak扫描内存泄漏后。我可以导出未引用对象地址的结果,比如0xffff880060bb3060[在更新中]

我使用下面的gdb命令查看这个地址的位置。 注意:我在/sys/module/hello/session/.text中找到了.text_地址,其值为0xFFFFFFFF038C000

sudo insmod hello.ko        
gdb hello.ko /proc/kcore

add-symbol-file hello.ko 0xffffffffa038c000
list *0xffff880060bb3060
但是,list命令不显示任何内容。 我已经使用这些步骤来调试内核oops消息,所以我确信我键入的命令是正确的

那么我如何使用gdb来分析kmemleak给出的结果呢

更新

我想我还应该提供示例代码hello.c:

#include <linux/module.h>
#include <linux/list.h>
#include <linux/slab.h>


struct num {
    struct list_head node;
    int number;
};

static int __init hello_init(void)
{
    LIST_HEAD(my_list);
    struct num *tmp;
    struct list_head *iterator;
    u8 i;

    for(i=0; i<5; i++) {
        tmp = kmalloc(sizeof(struct num), GFP_KERNEL); //I expect this line will be output as memory leak
        tmp->number = i;
        list_add(&tmp->node, &my_list);
    }

    list_for_each(iterator, &my_list) {
        printk("%d\n", list_entry(iterator, struct num, node)->number);
    }

    return 0;
}

static void hello_exit(void)
{
    printk(KERN_ALERT "Good, haha\n");
}

module_init(hello_init);
module_exit(hello_exit);
扫描结果如下:

 unreferenced object 0xffff880060bb3060 (size 32):
      comm "swapper/0", pid 1, jiffies 4294895149 (age 802.568s)
      hex dump (first 32 bytes):
        00 01 10 00 00 00 ad de 00 02 20 00 00 00 ad de  .......... .....
        00 28 b1 57 00 88 ff ff 01 4f 0a 56 00 00 00 00  .(.W.....O.V....
      backtrace:
        [<ffffffff8170ea7e>] kmemleak_alloc+0x4e/0xc0
        [<ffffffff811a5de8>] kmem_cache_alloc_trace+0xb8/0x160
        [<ffffffff810b0ed6>] pm_vt_switch_required+0x76/0xb0
        [<ffffffff813c1e61>] register_framebuffer+0x1d1/0x370
        [<ffffffff813db3fc>] vesafb_probe+0x5bc/0xa70
        [<ffffffff814870cc>] platform_drv_probe+0x3c/0x70
        [<ffffffff81484d74>] driver_probe_device+0x94/0x3d0
        [<ffffffff8148517b>] __driver_attach+0x8b/0x90
        [<ffffffff81482913>] bus_for_each_dev+0x73/0xb0
        [<ffffffff814847ae>] driver_attach+0x1e/0x20
        [<ffffffff814842f8>] bus_add_driver+0x208/0x2e0
        [<ffffffff81485844>] driver_register+0x64/0xf0
        [<ffffffff81486eca>] __platform_driver_register+0x4a/0x50
        [<ffffffff81d923f1>] vesafb_driver_init+0x12/0x14
        [<ffffffff810020f2>] do_one_initcall+0xf2/0x1b0
        [<ffffffff81d50f24>] kernel_init_freeable+0x144/0x1cc

泄漏对象的地址与任何符号都不对应-它是分配的内存,而不是代码中的位置。您可以在回溯中使用GDBand其他机制解析地址,例如FFFFFFFF 810B0ED6,它对应于pm_vt_switch_required函数的代码。回溯似乎没有显示模块_init或hello_init之类的函数?为什么?我的意思是,回溯似乎只显示内核函数?因为它不是模块中的直接泄漏。当泄漏对应于模块时,其名称出现在回溯中。我不确定我是否理解为直接泄漏。我又做了一次体验,调用跟踪类似于load_module->do_one_initcall,看起来hello_init是作为do_one_initcall中的函数指针发送的,所以它实际上是由内核函数调用的。这就是为什么它没有显示在回溯中?您刚刚发现了一个与您的模块无关的泄漏。这就是为什么您的hello_init不在回溯中。