使用 GDB------------- ########################################
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 auxv--Display the inferior 's auxiliary vector
info bookmarks -- Status of user-settable bookmarks
info breakpoints -- Status of user-settable breakpoints
info catch -- Exceptions that can be caught in the current stack frame
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 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 functions -- All function names
info handle -- What debugger does when program gets various signals
info inferiors -- IDs of currently known inferiors
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 mem -- Memory region attributes
info os -- Show OS data ARG
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
info scope -- List the variables local to a scope
info selectors -- All Objective-C selectors
info set -- Show all GDB settings
info sharedlibrary -- Status of loaded shared object libraries
info signals -- What debugger does when program gets various signals
info source -- Information about the current source file
info sources -- Source files in the program
info stack -- Backtrace of the stack
info static-tracepoint-markers -- List target static tracepoints markers
info symbol -- Describe what symbol is at location ADDRinfo target -- Names of targets and files being debugged
info tasks -- Provide information about all known Ada tasks
info terminal -- Print inferior's saved terminal status
info threads -- IDs of currently known threads . thread 4 : 跳转到线程 4 bt : 查看 4 线程堆栈 frame 2: 查看当前线程堆栈的地 2 行
info tracepoints -- Status of tracepoints
info tvariables -- Status of trace state variables and their values
info types -- All type names
info variables -- All global and static variable names
info vector -- Print the status of the vector unit
info warranty -- Various kinds of warranty you do not have
info watchpoints -- Status of watchpoints
info win -- List of all displayed windows
#####################################################
set ada -- Prefix command for changing Ada-specfic settings
set annotate -- Set annotation_level
set architecture -- Set architecture of target
set args -- Set argument list to give program being debugged when it is started
set auto-solib-add -- Set autoloading of shared library symbols
set backtrace -- Set backtrace specific variables
set breakpoint -- Breakpoint specific settings
set build-id-core-loads -- Set whether CORE-FILE loads the build-id associated files automatically
set build-id-verbose -- Set debugging level of the build-id locator
set can-use-hw-watchpoints -- Set debugger's willingness to use watchpoint hardware
set case-sensitive -- Set case sensitivity in name search
set charset -- Set the host and target character sets
set check -- Set the status of the type/range checker
set circular-trace-buffer -- Set target's use of circular trace buffer
set coerce-float-to-double -- Set coercion of floats to doubles when calling functions
set complaints -- Set max number of complaints about incorrect symbols
set confirm -- Set whether to confirm potentially dangerous operations
set cp-abi -- Set the ABI used for inspecting C++ objects
set data-directory -- Set GDB's data directory
set debug -- Generic command for setting gdb debugging flags
set debug-file-directory -- Set the directories where separate debug symbols are searched for
set debugvarobj -- Set varobj debugging
set default-collect -- Set the list of expressions to collect by default
set demangle-style -- Set the current C++ demangling style
set detach-on-fork -- Set whether gdb will detach the child of a fork
set disable-randomization -- Set disabling of debuggee's virtual address space randomization
set disassemble-next-line -- Set whether to disassemble next source line or insn when execution stops
set disassembly-flavor -- Set the disassembly flavor
set disconnected-tracing -- Set whether tracing continues after GDB disconnects
set displaced-stepping -- Set debugger's willingness to use displaced stepping
set editing -- Set editing of command lines as they are typed
set endian -- Set endianness of target
set environment -- Set environment variable value to give the program
set exec-direction -- Set direction of execution
set exec-done-display -- Set notification of completion for asynchronous execution commands
set exec-wrapper -- Set a wrapper for running programs
set extension-language -- Set mapping between filename extension and source language
set follow-exec-mode -- Set debugger response to a program call of exec
set follow-fork-mode -- Set debugger response to a program call of fork or vfork
set gnutarget -- Set the current BFD target
set height -- Set number of lines gdb thinks are in a page
set history -- Generic command for setting command history parameters
set host-charset -- Set the host character set
set inferior-tty -- Set terminal for future runs of program being debugged
set input-radix -- Set default input radix for entering numbers
set interactive-mode -- Set whether GDB should run in interactive mode or not
set language -- Set the current source language
set libthread-db-search-path -- Set search path for libthread_db
set listsize -- Set number of source lines gdb will list by default
set logging -- Set logging options
set max-user-call-depth -- Set the max call depth for user-defined commands
set may-insert-breakpoints -- Set permission to insert breakpoints in the target
set may-insert-fast-tracepoints -- Set permission to insert fast tracepoints in the target
set may-insert-tracepoints -- Set permission to insert tracepoints in the target
set may-interrupt -- Set permission to interrupt or signal the target
set may-write-memory -- Set permission to write into target memory
set may-write-registers -- Set permission to write into registers
set mem -- Memory regions settings
set multiple-symbols -- Set the debugger behavior when more than one symbol are possible matches
set non-stop -- Set whether gdb controls the inferior in non-stop mode
set observer -- Set whether gdb controls the inferior in observer mode
set opaque-type-resolution -- Set resolution of opaque struct/class/union types (if set before loading symbols)
set osabi -- Set OS ABI of target
set output-radix -- Set default output radix for printing of values
set overload-resolution -- Set overload resolution in evaluating C++ functions
set pagination -- Set state of pagination
set print -- Generic command for setting how things print
set prompt -- Set gdb's prompt
set radix -- Set default input and output number radices
set record -- Set record options
set remote -- Remote protocol specific variables
set remoteaddresssize -- Set the maximum size of the address (in bits) in a memory packet
set remotebaud -- Set baud rate for remote serial I/O
set remotebreak -- Set whether to send break if interrupted
set remotecache -- Set cache use for remote targets
set remoteflow -- Set use of hardware flow control for remote serial I/O
set remotelogbase -- Set numerical base for remote session logging
set remotelogfile -- Set filename for remote session recording
set remotetimeout -- Set timeout limit to wait for target to respond
set remotewritesize -- Set the maximum number of bytes per memory write packet (deprecated)
set schedule-multiple -- Set mode for resuming threads of all processes
set scheduler-locking -- Set mode for locking scheduler during execution
set script-extension -- Set mode for script filename extension recognition
set serial -- Set default serial/parallel port configuration
set solib-absolute-prefix -- Set an alternate system root
set solib-search-path -- Set the search path for loading non-absolute shared library symbol files
set stack-cache -- Set cache use for stack access
set step-mode -- Set mode of the step operation
set stop-on-solib-events -- Set stopping for shared library events
set struct-convention -- Set the convention for returning small structs
set substitute-path -- Usage: set substitute-path FROM TO
set symbol-reloading -- Set dynamic symbol table reloading multiple times in one run
set sysroot -- Set an alternate system root
set target-async -- Set whether gdb controls the inferior in asynchronous mode
set target-charset -- Set the target character set
set target-file-system-kind -- Set assumed file system kind for target reported file names
set target-wide-charset -- Set the target wide character set
set tcp -- TCP protocol specific variables
set tdesc -- Set target description specific variables
set trace-commands -- Set tracing of GDB CLI commands
set trust-readonly-sections -- Set mode for reading from readonly sections
set tui -- TUI configuration variables
set unwind-on-terminating-exception -- Set unwinding of stack if std::terminate is called while in call dummy
set unwindonsignal -- Set unwinding of stack if a signal is received while in a call dummy
set variable -- Evaluate expression EXP and assign result to variable VAR
set verbose -- Set verbosity
set watchdog -- Set watchdog timer
set width -- Set number of characters gdb thinks are in a line
set write -- Set writing into executable and core files
一般来说 GDB 主要调试的是 C/C++ 的程序.要调试 C/C++ 的程序,首先在编译时,我们必须要把调试信息加到可执行文件中.使用编译器(cc/gcc/g++)的 -g 参数可以做到这一点.如: $gcc -g -Wall hello.c -o hello
$g++ -g -Wall hello.cpp -o hello 如果没有 - g,你将看不见程序的函数名,变量名,所代替的全是运行时的内存地址.当你用 - g 把调试信息加入之后,并成功编译目标代码以后,让我们来看看如何用 gdb 来调试他. 启动 GDB 的方法有以下几种:
gdb <program>
gdb <program> core : 用 gdb 同时调试一个运行程序和 core 文件,core 是程序非法执行后 core dump 后产生的文件.
gdb <program> <PID> : 指定服务程序运行时的进程 ID.gdb 会自动 attach 上去,并调试他.program 应该在 PATH 环境变量中搜索得到.
GDB 启动时,可以加上一些 GDB 的启动开关,详细的开关可以用 gdb -help 查看.我在下面只例举一些比较常用的参数:
-symbols
-s : 从指定文件中读取符号表.
-se file : 从指定文件中读取符号表信息,并把他用在可执行文件中.
-core
-c : 调试时 core dump 的 core 文件.
-directory
-d : 加入一个源文件的搜索路径.默认搜索路径是环境变量中 PATH 所定义的路径.
GDB 的命令概貌 -------------
可以使用 help <class> 命令,如:help breakpoints,查看设置断点的所有命令. gdb 中,输入命令时,可以不用打全命令,只用打命令的前几个字符就可以了,你可以敲击两次 TAB 键来补齐命令的全称,如果有重复的,那么 gdb 会把其列出来. GDB 中运行 UNIX 的 shell 程序 ------------ 在 gdb 环境中,你可以执行 UNIX 的 shell 的命令,使用 gdb 的 shell 命令来完成: shell <command string> 调用 UNIX 的 shell 来执行 <command string>,环境变量 SHELL 中定义的 UNIX 的 shell 将会被用来执行 <command string>,如果 SHELL 没有定义,那就使用 UNIX 的标准 shell:/bin/sh.(在 Windows 中使用 Command.com 或 cmd.exe) 还有一个 gdb 命令是 make: make <make-args> 可以在 gdb 中执行 make 命令来重新 build 自己的程序.这个命令等价于 "shell make <make-args>". 在 GDB 中运行程序 ----------------- 当以 gdb <program> 方式启动 gdb 后,gdb 会在 PATH 路径和当前目录中搜索 <program> 的源文件.如要确认 gdb 是否读到源文件,可使用 l 或 list 命令,看看 gdb 是否能列出源代码.
在 gdb 中,运行程序使用 r 或是 run 命令.程序的运行,你有可能需要设置下面四方面的事.
1,程序运行参数.
set args 可指定运行时参数.(如:set args 10 20 30 40 50)
show args 命令可以查看设置好的运行参数.
2,运行环境.
path <dir> 可设定程序的运行路径.
show paths 查看程序的运行路径.
set environment varname [=value] 设置环境变量.如:set env USER=hchen
show environment [varname] 查看环境变量.
3,工作目录.
cd
相当于 shell 的 cd 命令.
pwd 显示当前的所在目录.
4,程序的输入输出.
info terminal 显示你程序用到的终端的模式.
使用重定向控制程序输出.如:run > outfile
tty 命令可以指写输入输出的终端设备.如:tty /dev/ttyb 调试已运行的程序 -------- 两种方法:
在 UNIX 下用 ps 查看正在运行的程序的 PID(进程 ID),然后用 gdb <program> PID 格式挂接正在运行的程序.
先用 gdb <program> 关联上源代码,并进行 gdb,在 gdb 中用 attach 命令来挂接进程的 PID.并用 detach 来取消挂接的进程.
暂停 / 恢复程序运行 -------- 当进程被 gdb 停住时,你可以使用 info program 来查看程序的是否在运行,进程号,被暂停的原因. 在 gdb 中,我们可以有以下几种暂停方式:断点(BreakPoint),观察点(Watch Point),捕捉点(Catch Point),信号(Signals),线程停止(Thread Stops).如果要恢复程序运行,可以使用 c 或是 continue 命令.设置断点(Break Points)我们用 break 命令来设置断点.下面有几点设置断点的方法:break <function> : 在进入指定函数时停住.C++ 中可以使用 class::function 或 function(type,type) 格式来指定函数名.break <linenum> : 在指定行号停住.
break + offset
break - offset
在当前行号的前面或后面的 offset 行停住.offiset 为自然数.
break filename:linenum
在源文件 filename 的 linenum 行处停住.
break filename:function
在源文件 filename 的 function 函数的入口处停住.
break *address
在程序运行的内存地址处停住.
break
break 命令没有参数时,表示在下一条指令处停住.
break ... if <condition>
... 可以是上述的参数,condition 表示条件,在条件成立时停住.比如在循环体中,可以设置 break if i=100,表示当 i 为 100 时停住程序.
查看断点时,可使用 info 命令,如下所示:(注:n 表示断点号)
info breakpoints[n] info
break [n]
设置观察点(WatchPoint) 观察点一般来观察某个表达式(变量也是一种表达式)的值是否有变化了,如果有变化,马上停住程序.我们有下面的几种方法来设置观察点:
watch <expr>
为表达式(变量)expr 设置一个观察点.一表达式值有变化时,马上停住程序.
rwatch <expr>
当表达式(变量)expr 被读时,停住程序.
awatch <expr>
当表达式(变量)的值被读或被写时,停住程序.
info watchpoints
列出当前所设置了的所有观察点.
设置捕捉点(CatchPoint)你可设置捕捉点来捕捉程序运行时的一些事件.如:载入共享库(动态链接库)或是 C++ 的异常.设置捕捉点的格式为:
catch <event>
当 event 发生时,停住程序.event 可以是下面的内容:
throw 一个 C++ 抛出的异常.(throw 为关键字)
catch 一个 C++ 捕捉到的异常.(catch 为关键字)
exec 调用系统调用 exec 时.(exec 为关键字,目前此功能只在 HP-UX 下有用)
fork 调用系统调用 fork 时.(fork 为关键字,目前此功能只在 HP-UX 下有用)
vfork 调用系统调用 vfork 时.(vfork 为关键字,目前此功能只在 HP-UX 下有用)
load 或 load <libname> 载入共享库(动态链接库)时.(load 为关键字,目前此功能只在 HP-UX 下有用)
unload 或 unload <libname> 卸载共享库(动态链接库)时.(unload 为关键字,目前此功能只在 HP-UX 下有用)
tcatch <event> 只设置一次捕捉点,当程序停住以後,应点被自动删除.
维护停止点 上面说了如何设置程序的停止点,GDB 中的停止点也就是上述的三类.在 GDB 中,如果你觉得已定义好的停止点没有用了,你可以使用 delete,clear,disable,enable 这几个命令来进行维护.
clear
清除所有的已定义的停止点.
clear <
function > clear
清除所有设置在函数上的停止点.
clear <linenum>
clear <filename:linenum>
清除所有设置在指定行上的停止点.
delete [breakpoints] [range...]
删除指定的断点,breakpoints 为断点号.如果不指定断点号,则表示删除所有的断点.range 表示断点号的范围(如:3-7).其简写命令为 d.
比删除更好的一种方法是 disable 停止点,disable 了的停止点,GDB 不会删除,当你还需要时,enable 即可,就好像回收站一样.
disable [breakpoints] [range...]
disable 所指定的停止点,breakpoints 为停止点号.如果什么都不指定,表示 disable 所有的停止点.简写命令是 dis.
enable [breakpoints] [range...]
enable 所指定的停止点,breakpoints 为停止点号.
enable [breakpoints] once range...
enable 所指定的停止点一次,当程序停止后,该停止点马上被 GDB 自动 disable.
enable [breakpoints] delete range...
enable 所指定的停止点一次,当程序停止后,该停止点马上被 GDB 自动删除.
停止条件维护 前面在说到设置断点时,我们提到过可以设置一个条件,当条件成立时,程序自动停止,这是一个非常强大的功能,这里,我想专门说说这个条件的相关维护命令.一般来说,为断点设置一个条件,我们使用 if 关键词,后面跟其断点条件.并且,条件设置好后,我们可以用 condition 命令来修改断点的条件.(只有 break 和 watch 命令支持 if,catch 目前暂不支持 if)
condition <bnum> <expression>
修改断点号为 bnum 的停止条件为 expression.
condition <bnum>
清除断点号为 bnum 的停止条件.
还有一个比较特殊的维护命令 ignore,你可以指定程序运行时,忽略停止条件几次.
ignore <bnum> <count>
表示忽略断点号为 bnum 的停止条件 count 次.
为停止点设定运行命令 我们可以使用 GDB 提供的 command 命令来设置停止点的运行命令.也就是说,当运行的程序在被停止住时,我们可以让其自动运行一些别的命令,这很有利行自动化调试.对基于 GDB 的自动化调试是一个强大的支持.
commands[bnum]...command - list...end
为断点号 bnum 指写一个命令列表.当程序被该断点停住时,gdb 会依次运行命令列表中的命令.例如:
break foo
if x > 0 commands printf "x is %d\n",
x
continue end
断点设置在函数 foo 中,断点条件是 x>0,如果程序被断住后,也就是,一旦 x 的值在 foo 函数中大于 0,GDB 会自动打印出 x 的值,并继续运行程序.
如果你要清除断点上的命令序列,那么只要简单的执行一下 commands 命令,并直接在打个 end 就行了.断点菜单 在 C++ 中,可能会重复出现同一个名字的函数若干次(函数重载),在这种情况下,break <function> 不能告诉 GDB 要停在哪个函数的入口.当然,你可以使用 break <function(type)> 也就是把函数的参数类型告诉 GDB,以指定一个函数.否则的话,GDB 会给你列出一个断点菜单供你选择你所需要的断点.你只要输入你菜单列表中的编号就可以了.如:
(gdb) b String: :after[0] cancel[1] all[2] file: String.cc;
line number: 867[3] file: String.cc;
line number: 860[4] file: String.cc;
line number: 875[5] file: String.cc;
line number: 853[6] file: String.cc;
line number: 846[7] file: String.cc;
line number: 735 > 2 4 6 Breakpoint 1 at 0xb26c: file String.cc,
line 867.Breakpoint 2 at 0xb344: file String.cc,
line 875.Breakpoint 3 at 0xafcc: file String.cc,
line 846.Multiple breakpoints were set.Use the "delete"command to delete unwanted breakpoints. (gdb)
可见,GDB 列出了所有 after 的重载函数,你可以选一下列表编号就行了.0 表示放弃设置断点,1 表示所有函数都设置断点.恢复程序运行和单步调试当程序被停住了,你可以用 continue 命令恢复程序的运行直到程序结束,或下一个断点到来.也可以使用 step 或 next 命令单步跟踪程序.
continue [ignore-count]
c [ignore-count]
fg [ignore-count]
恢复程序运行,直到程序结束,或是下一个断点到来.ignore-count 表示忽略其后的断点次数.continue,c,fg 三个命令都是一样的意思.
step <count>
单步跟踪,如果有函数调用,他会进入该函数.进入函数的前提是,此函数被编译有 debug 信息.很像 VC 等工具中的 step in.后面可以加 count 也可以不加,不加表示一条条地执行,加表示执行后面的 count 条指令,然后再停住.
next <count>
同样单步跟踪,如果有函数调用,他不会进入该函数.很像 VC 等工具中的 step over.后面可以加 count 也可以不加,不加表示一条条地执行,加表示执行后面的 count 条指令,然后再停住.
set step-mode
set step-mode on
打开 step-mode 模式,于是,在进行单步跟踪时,程序不会因为没有 debug 信息而不停住.这个参数有很利于查看机器码.
set step-mod off
关闭 step-mode 模式.
finish
运行程序,直到当前函数完成返回.并打印函数返回时的堆栈地址和返回值及参数值等信息.
until 或 u
当你厌倦了在一个循环体内单步跟踪时,这个命令可以运行程序直到退出循环体.
stepi 或 si
nexti 或 ni
单步跟踪一条机器指令!一条程序代码有可能由数条机器指令完成,stepi 和 nexti 可以单步执行机器指令.与之一样有相同功能的命令是 "display/i $pc" ,当运行完这个命令后,单步跟踪会在打出程序代码的同时打出机器指令(也就是汇编代码)
信号(Signals)---------- 信号是一种软中断,是一种处理异步事件的方法.一般来说,操作系统都支持许多信号.尤其是 UNIX,比较重要应用程序一般都会处理信号.UNIX 定义了许多信号,比如 SIGINT 表示中断字符信号,也就是 Ctrl+C 的信号,SIGBUS 表示硬件故障的信号;SIGCHLD 表示子进程状态改变信号;SIGKILL 表示终止程序运行的信号,等等.信号量编程是 UNIX 下非常重要的一种技术.
GDB 有能力在你调试程序的时候处理任何一种信号,你可以告诉 GDB 需要处理哪一种信号.你可以要求 GDB 收到你所指定的信号时,马上停住正在运行的程序,以供你进行调试.你可以用 GDB 的 handle 命令来完成这一功能.
handle < signal > <keywords... >
在 GDB 中定义一个信号处理.信号 <signal> 可以以 SIG 开头或不以 SIG 开头,可以用定义一个要处理信号的范围(如:SIGIO- SIGKILL,表示处理从 SIGIO 信号到 SIGKILL 的信号,其中包括 SIGIO,SIGIOT,SIGKILL 三个信号),也可以使用关键字 all 来标明要处理所有的信号.一旦被调试的程序接收到信号,运行程序马上会被 GDB 停住,以供调试.其 <keywords> 可以是以下几种关键字的一个或多个.
nostop
当被调试的程序收到信号时,GDB 不会停住程序的运行,但会打出消息告诉你收到这种信号.
stop
当被调试的程序收到信号时,GDB 会停住你的程序.
当被调试的程序收到信号时,GDB 会显示出一条信息.
noprint
当被调试的程序收到信号时,GDB 不会告诉你收到信号的信息.
pass
noignore
当被调试的程序收到信号时,GDB 不处理信号.这表示,GDB 会把这个信号交给被调试程序处理.
nopass
ignore
当被调试的程序收到信号时,GDB 不会让被调试程序来处理这个信号.
info signals
info handle
查看有哪些信号在被 GDB 检测中.
[] 线程(Thread Stops)
如果你程序是多线程的话,你可以定义你的断点是否在所有的线程上,或是在某个特定的线程.GDB 很容易帮你完成这一工作.
break < linespec > thread < threadno >
break < linespec > thread < threadno >
if...
linespec 指定了断点设置在的源程序的行号.threadno 指定了线程的 ID,注意,这个 ID 是 GDB 分配的,你可以通过 "info threads" 命令来查看正在运行程序中的线程信息.如果你不指定 thread <threadno> 则表示你的断点设在所有线程上面.你还可以为某线程指定断点条件.如:
(gdb) break frik.c: 13 thread 28
if bartab > lim
当你的程序被 GDB 停住时,所有的运行线程都会被停住.这方便你查看运行程序的总体情况.而在你恢复程序运行时,所有的线程也会被恢复运行.那怕是主进程在被单步调试时.
[] 查看栈信息
当程序被停住了,你需要做的第一件事就是查看程序是在哪里停住的.当你的程序调用了一个函数,函数的地址,函数参数,函数内的局部变量都会被压入 "栈"(Stack)中.你可以用 GDB 命令来查看当前的栈中的信息.
下面是一些查看函数调用栈信息的 GDB 命令:
backtrace
bt
打印当前的函数调用栈的所有信息.如:
(gdb) bt#0 func(n = 250) at tst.c: 6#1 0x08048524 in main(argc = 1, argv = 0xbffff674) at tst.c: 30#2 0x400409ed in __libc_start_main() from / lib / libc.so.6
从上可以看出函数的调用栈信息:__libc_start_main --> main() --> func()
backtrace
bt
n 是一个正整数,表示只打印栈顶上 n 层的栈信息.
backtrace <-n>
bt <-n>
-n 表一个负整数,表示只打印栈底下 n 层的栈信息.
如果你要查看某一层的信息,你需要切换当前栈,一般来说,程序停止时,最顶层的栈就是当前栈,如果你要查看栈下面层的详细信息,首先要做的是切换当前栈.
frame
f
n 是一个从 0 开始的整数,是栈中的层编号.比如:frame 0,表示栈顶,frame 1,表示栈的第二层.
up <n>
表示向栈的上面移动 n 层,可以不打 n,表示向上移动一层.
down <n>
表示向栈的下面移动 n 层,可以不打 n,表示向下移动一层.
上面的命令,都会打印出移动到的栈层的信息.如果你不想让其打出信息.你可以使用这三个命令:
select - frame < n > 对应于frame命令.up - silently < n > 对应于up命令.down - silently < n > 对应于down命令.
查看当前栈层的信息,你可以用以下 GDB 命令:
frame 或 f
会打印出这些信息:栈的层编号,当前的函数名,函数参数值,函数所在文件及行号,函数执行到的语句.
info frame
info f
这个命令会打印出更为详细的当前栈层的信息,只不过,大多数都是运行时的内存地址.比如:函数地址,调用函数的地址,被调用函数的地址,目前的函数是由什么样的程序语言写成的,函数参数地址及值,局部变量的地址等等.如:
(gdb) info f Stack level 0,
frame at 0xbffff5d4: eip = 0x804845d in func(tst.c: 6);
saved eip 0x8048524 called by frame at 0xbffff60c source language c.Arglist at 0xbffff5d4,
args: n = 250 Locals at 0xbffff5d4,
Previous frame 's sp is 0x0
Saved registers:
ebp at 0xbffff5d4, eip at 0xbffff5d8
'info args
打印出当前函数的参数名及其值.
info locals
打印出当前函数中所有局部变量及其值.
info catch
打印出当前的函数中的异常处理信息.
[] 查看源程序
[] 显示源代码
GDB 可以打印出所调试程序的源代码,当然,在程序编译时一定要加上 - g 的参数,把源程序信息编译到执行文件中.不然就看不到源程序了.当程序停下来以后,GDB 会报告程序停在了那个文件的第几行上.你可以用 list 命令来打印程序的源代码.还是来看一看查看源代码的 GDB 命令吧.
list <linenum>
显示程序第 linenum 行的周围的源程序.
list <function>
显示函数名为 function 的函数的源程序.
list
显示当前行后面的源程序.
list -
显示当前行前面的源程序.
一般是打印当前行的上 5 行和下 5 行,如果显示函数是是上 2 行下 8 行,默认是 10 行,当然,你也可以定制显示的范围,使用下面命令可以设置一次显示源程序的行数.
set listsize <count>
设置一次显示源代码的行数.
show listsize
查看当前 listsize 的设置.
list 命令还有下面的用法:
list <first>, <last>
显示从 first 行到 last 行之间的源代码.
list , <last>
显示从当前行到 last 行之间的源代码.
list +
往后显示源代码.
一般来说在 list 后面可以跟以下这些参数:
<linenum>
行号.
<+offset>
当前行号的正偏移量.
<-offset>
当前行号的负偏移量.
<filename:linenum>
哪个文件的哪一行.
<function>
函数名.
<filename:function>
哪个文件中的哪个函数.
<*address>
程序运行时的语句在内存中的地址.
[] 搜索源代码
不仅如此,GDB 还提供了源代码搜索的命令:
forward-search
search
向前面搜索.
reverse-search <regexp>
全部搜索.
其中,<regexp> 就是正则表达式,也主一个字符串的匹配模式,关于正则表达式,我就不在这里讲了,还请各位查看相关资料.
[] 指定源文件的路径
某些时候,用 - g 编译过后的执行程序中只是包括了源文件的名字,没有路径名.GDB 提供了可以让你指定源文件的路径的命令,以便 GDB 进行搜索.
directory
dir
加一个源文件路径到当前路径的前面.如果你要指定多个路径,UNIX 下你可以使用 ":",Windows 下你可以使用 ";".
directory
清除所有的自定义的源文件搜索路径信息.
show directories
显示定义了的源文件搜索路径.
[] 源代码的内存
你可以使用 info line 命令来查看源代码在内存中的地址.info line 后面可以跟 "行号","函数名","文件名: 行号","文件名: 函数名",这个命令会打印出所指定的源码在运行时的内存地址,如:
(gdb) info line tst.c: func Line 5 of "tst.c"starts at address 0x8048456 < func + 6 > and ends at 0x804845d < func + 13 > .
还有一个命令(disassemble)你可以查看源程序的当前执行时的机器码,这个命令会把目前内存中的指令 dump 出来.如下面的示例表示查看函数 func 的汇编代码.
(gdb) disassemble func Dump of assembler code
for
function func: 0x8048450 < func > :push % ebp 0x8048451 < func + 1 > :mov % esp,
%ebp 0x8048453 < func + 3 > :sub $0x18,
%esp 0x8048456 < func + 6 > :movl $0x0,
0xfffffffc( % ebp) 0x804845d < func + 13 > :movl $0x1,
0xfffffff8( % ebp) 0x8048464 < func + 20 > :mov 0xfffffff8( % ebp),
%eax 0x8048467 < func + 23 > :cmp 0x8( % ebp),
%eax 0x804846a < func + 26 > :jle 0x8048470 < func + 32 > 0x804846c < func + 28 > :jmp 0x8048480 < func + 48 > 0x804846e < func + 30 > :mov % esi,
%esi 0x8048470 < func + 32 > :mov 0xfffffff8( % ebp),
%eax 0x8048473 < func + 35 > :add % eax,
0xfffffffc( % ebp) 0x8048476 < func + 38 > :incl 0xfffffff8( % ebp) 0x8048479 < func + 41 > :jmp 0x8048464 < func + 20 > 0x804847b < func + 43 > :nop 0x804847c < func + 44 > :lea 0x0( % esi, 1),
%esi 0x8048480 < func + 48 > :mov 0xfffffffc( % ebp),
%edx 0x8048483 < func + 51 > :mov % edx,
%eax 0x8048485 < func + 53 > :jmp 0x8048487 < func + 55 > 0x8048487 < func + 55 > :mov % ebp,
%esp 0x8048489 < func + 57 > :pop % ebp 0x804848a < func + 58 > :ret End of assembler dump.
[] 查看运行时数据
在你调试程序时,当程序被停住时,你可以使用 print 命令(简写命令为 p),或是同义命令 inspect 来查看当前程序的运行数据.print 命令的格式是:
print < expr > print / <f > <expr >
<expr> 是表达式,是你所调试的程序的语言的表达式(GDB 可以调试多种编程语言),<f> 是输出的格式,比如,如果要把表达式按 16 进制的格式输出,那么就是 / x.
[] 表达式
print 和许多 GDB 的命令一样,可以接受一个表达式,GDB 会根据当前的程序运行的数据来计算这个表达式,既然是表达式,那么就可以是当前程序运行中的 const 常量,变量,函数等内容.可惜的是 GDB 不能使用你在程序中所定义的宏.
表达式的语法应该是当前所调试的语言的语法,由于 C/C++ 是一种大众型的语言,所以,本文中的例子都是关于 C/C++ 的.(而关于用 GDB 调试其它语言的章节,我将在后面介绍)
在表达式中,有几种 GDB 所支持的操作符,它们可以用在任何一种语言中.
@
是一个和数组有关的操作符,在后面会有更详细的说明.
::
指定一个在文件或是一个函数中的变量.
}
表示一个指向内存地址 <addr> 的类型为 type 的一个对象.
[] 程序变量
在 GDB 中,你可以随时查看以下三种变量的值:
全局变量(所有文件可见的)
静态全局变量(当前文件可见的)
局部变量(当前 Scope 可见的)
如果你的局部变量和全局变量发生冲突(也就是重名),一般情况下是局部变量会隐藏全局变量,也就是说,如果一个全局变量和一个函数中的局部变量同名时,如果当前停止点在函数中,用 print 显示出的变量的值会是函数中的局部变量的值.如果此时你想查看全局变量的值时,你可以使用 "::" 操作符:
file: :variable
function: :variable
可以通过这种形式指定你所想查看的变量,是哪个文件中的或是哪个函数中的.例如,查看文件 f2.c 中的全局变量 x 的值:
(gdb) p 'f2.c': :x
当然,"::" 操作符会和 C++ 中的发生冲突,GDB 能自动识别 "::" 是否 C++ 的操作符,所以你不必担心在调试 C++ 程序时会出现异常.
另外,需要注意的是,如果你的程序编译时开启了优化选项,那么在用 GDB 调试被优化过的程序时,可能会发生某些变量不能访问,或是取值错误码的情况.这个是很正常的,因为优化程序会删改你的程序,整理你程序的语句顺序,剔除一些无意义的变量等,所以在 GDB 调试这种程序时,运行时的指令和你所编写指令就有不一样,也就会出现你所想象不到的结果.对付这种情况时,需要在编译程序时关闭编译优化.一般来说,几乎所有的编译器都支持编译优化的开关,例如,GNU 的 C/C++ 编译器 GCC,你可以使用 "-gstabs" 选项来解决这个问题.关于编译器的参数,还请查看编译器的使用说明文档.
[] 数组
有时候,你需要查看一段连续的内存空间的值.比如数组的一段,或是动态分配的数据的大小.你可以使用 GDB 的 "@" 操作符,"@" 的左边是第一个内存的地址的值,"@" 的右边则是你想查看内存的长度.例如,你的程序中有这样的语句:
int * array = (int * ) malloc(len * sizeof(int));
于是,在 GDB 调试过程中,你可以以如下命令显示出这个动态数组的取值:
p * array@len
@的左边是数组的首地址的值,也就是变量 array 所指向的内容,右边则是数据的长度,其保存在变量 len 中,其输出结果,大约是下面这个样子的:
(gdb) p * array@len $1 = {
2,
4,
6,
8,
10,
12,
14,
16,
18,
20,
22,
24,
26,
28,
30,
32,
34,
36,
38,
40
}
如果是静态数组的话,可以直接用 print 数组名,就可以显示数组中所有数据的内容了.
[] 输出格式
一般来说,GDB 会根据变量的类型输出变量的值.但你也可以自定义 GDB 的输出的格式.例如,你想输出一个整数的十六进制,或是二进制来查看这个整型变量的中的位的情况.要做到这样,你可以使用 GDB 的数据显示格式:
x按十六进制格式显示变量.d按十进制格式显示变量.u按十六进制格式显示无符号整型.o按八进制格式显示变量.t按二进制格式显示变量.a按十六进制格式显示变量.c按字符格式显示变量.f按浮点数格式显示变量.
(gdb) p i $21 = 101(gdb) p / a i $22 = 0x65(gdb) p / c i $23 = 101 'e' (gdb) p / f i $24 = 1.41531145e-43(gdb) p / x i $25 = 0x65(gdb) p / t i $26 = 1100101
[] 查看内存
你可以使用 examine 命令(简写是 x)来查看内存地址中的值.x 命令的语法如下所示:
x / <n / f / u > <addr >
n,f,u 是可选的参数.
n 是一个正整数,表示显示内存的长度,也就是说从当前地址向后显示几个地址的内容.
f 表示显示的格式,参见上面.如果地址所指的是字符串,那么格式可以是 s,如果地址是指令地址,那么格式可以是 i.
u 表示从当前地址往后请求的字节数,如果不指定的话,GDB 默认是 4 个 bytes.u 参数可以用下面的字符来代替,b 表示单字节,h 表示双字节,w 表示四字节,g 表示八字节.当我们指定了字节长度后,GDB 会从指内存定的内存地址开始,读写指定字节,并把其当作一个值取出来.
<addr> 表示一个内存地址.
n/f/u 三个参数可以一起使用.例如:
命令:x/3uh 0x54320 表示,从内存地址 0x54320 读取内容,h 表示以双字节为一个单位,3 表示三个单位,u 表示按十六进制显示.
[] 自动显示
你可以设置一些自动显示的变量,当程序停住时,或是在你单步跟踪时,这些变量会自动显示.相关的 GDB 命令是 display.
display < expr > display / <fmt > <expr > display / <fmt > <addr >
expr 是一个表达式,fmt 表示显示的格式,addr 表示内存地址,当你用 display 设定好了一个或多个表达式后,只要你的程序被停下来,GDB 会自动显示你所设置的这些表达式的值.
格式 i 和 s 同样被 display 支持,一个非常有用的命令是:
display / i $pc
$pc 是 GDB 的环境变量,表示着指令的地址,/i 则表示输出格式为机器指令码,也就是汇编.于是当程序停下后,就会出现源代码和机器指令码相对应的情形,这是一个很有意思的功能.
下面是一些和 display 相关的 GDB 命令:
undisplay < dnums... > delete display < dnums... >
删除自动显示,dnums 意为所设置好了的自动显式的编号.如果要同时删除几个,编号可以用空格分隔,如果要删除一个范围内的编号,可以用减号表示(如:2-5)
disable display < dnums... > enable display < dnums... >
disable 和 enalbe 不删除自动显示的设置,而只是让其失效和恢复.
info display
查看 display 设置的自动显示的信息.GDB 会打出一张表格,向你报告当然调试中设置了多少个自动显示设置,其中包括,设置的编号,表达式,是否 enable.
[] 设置显示选项
GDB 中关于显示的选项比较多,这里我只例举大多数常用的选项.
set print address
set print address on
打开地址输出,当程序显示函数信息时,GDB 会显出函数的参数地址.系统默认为打开的,如:
(gdb) f#0 set_quotes(lq = 0x34c78 "<<", rq = 0x34c88 ">>") at input.c: 530 530
if (lquote != def_lquote)
set print address off
关闭函数的参数地址显示,如:
(gdb) set print addr off(gdb) f#0 set_quotes(lq = "<<", rq = ">>") at input.c: 530 530
if (lquote != def_lquote)
show print address
查看当前地址显示选项是否打开.
set print array
set print array on
打开数组显示,打开后当数组显示时,每个元素占一行,如果不打开的话,每个元素则以逗号分隔.这个选项默认是关闭的.与之相关的两个命令如下,我就不再多说了.
set print array off
show print array
set print elements
这个选项主要是设置数组的,如果你的数组太大了,那么就可以指定一个 <number-of-elements> 来指定数据显示的最大长度,当到达这个长度时,GDB 就不再往下显示了.如果设置为 0,则表示不限制.
show print elements
查看 print elements 的选项信息.
set print null-stop <on/off>
如果打开了这个选项,那么当显示字符串时,遇到结束符则停止显示.这个选项默认为 off.
set print pretty on
如果打开 printf pretty 这个选项,那么当 GDB 显示结构体时会比较漂亮.如:
$1 = {
next = 0x0,
flags = {
sweet = 1,
sour = 1
},
meat = 0x54 "Pork"
}
set print pretty off
关闭 printf pretty 这个选项,GDB 显示结构体时会如下显示:
$1 = {
next = 0x0,
flags = {
sweet = 1,
sour = 1
},
meat = 0x54 "Pork"
}
show print pretty
查看 GDB 是如何显示结构体的.
set print sevenbit-strings <on/off>
设置字符显示,是否按 "\nnn" 的格式显示,如果打开,则字符串或字符数据按 \ nnn 显示,如 "\065".
show print sevenbit-strings
查看字符显示开关是否打开.
set print union <on/off>
设置显示结构体时,是否显式其内的联合体数据.例如有以下数据结构:
typedef enum {
Tree,
Bug
}
Species;
typedef enum {
Big_tree,
Acorn,
Seedling
}
Tree_forms;
typedef enum {
Caterpillar,
Cocoon,
Butterfly
}
Bug_forms;
struct thing {
Species it;
union {
Tree_forms tree;
Bug_forms bug;
}
form;
};
struct thing foo = {
Tree,
{
Acorn
}
};
当打开这个开关时,执行 p foo 命令后,会如下显示:
$1 = {
it = Tree,
form = {
tree = Acorn,
bug = Cocoon
}
}
当关闭这个开关时,执行 p foo 命令后,会如下显示:
$1 = {
it = Tree,
form = {...
}
}
show print union
查看联合体数据的显示方式
set print object <on/off>: 在 C++ 中,如果一个对象指针指向其派生类,如果打开这个选项,GDB 会自动按照虚方法调用的规则显示输出,如果关闭这个选项的话,GDB 就不管虚函数表了.这个选项默认是 off.
show print object
查看对象选项的设置.
set print static-members <on/off>
这个选项表示,当显示一个 C++ 对象中的内容是,是否显示其中的静态数据成员.默认是 on.
show print static-members
查看静态数据成员选项设置.
set print vtbl <on/off>
当此选项打开时,GDB 将用比较规整的格式来显示虚函数表时.其默认是关闭的.
show print vtbl
查看虚函数显示格式的选项.
[] 历史记录
当你用 GDB 的 print 查看程序运行时的数据时,你每一个 print 都会被 GDB 记录下来.GDB 会以 $1, $2, $3 ..... 这样的方式为你每一个 print 命令编上号.于是,你可以使用这个编号访问以前的表达式,如 $1.这个功能所带来的好处是,如果你先前输入了一个比较长的表达式,如果你还想查看这个表达式的值,你可以使用历史记录来访问,省去了重复输入.
[]GDB 环境变量
你可以在 GDB 的调试环境中定义自己的变量,用来保存一些调试程序中的运行数据.要定义一个 GDB 的变量很简单只需使用 GDB 的 set 命令.GDB 的环境变量和 UNIX 一样,也是以 $ 起头.如:
set $foo = *object_ptr
使用环境变量时,GDB 会在你第一次使用时创建这个变量,而在以后的使用中,则直接对其賦值.环境变量没有类型,你可以给环境变量定义任一的类型.包括结构体和数组.
show convenience
该命令查看当前所设置的所有的环境变量.
这是一个比较强大的功能,环境变量和程序变量的交互使用,将使得程序调试更为灵活便捷.例如:
set $i = 0 print bar[$i++] - >contents
于是,当你就不必,print bar[0]->contents, print bar[1]->contents 地输入命令了.输入这样的命令后,只用敲回车,重复执行上一条语句,环境变量会自动累加,从而完成逐个输出的功能.
[] 查看寄存器
要查看寄存器的值,很简单,可以使用如下命令:
info registers
查看寄存器的情况.(除了浮点寄存器)
info all-registers
查看所有寄存器的情况.(包括浮点寄存器)
info registers <regname ...>
查看所指定的寄存器的情况.
寄存器中放置了程序运行时的数据,比如程序当前运行的指令地址(ip),程序的当前堆栈地址(sp)等等.你同样可以使用 print 命令来访问寄存器的情况,只需要在寄存器名字前加一个 $ 符号就可以了.如:p $eip.
[] 改变程序的执行
一旦使用 GDB 挂上被调试程序,当程序运行起来后,你可以根据自己的调试思路来动态地在 GDB 中更改当前被调试程序的运行线路或是其变量的值,这个强大的功能能够让你更好的调试你的程序,比如,你可以在程序的一次运行中走遍程序的所有分支.
[] 修改变量值
修改被调试程序运行时的变量值,在 GDB 中很容易实现,使用 GDB 的 print 命令即可完成.如:
(gdb) print x = 4
x=4 这个表达式是 C/C++ 的语法,意为把变量 x 的值修改为 4,如果你当前调试的语言是 Pascal,那么你可以使用 Pascal 的语法:x:=4.
在某些时候,很有可能你的变量和 GDB 中的参数冲突,如:
(gdb) whatis width type = double(gdb) p width $4 = 13(gdb) set width = 47 Invalid syntax in expression.
因为,set width 是 GDB 的命令,所以,出现了 "Invalid syntax in expression" 的设置错误,此时,你可以使用 set var 命令来告诉 GDB,width 不是你 GDB 的参数,而是
来源: