• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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        ![cppcrash-faultlogger-log](figures/20230407112159.png)
31
32    2. “设备/data/log/faultlog/temp/”路径下的故障日志,其文件名格式为“cppcrash-进程PID-系统毫秒级时间戳”,包含进程崩溃时栈内存、进程maps等信息。
33
34        ![cppcrash-temp-log](figures/20230407111853.png)
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的二进制可能无法正确获得行号。