使用GDB调试Linux内核空指针问题 |
您所在的位置:网站首页 › gdb调试linux内核 › 使用GDB调试Linux内核空指针问题 |
1.概述
在Linux内核开发中,我们会经常遇到访问空指针导致内核Oops或panic。遇到这种问题,需要先定位出是哪一个函数、哪一个变量导致的异常。通常情况下,Linux内核会打印出异常时的栈、模块、CPU寄存器等信息,但某些情况下,栈被破环,只能输出寄存器信息(U-Boot发生异常时只会输出寄存器信息),那我们只能根据寄存器信息还原出发生异常时的现场。 2,实例如下图所示,内核明确的出了异常原因-访问空指针,空指针解引用地址为0x00000003(若异常地址不为0,应该是访问了某个结构体中的变量,加上了偏移地址),发生异常的函数为__dwc3_gadget_ep_set_halt,上一个调用函数为dwc3_ep0_stall_and_restart。 pc寄存器保存了CPU执行的指令地址(0xffffff8008734ae4),可以根据该地址得到异常发生时调用的函数和访问的变量,lr保存了上一个调用函数的地址(0xffffff80087369e4)。下面使用gdb,还原发生异常时的现场。 首先启动aarch64-linux-gnu-gdb,使用file命令读取vmlinux镜像,获取Linux内核的所有符号。__dwc3_gadget_ep_set_halt函数部分代码如下,三个参数分别使用x0、x1、x2寄存器传递,内部调用了usb_endpoint_xfer_isoc内联函数。 [drivers/usb/dwc3/gadget.c] int __dwc3_gadget_ep_set_halt(struct dwc3_ep *dep, int value, int protocol) { struct dwc3_gadget_ep_cmd_params params; struct dwc3 *dwc = dep->dwc; int ret; if (usb_endpoint_xfer_isoc(dep->endpoint.desc)) { dev_err(dwc->dev, "%s is of Isochronous type\n", dep->name); return -EINVAL; } memset(¶ms, 0x00, sizeof(params)); ...... return ret; }如下图所示,lr寄存器保存的地址指向了dwc3_ep0_stall_and_restart函数,该函数内部调用了__dwc3_gadget_ep_set_halt函数。 使用ptype /o struct usb_endpoint_descriptor命令获取struct usb_endpoint_descriptor数据结构各个变量的偏移值。如下图所示,偏移值为3的变量为bmAttributes,即端点的属性。 从上面的分析中可以看出,红框3中[x0, #3]=0x00000003,x0中保存的地址为NULL,即指针变量desc是一个空指针,空指针解引用时发生了异常,也即在内联函数usb_endpoint_xfer_isoc中访问bmAttributes变量导致了异常。后续我们只需要排查是什么原因导致了指针变量desc变为空指针即可。 |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |