1# 分析CppCrash(进程崩溃) 2 3进程崩溃指C/C++运行时崩溃。FaultLogger模块提供进程崩溃故障检测、日志采集、日志存储、日志上报的能力,为开发者提供详细的维测日志以辅助故障定位。 4 5本文将分别介绍进程崩溃检测能力、崩溃日志获取和进程崩溃日志分析。在使用本指导分析日志前,需要开发者对C/C++程序堆栈信息有相关基础知识。 6 7## 进程崩溃检测能力 8 9进程崩溃基于Linux信号机制,目前主要支持对以下崩溃异常信号的处理: 10 11| 信号值 | 信号 | 解释 | 触发原因 | 12| -------- | -------- | -------- | -------- | 13| 4 | SIGILL | 非法指令。 | 进程执行了非法、格式错误、未知或特权指令。 | 14| 5 | SIGTRAP | 断点或陷阱异常。 | 异常或trap指令发生。 | 15| 6 | SIGABRT | 进程终止。 | 进程异常终止,通常为进程自身调用标准函数库的abort()函数。 | 16| 7 | SIGBUS | 非法内存访问。 | 进程访问了对齐或者不存在的物理地址。 | 17| 8 | SIGFPE | 浮点异常。 | 进程执行了错误的算术运算,如除数为0、浮点溢出、整数溢出等。 | 18| 11 | SIGSEGV | 无效内存访问。 | 进程访问了无效内存引用。 | 19| 16 | SIGSTKFLT | 栈错误。 | 处理器执行了错误的栈操作,如栈空时弹出、栈满时压入。 | 20| 31 | SIGSYS | 错误的系统调用。 | 系统调用时使用了错误或非法参数。 | 21 22## 崩溃日志获取 23 24进程崩溃日志是一种故障日志,与应用无响应日志、JS应用崩溃等都由FaultLogger模块进行管理,可通过如下三种方式获取: 25 26- 方式一:通过shell获取日志 27 28 1. 进程崩溃后,CppCrash文件会生成在“设备/data/log/faultlog/faultlogger/”路径下,故障日志文件名格式为“cppcrash-进程名-进程UID-秒级时间”,包含设备名、系统版本、进程崩溃调用栈等信息。 29 30  31 32 2. “设备/data/log/faultlog/temp/”路径下的故障日志,其文件名格式为“cppcrash-进程PID-系统毫秒级时间戳”,包含进程崩溃时栈内存、进程maps等信息。 33 34  35 36- 方式二:通过DevEco Studio获取日志 37 38 DevEco Studio会收集“设备/data/log/faultlog/faultlogger/”路径下的进程崩溃故障日志到FaultLog下,根据进程名和故障和时间分类显示。获取日志的方法参见:[DevEco Studio使用指南-FaultLog](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides-V2/ide-debug-hilog-0000001172459337-V2#section974519209435)。 39 40- 方式三:通过faultlogger接口获取 41 42 FaultLogger对外提供了面向应用的故障查询接口,可以查询应用自己的故障记录,以结构化的数据返回。接口的使用以及获取的故障信息规格详见[@ohos.faultLogger (故障日志获取)](../reference/apis-performance-analysis-kit/js-apis-faultLogger.md)。 43 44## 进程崩溃日志分析 45 46 47### 日志格式 48 49以下是一份DevEco Studio归档在FaultLog的进程崩溃日志的核心内容,与“设备/data/log/faultlog/faultlogger”下归档的日志内容相同。 50 51``` 52Generated by HiviewDFX@OpenHarmony 53================================================================== 54Device info:OpenHarmony 3.2 <- 设备信息 55Build info:OpenHarmony 4.0.5.5 <- 版本信息 56Fingerprint:5e6a663122524ea7c1772b0f16f23b50a2b5753c930ed681a721ac2e8c197645 <- 标识故障特征 57Module name:crasher_c <- 模块名 58Version:1.0.0 <- 版本号 59VersionCode:1000000 <- 版本代码 60PreInstalled:No <- 是否预置 61Foreground:Yes <- 崩溃时刻应用是否在前台 62Timestamp:2017-08-05 18:23:53.000 <- 故障发生时间戳 63Pid:1369 <- 进程号 64Uid:0 <- 用户ID 65Reason:Signal:SIGSEGV(SEGV_MAPERR)@00000000 <- 故障原因 66Fault thread Info: 67Tid:1369 Name:crasher <- 故障线程号,线程名 68#00 pc 00007be6 /data/crasher_c(SegmentFaultException+1)(1a75896316b332b9e7469de9d5a3e4e4) <- 调用栈 69#01 pc 000082c1 /data/crasher_c(ParseAndDoCrash+412)(1a75896316b332b9e7469de9d5a3e4e4) 70#02 pc 000083e1 /data/crasher_c(main+32)(1a75896316b332b9e7469de9d5a3e4e4) 71#03 pc 0006ef10 /system/lib/ld-musl-arm.so.1 72#04 pc 000038a0 /data/crasher_c(_start_c+84)(1a75896316b332b9e7469de9d5a3e4e4) 73#05 pc 00003844 /data/crasher_c(1a75896316b332b9e7469de9d5a3e4e4) 74... 75Registers: <- 故障现场寄存器 76r0:00000000 r1:008a262b r2:00000000 r3:00000000 77r4:ff9b3e39 r5:00000002 r6:008a93c1 r7:f7872788 78r8:f7777976 r9:f7872318 r10:f7872418 79fp:ff9b39a8 ip:f777deea sp:ff9b3968 lr:008a92c5 pc:008a8be6 80Other thread info: <- 其他线程信息 81Tid:1370, Name:crasher <- 线程号,线程名 82#00 pc 00000000001aa2e0 /system/lib/ld-musl-aarch64.so.1(sleep+52) <- 调用栈 83#01 pc 0000000000005188 /data/crasher_c(abea41f851573f032e3e73a1e17d209d) 84#02 pc 000000000019f234 /system/lib/ld-musl-aarch64.so.1 85#03 pc 000000000009f8ac /system/lib/ld-musl-aarch64.so.1 86... 87Memory near registers: <- 故障现场寄存器附近内存 88r1(/data/crasher_c): 89 008a2620 53697274 90 008a2624 45534749 91 ... 92 008a269c 20202020 93r4([stack]): 94 ff9b3e30 68736172 95 ff9b3e34 635f7265 96 ... 97 ff9b3eac 3d455a49 98r6(/data/crasher_c): 99 008a93b8 bf00bd80 100 008a93bc ffff96d7 101 ... 102 008a9434 bd802000 103r7(/system/lib/ld-musl-arm.so.1): 104 f7872780 00000000 105 f7872784 00000000 106 ... 107 f78727fc 00000000 108r8(/system/lib/ld-musl-arm.so.1): 109 f777796c 00646e65 110 f7777970 255f7325 111 ... 112 f77779e8 6d20726f 113r9(/system/lib/ld-musl-arm.so.1): 114 f7872310 00000001 115 f7872314 00000000 116 ... 117 f787238c 00000000 118r10(/system/lib/ld-musl-arm.so.1): 119 f7872410 00010000 120 f7872414 00000000 121 ... 122 f787248c 00000000 123fp([stack]): 124 ff9b39a0 00000001 125 ff9b39a4 f7872418 126 ... 127 ff9b3a1c ff9b3fd8 128r12(/system/lib/ld-musl-arm.so.1): 129 f777dee0 203e4425 130 f777dee4 25207461 131 ... 132 f777df5c 75747372 133sp([stack]): 134 ff9b3960 ff9b39a8 135 ff9b3964 008a91c1 136 ... 137 ff9b39dc 00000000 138lr(/data/crasher_c): 139 008a92bc e01cfc1b 140 008a92c0 fc90f7ff 141 ... 142 008a9338 ffff9609 143pc(/data/crasher_c): 144 008a8bdc ffff9f07 145 008a8be0 ffff9eb7 146 ... 147 008a8c58 edeaf000 148FaultStack: <- 崩溃线程栈的地址空间 149 ... 150 ff9b3964 008a91c1 151sp0:ff9b3968 0a9b39d4 <-#00栈顶 152 ff9b396c f5275648 153 ... 154 ff9b4168 ffffffff 155 156Maps: <- 故障时进程maps 1578a1000-8a4000 r--p 00000000 /data/crasher_c 1588a4000-8aa000 r-xp 00002000 /data/crasher_c 1598aa000-8ab000 r--p 00007000 /data/crasher_c 1608ab000-8ac000 rw-p 00007000 /data/crasher_c 161ada000-adb000 ---p 00000000 [heap] 162adb000-adc000 rw-p 00000000 [heap] 163... 164f7759000-f77af000 r--p 00000000 /system/lib/ld-musl-arm.so.1 165f77af000-f786f000 r-xp 00055000 /system/lib/ld-musl-arm.so.1 166f786f000-f7871000 r--p 00114000 /system/lib/ld-musl-arm.so.1 167f7871000-f7873000 rw-p 00115000 /system/lib/ld-musl-arm.so.1 168f7873000-f787f000 rw-p 00000000 [anon:ld-musl-arm.so.1.bss] 169ff993000-ff9b4000 rw-p 00000000 [stack] 170ffff0000-ffff1000 r-xp 00000000 [vectors] 171``` 172 173 174通过Shell获取的“/data/log/faultlog/temp”获取到的日志内容格式如下: 175 176 177``` 178Timestamp:2017-08-06 00:54:30.000 <- 故障发生时间 179Pid:1369 <- 进程号 180Uid:0 <- 用户ID 181Process name:crasher <- 进程名 182Reason:Signal:SIGSEGV(SEGV_MAPERR)@00000000 <- 异常信息 183Fault thread Info: 184Tid:1369, Name:crasher <- 异常线程号与线程名 185#00 pc 00007be6 /data/crasher_c(SegmentFaultException+1)(1a75896316b332b9e7469de9d5a3e4e4) <- 调用栈 186#01 pc 000082c1 /data/crasher_c(ParseAndDoCrash+412)(1a75896316b332b9e7469de9d5a3e4e4) 187#02 pc 000083e1 /data/crasher_c(main+32)(1a75896316b332b9e7469de9d5a3e4e4) 188#03 pc 0006ef10 /system/lib/ld-musl-arm.so.1 189#04 pc 000038a0 /data/crasher_c(_start_c+84)(1a75896316b332b9e7469de9d5a3e4e4) 190#05 pc 00003844 /data/crasher_c(1a75896316b332b9e7469de9d5a3e4e4) 191Registers: <- 故障现场寄存器 192r0:00000000 r1:008a262b r2:00000000 r3:00000000 193r4:ff9b3e39 r5:00000002 r6:008a93c1 r7:f7872788 194r8:f7777976 r9:f7872318 r10:f7872418 195fp:ff9b39a8 ip:f777deea sp:ff9b3968 lr:008a92c5 pc:008a8be6 196Other thread info: <- 其他线程信息 197Tid:1370, Name:crasher <- 线程id,线程名 198#00 pc 00000000001aa2e0 /system/lib/ld-musl-aarch64.so.1(sleep+52) <- 调用栈 199#01 pc 0000000000005188 /data/crasher_c(abea41f851573f032e3e73a1e17d209d) 200#02 pc 000000000019f234 /system/lib/ld-musl-aarch64.so.1 201#03 pc 000000000009f8ac /system/lib/ld-musl-aarch64.so.1 202Memory near registers: <- 故障现场寄存器附近内存 203r1(/data/crasher_c): 204 008a2620 53697274 205 008a2624 45534749 206 ... 207 008a269c 20202020 208r4([stack]): 209 ff9b3e30 68736172 210 ff9b3e34 635f7265 211 ... 212 ff9b3eac 3d455a49 213r6(/data/crasher_c): 214 008a93b8 bf00bd80 215 008a93bc ffff96d7 216 ... 217 008a9434 bd802000 218r7(/system/lib/ld-musl-arm.so.1): 219 f7872780 00000000 220 f7872784 00000000 221 ... 222 f78727fc 00000000 223r8(/system/lib/ld-musl-arm.so.1): 224 f777796c 00646e65 225 f7777970 255f7325 226 ... 227 f77779e8 6d20726f 228r9(/system/lib/ld-musl-arm.so.1): 229 f7872310 00000001 230 f7872314 00000000 231 ... 232 f787238c 00000000 233r10(/system/lib/ld-musl-arm.so.1): 234 f7872410 00010000 235 f7872414 00000000 236 ... 237 f787248c 00000000 238fp([stack]): 239 ff9b39a0 00000001 240 ff9b39a4 f7872418 241 ... 242 ff9b3a1c ff9b3fd8 243r12(/system/lib/ld-musl-arm.so.1): 244 f777dee0 203e4425 245 f777dee4 25207461 246 ... 247 f777df5c 75747372 248sp([stack]): 249 ff9b3960 ff9b39a8 250 ff9b3964 008a91c1 251 ... 252 ff9b39dc 00000000 253lr(/data/crasher_c): 254 008a92bc e01cfc1b 255 008a92c0 fc90f7ff 256 ... 257 008a9338 ffff9609 258pc(/data/crasher_c): 259 008a8bdc ffff9f07 260 008a8be0 ffff9eb7 261 ... 262 008a8c58 edeaf000 263FaultStack: <- 崩溃线程的栈地址空间 264 ... 265 ff9b3964 008a91c1 266sp0:ff9b3968 0a9b39d4 <- #00栈顶 267 ff9b396c f5275648 268 ... 269 ff9b4168 ffffffff 270 271Maps: <- 故障时进程maps 2728a1000-8a4000 r--p 00000000 /data/crasher_c 2738a4000-8aa000 r-xp 00002000 /data/crasher_c 2748aa000-8ab000 r--p 00007000 /data/crasher_c 2758ab000-8ac000 rw-p 00007000 /data/crasher_c 276ada000-adb000 ---p 00000000 [heap] 277adb000-adc000 rw-p 00000000 [heap] 278... 279f7759000-f77af000 r--p 00000000 /system/lib/ld-musl-arm.so.1 280f77af000-f786f000 r-xp 00055000 /system/lib/ld-musl-arm.so.1 281f786f000-f7871000 r--p 00114000 /system/lib/ld-musl-arm.so.1 282f7871000-f7873000 rw-p 00115000 /system/lib/ld-musl-arm.so.1 283f7873000-f787f000 rw-p 00000000 [anon:ld-musl-arm.so.1.bss] 284ff993000-ff9b4000 rw-p 00000000 [stack] 285ffff0000-ffff1000 r-xp 00000000 [vectors] 286``` 287 288### 通过日志定位问题 289 2901. 通过故障日志等基础信息确定问题模块和故障类别。 291 292 通过崩溃进程名一般能定界到故障的模块,通过信号能判断崩溃的原因,通过堆栈中的方法名,可以复原崩溃栈的函数调用链。 293 294 如范例中的SIGSEGV是由Linux内核抛出,原因为访问了非法内存地址,问题发生在SegmentFaultException函数中。 295 296 大部分场景下崩溃栈的最上层就是崩溃的原因,如空指针访问以及程序主动终止运行。少部分场景调用栈无法定位原因,需要查看其他信息,例如踩内存或者栈溢出的问题场景可以查看寄存器信息和maps等内容。 297 2982. 通过addr2line工具解析出代码行号来复原崩溃现场调用栈。 299 300 使用Linux addr2line工具解析崩溃栈的行号,需要使用带调试信息的二进制。一般在版本编译或者应用编译时会生成带调试信息的二进制。 301 302 应用二进制位置在DevEco Studio应用构建的临时目录中,如build/default/intermediates/libs。系统二进制位置在如下目录,对于直接获取的版本,二进制会归档在完整镜像包中。 303 304 ``` 305 \代码根路径\out\产品\lib.unstripped 306 \代码根路径\out\产品\exe.unstripped 307 ``` 308 309 - Linux环境下,开发者可以通过apt-get install addr2line命令安装addr2line软件来使用。 310 - 在应用开发环境下,开发者还可以使用SDK中归档的llvm-addr2line工具来解析行号,使用方法一致。 311 312 使用addr2line工具根据偏移地址解析行号: 313 314 [product name]为具体设备名。 315 316 ``` 317 root:~/OpenHarmony/out/[product name]/exe.unstripped/hiviewdfx/faultloggerd$ addr2line -Cfie crasher 00007be6 318 base/hiviewdfx/faultloggerd/tools/crasher/dfx_crasher.c:123 319 ``` 320 321 示例中的崩溃故障是由于访问了空指针,代码行为dfx_crasher.c文件的123行。修改后可以避免发生此崩溃。 322 323 另外,使用addr2line后,如果得出的行号看起来不是很正确,可以考虑对地址进行微调(如减1),或者考虑关闭一些编译优化,已知使用LTO的二进制可能无法正确获得行号。