当前位置: 首页 > article >正文

gdb 教程

文章目录

  • GDB
    • 启动 GDB 的方法
    • GDB 命令
    • 工具
    • 参考

GDB

GDB是Linux下的调试工具,可以调试C、C++、Go、java等语言

GDB提供了以下四个功能:

  • 程序启动时,可以按照自定义的要求运行程序,如设置参数和环境变量
  • 可以让被调试的程序在所指定的代码处暂停运行,并查看当前运行状态(如当前变量的值,函数的执行结果),即支持断点调试
  • 当程序被停止时,可以查看当前程序中的变量的状态
  • 在程序执行过程中,可以改变某个变量的值,还可改变代码的执行顺序

要使用gdb调试,必须在源代码生成二进制程序的时候,加上 -g 选项,release 模式,如果没有 -g ,将看不见程序的函数名、变量名,所替代的全是运行时的内存地址

可以通过 readelf -S 可执行文件 | grep debugfile 可执行文件 查看某个二进制文件有没有调试信息,如下红色框是调试信息

在这里插入图片描述

启动 GDB 的方法

  • gdb program:调式方式启动运行无参程序

  • gdb program core:用 GDB 同时调试一个运行程序和 core 文件,core 是程序非法执行后 core dump 后产生的文件

    # 查看 limit
    (base) china@china:~$ ulimit -c
    0
    (base) china@china:~$ ulimit -a
    real-time non-blocking time  (microseconds, -R) unlimited
    core file size              (blocks, -c) 0
    data seg size               (kbytes, -d) unlimited
    scheduling priority                 (-e) 0
    file size                   (blocks, -f) unlimited
    pending signals                     (-i) 127327
    max locked memory           (kbytes, -l) 4084144
    max memory size             (kbytes, -m) unlimited
    open files                          (-n) 1024
    pipe size                (512 bytes, -p) 8
    POSIX message queues         (bytes, -q) 819200
    real-time priority                  (-r) 0
    stack size                  (kbytes, -s) 8192
    cpu time                   (seconds, -t) unlimited
    max user processes                  (-u) 127327
    virtual memory              (kbytes, -v) unlimited
    file locks                          (-x) unlimited
    # 修改为不限制 core 文件大小
    (base) china@china:~$ ulimit -c unlimited
    (base) china@china:~$ ulimit -c
    unlimited
    
  • gdb program process_id:指定程序运行时的进程 ID,GDB 会自动 attach 上去,并调试,program 应该在 PATH 环境变量中搜索得到

    # 修改 /etc/sysctl.d/10-ptrace.conf
    kernel.yama.ptrace_scope = 0
    
    # 调试
    (base) china@china:~/thread-pool$ ps -ef | grep program_name
    china      53735   48756  0 20:32 pts/0    00:00:00 ./program_name
    (base) china@china:~/thread-pool$ sudo gdb program_name -p 53735
    

GDB 启动时常用参数

# 从指定文件中读取符号表
--symbols=SYMFILE

# 从指定文件中读取符号信息,并把它用在可执行文件中
--se=FILE

# 调试时 core dump 的 core 文件
--core=COREFILE

# 加入一个源文件的搜索路径,默认搜索路径是环境变量中 PATH 所定义的路径
--directory=DIR

调式core文件,段错误

# 查看
ulimit -a
ulimit -c
# 设置
ulimit -c unlimited

# 设置core生成目录为/data/coredump,默认当前目录下,%e表示程序名,%p表示进程id
echo /data/coredump/core.%e.%p> /proc/sys/kernel/core_pattern

当程序core dump时,可能会产生core文件,它能够很大程序帮助我们定位问题。但前提是系统没有限制core文件的产生。

ulimit -a

ulimit -c

ulimit -c unlimited # 此时会产生core文件

gdb 程序文件名 core文件名

调试core文件,需要设置ulimit -c unlimited,并设置core文件生成目录
当程序运行错误结束的时候,会自动生成一个core文件,gdb ./main core

GDB 命令

在这里插入图片描述

  • help

    # help 命令仅显示 GDB 命令种类
    (gdb) help
    # 查看 breakpoints 的所有命令
    (gdb) help breakpoints 
    
  • breakpoint:设置断点

    # 
    (gdb) braek function_name
    
    # 
    (gdb) break line_num
    
    # 在当前行号的前 offset 
    (gdb) break +offset
    
    # 在当前行号的后 offset
    (gdb) break -offset
    
    (gdb) break file_name:line_num
    
    (gdb) break file_name:function_name
    
    # 在程序运行的内存地址处
    (gdb) break *address
    
    # 如果 cond 成立
    (gdb) break …… if cond
    
    # 在下一条指令处停住
    (gdb) break
    
    # 查看断点,[n]表示断点号
    (gdb) info breakpoints [n]
    
  • watchpoint:设置观察点

    # 一旦 expr 值变化,程序停止
    (gdb) watch expr
    
    # 一旦 expr 被读时,程序停止
    (gdb) rwatch expr
    
    # 当 expr 被读或写,程序停止
    (gdb) awatch expr
    
    # 查看
    (gdb) info watchpoints
    
  • catchpoint:设置捕捉点,捕捉程序运行时的一些时间

    # 抛出的异常
    (gdb) catch throw
    
    # 捕获的异常
    (gdb) catch catch
    
    # 调用系统调用 exec 时
    (gdb) catch exec
    
    # 调用系统调用 fork 时
    (gdb) catch fork
    
    # 调用系统调用 vfork 时
    (gdb) catch vfork
    
    # load 或 load 载入共享库时
    (gdb) catch load
    
    # 卸载共享库时
    (gdb) catch unload
    
    # 只设置一次捕捉点,当程序停止后,自动删除
    (gdb) tcatch
    
  • 维护停止点:delete、clear、disable、enable

    # 清除所有已定义的停止点
    (gdb) clear
    
    # 
    (gdb) clear function_name
    
    # 
    (gdb) clear line_num
    
    # 删除所有的断点
    (gdb) delete
    
    # 删除指定的断点,breakpoints 是断点号,range 是断点号的范围 3-7
    (gdb) delete [breakpoints] [range...]
    
    # 关闭所有的断点
    (gdb) disable
    
    # 关闭指定的断点,breakpoints 是断点号,range 是断点号的范围 3-7
    (gdb) disable [breakpoints] [range...]
    
    # 开启所有的断点
    (gdb) enable
    
    # 开启指定的断点,breakpoints 是断点号,range 是断点号的范围 3-7
    (gdb) enable [breakpoints] [range...]
    
  • run

    # 
    (gdb) set args ...
    
    # 运行程序,直到程序结束或下一个断点
    (gdb) run args
    
    # 恢复程序运行,直到结束或者下一个断点
    (gdb) continue
    
    # 单步,会进入函数
    (gdb) setp
    
    # 单步,不会进入函数
    (gdb) next
    
    # 运行程序,直到当前函数完成返回,打印函数返回时的堆栈地址和返回值及参数值等信息
    (gdb) finish
    
    # 运行程序直到退出循环体
    (gdb) until
    
  • quit

    (gdb) quit
    
  • shell

    # shell command
    (gdb) shell pwd
    
    # 查看运行环境
    (gdb) path
    (gdb) show path
    
    # 
    (gdb) cd
    
    # 查看当前目录
    (gdb) pwd
    
  • log

    set logging on 打开日志功能
    	默认在当前目录生成gdb.txt
    

工具

  • readelf

    root@china:~/csapp# readelf -S ./main | grep debug
      [28] .debug_aranges    PROGBITS         0000000000000000  00003036
      [29] .debug_info       PROGBITS         0000000000000000  00003066
      [30] .debug_abbrev     PROGBITS         0000000000000000  000031af
      [31] .debug_line       PROGBITS         0000000000000000  00003295
      [32] .debug_str        PROGBITS         0000000000000000  00003321
      [33] .debug_line_str   PROGBITS         0000000000000000  0000341a
    
  • file

    root@china:~/csapp# file ./main
    ./main: ELF 64-bit LSB pie executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, BuildID[sha1]=fa5fb837d07c13549e0880c95a0e6ea0c5e54f57, for GNU/Linux 3.2.0, with debug_info, not stripped
    

参考

  • man gdb

  • GDB调试还不会?看这篇就够了!-腾讯云开发者社区-腾讯云 (tencent.com)

  • 【Linux】GDB用法详解(5小时快速教程) - Avatarx - 博客园 (cnblogs.com)


http://www.kler.cn/news/284959.html

相关文章:

  • springboot学习(2)
  • 美团2024秋招编程题:小美的red子序列数量之和
  • WebSocket 实现消息推送
  • AOP 面向切片编程
  • 我的推荐:腾讯云罗云《从零构建向量数据库》
  • 无人机之遥控器防水性能篇
  • Ubuntu 20.04 安装 GitHub CLI(gh),并使用
  • C语言——简单的do while循环找100~999之间的水仙花数(所有的三位水仙花数)
  • 数据结构(三)——双向链表,循环链表,内核链表,栈和队列
  • 『功能项目』怪物反击主角复活【14】
  • spring security 会话管理
  • 苹果M4芯片Mac全面曝光 或10月发布
  • OpenHarmony轻量设备Hi3861芯片开发板启动流程分析
  • redis能正常访问,但是springboot编译报错
  • 【Go函数详解】二、参数传递、变长参数与多返回值
  • java定时服务
  • Python学习日志(1)——安装
  • Linux-arm64中断现场保护详解
  • MySQL 集群技术全攻略:从搭建到优化(上)
  • 分类模型评估指标——准确率、精准率、召回率、F1、ROC曲线、AUC曲线
  • 快递盒检测检测系统源码分享 # [一条龙教学YOLOV8标注好的数据集一键训练_70+全套改进创新点发刊_Web前端展示]
  • RAG 向量数据库:掌握 Elasticsearch 作为向量数据库的终极指南
  • 【Python零基础】文件使用和异常处理
  • Vue(四) 组件、单文件组件、非单文件组件,重要的内置关系
  • 【计组 | Cache原理】讲透Cache的所有概念与题型方法
  • 大模型好书案例——《BERT基础教程:Transformer大模型实战》(附PDF)
  • LuaJit分析(一)LuaJit交叉编译
  • TCP的连接与断开
  • java基础开发-xstream解析xml
  • 去中心化(Decentralization)