Memory leaks 用gdb分析kmemleak扫描结果
我读过这个链接,但似乎没有给出最终答案 通过kmemleak扫描内存泄漏后。我可以导出未引用对象地址的结果,比如0xffff880060bb3060[在更新中] 我使用下面的gdb命令查看这个地址的位置。 注意:我在/sys/module/hello/session/.text中找到了.text_地址,其值为0xFFFFFFFF038C000Memory 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.
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不在回溯中。