本篇文章主要针对 KSCrash 捕获到崩溃后的记录操作。看看 KSCrash 都记录些什么内容,怎样记录的。特别是对堆栈信息的处理,对每个线程实现堆栈回溯和尝试符号解析的处理方式。
本篇文章主要都是贴的 KSCrash 的源码。会尽量对代码做注释说明。
前文已经分析过了,kscm_handleException 函数调用了 g_onExceptionEvent,而 g_onExceptionEvent 函数就是保存的 onCrash 函数。我们再来看一下 onCrash 的内容:
1 | static void onCrash(struct KSCrash_MonitorContext* monitorContext) |
其中调用了 kscrashreport_writeStandardReport 方法,这个方法里实现了对各种信息的记录操作,将所有信息写入到本地文件里。
1 | void kscrashreport_writeStandardReport(const KSCrash_MonitorContext* const monitorContext, const char* const path) |
接下来,我们一一查看上述调用的方法的具体内容,看看它们都具体做了什么工作。
1、写入方法:beginObject
beginObject 最终调用的即 addJSONData 函数:
1 | // 写入 name 及 "{" |
2、写入 report info:writeReportInfo
写入一些基础信息
1 | static void writeReportInfo(const KSCrashReportWriter* const writer, |
3、写入 binary images:writeBinaryImages
1 | static void writeBinaryImages(const KSCrashReportWriter* const writer, const char* const key) |
4、写入 process state:writeProcessState
1 | static void writeProcessState(const KSCrashReportWriter* const writer, |
5、写入 system info:writeSystemInfo
1 | static void writeSystemInfo(const KSCrashReportWriter* const writer, |
6、写入崩溃错误信息:writeError
1 | static void writeError(const KSCrashReportWriter* const writer, |
7、写入各线程堆栈信息:writeAllThreads
1 | static void writeAllThreads(const KSCrashReportWriter* const writer, |
writeBacktrace
我们来重点关注下 writeBacktrace 函数:
1 | static void writeBacktrace(const KSCrashReportWriter* const writer, |
1、其中 advanceCursor 函数用于遍历栈帧:
1 | static bool advanceCursor(KSStackCursor *cursor) |
2、其中 symbolicate 函数尝试对地址进行符号化:
1 | bool kssymbolicator_symbolicate(KSStackCursor *cursor) |
writeRegisters
1 | static void writeRegisters(const KSCrashReportWriter* const writer, |
writeStackContents & writeNotableAddresses
1 | static void writeStackContents(const KSCrashReportWriter* const writer, |
因篇幅原因,对上述 writeNotableRegisters 和 writeNotableStackContents 就不做过多详细的分析了。其中,他们都调用了 writeMemoryContents 关键方法:
1 | static void writeMemoryContents(const KSCrashReportWriter* const writer, |
以上方法判断了 OC 对象类型,String、URL、Date、Array、Number、Dictionary、Block 等类型,并对这些类型分别做了取值与写入操作。因篇幅原因就不再进行详细分析了。
小结
KSCrash 对崩溃后日志的记录,主要是系统信息、崩溃信息、堆栈信息等等。尤其是堆栈信息,将各线程挂起,一一记录堆栈,并且会对堆栈地址尝试符号化。
对 KSCrash 的源码笔记写了好久,本系列笔记也只是按代码执行顺序过了一遍,大概了解了 KSCrash 的工作内容和工作过程。后续有精力的话再对其实现原理与细节进行补充吧。