linux内核调试技术之GDB和GDBServer

1、调试原理

  GDB调试是应用程序在开发板上运行,然后在PC机上对开发板上得应用程序进行调试,PC机运行GDB,开发板上运行GDBServer。在应用程序调试的时候,pc机上的gdb向开发板上的GDBServer发出命令,而开发板上的gdbserver就会向应用程序发出信号,使应用程序停下来或者完成其他一些工作。

2、安装GDB和GDBServer(gdb-7.4.tar.bz2 )

  2.1、GDB  

    1、下载: http://ftp.gnu.org/gnu/gdb/

    2、解压:tar xvf gdb-7.4.tar.bz2

    3、配置:cd gdb-7.4/

./configure --target=arm-linux

    4、编译:make

    5、安装:mkdir tmp

make install prefix=$PWD/tmp

    6、拷贝:cp tmp/bin/arm-linux-gdb  /bin/

    7、查看版本 /bin/arm-linux-gdb -v (使用绝对路径使用gdb)

  2.2、GDBServer

    1、cd gdb/gdbserver/

    2、配置: ./configure --target=arm-linux --host=arm-linux

    3、编译: make CC=arm-linux-gcc

  2.3、编译GDBServer的时候会出现以下错误
linux-arm-low.c: In function `arm_stopped_by_watchpoint‘:
linux-arm-low.c:642: error: `PTRACE_GETSIGINFO‘ undeclared (first use in this function)
linux-arm-low.c:642: error: (Each undeclared identifier is reported only once
linux-arm-low.c:642: error: for each function it appears in.)

  该错误是因为找不到PTRACE_GETSIGINFO宏,导致编译错误。我们到交叉编译链去搜索一下,我们交叉编译地址为 /work/tools/gcc-3.4.5-glibc-2.3.6

# cd  /work/tools/gcc-3.4.5-glibc-2.3.6
# grep "PTRACE_GETSIGINFO" * -nR
arm-linux/sys-include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO    0x4202
arm-linux/include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO    0x4202
distributed/arm-linux/sys-include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO    0x4202
distributed/arm-linux/include/linux/ptrace.h:27:#define PTRACE_GETSIGINFO    0x4202

  可以看到,在交叉编译链里面,定义了PTRACE_GETSIGINFO宏为0x4202,头文件为include<linux/ptrace.h>中。

  有两种解决办法,可任选其一:

  ① 在linux-arm-low.c中直接添加宏 #define PTRACE_GETSIGINFO 0x4202

  ② 在linux-arm-low.c中将#include <sys/ptrace.h> 更改为 #include <linux/ptrace.h>

  再次编译,编译通过。

  2.4、将gdbserver拷贝到开发板的bin目录下
#cp gdbserver /work/nfs_root/first_fs/bin

3、调试

  3.1、在编译要进行调试的应用程序 加上 -g

   测试程序如下(test_debug.c)

  

#include <stdio.h>

void C(int *p)
{
    *p = 0x12;
}

void B(int *p)
{
    C(p);
}
void A(int *p)
{
    B(p);
}
void A2(int *p)
{
    C(p);
}
int main(int argc, char **argv)
{
    int a;
    int *p = NULL;
    A2(&a);  // A2 > C
    printf("a = 0x%x\n", a);
    A(p);    // A > B > C
    return 0;
}

  编译:

#arm-linux-gcc -g -o test_debug test_debug.c
3.2、在开发板上:

  打印出如下信息:

#gdbserver 192.168.1.10:123 ./test_debugProcess ./test_debug created; pid = 751
Listening on port 2345

  注释:192.168.1.10:本开发板的ip

   123:端口号,自己随便写的

   ./test_debug:要调试的程序

3.3、在PC上输入:
    /bin/arm-linux-gdb ./test-debug
           target remote 192.168.183.127:2345
3.4、正式调试!介绍几个常用的命令

  (1)l:列出所有源代码

  (2)break main:在main处打断点

          break test_debug.c:11:在test_debug.c的11行打断点

  (3)c:运行到断点处

  (4)step:单步执行

  (5)next:单步执行,但是step会进入函数里面,但是next不会

  (6)print a:打印a这个变量的值

  (7)quit:退出,输入此命令则开发板上的gdbserver也退出

   (8)  详细的GDB调试命令

4、另外一种调试方法

  让程序在开发板上直接运行,当它发生错误时,令它产生core dump文件,然后使用gdb根据core dump文件找到发生错误的地方

  在ARM板上:
  4.1、 ulimit -c unlimited
  4.2、 执行应用程序 : 程序出错时会在当前目录下生成名为core的文件

  在PC上:

  4.3、首先将core文件拷贝到pc机上

      然后:/bin/arm-linux-gdb ./test_debug ./core

  打印出如下信息:

GNU gdb (GDB) 7.4
Copyright (C) 2012 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
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 "--host=i686-pc-linux-gnu --target=arm-linux".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>...
Reading symbols from /home/share/jz2440/test_debug...done.
[New LWP 748]
warning: `/lib/libc.so.6‘: Shared library architecture unknown is not compatible with target architecture arm.
warning: `/lib/ld-linux.so.2‘: Shared library architecture unknown is not compatible with target architecture arm.
Core was generated by `./test_debug‘.
Program terminated with signal 11, Segmentation fault.
#0  0x000084ac in C (p=0x0) at test_debug.c:6
6               *p = 0x12;

  4.4、bt:可以显示调用关系

#0  0x000084ac in C (p=0x0) at test_debug.c:6
#1  0x000084d0 in B (p=0x0) at test_debug.c:12
#2  0x000084f0 in A (p=0x0) at test_debug.c:17
#3  0x00008554 in main (argc=1, argv=0xbeb32eb4) at test_debug.c:34
时间: 2024-08-04 13:54:56

linux内核调试技术之GDB和GDBServer的相关文章

Linux内核调试技术——jprobe使用与实现

前一篇博文介绍了kprobes的原理与kprobe的使用与实现方式,本文介绍kprobes中的第二种探测技术jprobe,它基于kprobe实现,不能在函数的任意位置插入探测点,只能在函数的入口处探测,一般用于监测函数的入参值.本文首先通过一个简单的示例介绍jprobe的使用方式,然后通过源码详细分析jprobe的实现流程. 内核源码:Linux-4.1.x 实验环境:Fedora25(x86_64).树莓派1b 1.jprobe使用实例 使用jprobe探测函数的入参值,需要编写内核模块.同k

Linux内核调试技术——kretprobe使用与实现

摘自:https://blog.csdn.net/luckyapple1028/article/details/54782659前两篇博文介绍了kprobes探测技术中kprobe和jprobe的使用与实现.本文介绍kprobes中的最后一种探测技术kretprobe,它同样基于kprobe实现,可用于探测函数的返回值以及计算函数执行的耗时.本文首先通过一个简单的示例程序介绍kretprobe的使用方式,然后通过源码分析它是如何实现的. 内核源码:Linux-4.1.x 实验环境:Fedora2

Linux内核调试技术——进程上下文R状态死锁监测

前一篇博文介绍了内核监测D状态死锁的hung task机制,本文介绍另一种死锁状态的监测手段--R状态死锁监测.R状态死锁指的是某一任务一直处于TASK_RUNNING态且一直占用着CPU,从而导致其他进程得不到调度而饿死的情况.一般情况下,R状态死锁较可能是由于程序出现死循环导致的,可以出现在内核态的进程上下文中(内核配置为非抢占式,soft lockup),也可以出现在中断上下文中的中断处理程序中(hard lockup).异常的程序一直运行,CPU无法调度到其他的任务运行,对于单CPU的设

Linux内核调试技术——进程D状态死锁检测

Linux的进程存在多种状态,如TASK_RUNNING的运行态.EXIT_DEAD的停止态和TASK_INTERRUPTIBLE的接收信号的等待状态等等(可在include/linux/sched.h中查看).其中有一种状态等待为TASK_UNINTERRUPTIBLE,称为D状态,该种状态下进程不接收信号,只能通过wake_up唤醒.处于这种状态的情况有很多,例如mutex锁就可能会设置进程于该状态,有时候进程在等待某种IO资源就绪时(wait_event机制)会设置进程进入该状态.一般情况

Linux内核调试的方式以及工具集锦

CSDN GitHub Linux内核调试的方式以及工具集锦 LDD-LinuxDeviceDrivers/study/debug 本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可, 转载请注明出处, 谢谢合作 因本人技术水平和知识面有限, 内容如有纰漏或者需要修正的地方, 欢迎大家指正, 也欢迎大家提供一些其他好的调试工具以供收录, 鄙人在此谢谢啦 "调试难度本来就是写代码的两倍. 因此, 如果你写代码的时候聪明用尽, 根据定义, 你就没有能耐去调试它了.&qu

Linux Kernel - Debug Guide (Linux内核调试指南 )

http://blog.csdn.net/blizmax6/article/details/6747601 linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级调试 ***第一部分:基础知识*** 总纲:内核世界的陷阱 源码阅读的陷阱 代码调试的陷阱 原理理解的陷阱 建立调试环境 发行版的选择和安装 安装交叉编译工具 bin工具集的使用 qemu的使用 initrd.img的原理与制作 x86虚拟调试环境的建立 arm虚拟调试环境的建立 arm开发板调试环

第10章 嵌入式Linux的调试技术 学习心得

第10章嵌入式Linux的调试技术 心得体会 这一章主要概括的介绍了嵌入式Linux的调试技术的主要内容.通过对第10章的学习,使我对嵌入式Linux的调试技术的方法以及操作步骤有了一个基本的认识. 一 调试前的准备 在调试一个bug之前,我们所要做的准备工作有: 有一个被确认的bug. 包含这个bug的内核版本号,需要分析出这个bug在哪一个版本被引入,这个对于解决问题有极大的帮助.可以采用二分查找法来逐步锁定bug引入版本号. 对内核代码理解越深刻越好,同时还需要一点点运气. 该bug可以复

linux内核调试指南

linux内核调试指南 一些前言 作者前言 知识从哪里来 为什么撰写本文档 为什么需要汇编级调试 ***第一部分:基础知识*** 总纲:内核世界的陷阱 源码阅读的陷阱 代码调试的陷阱 原理理解的陷阱 建立调试环境 发行版的选择和安装 安装交叉编译工具 bin工具集的使用 qemu的使用 initrd.img的原理与制作 x86虚拟调试环境的建立 arm虚拟调试环境的建立 arm开发板调试环境的建立 gdb基础 基本命令 gdb之gui gdb技巧 gdb宏 汇编基础--X86篇 用户手册 AT&

嵌入式 Linux 的调试技术读书笔记

对于复杂的 Linux 驱动及 HAL等程序库,需要使用各种方法对其进行调试. 例如,设置断点. 逐步跟踪代码.-输出调试值息等.虽然撒入式Linux在调试方面并没有 Visual Studio. Delphi. Eclipse 这些可视偌工其荒便,但学习一些这方面的技术无疑更奇脚手亮发强款而稳定的 Linux 内核模块对于嵌入式 Linux 俞核模块.可fA,衍程庄. 央事库的调试可能要更复杂一些.因为在失多赞时候需要至 少两台机器开发机和目标机. 在 Linux 文件系统中, /proc 经