韩 大卫 吉林师范 大学 2014 12 10 转载请表明出处 关于内核报错 Unable to handle kernel paging request at virtual address 的问题 绝 大多数都是 由于程序使 用了不可 用的指针 而引起的 定位这类问题的办法很简单 也希望我的描述 足够简单实 用 以我下 面的 一个实例说明 epc exception program counter 异常程序计数器 ra return address 返回地址 我们可以根据 CPU 0 Unable to handle kernel paging request at virtual address 0000000000000078 epc ffffffff805e96e8 ra ffffffff80ec73d0 找到epc的具体位置 再根据具 体的汇编程序定位出引起epc的具体原因 另外 如有必须知道全部的调 用路径 那么重复定位epc的 方法 根据call trace 逐步定位即可 在编译linux 的时候 会产 生 一个System map vmlinux 以及vmlinux o 我们使 用System map 和vmlinux o 即可 因为vmlinux可能是被特定压缩 工具压缩过的 根据您的 makefi le 无法使 用objdump 工具做反汇编 先打开System map 将 epc ffffffff805e96e8 里的 ffffffff805e96e8 地址拷 贝下来 直接在System map 里 面查找 如果没 有找到 那么将ffffffff805e96e8 最后两位删掉 即ffffffff805e96 查找这个地址 绝 大多数情况都可以找 到 我的如下 看起来 问题是出在 add mtd device 这个函数 里 面 epc 的位置是在ffffffff805e96e8 add mtd device 的地址是在ffffffff805e96c0 那么应该是在 add mtd device 里的 ffffffff805e96e8 ffffffff805e96c0 0 x28 这个偏移位置出了问题 现在我们需要观察 vmlinux o 的汇编代码 找到 add mtd device 函数的汇编 观察 0 x28 位置的汇编 语 言 先使 用xxx objdump xxx为具体的交叉编译 工具前缀 将vmlinux o 反汇编出来 我的做法是 mips64 octeon linux gnu objdump dr vmlinux o linux dr 之后打开linux dr 这个 文件 找到 add mtd device 的定义处 可以看到 0 x28 位置的汇编 28 dc820078 ld v0 120 a0 ld v0 120 a0 的含义是 先取寄存器a0的数值的地址 再将该地址后120字节处的数值加载到v0 寄存器 a0 是取a0寄存器的地址 a0是负责传递函数的第 一个参数的寄存器 dc820078 就是ld v0 120 a0 对应的机器码 根据CPU 0 Unable to handle kernel paging request at virtual address 0000000000000078 这句话 的提 示可以知道 是在对a0的0 x78 120 地址取值的时候发 生了错误 很可能是a0地址本 身不可 用 如果能确认的话 就可以证明add mtd device的第 一个参数使 用 一个不可 用的指针 这时候就可以检查源代码 相信您有能 力很快到定位问题 但如果该函数很 大 不容易定位 那么我们可以通过120这个信息定位到该函数 里具体的语句 我的实例 打开linux内核源代码 计算120字节在add mtd device 第 一个参数类型 里的位置 得到参数成员 vi t add mtd device 如下图 找到第 一个参数的类型struct mtd info 定义 通过逐步计算每个成员偏移 注意填充字节 可以算出 第120字节的成员为backing dev info 那么 在代码 里 出现epc的程序就是第 一个出现该成员的地 方 如果这个偏移太 大 很难计算的话 不妨在代码 里 在调 用该函数前 自定义 一个该参数类型的变量 估计 一个 大概的成员 计算他们的偏移 在知道这个成员偏移量的基础上 再计算120的成员位置 会 容易 一些 我的做法是 struct mtd info my 0 unsigned long len unsigned long printk sizeof is 0 x lu n len 当然 这需要重启设备 并load新编译的linux 关于定位epc 位置 总结 一下 1 打开System map 找到epc之前的最近函数的地址 计算出epc距离该函数的偏移值 2 使 用objdump 找到该函数 分析 epc 偏移处的汇编代码 3 打开源代码 根据分析汇编代码得到的信息进 行定位 希望以上信息对您有帮助
展开阅读全文