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 "hilog/log.h"
24 #include "inttypes.h"
25 #include "stdio.h"
26 #include "stdlib.h"
27 #include "string.h"
28 #include "strings.h"
29
30 #ifdef LOG_DOMAIN
31 #undef LOG_DOMAIN
32 #define LOG_DOMAIN 0xD002D11
33 #endif
34
35 #ifdef LOG_TAG
36 #undef LOG_TAG
37 #define LOG_TAG "Unwind"
38 #endif
39
40 static const int ARG1024 = 1024;
41 static const int ARG128 = 128;
42
TriggerTrapException(void)43 NOINLINE int TriggerTrapException(void)
44 {
45 __asm__ volatile(".inst 0xde01");
46
47 return 0;
48 }
49
RaiseAbort(void)50 NOINLINE int RaiseAbort(void)
51 {
52 HILOG_FATAL(LOG_CORE, "Test Trigger ABORT!");
53 int ret = raise(SIGABRT);
54 if (ret != 0) {
55 printf("raise failed!");
56 }
57 return 0;
58 }
Abort(void)59 NOINLINE int Abort(void)
60 {
61 HILOG_FATAL(LOG_CORE, "Test Trigger ABORT!");
62 abort();
63 return 0;
64 }
65
RaiseBusError(void)66 NOINLINE int RaiseBusError(void)
67 {
68 int ret = raise(SIGBUS);
69 if (ret != 0) {
70 printf("remove failed!");
71 }
72 return 0;
73 }
74
DumpStackTrace(void)75 NOINLINE int DumpStackTrace(void)
76 {
77 int ret = raise(35); // 35:SIGDUMP
78 if (ret != 0) {
79 printf("remove failed!");
80 }
81 return 0;
82 }
83
RaiseFloatingPointException(void)84 NOINLINE int RaiseFloatingPointException(void)
85 {
86 int ret = raise(SIGFPE);
87 if (ret != 0) {
88 printf("remove failed!");
89 }
90 return 0;
91 }
92
RaiseIllegalInstructionException(void)93 NOINLINE int RaiseIllegalInstructionException(void)
94 {
95 int ret = raise(SIGILL);
96 if (ret !=0) {
97 printf("ramove failed!");
98 }
99 return 0;
100 }
IllegalInstructionException(void)101 NOINLINE int IllegalInstructionException(void)
102 {
103 char mes[] = "ABCDEFGHIJ";
104 char* ptr = mes;
105 ptr = NULL;
106 *ptr = 0;
107
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*)malloc(ARG1024 * ARG1024);
197 if (!buf) {
198 printf("malloc return null\n");
199 if (setrlimit(RLIMIT_AS, &oldRlimit) != 0) {
200 printf("restore rlimit failed\n");
201 }
202 printf("restore rlimit ok\n");
203 abort();
204 }
205 bufferArray[i] = buf;
206 }
207 for (int i = 0; i < ARG128; i++) {
208 printf("0x%x", *(bufferArray[i] + 1));
209 }
210
211 return 0;
212 }
213
ProgramCounterZero(void)214 NOINLINE int ProgramCounterZero(void)
215 {
216 printf("test PCZero");
217 #if defined(__arm__)
218 __asm__ volatile (
219 "mov r0, #0x00\n mov lr, pc\n bx r0\n"
220 );
221 #elif defined(__aarch64__)
222 __asm__ volatile (
223 "movz x0, #0x0\n"
224 "adr x30, .\n"
225 "br x0\n"
226 );
227 #endif
228 return 0;
229 }
230
MultiThreadCrash(void)231 NOINLINE int MultiThreadCrash(void)
232 {
233 printf("test MultiThreadCrash");
234
235 pthread_t t[2];
236 int threadID[2] = {1, 2};
237 pthread_create(&t[0], NULL, SleepThread, &threadID[0]);
238 pthread_create(&t[1], NULL, SleepThread, &threadID[1]);
239 pthread_detach(t[0]);
240 pthread_detach(t[1]);
241 sleep(1);
242
243 int ret = raise(SIGSEGV);
244 if (ret != 0) {
245 printf("remove failed!");
246 }
247
248 return 0;
249 }
250
StackOver64(void)251 NOINLINE int StackOver64(void)
252 {
253 printf("test StackOver64");
254
255 return TestFunc1();
256 }
257
SleepThread(void * argv)258 void *SleepThread(void *argv)
259 {
260 int threadID = *(int*)argv;
261 printf("create MultiThread %d", threadID);
262
263 int sleepTime = 10;
264 sleep(sleepTime);
265
266 return 0;
267 }
268
StackTop(void)269 NOINLINE int StackTop(void)
270 {
271 printf("test StackTop");
272
273 #if defined(__arm__)
274 int stackTop;
275 __asm__ volatile ("mov %0, sp":"=r"(stackTop)::);
276 printf("crasher_c: stack top is = %08x", stackTop);
277 #elif defined(__aarch64__)
278 uint64_t stackTop;
279 __asm__ volatile ("mov %0, sp":"=r"(stackTop)::);
280 printf("crasher_c: stack top is = %16llx", (unsigned long long)stackTop);
281 #else
282 return 0;
283 #endif
284
285 FILE *fp = NULL;
286 fp = fopen("sp", "w");
287 if (fp == NULL) {
288 printf("open file error!");
289 return 0;
290 }
291
292 #if defined(__arm__)
293 int ret = fprintf(fp, "%08x", stackTop);
294 #elif defined(__aarch64__)
295 int 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 // trigger an error to crash
305 int a = 1;
306 int *b = &a;
307 b = NULL;
308 *b = 1;
309
310 return 0;
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 printf(" STACKTRACE raise a SIGDUMP\n");
325
326 printf(" triSIGILL trigger a SIGILL\n");
327 printf(" triSIGSEGV trigger a SIGSEGV\n");
328 printf(" triSIGTRAP trigger a SIGTRAP\n");
329 printf(" triSIGABRT trigger a SIGABRT\n");
330
331 printf(" Loop trigger a ForeverLoop\n");
332 printf(" MaxStack trigger SIGSEGV after 64 function call\n");
333 printf(" MaxMethod trigger SIGSEGV after call a function with longer name\n");
334 printf(" OOM trigger out of memory\n");
335 printf(" STACKOF trigger a stack overflow\n");
336 printf(" PCZero trigger pc = 0\n");
337 printf(" MTCrash trigger crash with multi-thread\n");
338 printf(" StackOver64 trigger SIGSEGV after 70 function call\n");
339 printf(" StackTop trigger SIGSEGV to make sure stack top\n");
340 printf(" if you want the command execute in a sub thread\n");
341 printf(" add thread Prefix, e.g crasher thread-SIGFPE\n");
342 printf("\n");
343 }
344
DoCrashInThread(void * inputArg)345 void *DoCrashInThread(void *inputArg)
346 {
347 prctl(PR_SET_NAME, "SubTestThread");
348 const char *arg = (const char *)(inputArg);
349 return (void *)((uint64_t)(ParseAndDoCrash(arg)));
350 }
351
DoActionOnSubThread(const char * arg)352 uint64_t DoActionOnSubThread(const char *arg)
353 {
354 pthread_t t;
355 pthread_create(&t, NULL, DoCrashInThread, (char *)(arg));
356 void *result = NULL;
357 pthread_join(t, &result);
358 return (uint64_t)(result);
359 }
360
ParseAndDoCrash(const char * arg)361 uint64_t ParseAndDoCrash(const char *arg)
362 {
363 // Prefix
364 if (!strncmp(arg, "thread-", strlen("thread-"))) {
365 return DoActionOnSubThread(arg + strlen("thread-"));
366 }
367
368 // Action
369 if (!strcasecmp(arg, "SIGFPE")) {
370 return RaiseFloatingPointException();
371 }
372
373 if (!strcasecmp(arg, "SIGILL")) {
374 return RaiseIllegalInstructionException();
375 }
376
377 if (!strcasecmp(arg, "triSIGILL")) {
378 return IllegalInstructionException();
379 }
380
381 if (!strcasecmp(arg, "SIGSEGV")) {
382 return RaiseSegmentFaultException();
383 }
384
385 if (!strcasecmp(arg, "SIGTRAP")) {
386 return RaiseTrapException();
387 }
388
389 if (!strcasecmp(arg, "SIGABRT")) {
390 return RaiseAbort();
391 }
392
393 if (!strcasecmp(arg, "triSIGABRT")) {
394 return Abort();
395 }
396
397 if (!strcasecmp(arg, "triSIGSEGV")) {
398 return SegmentFaultException();
399 }
400
401 if (!strcasecmp(arg, "SIGBUS")) {
402 return RaiseBusError();
403 }
404
405 if (!strcasecmp(arg, "triSIGTRAP")) {
406 return TriggerTrapException();
407 }
408
409 if (!strcasecmp(arg, "STACKTRACE")) {
410 return DumpStackTrace();
411 }
412
413 if (!strcasecmp(arg, "Loop")) {
414 int i = 0;
415 while (1) {
416 usleep(10000); // 10000:sleep 0.01 second
417 i++;
418 }
419 }
420
421 if (!strcasecmp(arg, "MaxStack")) {
422 return MaxStackDepth();
423 }
424
425 if (!strcasecmp(arg, "MaxMethod")) {
426 return MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC();
427 }
428
429 if (!strcasecmp(arg, "STACKOF")) {
430 return StackOverflow();
431 }
432
433 if (!strcasecmp(arg, "OOM")) {
434 return Oom();
435 }
436
437 if (!strcasecmp(arg, "PCZero")) {
438 return ProgramCounterZero();
439 }
440
441 if (!strcasecmp(arg, "MTCrash")) {
442 return MultiThreadCrash();
443 }
444
445 if (!strcasecmp(arg, "StackOver64")) {
446 return StackOver64();
447 }
448
449 if (!strcasecmp(arg, "StackTop")) {
450 return StackTop();
451 }
452
453 if (!strcasecmp(arg, "CrashTest")) {
454 return CrashTest();
455 }
456
457 return 0;
458 }
459
TestFunc70(void)460 NOINLINE int TestFunc70(void)
461 {
462 int ret = raise(SIGSEGV);
463 if (ret != 0) {
464 printf("remove failed!");
465 }
466 return 0;
467 }
468
CrashTest(void)469 NOINLINE int CrashTest(void)
470 {
471 int sleepTime = 3;
472 sleep(sleepTime);
473 int ret = raise(SIGSEGV);
474 if (ret != 0) {
475 printf("remove failed!");
476 }
477 return 0;
478 }
479
main(int argc,char * argv[])480 int main(int argc, char *argv[])
481 {
482 PrintUsage();
483 if (argc <= 1) {
484 printf("wrong usage!");
485 PrintUsage();
486 return 0;
487 }
488
489 printf("ParseAndDoCrash done: %" PRIu64 "!\n", ParseAndDoCrash(argv[1]));
490 return 0;
491 }
492
493 // auto gen function
494 GEN_TEST_FUNCTION(0, 1)
495 GEN_TEST_FUNCTION(1, 2)
496 GEN_TEST_FUNCTION(2, 3)
497 GEN_TEST_FUNCTION(3, 4)
498 GEN_TEST_FUNCTION(4, 5)
499 GEN_TEST_FUNCTION(5, 6)
500 GEN_TEST_FUNCTION(6, 7)
501 GEN_TEST_FUNCTION(7, 8)
502 GEN_TEST_FUNCTION(8, 9)
503 GEN_TEST_FUNCTION(9, 10)
504
505 GEN_TEST_FUNCTION(10, 11)
506 GEN_TEST_FUNCTION(11, 12)
507 GEN_TEST_FUNCTION(12, 13)
508 GEN_TEST_FUNCTION(13, 14)
509 GEN_TEST_FUNCTION(14, 15)
510 GEN_TEST_FUNCTION(15, 16)
511 GEN_TEST_FUNCTION(16, 17)
512 GEN_TEST_FUNCTION(17, 18)
513 GEN_TEST_FUNCTION(18, 19)
514 GEN_TEST_FUNCTION(19, 20)
515
516 GEN_TEST_FUNCTION(20, 21)
517 GEN_TEST_FUNCTION(21, 22)
518 GEN_TEST_FUNCTION(22, 23)
519 GEN_TEST_FUNCTION(23, 24)
520 GEN_TEST_FUNCTION(24, 25)
521 GEN_TEST_FUNCTION(25, 26)
522 GEN_TEST_FUNCTION(26, 27)
523 GEN_TEST_FUNCTION(27, 28)
524 GEN_TEST_FUNCTION(28, 29)
525 GEN_TEST_FUNCTION(29, 30)
526
527 GEN_TEST_FUNCTION(30, 31)
528 GEN_TEST_FUNCTION(31, 32)
529 GEN_TEST_FUNCTION(32, 33)
530 GEN_TEST_FUNCTION(33, 34)
531 GEN_TEST_FUNCTION(34, 35)
532 GEN_TEST_FUNCTION(35, 36)
533 GEN_TEST_FUNCTION(36, 37)
534 GEN_TEST_FUNCTION(37, 38)
535 GEN_TEST_FUNCTION(38, 39)
536 GEN_TEST_FUNCTION(39, 40)
537
538 GEN_TEST_FUNCTION(40, 41)
539 GEN_TEST_FUNCTION(41, 42)
540 GEN_TEST_FUNCTION(42, 43)
541 GEN_TEST_FUNCTION(43, 44)
542 GEN_TEST_FUNCTION(44, 45)
543 GEN_TEST_FUNCTION(45, 46)
544 GEN_TEST_FUNCTION(46, 47)
545 GEN_TEST_FUNCTION(47, 48)
546 GEN_TEST_FUNCTION(48, 49)
547 GEN_TEST_FUNCTION(49, 50)
548
549 GEN_TEST_FUNCTION(50, 51)
550 GEN_TEST_FUNCTION(51, 52)
551 GEN_TEST_FUNCTION(52, 53)
552 GEN_TEST_FUNCTION(53, 54)
553 GEN_TEST_FUNCTION(54, 55)
554 GEN_TEST_FUNCTION(55, 56)
555 GEN_TEST_FUNCTION(56, 57)
556 GEN_TEST_FUNCTION(57, 58)
557 GEN_TEST_FUNCTION(58, 59)
558 GEN_TEST_FUNCTION(59, 60)
559
560 GEN_TEST_FUNCTION(60, 61)
561 GEN_TEST_FUNCTION(61, 62)
562 GEN_TEST_FUNCTION(62, 63)
563 GEN_TEST_FUNCTION(63, 64)
564 GEN_TEST_FUNCTION(64, 65)
565 GEN_TEST_FUNCTION(65, 66)
566 GEN_TEST_FUNCTION(66, 67)
567 GEN_TEST_FUNCTION(67, 68)
568 GEN_TEST_FUNCTION(68, 69)
569 GEN_TEST_FUNCTION(69, 70)
570