• 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 "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