首页 > 系统相关 >Linux GDB Debugging

Linux GDB Debugging

时间:2022-12-13 13:32:01浏览次数:68  
标签:Debugging 函数 程序 gdb 命令 GDB Linux 断点

Linux GDB Debugging

Catalog

1. GDB Introduction
2. GDB基本命令

 

1. GDB Introduction

GDB是GNU开源组织发布的一个强大的UNIX下的程序调试工具,GDB主要可帮助工程师完成下面4个方面的功能

1. 启动程序,可以按照工程师自定义的要求随心所欲的运行程序
2. 让被调试的程序在工程师指定的断点处停住,断点可以是条件表达式
3. 当程序被停住时,可以检查此时程序中所发生的事,并追索上文
4. 动态地改变程序的执行环境

在命令行上键入gdb并按回车键就可以运行gdb了, 如果一切正常的话, gdb 将被启动并且你将在屏幕上看到类似的内容

GNU gdb (GDB) Red Hat Enterprise Linux (7.2-75.el6)
Copyright (C) 2010 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "x86_64-redhat-linux-gnu".
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
(gdb)
//当启动gdb后,我们能在命令行上指定很多的选项: gdb -h
aliases -- Aliases of other commands
breakpoints -- Making program stop at certain points
data -- Examining data
files -- Specifying and examining files
internals -- Maintenance commands
obscure -- Obscure features
running -- Running the program
stack -- Examining the stack
status -- Status inquiries
support -- Support facilities
tracepoints -- Tracing of program execution without stopping the program
user-defined -- User-defined commands

0x1: GDB启动

//当用这种方式运行gdb,我们能直接指定想要调试的程序. 这将告诉gdb装入名为fname的可执行文件
1. gdb <program>

//我们也可以用gdb去检查一个因程序异常终止而产生的core dump文件
2. gdb <corename>

//与一个正在运行的程序相连,gdb会自动attach上去,并调试它,program应该在PATH环境变量中搜索得到
3. gdb programname pid

0x2: GDB启动参数

gdb [-help] [-nx] [-q] [-batch] [-cd=dir] [-f] [-b bps] [-tty=dev] [-s symfile] [-e prog] [-se prog] [-c core] [-x cmds] [-d dir] [prog[core|procID]]

1. -help (-h): 列出所有选项,并附简要说明
2. -symbols=file (-s file): 读出文件(file)中的符号表
3. -write: 开通(enable)往可执行文件和核心文件写的权限
4. -exec=file (-e file): 在适当时候把File作为可执行的文件执行,来检测与core dump结合的数据
5. -se File: 从File读取符号表并把它作为可执行文件
6. -core File (-c File): 把File作为core dump来执行
7. -directory=Directory (-d Directory): 把Dicrctory加入源文件搜索的路径中
8. -cd=Directory: 运行GDB,使用Directory作为它的工作目录,取代当前工作目录

0x3: 为调试编译代码

为了使gdb正常工作,你必须使你的程序在编译时包含调试信息(DEBUG信息)。调试信息包含你程序里的每个变量的类型和在可执行文件里的地址映射以及源代码的行号。gdb利用这些信息使源代码和机器码相关联

//在编译时用"-g"选项打开调试选项
gcc –g gdb_example.c –o gdb_example
g++ –g gdb_example.c –o gdb_example

 

2. GDB基本命令

0x1: 测试环境准备

#include <stdio.h> 
#include <string.h>
#include <malloc.h>

void my_print (char *string)
{
printf ("The string is %s\n", string);
}

void my_print2 (char *string)
{
char *string2;
int size, i;

size = strlen (string);
string2 = (char *) malloc (size + 1);

for (i = 0; i < size; i++)
{
string2[size - i] = string[i];
}
string2[size+1] = '\0';

printf ("The string printed backward is %s\n", string2);
}

main ()
{
char my_string[] = "hello there";

my_print (my_string);
my_print2 (my_string);
}
//gcc -g test.c -o test

Linux GDB Debugging_GDB

结果不符合预期,我们通过GDB调试这个程序来学习GDB的调试命令

0x2: list命令

在gdb中运行"list/l"命令可以列出代码

1. 显示程序第linenum行周围的源程序
list <linenum>
l <linenum>

2. 显示函数名为function的函数的源程序
list <function>
l <function>

3. 显示当前行后面的源程序
list

4. 显示当前行前面的源程序
list -

Linux GDB Debugging_内存地址_02

0x3: run命令

在gdb中,运行程序使用run命令,run指令会重头运行一次程序。在程序运行前,我们可以设置如下4方面的工作环境

1. 程序运行参数  
1) 指定运行时参数: set args 10 20 30 40 50
2) 查看设置好的运行参数: show args
2. 运行环境
1) 设定程序的运行路径: path <dir>
2) 查看程序的运行路径: show paths
3) 设置环境变量: set environment varname [=value],如set env USER=baohua;
4) 查看环境变量: show environment [varname]
3. 工作目录
1) cd <dir>: 相当于shell的cd命令
2) pwd: 显示当前所在的目录。
4. 程序的输入输出
1) info terminal: 用于显示程序用到的终端的模式
2) gdb中也可以使用重定向控制程序输出,如: run > outfile
3) tty命令可以指定输入输出的终端设备,如:tty /dev/ttyS1

在gdb提示符下按回车健将重复上一个命令

0x4: break命令

在gdb中用break命令来设置断点,设置断点的方法包括

1. 在进入指定函数时停住,C++中可以使用class::function或function(type, type)格式来指定函数名  
break <function>

2. 在指定行号停住
break <linenum>

3. 在当前行号的前面或后面的offset行停住,offiset为自然数
break +offset
break -offset

4. 在源文件filename的linenum行处停住
break filename:linenum

5. 在源文件filename的function函数的入口处停住
break filename:function

6. 在程序运行的内存地址处停住
break *address

7. break命令没有参数时,表示在下一条指令处停住
break

8. 条件IF断点
break ... if <condition>
1) "..."可以是上述的break <linenum>、break +offset / break –offset中的参数
2) condition表示条件
在条件成立时停住。比如在循环体中,可以设置break if i=100,表示当i为100时停住程序

9. xbreak
在当前函数的退出的点上设置一个断点

10. txbreak
在当前函数的退出的点上设置一个临时的断点(只可使用一次)

11. 查看断点时
info
info breakpoints [n]、info break [n](n表示断点号)

0x5: 单步命令

在调试过程中

1. next/n命令: 用于单步执行,类似VC++中的step over,next单步不会进入函数的内部
2. step/s命令: 在单步执行一个函数时,会进入其内部,类似VC++中的step into

单步执行的更复杂用法包括

1. 单步跟踪
step <count>
如果有函数调用,则"进入"该函数(进入函数的前提是,此函数被编译有debug信息)。step后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住

2. 单步跟踪next <count>
如果有函数调用,它"不会"进入该函数。同样地,next后面不加count表示一条条地执行,加表示执行后面的count条指令,然后再停住

3. set step-mode
1) set step-mode on: 打开step-mode模式,这样,在进行单步跟踪时,程序不会因为没有debug信息而不停住,这个参数的设置可便于查看机器码
2) set step-mod off: 关闭step-mode模式。

4. finish
运行程序,直到当前函数完成返回,并打印函数返回时的堆栈地址和返回值及参数值等信息

5. until/u
一直在循环体内执行单步,退不出来是一件令人烦恼的事情,until命令可以运行程序直到退出循环体

6. stepi/si、nexti/ni
stepi和nexti用于单步跟踪一条机器指令,一条程序代码有可能由数条机器指令完成,stepi和nexti可以单步执行机器指令

7. display/i $pc
单步跟踪会在打出程序代码的同时打出机器指令,即汇编代码

0x6: continue命令

当程序被停住后,可以使用continue/c命令,(fg命令同continue命令)恢复程序的运行直到程序结束,或到达下一个断点,命令格式为

continue [ignore-count]
c [ignore-count]
fg [ignore-count]
//ignore-count表示忽略其后多少次断点

0x7: print命令

在调试程序时,当程序被停住时,可以使用print/p命令,或是同义命令inspect来查看当前程序的运行数据。print命令的格式是

print <expr>  
//<expr>是表达式,是被调试的程序中的表达式

print /<f> <expr>
/*
<f>是输出的格式
1. x: 按十六进制格式显示变量
2. d: 按十进制格式显示变量
3. u: 按十六进制格式显示无符号整型
4. o: 按八进制格式显示变量
5. t: 按二进制格式显示变量
6. a: 按十六进制格式显示变量
7. c: 按字符格式显示变量
8. f: 按浮点数格式显示变量
*/

expr: 表达式
在表达式中,有几种GDB所支持的操作符,它们可以用在任何一种语言中
1. "@"是一个和数组有关的操作符
2. "::"指定一个在文件或是函数中的变量
3. "{<type>} <addr>"表示一个指向内存地址<addr>的类型为type的一个对象

0x8: watch命令

watch一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序。我们有下面的几种方法来设置观察点
1. watch <expr>
为表达式(变量)expr设置一个观察点。一量表达式值有变化时,马上停住程序

2. rwatch <expr>
当表达式(变量)expr被读时,停住程序

3. awatch <expr>
当表达式(变量)的值被读或被写时,停住程序

4. info watchpoints
列出当前所设置了的所有观察点

0x9: examine命令

我们可以使用examine/x命令,来查看内存地址中的值。examine命令的语法如下所示

x/<n/f/u> <addr> 
1. <addr>: 表示一个内存地址
2. <n/f/u>: 可选的参数
1) n: 一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容
2) f: 显示的格式,如果地址所指的是字符串,那么格式可以是s,如果地址是指令地址,那么格式可以是i
3) u: 表示从当前地址往后请求的字节数,如果不指定的话,GDB默认是4字节。u参数可以被一些字符代替
4) b: 表示单字节
5) h: 表示双字节
6) w: 表示四字节
7) g: 表示八字节
当我们指定了字节长度后,GDB会从指定的内存地址开始,读写指定字节,并把其当作一个值取出来。n、f、u这3个参数可以一起使用,例如命令
x/3uh 0x54320: 表示从内存地址0x54320开始以双字节为1个单位(h)、16进制方式(u)显示3个单位(3)的内存

0x10: set命令

修改寄存器  
1. set $v0 = 0x004000000
2. set $epc = 0xbfc00000

修改内存
1. set {unsigned int}0x8048a51=0x0

0x11: jump命令

一般来说,被调试程序会按照程序代码的运行顺序依次执行,但是GDB也提供了乱序执行的功能,也就是说,GDB可以修改程序的执行顺序,从而让程序随意跳跃

1. jump <linespec>: 指定下一条语句的运行点
1) <linespec>可以是文件的行号
2) 可以是file:line格式
3) 也可以是+num这种偏移量格式,表示下一条运行语句从哪里开始

2. jump <address>
这里的<address>是代码行的内存地址
//注意,jump命令不会改变当前的程序栈中的内容(它是纯粹的EIP修改跳转),所以,如果使用jump从一个函数跳转到另一个函数,当跳转到的函数运行完返回,进行出栈操作时必然会发生错误,这可能导致意想不到的结果,所以最好只用jump在同一个函数中进行跳转

0x12: signal命令

使用singal命令,可以产生一个信号量给被调试的程序,如中断信号"Ctrl+C"。这非常方便于程序的调试,可以在程序运行的任意位置设置断点,并在该断点用GDB产生一个信号量,这种精确地在某处产生信号的方法非常有利于程序的调试

signal命令的语法是:signal <signal>
//UNIX的系统信号量通常从1到15,所以<signal>取值也在这个范围

0x13: return命令

如果在函数中设置了调试断点,在断点后还有语句没有执行完,这时候我们可以使用return命令强制函数忽略还没有执行的语句并返回

return
return <expression>
//return命令用于取消当前函数的执行,并立即返回,如果指定了<expression>,那么该表达式的值会被作为函数的返回值

0x14: call命令

call命令用于强制调用某函数

call <expr> 
表达式中可以一是函数,以此达到强制调用函数的目的,它会显示函数的返回值(如果函数返回值不是void)

0x15: info命令

info命令可以在调试时用来查看相关信息

1. 寄存器
1) info registers: 查看除了浮点寄存器以外的寄存器
2) info all-registers: 查看所有寄存器,包括浮点寄存器
3) info registers <regname ...>: 查看所指定的寄存器

2. 断点
1) info break: 查看断点信息

3. 观察点
1) info watchpoints: 列出当前所设置的所有观察点

4. 信号
1) info signals: 查看有哪些信号正在被GDB检测
2) info handle: 查看有哪些信号正在被GDB检测

5. info line <xx>: 查看源代码在内存中的地址
info line后面可以跟行号、函数名、文件名:行号、文件名:函数名等多种形式,例如下面的命令会打印出所指定的源码在运行时的内存地址:
//info line tst.c:func

6. info threads: 查看多线程

0x16: set scheduler-locking off|on|step

1. off: 不锁定任何线程,也就是所有线程都执行,这是默认值。 
2. on: 只有当前被调试程序会执行
3. step: 在单步的时候,除了next过一个函数的情况以外,只有当前线程会执行

与多线程调试相关的命令还包括

1. thread ID
切换当前调试的线程为指定ID的线程

2. break thread_test.c:123 thread all
在所有线程中相应的行上设置断点

3. thread apply ID1 ID2 command
让一个或者多个线程执行GDB命令command

4. thread apply all command
让所有被调试线程执行GDB命令command

0x17:disassemble

disassemble命令用于反汇编,它可被用来查看当前执行时的源代码的机器码,其实际上只是把目前内存中的指令dump出来

1. 反汇编一个函数
disass func_name

2. 反汇编一段内存地址, 第1个参数是起始地址,第2个是终止地址
disassemble 0x0 0x10
//可以使用 info line 命令来映射一个源码行到程序地址,然后使用命令disassemble显示一个地址范围的机器指令

3. disassemble 不带参数
默认的反汇编范围是 所选择帧的pc附近的函数

Linux GDB Debugging_寄存器_03

0x18: kill [filename]

终止正在调试的程序

0x19: clear

删除一个断点,这个命令需要指定代码行或者函数名作为参数 

0x20: bt/Backtrace

显示程序堆栈信息,即显示函数调用栈的信息

0x21: enable、enable

1. disable: 禁止断点功能,这个命令需要禁止的断点在断点列表索引值作为参数
2. enable: 允许断点功能,这个命令需要允许的断点在断点列表索引值作为参数

0x22: ignore

忽略某个断点制定的次数

ignore 4 23: 忽略断点4的23次运行,在第24次的时候中断

0x23: load

动态载入一个可执行文件到调试器

0x24: whatis

显示变量的值和类型

0x25: ptype

显示变量的类型

0x26: make

使你能不退出GDB就可以重新产生可执行文件

0x27: shell

使你能不离开GDB就执行 UNIX shell 命令

Relevant Link:

http://www.chinalinuxpub.com/doc/pro/gdb.html 
http://www.vimer.cn/2009/11/%E4%BD%BF%E7%94%A8gdb%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F%E8%AF%A6%E8%A7%A3.html
https://www.ibm.com/developerworks/cn/linux/sdk/gdb/

http://www.vimer.cn/2009/11/%E4%BD%BF%E7%94%A8gdb%E8%B0%83%E8%AF%95%E7%A8%8B%E5%BA%8F%E8%AF%A6%E8%A7%A3.html

 

Copyright (c) 2015 LittleHann All rights reserved

 



标签:Debugging,函数,程序,gdb,命令,GDB,Linux,断点
From: https://blog.51cto.com/u_15775105/5933870

相关文章

  • Linux相关命令
    目录相关命令1.pwd显示当前工作目录绝对路径2.ls列出目录下全部文件ls-a显示全部文件,包括隐藏文件ls-l可简化成ll,列出详细信息,包括文件的属性和权限3.cd切换到指......
  • 【Azure 应用服务】PHP应用部署在App Service for Linux环境中,上传文件大于1MB时,遇见
    问题描述在PHP项目部署在AppService后,上传文件如果大于1MB就会遇见413RequestEntityTooLarge的问题。 问题解决目前这个问题,首先需要分析应用所在的环境。在AppSe......
  • linux c 语言 strsep trim isspace
     函数原型:              char*strtok(char*s,constchar*delim);                       char*strsep......
  • Linux libxls和xlslib读写Excel文档【转】
    转自:https://www.joxrays.com/linux-xls/这里要讨论的是两款开源库libxls和xlslib,前者用与读Excel,后者用于写.所以可以在Linux或Windows上使用libxls(读Excel......
  • 【安装】Linux安装Elasticsearch教程
    Elastic官网​​开源搜索:Elasticsearch、ELKStack和Kibana的开发者|Elastic​​Elasticsearch(官网:​​https://www.elastic.co/cn/products/elasticsearch​​ )需要......
  • Linux 系统日常巡检脚本
    https://www.pythondesign.cn/994.htmlLinux系统日常巡检脚本,巡检内容包含了,磁盘,内存cpu进程文件更改用户登录等一系列的操作直接用就行了报告以邮件发送到邮箱在......
  • 【Linux】Linux 快捷配置 alias
     alias ll="ls-l" 使用普通用户登录,执行cd~就进入家目录了,一把是在/home/普通用户名,.bashrc就在家目录里,ls-a就能看到以.开头的隐藏文件了。  可以配置全局变量vi/......
  • 【Linux】PHP 执行 shell脚本
    需要去除禁用的函数 去php.ini 查询php是哪个用户执行的psaux|grepphp  需要配置执行php的用户权限vi/etc/sudoers##Allowroottorunanycommandsanywhereroo......
  • 【Linux】Linux 同步远程文件 或 本地文件 rsync命令
    目录​​介绍​​​​特征​​​​用法​​​​远程拷贝同步文件、目录​​​​本地到远程​​​​远程到本地​​​​本地拷贝同步文件、目录​​​​同步一个文件从本地一......
  • linux查看服务器参数
    cpu物理cpu,核数,逻辑cpu数物理cpu(physicalid):主板上实际插入cpu数量cpu核心数(cpucores):单块cpu上能处理数据的芯片组的数量,双核,四核等逻辑cpu:=物理cpu个数*每个cp......