$ gdb [executable | executable process_id | executable core_file]
$ gdb -tui
usage with TUI instead of CLIIs is not necessary use the prefix ./
to load an executable. The corresponding
source files are loaded automatically according to information embedded inside
the executable, manual loading is possible with the directory
command.
Commands may always be truncated if the abbreviation is unambiguous.
Environment variables can be modified within GDB, which is useful to control behavior of programs.
set environment_variable variable_name = value
set environment variableThe handling of signals like SIGINT
- which is often invoked by Ctrl+c
- and
other signals can be modified, shown and even send from within GDB.
info signals
or info handle
print table of signals and how GDB handle each onehandle signal keyword
modify behavior of signal handlingsignal signal_name
send a signal to program, either name or number of the signalfork()
.SIGTRAP
signal which will cause
it to terminate - unless it catches the signal.sleep()
can be used in the child process if a self-defined
environment variable is set. Use subsequently $ ps
to get the process_id
of
the child and use a new instance of GDB to attach to it.However - on recent Linux systems it is possible to debug either the child or
parent process after a fork()
or both - while one process is held suspended.
set follow-fork-mode [parent | child]
default is parent
show follow-fork mode
set detach-on-fork [on | off]
default is on
, with off
both process remain under control of GDB, supported on Linuxshow detach-on-fork
info inferiors
inferior inferior_number
make inferior_number
the current inferiorhttps://sourceware.org/gdb/current/onlinedocs/gdb/Forks.html
There are two modes available the all-stop mode - which is the default - and the non-stop mode - when the target supports it. The mode preference only applies when GDB starts or connects to a program. In all-stop mode all threads stop execution when GDB halts the program and all threads continue execution when GDB continues execution - also when stepping. In non-stop mode all threads continue execution while only one or multiple threads are halted by GDB.
set pagination [on | off]
using CLI pagination breaks non-stop mode, set it to off
beforeset non-stop [on | off]
turn non-stop mode on or offshow non-stop
info threads
displays a summary of all threads currently existing in the program.thread thread_number
make thread_number the current threadshow print thread-events
show messages when a thread has started or exitedset print thread-events [on | off]
- turn messages about threads on
or off
, default is on
In multi-threaded programs breakpoints or some other events in one thread may
cause blocking system calls in other threads to return prematurely. Therefore it
is important to check and handle the return values of system calls appropriately
- anyway a good programming style e.g. use the return of sleep()
within a
while loop.
https://sourceware.org/gdb/current/onlinedocs/gdb/Thread-Stops.html
run
accepts same options like the executable and passes the command to the shell. pipes, redirections and wildcards are usable.quit
exit debugger, ask for confirmation if a session is activeattach process_id
attach to running processdetach
detach from running processtarget
switch between in debug targtes e.g. process inside GDB, external process and core dumpfile executable
load or reload possibly modified executabledirectory
load or reload sources from compilation directory or current directoryTheir are two possible modes remote
and remote-extended
where the later
offers more comfortable features but is sometimes not available. The remote side
is refered as target
and the debugging side usually as host
. While the
executable on the target
can be stripped, the executable on the host
must be
fully debuggable i.e. symbol tables and libraries are available. If necessary
use:
file
specify location of executable on the host, if neededset sysroot
specify location on the host of target libraries unless GDB uses correct sysroot anyway$ gdbserver hostname_of_host:port_number executable
start program $ gdbserver hostname_of_host:port_number --attach process_id
attach to already running program$ gdb
on hosttarget [remote | extended-remote] hostname_of_target:port_number
within gdb on hostIt is also possible to use STDIO pipes:
target remote | ssh -T hostname gdbserver - --attach process_id
uses SSH without pseudo terminal and -
tells gdbserver to use stdio pipeshttps://sourceware.org/gdb/current/onlinedocs/gdb/Remote-Debugging.html
Several commands accept a location as line_spec
:
line_number
[-offset | +offset]
function
filename:line_number
filename:function
label
within functionSymbols specific to C++ programming language - like namespaces, classes and
scope operators - are usable e.g. [namespace::class::member_function]
. When an
expression is ambiguous a menu can be displayed, by default this feature is off
and all possible matches are used. This behavior can be modified with
set multiple-symbols mode
.
list [line_spec | first_line last_line]
print source lines, by default continues with the next ten linesbacktrace
shows the stack frames, summary of how
the program got where it is. the current executing frame is frame zero, followed
by its callers counting upward to the main function.frame nr_of_frame
shows current selected frame and re-centers position for list
up
one frame updown
one frame downnext
executes next source linestep
executes next source line and enters functions when debugging symbols are availablecontinue [-a]
resumes execution until program is halted by
a breakpoint or signal. when multipe threads are stopped independently, the
option -a
continues execution of all threads.until
executes until target is reachedfinish
executes up to end of current functioninterrupt [-a]
stop the whole program i.e. all threads in non-stop modejump line_spec
continue execution at line_spec
. this doesn't modify the
stack frame, stack pointer, contents of any memory location or registers,
therefore the results will be bizarre (depending on machine language) when
jump
is used to change the current executing function. jumps within the same
function should be save.break [line_spec] [thread thread_id] [if condition]
set a
breakpoint. when several overloaded functions are possible, GDB will provide a
menu.
if condition
set a breakpoint with a condition, evaluate condition each time the breakpoint is reachedthread thread_id
set a thread specific breakpoint which applies until the specfified thread exitswatch expression
set a watchpointinfo [break | breakpoints | watchpoints]
print a table of all breakpoints and watchpointsprint [variable | function() ]
show, evaluate and
manipulate data, this includes the manual execution of functions. dereference
*
and member access ->
are usable.print variable = value
manipulates data through assignment
print str.operator=("value")
set variable = value
maniuplates data through assignment but doesn't print
the result. if the variable name is identical to a subcommand of set
use the
variable
subcommand i.e. set variable variable_name = value
instead.ptype
show precise type definitionx [count][type][size] memory_address
print memory at given address, optionally with given count
, type
and size
count
number of itemstype
o(octal), x(hex), d(decimal), u(unsigned decimal), t(binary), f(float), a(address), i(instruction), c(char), s(string) and z(hex, zero padded on the left)size
b(byte), h(halfword), w(word) and g(giant, 8 bytes)info
info program
info args
print the args of the selected frame or programinfo locals
local variablesinfo variables
names and types of all variables execluding local variablesinfo address variable
exact locationinfo frame
info about current stack frameulimit -c unlimited
within file .bashrc
-g
An executable file must be loaded writable and an address within the executable
modified with set
- afterwards GDB must be quit immediately.
set write on
allows modification of binary files, likely causes messages like text file bussy
file executable
disas/r function
show disassemblyset {type} addr = value
where type
is a variable type, addr
is address
within the executable - retrieved from the dissassembly and not the from the
current program memory like a variable or pointer address.quit
leave gdb, file is writtenA binary patch can be created with diff [-a | --text]
and applied by patch
but diff
is not designed for binary patches. The resulting patch likely
becomes bigger then the binaries without actual source lines to compare.
Therefore dedicated binary patch tools are commended and perform appropriately.
Git has also support for creating and applying binary patches. Binary patching
also can be done manually with UNIX tools like dd
and strings
:
https://unix.stackexchange.com/a/214824
Reverse debugging stores a record within a buffer, the record either stops when
it reaches the limit of the buffer or overwrites the exiting record when working
as circular buffer.
* set record stop-at-limit [on | off]
when off
record log is used as circular/ring-buffer
* show record stop-at-limit
record
starts recordrecord-stop
stops record and replay target, maybe program will terminatedreverse-next
reexecutes last source linereverse-continue
reexecute until haltedrecord-step
reexecutes last source line, enters functionsreverse-finish
rexecutes up to the begin of the functionhttps://www.sourceware.org/gdb/wiki/ProcessRecord/Tutorial
breakpoint [line_spec]
program must be running, set break at appropriate location e.g. main()
or even _start
run
record
reverse-[next | step | finish | ...]
- reverse execute[next | step | finish | ...]
- forward executecontinue
will return the program to the end of the current record and haltrecord stop
In case of issues with xsave
or similiar set the environment variable
LD_BIND_NOW
to 1
before running the program.
set environment_variable LD_BIND_NOW = 1
Quote from the man page:
If set to a nonempty string, causes the dynamic linker to resolve all symbols at program startup instead of deferring function call resolution to the point when they are first referenced. This is useful when using a debugger.