5.6 C++ source code debuggers

5.6.2 Introduction to the LLVM lldb

If you are working on macOS, you may be building OOMMF with g++ or clang++. The native debugger for clang++ is lldb, which is included as part of the Xcode package. Both g++ and clang++ use the same debugging symbol format, so in principle you should be able to use either debugger with either compiler, but if you have problems with one try the other.

The lldb debugger is a command-line debugger very similar in concept to gdb, and although the command syntax is somewhat different, lldb provides a fair number of aliases to ease the transition for veteran gdb users. Fig. 5.6 lists a few of the more common lldb commands, and Figs. 5.7 and 5.8 illustrate an lldb debugging session analogous to the gdb session presented in Figs. 5.4 and 5.5.

 

Figure 5.6: lldb Debugger Cheatsheet  (description)
Shell command: lldb [-c corefile (opt)] darwin/oxs
Command Abbr. Description
Process control
process launch -- [args] r [args] run executable with args
process launch r run executable with last args
settings show target.run-args display current args
settings set target.env-vars env FOO=bar set envr. variable FOO to “bar”
   FOO=bar
Ctrl-C stop and return to (lldb) prompt
process kill kill terminate current run
quit exit lldb
Introspection
thread backtrace bt stack trace of current thread
frame select 5 f 5 change to stack frame 5
frame variable print args & vars for current frame
frame variable foo p foo print value of variable foo
source list -f foo.cc -l 50 l foo.cc:50 list source after line 50 of foo.cc
source list l list next ten lines
source list -r l - list preceding ten lines
source list -c 20 list 20 lines
Flow control
breakpoint set set breakpoint at line 99 of foo.cc
  --file foo.cc --line 99
breakpoint set break at C++ routine foo::bar()
  --name foo::bar
breakpoint list br l list breakpoints
breakpoint delete 4 br del 4 delete breakpoint 4
breakpoint delete br del delete all breakpoints
breakpoint modify -i 100 3 skip breakpoint 3 100 times
breakpoint modify -c i>7 3 break if i>7 at breakpoint 3
watchpoint set variable foo break when foo changes value
thread continue c continue running
thread step-in s take one step, into subroutines
thread step-over n take one step, over subroutines
thread step-out finish run to end of current subroutine
Threads
thread list list all threads
thread select 2 switch context to thread 2

 

 

Figure 5.7: Sample lldb session, part 1: Locating the error (description)
% cd app/oxs
% lldb darwin/oxs
(lldb) target create "darwin/oxs"
Current executable set to ’oommf/app/oxs/darwin/oxs’ (x86_64).
(lldb) process launch -- boxsi.tcl examples/stdprob1.mif -threads 1
Process 36662 launched: ’oommf/app/oxs/darwin/oxs’ (x86_64)
Assertion failed: (0<=index && index<size) [...] file meshvalue.h, line 319.
Process 36662 stopped
* thread #1, queue = ’com.apple.main-thread’, stop reason = hit program assert
    frame #4: 0x00000001000065cc oxs [...] at meshvalue.h:319:3
   316  template<class T>
   317  const T& Oxs_MeshValue<T>::operator[](OC_INDEX index) const
   318  {
-> 319    assert(0<=index && index<size);
   320    return arr[index];
   321  }
   322
Target 0: (oxs) stopped.
(lldb) bt
* thread #1, queue = ’com.apple.main-thread’, stop reason = hit program assert
    frame #0: 0x00007fff207ba91e libsystem_kernel.dylib‘__pthread_kill + 10
[...]
  * frame #4: 0x00000001000065cc oxs‘Oxs_MeshValue<double>::operator[](th...
    frame #5: 0x0000000100350fa8 oxs‘Oxs_UniaxialAnisotropy::RectIntegEne...
[...]
(lldb) frame select 5
frame #5: 0x0000000100350fa8 oxs‘Oxs_UniaxialAnisotropy::RectIntegEnergy(...
   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];
   242      } else {
   243        if(!Ha_is_uniform) field_mult = Ha[i];
   244        k = 0.5*MU0*field_mult*Ms[i];
(lldb) frame variable i
(OC_INDEX) i = 40000
(lldb) frame variable Ms_inverse
(const Oxs_MeshValue<double> &) Ms_inverse = 0x0000000102b77928: {
  arr = 0x0000000101da4000
  size = 40000
[...]
(lldb) process kill
Process 36662 exited with status = 9 (0x00000009)

 

 

Figure 5.8: Sample lldb session, part 2: Bug details (lldb output edited for space) (description)
(lldb) breakpoint set --file uniaxialanisotropy.cc --line 239
Breakpoint 1: where = oxs‘Oxs_UniaxialAnisotropy::RectIntegEnergy(Oxs_Sim...
(lldb) process launch
Process 36718 launched: ’oommf/app/oxs/darwin/oxs’ (x86_64)
[...]
* thread #1, queue = ’com.apple.main-thread’, stop reason = breakpoint 1.1
   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];
(lldb) breakpoint list
Current breakpoints:
1: file = ’uniaxialanisotropy.cc’, line = 239, exact_match = 0, locations...
  1.1: where = oxs‘Oxs_UniaxialAnisotropy::RectIntegEnergy(Oxs_SimState c...
(lldb) breakpoint modify -i 39999 1
(lldb) thread continue
* thread #1, queue = ’com.apple.main-thread’, stop reason = breakpoint 1.1
-> 239      if(aniscoeftype == K1_TYPE) {
(lldb) p i
(OC_INDEX) $0 = 39991
(lldb) breakpoint modify -c i>=40000
(lldb) c
* thread #1, queue = ’com.apple.main-thread’, stop reason = breakpoint 1.1
-> 239      if(aniscoeftype == K1_TYPE) {
(lldb) thread step-over
* thread #1, queue = ’com.apple.main-thread’, stop reason = step over
-> 240        if(!K1_is_uniform) k = K1[i];
(lldb) n
* thread #1, queue = ’com.apple.main-thread’, stop reason = step over
-> 241        field_mult = (2.0/MU0)*k*Ms_inverse[i];
(lldb) thread step-in
* thread #1, queue = ’com.apple.main-thread’, stop reason = step in
   317  const T& Oxs_MeshValue<T>::operator[](OC_INDEX index) const
   318  {
-> 319    assert(0<=index && index<size);
(lldb) print (void) printf("%d,%d\n", index, size)
40000,40000
(lldb) quit