Introduction to the GNU gdb debugger
This section provides a brief overview on using gdb for debugging
OOMMF programs. For a more thorough background you can refer to the
extensive documentation available from the GNU Project or the many
online tutorials.
In the following examples, the (bash) shell prompt is indicated by
$, and the gdb prompt with (gdb). You launch gdb
from the command line with the name of the executable file. You can
provide arguments to the executable when you run the program inside
gdb. For example, to debug a problem with an Oxs extension,
we would run Boxsi with a sample troublesome .mif file, say
$ cd oommf/app/oxs
$ gdb linux-x86_64/oxs
(gdb) run boxsi.tcl local/foo/foo.mif -threads 1
Subsequent run commands will reuse the same arguments unless you
specify new ones. In this example the -threads 1 option to
Boxsi is used to simplify the debugging process. If you need or
want to debug with multiple threads, then read up on the “thread”
command in the gdb documentation.
The program run will automatically terminate and return to the
(gdb) prompt if the program exits or aborts. Alternately you can
Ctrl-C at any time to manually halt. To exit gdb type
quit at the (gdb) prompt.
gdb has a large collection of commands that
you can use to control program flow and inspect program data. An example
we saw before is backtrace, which can be abbreviated as
bt. Fig. 5.3 lists a few of the more common
commands, and Figs. 5.4 and
5.5 provide an example debugging session
illustrating their use.
Shellcommand: gdb linux-x86_64/oxs [corefile (opt)] |
Command |
Abbr. |
Description |
Process control |
run [args] |
|
run executable with args |
run |
|
run executable with last args |
show args |
|
display current args |
set env FOO bar |
|
set envr. variable FOO to “bar” |
unset env FOO |
|
unset environment variable FOO |
Ctrl-C |
|
stop and return to (gdb) prompt |
kill |
|
terminate current run |
quit |
|
exit gdb |
Introspection |
backtrace |
bt |
stack trace |
frame 7 |
f 7 |
change to stack frame 7 |
list 123 |
l 123 |
list source about line 123 |
list foo.cc:50 |
|
list source about line 50 of foo.cc |
list - |
l - |
list preceding ten lines |
list foo::bar |
|
list first ten lines of function foo::bar() |
set listsize 20 |
|
change list output length to 20 lines |
info locals |
i lo |
print local variables |
info args |
|
print function arguments |
print foo |
p foo |
write info on variable foo |
printf " %g" , foo |
|
print foo with format %g (note comma) |
Flow control |
break bar.cc:13 |
b bar.cc:13 |
set breakpoint at line 13 of bar.cc |
break foo::bar |
b foo::bar |
break on entry to C++ routine foo::bar() |
info breakpoints |
i b |
list breakpoints |
delete 4 |
d 4 |
delete breakpoint 4 |
delete |
d |
delete all breakpoints |
ignore 3 100 |
|
skip breakpoint 3 100 times |
watch -location foo |
|
break when foo changes value |
condition 2 foo> 10 |
|
break if foo> 10 at breakpoint 2 |
continue |
c |
continue running |
step [#] |
s [#] |
take # steps, follow into subroutines |
next [#] |
n [#] |
take # steps, step over subroutines |
finish |
|
run to end of current subroutine (step out) |
Threads |
info threads |
i th |
list threads |
thread 4 |
t 4 |
switch context to thread 4 |
$ cd app/oxs
$ gdb linux-x86_64/oxs
(gdb) run boxsi.tcl examples/stdprob1.mif -threads 1
Starting program: oommf/app/oxs/linux-x86_64/oxs boxsi.tcl examples/stdp...
oxs: oommf/app/oxs/base/meshvalue.h:319: const T& Oxs_MeshValue<T>::oper...
Assertion `0<=index && index<size' failed.
Thread 1 "oxs" received signal SIGABRT, Aborted.
0x00007ffff65d837f in raise () from /lib64/libc.so.6
(gdb) bt
#0 0x00007ffff65d837f in raise () from /lib64/libc.so.6
[...]
#4 0x000000000041012a in Oxs_MeshValue<double>::operator[]
(this=0xcbeb58, index=40000) at oommf/app/oxs/base/meshvalue.h:319
#5 0x000000000061e88a in Oxs_UniaxialAnisotropy::RectIntegEnergy
(this=0x1307d60, state=..., ocedt=..., ocedtaux=..., node_start=36864,
node_stop=40000) at oommf/app/oxs/ext/uniaxialanisotropy.cc:241
[...]
(gdb) frame 5
#5 0x000000000061e88a in Oxs_UniaxialAnisotropy::RectIntegEnergy...
241 field_mult = (2.0/MU0)*k*Ms_inverse[i];
(gdb) set listsize 5
(gdb) list
239 if(aniscoeftype == K1_TYPE) {
240 if(!K1_is_uniform) k = K1[i];
241 field_mult = (2.0/MU0)*k*Ms_inverse[i];
242 } else {
243 if(!Ha_is_uniform) field_mult = Ha[i];
(gdb) print i
$1 = 40000
(gdb) print Ms_inverse
$2 = (const Oxs_MeshValue<double> &) @0xcbeb58: {arr = 0x7ffff7ebf000,
size = 40000, arrblock = {datablock = 0x7ffff7ebe010 "",
arr = 0x7ffff7ebf000, arr_size = 40000, strip_count = 1,
strip_size = 320000, strip_pos = std::vector of length 2,
capacity 2 = {0, 320000}}, static MIN_THREADING_SIZE = 10000}
(gdb) kill
Kill the program being debugged? (y or n) y
[Inferior 1 (process 1309854) killed]
Figure
5.
4:
Sample
gdb session,
part 1: Locating the error
(description)
(gdb) break uniaxialanisotropy.cc:239
Breakpoint 1 at 0x61e811: file ext/uniaxialanisotropy.cc, line 239.
(gdb) run
Starting program: oommf/app/oxs/linux-x86_64/oxs boxsi.tcl examples/s...
[...]
Thread 1 "oxs" hit Breakpoint 1, Oxs_UniaxialAnisotropy::RectIntegEne...
239 if(aniscoeftype == K1_TYPE) {
(gdb) info breakpoints
Num Type Disp Enb Address What
1 breakpoint keep y 0x000000000061e811 in Oxs_UniaxialAni...
breakpoint already hit 1 time
(gdb) ignore 1 39999
Will ignore next 39999 crossings of breakpoint 1.
(gdb) continue
Thread 1 "oxs" hit Breakpoint 1, Oxs_UniaxialAnisotropy::RectIntegEne...
239 if(aniscoeftype == K1_TYPE) {
(gdb) print i
$3 = 39991
(gdb) condition 1 i>=40000
(gdb) c
Thread 1 "oxs" hit Breakpoint 1, Oxs_UniaxialAnisotropy::RectIntegEne...
239 if(aniscoeftype == K1_TYPE) {
(gdb) l
237
238 for(OC_INDEX i=node_start;i<=node_stop;++i) {
239 if(aniscoeftype == K1_TYPE) {
240 if(!K1_is_uniform) k = K1[i];
241 field_mult = (2.0/MU0)*k*Ms_inverse[i];
(gdb) next
240 if(!K1_is_uniform) k = K1[i];
(gdb) n
241 field_mult = (2.0/MU0)*k*Ms_inverse[i];
(gdb) step
Oxs_MeshValue<double>::operator[] (this=0xcbeb58, index=40000)
at oommf/app/oxs/base/meshvalue.h:319
319 assert(0<=index && index<size);
(gdb) printf "%d,%d\n", index, size
40000,40000
(gdb) quit
Figure
5.
5:
Sample
gdb session,
part 2: Bug details
(description)
Two notes concerning gdb on macOS: First, as mentioned earlier,
if you install gdb through MacPorts, the executable name is
ggdb. Second, debuggers operate outside the normal end-user program
envelope and may run afoul of the OS security system. In particular to
use gdb you may need to set up a certificate in the
macOS System Keychain for it; details on this process can be found
online. This issue might be resolved for lldb (next section) as
part of the installation process if it and clang++ were installed
as part of the Xcode package.
This introduction only scratches the surface of gdb commands and
capabilities. You can find tutorials and additional information online,
or else refer to the gdb documentation from GNU for full details.
OOMMF Documentation Team
September 27, 2024