gdb 对于看系统内部是非常有用. 在这个级别精通调试器的使用要求对 gdb 命令有信心, 需要理解目标平台的汇编代码, 以及对应源码和优化的汇编码的能力.

调试器必须把内核作为一个应用程序来调用. 除了指定内核映象的文件名之外, 你需要在 命令行提供一个核心文件的名子. 对于一个运行的内核, 核心文件是内核核心映象,

/proc/kcore. 一个典型的 gdb 调用看来如下:

gdb /usr/src/linux/vmlinux /proc/kcore

第一个参数是非压缩的 ELF 内核可执行文件的名子, 不是 zImage 或者 bzImage 或者给 启动环境特别编译的任何东东.

gdb 命令行的第二个参数是核心文件的名子. 如同任何 /proc 中的文件, /proc/kcore 是在被读的时候产生的. 当 read 系统调用在 /proc 文件系统中执行时, 它映射到一个 数据产生函数,而不是一个数据获取函数; 我们已经在本章"使用 /proc 文件系统"一节中 利用了这个特点. kcore 用来代表内核"可执行文件", 以一个核心文件的形式; 它是一个 巨大的文件, 因为他代表整个的内核地址空间, 对应于所有的物理内存. 从 gdb 中, 你 可查看内核变量,通过发出标准 gdb 命令. 例如, p jiffies 打印时钟的从启动到当前时 间的嘀哒数.

当你从 gdb 打印数据, 内核仍然在运行, 各种数据项在不同时间有不同的值; 然而, gdb 通过缓存已经读取的数据来优化对核心文件的存取. 如果你试图再次查看 jiffies 变量, 你会得到和以前相同的答案. 缓存值来避免额外的磁盘存取对传统核心文件是正确的做法, 但是在使用一个"动态"核心映象时就不方便. 解决方法是任何时候你需要刷新 gdb 缓存 时发出命令 core-file /proc/kcore; 调试器准备好使用新的核心文件并且丢弃任何旧信 息. 然而, 你不会一直需要发出 core-file 在读取一个新数据时; gdb 读取核心以多个 几 KB 的块的方式, 并且只缓存它已经引用的块.

gdb 通常提供的不少功能在你使用内核时不可用. 例如, gdb 不能修改内核数据; 它希望 在操作内存前在它自己的控制下运行一个被调试的程序. 也不可能设置断点或观察点, 或 者单步过内核函数.

注意, 为了给 gdb 符号信息, 你必须设置 CONFIG_DEBUG_INFO 来编译你的内核. 结果是 一个很大的内核映象在磁盘上, 但是, 没有这个信息, 深入内核变量几乎不可能.

有了调试信息, 你可以知道很多内核内部的事情. gdb 愉快地打印出结构, 跟随指针, 等 等. 而有一个事情比较难, 然而, 是检查 modules. 因为模块不是传递给 gdb 的 vmlinux 映象, 调试器对它们一无所知. 幸运的是, 作为 2.6.7 内核, 有可能教给 gdb 需要如何 检查可加载模块.

Linux 可加载模块是 ELF 格式的可执行映象; 这样, 它们被分成几个节. 一个典型的模 块可能包含一打或更多节, 但是有 3 个典型的与一次调试会话相关:

.text

这个节包含有模块的可执行代码. 调试器必须知道在哪里以便能够给出回溯或者设 置断点.( 这些操作都不相关, 当运行一个调试器在 /proc/kcore 上, 但是它们在 使用 kgdb 时可能有用, 下面描述).

.bss

.data

这 2 个节持有模块的变量. 在编译时不初始化的任何变量在 .bss 中, 而那些要 初始化的在 .data 里.

使 gdb 能够处理可加载模块需要通知调试器一个给定模块的节加载在哪里. 这个信息在 sysfs 中, 在 /sys/module 下. 例如, 在加载 scull 模块后, 目录

/sys/module/scull/sections 包含名子为 .text 的文件; 每个文件的内容是那个节的基 地址.

我们现在该发出一个 gdb 命令来告诉它关于我们的模块. 我们需要的命令是 add- symble-flile; 这个命令使用模块目标文件名, .text 基地址作为参数, 以及一系列描述 任何其他感兴趣的节安放在哪里的参数. 在深入位于 sysfs 的模块节数据后, 我们可以 构建这样一个命令:

(gdb) add-symbol-file .../scull.ko 0xd0832000 \

-s .bss 0xd0837100 \

-s .data 0xd0836be0

我们已经包含了一个小脚本在例子代码里( gdbline ), 它为给定的模块可以创建这个命 令.

我们现在使用 gdb 检查我们的可加载模块中的变量. 这是一个取自 scull 调试会话的快 速例子:

(gdb) add-symbol-file scull.ko 0xd0832000 \

-s .bss 0xd0837100 \

-s .data 0xd0836be0

add symbol table from file "scull.ko" at

.text_addr = 0xd0832000

.bss_addr = 0xd0837100

.data_addr = 0xd0836be0 (y or n) y

Reading symbols from scull.ko...done.

(gdb) p scull_devices[0]

$1 = {data = 0xcfd66c50, quantum = 4000,

qset = 1000,

size = 20881,

access_key = 0,

...}

这里我们看到第一个 scull 设备当前持有 20881 字节. 如果我们想, 我们可以跟随数据 链, 或者查看其他任何感兴趣的模块中的东东.

这是另一个值得知道的有用技巧:

(gdb) print *(address)

这里, 填充 address 指向的一个 16 进制地址; 输出是对应那个地址的代码的文件和行 号. 这个技术可能有用, 例如, 来找出一个函数指针真正指向哪里.

我们仍然不能进行典型的调试任务, 如设置断点或者修改数据; 为进行这些操作, 我们需 要使用象 kdb( 下面描述 ) 或者 kgdb ( 我们马上就到 )这样的工具.

linux 使用 gdb的更多相关文章

  1. 使用linux的GDB打印STL(vector,map,set..................)

    在linux用gdb或者cgdb计较不爽的地方是无法打印STL的东西,所有啊去网上找了找解决方案https://www.douban.com/note/182826844/?qq-pf-to=pcqq ...

  2. Linux之GDB学习

    Linux之GDB学习 GDB是一款优秀的调试工具,懂的人自然懂,一直以来用它都没有好好整理过使用方法,我用的也是皮毛,目前先整理一下皮毛,日后再更新 使用方法 编译C++ 从编译的角度上来说,需要在 ...

  3. linux中gdb的可视化调试

    今天get到一个在linux下gdb调试程序的技巧和大家分享一下!平时我们利用gcc进行编程,进行程序调试时,观察程序的跳转等不是这么直观.都是入下的界面! 但是如果我们在编译连接时上加了-g命令生成 ...

  4. Linux知识(5)----LINUX下GDB调试

    命令 解释 示例   file 加载被调试的可执行程序文件.因为一般都在被调试程序所在目录下执行GDB,因而文本名不需要带路径. (gdb) file gdb-sample     r c Run的简 ...

  5. 一文入门Linux下gdb调试(二)

    作者:良知犹存 转载授权以及围观:欢迎添加微信号:Conscience_Remains 总述     今天我们介绍一下core dump文件,Core dump叫做核心转储,它是进程运行时在突然崩溃的 ...

  6. linux下gdb如何处理coredump错误

    linux下gdb如何处理coredump错误 在编写C++程序中,我们经常会遇到一种错误,segment fault, 这种coredump错误 会导致程序运行时异常退出或者终止,这种错误没有明显错 ...

  7. 【转载】Linux之gdb

    转载自:http://blog.chinaunix.net/uid-22312037-id-3812061.html 一.常规调试         gdb是Linux下常用的程序调试工具,当然前提是用 ...

  8. 【Linux】gdb调试core文件

    编写服务器端程序,很容易遇到Crash问题,比较幸运的是Linux提供了core file,保留了Crash的现场.有时候,根据当前的调用栈,并且打印出当前栈的变量就可以分析出crash的原因,但是, ...

  9. linux之gdb使用

    gdb是linux下用来调试的一款软件,在这里,我只记录平常经常会用到的知识点,用到什么,就记录什么,在调试环境中去熟悉调试方法和调试工具,这才会加深理解. gdb能够做什么?它可以按照你的定义,随心 ...

  10. linux之GDB常用命令汇总

    查看gdb的版本号 (1)rpm -q gdb 会显示是否安装gdb及版本号 (2)gdb --version也可以 breakpoint b main; b 20; 设置断点 breakpoint ...

随机推荐

  1. spring - constructor-arg的常规用法

     1.使用构造子注入时,则使用constructor-arg子标签,来指定构造函数的参数.    <bean id="provider" class="com.ap ...

  2. JS文字球状放大效果

    在线演示 本地下载

  3. python 字符串匹配的应用

  4. vue-cnodejs

    感谢那些无私开源的程序员,你们是最可爱的人儿~~~~ //根app app.js <template> <div id="app"> <v-heade ...

  5. 用var 变量=函数名 方式调用函数时如何传值的问题

    通过:xmlhttp.onreadystatechange= function(){FuncName(param)};orxmlhttp.onreadystatechange= new Functio ...

  6. jQuery第3天

    复习 如何区别 JS DOM对象和 JQ 包装对象? JQ对象其实是经过包装的DOM对象,包装后可调用 JQ 的方法. JS 对象基本上都是属性为主,JQ基本上都方法为主. 可通过 console.d ...

  7. 【Leetcode链表】反转链表 II(92)

    题目 反转从位置 m 到 n 的链表.请使用一趟扫描完成反转. 说明: 1 ≤ m ≤ n ≤ 链表长度. 示例: 输入: 1->2->3->4->5->NULL, m ...

  8. WebGL three.js学习笔记 加载外部模型以及Tween.js动画

    WebGL three.js学习笔记 加载外部模型以及Tween.js动画 本文的程序实现了加载外部stl格式的模型,以及学习了如何把加载的模型变为一个粒子系统,并使用Tween.js对该粒子系统进行 ...

  9. Maven中央存储库 和 如何从Maven远程存储库下载?

    当你建立一个 Maven 的项目,Maven 会检查你的 pom.xml 文件,以确定哪些依赖下载.首先,Maven 将从本地资源库获得 Maven 的本地资源库依赖资源,如果没有找到,然后把它会从默 ...

  10. Python操作pymysql写入数据库时的错误

    错误一 InternalError: (pymysql.err.InternalError) (1366, "Incorrect string value: '\\xE6\\xAD\\xA3 ...