When I get a crash report, the offending part of my code will sometimes look like this, instead of showing me the actual line number, even though the crash report is symboli
[note this ONLY works if you save Archives in XCode of all the builds you released]
Information you need to collect first:
-[ViewController myMethod:])armv7 or arm64. If you don't know, try both.Ok here are the steps:
cd to that directory shown in Finderexecute the following in the shell:
lldb -arch ARCH Products/Applications/APPNAME.app/APPNAME
inside lldb do the following:
(lldb) add-dsym dSYMs/APPNAME.app.dSYM/Contents/Resources/DWARF/APPNAME
(lldb) disassemble --name CRASHING_FUNCTION_NAME
you now see a rich disassembly with symbols, and lo and behold, each line shows the same decimal offset as the original useless Apple backtrace (in the OPs example, the useless offset was 47), as in:
APPNAME[0xf4a7c] <+47>: ldr r0, [r0, r1]
you might be able to figure out the corresponding source line just from this information, if the disassembly has enough symbols to help you figure out where you are.
if not, there is another great trick. Pass the address of the line that crashed:
(lldb) image lookup -v --address 0xf4a7c
Now lldb shows you a rich collection of information---much richer than what is shown by Apple stack backtraces even when they do contain line numbers, and much richer than lldb source list---about all the source lines that contributed to the assembler instruction at that address. Pay close attention to both the Summary and LineEntry sections. Example:
Address: APPNAME[0x000f4a7c] (APPNAME.__TEXT.__text + 963740)
Summary: APPNAME`myclass::myfunc(bool, bool) + 904 [inlined] std::__1::deque >::operator[](unsigned long) + 22 at myfile.cpp:37945
APPNAME`myclass::myfunc(bool, bool) + 882 [inlined] myinlinefunc(int) + 14 at myfile.cpp:65498
APPNAME`myclass::myfunc(bool, bool) + 868 at myfile.cpp:65498
Module: file = "/Users/myuser/mydir/arch/Products/Applications/APPNAME.app/APPNAME", arch = "armv7"
CompileUnit: id = {0x000483a4}, file = "/Users/myuser/mydir/myfile.cpp", language = "objective-c++"
Function: id = {0x0045edde}, name = "myfunc", range = [0x000f46f4-0x000f572a)
FuncType: id = {0x0045edde}, decl = myfile.cpp:65291, compiler_type = "void (_Bool, _Bool)"
Blocks: id = {0x0045edde}, range = [0x000f46f4-0x000f572a)
id = {0x0045f7d8}, ranges = [0x000f4936-0x000f51c0)[0x000f544c-0x000f5566)[0x000f5570-0x000f5698)
id = {0x0046044c}, ranges = [0x000f49c6-0x000f49ce)[0x000f49d6-0x000f49d8)[0x000f4a2e-0x000f4a38)[0x000f4a58-0x000f4a82), name = "myinlinefunc", decl = myfile.cpp:37938, mangled = _Z11myinlinefunci, demangled = myinlinefunc(int)
id = {0x00460460}, ranges = [0x000f4a58-0x000f4a64)[0x000f4a66-0x000f4a82), name = "operator[]", decl = deque:1675, mangled = _ZNSt3__15dequeI12mystructNS_9allocatorIS1_EEEixEm, demangled = std::__1::deque >::operator[](unsigned long)
LineEntry: [0x000f4a7c-0x000f4a82): /Applications/Xcode7.3.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../include/c++/v1/deque:1678:14
Symbol: id = {0x00000805}, range = [0x000f46f4-0x000f572a), name="myclass::myfunc(bool, bool)", mangled="_ZN7myclass7myfuncEbb"
Variable: id = {0x00460459}, name = "myvar1", type = "int", location = , decl = myfile.cpp:37938
Variable: id = {0x0045f7dd}, name = "myvar2", type = "bool", location = , decl = myfile.cpp:65583
Variable: id = {0x0045edf2}, name = "this", type = "myclass *", location = [sp+56], decl =
Variable: id = {0x0045ee01}, name = "myvar3", type = "bool", location = , decl = myfile.cpp:65291
Variable: id = {0x0045ee0e}, name = "myvar4", type = "bool", location = , decl = myfile.cpp:65292
In this example under Summary, we can see that the line that crashed was actually a combination of code from myclass::myfunc(), myinlinefunc() and std::deque::operator[]. This kind of mashing together is very common for optimized code. This is often enough information to find the offending source line of your code. Under LineEntry we see the line number for the most-nested code contributing to that assembler line, which in this case is in the STL std::deque code, but in other cases might be the exact line number you want in your code.
Now the only remaining question is: why on earth doesn't Apple just do this for us in the original backtrace? They clearly have all this information themselves! Why do they make us jump through such hoops? What are they hiding?