The art of debugging with GDB (4) --Inspecting Variables

1. The basic print command

The format for the print (abbreviated as p) command is either print expression or print /FMT express where FMT is a single letter defining the format of data to print.

1.1 Syntax

print [Expression]
 
print $[Previous value number]
 
print {[Type]}[Address]
 
print [First element]@[Element count]
 
print /[Format] [Expression]

1.2 Parameters

Expression
        Specifies the expression that will be evaluated and printed. The expression can include references to variables (e.g. i), registers (e.g. $eax) and pseudo-registers (e.g. $pc). Note that if your expression refers to a local variable, you need to ensure that you have selected the correct frame. You can navigate frames using the up and down commands.

Previous value number
        When this format is used and i is specified as the previous value number, the print command will repeat the output produced by its i-th invocation.

Type/Address
        This format allows explicitly specifying the address of the evaluated expression and can be used as a shortcut to the C/C++ type conversion. E.g. *((int *)p) is equivalent to {int}p

First element/Element count
        This form allows interpreting the First element expression as an array of Element count sequential elements. The most common example of it is *argv@argc

Format
        If specified, allows overriding the output format used by the command. Valid format specifiers are:

letterformat
ddecimal (default)
ooctal
xhexadecimal
tbinary
uunsigned
ffloating point
iinstruction
ccharacter
sstring
aaddress

1.3 Examples

We will demonstrate the print command using a basic C++ program that prints its own command-line arguments:

#include <stdio.h>

int main(int argc, char **argv)
{
  for(int i = 0; i < argc; i++)
    printf("Arg %d: %s\n", i, argv[i]);
  return 0;
}

We will step into the loop and use several forms of print to show the values of various variables:

(gdb) set args arg1 arg2 arg3
(gdb) start
Temporary breakpoint 1 at 0x8048426: file test.c, line 5.
Starting program: /home/mg/test arg1 arg2 arg3

Temporary breakpoint 1, main (argc=4, argv=0xbffff024) at test.c:5
warning: Source file is more recent than executable.
5 for(int i = 0; i < argc; i++)
(gdb) next
6 printf("Arg %d: %si, argv[i]);
(gdb) print i
$1 = 0
(gdb) print argv[i]
$2 = 0xbffff204 "/home/mg/test"
(gdb) print /a argv[i]
$3 = 0xbffff204
(gdb) print /s argv[i]
$4 = 0xbffff204 "/home/mg/test"
(gdb) print /c argv[i]
$5 = 4 '\004'
(gdb) print *argv
$6 = 0xbffff204 "/home/mg/test"
(gdb) print *argv@argc
$7 = {0xbffff204 "/home/mg/test", 0xbffff215 "arg1", 0xbffff21a "arg2", 0xbffff21f "arg3"}
(gdb) print {void *}argv@argc
$8 = {0xbffff204, 0xbffff215, 0xbffff21a, 0xbffff21f}
(gdb) print $2
$9 = 0xbffff204 "/home/mg/test"
(gdb) next
Arg 0: /home/mg/test
5 for(int i = 0; i < argc; i++)
(gdb) next
6 printf("Arg %d: %si, argv[i]);
(gdb) print $2
$10 = 0xbffff204 "/home/mg/test"
(gdb) print argv[i]
$11 = 0xbffff215 "arg1"
(gdb) print /t argv[i]
$12 = 10111111111111111111001000010101

2. the printf command

GDB’s print command has a more powerful cousin, printf, with formatting similar to that of its C-language namesake.

The help message of printf given by GDB:

(gdb) help printf
Formatted printing, like the C "printf" function.
Usage: printf "format string", arg1, arg2, arg3, ..., argn
This supports most C printf format specifications, like %s, %d, etc.
(gdb)

Examples:

(gdb) printf "tree is %lx and data is %s\n", tree, data
tree is 4052a0 and data is gecko

3. The x command (x /NFS address)

In some cases, you might wish to examine memory at a given address, rather than via the name of a variable. GDB provides the x(“examine”) command for this purpose.

3.1 Syntax

x command
        Displays the memory contents at a given address using the specified format.

Syntax
        x /NFS address

        N: number of items to print (default 1),
        F: single letter format as used in the print command
        S: the size of each memory location.

Here are the size options:

letterSIZebytes
bbyte1
hhalfword2
wword4
ggiant8

3.2 Example

We will demonstrate the x command using a basic program that defines a byte array on the stack:

int main()
{
    char testArray[] = "0123456789ABCDEF";
    return 0;
}

We will now use the x command to display the contents of the memory occupied by the testArray array in various formats. We will also show how to use the x command to disassemble the instructions pointed by the program counter pseudo-register ($pc).

(gdb) start
Temporary breakpoint 1 at 0x8048446: file test.cpp, line 2.
Starting program: /home/bazis/test

Temporary breakpoint 1, main () at test.cpp:2
2 {
(gdb) next
3 char testArray[] = "0123456789ABCDEF";
(gdb) next
4 return 0;
(gdb) x testArray
0xbfffef7b: 0x33323130
(gdb) x/c testArray
0xbfffef7b: 48 '0'
(gdb) x/5c testArray
0xbfffef7b: 48 '0' 49 '1' 50 '2' 51 '3' 52 '4'
(gdb) x/2c
0xbfffef80: 53 '5' 54 '6'
(gdb) x/wx testArray
0xbfffef7b: 0x33323130
(gdb) x/2hx testArray
0xbfffef7b: 0x3130 0x3332
(gdb) x/gx testArray
0xbfffef7b: 0x3736353433323130
(gdb) x/s testArray
0xbfffef7b: "0123456789ABCDEF"
(gdb) x/5bx testArray
0xbfffef7b: 0x30 0x31 0x32 0x33 0x34
(gdb) x/5i $pc
=> 0x8048477 <main()+58>: mov $0x0,%eax
0x804847c <main()+63>: mov 0x1c(%esp),%edx
0x8048480 <main()+67>: xor %gs:0x14,%edx
0x8048487 <main()+74>: je 0x804848e <main()+81>
0x8048489 <main()+76>: call 0x8048310 <__stack_chk_fail@plt>

4. the display command

The display (abbreviated as disp) command tells GDB to automatically print the specified item each time there is a pause in execution (due to a breakpoint, the next or step commands, and so on).

(gdb) display  *tmp
1: *tmp = {val = 12, left = 0x8049698, right = 0x0}
(gdb) c
Continuing.
Breakpoint 1, insert (btp=0x804967c, x=5) at bintree.c:37
37 if (x < tmp->val) {
1: *tmp = {val = 8, left = 0x0, right = 0x0}

As seen here, GDB automatically printed *tmp after hitting the breakpoint, since you had issued the display command.
Of course, a variable in the display list will only be displayed during times in which it is in scope.

The display command can take a format specification as the x command do, (i.e., display /NFS EXP).

The help message of display given by GDB:

(gdb) help display
Print value of expression EXP each time the program stops.
/FMT may be used before EXP as in the "print" command.
/FMT "i" or "s" or including a size-letter is allowed,
as in the "x" command, and then EXP is used to get the address to examine
and examining is done as in the "x" command.

With no argument, display all currently requested auto-display expressions.
Use "undisplay" to cancel display requests previously made.
(gdb)

You can temporarily disable a display item. For instance,

(gdb) disable display 1

temporarily disables item 1 in the display list. If you do not know the item numbers (the dispaly identifiers), you can check via the info display command. To re-enable an item, use enable , for example

(gdb) enable display 1

To delete a display item entirely, use undisplay , for example,

(gdb) undisplay 1
调试是在编程过程中解决错误和问题的重要步骤。GNU调试器(GDB)是一种功能强大的调试工具,它允许我们在源代码级别上进行调试。 首先,为了使用GDB进行源代码级别调试,我们需要安装GDB。我们可以通过访问GNU调试器项目的官方网站,从那里下载并安装GDB软件包。 一旦安装完成,我们可以在终端中使用“gdb”命令来启动GDB调试器。然后,通过在命令行中指定可执行文件的路径,我们可以将程序加载到GDB中。 在源代码级别调试中,我们可以使用GDB的一些命令来执行不同的操作。例如,我们可以使用“break”命令设置断点,以便在程序执行时停止。我们还可以使用“run”命令开始执行程序,直到遇到断点为止。 一旦程序停止在断点处,我们可以使用GDB的其他命令来查看和修改程序状态。例如,我们可以使用“print”命令显示变量的值,以帮助我们理解程序的行为。我们还可以使用“step”命令逐行执行程序,并在每一步检查变量和代码的状态。 除了这些基本命令外,GDB还提供了许多其他功能,如条件断点、查看内存内容、查看函数调用栈等等。这些功能可以帮助我们更全面地理解程序的执行过程和错误的来源。 总之,GDB是一个强大的源代码级别调试工具,可以帮助我们解决编程过程中的错误和问题。通过使用GDB,我们可以在程序执行过程中查看和修改变量和代码的状态,以便更好地理解程序的行为和调试错误。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值