1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "dfx_crasher.h"
17
18 #include <pthread.h>
19 #include <signal.h>
20 #include <sys/prctl.h>
21 #include <sys/resource.h>
22 #include <unistd.h>
23 #include "errno.h"
24 #include "hilog/log.h"
25 #include "inttypes.h"
26 #include "stdio.h"
27 #include "stdlib.h"
28 #include "string.h"
29 #include "strings.h"
30 #include "dfx_define.h"
31
32 #ifdef LOG_DOMAIN
33 #undef LOG_DOMAIN
34 #define LOG_DOMAIN 0xD002D11
35 #endif
36
37 #ifdef LOG_TAG
38 #undef LOG_TAG
39 #define LOG_TAG "Unwind"
40 #endif
41
42 static const int ARG1024 = 1024;
43 static const int ARG128 = 128;
44
TriggerTrapException(void)45 NOINLINE int TriggerTrapException(void)
46 {
47 #ifndef __x86_64__
48 __asm__ volatile(".inst 0xde01");
49 #endif
50 return 0;
51 }
52
RaiseAbort(void)53 NOINLINE int RaiseAbort(void)
54 {
55 HILOG_FATAL(LOG_CORE, "Test Trigger ABORT!");
56 int ret = raise(SIGABRT);
57 if (ret != 0) {
58 printf("raise failed!");
59 }
60 return 0;
61 }
Abort(void)62 NOINLINE int Abort(void)
63 {
64 HILOG_FATAL(LOG_CORE, "Test Trigger ABORT!");
65 abort();
66 return 0;
67 }
68
RaiseBusError(void)69 NOINLINE int RaiseBusError(void)
70 {
71 int ret = raise(SIGBUS);
72 if (ret != 0) {
73 printf("remove failed!");
74 }
75 return 0;
76 }
77
RaiseFloatingPointException(void)78 NOINLINE int RaiseFloatingPointException(void)
79 {
80 int ret = raise(SIGFPE);
81 if (ret != 0) {
82 printf("remove failed!");
83 }
84 return 0;
85 }
86
RaiseIllegalInstructionException(void)87 NOINLINE int RaiseIllegalInstructionException(void)
88 {
89 int ret = raise(SIGILL);
90 if (ret != 0) {
91 printf("ramove failed!");
92 }
93 return 0;
94 }
95
IllegalInstructionException(void)96 NOINLINE int IllegalInstructionException(void)
97 {
98 #if defined(__aarch64__)
99 __asm__ volatile(".word 0\n");
100 #elif defined(__arm__)
101 __asm__ volatile(".word 0xe7f0def0\n");
102 #elif defined(__x86_64__)
103 __asm__ volatile("ud2\n");
104 #else
105 #error
106 #endif
107 return 0;
108 }
109
RaiseSegmentFaultException(void)110 NOINLINE int RaiseSegmentFaultException(void)
111 {
112 printf("call RaiseSegmentFaultException \n");
113 int ret = raise(SIGSEGV);
114 if (ret != 0) {
115 printf("remove failed!");
116 }
117 return 0;
118 }
119
SegmentFaultException(void)120 NOINLINE int SegmentFaultException(void)
121 {
122 volatile char *ptr = NULL;
123 *ptr;
124
125 return 0;
126 }
127
RaiseTrapException(void)128 NOINLINE int RaiseTrapException(void)
129 {
130 int ret = raise(SIGTRAP);
131 if (ret != 0) {
132 printf("remove failed!");
133 }
134 return 0;
135 }
136
TrapException(void)137 NOINLINE int TrapException(void)
138 {
139 return 0;
140 }
141
MaxStackDepth(void)142 NOINLINE int MaxStackDepth(void)
143 {
144 return TestFunc1();
145 }
146
MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC(void)147 NOINLINE int MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC(void)
148 {
149 printf("call MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC \n");
150 int ret = raise(SIGSEGV);
151 if (ret != 0) {
152 printf("remove failed!");
153 }
154 return 0;
155 }
156
StackOverflow(void)157 NOINLINE int StackOverflow(void)
158 {
159 printf("call StackOverflow\n");
160
161 // for stack overflow test
162 char a[1024][1024][1024] = { { {'1'} } };
163 char b[1024][1024][1024] = { { {'1'} } };
164 char c[1024][1024][1024] = { { {'1'} } };
165 char d[1024][1024][1024] = { { {'1'} } };
166 printf("a[0][0] is %s\n", a[0][0]);
167 printf("b[0][0] is %s\n", b[0][0]);
168 printf("c[0][0] is %s\n", c[0][0]);
169 printf("d[0][0] is %s\n", d[0][0]);
170
171 return 0;
172 }
173
Oom(void)174 NOINLINE int Oom(void)
175 {
176 struct rlimit oldRlimit;
177 if (getrlimit(RLIMIT_AS, &oldRlimit) != 0) {
178 printf("getrlimit failed\n");
179 raise(SIGINT);
180 }
181 printf("old rlimit, cur:0x%016" PRIx64 " max:0x%016" PRIx64 "\n",
182 (uint64_t)oldRlimit.rlim_cur, (uint64_t)oldRlimit.rlim_max);
183
184 struct rlimit rlim = {
185 .rlim_cur = (ARG128 - 1) * ARG1024 * ARG1024,
186 .rlim_max = (ARG128 - 1) * ARG1024 * ARG1024,
187 };
188
189 if (setrlimit(RLIMIT_AS, &rlim) != 0) {
190 printf("setrlimit failed\n");
191 raise(SIGINT);
192 }
193 char* bufferArray[ARG128];
194 for (int i = 0; i < ARG128; i++) {
195 char* buf = (char*)malloc(ARG1024 * ARG1024);
196 if (buf == NULL) {
197 printf("malloc return null\n");
198 if (setrlimit(RLIMIT_AS, &oldRlimit) != 0) {
199 printf("restore rlimit failed\n");
200 }
201 printf("restore rlimit ok\n");
202 abort();
203 }
204 bufferArray[i] = buf;
205 }
206 for (int i = 0; i < ARG128; i++) {
207 printf("0x%x", *(bufferArray[i] + 1));
208 }
209
210 return 0;
211 }
212
ProgramCounterZero(void)213 NOINLINE int ProgramCounterZero(void)
214 {
215 printf("test PCZero");
216 #if defined(__arm__)
217 __asm__ volatile (
218 "mov r0, #0x00\n mov lr, pc\n bx r0\n"
219 );
220 #elif defined(__aarch64__)
221 __asm__ volatile (
222 "movz x0, #0x0\n"
223 "adr x30, .\n"
224 "br x0\n"
225 );
226 #endif
227 return 0;
228 }
229
MultiThreadCrash(void)230 NOINLINE int MultiThreadCrash(void)
231 {
232 printf("test MultiThreadCrash");
233
234 pthread_t t[2];
235 int threadID[2] = {1, 2};
236 pthread_create(&t[0], NULL, SleepThread, &threadID[0]);
237 pthread_create(&t[1], NULL, SleepThread, &threadID[1]);
238 pthread_detach(t[0]);
239 pthread_detach(t[1]);
240 sleep(1);
241
242 int ret = raise(SIGSEGV);
243 if (ret != 0) {
244 printf("remove failed!");
245 }
246
247 return 0;
248 }
249
StackOver64(void)250 NOINLINE int StackOver64(void)
251 {
252 printf("test StackOver64");
253
254 return TestFunc1();
255 }
256
SleepThread(void * argv)257 void *SleepThread(void *argv)
258 {
259 int threadID = *(int*)argv;
260 printf("create MultiThread %d", threadID);
261
262 int sleepTime = 10;
263 sleep(sleepTime);
264
265 return 0;
266 }
267
StackTop(void)268 NOINLINE int StackTop(void)
269 {
270 printf("test StackTop\n");
271 register void* stackTop;
272 #if defined(__arm__)
273 __asm__ volatile ("mov %0, sp":"=r"(stackTop)::);
274 printf("crasher_c: stack top is = %08x\n", (unsigned int)stackTop);
275 #elif defined(__aarch64__)
276 __asm__ volatile ("mov %0, sp":"=r"(stackTop)::);
277 printf("crasher_c: stack top is = %16llx\n", (unsigned long long)stackTop);
278 #else
279 return 0;
280 #endif
281
282 FILE *fp = NULL;
283 fp = fopen("/data/sp", "w");
284 if (fp == NULL) {
285 printf("Open /data/sp failed, errno(%d)\n", errno);
286 return 0;
287 }
288
289 int ret = 0; // for fixing compile error on x64
290 #if defined(__arm__)
291 ret = fprintf(fp, "%08x", (unsigned int)stackTop);
292 #elif defined(__aarch64__)
293 ret = fprintf(fp, "%16llx", (unsigned long long)stackTop);
294 #endif
295 if (ret == EOF) {
296 printf("error!");
297 }
298 ret = fclose(fp);
299 if (ret == EOF) {
300 printf("close error!");
301 }
302
303 #if defined(__arm__)
304 __asm__ volatile ("mov r1, #0\nldr r2, [r1]\n");
305 #elif defined(__aarch64__)
306 __asm__ volatile ("mov x1, #0\nldr x2, [x1]\n");
307 #endif
308 return ret;
309 }
310
PrintUsage(void)311 void PrintUsage(void)
312 {
313 printf(" usage: crasher CMD\n");
314 printf("\n");
315 printf(" where CMD support:\n");
316 printf(" SIGFPE raise a SIGFPE\n");
317 printf(" SIGILL raise a SIGILL\n");
318 printf(" SIGSEGV raise a SIGSEGV\n");
319 printf(" SIGTRAP raise a SIGTRAP\n");
320 printf(" SIGABRT raise a SIGABRT\n");
321 printf(" SIGBUS raise a SIGBUS\n");
322
323 printf(" triSIGILL trigger a SIGILL\n");
324 printf(" triSIGSEGV trigger a SIGSEGV\n");
325 printf(" triSIGTRAP trigger a SIGTRAP\n");
326 printf(" triSIGABRT trigger a SIGABRT\n");
327
328 printf(" Loop trigger a ForeverLoop\n");
329 printf(" MaxStack trigger SIGSEGV after 64 function call\n");
330 printf(" MaxMethod trigger SIGSEGV after call a function with longer name\n");
331 printf(" OOM trigger out of memory\n");
332 printf(" STACKOF trigger a stack overflow\n");
333 printf(" PCZero trigger pc = 0\n");
334 printf(" MTCrash trigger crash with multi-thread\n");
335 printf(" StackOver64 trigger SIGSEGV after 70 function call\n");
336 printf(" StackTop trigger SIGSEGV to make sure stack top\n");
337 printf(" if you want the command execute in a sub thread\n");
338 printf(" add thread Prefix, e.g crasher thread-SIGFPE\n");
339 printf("\n");
340 }
341
DoCrashInThread(void * inputArg)342 void *DoCrashInThread(void *inputArg)
343 {
344 prctl(PR_SET_NAME, "SubTestThread");
345 const char *arg = (const char *)(inputArg);
346 return (void *)((uint64_t)(ParseAndDoCrash(arg)));
347 }
348
DoActionOnSubThread(const char * arg)349 uint64_t DoActionOnSubThread(const char *arg)
350 {
351 pthread_t t;
352 pthread_create(&t, NULL, DoCrashInThread, (char *)(arg));
353 void *result = NULL;
354 pthread_join(t, &result);
355 return (uint64_t)(result);
356 }
357
ParseAndDoCrash(const char * arg)358 uint64_t ParseAndDoCrash(const char *arg)
359 {
360 // Prefix
361 if (!strncmp(arg, "thread-", strlen("thread-"))) {
362 return DoActionOnSubThread(arg + strlen("thread-"));
363 }
364
365 // Action
366 if (!strcasecmp(arg, "SIGFPE")) {
367 return RaiseFloatingPointException();
368 }
369
370 if (!strcasecmp(arg, "SIGILL")) {
371 return RaiseIllegalInstructionException();
372 }
373
374 if (!strcasecmp(arg, "triSIGILL")) {
375 return IllegalInstructionException();
376 }
377
378 if (!strcasecmp(arg, "SIGSEGV")) {
379 return RaiseSegmentFaultException();
380 }
381
382 if (!strcasecmp(arg, "SIGTRAP")) {
383 return RaiseTrapException();
384 }
385
386 if (!strcasecmp(arg, "SIGABRT")) {
387 return RaiseAbort();
388 }
389
390 if (!strcasecmp(arg, "triSIGABRT")) {
391 return Abort();
392 }
393
394 if (!strcasecmp(arg, "triSIGSEGV")) {
395 return SegmentFaultException();
396 }
397
398 if (!strcasecmp(arg, "SIGBUS")) {
399 return RaiseBusError();
400 }
401
402 if (!strcasecmp(arg, "triSIGTRAP")) {
403 return TriggerTrapException();
404 }
405
406 if (!strcasecmp(arg, "Loop")) {
407 int i = 0;
408 while (1) {
409 usleep(10000); // 10000:sleep 0.01 second
410 i++;
411 }
412 }
413
414 if (!strcasecmp(arg, "MaxStack")) {
415 return MaxStackDepth();
416 }
417
418 if (!strcasecmp(arg, "MaxMethod")) {
419 return MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC();
420 }
421
422 if (!strcasecmp(arg, "STACKOF")) {
423 return StackOverflow();
424 }
425
426 if (!strcasecmp(arg, "OOM")) {
427 return Oom();
428 }
429
430 if (!strcasecmp(arg, "PCZero")) {
431 return ProgramCounterZero();
432 }
433
434 if (!strcasecmp(arg, "MTCrash")) {
435 return MultiThreadCrash();
436 }
437
438 if (!strcasecmp(arg, "StackOver64")) {
439 return StackOver64();
440 }
441
442 if (!strcasecmp(arg, "StackTop")) {
443 return StackTop();
444 }
445
446 if (!strcasecmp(arg, "CrashTest")) {
447 return CrashTest();
448 }
449
450 return 0;
451 }
452
TestFunc70(void)453 NOINLINE int TestFunc70(void)
454 {
455 int ret = raise(SIGSEGV);
456 if (ret != 0) {
457 printf("remove failed!");
458 }
459 return 0;
460 }
461
CrashTest(void)462 NOINLINE int CrashTest(void)
463 {
464 int sleepTime = 3;
465 sleep(sleepTime);
466 int ret = raise(SIGSEGV);
467 if (ret != 0) {
468 printf("remove failed!");
469 }
470 return 0;
471 }
472
main(int argc,char * argv[])473 int main(int argc, char *argv[])
474 {
475 PrintUsage();
476 if (argc <= 1) {
477 printf("wrong usage!");
478 PrintUsage();
479 return 0;
480 }
481
482 printf("ParseAndDoCrash done: %" PRIu64 "!\n", ParseAndDoCrash(argv[1]));
483 return 0;
484 }
485
486 // auto gen function
487 GEN_TEST_FUNCTION(0, 1)
488 GEN_TEST_FUNCTION(1, 2)
489 GEN_TEST_FUNCTION(2, 3)
490 GEN_TEST_FUNCTION(3, 4)
491 GEN_TEST_FUNCTION(4, 5)
492 GEN_TEST_FUNCTION(5, 6)
493 GEN_TEST_FUNCTION(6, 7)
494 GEN_TEST_FUNCTION(7, 8)
495 GEN_TEST_FUNCTION(8, 9)
496 GEN_TEST_FUNCTION(9, 10)
497
498 GEN_TEST_FUNCTION(10, 11)
499 GEN_TEST_FUNCTION(11, 12)
500 GEN_TEST_FUNCTION(12, 13)
501 GEN_TEST_FUNCTION(13, 14)
502 GEN_TEST_FUNCTION(14, 15)
503 GEN_TEST_FUNCTION(15, 16)
504 GEN_TEST_FUNCTION(16, 17)
505 GEN_TEST_FUNCTION(17, 18)
506 GEN_TEST_FUNCTION(18, 19)
507 GEN_TEST_FUNCTION(19, 20)
508
509 GEN_TEST_FUNCTION(20, 21)
510 GEN_TEST_FUNCTION(21, 22)
511 GEN_TEST_FUNCTION(22, 23)
512 GEN_TEST_FUNCTION(23, 24)
513 GEN_TEST_FUNCTION(24, 25)
514 GEN_TEST_FUNCTION(25, 26)
515 GEN_TEST_FUNCTION(26, 27)
516 GEN_TEST_FUNCTION(27, 28)
517 GEN_TEST_FUNCTION(28, 29)
518 GEN_TEST_FUNCTION(29, 30)
519
520 GEN_TEST_FUNCTION(30, 31)
521 GEN_TEST_FUNCTION(31, 32)
522 GEN_TEST_FUNCTION(32, 33)
523 GEN_TEST_FUNCTION(33, 34)
524 GEN_TEST_FUNCTION(34, 35)
525 GEN_TEST_FUNCTION(35, 36)
526 GEN_TEST_FUNCTION(36, 37)
527 GEN_TEST_FUNCTION(37, 38)
528 GEN_TEST_FUNCTION(38, 39)
529 GEN_TEST_FUNCTION(39, 40)
530
531 GEN_TEST_FUNCTION(40, 41)
532 GEN_TEST_FUNCTION(41, 42)
533 GEN_TEST_FUNCTION(42, 43)
534 GEN_TEST_FUNCTION(43, 44)
535 GEN_TEST_FUNCTION(44, 45)
536 GEN_TEST_FUNCTION(45, 46)
537 GEN_TEST_FUNCTION(46, 47)
538 GEN_TEST_FUNCTION(47, 48)
539 GEN_TEST_FUNCTION(48, 49)
540 GEN_TEST_FUNCTION(49, 50)
541
542 GEN_TEST_FUNCTION(50, 51)
543 GEN_TEST_FUNCTION(51, 52)
544 GEN_TEST_FUNCTION(52, 53)
545 GEN_TEST_FUNCTION(53, 54)
546 GEN_TEST_FUNCTION(54, 55)
547 GEN_TEST_FUNCTION(55, 56)
548 GEN_TEST_FUNCTION(56, 57)
549 GEN_TEST_FUNCTION(57, 58)
550 GEN_TEST_FUNCTION(58, 59)
551 GEN_TEST_FUNCTION(59, 60)
552
553 GEN_TEST_FUNCTION(60, 61)
554 GEN_TEST_FUNCTION(61, 62)
555 GEN_TEST_FUNCTION(62, 63)
556 GEN_TEST_FUNCTION(63, 64)
557 GEN_TEST_FUNCTION(64, 65)
558 GEN_TEST_FUNCTION(65, 66)
559 GEN_TEST_FUNCTION(66, 67)
560 GEN_TEST_FUNCTION(67, 68)
561 GEN_TEST_FUNCTION(68, 69)
562 GEN_TEST_FUNCTION(69, 70)
563