• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021-2022 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 /* This files contains faultlog cpp crasher modules. */
17 
18 #include "dfx_crasher.h"
19 
20 #include <cinttypes>
21 #include <csignal>
22 #include <cstdio>
23 #include <cstdlib>
24 #include <cstring>
25 #include <fstream>
26 #include <hilog/log.h>
27 #include <iostream>
28 #include <pthread.h>
29 #include <sys/prctl.h>
30 #include <sys/resource.h>
31 #include <thread>
32 #include <unistd.h>
33 #include <vector>
34 #include "securec.h"
35 
36 #ifdef HAS_HITRACE
37 #include <hitrace/hitracechain.h>
38 using namespace OHOS::HiviewDFX;
39 #endif
40 
41 #ifdef LOG_DOMAIN
42 #undef LOG_DOMAIN
43 #define LOG_DOMAIN 0xD002D11
44 #endif
45 
46 #ifdef LOG_TAG
47 #undef LOG_TAG
48 #define LOG_TAG "Unwind"
49 #endif
50 
51 static const int ARG1024 = 1024;
52 static const int ARG128 = 128;
53 
54 static const int NUMBER_TWO = 2;
55 static const int NUMBER_ONE = 1;
56 
57 static const int SIGDUMP = 35;
58 
DfxCrasher()59 DfxCrasher::DfxCrasher() {}
~DfxCrasher()60 DfxCrasher::~DfxCrasher() {}
61 
GetInstance()62 DfxCrasher &DfxCrasher::GetInstance()
63 {
64     static DfxCrasher instance;
65     return instance;
66 }
67 
TriggerTrapException() const68 NOINLINE int DfxCrasher::TriggerTrapException() const
69 {
70     __asm__ volatile(".inst 0xde01");
71 
72     return 0;
73 }
74 
TriggerSegmentFaultException() const75 NOINLINE int DfxCrasher::TriggerSegmentFaultException() const
76 {
77     std::cout << "test TriggerSegmentFaultException" << std::endl;
78     // for crash test force cast the type
79     int *a = (int *)(&TestFunc70);
80     *a = SIGSEGV;
81     return 0;
82 }
83 
RaiseAbort() const84 NOINLINE int DfxCrasher::RaiseAbort() const
85 {
86     HILOG_FATAL(LOG_CORE, "Test Trigger ABORT!");
87     raise(SIGABRT);
88     return 0;
89 }
90 
Abort(void) const91 NOINLINE int DfxCrasher::Abort(void) const
92 {
93     HILOG_FATAL(LOG_CORE, "Test Trigger ABORT!");
94     abort();
95     return 0;
96 }
97 
RaiseBusError() const98 NOINLINE int DfxCrasher::RaiseBusError() const
99 {
100     raise(SIGBUS);
101     return 0;
102 }
103 
DumpStackTrace() const104 NOINLINE int DfxCrasher::DumpStackTrace() const
105 {
106     if (raise(SIGDUMP) != 0) {
107         std::cout << "raise error" << std::endl;
108     }
109     return 0;
110 }
111 
RaiseFloatingPointException() const112 NOINLINE int DfxCrasher::RaiseFloatingPointException() const
113 {
114     raise(SIGFPE);
115     return 0;
116 }
117 
RaiseIllegalInstructionException() const118 NOINLINE int DfxCrasher::RaiseIllegalInstructionException() const
119 {
120     raise(SIGILL);
121     return 0;
122 }
123 
IllegalInstructionException(void) const124 NOINLINE int DfxCrasher::IllegalInstructionException(void) const
125 {
126     char mes[] = "ABCDEFGHIJ";
127     char* ptr = mes;
128     ptr = nullptr;
129     *ptr = 0;
130 
131     return 0;
132 }
133 
SegmentFaultException(void) const134 NOINLINE int DfxCrasher::SegmentFaultException(void) const
135 {
136     volatile char *ptr = nullptr;
137     *ptr;
138 
139     return 0;
140 }
141 
RaiseSegmentFaultException() const142 NOINLINE int DfxCrasher::RaiseSegmentFaultException() const
143 {
144     std::cout << "call RaiseSegmentFaultException" << std::endl;
145     raise(SIGSEGV);
146     return 0;
147 }
148 
RaiseTrapException() const149 NOINLINE int DfxCrasher::RaiseTrapException() const
150 {
151     raise(SIGTRAP);
152     return 0;
153 }
154 
MaxStackDepth() const155 NOINLINE int DfxCrasher::MaxStackDepth() const
156 {
157     return TestFunc1();
158 }
159 
MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC() const160 NOINLINE int DfxCrasher::MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC() const
161 {
162     std::cout << "call MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC" << std::endl;
163     raise(SIGSEGV);
164     return 0;
165 }
166 
StackOverflow() const167 NOINLINE int DfxCrasher::StackOverflow() const
168 {
169     std::cout << "call StackOverflow" << std::endl;
170     // for stack overflow test
171     char a[1024][1024][1024] = { { {'1'} } };
172     char b[1024][1024][1024] = { { {'1'} } };
173     char c[1024][1024][1024] = { { {'1'} } };
174     char d[1024][1024][1024] = { { {'1'} } };
175 
176     std::cout << a[0][0] << std::endl;
177     std::cout << b[0][0] << std::endl;
178     std::cout << c[0][0] << std::endl;
179     std::cout << d[0][0] << std::endl;
180 
181     return 0;
182 }
183 
Oom() const184 NOINLINE int DfxCrasher::Oom() const
185 {
186     std::cout << "test oom" << std::endl;
187     struct rlimit oldRlimit;
188     if (getrlimit(RLIMIT_AS, &oldRlimit) != 0) {
189         std::cout << "getrlimit failed" << std::endl;
190         raise(SIGINT);
191     }
192     std::cout << std::hex << "old rlimit, cur:0x" << oldRlimit.rlim_cur << std::endl;
193     std::cout << std::hex << "old rlimit, max:0x" << oldRlimit.rlim_max << std::endl;
194 
195     struct rlimit rlim = {
196         .rlim_cur = ARG128 * ARG1024 * ARG1024,
197         .rlim_max = ARG128 * ARG1024 * ARG1024,
198     };
199 
200     if (setrlimit(RLIMIT_AS, &rlim) != 0) {
201         std::cout << "setrlimit failed" << std::endl;
202         raise(SIGINT);
203     }
204 
205     std::vector<void*> vec;
206     for (int i = 0; i < ARG128; i++) {
207         char* buf = static_cast<char*>(malloc(ARG1024 * ARG1024));
208         if (!buf) {
209             std::cout << "malloc return null" << std::endl;
210             if (setrlimit(RLIMIT_AS, &oldRlimit) != 0) {
211                 std::cout << "restore rlimit failed" << std::endl;
212             }
213             std::cout << "restore rlimit ok" << std::endl;
214             abort();
215         }
216 
217         if (memset_s(buf, ARG1024 * ARG1024, 0xff, ARG1024 * ARG1024)) {
218             std::cout << "oom memset_s failed." << std::endl;
219         }
220         vec.push_back(buf);
221     }
222     return 0;
223 }
224 
ProgramCounterZero() const225 NOINLINE int DfxCrasher::ProgramCounterZero() const
226 {
227     std::cout << "test PCZero" << std::endl;
228 #if defined(__arm__)
229     __asm__ volatile (
230         "mov r0, #0x00\n mov lr, pc\n bx r0\n"
231     );
232 #elif defined(__aarch64__)
233     __asm__ volatile (
234         "movz x0, #0x0\n"
235         "adr x30, .\n"
236         "br x0\n"
237     );
238 #endif
239     return 0;
240 }
241 
MultiThreadCrash() const242 NOINLINE int DfxCrasher::MultiThreadCrash() const
243 {
244     std::cout << "test MultiThreadCrash" << std::endl;
245 
246     std::thread (SleepThread, NUMBER_ONE).detach();
247     std::thread (SleepThread, NUMBER_TWO).detach();
248     sleep(1);
249 
250     raise(SIGSEGV);
251 
252     return 0;
253 }
254 
StackOver64() const255 NOINLINE int DfxCrasher::StackOver64() const
256 {
257     std::cout << "test StackOver64" << std::endl;
258 
259     return TestFunc1();
260 }
261 
SleepThread(int threadID)262 int SleepThread(int threadID)
263 {
264     std::cout << "create MultiThread " <<  threadID << std::endl;
265 
266     int sleepTime = 10;
267     sleep(sleepTime);
268 
269     return 0;
270 }
271 
StackTop() const272 NOINLINE int DfxCrasher::StackTop() const
273 {
274     std::cout << "test StackTop" << std::endl;
275 #if defined(__arm__)
276     unsigned int stackTop;
277     __asm__ volatile ("mov %0, sp":"=r"(stackTop)::);
278 #elif defined(__aarch64__)
279     uint64_t stackTop;
280     __asm__ volatile ("mov %0, sp":"=r"(stackTop)::);
281 #endif
282     std::cout << "crasher_c: stack top is = " << std::hex << stackTop << std::endl;
283 
284     std::ofstream fout;
285     fout.open("sp");
286     fout << std::hex << stackTop << std::endl;
287     fout.close();
288 
289     // trigger an error to crash
290     int a = 1;
291     int *b = &a;
292     b = nullptr;
293     *b = 1;
294 
295     return 0;
296 }
297 
PrintUsage() const298 void DfxCrasher::PrintUsage() const
299 {
300     std::cout << "  usage: crasher CMD" << std::endl;
301     std::cout << "" << std::endl;
302     std::cout << "  where CMD support:" << std::endl;
303     std::cout << "  SIGFPE                raise a SIGFPE" << std::endl;
304     std::cout << "  SIGILL                raise a SIGILL" << std::endl;
305     std::cout << "  SIGSEGV               raise a SIGSEGV" << std::endl;
306     std::cout << "  SIGTRAP               raise a SIGTRAP" << std::endl;
307     std::cout << "  SIGABRT               raise a SIGABRT" << std::endl;
308     std::cout << "  SIGBUS                raise a SIGBUS" << std::endl;
309     std::cout << "  STACKTRACE            raise a SIGDUMP" << std::endl;
310 
311     std::cout << "  triSIGILL             trigger a SIGILL\n" << std::endl;
312     std::cout << "  triSIGSEGV            trigger a SIGSEGV\n" << std::endl;
313     std::cout << "  triSIGTRAP            trigger a SIGTRAP\n" << std::endl;
314     std::cout << "  triSIGABRT            trigger a SIGABRT\n" << std::endl;
315 
316     std::cout << "  Loop                  trigger a ForeverLoop" << std::endl;
317     std::cout << "  MaxStack              trigger SIGSEGV after 64 function call" << std::endl;
318     std::cout << "  MaxMethod             trigger SIGSEGV after call a function with longer name" << std::endl;
319     std::cout << "  STACKOF               trigger a stack overflow" << std::endl;
320     std::cout << "  OOM                   trigger out of memory" << std::endl;
321     std::cout << "  PCZero                trigger pc = 0" << std::endl;
322     std::cout << "  MTCrash               trigger crash with multi-thread" << std::endl;
323     std::cout << "  StackOver64           trigger SIGSEGV after 70 function call" << std::endl;
324     std::cout << "  StackTop              trigger SIGSEGV to make sure stack top" << std::endl;
325     std::cout << "  if you want the command execute in a sub thread" << std::endl;
326     std::cout << "  add thread Prefix, e.g crasher thread-SIGFPE" << std::endl;
327     std::cout << std::endl;
328 }
329 
CrashInLambda()330 NOINLINE static uint64_t CrashInLambda()
331 {
332     std::function<void()> lambda = TestFunc50;
333     lambda();
334     return 0;
335 }
336 
DoDumpCrash()337 NOINLINE static uint64_t DoDumpCrash()
338 {
339     std::thread t(TestFunc1);
340     raise(SIGDUMP);
341     t.join();
342     return 0;
343 }
344 
TestExitHook()345 NOINLINE static uint64_t TestExitHook()
346 {
347     exit(1);
348     return 0;
349 }
350 
SigHookHandler(int signo)351 void SigHookHandler(int signo)
352 {
353     printf("SigHookHandler:%d\n", signo);
354 }
355 
TestSigHook()356 NOINLINE static uint64_t TestSigHook()
357 {
358     signal(SIGSEGV, SigHookHandler);
359     return 0;
360 }
361 
DoCrashInThread(void * inputArg)362 void* DfxCrasher::DoCrashInThread(void * inputArg)
363 {
364     prctl(PR_SET_NAME, "SubTestThread");
365     const char* arg = (const char *)(inputArg);
366     return (void*)(DfxCrasher::GetInstance().ParseAndDoCrash(arg));
367 }
368 
DoActionOnSubThread(const char * arg) const369 uint64_t DfxCrasher::DoActionOnSubThread(const char *arg) const
370 {
371     pthread_t t;
372     pthread_create(&t, nullptr, DfxCrasher::DoCrashInThread, const_cast<char*>(arg));
373     void *result = nullptr;
374     pthread_join(t, &result);
375     return (uint64_t)(result);
376 }
377 
ParseAndDoCrash(const char * arg)378 uint64_t DfxCrasher::ParseAndDoCrash(const char *arg)
379 {
380     // Prefix
381     if (!strncmp(arg, "thread-", strlen("thread-"))) {
382         return DoActionOnSubThread(arg + strlen("thread-"));
383     }
384 #ifdef HAS_HITRACE
385     auto beginId = HiTraceChain::Begin("test", HITRACE_FLAG_NO_BE_INFO);
386 #endif
387     // Action
388     if (!strcasecmp(arg, "SIGFPE")) {
389         return RaiseFloatingPointException();
390     }
391 
392     if (!strcasecmp(arg, "SIGILL")) {
393         return RaiseIllegalInstructionException();
394     }
395 
396     if (!strcasecmp(arg, "SIGSEGV")) {
397         return RaiseSegmentFaultException();
398     }
399 
400     if (!strcasecmp(arg, "SIGTRAP")) {
401         return RaiseTrapException();
402     }
403 
404     if (!strcasecmp(arg, "triSIGILL")) {
405         return IllegalInstructionException();
406     }
407 
408     if (!strcasecmp(arg, "SIGABRT")) {
409         return RaiseAbort();
410     }
411 
412     if (!strcasecmp(arg, "triSIGABRT")) {
413         return Abort();
414     }
415 
416     if (!strcasecmp(arg, "SIGBUS")) {
417         return RaiseBusError();
418     }
419 
420     if (!strcasecmp(arg, "STACKTRACE")) {
421         return DumpStackTrace();
422     }
423 
424     if (!strcasecmp(arg, "triSIGTRAP")) {
425         return TriggerTrapException();
426     }
427 
428     if (!strcasecmp(arg, "Loop")) {
429         int i = 0;
430         while (1) {
431             usleep(10000); // 10000:sleep 0.01 second
432             i++;
433         }
434     }
435 
436     if (!strcasecmp(arg, "triSIGSEGV")) {
437         return SegmentFaultException();
438     }
439 
440     if (!strcasecmp(arg, "MaxStack")) {
441         return MaxStackDepth();
442     }
443 
444     if (!strcasecmp(arg, "MaxMethod")) {
445         return MaxMethodNameTest12345678901234567890123456789012345678901234567890ABC();
446     }
447 
448     if (!strcasecmp(arg, "STACKOF")) {
449         return StackOverflow();
450     }
451 
452     if (!strcasecmp(arg, "OOM")) {
453         return Oom();
454     }
455 
456     if (!strcasecmp(arg, "PCZero")) {
457         return ProgramCounterZero();
458     }
459 
460     if (!strcasecmp(arg, "MTCrash")) {
461         return MultiThreadCrash();
462     }
463 
464     if (!strcasecmp(arg, "StackOver64")) {
465         return StackOver64();
466     }
467 
468     if (!strcasecmp(arg, "StackTop")) {
469         return StackTop();
470     }
471 
472     if (!strcasecmp(arg, "DumpCrash")) {
473         return DoDumpCrash();
474     }
475 
476     if (!strcasecmp(arg, "CrashInLambda")) {
477         return CrashInLambda();
478     }
479 
480     if (!strcasecmp(arg, "ExitHook")) {
481         return TestExitHook();
482     }
483 
484     if (!strcasecmp(arg, "SigHook")) {
485         return TestSigHook();
486     }
487 #ifdef HAS_HITRACE
488     HiTraceChain::End(beginId);
489 #endif
490     return 0;
491 }
492 
TestFunc70()493 NOINLINE int TestFunc70()
494 {
495     raise(SIGSEGV);
496     return 0;
497 }
498 
main(int argc,char * argv[])499 int main(int argc, char *argv[])
500 {
501     DfxCrasher::GetInstance().PrintUsage();
502     if (argc <= 1) {
503         std::cout << "wrong usage!";
504         DfxCrasher::GetInstance().PrintUsage();
505         return 0;
506     }
507 
508     std::cout << "ParseAndDoCrash done:" << DfxCrasher::GetInstance().ParseAndDoCrash(argv[1]) << "!\n";
509     return 0;
510 }
511 
512 // auto gen function
513 GEN_TEST_FUNCTION(0, 1)
514 GEN_TEST_FUNCTION(1, 2)
515 GEN_TEST_FUNCTION(2, 3)
516 GEN_TEST_FUNCTION(3, 4)
517 GEN_TEST_FUNCTION(4, 5)
518 GEN_TEST_FUNCTION(5, 6)
519 GEN_TEST_FUNCTION(6, 7)
520 GEN_TEST_FUNCTION(7, 8)
521 GEN_TEST_FUNCTION(8, 9)
522 GEN_TEST_FUNCTION(9, 10)
523 
524 GEN_TEST_FUNCTION(10, 11)
525 GEN_TEST_FUNCTION(11, 12)
526 GEN_TEST_FUNCTION(12, 13)
527 GEN_TEST_FUNCTION(13, 14)
528 GEN_TEST_FUNCTION(14, 15)
529 GEN_TEST_FUNCTION(15, 16)
530 GEN_TEST_FUNCTION(16, 17)
531 GEN_TEST_FUNCTION(17, 18)
532 GEN_TEST_FUNCTION(18, 19)
533 GEN_TEST_FUNCTION(19, 20)
534 
535 GEN_TEST_FUNCTION(20, 21)
536 GEN_TEST_FUNCTION(21, 22)
537 GEN_TEST_FUNCTION(22, 23)
538 GEN_TEST_FUNCTION(23, 24)
539 GEN_TEST_FUNCTION(24, 25)
540 GEN_TEST_FUNCTION(25, 26)
541 GEN_TEST_FUNCTION(26, 27)
542 GEN_TEST_FUNCTION(27, 28)
543 GEN_TEST_FUNCTION(28, 29)
544 GEN_TEST_FUNCTION(29, 30)
545 
546 GEN_TEST_FUNCTION(30, 31)
547 GEN_TEST_FUNCTION(31, 32)
548 GEN_TEST_FUNCTION(32, 33)
549 GEN_TEST_FUNCTION(33, 34)
550 GEN_TEST_FUNCTION(34, 35)
551 GEN_TEST_FUNCTION(35, 36)
552 GEN_TEST_FUNCTION(36, 37)
553 GEN_TEST_FUNCTION(37, 38)
554 GEN_TEST_FUNCTION(38, 39)
555 GEN_TEST_FUNCTION(39, 40)
556 
557 GEN_TEST_FUNCTION(40, 41)
558 GEN_TEST_FUNCTION(41, 42)
559 GEN_TEST_FUNCTION(42, 43)
560 GEN_TEST_FUNCTION(43, 44)
561 GEN_TEST_FUNCTION(44, 45)
562 GEN_TEST_FUNCTION(45, 46)
563 GEN_TEST_FUNCTION(46, 47)
564 GEN_TEST_FUNCTION(47, 48)
565 GEN_TEST_FUNCTION(48, 49)
566 GEN_TEST_FUNCTION(49, 50)
567 
568 GEN_TEST_FUNCTION(50, 51)
569 GEN_TEST_FUNCTION(51, 52)
570 GEN_TEST_FUNCTION(52, 53)
571 GEN_TEST_FUNCTION(53, 54)
572 GEN_TEST_FUNCTION(54, 55)
573 GEN_TEST_FUNCTION(55, 56)
574 GEN_TEST_FUNCTION(56, 57)
575 GEN_TEST_FUNCTION(57, 58)
576 GEN_TEST_FUNCTION(58, 59)
577 GEN_TEST_FUNCTION(59, 60)
578 
579 GEN_TEST_FUNCTION(60, 61)
580 GEN_TEST_FUNCTION(61, 62)
581 GEN_TEST_FUNCTION(62, 63)
582 GEN_TEST_FUNCTION(63, 64)
583 GEN_TEST_FUNCTION(64, 65)
584 GEN_TEST_FUNCTION(65, 66)
585 GEN_TEST_FUNCTION(66, 67)
586 GEN_TEST_FUNCTION(67, 68)
587 GEN_TEST_FUNCTION(68, 69)
588 GEN_TEST_FUNCTION(69, 70)
589