【Linux】GDB调试(第七篇)

server/2024/12/23 5:01:55/

目录

1.概述

2.调试器的种类

3.GDB的调试命令

4.多线程调试

4.1断点锁定某个线程

5.GDB一些小技巧

6.GDB的底层原理


1.概述

gdb是GNU开源组织发布的一个强大的Linux下的程序调试工具。

 一般来说,GDB主要帮助你完成下面四个方面的功能:

1、启动你的程序,可以按照你的自定义的要求随心所欲的运行程序。

2、可让被调试的程序在你所指定的调置的断点处停住。(断点可以是条件表达式)

3、当程序被停住时,可以检查此时你的程序中所发生的事。

4、你可以改变你的程序,将一个BUG产生的影响修正从而测试其他BUG。

2.调试器的种类

两类调试器:GUI调试器(VS),GDB调试器 GDB命令调试器 对初学者不友好 需要掌握大量的调试命令 GUI调试器(上手简单,开销较大 ,某些GUI调试器可能出现调试冲突)

3.GDB的调试命令

list [l] 行号 #打印行号附近的代码 默认显示10行
run[r ] #开始执行不调试
start #单步调试
step[s] #逐语句执行,如果在模块位置,进入到模块内部
next[n] #逐过程执行,如果是模块不进入模块内部,直接运行模块,返回结果
​

执行程序的命令 : -g

gcc test.c -g -o app

启动GDB 调试命令: gdb app

常用断点调试命令

#断点
break [b] 行号 或者函数名     #在指定位置加设断点
#某段代码假设断点后,调试时可用run全速运行,
#如果以start启动调试,可以使用continue快速跳转到断点位置暂停
info breakpoints  #查看断点详细信息
delete [d] 断点编号   # 可以一次删除多个 比如 d  1 3 4
disable 断点编号 #禁用断点,不会暂停
enable 启用断点#恢复暂停功能
tbreak #临时断点(一次性断点)
continue [c] #继续运行
print [p] 变量 #输出程序中的数据信息
set var 变量#值,可以在运行调试阶段修改变量数据
finish #跳出模块,返回调用位置
until 行号#跳出循环
clear #清除指定行或函数处的断点
q #退出gdb调试

3.1打印内存  

格式:

x/NFU ADDR  

N:重复后面FU次数   

F:/x16进制 /c字符 /s字符串 /a地址 /d十进制 /i汇编 /t二进制   

U:b字节 h(2字节) w(4字节默认) g(8字节)

3.2自动换行   

(gdb)set height 0   去掉less的功能,一次性打印所有

3.3打印所有线程堆栈   

(gdb)thread apply all bt

3.4查看某个地址意义   

(gdb)info line *0x00f43126 //会打印出这个函数名   等价于:arm-linux-addr2line 0x00f43126 -e ./build_debug

3.5查看结构体定义

(gdb)ptype pTimeVal
type = struct{
int32 i32tv;
int32 i32Usec;
}

3.6打印格式美观

(gdb)set print pretty on
​

3.7打印数组

(gdb)p *pstTmpStruct->pst@4
$35 = {0x1, 0x2, 0x3, 0x4}
12

3.8display  每次断点时打印某个值 3.9查看指令

info args:查看当前函数的参数及其值
info line:查看源代码在内存中地址,可以跟行号、函数名
info locals:显示当前函数的局部变量
info symbol:显示全局变量信息
info function:显示所有函数名称
info thread:查看线程信息
info registers:列举寄存器值
1234567

3.10指定动态库位置

(gdb)set solib-search-patch ./libso/
(gdb)set solib-absolute-prefix  ./libso/
12

3.11打印当前进程map信息 定位内存相关死机问题时比较常用,确认当前申请的大块内存的头尾

i proc map

4.多线程调试

 单步调试n、s都会遇到一个问题,某个接口可能是多线程调用的,n执行一步可能会跑到其他线程中执行,造成调试不便,所以在执行单步调试前我们可以先将线程锁定,只能执行到当前线程:

(gdb)set scheduler-locking on
(gdb)set scheduler-locking off

4.1断点锁定某个线程

有时将某个接口,如get()函数增加断点时,该接口被多个线程调用,不是我们想分析的线程,如果想指定到某个线程的调用,需要指定线程号,针对线程打断点:

(gdb)b get thread 23

5.GDB一些小技巧

1.shell 终端命令

2.日志功能

set logging on

3.观察一个变量的值是否发生变化 watch *地址

4.info watchpointsq

5.设置core 文件 (如果 没有core 查看 ulimit -a )

6.调试运行的进程 gdb -p 进程ID

6.GDB的底层原理

系统启动GDB进程,这个进程会调用系统函数fork()来创建一个子进程,这个子进程做两件事:

1.调用系统函数ptrace(PTRACE_TRACEME,[其他参数]);

2.通过exec来加载、执行可程序程序test,那么test程序就在这个子进程中开始执行G

ptrace这个函数是使得GDB拥有了强大的调试能力。函数原型:

#include <sys/ptrace.h>
long ptrace(enum _ptrace_request request,pid_t pid,void* addr, void* data);

The ptrace() system call provides a means by which one process (the "tracer") may observe and control the execution of another process (the "tracee"), and examine and change the tracee's memory and registers. It is primarily used to implement breakpoint debugging and system call tracing.

tracer 就是调试程序,即GDB程序,tracee就是被调试程序,对应于上面的test.一般习惯用-er和-ee来表示主动和被动的关系。

ptrace系统函数是linux内核提供的一个用于进程跟踪的系统调用,通过它,一个进程(gdb)可以读写另外一个进程(test)的指令空间、数据空间、堆栈和寄存器的值。而且gdb进程接管了test进程的所有信号,也就是说系统向test发送的所有信号,都被gdb进程接收,这样一来,test进程的执行就被gdb控制了,从而达到调试的目的。

也就是说,如果没有gdb调试,操作系统与目标进行之间是直接交互的;如果使用GDB来调试,那么操作系统发给目标进程的信号就会被gdb截获,gdb根据信号的属性来决定:在继续运行目标程序时是否把当前截获的信号转交给目标程序,如此一来,目标程序就在gdb发来的信号指挥下进行相应的动作。


http://www.ppmy.cn/server/109549.html

相关文章

set与map

1&#xff0c;介绍 ES6提新的数据结构。set它类似于数组&#xff0c;值都是唯一的&#xff0c;本身是一个构造函数。 map数据结构 它类似于对象&#xff0c;也是键值对的集合&#xff0c;但是“键”的范围不限于字符串&#xff0c;各种类 型的值&#xff08;包括对象&#x…

LeetCode - 9 回文数

题目来源 9. 回文数 - 力扣&#xff08;LeetCode&#xff09; 题目描述 给你一个整数 x &#xff0c;如果 x 是一个回文整数&#xff0c;返回 true &#xff1b;否则&#xff0c;返回 false 。 回文数 是指正序&#xff08;从左向右&#xff09;和倒序&#xff08;从右向左&…

深入理解归并排序

目录 一、概念 二、递归版实现 三、非递归实现 三、文件归并排序 小结 一、概念 归并排序&#xff08;Merge sort&#xff09;是建立在归并操作上的一种有效的排序算法&#xff0c;该算法是采用分治法&#xff08;Divide and Conquer&#xff09;的一个非常典型的应用。将…

78.给你一个整数数组 nums ,数组中的元素 互不相同 。返回该数组所有可能的 子集 (幂集)。

78. 子集 LeetCode 78. 子集详解 一、题目描述 给你一个整数数组 nums,数组中的元素互不相同。返回该数组所有可能的子集(幂集)。 解集不能包含重复的子集。你可以按任意顺序返回解集。 示例 1: 输入:nums = [1,2,3] 输出:[[],[1],[2],[1,2],[3],[1,3],[2,3],[1,2,…

使用 streamlink 把 m3u8 转为 mp4

问题描述&#xff0c; 背景&#xff0c; 来源&#xff1a; 下载 m3u8 ts —> 转为mp4, 按照以往的做法&#xff0c; 就是使用 python requests 一步一步地下载 m3u8, ts&#xff0c; 然后转换。 但是个人写的东西&#xff0c;毕竟问题比较多。 而且&#xff0c; 但是&…

浅谈常见的分布式ID生成方案

一、UUID UUID是通用唯一标识码的缩写&#xff0c;其目的是让分布式系统中的所有元素都有唯一的辨识信息&#xff0c;而不需要通过中央控制器来指定唯一标识。 优点&#xff1a; &#xff08;1&#xff09;降低全局节点的压力&#xff0c;使得主键生成速度更快&#xff1b; &…

Qt QT中QString 类的使用--获取指定字符位置、截取子字符串等

QString 类中各函数的作用。 一、字符串连接函数 1、QString也重载的和运算符。这两个运算符可以把两个字符串连接到一起。 2、QString的append()函数则提供了类似的操作&#xff0c;例如&#xff1a; str "User:";str.append(userName);str.append("\n"…

市场纷乱中,沃尔沃坚守长期主义之道,用“P1+P4”解决用户痛点3A品质,插混王者——沃尔沃插混让性能成为插混必要条件

“造车就像西天取经&#xff0c;明确的方向、实现目标的能力&#xff0c;内心的坚持缺一不可”,本届成都国际车展上&#xff0c;来自沃尔沃汽车集团全球高级副总裁袁小林的一句话可谓是振聋发聩&#xff0c;向沉迷玩转“流量密码”的车企&#xff0c;向因各种噱头而迷茫的用户发…