As I mentioned I am trying to recover the line of a crash and also the function in wich it occurs.
I need to metion that I have tried the next code in AppDelegate and I get the stack not symbolicated and the class and also the error throwed:
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
void uncaughtExceptionHandler(NSException *exception) {
NSLog(@"Exception description - %@",[exception description]);
NSLog(@"Exception name - %@", [exception name]);
NSLog(@"Reason - %@", [exception reason]);
NSLog(@"\n\n - %@", [exception callStackSymbols]);
NSLog(@"\n\n - %@", [exception callStackReturnAddresses]);
}
But by using these I don't get the line of the crash, as I intend to save it in CoreData.
Also I am not interested in xcode aproaches as: "Add Exception Breakpoint" or other aproaces as: XCode > Window > Devices > view crash logs on a device, Test Flight aproaches or implementing other frameworks in the app as Crashlytics.
I mention these because I am very interested in the way it can be done by code.
Also am able to get dsym of the app archive it when an app archive is made and upload it to a server using a RunScript written using Bash. So I can use the dsym if it is needed to achive the crash line.
Also I know that the next aproach can be used to obtain the current code line: LINE and _FUNCTION__ to get the function name.
Also if you can provide code examples from open source PLCrashReporter on how they do it I will much apreciate.
Than you all in advance! :)
There are basically two types of crashes:
- Uncaught exceptions, which can be catched with code similar to yours
- Signal based crashes, which can be catched with signal handlers (or Mach Exception handlers, but that won't catch all Signals)
Then catching any of these crashes, you need to get the stack trace (of all threads). [NSException callStackSymbols]
will give you some symbols (only for an exception crash), for lots of OS symbols it will only show redacted
, for your app it will provide some symbols if you don't strip them from your binary. It is recommended to strip the symbols from the binary to get the file size down (a lot), and these symbols would also never provide the filenames and line numbers anyway.
So instead you need to get the following information from the stack frames: binary, binary UUID, cpu architecture and memory address. [NSException callStackReturnAddresses]
will give you the memory addresses, but again only for an exception based crash. In addition it doesn't provide the binary image corresponding to a memory address.
So you need to get the binary images list with the range of addresses in memory each binary image covers, and also a way to get the memory addresses of stack frames for threads also for non exception based crashes. If want to learn how that is that, you basically can take a look at ALL of PLCrashReporters code, since that is the purpose of the open source project and it is not the scope of StackOverflow to explain such complex scenarios. Read the code, the documentation and learn :) To give you the short gist: don't do it yourself, simply use PLCrashReporter.
Now to get the symbols including filenames and line numbers, you need to symbolicate the crash reports by using the OS symbols for the corresponding OS version and the corresponding CPU architecture from the device where the crash report happened. Also you need the symbols (dSYM) packages from the exact binary (and frameworks) that triggered the crash report from your app. Each binary image has a unique UUID and the symbol file your are using to get the symbols need to have the same UUID for the same CPU architecture.
Now you need to run the tool atos
to get the symbols for a specific memory address from a specific symbol file. The following stack overflow answer shows how to do that: https://stackoverflow.com/a/13576028/474794
As an alternative, you can use the symbolicatecrash.pl
script which comes with Xcode and takes a Apple standard formatted crash report (PLCrashReporter has a conversion tool to create such reports from its more compact reports).
You can use __PRETTY_FUNCTION__
in your logs, that will give you the line, class and name of function.
NSLog(@"%@", __PRETTY_FUNCTION__);
You can fill out the rest of the log with any other information you like.