1 #include <stdio.h>
2 #include <string.h>
3 #include <stdint.h>
4 #include <stdlib.h>
5 #include <math.h>
6 #include <cutils/log.h>
7
8 #include "crash_analyzer_defs.h"
9 #include "crash_analyzer.h"
10
11 #define MAX_PATTERN_SIZE 1024
12 #define MAX_CSTRING_SIZE 8000
13 #define SEPARATOR " | "
14
find_rightmost_setbit_position(uint32_t number)15 int find_rightmost_setbit_position(uint32_t number)
16 {
17 if (number)
18 return log2(number ^ (number & (number - 1)));
19
20 return -1;
21 }
22
find_exception_in_hmd_dmx(unsigned char * buf,int buf_len,const char * core,char * outbuf,int outbuf_max_size)23 char* find_exception_in_hmd_dmx(unsigned char *buf, int buf_len,
24 const char *core, char *outbuf,
25 int outbuf_max_size)
26 {
27 char exccause[64] = {0};
28 char epc1[32] = {0};
29 uint32_t *wordBuf = (uint32_t*)buf;
30
31 if (buf == NULL || buf_len < HMD_DMX_INDEX_MAX * BYTES_PER_WORD ||
32 core == NULL || outbuf == NULL || outbuf_max_size <= 0 ||
33 wordBuf[START_HMD_DMX_INDEX] == 0 ||
34 strlen(outbuf) >= outbuf_max_size)
35 return outbuf;
36
37 int excepIndex = wordBuf[EXCEPTION_INDEX];
38
39 if (excepIndex >= HMD_DMXEXCEPTIONCAUSELIST_SIZE) {
40 strncpy(exccause, "Reserved", sizeof(exccause));
41 }
42 else {
43 strncpy(exccause, Hmd_DmxExceptionCauseList[excepIndex],
44 sizeof(exccause));
45 }
46
47 snprintf(epc1, sizeof(epc1), "0x%08x", wordBuf[EPC1_INDEX]);
48
49 if (strlen(outbuf) > 0) {
50 strncat(outbuf, SEPARATOR,
51 outbuf_max_size - strlen(outbuf) - 1);
52 }
53
54 strncat(outbuf, core,
55 outbuf_max_size - strlen(outbuf) - 1);
56 strncat(outbuf, " crash ",
57 outbuf_max_size - strlen(outbuf) - 1);
58 strncat(outbuf, exccause,
59 outbuf_max_size - strlen(outbuf) - 1);
60 strncat(outbuf, "/",
61 outbuf_max_size - strlen(outbuf) - 1);
62 strncat(outbuf, epc1,
63 outbuf_max_size - strlen(outbuf) - 1);
64
65 return outbuf;
66 }
67
find_exceptionin_cm4(unsigned char * buf,int buf_len,const char * core,char * outbuf,int outbuf_max_size)68 char* find_exceptionin_cm4(unsigned char *buf, int buf_len, const char *core,
69 char *outbuf, int outbuf_max_size)
70 {
71
72 char cause[64] = {0};
73 uint32_t *wordBuf = (uint32_t*)buf;
74
75 if (buf == NULL || buf_len < CM4_INDEX_MAX * BYTES_PER_WORD ||
76 core == NULL || outbuf == NULL || outbuf_max_size <= 0 ||
77 wordBuf[START_CM4_INDEX] == 0 ||
78 strlen(outbuf) >= outbuf_max_size)
79 return outbuf;
80
81 int faultStatusRegister = wordBuf[FAULT_STATUS_INDEX];
82
83 int exceptionBitSet = find_rightmost_setbit_position(faultStatusRegister);
84
85 if (exceptionBitSet == -1) {
86 return outbuf;
87 }
88
89 if (exceptionBitSet >= CM4EXCEPTIONCAUSELIST_SIZE) {
90 strncpy(cause, "Reserved", sizeof(cause));
91 }
92 else {
93 strncpy(cause, Cm4ExceptionCauseList[exceptionBitSet],
94 sizeof(cause));
95 }
96
97 if(strlen(outbuf) > 0){
98 strncat(outbuf, SEPARATOR,
99 outbuf_max_size - strlen(outbuf) - 1);
100 }
101
102 strncat(outbuf, core,
103 outbuf_max_size - strlen(outbuf) - 1);
104 strncat(outbuf, " crash ",
105 outbuf_max_size - strlen(outbuf) - 1);
106 strncat(outbuf, cause,
107 outbuf_max_size - strlen(outbuf) - 1);
108
109 return outbuf;
110 }
111
112
find_fatal_assert(unsigned char * buf,int buf_len,int size,const char * core,char * outbuf,int outbuf_max_size)113 char* find_fatal_assert(unsigned char *buf, int buf_len, int size,
114 const char *core, char *outbuf,
115 int outbuf_max_size)
116 {
117
118 char cause[64] = {0};
119 char lineNumStr[10] = {0};
120 uint32_t *wordBuf = (uint32_t*)buf;
121 uint32_t wordSize = size / 4;
122 /*
123 *|Time Stamp|Event Label,Debug Level,Line No|Opaque Data 1|Opaque Data 2|Opaque Data 3|Opaque Data 4|
124 *|(64 bits) | (12 bits), (4 bits), (16 bits)| (32 bits) | (32 bits) | (32 bits) | (32 bits) |
125 */
126 int info_size = 7;
127 /* Index of event label word in 64 bit timestamp */
128 int curEvtIndex = 2;
129
130 if (buf == NULL || size <= 0 || buf_len < size || core == NULL ||
131 outbuf == NULL || outbuf_max_size <= 0 ||
132 strlen(outbuf) >= outbuf_max_size)
133 return outbuf;
134
135 /* This 32-bit word containing this info
136 * is in Little-Endian format to read
137 * the value of this fields.
138 *
139 * |0...11| -> Module Id
140 * |12...15| -> Log level
141 * |16...31| -> Line no
142 */
143 while (curEvtIndex < wordSize) {
144 int evt = wordBuf[curEvtIndex];
145 int logLevel = (evt >> 12) & 0xF;
146
147 if (logLevel != DBG_LOG_LVL_FATAL) {
148 curEvtIndex += info_size;
149 continue;
150 }
151
152 int module_id = evt & 0xFFF;
153 int lineNo = (evt >> 16) & 0xFFFF;
154
155 if (module_id >= ASSERTDEBUGMODLIST_SIZE) {
156 /* Invalid module id */
157 curEvtIndex += info_size;
158 continue;
159 }
160 else {
161 snprintf(cause, sizeof(cause), "%s",
162 AssertDebugModList[module_id]);
163 }
164
165 strncat(cause , "+",
166 sizeof(cause) - strlen(cause) - 1);
167
168 snprintf(lineNumStr, sizeof(lineNumStr), "%d", lineNo);
169
170 strncat(cause, lineNumStr,
171 sizeof(cause) - strlen(cause) - 1);
172
173 if(strlen(outbuf) > 0) {
174 strncat(outbuf, SEPARATOR,
175 outbuf_max_size - strlen(outbuf) - 1);
176 }
177
178 strncat(outbuf, "ASSERT LOG in ",
179 outbuf_max_size - strlen(outbuf) - 1);
180 strncat(outbuf, core,
181 outbuf_max_size - strlen(outbuf) - 1);
182 strncat(outbuf, " ",
183 outbuf_max_size - strlen(outbuf) - 1);
184 strncat(outbuf, cause,
185 outbuf_max_size - strlen(outbuf) - 1);
186
187 return outbuf;
188 }
189
190 return outbuf;
191 }
192
analyse_crash_info(const unsigned char * buf,const int buf_len,char * out_crash_analyzer_str,int max_out_crash_analyzer_str_size)193 int analyse_crash_info(const unsigned char *buf, const int buf_len,
194 char *out_crash_analyzer_str,
195 int max_out_crash_analyzer_str_size)
196 {
197 unsigned int file_index = 0, size = 0, tot_len = 0;
198 int fcount = 0;
199 unsigned char *ptr = NULL;
200
201 if (buf == NULL || out_crash_analyzer_str == NULL ||
202 buf_len <= 0 || max_out_crash_analyzer_str_size <= 0) {
203 ALOGE("%s: Bad parameters", __func__);
204 return -1;
205 }
206
207 out_crash_analyzer_str[0] = '\0';
208
209 while ((tot_len + STEP_LENGTH - 1 < buf_len) && (fcount++ < FILE_MAX)) {
210 file_index = buf[tot_len];
211
212 size = buf[tot_len + 8] |
213 buf[tot_len + 9] << 8 |
214 buf[tot_len + 10] << 16 |
215 buf[tot_len + 11] << 24;
216
217 tot_len += STEP_LENGTH;
218 ptr = (unsigned char*)buf + tot_len;
219
220 if (file_index == CM4_DUMP_DEBUG) {
221 find_fatal_assert(ptr, buf_len - tot_len, size, "CM4",
222 out_crash_analyzer_str,
223 max_out_crash_analyzer_str_size);
224 } else if(file_index == HMD_DUMP_DEBUG) {
225 find_fatal_assert(ptr, buf_len - tot_len, size, "HMD",
226 out_crash_analyzer_str,
227 max_out_crash_analyzer_str_size);
228 } else if(file_index == DMX_DUMP_DEBUG) {
229 find_fatal_assert(ptr, buf_len - tot_len, size, "DMX",
230 out_crash_analyzer_str,
231 max_out_crash_analyzer_str_size);
232 } else if(file_index == CM4_DUMP_CRASH) {
233 find_exceptionin_cm4(ptr, buf_len - tot_len, "CM4",
234 out_crash_analyzer_str,
235 max_out_crash_analyzer_str_size);
236 } else if(file_index == HMD_DUMP_CRASH) {
237 find_exception_in_hmd_dmx(ptr, buf_len - tot_len, "HMD",
238 out_crash_analyzer_str,
239 max_out_crash_analyzer_str_size);
240 } else if(file_index == DMX_DUMP_CRASH) {
241 find_exception_in_hmd_dmx(ptr, buf_len - tot_len, "DMX",
242 out_crash_analyzer_str,
243 max_out_crash_analyzer_str_size);
244 } else {
245 ALOGE("%s: unknown index number: %u", __func__ , file_index);
246 }
247
248 tot_len += size;
249 }
250
251 return strlen(out_crash_analyzer_str);
252 }
253