gdb使用相关知识

  1. 什么是gdb

    参考答案

    gdb全称为GNU Debugger,是可以运行于多种类Unix平台的程序调试软件。类似的软件还有lldblldb常用于macos

    参考资料:

  2. gdb常见命令有哪些?

    参考答案

    gdb的常见命令有:

    1. help: 获取gdb命令帮助
    2. help <command>: 获取特定gdb命令的帮助
    3. run: 运行到下个断点或程序结束
    4. step: 单步(逐语句)调试,会进入到函数内部执行
    5. next: 单步(逐语句)调试,但不会进入到函数内部执行
    6. finish: 结束当前函数或循环
    7. continue: 执行到下个断点或程序结束
    8. up <N>: 往栈顶移动N帧,N默认为1
    9. down <N>: 往栈顶移动N帧,N默认为1
    10. list: 打印当前点附近的代码
    11. print <name>: 打印名为name的变量值
    12. print *<name>: 打印name指针指向的值
    13. print/x <name>: 以16进制打印name的值
    14. print <name>@<n>: 打印以name为起始地址的n个值
    15. break <name>: 在函数name处设置断点
    16. break <num>: 在行num处设置断点
    17. disable 1: 去使能断点1
    18. enable 1: 使能断点1
    19. delete 1: 删除断点1
    20. delete: 删除所有断点
    21. condition 1 <expr>: 断点1的停止条件为表达式expr为true
    22. condition 1: 删除断点1的所有条件
    23. info break: 显示所有的断点信息
    24. backtrace: 查看栈信息
    25. display <name>: 始终显示变量name的值
    26. undisplay <name>: 取消跟踪name的值
    27. watch <expr>: 监视expr的值,一旦有变化就暂停程序

    参考资料:

  3. gdb调试的原理是?

    参考答案

    gdb使用系统调用ptrace(process trace)去观察和控制其它进程的执行、检查和修改其它进程的内存和寄存器。ptrace的原型如下:

    long ptrace(enum __ptrace_request request, pid_t pid, void *addr, void *data);
    

    根据ptrace的manual手册,主要有两种跟踪进程的方式:

    1. 父进程通过fork系统调用创建子进程,在子进程中作如下ptrace调用,然后再通过execv加载子进程程序。

      ptrace(PTRACE_TRACEME, 0, 0, 0);
      
    2. 使用如下ptrace调用直接跟踪其它进程:

      ptrace(PTRACE_ATTACH, pid, 0, 0);
      

    当进程被跟踪时,每当有信号(signal)被分发给被跟踪的进程(tracee)时都会导致tracee暂停(SIGKILL是个例外)。进行跟踪的进程(tracer)通过waitpid系统调用(或类似的wait相关的系统调用)获知tracee被跟踪的情况。当tracee停止时,tracer还可以使用多种ptrace request去检查或修改tracee

    gdb断点(breakpoint)功能的软件实现原理是在指定位置插入断点指令(INT),当被调试的程序执行到断点位置时,产生SIGTRAP信号并转由gdb处理。

    参考资料:

  4. 如何调试多进程程序?

    参考答案

    当我们使用gdb调试多进程程序时,如果进程使用fork创建了子进程,gdb仍会继续跟踪原来的进程,子进程正常执行。要想允许调试子进程,有两种方法:

    1. 使用attch pid的方式跟踪子进程,其中pid为子进程的进程ID
    2. gdb中使用set follow-fork-mode配置fork时跟踪子进程还是父进程

    参考资料:

  5. 如何调试多线程程序?

    参考答案

    gdb提供以下功能调试多线程程序:

    1. 新线程创建的自动提醒
    2. thread <threadno>命令用于在调试的进程间切换
    3. info threads命令用于查询所有已存在的线程
    4. thread apply <threadno> <all> args命令用于对指定的一条线程或多条指令应用指令
    5. 用于线程的断点

    需要注意的是,threadnogdb为每个线程分配的线程ID,是一个内部ID

    参考资料:

  6. 什么是core文件?有什么作用?

    参考答案

    core文件指core dump file,是操作系统在进程收到某些信号而终止时,将此时进程空间的内容及有关进程的状态的其它信息写入一个磁盘文件。core文件中的信息一般用于调试。 程序自身的core dump file一般可以用于分析程序是在哪里错了,而外部程序触发的core dump file一般来于分析进程的运行情况,比如分析内存使用、线程状态等。 core dump的缺点有:

    1. 性能问题:对进程进行core dump可能会耗费大量系统资源、造成内存清理的延迟,尤其是占用大量内存的进程。
    2. 磁盘空间问题:对进程进行core dump会占用大量磁盘空间。
    3. 安全问题:core文件可能包含敏感数据(如密码和密钥),这部分敏感数会被写入到磁盘。

    Linux上要去使能core dump功能,有以下方式:

    1. 使用sysctl设置kernel.core_pattern的值为/dev/null
    2. 按如下方式配置/etc/systemd/coredump.conf.d/custom.conf:
     ```
     [Coredump]
     Storage=none
     ```
    
    1. 按如下方式配置/etc/security/limits.conf:
     ```
     * hard core 0
     ```
    
    1. 使用ulimit指令:ulimit -c 0

    使用gdb对已有进程生成core dump file的方式为:

    1. gdb -p <pid>启动对进程的调试,其中<pid>为进程的进程ID
    2. gdb中使用指令generate-core-file生成core dump file

    参考资料:

  7. 如何使用GDB进行远程调试?

    参考答案

    使用GDB进行远程调试通常需要以下步骤:

    1. 准备目标设备和调试主机:
      • 确保目标设备和调试主机在同一网络中,并可以相互通信。
      • 在目标设备上安装并运行GDB服务器软件,例如OpenOCD、J-Link GDB Server等。
      • 在调试主机上安装GDB调试器。
    2. 启动GDB服务器:
      • 在目标设备上运行GDB服务器,配置它以监听特定的端口,例如TCP端口。
    3. 连接到目标设备:
      • 在调试主机上打开终端或命令行界面,启动GDB调试器。
      • 使用GDB的"target remote"命令连接到目标设备的IP地址和端口,例如:target remote <target_ip_address>:<port>
    4. 加载和调试程序:
      • 使用GDB的"file"命令加载目标设备上的可执行文件,例如:file <executable_file>
      • 设置断点、单步执行或其他调试操作,以控制程序的执行。
      • 使用GDB的其他命令进行调试,例如查看变量、回溯函数调用等。

    需要注意的是,远程调试的具体步骤可能因目标设备和调试工具的不同而有所差异。建议参考相关的GDB调试器和GDB服务器的文档,以了解更详细的配置和使用说明。

    参考资料: