您的位置:首页 > 其它

通过GDB调试内核(Kernel)和模块(Module)

2017-08-03 22:07 330 查看

一、   需求

在Linux内核开发过程中不可避免地地会面对如何调试内核的问题。比如printk() 是调试内核代码时最常用的一种技术,但是这种调试方法需要对问题产生的点有个大概的感知,这样才能有的放矢地在合适的代码处添加打印信息。
但是很多情况下,我们对问题产生的原因毫无头绪,也就不可能在茫茫的代码中添加printk,这时候我们就依赖于GDB构建Linux内核调试环境。本文以Linux 4.1.15为例,介绍调试环境的搭建过程。

二、   原理

参考内核文档:
linux/Documentation/gdb-kernel-debugging.txt

GDB调试过程中需要加载符号信息,即lx-symbols命令,该命令是实现在内核自带python脚本:/linux/scripts/gdb/vmlinux-gdb.py,这也是”build gdb 7.2+ (recommended: 7.4+) with python supportenabled”的原因。

三、   在虚拟机上搭建调试环境

1. 检查虚拟机上已安装的GDB和python

[admin@local
/home/elvis]

$whichgdb

/usr/bin/gdb

[admin@local
/home/elvis]

$/usr/bin/gdb-v

GNUgdb (GDB) Red Hat Enterprise Linux (7.0.1-37.el5)

Copyright(C) 2009 Free Software Foundation, Inc.

LicenseGPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>

Thisis free software: you are free to change and redistribute it.

Thereis NO WARRANTY, to the extent permitted by law. Type "show copying"

and"show warranty" for details.

ThisGDB was configured as "x86_64-redhat-linux-gnu".

Forbug reporting instructions, please see:

<http://www.gnu.org/software/gdb/bugs/>.

[admin@local
/home/elvis]
$which python
/usr/bin/python

[admin@local
/home/elvis]
$/usr/bin/python-org--version
Python2.5.4

2. 注意事项

l  内核文档建议选择GDB 7.4+,但是实际的编译调试过程中发现让GDB加载python脚本需要auto-load功能,GDB 7.5+以后版本才支持该功能。
l  /linux/scripts/gdb/vmlinux-gdb.py脚本使用了python的一个新功能dictionary comprehensions,该功能只能到Python 2.7之后才支持。详情参考https://docs.python.org/2/whatsnew/2.7.html-
new-features-added-to-python-2-7-maintenance-releases
l  由于开发机器上现有的Python 2.5.4版本过低,并且安装在非标准目录/usr/xx,在GDB编译过程中会报错,该问题的workaround方法是:
 
[admin@local
/home/elvis/linux]
$mv /usr/bin/python /usr/bin/python-org
[admin@local
/home/elvis/linux]
$cp /usr/python-2.7/bin/python /usr/bin/python
 
该方法只是将Python 2.7替换掉原有的Python。如有其它更好办法,请更新此文档。

3. Build GDB withPython Support

由于开发机上已经安装GDB 7.0.1,为了不影响公用该开发机其它项目的编译,最好自己编译一个仅供自己使用的GDB。这里选择的是支持auto-load功能的GDB 7.5。
 
首先,编译之前需要检查几个事项:
(1)   python是否支持Dictionary Comprehension功能
[admin@local
/home/elvis/gdb-7.5]
$python
Python2.7 (r27, May 27 2013, 20:02:53)
[GCC4.1.2 20080704 (Red Hat 4.1.2-46)] on linux2
Type"help", "copyright", "credits" or"license" for more information.
>>>d = {n: True for n in range(5)}
>>>d
{0:True, 1: True, 2: True, 3: True, 4: True}
>>>
如果d正常打印未告警,说明支持Dictionary Comprehension语法。
 
(2)   编译GDB过程中需要使用到动态链接库libpython2.7.*.so。动态链接库程序ld.so加载动态库时,搜索的是一个缓存文件/etc/ld.so.cache,这是一个二进制文件,用vim打开确认一下路径中包含libpython2.7.so.1.0,如果未包含该动态库,请将路径“/usr/python-2.7/lib/”添加到/etc/ld.so.conf之后,键入命令ldconfig更新缓存文件ld.so.cache。
[admin@local
/home/elvis/gdb-7.5]
$sudo ldconfig
 
(3)   Build GDB with Python Support
[admin@local
/home/elvis]
$tar zxvf gdb-7.5.tar.gz

$cd gdb-7.5

 

再次检查GDB编译所需的头文件和链接选项,与目标Python路径是否一致:
[admin@local
/home/elvis/gdb-7.5]
$python ./gdb/python/python-config.py--includes
-I/usr/python-2.7/include/python2.7

-I/usr/python-2.7/include/python2.7
 
[admin@local
/home/elvis/gdb-7.5]
$python ./gdb/python/python-config.py--ldflags
-lpthread-ldl -lutil -lm -lpython2.7 -Xlinker -export-dynamic

 

检查完成之后开始编译:
$mkdirbin

$cdbin/

$../configure--with-python

$make

 

4. 检查编译后的GDB是否支持linux自带的vmlinux-gdb.py脚本。

[admin@local
/home/elvis/linux]
$/home/elvis/gdb-7.5/bin/gdb/gdb
GNU gdb(GDB) 7.5
Copyright(C) 2012 Free Software Foundation, Inc.
LicenseGPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This isfree software: you are free to change and redistribute it.
There isNO WARRANTY, to the extent permitted by law. Type "show copying"
and"show warranty" for details.
This GDBwas configured as "x86_64-unknown-linux-gnu".
For bugreporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb) set debug auto-load on --->To demo “auto-load” function. No need for daily use
(gdb) set auto-load safe-path . --->Set current Directory as safe-path
auto-load:Updating directories of ".".
auto-load:Using directory ".".
auto-load:And canonicalized as "/elvis/linux".
(gdb) file ./build/vmlinux     --->Load Linux kernel Symbols
Readingsymbols from /elvis/linux/build/vmlinux...done.
auto-load:Attempted file "/elvis/linux/build/vmlinux-gdb.gdb" does not exist.
auto-load:Expanded $-variables to"/usr/local/lib/debug:/usr/local/share/gdb/auto-load".
auto-load:Searching 'set auto-load scripts-directory' path"$debugdir:$datadir/auto-load".
auto-load:Attempted file "/usr/local/lib/debug/elvis/linux/build/vmlinux-gdb.gdb"does not exist.
auto-load:Attempted file "/usr/local/share/gdb/auto-load/elvis/linux/build/vmlinux-gdb.gdb"does not exist.
auto-load:Attempted file "/elvis/linux/build/vmlinux-gdb.py" exists.
auto-load:Loading Python script "/elvis/linux/build/vmlinux-gdb.py" byextension for objfile "/elvis/linux/build/vmlinux".
auto-load:Matching file "/elvis/linux/build/vmlinux-gdb.py" to pattern"."
auto-load:Not matched - pattern ".".
auto-load:Matching file "/elvis/linux/build/vmlinux-gdb.py" to pattern"/elvis/linux"
auto-load:Matched - file "/elvis/linux" to pattern "/elvis/linux".
auto-load:File "/elvis/linux/build/vmlinux-gdb.py" matches directory"/elvis/linux".
(gdb)apropos lx
functionlx_current -- Return current task
functionlx_module -- Find module by name and return the module variable
functionlx_per_cpu -- Return per-cpu variable
functionlx_task_by_pid -- Find Linux task by PID and return the task_struct variable
functionlx_thread_info -- Calculate Linux thread_info from task variable
lx-dmesg-- Print Linux kernel log buffer
lx-lsmod-- List currently loaded modules
lx-symbols-- (Re-)load symbols of Linux kernel and currently loaded modules
(gdb)
 
至此,GDB的环境搭建部分已经完成。

四. Qemu虚拟机环境

Qemu环境准备:需要在qemu的启动选项里面加上”-s”即可:
#!/bin/bash
……
echoStarting VM ...\
set -x
$TRACE$QEMU $* \
-s \
-m ${MEM_MB} \
-smp cpus=${CPUS} \
-nodefconfig -nodefaults -no-user-config \
-parallel none \
-vga none \
-display none \
-bootmenu=off \
……
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  gdb 内核 调试 kernel