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