读书笔记《Debug Hacks --调试技术与工具》(2-GDB调试(一))

本文涉及的主要用法:

  1. 设置/删除断点;

  2. 显示栈调用;

  3. 显示/设置变量值;

  4. 生成coredump文件;

  5. 查看内存地址。

要调试的源码

#include "stdio.h"


static int binarySearch(int array[], int len, int key)
{
	int left = 0;
	int right = len - 1;

	while (left <= right)
	{
		int mid = (left + right) / 2;
		if (array[mid] == key)
		{
			return mid;
		}
		else if (array[mid] < key)
		{
			left = mid + 1;
		}
		else
		{
			right = mid - 1;
		}
	}
	
	return -1;

}

int main()
{
	int arrToSearch[] = {1,2,4,5,7,9,12,34,56,78,90};
	

	int res = binarySearch(arrToSearch, sizeof(arrToSearch)/sizeof(int), 78);
	printf("binarySearch return: [%d]\n", res);
	
	return 0;

}

生成调试信息

通过gcc的-g选项,生产调试信息:

gcc -Wall -g main.c

开始调试

$ gdb ./a.out 
GNU gdb (Ubuntu 7.7.1-0ubuntu5~14.04.3) 7.7.1
Copyright (C) 2014 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-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<http://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:
<http://www.gnu.org/software/gdb/documentation/>.
For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from ./a.out...done.
(gdb)

设置断点

有以下四种方法(通过函数名或者行号指定断点位置),比如设置在main函数,:
(如果程序处于暂停状态,还可以通过偏移量或者指定地址设置断点)

(gdb) break main
Breakpoint 1 at 0x4005c7: file main.c, line 31.
(gdb) break 29
Note: breakpoint 1 also set at pc 0x4005c7.
Breakpoint 2 at 0x4005c7: file main.c, line 29.
(gdb) break main.c:29
Note: breakpoints 1 and 2 also set at pc 0x4005c7.
Breakpoint 3 at 0x4005c7: file main.c, line 29.
(gdb) break main.c:main
Note: breakpoints 1, 2 and 3 also set at pc 0x4005c7.
Breakpoint 4 at 0x4005c7: file main.c, line 31.

开始运行

指令为run,简写r:

(gdb) r -a
Starting program: /home/lvgh/back/gdbTest/a.out -a

Breakpoint 1, main () atmain.c:33
31		int arrToSearch[] = {1,2,4,5,7,9,12,34,56,78,90};

显示栈帧(backtrace)

比如把断点打在binarySearch, 运行起来后,查阅栈帧,指令简写bt:

(gdb) bt
#0  binarySearch (array=0x7fffffffe550, len=11, key=78) at main.c:6
#1  0x000000000040062a in main () at main.c:33

如果栈帧太多,可以指定只显示前N个或后N个。

bt N 或者 bt full -N

显示变量值(print)

print可简写为p,p可以设置显示的变量的格式
指定格式的方式如下:
格式 说明
x 十六进制
d 十进制
u 无符号十进制
o 八进制
t 二进制(two)
a 地址(address)
c 字符(ASCII)
f 浮点小数
s 字符串
i 机器语言

示例:

(gdb) p right
$1 = 10
(gdb) p /x right
$2 = 0xa

单步执行(next/step)

next(简写 n): 根据源代码一行一行执行;
step(简写 p): 可进入函数内部执行;
(对应汇编代码的调试指令为:nexti与stepi)

继续运行(continue)

在遇到断点后,跳过断点,则执行指令continue(简写c)。
continue指令后面可跟数字,表明跳过多少个断点。(continue 次数)

监视点(watch/awatch/rwatch)

watch <表达式> : 表达式发生变化时暂停运行;
awatch <表达式> : 表达式被访问,改变时暂停运行;
rwatch <表达式> : 表达式被访问时暂停运行。

查阅(info)

命令 info 后面可以跟不同的参数:

info address -- Describe where symbol SYM is stored
info all-registers -- List of all registers and their contents
info args -- Argument variables of current stack frame
info auto-load -- Print current status of auto-loaded files
info auto-load-scripts -- Print the list of automatically loaded Python scripts
info auxv -- Display the inferior's auxiliary vector
info bookmarks -- Status of user-settable bookmarks
info breakpoints -- Status of specified breakpoints (all user-settable breakpoints if no argument)
info checkpoints -- IDs of currently known checkpoints
info classes -- All Objective-C classes
info common -- Print out the values contained in a Fortran COMMON block
info copying -- Conditions for redistributing copies of GDB
info dcache -- Print information on the dcache performance
info display -- Expressions to display when program stops
info exceptions -- List all Ada exception names
info extensions -- All filename extensions associated with a source language
info files -- Names of targets and files being debugged
info float -- Print the status of the floating point unit
info frame -- All about selected stack frame
info frame-filter -- List all registered Python frame-filters
info functions -- All function names
info handle -- What debugger does when program gets various signals
info inferiors -- IDs of specified inferiors (all inferiors if no argument)
info line -- Core addresses of the code for a source line
info locals -- Local variables of current stack frame
info macro -- Show the definition of MACRO
info macros -- Show the definitions of all macros at LINESPEC
info mem -- Memory region attributes
info os -- Show OS data ARG
info pretty-printer -- GDB command to list all registered pretty-printers
info probes -- Show available static probes
info proc -- Show /proc process information about any running process
info program -- Execution status of the program
info record -- Info record options
info registers -- List of integer registers and their contents

删除断点/监视点(delete)

通过info获取对应的断点/监视点的号码: info b
delete <编号> 删除

(gdb) info b
Num     Type            Disp Enb Address            What
1       read watchpoint keep y                      glocalTest
	breakpoint already hit 1 time
(gdb) delete 1
(gdb) info b
No breakpoints or watchpoints.
(gdb) 

改变变量的值(set)

set variable <变量>=<表达式>
比如:

(gdb) p glocalTest
$1 = 0
(gdb) set variable glocalTest=99
(gdb) p glocalTest
$2 = 99
(gdb) 

生成内核转储文件(generate-core-file)

(gdb) generate-core-file 
Saved corefile core.22457

查看内存值(examine)

命令examine,简写x
格式为:x /
n f u 是可选参数。
n是一个正整数,表示从开始,要显示的内存的长度。
f是显示的格式,参见下面的说明。
u是表示每次读取的字节数,默认是4bytes。b表示单字节,h表示双字节,w表示四字节,g表示八字节。
显示格式的说明:
x 按十六进制格式显示变量。
d 按十进制格式显示变量。
u 按十六进制格式显示无符号整型。
o 按八进制格式显示变量。
t 按二进制格式显示变量。
a 按十六进制格式显示变量。
c 按字符格式显示变量。
f 按浮点数格式显示变量。
比如:

(gdb) x /20uh arrToSearch
0x7fffffffe550:	1	0	2	0	4	0	5	0
0x7fffffffe560:	7	0	9	0	12	0	34	0
0x7fffffffe570:	56	0	78	0
(gdb) x /20xb arrToSearch
0x7fffffffe550:	0x01	0x00	0x00	0x00	0x02	0x00	0x00	0x00
0x7fffffffe558:	0x04	0x00	0x00	0x00	0x05	0x00	0x00	0x00
0x7fffffffe560:	0x07	0x00	0x00	0x00
(gdb) x /20xh arrToSearch
0x7fffffffe550:	0x0001	0x0000	0x0002	0x0000	0x0004	0x0000	0x0005	0x0000
0x7fffffffe560:	0x0007	0x0000	0x0009	0x0000	0x000c	0x0000	0x0022	0x0000
0x7fffffffe570:	0x0038	0x0000	0x004e	0x0000
(gdb) x /20xw arrToSearch
0x7fffffffe550:	0x00000001	0x00000002	0x00000004	0x00000005
0x7fffffffe560:	0x00000007	0x00000009	0x0000000c	0x00000022
0x7fffffffe570:	0x00000038	0x0000004e	0x0000005a	0x00000000
0x7fffffffe580:	0x00000000	0x00000000	0xf7a32f45	0x00007fff
0x7fffffffe590:	0x00000000	0x00000000	0xffffe668	0x00007fff

以上,就是gdb调试的基础。

你可能感兴趣的:(读书笔记,linux相关)