野火电子论坛

 找回密码
 注册

QQ登录

只需一步,快速开始

查看: 1456|回复: 0

[经验\资料] 使用addr2line工具定位oops错误

[复制链接]
发表于 2021-7-28 22:33:56 | 显示全部楼层 |阅读模式

在编写linux驱动程序时,内核发生了oops错误,并打印了一大堆错误信息如下:Unable to handle kernel NULL pointer dereference at virtual address 00000000

pgd = 23b16ac7
[00000000] *pgd=00000000
Internal error: Oops: 80000005 [#1] PREEMPT SMP ARM
Modules linked in: ssd1306fb_spi(O+) g_multi snd_soc_fsl_asrc snd_soc_core snd_pcm_dmaengine snd_pcm snd_timer [last unloaded: ssd1306fb_spi]
CPU: 0 PID: 476 Comm: insmod Tainted: G           O      4.19.35-imx6 #1stable
Hardware name: Freescale i.MX6 UltraLite (Device Tree)
PC is at   (null)
LR is at bit_putcs+0x270/0x40c
pc : [<00000000>]    lr : [<80497a6c>]    psr: 600f0013
sp : 86edba18  ip : 00000001  fp : 86008800
r10: 00000000  r9 : 000000ff  r8 : 00000001
r7 : 00000010  r6 : 876e9120  r5 : 87692010  r4 : ffffffff
r3 : 00000000  r2 : 00000000  r1 : 86edba7c  r0 : 8741a000
Flags: nZCv  IRQs on  FIQs on  Mode SVC_32  ISA ARM  Segment none
Control: 10c53c7d  Table: 8686406a  DAC: 00000051
Process insmod (pid: 476, stack limit = 0xa0438ff4)
Stack: (0x86edba18 to 0x86edc000)
...
[<80497a6c>] (bit_putcs) from [<80491a60>] (fbcon_putcs+0xf4/0x10c)
[<801ae464>] (do_init_module) from [<801ad38c>] (load_module+0x2174/0x257c)
[<801ad38c>] (load_module) from [<801ada18>] (sys_finit_module+0xc4/0x110)
[<801ada18>] (sys_finit_module) from [<80101000>] (ret_fast_syscall+0x0/0x54)
Exception stack(0x86edbfa8 to 0x86edbff0)
bfa0:                   336e7f00 00000000 00000003 004cc7e0 00000000 7ebc7c38
bfc0: 336e7f00 00000000 00000000 0000017b 0238b160 00000000 7ebc7db8 00000000
bfe0: 7ebc7be8 7ebc7bd8 004c4e41 76ca0d92
Code: bad PC value
---[ end trace 701ce5fc9b7e7151 ]---

上面的oops打印信息展示了内核出错时程序的调用关系和出错的原因。可以看到内核发生错误是在<80497a6c>fbcon_putcs+0xf4/0x10c处,并且是因为访问了NULL指针所导致的错误,其中0xf4表示的是位于该函数第0x18字节处,0x10c表示该函数共0x10c个字节。尽管如此,我们还是不知道具体是到底是哪里使用了NULL指针。有没有什么工具可以利用这些信息定位到具体是某个文件的某一行呢?之前调试单片机HardFault的cmBackTrace工具,该工具本质上是利用addr2line和输出的函数调用栈信息,还原发生错误时的现场信息,定位问题代码位置。抱着尝试的态度,有了这篇文章,作为记录。

addr2line工具

addr2line工具是一个可以将指令的地址和可执行映像转换为文件名、函数名和源代码行数的工具,更多的介绍,可以进行百度/谷歌。下面列举之后会用到的参数以及对应含义:

参数 作用
-e 指定需要转换地址的可执行文件名
-f 在显示文件名、行号输出信息的同时显示函数名信息
-p 输出信息更加人性化
-a 在函数名、文件和行号信息之前,显示地址,以十六进制形式

内核配置CONFIG_DEBUG_INFO

使用addr2line工具之前,请确保内核配置正确:<code>CONFIG_DEBUG_INFO=y</code>,该配置使能以调试方式编译内核,这样编译生成的vmlinux文件才会带有调试信息。make menuconfig位置位于:Kernel hacking > Compile-time checks and compiler options>[] Compile the kernel with debug info处。

使用addr2line进行定位

addr2line -f -e vmlinux文件的路径 出错位置的16进制码 -p -a

使用上述命令,就可以定位到发生错误的具体文件以及具体的行数。

在这里插入图片描述

addr2line工具定位到文件drivers/video/fbdev/core/bitblit.c的第192行。该文件的第192行位于函数bit_putcs之中。

static void bit_putcs(struct vc_data *vc, struct fb_info *info,
              const unsigned short *s, int count, int yy, int xx,
              int fg, int bg)
{
    /* 省略部分代码 */
184     if (!mod)
185         bit_putcs_aligned(vc, info, s, attribute, cnt, pitch,
186                   width, cellsize, &amp;image, buf, dst);
187     else
188         bit_putcs_unaligned(vc, info, s, attribute, cnt,
189                     pitch, width, cellsize, &amp;image,
190                     buf, dst);
191                   
192     image.dx += cnt * vc-&gt;vc_font.width;
    /* 省略部分代码 */              
}

在bit_puts函数的第192行之前调用了函数bit_putcs_unaligned,bit_putcs_unaligned函数的结尾调用了函数指针info->fbops->fb_imageblit。

static inline void bit_putcs_unaligned(struct vc_data *vc,
                       struct fb_info *info, const u16 *s,
                       u32 attr, u32 cnt, u32 d_pitch,
                       u32 s_pitch, u32 cellsize,
                       struct fb_image *image, u8 *buf,
                       u8 *dst)
{
    /* 省略部分代码 */
    info-&gt;fbops-&gt;fb_imageblit(info, image);
}

而我编写的驱动模块,fb_ops结构体确实没有对成员fb_imageblit进行赋值,最终成功定位到使用NULL指针的具体位置。实际测试,将一个空函数赋值给fb_fbops函数的成员fb_imageblit,加载模块时,内核也不提示oops错误,证明找对地方了。

static struct fb_ops fb_fbops = {
    .owner = THIS_MODULE,
    .fb_read = fb_sys_read,
};
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

联系站长|手机版|野火电子官网|野火淘宝店铺|野火电子论坛 ( 粤ICP备14069197号 ) 大学生ARM嵌入式2群

GMT+8, 2024-11-24 16:24 , Processed in 0.066400 second(s), 24 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表