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 1Subsequent 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]
(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
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.