0%

GDB常用指令

GDB

官方资料

陈皓大神笔记:1234567答疑

本笔记基于陈皓大神的笔记

启动GDB

调试程序

gdb <program>

调试core

gdb <program> core

调试运行中的进程

gdb <program> <PID>

gdb attach <PID>

启动时常用参数

  • -s/-symbols <file> :指定符号表
  • -se file:指定文件中读取符号表信息
  • -directory\-d <directory>:加入一个源文件的搜索路径,默认搜索路径是环境变量中PATH所定义的路径。
  • -core/-c <file>:调试时core dump的core文件

启动时常用指令

程序运行参数

1
2
set args #可指定运行时参数。(如:set args 10 20 30 40 50)
show args #命令可以查看设置好的运行参数。

设置运行环境

1
2
3
4
path <dir> #可设定程序的运行路径。
show paths #查看程序的运行路径。
set environment varname [=value] #设置环境变量。如:set env USER=hchen
show environment [varname] #查看环境变量。

设置工作目录

1
2
cd <dir> #相当于shell的cd命令。
pwd #显示当前的所在目录。

程序的输入输出

1
2
info terminal #显示你程序用到的终端的模式。
run > outfile #使用重定向控制程序输出

运行shell命令

shell <command string>

可以在gdb中直接make,rebuild 程序

make <make-args> = shell make <make-args>

暂停/恢复

设置断点

  • 函数

    break <function>/<filename:function>

    c++中可以使用class::function或function(type,type)格式来指定函数名。

  • 行号

    break <linenum>/<filename:linenum>

  • 内存:

    break *address

    在程序运行的内存地址处停住

  • 条件

    break ... if <condition>

    …可以是上述的参数,condition表示条件

  • 打印断点

    info breakpoints/break [n]

设置观察点

观察某个表达式(变量也是一种表达式)的值是否有变化了

  • expr值有变化时,马上停住程序

    watch <expr>

  • expr被读时,停住程序

    rwatch <expr>

  • expr被读或被写时,停住程序

    awatch <expr>

  • 打印观察点

    info watchpoints

设置捕获事件

捕捉程序运行时的一些事件

  • 格式

    • catch <event>
    • tcatch <event>:设置捕捉点,当停住后自动删除。
  • 事件

    • throw :C++抛出的异常
    • catch:C++捕捉到的异常
    • exec/fork/vfork:exec/fork/vfork被调用
      • load/unload:载入/卸载动态库

维护停止点与停止条件

  • clear:清除所有的停止点
  • clear <function>/<filename:function>: 清除该函数上所有的停止点
  • clear <linenum>/<filename:linenum>:清除该行上所有的停止点
  • delete/disable/enable [breakpoints] [range...]:删除/禁用/使能指定断点
  • condition <bnum> <expression>:修改断点停止条件,bnum—断点号
  • condition <bnum>:删除断点停止条件
  • ignore <bnum> <count>:忽略断点的停止条件count次

恢复运行与单步调试

  • 继续:continue/fg [ignore-count]

    ignore-count:跳过断点次数

  • 逐语句:step <count>

  • 逐过程:next <count>

  • step-mode模式:set step-mode on/off

    单步跟踪时,程序不会因为没有debug信息而不停住

  • 离开当前函数:finish

  • 离开当前循环体:until/u

  • 单步一条机器指令:stepi/si/nexti/ni

  • 运行:run/r

信号

  • 指令

    handle <signal> <keywords...>

  • keywords

    • nostop:不停止运行,但会打印信息
    • stop:停止运行。
    • print:打印信息
    • noprint:不打印信息
    • pass/noignore:信号下发给程序
    • nopass/ignore:信号不下发给程序
  • 查看有哪些信号在被GDB检测

    info signals/handle

多线程调试

当你的程序被GDB停住时,所有的运行线程都会被停住

  • 查看线程

    info threads

  • 切换线程

    thread <ID>

  • 特定线程打断点

    break <linespec> thread <threadno> [if ...]

  • 控制其他线程

    set scheduler-locking off|on|step

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

查看信息

查看栈信息

  • 栈的所有信息
    • bt:调用栈的所有信息
    • bt <n> :打印栈顶上n层的栈信息
    • bt <-n>:打印栈底下n层的栈信息
  • 切换当前栈
    • 默认当前层:栈顶层
    • f <n>:切换至第n层
    • up/down <n>:向上/下面移动n层,可以不打n,表示向上/下移动一层
  • 信息打印
    • info f:当前栈层的详情
    • info args:入参及其值
    • info locals:所有局部变量及其值。

查看源程序

显示源代码

  • list <linenum>/<function>/<first>, <last>/ , <last>/<+|-offset>:显示周围代码/函数代码/行区域代码/向前|后便宜
  • set listsize <count>:设置一次显示源代码的行数

搜索源代码

  • 向前搜索:forward-search/search <regexp>,regexp为正则表达式
  • 全部搜索:reverse-search <regexp>

源文件路径

  • 设置路径

    directory <dirname ... >

    dir <dirname ... >

  • 清除路径

    directory

  • 显示路径

    show directories

源代码的内存

  • 查看源码在内存中的地址

    info line <function>/<filename:function>/<linenum>/<filename:linenum>

  • 查看函数的汇编代码

    disassemble <function>/<filename:function>

查看变量

指令格式

  • 命令

    print <expr>

    print /<f> <expr>:f 输出格式

  • 操作符

    • @:是一个和数组有关的操作符
    • :::指定一个在文件或是一个函数中的变量。
    • {<type>} <addr>:表示一个指向内存地址\的类型为type的一个对象。

数组

p *array@len

输出格式

  • x:按十六进制格式显示变量
  • d:按十进制格式显示变量
  • u:按十六进制格式显示无符号整型
  • o:按八进制格式显示变量
  • t:按二进制格式显示变量
  • a:按十六进制格式显示变量
  • c:按字符格式显示变量
  • f:按浮点数格式显示变量

    查看内存

  • 指令

    examine 简写 x

    x/<n/f/u> <addr>

    例子:x/3uh 0x54320

  • 参数

    • n:表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容
    • f:表示显示的格式,参上
    • u:表示数据宽度,默认是4B。u参数可以用下面的字符来代替
      • b表示单字节
      • h表示双字节
      • w表示四字节
      • g表示八字节

自动显示

设置自动显示的变量,当程序停住时,或单步时,这些变量会自动显示

  • display <expr>/display/<fmt> <expr>/ display/<fmt> <addr>
  • undisplay/delete <dnums...>:删除自动显示
  • disable/enable display <dnums...>:禁用/使能自动显示
  • info display:展示自动显示表

打印的历史记录

每一个print都会被GDB记录下来。GDB会以$1, $2, $3 …..这样的方式为你每一个print命令编上号。于是,你可以使用这个编号访问以前的表达式,如$1

定义环境变量

和shell一样使用$

  • 定义:set $i = 0
  • 显示:show convenience
  • 使用:$i

显示选项

​ 略,个人觉得默认的挺好用的

查看寄存器

​ 略,目前从事服务器开发,不大可能接触。

改变程序的执行

修改变量值

print x=4

跳转执行

  • jump <linespec>

    \:文件的行号,可以是file:line格式,可以是+num这种偏移量格式

  • jump <address>

    \:代码行的内存地址

  • 注意事项:jump不会改变当前的程序栈中的内容,所以,当你从一个函数跳到另一个函数时,当函数运行完返回时进行弹栈时必然会发生错误,所以最好是同一个函数中进行跳转。

产生信号量

  • signal <singal>

  • \:UNIX的系统信号量通常从1到15。所以\取值也在这个范围

  • single命令和shell的kill命令不同,系统的kill命令发信号给被调试程序时,是由GDB截获的,而single命令所发出一信号则是直接发给被调试程序的

强制函数返回

return

return <expression>

强制调用函数

call <expr>

设置生成dump

Windows

  • SetUnhandledExceptionFilter() :崩溃时触发的回调函数
  • 使用dbghelp.lib的MiniDumpWriteDump(),生成dump文件
  • 使用在VS工程中,打开dmp文件
    • 使用仅限本机经
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
#include "stdafx.h"  
#include <windows.h>
#include <DbgHelp.h>
#pragma comment(lib, "dbghelp.lib")

static char* g_szFilePath;
//我们的回调函数
LONG __stdcall ExceptCallBack( EXCEPTION_POINTERS *pExcPointer)
{
MessageBox(NULL,"程序崩溃!",NULL,MB_OK);

//创建dump文件
HANDLE hFile = CreateFile(g_szFilePath, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,FILE_ATTRIBUTE_NORMAL ,NULL);

//向文件写下当前程序崩溃相关信息
MINIDUMP_EXCEPTION_INFORMATION loExceptionInfo;
loExceptionInfo.ExceptionPointers = pExcPointer;
loExceptionInfo.ThreadId = GetCurrentThreadId();
loExceptionInfo.ClientPointers = TRUE;
MiniDumpWriteDump(GetCurrentProcess(), GetCurrentProcessId(),hFile, MiniDumpNormal, &loExceptionInfo, NULL, NULL);
CloseHandle(hFile);

return EXCEPTION_EXECUTE_HANDLER;
}

void Dump_Init(char* szFilePath){
g_szFilePath = szFilePath;
SetUnhandledExceptionFilter(ExceptCallBack);
}
/*
int _tmain(int argc, _TCHAR* argv[])
{
//设置崩溃回调函数
Dump_Init("C:/Users/liliangwei/Desktop/dump.dmp");
int * p = NULL;
*p = 1;
return 0;
} */

Linux

如果无目录名,则core生成在命令运行目录

core 文件大小

ulimit -c unlimited

  • 要永久生效需要,加到shell初始化文件 /etc/profile 中

  • unlimited:不限制、0: 关闭

  • 单位block,默认值1KB,查看 stat -fc %s .

core 文件路径

  • 查看:cat /proc/sys/kernel/core_pattern

  • 临时设置:echo '%e.core.%p' > /proc/sys/kernel/core_pattern

  • 永久设置:sysctl -w kernel.core_pattern=%e.core.%p

路径参数

未设置绝对路径,默认使用进程所在目录

当core_uses_pid=1时,若core_pattern无设置%p,则会自动在末尾跟上

关闭core_uses_pid:sysctl -w kernel.core_uses_pid=0

  • %p:进程id
  • %u:用户id
  • %g:用户组id
  • %s:导致产生core的信号
  • %t:core文件生成时的unix时间
  • %h:主机名
  • %e:进程名

GDB 指令缩写

缩写 原义 意义
b break 打断点
c continue 继续
d delete 删除断点
f frame 栈层跳转
i info 查看信息
j jump 程序跳转
l list 展示源码
n next 单步-过程
p print 打印与设置变量
r run 运行
s step 单步-语句
u until 离开循环体
ni nexti 机器级单步
si stepi 机器级单步
bt backtrace 所有栈信息
wa watch 设置观察点
ig ignore 忽略断点
fin finish 离开函数