linux gdb自動測試

linux gdb自動測試

 (2011-06-27 23:42:33)
標籤: 

gdb

分類: linux

0. set height 0 設置屏幕打印不受限制,不然gdb一直要手動的按enter確認
0. set logging on
  set logging file filename設置gdb的log文件輸出,屏幕可看的東西太少,還是輸出到文件爽
1. 先b file:line打斷點,gdb打印出斷點號n
2. command n
  printf "x is %d\n",x
  c
  end
  設置運行到斷點n時的要看的內容,
  如果command後面沒有參數n,則命令被賦給最後一個breakpoint,這其實是說b和command連在一起用,在腳本里用就非常方便了
3. run


4. 在gdb裏每次輸同樣的command還比較麻煩,可替代的方法是把這些命令(如上面的breakpoint,custom command等)都寫在一個文件裏,
作爲gdb的命令腳本文件用source -v file來執行,-v參數指示gdb在執行這些命令時打印出命令本身信息。
在腳本文件裏可以用if,else, while,end,loop_break, loop_continue這些條件語句,相當強大

5. 如果已經在gdb裏設置了很多breakpoint和相應的command,則可以用save breakpoints filename把設置的breakpoint和命令保存到文件中,
保存的文件忽略了在此gdb實例中的breakpoint number。

6.在腳本中可能會用到的幾個命令有:
1)改變變量的值: print x=4,意思爲把4賦值給x,然後再打印出表達式的值(這裏就是等號右邊的4)
       set var width=47,把47賦值給width,
       set {int}0x83040 = 4把內存地址0x83040強制轉換成int,並賦值
2)改變執行順序: jump linespec or jump location  這個指令不改變stack frame,stack pointer,memory location,僅僅改變program counter,
所以一般只在同一個函數內才使用這個指令,可以向前向後jump,向後jump一般就是仔細檢查已經執行過的代碼是否有錯

3)發送信號signal signalno,向程序發送一個signalno信號

4)set confirm off指明gdb所有要確認的地方全部爲yes

set breakpoint pending on 讓打在so裏的斷點自動在pending狀態

5)call express 調用一個函數

6) return or return express,從一個函數返回

7) print的格式符
 print [/f ] [expr]
 p [/f ] [expr]
 show value of expr [or last value $]
 according to format f:
 x hexadecimal
 d signed decimal
 u unsigned decimal
 o octal
 t binary
 a address, absolute and relative
 c character
 f floating point

 

7.info address symbol:查詢symbol的地址,一般symbol爲局部變量,則爲在stack上的offset。
info symbol addr:查詢在addr或附近對應的symbol
例子:(gdb) info symbol 0x54320
_initialize_vx + 396 in section .text

whatis [arg]: 打印arg的數據類型,arg可以爲表達式或一個數據類型
ptype [arg]:打印arg的詳細數據類型
例子:對於數據結構struct complex {double real; double imag;} v;
(gdb) whatis v
type = struct complex
(gdb) ptype v
type = struct complex {
double real;
double imag;
}

8.info types regexp
info types:打印符合正則表達式regexp的所有類型的數據類型

info scope location:列出在一個作用範圍內的所有局部變量,location可以是函數,代碼行,或內存地址(加×號)
List all the variables local to a particular scope. This command accepts a
location argument—a function name, a source line, or an address preceded by
a ‘*’, and prints all the variables local to the scope defined by that location.
例子:
(gdb) info scope command line handler
Scope for command_line_handler:
Symbol rl is an argument at stack/frame offset 8, length 4.
Symbol linebuffer is in static storage at address 0x150a18, length 4.
Symbol linelength is in static storage at address 0x150a1c, length 4.
Symbol p is a local variable in register $esi, length 4.
Symbol p1 is a local variable in register $ebx, length 4.
Symbol nline is a local variable in register $edx, length 4.
Symbol repeat is a local variable at frame offset -8, length 4.


info functions regexp:打印符合正則regexp的所有函數的函數名和數據類型


9.maint print symbols filename
maint print psymbols filename
maint print msymbols filename:把debugging符號數據dump到一個文件裏
Write a dump of debugging symbol data into the file filename. These commands
are used to debug the gdb symbol-reading code


10.set sysroot path:設置根目錄,一般在host調試target代碼時可用到,此時target鏈接的庫一般不在/usr/lib目錄下
Use path as the system root for the program being debugged.
If path starts with the sequence ‘remote:’, gdb will retrieve the target libraries
from the remote system.
The set solib-absolute-prefix command is an alias for set sysroot.
set solib-search-path path
If this variable is set, path is a colon-separated list of directories to search for
shared libraries. ‘solib-search-path’ is used after ‘sysroot’ fails to locate the
library, or if the path to the library is relative instead of absolute.

 

11.set debug-file-directory directories:設置debug文件查找目錄,一般在exe文件和debug 符號文件分開儲存時使用
用下面的兩個命令可從elf格式exe文件分離debug symbol
objcopy --only-keep-debug foo foo.debug
strip -g foo
用下面的debug 文件鏈接指令
objcopy --add-gnu-debuglink=foo.debug foo 或build Id指令
Build ID gets embedded into the main executable using ld --build-id or the gcc
counterpart gcc -Wl,--build-id.


12.用戶自定義命令
用戶自定義命令是由一序列gdb命令組成的一個命令,可以向他傳遞參數,參數用$0 - $9訪問。
A user-defined command is a sequence of gdb commands to which you assign a new name
as a command. This is done with the define command. User commands may accept up to
10 arguments separated by whitespace. Arguments are accessed within the user command
via $arg0...$arg9.
例子:
define adder
print $arg0 + $arg1 + $arg2
end

12.1 dont-repeat:在自定義命令裏使用,告訴gdb用戶按回車鍵不用重複上一個命令。
12.2 可以定義命令的hook,在執行命令前或命令後執行hook命令,hook形式爲hook-func,hookpost-func。
在hook裏可以調用自己hook的命令,這時就不會再執行命令的hook了,防止無限循環。
例子:
define hook-echo
echo <<<---
end
define hookpost-echo
echo --->>>\n
end
(gdb) echo Hello World
<<<---Hello World--->>>
(gdb)
You can hook a multi-word command by adding hook- or hookpost- to the last word
of the command, e.g. ‘define target hook-remote’ to add a hook to ‘target remote’.


13.set detach-on-fork mode off: 在debug父子進程時,parent和child都被gdb控制,當一個在debug時,另外一個suspend起來
Both processes will be held under the control of gdb. One process
(child or parent, depending on the value of follow-fork-mode) is
debugged as usual, while the other is held suspended.
 

14. gdb可以保存某一個時間點的program狀態或者說是process映像,並且稍後又可以返回到這個狀態。這個技術叫checkpoint。
每個checkpoint是process的一個copy,這樣當一個bug很難重現,而又擔心調試過頭了又要從頭開始重現時,可以在估計要重現這個bug之前,
做一個checkpoint,這樣即使debug過頭了,也可以從這個checkpoint開始,而不用restart整個program。
但是每個checkpoint有一個唯一的process id,這個pid與original pid不同,如果程序用來pid的信息就要考慮了。
gdb is able to save a snapshot of a program’s state, called
a checkpoint, and come back to it later.

Each checkpoint will have a unique process id
(or pid), and each will be different from the program’s original pid.

A checkpoint, however, is an identical copy of a process. Therefore if you create a
checkpoint at (eg.) the start of main, and simply return to that checkpoint instead of
restarting the process, you can avoid the effects of address randomization and your symbols
will all stay in the same place.
 

15.rbreak regex:用正則表達式regexp打斷點,正則表達式與grep所用的規則一樣
Set breakpoints on all functions matching the regular expression regex

rbreak file:regex:只在某個文件裏應用正則表達式regexp打斷點
If rbreak is called with a filename qualification, it limits the search for functions
matching the given regular expression to the specified file.
The syntax of the regular expression is the standard one used with tools like
‘grep’.
 

16。在gdb裏可以設置一個watchpoint開觀察某個express的值是否被改變。express可以是某個變量或被cast到一個數據類型的內存地址。
watchpoint在你對bug無從下手的時候非常有用。如果是用software形式實現watchpoint,會嚴重降低program的速度。
在多線程環境中,watchpoint的作用非常有限,因爲gdb的software watchpoint只能在一個線程裏觀察express。
You can use a watchpoint to stop execution whenever the value of an expression changes,
without having to predict a particular place where this may happen.

The expression may be:
A reference to the value of a single variable.
An address cast to an appropriate data type. For example, ‘*(int *)0x12345678’ will
watch a 4-byte region at the specified address (assuming an int occupies 4 bytes).
An arbitrarily complex expression, such as ‘a*b + c/d’. The expression can use any operators
valid in the program’s native language.

Depending on your system, watchpoints may be implemented in software or hardware.
gdb does software watchpointing by single-stepping your program and testing the variable’s
value each time, which is hundreds of times slower than normal execution.

watch expr [thread threadnum]:當express被改寫時
Set a watchpoint for an expression. gdb will break when the expression expr
is written into by the program and its value changes.

rwatch expr [thread threadnum]:當express被讀取時
Set a watchpoint that will break when the value of expr is read by the program.
awatch expr [thread threadnum]:當express被讀寫時
Set a watchpoint that will break when expr is either read from or written into
by the program.
 
Warning: In multi-threaded programs, software watchpoints have only limited
usefulness. If gdb creates a software watchpoint, it can only watch the value
of an expression in a single thread.

 

17. gdb可以用catchpoint開捕獲event,如throw,catch,syscall等事件
You can use catchpoints to cause the debugger to stop for certain kinds of program events,
such as C++ exceptions or the loading of a shared library. Use the catch command to set
a catchpoint.

catch event
Stop when event occurs. event can be any of the following:
throw The throwing of a C++ exception.
catch The catching of a C++ exception.
exception
An Ada exception being raised. If an exception name is specified
at the end of the command (eg catch exception Program_Error),
the debugger will stop only when this specific exception is raised.
Otherwise, the debugger stops execution when any Ada exception
is raised.
When inserting an exception catchpoint on a user-defined exception
whose name is identical to one of the exceptions defined by the language,
the fully qualified name must be used as the exception name.
Otherwise, gdb will assume that it should stop on the pre-defined
exception rather than the user-defined one. For instance, assuming
an exception called Constraint_Error is defined in package
Pck, then the command to use to catch such exceptions is catch
exception Pck.Constraint_Error.
exception unhandled
An exception that was raised but is not handled by the program.
assert A failed Ada assertion.
exec A call to exec. This is currently only available for HP-UX and
gnu/Linux.
syscall
syscall [name | number] ...
A call to or return from a system call, a.k.a. syscall. A syscall is a
mechanism for application programs to request a service from the
operating system (OS) or one of the OS system services. gdb can
catch some or all of the syscalls issued by the debuggee, and show
the related information for each syscall. If no argument is specified,
calls to and returns from all system calls will be caught.
name can be any system call name that is valid for the underlying
OS. Just what syscalls are valid depends on the OS. On GNU and
Unix systems, you can find the full list of valid syscall names on
‘/usr/include/asm/unistd.h’.
Normally, gdb knows in advance which syscalls are valid for each
OS, so you can use the gdb command-line completion facilities (see
Section 3.2 [command completion], page 19) to list the available
choices.

 

 

18.可以用if設置條件斷點,之後還可以用condition來改變條件斷點的條件
Break conditions can be specified when a breakpoint is set, by using ‘if’ in the arguments
to the break command. See Section 5.1.1 [Setting Breakpoints], page 44. They can also be
changed at any time with the condition command.
You can also use the if keyword with the watch command. The catch command does
not recognize the if keyword; condition is the only way to impose a further condition on
a catchpoint.
18.1condition bnum expression
Specify expression as the break condition for breakpoint, watchpoint, or catchpoint
number bnum. After you set a condition, breakpoint bnum stops your
program only if the value of expression is true

 

17.handle signal [keywords...]:設置signal的處理
Change the way gdb handles signal signal. signal can be the number of a
signal or its name (with or without the ‘SIG’ at the beginning); a list of signal
numbers of the form ‘low-high’; or the word ‘all’, meaning all the known signals.

The keywords allowed by the handle command can be abbreviated. Their full names
are:
nostop gdb should not stop your program when this signal happens. It may still print a message telling you that the signal has come in.
stop gdb should stop your program when this signal happens. This implies the print keyword as well.
print gdb should print a message when this signal happens.
noprint gdb should not mention the occurrence of the signal at all. This implies the nostop keyword as well.
pass noignore gdb should allow your program to see this signal; your program can handle the signal, or else it may terminate if the signal is fatal and not handled. pass and noignore are synonyms.
nopass ignore gdb should not allow your program to see this signal. nopass and ignore are synonyms.

 

18. gdb可以配置多線程環境的debug模式,當一個thread被debug時,其他thread是stop還是自由的run。gdb有all-stop和non-stop模式。
Stopping and Starting Multi-thread Programs

In all-stop mode, whenever your program stops under gdb for any reason, all threads of
execution stop, not just the current thread.

Non-Stop Mode:In non-stop mode, when a thread stops to report a debugging event, only that thread is stopped; gdb does not stop other threads as well.To stop the
whole program, use interrupt -a.

To enter non-stop mode, use this sequence of commands before you run or attach to
your program:
# Enable the async interface.
set target-async 1
# If using the CLI, pagination breaks non-stop.
set pagination off
# Finally, turn it on!
set non-stop on

 

19. 在某些平臺,gdb可以record並replay整個debug過程
On some platforms, gdb provides a special process record and replay target that can record
a log of the process execution, and replay it later with both forward and reverse execution
commands.

target record
This command starts the process record and replay target. The process record
and replay target can only debug a process that is already running. Therefore,
you need first to start the process with the run or start commands, and then
start the recording with the target record command.
Both record and rec are aliases of target record.

record stop
Stop the process record and replay target.

record save filename
Save the execution log to a file ‘filename’.

record restore filename
restore the execution log from a file ‘filename’.
 

20.directory dirname ...
dir dirname ...
增加source 文件的搜索路徑Add directory dirname to the front of the source path.


21. set substitute-path from to是指source文件的替換路徑,當代碼樹被移動過非常有用
Define a source path substitution rule, and add it at the end of the current list
of existing substitution rules. If a rule with the same from was already defined,
then the old rule is also deleted.
 

22.display expr:增加自動顯示變量
Add the expression expr to the list of expressions to display each time your
program stops.


23.generate-core-file [file]
gcore [file]
生成某個時刻program的core dump。

24.搜索內存
Memory can be searched for a particular sequence of bytes with the find command.
find [/sn] start_addr, +len, val1 [, val2, ...]
find [/sn] start_addr, end_addr, val1 [, val2, ...]
Search memory for the sequence of bytes specified by val1, val2, etc.

 

25. 當程序嚴重依賴real-time時,我們不想在debug時停止下來與用於交互,可以用trace 命令來跟蹤一個express。
If the program’s
correctness depends on its real-time behavior, delays introduced by a debugger might cause
the program to change its behavior drastically, or perhaps fail, even when the code itself is
correct. It is useful to be able to observe the program’s behavior without interrupting it.
Using gdb’s trace and collect commands, you can specify locations in the program,
called tracepoints, and arbitrary expressions to evaluate when those tracepoints are reached.

trace location:要trace的地方
The trace command is very similar to the break command

actions [num]
collect expr1, expr2, ...
Collect values of the given expressions when the tracepoint is hit.

$regs Collect all registers.
$args Collect all function arguments.
$locals Collect all local variables.
$_sdata Collect static tracepoint marker specific data.

teval expr1, expr2, ...
Evaluate the given expressions when the tracepoint is hit.

while-stepping n
Perform n single-step instruction traces after the tracepoint, collecting new data
after each step.

set default-collect expr1, expr2, ...
This variable is a list of expressions to collect at each tracepoint hit.

tstart This command takes no arguments. It starts the trace experiment, and begins
collecting data.

tstop This command takes no arguments. It ends the trace experiment, and stops
collecting data.

tfind start
Find the first snapshot in the buffer.

tsave [ -r ] filename
Save the trace data to filename.

26. gdb打印命令
26.1 gdb操作符
gdb除了支持編程語言支持的操作符外,還支持@, ::, {type}addr形式的操作符。
26.2 @操作符:
一個二進制操作符,把一片內存當作array來處理。@的左操作數是內存地址,右操作數爲array的長度.
如代碼爲int *array = (int *) malloc (len * sizeof (int));
則可以用(gdb) p *array@len
另外還可以用強制轉換來生成一個artificial array,如:
(gdb) p/x (short[2])0x12345678
$1 = {0x1234, 0x5678}
有時光用artificial array還不夠,因爲在複雜數據結構裏,想查看的element並不連續,如想看一個struct裏的某個指針字段的值,
這時就要與convenience variables結合起來。例如想看一個
struct
{
int a;
int* fv;
int c;
}dtab[10];裏的fv的值,就可以用下面的命令:
(gdb) set $i = 0
(gdb) p dtab[$i++]->fv
(gdb) RET
(gdb) RET
(gdb) ...

26.3 ::操作符
假如一個變量在多個文件中定義,爲避免gdb解釋歧義,可以用::操作符來限定,如:
(gdb) file::variable
(gdb) function::variable
(gdb) p ’f2.c’::x

26.4 {type} addr:
把address轉換成type類型, address不必非在內存中。

26.5 examine memory
形式如:
x/nfu addr
x addr
x Use the x command to examine memory.
其中,x爲examine memory命令, n爲重複次數,f爲格式,與print命令參數一樣,u爲長度,如b,h,w,g,分別是1,2,4,8字節。

26.6 convenience variables
gdb提供convenience variables,形式爲$abc,任何name前加$就爲convenience variables,以後可以隨時引用他。
convenience variables保存在gdb裏,不是program的一部分,不會影響程序的運行。convenience variables沒有類型,在express中引用會自動變換成express需要的類型。


26.7 value history
gdb把每一個print打印的值都保存下來,組成一個value history,並給他分配一個編號,編號從1開始順序增加,以後可以用$1,$2的形式引用這些value。
$爲最近的value(倒數第一個),$$最近再之前的value(倒數第二個), $$n爲倒數第n個value.
例如有一段代碼:
struct AA
{
int a;
struct AA* next;
};
struct AA * a = new struct AA[100];

(gdb) p/x a
(gdb) *$
(gdb) p *$.next
(gdb) RET
(gdb) RET
...就可以一直打印出來。

value history一直保存在gdb裏,直到重讀或丟棄了符號表。
另外value history保存的是print express命令時express的值,而不是express本身。如:x的值爲4,在用下面兩個命令後
(gdb)print x
(gdb)set x=5
但是value history裏保存的值還是4,而不是5,儘管x的值已經改變了。

26.8 一些print的config
set print array on
set print array-indexes on
set print pretty on
set print object on
set print vtbl on

以下爲從gdb摘抄原文:
gdb supports these operators, in addition to those common to programming languages:
‘@’ is a binary operator for treating parts of memory as arrays.
referring to a contiguous span of memory as an artificial array, using
the binary operator ‘@’. The left operand of ‘@’ should be the first element of the desired
array and be an individual object. The right operand should be the desired length of the
array.
If a program says
int *array = (int *) malloc (len * sizeof (int));
you can print the contents of array with
(gdb) p *array@len
The left operand of ‘@’ must reside in memory.

Another way to create an artificial array is to use a cast. This re-interprets a value as if
it were an array. The value need not be in memory:
(gdb) p/x (short[2])0x12345678
$1 = {0x1234, 0x5678}

Sometimes the artificial array mechanism is not quite enough; in moderately complex
data structures, the elements of interest may not actually be adjacent—for example, if you
are interested in the values of pointers in an array. One useful work-around in this situation
is to use a convenience variable (see Section 10.11 [Convenience Variables], page 111) as
a counter in an expression that prints the first interesting value, and then repeat that
expression via RET. For instance, suppose you have an array dtab of pointers to structures,
and you are interested in the values of a field fv in each structure. Here is an example of
what you might type:
(gdb) set $i = 0
(gdb) p dtab[$i++]->fv
(gdb) RET
(gdb) RET
(gdb) ...

:: ‘::’ allows you to specify a variable in terms of the file or function where it is
defined.
(gdb) file::variable
(gdb) function::variable
Here file or function is the name of the context for the static variable. In the case of file
names, you can use quotes to make sure gdb parses the file name as a single word.
(gdb) p ’f2.c’::x

{type} addr
Refers to an object of type type stored at address addr in memory. addr may
be any expression whose value is an integer or pointer (but parentheses are
required around binary operators, just as in a cast). This construct is allowed
regardless of what kind of data is normally supposed to reside at addr.


examine memory in any of several formats,
independently of your program’s data types.
x/nfu addr
x addr
x Use the x command to examine memory.
n, f, and u are all optional parameters that specify how much memory to display and how
to format it; addr is an expression giving the address where you want to start displaying
memory.


gdb provides convenience variables that you can use within gdb to hold on to a value
and refer to it later. These variables exist entirely within gdb; they are not part of your
program, and setting a convenience variable has no direct effect on further execution of your
program. That is why you can use them freely.
Convenience variables are prefixed with ‘$’. Any name preceded by ‘$’ can be used for a
convenience variable, unless it is one of the predefined machine-specific register names.


Values printed by the print command are saved in the gdb value history. This allows you
to refer to them in other expressions. Values are kept until the symbol table is re-read or
discarded.
The values printed are given history numbers by which you can refer to them. These
are successive integers starting with one. print shows you the history number assigned to
a value by printing ‘$num = ’ before the value; here num is the history number.
Just $ refers to the most recent value in the history, and $$ refers to the value before that. $$n refers to the nth value from
the end;
For example, suppose you have just printed a pointer to a structure and want to see the
contents of the structure. It suffices to type
p *$
If you have a chain of structures where the component next points to the next one, you
can print the contents of the next one with this:
p *$.next
You can print successive links in the chain by repeating this command—which you can do
by just typing RET.

Note that the history records values, not expressions. If the value of x is 4 and you type
these commands:
print x
set x=5
then the value recorded in the value history by the print command remains 4 even though
the value of x has changed.


For implementing pretty printers for new types you should read the Python API details.

set print array on
Pretty print arrays. This format is more convenient to read, but uses more
space. The default is off.

set print array-indexes on
Print the index of each element when displaying arrays. May be more convenient
to locate a given element in the array or quickly find the index of a given element
in that printed array. The default is off.

set print pretty on
Cause gdb to print structures in an indented format with one member per line,
like this:
$1 = {
next = 0x0,
flags = {
sweet = 1,
sour = 1
},
meat = 0x54 "Pork"
}

set print object off
Display only the declared type of objects, without reference to the virtual function
table. This is the default setting.

set print vtbl on
Pretty print C++ virtual function tables. The default is off. (The vtbl commands
do not work on programs compiled with the HP ANSI C++ compiler
(aCC).)

發佈了36 篇原創文章 · 獲贊 8 · 訪問量 8萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章