• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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