gdb调试动态加载模块
来源:互联网 发布:小米手机关闭4g网络 编辑:程序博客网 时间:2024/05/18 07:11
本文也即《Linux Device Drivers》,LDD3的第四章Debuging Techniques的读书笔记之六,但我们不限于此内容。这章看得比较慢,最近比较懒,而陷入了文档工作中,我决定这章节不会有之七,在之六打住。
在用户程序中,有很多编译工具同提供的debug工具,用于设置断点或者单步跟踪,但是在kernel程序中是很困难的。LDD3介绍了gdb对于kernel模块的使用方式,但是需要kernel版本在2.6.7以上。我们需要两个文件vmlinux和/proc/kcore。我注意到moblin是没有看kcore的,而moblin的快速启动和效率是对linux的一个很大的优化,所以不知道以后是否还能通过这个方式。我在fc10进行实验,具体如下:
一、先获得vmlinux。
这个不是/boot中任何相关的不bzImage或者zImage等经过压缩的文件,而且我们需要打开CONFIG_DEGBU_INFO的选项,因此我打算重新编译kernel来获取。根据我linux的当前版本,在网上下载kernel的source code文件kernel-2.6.27.5-117.fc10.src.rpm。下面的操作都在非root的普通用户下执行。
1、rpm –ivh kernel-2.6.27.5-117.fc10.src.rpm,在~/rpmbuild/中或有SPECS/kernel.specs;
2、进入~/rpmbuild/SPECS目录,执行rpmbuild –bp kernel.specs,在~/rpmbuild/BUILD/下有源代码
3、进入~/rpmbuild/BUILD/kernel-2.6.27/linux-2.6.27.i386目录,需要根据我们的环境生成我们的.config文件,执行perl merge.pl config-i686 config-x86-generic > .config
4、打开CONFIG_DEBUG_INFO的选项,执行make menuconfig,进入kernel hacking的选项,打开Kernel debugging,选择Compile the kernel with debug info,保存,查看vi .config,确认CONFIG_DEBUG_INFO的选项已经设置为y。
5、如果我们直接编译,有一个bug,是Toshiba的api,需要打补丁,既然我的机器没有日立的API,可以在.config中将CONFIG_ACPI_TOSHIBA的选项直接关闭解决。我们只需要获得vmlinux,执行 make ARCH=x86 bzImage即可。这个过程花点时间,完成后在当前目录有一个文件vmlinux,这就是我们所需的。
二、进入kernel的gdb模式:
执行gdb vmlinux /proc/kcore,在moblin中,不直接使用gdb vmlinux即可。我们加载scull模块后,在/sys/module/scull/sections中,使用ls -a的命令,有很多系统文件,用于显示scull模块的内存物理位置,其中需要注意的有.text。显示模块执行executable code的位置,.bss和.data显示模块变量的位置,如果编译时没有初始化位于.bss,如果编译时已经初始化则位于.data。 需查清各自物理内存的位置。cat .data .bss .text
下面是处理的过程:
$ sudo gdb vmlinux /proc/kcore
GNU gdb Fedora (6.8-29.fc10)
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i386-redhat-linux-gnu"...
Core was generated by `ro root=UUID=e57e257e-7340-411c-a6bb-6eb375f5aa8b rhgb quiet'.
[New process 0]
#0 0x00000000 in ?? ()
(gdb) add-symbol-file /home/wei/workspace/learning/kernel_module/scull_debug/scull.ko 0xf9df8000 -s .bss 0xf9dfaa00 -s .data 0xf9df9720
add symbol table from file "/home/wei/workspace/learning/kernel_module/scull_debug/scull.ko" at
.text_addr = 0xf9df8000
.bss_addr = 0xf9dfaa00
.data_addr = 0xf9df9720
(y or n) y
Reading symbols from /workspace/wei/learning/kernel_module/scull_debug/scull.ko...done.
(gdb) p mydev[0]
$1 = {data = 0x0, quantum = 0, qset = 0, size = 0, access_key = 0, sem = {
lock = {raw_lock = {slock = 0}}, count = 1, wait_list = {
next = 0xf9dfaa3c, prev = 0xf9dfaa3c}}, cdev = {kobj = {name = 0x0,
entry = {next = 0xf9dfaa48, prev = 0xf9dfaa48}, parent = 0x0,
kset = 0x0, ktype = 0xc07d97c0, sd = 0x0, kref = {refcount = {
counter = 1}}, state_initialized = 1, state_in_sysfs = 0,
state_add_uevent_sent = 0, state_remove_uevent_sent = 0},
owner = 0xf9df9880, ops = 0xf9df9740, list = {next = 0xf9dfaa70,
prev = 0xf9dfaa70}, dev = 260046848, count = 1}}
(gdb) p mydev[0] //这里通过用户程序写入信息,在执行一次,发现结果相同,gdb给出的是上次结果的缓存
$2 = {data = 0x0, quantum = 0, qset = 0, size = 0, access_key = 0, sem = {
lock = {raw_lock = {slock = 0}}, count = 1, wait_list = {
next = 0xf9dfaa3c, prev = 0xf9dfaa3c}}, cdev = {kobj = {name = 0x0,
entry = {next = 0xf9dfaa48, prev = 0xf9dfaa48}, parent = 0x0,
kset = 0x0, ktype = 0xc07d97c0, sd = 0x0, kref = {refcount = {
counter = 1}}, state_initialized = 1, state_in_sysfs = 0,
state_add_uevent_sent = 0, state_remove_uevent_sent = 0},
owner = 0xf9df9880, ops = 0xf9df9740, list = {next = 0xf9dfaa70,
prev = 0xf9dfaa70}, dev = 260046848, count = 1}}
(gdb) core-file /proc/kcore //更新,flush cache,下次查询,将是实时内容
Core was generated by `ro root=UUID=e57e257e-7340-411c-a6bb-6eb375f5aa8b rhgb quiet'.
[New process 0]
#0 0x00000000 in ?? ()
(gdb) p mydev[0]
$3 = {data = 0xee327020, quantum = 1024, qset = 64, size = 1500,
access_key = 0, sem = {lock = {raw_lock = {slock = 2570}}, count = 1,
wait_list = {next = 0xf9dfaa3c, prev = 0xf9dfaa3c}}, cdev = {kobj = {
name = 0x0, entry = {next = 0xf9dfaa48, prev = 0xf9dfaa48},
parent = 0x0, kset = 0x0, ktype = 0xc07d97c0, sd = 0x0, kref = {
refcount = {counter = 1}}, state_initialized = 1, state_in_sysfs = 0,
state_add_uevent_sent = 0, state_remove_uevent_sent = 0},
owner = 0xf9df9880, ops = 0xf9df9740, list = {next = 0xf264df28,
prev = 0xf264df28}, dev = 260046848, count = 1}}
(gdb)
我们也可以通过print * (address)来查看某一个位置上的数据,例如上例子中,我们知道data的入口地址,我们就可以进一步查询相关内容,但是说实在的,我觉得这个还不很好用,俺们喜欢printk。
- gdb调试动态加载模块
- linux gdb调试可加载内核模块
- gdb远程调试--动态加载符号文件
- linux下用GDB调试可加载模块
- linux下用GDB调试可加载模块
- 内核gdb模块调试
- osx下gdb调试如何指定目录加载动态库
- gdb调试在加载指定动态库时中断
- GDB调试动态库
- 用gdb调试内核模块
- gdb调试动态链接库
- gdb调试动态链接so
- 模块动态加载技术
- Flex动态加载模块
- 模块动态加载-总结
- python动态加载模块
- Lua动态加载模块
- dkms动态模块加载
- Java项目中文乱码,设置UTF-8
- 目标管理和自我控制
- 基于协同过滤的SVD的推荐系统
- opencv-图像基本操作
- 进程间的通信之管道
- gdb调试动态加载模块
- Android Studio新建的工程继承了AppCompatActivity设置隐藏标题栏后闪退
- Java多线程池的使用
- java 可变类 不可变类区别
- 10K 问题的解决:一个系统管理员如何管理 2000x 台服务器
- android 使用TableLayout 绘制表格
- 学习心得
- SSH登录后无法上传文件,修改sftp-server目录解决
- 基于Pytorch和Beam Search的中文聊天机器人