ILD

GDB学习笔记1
作者:Yuan Jianpeng 邮箱:yuanjp89@163.com
发布时间:2019-4-17 站点:Inside Linux Development

GDB可以做4种事情

1 运行程序,设定影响它的任何事情。

2 使程序停在特定的条件。

3 当程序暂停时,检查发生了什么。

4 改变程序。以便测试如何纠正bug。


1 一个GDB例子

$ gdb m4

$ set width 70

$ break m4_changequote

Breakpoint 1 at 0x62f4: file builtin.c, line 879.

$ run

Starting program: /work/Editorial/gdb/gnu/m4/m4

$ n

$ s

$ bt

$ p lquote

$ l

$ c

$ quit

set width, 设置GDB的输出宽度。

break m4_changequote,在m4_changequote这个函数断点。

run,开始运行程序。

n,next,advance execution to the next line of the current function. 执行到当前函数的下一行。

s,step,goes to the next line to be executed in any subroutine,运行到子程序的第一行。

bt,backtrace,打印函数调用栈

p,打印变量的值。

l,list,显示当前行附件的源代码。

c,continue,继续执行到下一个断点。

quit,结束GDB session。


2 Getting In and Out of GDB

2.1 Invoking GDB

$ gdb program

$ gdb program core

$ gdb program 1234

第一种是最常用的方式,第二种指定了core文件。第3种方式,指定一个process ID,用来调试运行中的程序。


传递参数的方式如下:

$ gdb --args gcc -O2 -c foo.c


GDB总是把非选项参数,当成可执行文件和core文件(或者process ID)。


2.1.1 Choosing Files

-symbols file

-s file

指定符号文件


-exec file

-e file

指定可执行文件


-se file

同时指定符号文件和可执行文件。


-core file

-c file

指定core dump文件


2.1.2 Choosing Modes

2.1.3 What gdb Does During Startup


2.2 Quiting GDB

quit [expression]

q

Ctrl -d

第一种的expression表示退出的值。


2.3 Shell Commands

GDB可以不退出的情况下执行Shell命令和Make命令

shell command-string

!command-string

!后面有空格,则使用SHELL环境变量指定的shell执行,否则使用默认shell执行,/bin/sh


make make-args


2.4 Logging Output

记录GDB命令的输出到一个文件。

set logging on/off

set logging file file

set logging overwrite [on|off]

set logging redirect [on|off]

show logging


3 GDB Commands

GDB命令支持1个或几个字母的简写。RET命令,重复上一条命令。可以是用TAB补全。


help命令

info命令,显示被调试程序的信息

set命令,设置环境变量

show命令,显示GDB自身的信息。


4 Running Programs Under GDB

DWARF is currently the most expressive and best supported debugging format in gdb.

使用-g选项编译程序。


run命令,可以带参数,这些参数作为要运行程序的参数,这些参数将传递给Shell做扩展。run不带参数,则使用上一次run命令的参数。


也可以使用

set args

show args


例如:

(gdb) set args 1 2 3

(gdb) show args

Argument list to give program being debugged when it is started is "1 2 3".

(gdb) run

Starting program: /bin/echo 1 2 3

1 2 3

[Inferior 1 (process 7669) exited normally]


环境变量

show environment [varname]

set environment varname[=value]

unset environment varname


working directory

set cwd [directory]

show cwd

设置程序的工作目录,如果没有用这个命令设置,则继承GDB的工作目录。


cd [directory]

pwd

设置,查看GDB的当前工作目录。


4.6 Your Program's Input and Output

默认,你运行的程序和GDB使用一个terminal,GDB转换terminal到自己来和你交互命令。当程序运行时,又切换回你运行的程序。


可以使用重定向

run > outfile


4.7 Debugging an Already-running Process

attach process-id

为了使用attch,gdb需要找到进程的二进制文件,gdb会去当前工作目录搜索,也可以使用file命令指定符号文件。

detach


killing the child process

kill命令


4.10 Debugging Programs with multiple threads

info threads,显示所有线程信息

thread thread-id,Make thread ID thread-id the current thread,id是info threads显示的第一列。

thread apply thread-id-list | all command


5 Stopping and Continuing

5.1 breakpoints, watchpoints, and catchpoints

breakpoints是断点

watchpoint是一个特殊的断点,当一个表达式的值变化时,程序停下来。

catachpoint是一个特殊的断点,当某个事件发生时,程序停下来。


上述的每种断点,GDB都赋予一个数字,许多命令使用数字来控制断点,断点可以disable,enable。


5.1.1 setting breakpoints

通过break命令设置断点,简写为b。


break location

可以是函数名,也可以是行号,或者指令的地址。


break

在stack frame的下一条要执行的指令,类似finish


break ... if cond

cond为非0时,断点生效。


tbreak args

只执行一次的断点,


info breakpoints

info break

打印断点信息


5.1.2 setting watchpoints

当一个表达式的值改变时,触发断点,也叫做data breakpoint。

单个变量

一个地址的值,如 *(int *)0x12345678

一个复杂的表达式,如 a*b + c/d


当一个表达式的值不能被评估时,你也可以将watchpoint设置在该表达式上。

但是当前context,要有该表达式才行。比如,如下报错

(gdb) watch a

No symbol "a" in current context.


watch [-l | -location] expr [thread thread-id]

-l选项,监视expr表示的地址处的内存,大小为表达式的类型。


rwatch [-l | -location] expr [thread thread-id]

当表达式的值,被读取时,


awatch [-l | -location] expr [thread thread-id]

当表达式的值被读或者写时


info watchpoints


5.1.4 deleting breakpoints

clear命令根据地址删除断点,delete命令根据编号删除断点。


clear,删除被stack frame的下一个条指令的断点。

clear location,删除指定location的断点

    clear function

    clear filename:function

    clear linenum

    clear filename:linenum


delete [breakpoints],简写为d


5.1.5 disabling breakpoints

disable [breakpoints]

enable [breakpoints]

enable [breakpoints] once

只激活一次

enable [breakpoints] count count

激活count次

enable [breakpoints] delete 

激活后删掉


5.1.8 dynamic printf

动态打印命令dpirntf和断点结合,实现插入printf的效果。


注意:dprintf也是一种断点,在info breakpoint会显示,有编号,可以删除。dprintf打印后,不会停下来。


(gdb) dprintf test.c:9,"%d %d %d\n",a,b,c                                       

Dprintf 7 at 0x400510: file test.c, line 9.


(gdb) run

Starting program: /work/code/gdb/a.out

1 2 3


dprintf location,template,expression[,expression...]


set dprintf-style style

    gdb,使用GDB的printf命令打印

    call,使用被调试程序的函数打印

    agent,使用remote debugging agent,如gdbserver打印。


set dprintf-function function

    如果style是call,指定打印函数,默认是printf


set dprintf-channel channel

    将channel做为打印函数的第一个参数,当打印函数是fprintf时,需要指定,可以指定是stderr还是stdout等。


5.2 Continuing and Stepping


continue, 继续执行,简写为c


step,单步执行,简写为s,如果函数有调式信息,会进入到函数。


step count


next [count],和step类似,但是不进入函数。


finish,运行到函数结束,简写为fin。


until

u


until location


advance location


stepi

stepi arg

si

执行一条机器指令,arg是执行的count。


nexti

nexti arg

ni

执行吓一跳指令,但如果是函数调用,执行到函数返回。


5.3 Skipping over Functions and Files

skip命令,跳过不感兴趣的源文件或函数,在step执行的时候很有用。




6 Running programs backward

反向执行程序,有时想回去看看发生了啥,反向执行还是有很用的。


reverse-continue 

rc


reverse-step [count]

reverse-stepi

reverse-nexti

reverse-next

reverse-finish



8 Examining the stack

backtrace

bt


where, info stack是bt的别名。


8.3 selecting a frame


frame [spec]

f [spec]

    spec可以为:

    num

    level num,记住0等级是最内侧(当前执行)的帧。

    address stack-address,根据栈地址选择帧

    function function-name,根据函数名选择帧

    view stack-address,根据地址查看栈,特别有用,当有多个栈,或者栈被bug损坏了。


up [n]

down [n]


8.4 Information about a frame

frame 

f

打印帧的简短信息


info frame [spec]

info f [spec]

打印详细的帧信息


info args,打印参数

(gdb) info arg

argc = 1

argv = 0x7fffffffdd28


info locals

打印local varables


9 Examining source files

GDB可以打印你程序源代码的一部分。因为记录在程序中的调试信息保存了编译程序的源代码。


list linenum

list function

list

list +

list -

set listsize count

show listsize

list location

list ,last

list first,


9.1 Specifying a location


9.2.1 linespec location

linenum,指定当前源文件的行号。


-offset

+offset,指定当前行的偏移。


filename:linenum,文件名和行号


function,函数


function:label,函数和标签


filename:function,文件名和函数


label,当前栈帧处的标签。


10 Examining Data

使用print命令,简写为p


print expr,打印表达式的值


print /f expr,按指定格式打印表达式


print,

print /f,打印上一次的表达式的值。



ptype exp,打印结构体的原型

(gdb) ptype d

type = struct a {

    int b;

    int c;

}



10.1 Expressions

GDB支持C语言的所有运算符。除此之外,GDB还支持


@ 二目运算符,将内存一部分当成数组。


::

指定函数或文件中的变量,file::variable,function::variable


{type}addr

addr是一个表达式,值是整数或指针,将这个地址处的内存当成一个type类型的对象。


10.4 Artificial Arrays

@左边是数组的第一个元素,右边是数组的长度。


int e[3] = { 1, 2, 3};


(gdb) ptype d

type = struct a {

    int b;

    int c;

}


如下是artificial array,注意0x12345678不是地址,而是内容。

(gdb) p /x (short[])0x12345678

$3 = {0x5678, 0x1234}


10.7 Automatic display

每次停下来的时候都显示一个表达式的值


display expr

display /fmt expr

undisplay dnums

delete display dnums

disable display dnums

enable display dnums

info display


10.13 Registers

打印寄存器

info registers

info all-registers,还打印浮点数和向量寄存器。

info registers regname


GDB有4个标准寄存器名称,可以使用print命令打印

$pc $sp $fp $ps


参考:

GDB手册

Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.