C++: How to debug 'bus error' using lldb? - c++11

I'm new to lldb debugging. Recently, I compiled my code and tried to test it. After compilation when I run it, I get 'Bus Error'. So, I thought to use lldb debugger to find out the problem. The terminal gives me output like this:
$ lldb ./testLSTMForwardPass
(lldb) target create "./testLSTMForwardPass"
Current executable set to './testLSTMForwardPass' (x86_64).
(lldb) run
Process 96512 launched: './testLSTMForwardPass' (x86_64)
Testing LSTM Forward pass:
Process 96512 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x102742ba8)
frame #0: 0x0000000102742ba8
-> 0x102742ba8: addb %al, (%rax)
0x102742baa: addb %al, (%rax)
0x102742bac: addb %al, (%rax)
0x102742bae: addb %al, (%rax)
Target 0: (testLSTMForwardPass) stopped.
(lldb) bt all
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x102742ba8)
* frame #0: 0x0000000102742ba8
frame #1: 0x00000001015a1768 libMatrix.so`TMatrixT<double>::operator=(this=0x00007ffeefbfdd60, source=0x0000000102742b60) at TMatrixT.cxx:1739 [opt]
frame #2: 0x00000001015a16e8 libMatrix.so`TMatrixT<double>::TMatrixT(this=0x00007ffeefbfdd60, another=0x0000000102742b60) at TMatrixT.cxx:87 [opt]
frame #3: 0x0000000100006cf0 testLSTMForwardPass`double testForwardPass<TMVA::DNN::TReference<double> >(timeSteps=<unavailable>, batchSize=<unavailable>, stateSize=<unavailable>, inputSize=<unavailable>) at TestLSTMForwardPass.h:98 [opt]
frame #4: 0x000000010000695a testLSTMForwardPass`main at TestLSTMForwardPass.cxx:28 [opt]
frame #5: 0x00007fff65722145 libdyld.dylib`start + 1
frame #6: 0x00007fff65722145 libdyld.dylib`start + 1
I'm not able to understand what this output means. It would be great if anyone can help me to understand it properly. :)

Related

How to display callstack line numbers when my program is broken in Rust?

I use RUST_BACKTRACE=full ./my-program to run my compiled program.
However, I get a message like below which has only the function address without line numbers.
thread 'main' panicked at 'index out of bounds: the len is 6 but the index is 6', src/libcore/slice/mod.rs:734
stack backtrace:
0: 0x100a26463 - std::sys::imp::backtrace::tracing::imp::unwind_backtrace::hbdeac7eba2f064c6
1: 0x100a2786d - std::panicking::default_hook::{{closure}}::h9e0a6ca9bb64b479
2: 0x100a27434 - std::panicking::default_hook::h9043ae80af471c9f
3: 0x100a29f17 - std::panicking::rust_panic_with_hook::h05996066754c6be9
4: 0x100a29e04 - std::panicking::begin_panic::h9fecf34da42eb910
5: 0x100a29d22 - std::panicking::begin_panic_fmt::he5aad713258a67c3
6: 0x100a29c87 - rust_begin_unwind
7: 0x100a4a5f0 - core::panicking::panic_fmt::he26d734b771c5b2c
8: 0x100a4a568 - core::panicking::panic_bounds_check::h19dd3f615b4fea05
9: 0x100a1fc76 - <usize as core::slice::SliceIndex<[T]>>::index::h1f41340feec36937
10: 0x100a1f744 - core::slice::<impl core::ops::Index<I> for [T]>::index::h3246d2321fb7f789
11: 0x100a205b6 - sort::merge::h697218a53d5049aa
12: 0x100a20227 - sort::merge_sort::h10fe012581f48b43
13: 0x100a201e5 - sort::merge_sort::h10fe012581f48b43
14: 0x100a201e5 - sort::merge_sort::h10fe012581f48b43
15: 0x100a20159 - sort::merge_sort_pub::hb18b616b61510f3b
16: 0x100a20e24 - sort::main::hffac78b51f3ea2c3
17: 0x100a29c45 - std::panicking::try::do_call::h24a2756282b9a31c
18: 0x100a2ba2a - __rust_maybe_catch_panic
19: 0x100a2a1d0 - std::rt::lang_start::hd19f94db0c6a490e
20: 0x100a20fc9 - main
Is there any method to add the line numbers at the break spot?
This problem is a cross-platform issue and is tracked as Rust issue 24346. My workspace is macOS 10.12.4:
>rustc -vV
rustc 1.18.0-nightly (2564711e8 2017-04-04)
binary: rustc
commit-hash: 2564711e803f62e04bebf10408cc1c11297c0caf
commit-date: 2017-04-04
host: x86_64-apple-darwin
release: 1.18.0-nightly
LLVM version: 3.9
The workaround is to use a debugger to get the callstack information.
I have a hellobugs.rs file only present several lines of buggy code. At line 3, I cause a panic due to accessing the vector out of bounds:
fn main() { // 1
let v = vec![1, 2, 3]; // 2
println!("{}", v[4]); // 3
} // 4
Compile this with rustc hellobugs.rs -g -o hellobugs Don't forget the -g argument.
Running with RUST_BACKTRACE=full ./hellobugs will get backtraces but without line numbers on my macOS. As the issue says, we can use rust-lldb hellobugs to debug it and get detailed backtraces. Of course, using lldb is okay as well:
>rust-lldb hellobugs
...lots of rust-lldb message...
(lldb) breakpoint set -b rust_begin_unwind
Breakpoint 1: where = hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468, address = 0x000000010000a5b4
(lldb) r
Process 41626 launched: '/Users/xxx/bin/hellobugs' (x86_64)
hellobugs was compiled with optimization - stepping may behave oddly; variables may not be available.
Process 41626 stopped
* thread #1: tid = 0x6c3e39, 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
frame #0: 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468 [opt]
(lldb) bt
* thread #1: tid = 0x6c3e39, 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1
* frame #0: 0x000000010000a5b4 hellobugs`std::panicking::rust_begin_panic + 4 at panicking.rs:468 [opt]
frame #1: 0x000000010002af51 hellobugs`core::panicking::panic_fmt + 129 at panicking.rs:69 [opt]
frame #2: 0x000000010002aec9 hellobugs`core::panicking::panic_bounds_check + 105 at panicking.rs:56 [opt]
frame #3: 0x0000000100001726 hellobugs`collections::vec::{{impl}}::index<i32>(self=0x00007fff5fbff720, index=4) + 118 at vec.rs:1426
frame #4: 0x0000000100001826 hellobugs`hellobugs::main + 182 at hellobugs.rs:3
frame #5: 0x000000010000a5a6 hellobugs`std::panicking::try::do_call<fn(),()> [inlined] core::ops::FnOnce::call_once<fn(),()> + 6 at ops.rs:2606 [opt]
frame #6: 0x000000010000a5a4 hellobugs`std::panicking::try::do_call<fn(),()> + 4 at panicking.rs:454 [opt]
frame #7: 0x000000010000c38b hellobugs`panic_unwind::__rust_maybe_catch_panic + 27 at lib.rs:98 [opt]
frame #8: 0x000000010000ab31 hellobugs`std::rt::lang_start [inlined] std::panicking::try<(),fn()> + 44 at panicking.rs:433 [opt]
frame #9: 0x000000010000ab05 hellobugs`std::rt::lang_start [inlined] std::panic::catch_unwind<fn(),()> at panic.rs:361 [opt]
frame #10: 0x000000010000ab05 hellobugs`std::rt::lang_start + 325 at rt.rs:57 [opt]
frame #11: 0x000000010000192a hellobugs`main + 42
frame #12: 0x00007fffdfc5f235 libdyld.dylib`start + 1
(lldb)
My results are as above. You can see at frame #4 there comes the buggy result of at hellobug.rs:3. This informs us the 3rd line has a bug. It is a little bother to use lldb and trace, but it's accurate!

NSTextView inspector bar crash on Sierra 10.12

Is anyone else seeing a crash calling setUsesInspectorBar on NSTextView for Sierra (release build)? This code worked just fine on 10.11.5 but crashes in AppKit on Sierra. I thought it was a beta version bug I'm still getting it on the full release.
Here's the back trace from lldb.
(lldb) bt
* thread #1: tid = 0x76deb, 0x9ecfe013 libobjc.A.dylib`objc_msgSend + 19, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0xa007cc0f)
* frame #0: 0x9ecfe013 libobjc.A.dylib`objc_msgSend + 19
frame #1: 0x95c5f861 Foundation`releasingRelinquish + 29
frame #2: 0x95c22636 Foundation`-[NSConcreteMapTable removeObjectForKey:] + 127
frame #3: 0x92fbec6e AppKit`-[NSStackViewContainer removeView:] + 102
frame #4: 0x92798554 AppKit`-[NSStackView _insertView:atIndex:inGravity:animated:] + 212
frame #5: 0x9279847b AppKit`-[NSStackView insertView:atIndex:inGravity:] + 40
frame #6: 0x9279839b AppKit`-[NSStackView addView:inGravity:] + 78
frame #7: 0x92f5ec2c AppKit`-[__NSInspectorBarView addItem:] + 71
frame #8: 0x929281c1 AppKit`__23-[NSInspectorBar _tile]_block_invoke + 303
frame #9: 0x94566871 CoreFoundation`__53-[__NSArrayM enumerateObjectsWithOptions:usingBlock:]_block_invoke + 81
frame #10: 0x94566717 CoreFoundation`-[__NSArrayM enumerateObjectsWithOptions:usingBlock:] + 167
frame #11: 0x945665f5 CoreFoundation`-[NSArray enumerateObjectsUsingBlock:] + 53
frame #12: 0x92925e95 AppKit`-[NSInspectorBar _tile] + 484
frame #13: 0x92924e3d AppKit`-[NSInspectorBar _update] + 224
frame #14: 0x92630b28 AppKit`-[NSTextView updateInspectorBar] + 71
frame #15: 0x9263159b AppKit`-[NSTextView updateRuler] + 2622
frame #16: 0x9292440f AppKit`-[NSTextView(NSSharing) setUsesInspectorBar:] + 350
frame #17: 0x0014eef4 DockShelf`"-[TTextEditorWindowController awakeFromNib]"(self=0x0073ecc0, _cmd="awakeFromNib") + 116 at UTextEditor_2.pas:124
This is a bug in AppKit with 32-bit apps. Unfortunately, not workaround-able (without removing inspector bar support) and will require a fix in AppKit.
This should be fixed with 10.12.2
Try to remove NSTextView component in IB and then insert it back again from component's palette. It is possible that your old XIB file contains some keywords which are not recognised/compiled properly into NIB file and Sierra cannot process file.

Debugging neovim, buffer overflow detected by OS X 10.9 libc, in need of a better way to debug it

First of all a bit of context: I'm trying to debug an issue that's happening with neovim, I'm not sure if this also happens with plain vim, but it's not all that relevant.
Even though the reporter uses linux and I use OSX 10.9, I've been able to get "similar" behaviour by using specific compilers + flags:
When I use either gcc 4.8.2 or gcc 4.9 (dev) combined with even a little bit of optimization, fortification and stack smashing protection, neovim crashes on startup.
$ edit CMakeLists.txt
$ ... -Wall -O1 -g -g3 -ggdb -mtune=generic -pipe -fstack-protector --param=ssp-buffer-size=4 -D_FORTIFY_SOURCE=2 -Wextra -pedantic -Wno-unused-parameter -std=gnu99 ...
$ make clean && make cmake CMAKE_EXTRA_FLAGS="-DCMAKE_C_COMPILER=/usr/local/bin/gcc-4.8" && make
I've been trying to debug it with lldb (gdb doesn't seem to give my any symbols, even after codesigning). I've gotten as far as this:
compiled with gcc 4.9:
➜ neovim git:(fortify-and-stack-protector) ✗ lldb ./build/bin/nvim
Current executable set to './build/bin/nvim' (x86_64).
(lldb) run src/eval.c
Process 1295 launched: './build/bin/nvim' (x86_64)
Process 1295 stopped
* thread #1: tid = 0x242b4f, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff93f34866: jae 0x7fff93f34870 ; __pthread_kill + 20
0x7fff93f34868: movq %rax, %rdi
0x7fff93f3486b: jmpq 0x7fff93f31175 ; cerror_nocancel
0x7fff93f34870: ret
(lldb) bt
* thread #1: tid = 0x242b4f, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff91b6435c libsystem_pthread.dylib`pthread_kill + 92
frame #2: 0x00007fff8ce68b1a libsystem_c.dylib`abort + 125
frame #3: 0x00007fff8ce68c91 libsystem_c.dylib`abort_report_np + 181
frame #4: 0x00007fff8ce8c860 libsystem_c.dylib`__chk_fail + 48
frame #5: 0x00007fff8ce8c830 libsystem_c.dylib`__chk_fail_overflow + 16
frame #6: 0x00007fff8ce8ca7f libsystem_c.dylib`__strcpy_chk + 83
frame #7: 0x000000010002e1a6 nvim`call_user_func [inlined] add_nr_var(nr=1, name=<unavailable>, v=<unavailable>, dp=<unavailable>) + 42 at eval.c:18744
frame #8: 0x000000010002e17c nvim`call_user_func(fp=0x000000010030bd30, argcount=0, argvars=0x00007fff5fbfed80, rettv=0x00007fff5fbfef50, firstline=1, lastline=1, selfdict=0x0000000000000000) + 425 at eval.c:18455
frame #9: 0x000000010002ef33 nvim`call_func(funcname=<unavailable>, len=<unavailable>, rettv=0x00007fff5fbfef50, argcount=0, argvars=0x00007fff5fbfed80, firstline=1, lastline=1, doesrange=0x00007fff5fbfef44, evaluate=1, selfdict=0x0000000000000000) + 717 at eval.c:7363
frame #10: 0x0000000100032d1a nvim`get_func_tv(name=0x000000010030be20, len=9, rettv=0x00007fff5fbfef50, arg=0x00007fff5fbfef48, firstline=1, lastline=1, doesrange=0x00007fff5fbfef44, evaluate=1, selfdict=0x0000000000000000) + 340 at eval.c:7222
frame #11: 0x000000010003673e nvim`ex_call(eap=0x00007fff5fbff190) + 475 at eval.c:3086
frame #12: 0x000000010005634b nvim`do_cmdline(cmdline=<unavailable>, fgetline=0x00000001000494e3, cookie=0x00007fff5fbff790, flags=7) + 13602 at ex_docmd.c:2103
frame #13: 0x0000000100049d52 nvim`do_source(fname=0x000000010017bb3b, check_other=<unavailable>, is_vimrc=<unavailable>) + 1615 at ex_cmds2.c:2695
frame #14: 0x00000001001702c3 nvim`main + 251 at main.c:2009
frame #15: 0x00000001001701c8 nvim`main(argc=<unavailable>, argv=<unavailable>) + 5152 at main.c:1919
frame #16: 0x00007fff8b32d5fd libdyld.dylib`start + 1
(lldb) frame variable
(lldb) frame info
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
(lldb) frame select 7
frame #7: 0x000000010002e1a6 nvim`call_user_func [inlined] add_nr_var(nr=1, name=<unavailable>, v=<unavailable>, dp=<unavailable>) + 42 at eval.c:18744
18741 */
18742 static void add_nr_var(dict_T *dp, dictitem_T *v, char *name, varnumber_T nr)
18743 {
-> 18744 STRCPY(v->di_key, name);
18745 v->di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
18746 hash_add(&dp->dv_hashtab, DI2HIKEY(v));
18747 v->di_tv.v_type = VAR_NUMBER;
compiled with gcc 4.8.2:
➜ neovim git:(fortify-and-stack-protector) ✗ lldb ./build/bin/nvim
Current executable set to './build/bin/nvim' (x86_64).
(lldb) rune
error: 'rune' is not a valid command.
(lldb) run
Process 3242 launched: './build/bin/nvim' (x86_64)
Process 3242 stopped
* thread #1: tid = 0x2454cb, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
libsystem_kernel.dylib`__pthread_kill + 10:
-> 0x7fff93f34866: jae 0x7fff93f34870 ; __pthread_kill + 20
0x7fff93f34868: movq %rax, %rdi
0x7fff93f3486b: jmpq 0x7fff93f31175 ; cerror_nocancel
0x7fff93f34870: ret
(lldb) bt
* thread #1: tid = 0x2454cb, 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10, queue = 'com.apple.main-thread, stop reason = signal SIGABRT
frame #0: 0x00007fff93f34866 libsystem_kernel.dylib`__pthread_kill + 10
frame #1: 0x00007fff91b6435c libsystem_pthread.dylib`pthread_kill + 92
frame #2: 0x00007fff8ce68b1a libsystem_c.dylib`abort + 125
frame #3: 0x00007fff8ce68c91 libsystem_c.dylib`abort_report_np + 181
frame #4: 0x00007fff8ce8c860 libsystem_c.dylib`__chk_fail + 48
frame #5: 0x00007fff8ce8c830 libsystem_c.dylib`__chk_fail_overflow + 16
frame #6: 0x00007fff8ce8ca7f libsystem_c.dylib`__strcpy_chk + 83
frame #7: 0x000000010002a969 nvim`eval_init + 129 at eval.c:868
frame #8: 0x0000000100089ffd nvim`main(argc=1, argv=0x00007fff5fbffa58) + 140 at main.c:175
frame #9: 0x00007fff8b32d5fd libdyld.dylib`start + 1
frame #10: 0x00007fff8b32d5fd libdyld.dylib`start + 1
(lldb) frame select 7
frame #7: 0x000000010002a969 nvim`eval_init + 129 at eval.c:868
865
866 for (i = 0; i < VV_LEN; ++i) {
867 p = &vimvars[i];
-> 868 STRCPY(p->vv_di.di_key, p->vv_name);
869 if (p->vv_flags & VV_RO)
870 p->vv_di.di_flags = DI_FLAGS_RO | DI_FLAGS_FIX;
871 else if (p->vv_flags & VV_RO_SBX)
For this issue to appear, there needs to be some optimization, however this means that the compiler will inline things and throw away arguments, which is annoying and doesn't allow me to see the most important things at a glance. Would there be a combination of flags I could try that would keep the problem but allow better debuggability?
Is this likely a compiler bug? Clang seems to avoid it somehow, and GCC too when I turn off optimization.
gcc 4.8.2 and gcc 4.9 give a similar error (both times at a STRCPY) but in different locations, this worries me even more.
Where is the code for __chk_fail_overflow and __chk_overlap? They get called in strcpy_chk which I assume is the replacement of strcpy that gets inserted when compiling with -D_FORTIFY_SOURCE=2. I haven't been able to grep for it. I've grepped in this repo: https://github.com/aosm/Libc which appears to be the OSX 10.9 libc as I've tried to verify with apple's own opensource site.
How does the compiler decide what the 3rd argument to strcpy_chk is?! The original invocation to STRCPY doesn't include any size information:
.
STRCPY(v->di_key, name);
// I think gcc/clang replace this with:
__strcpy_chk(v->di_key, name, SOME_MAGIC_SIZE);
I hope some of the guru's on stack overflow could give me some tips/hints on what I should do next!
EDIT: I've been able to compile with -Og and gcc 4.8.2 and still provoke the error, hopefully this will give some more info.
So, I couldn't stop myself from digging further and finally got the idea of looking at the stack + registers when entereing the dreaded __strcpy_chk, where I found:
(lldb) register read
General Purpose Registers:
rax = 0x0000000000000057
rbx = 0x00000001001d3900 vimvars
rcx = 0x6300f1e7a96add52
rdx = 0x0000000000000001 /* this is probably the size parameter */
rdi = 0x00000001001d3919 vimvars + 25
rsi = 0x000000010016730e "count"
So gcc had deduced that the size of the dst parameter was 1, and is passing that to __strcpy_chk. So, because of the -D_FORTIFY_SOURCE=2, gcc replaces calls of well-known functions with their safe variants when it can deduce the size. Such is the case here as we'll see: the dst parameter is the vv_di.di_key field of this struct:
static struct vimvar {
char *vv_name; /* name of variable, without v: */
dictitem_T vv_di; /* value and name for key */
char vv_filler[16]; /* space for LONGEST name below!!! */
char vv_flags; /* VV_COMPAT, VV_RO, VV_RO_SBX */
}
struct dictitem_S {
typval_T di_tv; /* type and value of the variable */
char_u di_flags; /* flags (only used for variable) */
char_u di_key[1]; /* key (actually longer!) */
}
Which has size 1. Gcc of course doesn't realize that this was somehow intentional: the vv_filler flag is meant to store the actual string. Which is why the comment says actually longer. vv_filler follows immediately on di_key in the struct.
I can't really fault the compiler for this, it makes sense. Someone at the neovim project is busy rebuilding the interpreter to be a translator from VimL to lua. A "stupid" fix at the moment is to either disable source fortifying or lower it a level to -D_FORTIFY_SOURCE=1, which should stop gcc from making these assumptions. Ideally though, we'd be able to fix this while keeping -D_FORTIFY_SOURCE=2 and not regressing in performance (vimvar is of course an oft-used struct).
I have some extra questions though. Is what the vim codebase does here legal? There were some discussions on the neovim issue tracker where some commenters suggested that relying on this was entirely undefined. One argument that I found interesting was that there could be space between the end of struct dictitem_S and vv_filler (padding). The commenter argued that it was illegal (UB) to use this space. Reading the relevant C99 documents doesn't provide immediate clarity on this specific case. The struct hack is allowed, but we were not sure if it is allowed for nested structs. i.e.: the struct hack appears at the end of dictitem_S, but definitely not at the end of its containing struct (vimvar).

Symbolic exception breakpoint on -[NSRangeException raise]

Adding a symbolic breakpoint in Xcode gives you an example template of -[NSException raise]. I want to do the same thing but specifically on -[NSRangeException raise]. The reason being that I want to breakpoint only on specific array bounds exceptions, for example:
*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 31 beyond bounds [0 .. 30]'
Yes, I know that I can add a catch all exception breakpoint. However, I do not want to do that as I do not want to breakpoint on the many exceptions generated throughout using the app.
I've tried quite a few things based on other posts related to NSException. However, I have not found anything that works successfully as yet.
For example I tried:
This journal entry was also of interest albeit inconclusive:
Dealing with NSArray "out of bounds"
So, basically, the question is, in Xcode, how to breakpoint specifically and only on a range exception?
NSRangeException isn't a class:
grep NSRangeException /System/Library/Frameworks/Foundation.framework/Headers/NSException.h
FOUNDATION_EXPORT NSString * const NSRangeException;
Turns out, range exceptions are just NSExceptions whose name is NSRangeException, i.e.:
(lldb) b s -n objc_exception_throw
Breakpoint 2: where = libobjc.A.dylib`objc_exception_throw, address = 0x00007fff8e3c2e4a
(lldb) c
Process 58216 resuming
Process 58216 stopped
* thread #1: tid = 0x1d7f4b, function: objc_exception_throw , stop reason = breakpoint 2.1
frame #0: 0x00007fff8e3c2e4a libobjc.A.dylib`objc_exception_throw
libobjc.A.dylib`objc_exception_throw:
-> 0x7fff8e3c2e4a: pushq %rbp
0x7fff8e3c2e4b: movq %rsp, %rbp
0x7fff8e3c2e4e: pushq %r15
0x7fff8e3c2e50: pushq %r14
(lldb) bt
* thread #1: tid = 0x1d7f4b, function: objc_exception_throw , stop reason = breakpoint 2.1
frame #0: 0x00007fff8e3c2e4a libobjc.A.dylib`objc_exception_throw
frame #1: 0x00007fff841ca1df CoreFoundation`-[__NSArrayI objectAtIndex:]
frame #2: 0x0000000100000eb9 range-exception`-[Foo throwIt] at range-exception.m:14
frame #3: 0x0000000100000f27 range-exception`main at range-exception.m:22
frame #4: 0x00007fff8468d5fd libdyld.dylib`start
frame #5: 0x00007fff8468d5fd libdyld.dylib`start
(lldb) expr (NSString *) [((NSException *) $arg1) name]
(NSString *) $0 = 0x00007fff74177990 #"NSRangeException"
So you could set a breakpoint on objc_exception_throw, and write a breakpoint condition comparing the name to NSRangeException. Something like:
[(NSString *) [((NSException *) $arg1) name] isEqual: (NSString *) NSRangeException]
should do the trick.
To make a breakpoint for NSRangeException, use an Exception breakpoint. It's one of the options when you click the "+" in the breakpoint navigator. Found this info from this answer: https://stackoverflow.com/a/9718552/591487

How to track down the line that's causing a runtime error?

My app is crashing with this error message:
'NSInvalidArgumentException', reason: '-[__NSCFDictionary setObject:forKey:]: attempt to insert nil value (key: 0)'
and I am trying to find where this is occuring in my code. I have set NSZombiesEnabled in the environment variables, however it's pretty hard to figure out the location. Any idea on how to debug?
I typed in bt and here's what I see:
frame #0: 0x30d1832c libsystem_kernel.dylib`__pthread_kill + 8
frame #1: 0x3597d20e libsystem_c.dylib`pthread_kill + 54
frame #2: 0x3597629e libsystem_c.dylib`abort + 94
frame #3: 0x35055f6a libc++abi.dylib`abort_message + 46
frame #4: 0x3505334c libc++abi.dylib`_ZL17default_terminatev + 24
frame #5: 0x36c38356 libobjc.A.dylib`_objc_terminate + 146
frame #6: 0x350533c4 libc++abi.dylib`_ZL19safe_handler_callerPFvvE + 76
frame #7: 0x35053450 libc++abi.dylib`std::terminate() + 20
frame #8: 0x35054824 libc++abi.dylib`__cxa_rethrow + 88
frame #9: 0x36c382a8 libobjc.A.dylib`objc_exception_rethrow + 12
frame #10: 0x3428d50c CoreFoundation`CFRunLoopRunSpecific + 404
frame #11: 0x3428d36c CoreFoundation`CFRunLoopRunInMode + 104
frame #12: 0x3826f438 GraphicsServices`GSEventRunModal + 136
frame #13: 0x36d27cd4 UIKit`UIApplicationMain + 1080
frame #14: 0x00051cdc AppName`main + 80 at main.m:16
Add exceptions as a breakpoint. Assuming Xcode 4+...
At the top of the navigator frame (where you view files and such), you will see a little icon that looks like a sideways arrow.
That will show the breakpoint navigator. At the bottom of that view, click the + to add a breakpoint.
Click on "Add exception breakpoint..."
The default option is probably fine... you want to break on throw of all exceptions.
Now, when you run, you will get a breakpoint anywhere your app throws an exception.
Is the error happening in your testing? Are you seeing it from crash logs from iTunes Connect?
If you are able to reproduce it locally, run the scenario to duplicate the error and when the debugger becomes active, type "bt" at the (gdb) prompt in the Console for a stacktrace with a line number.
Try to add this part of code in your AppDelegate :
void uncaughtExceptionHandler(NSException *exception);
void uncaughtExceptionHandler(NSException *exception) {
NSLog(#"CRASH: %#", exception);
NSLog(#"Stack Trace: %#", [exception callStackSymbols]);
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
// your previous code here
return YES;
}
Next time your error occurs, you should have some additional infos on the crash.

Resources