嵌入式Linux内核调试技术

技术分类: 嵌入式系统  | 2007-12-05
来源:电子产品世界 | 作者:北京麦克泰软件技术有限公司 宋尚春

  2.1.2 内核调试

  首先,配置BDI2000,确保目标机的正常初始化。通常来说到了调试内核的阶段,板子的boot应该是正常的,所以利用boot来完成目标机的初始化;另一种方式是通过BDI的配置文件来完成。

  接下来就是下载代码进行调试了。如果代码已经固化,那仅下载调试信息给仿真器即可;否则需要把代码下载到RAM里运行,同时下载调试信息给仿真器。本文所用的是后一种方式。

  由于Linux运行之后会启动MMU而使地址重映射,因此第一个断点通常在函数start_kernel( ),而且只能设置为硬断点。硬件断点是非常有限的,有的处理器甚至只能设置一个。所以,在调试Linux内核时,使用普通的GDB进行断点设置会非常不方便。LinuxScope可以很方便的切换断点模式,并支持软断点,使断点的设置不再受到限制,为调试Linux内核提供强有力的支持。具体步骤如下:

  1) BDI配置文件的断点模式:soft

  2) LinuxScope配置默认的断点模式:soft /hard 都可以

  3)用BDI下载压缩的内核:load  0x20000 zImage bin

  4) 把PC指针指到内核入口地址:ti 0x30000

  5) 运行LinuxScope,在start_kernel处设置硬件断点

  6) go,停下来后再设置软断点即可

调试界面

  2.2 模块内核调试

  我们使用BDI2000来调试Linux内核的另外一个重要原因就是它可以支持调试内核模块。内核模块是一些可以让操作系统内核在需要时载入和执行的代码,这意味着它可以在不需要时由操作系统卸载。这种方式可以扩展操作系统内核的功能,而不需要重新启动系统,这一点对调试驱动的工程师特别有用。因为如果驱动程序编译进内核的话,会增加内核的大小,还要改动内核的源文件,而且不能动态的卸载,不利于调试,所以推荐使用模块方式。

  2.2.1 调试Linux 2.4内核模块

  2.4内核模块的调试比较简单,使用命令“insmod -m”来加载模块。参数“-m”非常重要,它的功能是在把模块加载到内存时产生一个加载map表。然后通过LinuxScope调试器加载相应的调试信息。例如:

  [root@lisl tmp]# insmod -m hello.o >modaddr

  查看模块加载信息文件modaddr如下:

  .this           00000060  c88d8000  2**2

  .text           00000035  c88d8060  2**2

  .rodata         00000069  c88d80a0  2**5

  ……

  .data           00000000  c88d833c  2**2

  .bss            00000000  c88d833c  2**2

  ……

  在这些信息中,我们用到的只有.text、.rodata、.data、.bss。当然,把相关的信息输入LinuxScope调试器,它会把

以上地址信息加入到gdb中进行模块功能的调试。

  这里需要注意的是对模块进行编译时,也需要增加“-g”选项。

  另外,这种方法也存在一定的不足,它不能调试模块初始化的代码,因为此时模块初始化代码已经执行过了。如果不执行模块的加载又无法获得模块插入地址,更不可能在模块初始化之前设置断点了。如果初始化部分有问题,那么将无法进行调试。遇到这样的情况可以修改代码,延迟初始化部分的执行。另外,也可以采用以下替代方法:当插入内核模块时,内核模块机制将调用函数sys_init_module (kernel/modle.c)执行对内核模块的初始化,该函数将调用所插入模块的初始化函数。程序代码片断如下:

  …… ……
 if (mod->init != NULL)
  ret = mod->init();
  …… ……

  在该语句上设置断点,也能在执行模块初始化之前停下来。

0
0
(请您对文章做出评价)
1】【2】【3
加载中

对文章的评论

更多评论

剩余字数:  

浏览该文章的用户还看过...

  • 文 章

  • 论 坛

  • 博 客

  • 小 组

设计资源与分销

  • 博客推荐

  • 论坛推荐

  • 在线研讨会