IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 系统运维 -> Linux驱动之oops错误:addr2line工具定位错误 -> 正文阅读

[系统运维]Linux驱动之oops错误:addr2line工具定位错误

前言

在编写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 ]---

常见的方法是利用objdump工具进行反汇编,然后使用gbd的list指令加上出错函数和偏移量,就可以定位出错的具体位置,前提是有源代码的情况下。
上面的oops打印信息展示了内核出错时程序的调用关系和出错的原因。可以看到内核发生错误是在fbcon_putcs+0xf4/0x10c处,并且是因为访问了NULL指针所导致的错误,其中0xf4表示的是位于该函数第0x18字节处,0x10c表示该函数共0x10c个字节。尽管如此,我们还是不知道具体是到底是哪里使用了NULL指针。有没有什么工具可以利用这些信息定位到具体是某个文件的某一行呢?说到这里,不得不吐槽一下,嵌入式真是一步一个脚印(坑)!使用单片机时,有硬件错误HardFault;本想着进入linux世界,起码会好点,结果还是泪。。。得益于之前调试HardFault的cmBackTrace工具,该工具本质上是利用addr2line和输出的函数调用栈信息,还原发生错误时的现场信息,定位问题代码位置。抱着尝试的态度,有了这篇文章,作为记录。

addr2line工具

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

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

内核配置CONFIG_DEBUG_INFO

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

使用addr2line进行定位

在这里插入图片描述
可以看到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, &image, buf, dst);
187		else
188			bit_putcs_unaligned(vc, info, s, attribute, cnt,
189					    pitch, width, cellsize, &image,
190					    buf, dst);
191					    
192		image.dx += cnt * vc->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->fbops->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,
};
  系统运维 最新文章
配置小型公司网络WLAN基本业务(AC通过三层
如何在交付运维过程中建立风险底线意识,提
快速传输大文件,怎么通过网络传大文件给对
从游戏服务端角度分析移动同步(状态同步)
MySQL使用MyCat实现分库分表
如何用DWDM射频光纤技术实现200公里外的站点
国内顺畅下载k8s.gcr.io的镜像
自动化测试appium
ctfshow ssrf
Linux操作系统学习之实用指令(Centos7/8均
上一篇文章      下一篇文章      查看所有文章
加:2021-07-29 12:03:21  更:2021-07-29 12:05:32 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 17:28:52-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码