赞
踩
嵌入式开发必备工具!!!学就完事了!!!
目录
- 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//结构体和数组显示规则更好看,每行一个
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 标签
代码执行正常是从上往下,那么现在是从下往上。对于代码而言,就相当于一个变量从赋值状态变为没赋值,把给他的值撤销了
先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文件
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,对比结果找到答案
解决办法:
编辑/etc/sysctl.d/10-ptrace.conf这个文件,若没有,创建之。设置(默认是1)
kernel.yama.ptrace_scope = 0
在后续使用中,开启sudo执行命令,例如sudo gdb attach pid即可解决
解决办法:
在你确少信息的目录添加这个文件,文件内容如下
- /* 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)

Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。