GDB调试大全

news2024/11/24 18:26:30

嵌入式开发必备工具!!!学就完事了!!!


目录

GDB初使用

准备条件:Makefile,section1.cpp

初步使用命令

 启动调试

启动调试别传入参数

附加到进程

逐过程执行

逐语句执行

退出函数

调试断点管理

设置断点

 查看禁用删除断点

变量查看与修改

查看变量

查看函数参数

 设置字符串的显示规则

 设置结构体和数组显示规则

 使用GDB内嵌函数

 变量查看和修改

修改整型

修改字符串

修改结构体

内存查看和修改 

从内存地址修改

查看内存 

查看整型

查看字符串

寄存器查看和修改

 查看​编辑

 修改

 源代码查看搜索

查看

 搜索

 函数调用栈管理

栈帧

观察点使用

 捕获点

​编辑 为断点执行命令

窗口管理

 查看对象类型

多线程调试管理

线程查找,线程断点 

 为线程执行命令

 线程的日志信息控制

 外部命令和保存文件

 跳转执行

 反向执行undo

 多进程

调试子进程

 多进程调试

调试时调用内部函数和外部函数

调试时跳过指定函数

 制作和调试发行版

 修改可执行文件

内存泄漏检测

远程调试 

死锁调试

核心存储core-dump

栈溢出的core-dump

无调试符号的core-dump

软件密码“破解”

BUG专区


GDB初使用

准备条件:Makefile,section1.cpp

EXE:= section1
EXECUTABLE:= $(EXE)

LIBDIR:=
LIBS:=
INCLUDES:=.
SRCDIR:=

CC:=g++
CFLAGS:= -g -Wall -O0  
CPPFLAGS:= $(CFLAGS)
CPPFLAGS+= $(addprefix -I,$(INCLUDES))
CPPFLAGS+= -I.
CPPFLAGS+= -MMD

RM-F:= rm -f

SRCS:= $(wildcard *.cpp) $(wildcard $(addsuffix /*.cpp, $(SRCDIR)))
OBJS:= $(patsubst %.cpp,%.o,$(SRCS))
DEPS:= $(patsubst %.o,%.d,$(OBJS))
MISSING_DEPS:= $(filter-out $(wildcard $(DEPS)),$(DEPS))


.PHONY : all deps objs clean
all:$(EXECUTABLE)
deps:$(DEPS)

objs:$(OBJS)
clean:
	@$(RM-F) *.o
	@$(RM-F) *.d
	@$(RM-F) $(EXE)

ifneq ($(MISSING_DEPS),)
$(MISSING_DEPS):
	@$(RM-F) $(patsubst %.d,%.o,$@)
endif
-include $(DEPS)
$(EXECUTABLE) : $(OBJS)
	$(CC) -o $(EXECUTABLE) $(OBJS) $(addprefix -L,$(LIBDIR)) $(addprefix -l,$(LIBS))

#include <iostream>
void test()
{
	int i=100;
	std::cout << "i is "  << i << std::endl;
}
int main(int argc,char**argv)
{
	int itest=100;test();
	const char *str="this is a test";
	std::cout << "itest is " << itest << ",str is " << str << std::endl;
	std::cout << "参数为:" << std::endl;
	for(int i=0;i<argc;i++)
	{
		std::cout << argv[i]<<std::endl;
	}
	std::cout << "Hello world\n";
	return 0;
}

初步使用命令

查看代码:l。默认每次显示10行

设置断点:b 

查看断点:i b

运行调试:r

逐行运行:n

断点运行:c

查看指定变量:i itest

查看局部变量:i locales

退出:q

 启动调试

启动调试别传入参数

当某些程序需要我们进行传参输入,可以通过下面几种方法

gdb --args 参数

gdb之后,使用:set  参数

gdb之后,使用:r 参数

附加到进程

当一个进程已经运行了,我们对它进行调试,可以如下两种命令

gdb attach pid

gdb --pid pid

其中pid是进程号,通过ps aux | grep sec进行查询

逐过程执行

不会进入函数

n

逐语句执行

会进入函数

s

退出函数

在逐语句中,不想在函数中执行了,可以直接跳出函数

finish

调试断点管理

设置断点

1.b 文件名:行数

2.b 函数名,如果是同名函数则都会标记

3.rb 名字。对于带这个名字的函数都会进行标记,包括虚函数,或者命名不全的函数

4.b 断点 条件   b main.cpp:14 if i==90。也就是执行循环到到i=90才会停止

5.tb 断点。设置临时断点。对于一个循环来说,虽然断点在这,但只会执行一次,就不执行循环了

 查看禁用删除断点

i b查看所有断点

i b 1 查看编号1的断点

delete 1删除断点1

delete 删除所有断点

disable 1禁用断点1

enable 1使能断点1

变量查看与修改

查看变量

info args 查看输入的全部信息

查看函数参数

p argc查看输入了几个变量

p argv[0]查看第一个变量是什么

 设置字符串的显示规则

set p null-stop//设置字符串不显示后面的空余空间

 设置结构体和数组显示规则

set p pretty//结构体和数组显示规则更好看,每行一个

 使用GDB内嵌函数

sizeof:显示数据大小

 变量查看和修改

在一个循环中,为了加快循环,可以设置循环条件的值,例如下面代码中,for循环10次,在第3次的时候,通过设置i=10,可以提前结束循环

注意事项1:如果按照这种方式,那么后续的值也不会边,相当于for中的语句就不会执行累加

注意事项2:对于输入的参数也可以进行修改,类似代码运行输入1,我们可以在gdb中设置为2

修改整型

p int=10

修改字符串

p str=“str”

 

 设置字符串无效

关于C ++:在gdb中设置字符串 | 码农家园 (codenong.com)

修改结构体

p test.name="str"

p test.agr=10

p strcpy(test.name, "str")

内存查看和修改 

从内存地址修改

查看内存 

x /d 10进制显示

x /b 二进制显示

x /s显示字符串

查看整型

查看字符串

 查看字符串

寄存器查看和修改

如果没有加-g,那么不能直接用 i 和 p取查看信息,这时候只能通过查看寄存器里面的值

 查看

对于函数参数少于6个的就在这里,多了的就在栈里面

普通参数:正常显示 i r 寄存器

指针:先找到地址,再利用 x 或者 p

 修改

在程序执行中,我可能执行了第一步不想执行第二步,而直接执行第三步,那么我就需要找到第三步的汇编地址,然后执行这个地址。

rip和pc寄存器用来存放下一个需要执行指令的地址,因此我们就是找到需要执行指令的地址,然后设置rip寄存器

注意事项:可以进行代码回退,也就是执行之前的代码

查看某行指令地址:i line 16

修改rip寄存器:p ¥rip=地址

                         set var $rip=地址

 源代码查看搜索

查看

设置显示行数:set listsize 10

显示指定函数代码:l 文件::函数

希纳是指定文件行数:l 文件::行数

 

 搜索

search:往下搜索

forward-search:往下搜索

reverse-search:往上搜索

show directory:显示当前代码搜索路径

directory 路径:设置搜索代码的文件路径。一般有当前路径+工作路径

注意事项:可以通过 l 行数去跳转搜索的起始位置

 函数调用栈管理

栈帧

当一个函数执行了还没有返,就称它为一个栈帧,这个栈帧存放在函数在栈中,当函数退出才会消失

查看有哪些栈帧:bt

切换帧: f 帧号

查看栈帧信息

观察点使用

watch 写观察点。当观察点的被写入化时产生中断

rwatch:读观察点。当观察点的值被读取时产生中断

awatch:读写观察点

指定线程的值进行修改:watch 变量 thread 线程号 

查看有哪些线程:i thread

指定某个值为多少时:watch 变量1 + 变量2 > 10

 捕获点

设置该函数为一个特殊断点,当程序执行到这个函数就会中断

普通函数 :catch 函数名字

系统调用:catch syscall 函数名字

 为断点执行命令

1.设置一个断点命令,当断点执行到这里时,可以输出一些元素值

commads

命令1

命令2

end

2.删除断点命令。不需要再打印

commads 断点号

end

 

保存断点信息

save breakpoints 文件名.txt

 还原断点信息

source 文件名.txt

窗口管理

打开一个ui界面,方便使用

 查看对象类型

查看变量具体信息,例如属于哪一个类,是基类还是派生类

whatis 名字

set print object on显示new对象真实的类

ptype /r 不用

ptype /o 结构体成员有多大,偏移量是多少

ptype /m 不显示成员函数

ptype /t

i variables 名字:对于全局和静态变量查看,可以再哪个文件下定义

 

 

多线程调试管理

info threads:查看所有线程信息

thread num:切换线程

线程查找,线程断点 

thread find:查找线程(只能查找地址,id,名字。后面的函数不能)

thread name:设置线程名字(先切换到像改名字的线程,然后执行)

b breakpoint thread id:为线程设置断点(只有设置的线程会在中断处停止,其他线程不会)

 

 为线程执行命令

thread apply 2 3 i args 显示线程2,线程3的参数

thread apply 2-6 i args 显示线程2-6的参数

thread apply all i args显示所有线程的参数

thread apply 2 -s i args对线程2执行 i args命令,如果命令错误就没有提示

thread apply 2 3 -q i args会把线程2,线程3的信息连在一起显示

 

 

 线程的日志信息控制

线程创建和结束时会在终端打印很多输出,为了不影响观看,于是可以控制

show print thread-events:查看当前线程显示状态

set print thread-events off:关闭当前线程显示状态

 外部命令和保存文件

在gdb中可以使用shell命令,也可以使用 ! 代替shell

设置保存debug文件:set logging file 名字.txt

保存文件:set logging on

查看文件:!cat 文件.txt 或者 shell cat 文件.txt

 跳转执行

在gdb调试中,可以回溯到之前代码,或者跳过前面的代码直接执行后面代码

1.通过找到line的地址,设置寄存器

2.在line设置断点,然后 jump 行数

3.通过标签,然后jump 标签

 反向执行undo

代码执行正常是从上往下,那么现在是从下往上。对于代码而言,就相当于一个变量从赋值状态变为没赋值,把给他的值撤销了

先record,再利用rn回溯

 

 多进程

调试子进程

默认是父进程调试。如果要设置子进程需要进行设置

set follow-fork-mode child

父进程和子进程一起调试

先设置到子进程,然后

set detach-on-fork off:关闭父进程的detach

i inferiors查看当前进程及其子进程信息

inferior 号码:切换进程号码

 多进程调试

inferior就是一个调试对象,就是一个调试进程

首先在新建一个gdb,此时i inferior是空的,执行需要调试的进程,首先add-inferior,然后利用attach 进程号进行添加,然后再重复这个过程

在调试过程中,可以只执行一个进程,或者两个都执行。

show schedule-multiple:显示是否所有进程都执行

set schedule-multiple on:开启所有进程一起执行

detach inferiors 号码:关闭号码调试的进程

remove-inferior:删除一个add之后的inferior(不能删除当前的,只能删除之前的)

调试时调用内部函数和外部函数

内部函数

p 函数(参数)

call 函数(参数)

注意事项:如果函数没有返回值,void不会显示 

 

 外部函数

调试时跳过指定函数

 1.进入函数执行finish或者return,可以结束这个函数

跳过一个文件执行

 skip file 文件

 跳过一个目录下所有文件

skip -gfi 文件夹/*.*

 制作和调试发行版

为了调试一些没有调试信息的程序

制作发行版本

1.不加-g

2.利用strip:strip -g release-section -o release。可以直接利用带调试信息的生成没有调试信息的可执行文件

 1.调试发行版的可执行文件

gdb --symbol=release-section -exec=release

 直接利用带有调试信息的版本调试没有调试信息的

2.利用待调试信息的可执行文件单独生成调试信息给可执行程序

objcopy --only-keep-debug release-section debug.sym
gdb --symbol=debug.sym -exec=release
 

 修改可执行文件

首先对调试文件利用写的gdb进入:gdb --write 调试文件

然后修改某个函数的值

1.disassemble /mr check_some:查看汇编代码

2. p {unsigned char}地址=0x65:修改某一个字节的值

3.q退出来执行 

内存泄漏检测

通过gdb来查看某些函数是否有内存泄漏问题。比较函数进出的内存占用情况来判断

注意事项:在内存中,除了malloc分配地址,本身也还有链表来存储空间也需要内存

call malloc_stats()查看当前的内存分布

call malloc_info(0,stdout)把内存分布情况按照xml格式输出

加入 -fsanitize=address选项,在发生内存泄漏,堆栈溢出,野指针,全局内存会直接定位到具体代码

远程调试 

 远程调试

利用客户端调试远程服务端。服务端需要按照gdbserver

服务端:gdbserver ip:9988 ./调试文件

客户端:1: gdb

               2:target remote ip:9988

死锁调试

利用attach把程序加进来,然后查看线程,以及分析线程的bt来确定是否有死锁

核心存储core-dump

 为活着的进程生成core-dump文件

1.利用gdb attach 进程号添加进程

2.利用gcore test.core生成文件

 当程序发送段错误时生成core-dump文件

ulimit -c 查看是否允许保留core文件。0为不保存

ulimit -c unlimited 允许生成core文件

修改生成dump文件的名字:sudo echo -e "%e-%p-%t" > /proc/sys/kernel/core_pattern

利用dump文件进行调试

 

软件密码“破解”

通过 ri 汇编执行到出错位置,查看输入寄存器rsi和rdi,对比结果找到答案

BUG专区

1.gab attach出错:ptrace: 不允许的操作.attach: 没有那个文件或目录

解决办法:

编辑/etc/sysctl.d/10-ptrace.conf这个文件,若没有,创建之。设置(默认是1)

kernel.yama.ptrace_scope = 0

在后续使用中,开启sudo执行命令,例如sudo gdb attach pid即可解决

2./sysdeps/unix/sysv/linux/read.c不存在

解决办法:

在你确少信息的目录添加这个文件,文件内容如下

/* Linux read syscall implementation.
   Copyright (C) 2017-2022 Free Software Foundation, Inc.
   This file is part of the GNU C Library.

   The GNU C Library is free software; you can redistribute it and/or
   modify it under the terms of the GNU Lesser General Public
   License as published by the Free Software Foundation; either
   version 2.1 of the License, or (at your option) any later version.

   The GNU C Library is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
   Lesser General Public License for more details.

   You should have received a copy of the GNU Lesser General Public
   License along with the GNU C Library; if not, see
   <https://www.gnu.org/licenses/>.  */

#include <unistd.h>
#include <sysdep-cancel.h>

/* Read NBYTES into BUF from FD.  Return the number read or -1.  */
ssize_t
__libc_read (int fd, void *buf, size_t nbytes)
{
  return SYSCALL_CANCEL (read, fd, buf, nbytes);
}
libc_hidden_def (__libc_read)

libc_hidden_def (__read)
weak_alias (__libc_read, __read)
libc_hidden_def (read)
weak_alias (__libc_read, read)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/668282.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

apm装机教程(二):四旋翼

文章目录 前言一、接线二、刷固件三、设置机架四、校准遥控器五、设置遥控开关六、校准传感器七、设置参数 前言 硬件&#xff1a; pix2.4.8 250穿越机 云卓T10遥控 软件&#xff1a; APM4.3.7 QGC MP 一、接线 GPS接gps和i2c口&#xff0c;接收机的p/s口接飞控RCIN 二、刷…

SAP从入门到放弃系列之BOM行项目类别-R类别-Part3

文章目录 一、BOM行项目类别设置二、BOM主数据维护三、参数详解3.1、尺寸大小3.2、尺寸大小单位3.3、公式3.4、所需数量3.5、可变尺寸数量3.6、可变尺寸数量单位 四、测试示例演示&#xff1a;小结 一、BOM行项目类别设置 创建或者更改BOM时&#xff0c;BOM行项目类别选择R&am…

SSM超市库存商品管理系统+jsp【附万字文档(Lun文)】

主要功能 管理员权限登录&#xff1a; ①主页、个人中心&#xff1a;修改密码、个人信息 ②员工管理&#xff1a;可以根据员工姓名、手机号、身份证查询&#xff0c;以及增删改查操作 ③会员管理&#xff1a;可以根据会员姓名、手机号、身份证查询&#xff0c;以及增删改查操作…

【进阶]Java:线程通信(了解)

什么是线程通信&#xff1f; 当多个线程共同操作共享的资源时&#xff0c;线程间通过某种方式互相告知自己的状态&#xff0c;以相互协调&#xff0c;并避免无效的资源争夺。 线程通信的常见模型&#xff08;生产者与消费者模型&#xff09; 生产者线程负责生产数据消费者线…

IDE/VS2017社区版安装+Qt部署+旧项目迁移

文章目录 概述安装包获取卸载旧版本安装过程首次使用Qt插件配置和使用插件配置Qt项目创建向导 VS2015项目迁移到VS2017 概述 这几天想开始使用glog这个开源日志库&#xff0c;发现其已经在很大程度上使用C14标准了&#xff0c;而VS2015并不能完全支持该标准。根据一些教程试图…

Java的Set接口及其实现类(面试题)

Set接口中没有额外定义新的方法&#xff0c;使用的都是Collection接口中声明过的方法。 * 1. Set接口的框架&#xff1a;** |----Collection接口&#xff1a;单列集合&#xff0c;用来存储一个一个的对象* |----Set接口&#xff1a;存储无序的、不可重复的数据 --&g…

【Spring】— 应用案例——基于注解的Spring MVC应用

目录 应用案例——基于注解的Spring MVC应用1.搭建项目环境2.修改配置文件3.修改Controller类4.启动项目&#xff0c;测试应用 应用案例——基于注解的Spring MVC应用 为了帮助读者熟悉掌握Spring MVC的核心类和注解的使用&#xff0c;接下来将以注解的方式对入门案例进行改写…

CPU多核一定比单核性能强吗

在一般人的眼中&#xff0c;多核性能肯定比单核强&#xff0c;处理器核心越多越好&#xff0c;但果真如此吗&#xff1f; 许多人认为CPU 内核越多越好。然而&#xff0c;情况并非总是如此。这就是为什么更多内核并非在所有情况下都是好的选择&#xff0c;这不仅仅是因为在芯片…

数据结构——单向链表(万字讲解)

单向链表&#xff08;又名单链表、线性链表&#xff09;是链表的一种&#xff0c;其特点是链表的链接方向是单向的&#xff0c;对链表的访问要通过从头部开始&#xff0c;依序往下读取。 //单链表的打印 void SLTPrint(SLTNode* phead) {SLTNode* cur phead;while (cur){pri…

数据孤岛如何形成,企业如何破解?

国内企业数据化现状 在数字化时代&#xff0c;数据已经成为了企业不可或缺的重要资产。企业内部部门或系统之间存在着数据割裂现象&#xff0c;导致数据无法流通和共享&#xff0c;从而形成数据孤岛的现象。对于企业来说&#xff0c;数据孤岛问题是十分普遍的&#xff0c;它阻…

如何在项目管理中获得更多权威和影响力?这篇文章告诉你!

1 透明力 信息力和感知力是对环境的观察、观察、再观察&#xff0c;这些 观察的结果只有透明出来&#xff0c;才能发挥效用。你要想法把你看到的问题可视化&#xff0c;让决策者和团队都能看到问题。即透明的力量。 1.1 怎么运用透明的力量呢&#xff1f; 我曾在某团队经常听…

win11 系统安装 wsl

1. 打开虚拟设置 在【开始】搜索【启用或关闭 Windows 功能】&#xff0c;打开Windows 功能对话框&#xff0c;勾选“适用于Linux的Windows子系统”和“虚拟机平台”两个选项。 2. wsl 安装 管理员模式启动powershell 设置wsl版本&#xff1a;wsl --set-default-version 1 更新…

业务 IT 一体化:华为云 SaaS Package 做到了

SaaS 这个概念在近两年可谓十分火热&#xff0c;特别是进入到了后疫情时代&#xff0c;似乎离不开 SasS。然而很多人并没有真正理解 SaaS 的概念&#xff0c;对 SaaS 的认知还是比较片面。 你要弄清 SaaS&#xff0c;首先就绕不开 laaS 和 PaaS。下面这张图可以很直观地让你明…

leetcode40. 组合总和 II (java-回溯算法)

组合总和 II leetcode40. 组合总和 II题目描述解题思路代码演示 回溯算法专题 leetcode40. 组合总和 II 来源&#xff1a;力扣&#xff08;LeetCode&#xff09; 链接&#xff1a;https://leetcode.cn/problems/combination-sum-ii 题目描述 给定一个候选人编号的集合 candida…

【滤波】扩展卡尔曼滤波器

本文主要翻译自rlabbe/Kalman-and-Bayesian-Filters-in-Python的第11章节11-Extended-Kalman-Filters&#xff08;扩展卡尔曼滤波&#xff09;。 %matplotlib inline#format the book import book_format book_format.set_style()我们发展了线性卡尔曼滤波器的理论。然后在上两…

Fiddler之日常使用简介

目录 前言&#xff1a; Fiddler界面简介 一、Fiddler抓取http、https请求配置 二、抓取指定域名会话 三、http请求统计试图 前言&#xff1a; Fiddler是一款功能强大的Web调试工具&#xff0c;它可以帮助开发人员在开发和测试过程中捕获、修改和检查HTTP请求和响应。 使用Fiddl…

Python基础(11)——Python循环(while、for)

Python基础&#xff08;11&#xff09;——Python循环&#xff08;while、for&#xff09; 文章目录 Python基础&#xff08;11&#xff09;——Python循环&#xff08;while、for&#xff09;目标一. 循环简介1.1 循环的作用1.2 循环的分类 二. while的语法2.1 快速体验 三. w…

全球开源 AI 游戏开发挑战赛,只等你来!

我们在之前的文章中 预告过 (*划重点&#xff0c;IP 属地法国)&#xff1a;7 月初&#xff0c;我们将举办一次与 AI 游戏相关的黑客松活动&#xff0c;这是有史以来的首次开源游戏开发挑战赛&#xff0c;借助人工智能工具释放你的创造力&#xff0c;一起打破游戏开发的边界。 比…

Python自动化测试 软件测试最全教程(附笔记),看完就可就业

最近看到很多粉丝在后台私信我&#xff0c;叫我做一期Python自动化测试的教程&#xff0c;其实关于这个问题&#xff0c;我也早就在着手准备了&#xff0c;我录制了一整套完整的Python自动化测试的教程&#xff0c;都上传在B站上面&#xff0c;大家有兴趣的可以去看一下&#x…

Redis 2023面试5题(二)

一、Redis key没设置过期时间却被redis主动删除了 如果一个 Redis 键没有设置过期时间&#xff0c;那么 Redis 无法判断该键是否应该自动删除。因此&#xff0c;如果一个没有设置过期时间的键被 Redis 主动删除了&#xff0c;可能是以下原因之一&#xff1a; 内存不足&#x…