1 | // SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd. |
2 | // |
3 | // SPDX-License-Identifier: GPL-3.0-or-later |
4 | |
5 | #include "backtrace.h" |
6 | |
7 | #include <qlogging.h> |
8 | #include <QCoreApplication> |
9 | |
10 | #include <csignal> |
11 | #include <execinfo.h> |
12 | #include <cxxabi.h> |
13 | #include <dlfcn.h> |
14 | #include <sstream> |
15 | |
16 | #define TOSTRING(s) #s |
17 | |
18 | DPF_BEGIN_NAMESPACE |
19 | namespace backtrace { |
20 | |
21 | /*! |
22 | * \brief demangle ABI-mandated entry point in the |
23 | * C++ runtime library for demangling |
24 | * \param value backtrace string |
25 | * \return demangled value |
26 | */ |
27 | std::string demangle(void *value) |
28 | { |
29 | if (!value) |
30 | return "" ; |
31 | |
32 | std::ostringstream ostream; |
33 | ostream.imbue(std::locale::classic()); |
34 | ostream << value << " : " ; |
35 | Dl_info info = {nullptr, nullptr, nullptr, nullptr}; |
36 | if (dladdr(value, &info) == 0) { |
37 | ostream << "???" ; |
38 | } else { |
39 | if (info.dli_sname) { |
40 | int status = 0; |
41 | char *demangledName = abi::__cxa_demangle(info.dli_sname, nullptr, nullptr, &status); |
42 | if (demangledName) { |
43 | ostream << demangledName; |
44 | free(demangledName); |
45 | } else { |
46 | ostream << info.dli_sname; |
47 | } |
48 | } else { |
49 | ostream << "???" ; |
50 | } |
51 | |
52 | long offset = reinterpret_cast<char *>(value) - reinterpret_cast<char *>(info.dli_saddr); |
53 | ostream << std::hex << " + 0x" << offset ; |
54 | |
55 | if (info.dli_fname) |
56 | ostream << " @ " << info.dli_fname; |
57 | } |
58 | return ostream.str(); |
59 | } |
60 | |
61 | /*! |
62 | * \brief logStackInfo |
63 | * \param signal kernel expection signal |
64 | */ |
65 | [[noreturn]] void logStackInfo(int signal) |
66 | { |
67 | const int bufSize = 100; |
68 | void *buffer[bufSize] = {nullptr}; |
69 | int numLine = ::backtrace(buffer, bufSize); |
70 | |
71 | std::string strSig; |
72 | switch (signal) { |
73 | case SIGINT: /* Interactive attention signal. */ |
74 | strSig = TOSTRING(SIGINT); |
75 | break; |
76 | case SIGILL: /* Illegal instruction. */ |
77 | strSig = TOSTRING(SIGILL); |
78 | break; |
79 | case SIGABRT: /* Abnormal termination. */ |
80 | strSig = TOSTRING(SIGABRT); |
81 | break; |
82 | case SIGFPE: /* Erroneous arithmetic operation. */ |
83 | strSig = TOSTRING(SIGFPE); |
84 | break; |
85 | case SIGSEGV: /* Invalid access to storage. */ |
86 | strSig = TOSTRING(SIGSEGV); |
87 | break; |
88 | case SIGTERM: /* Termination request. */ |
89 | strSig = TOSTRING(SIGTERM); |
90 | break; |
91 | default: |
92 | char szTmpBuf[bufSize] = {0}; |
93 | sprintf(szTmpBuf, "No register signal: %d" , signal); |
94 | strSig = szTmpBuf; |
95 | break; |
96 | }; |
97 | QString head,end; |
98 | head = QString("****************** %0 crashed backtrace ******************" ) |
99 | .arg(qApp->applicationName()); |
100 | qCritical("%s" , head.toStdString().data()); |
101 | qCritical("* signal:%s numLine:%d" , strSig.data(), numLine); |
102 | for (int i = 1; i < numLine; ++i) { |
103 | std::string stackInfo = demangle(buffer[i]); |
104 | qCritical("* %d> %s" , i, stackInfo.data()); |
105 | } |
106 | for(int index = head.size(); index > 0; index --) { |
107 | end += "*" ; |
108 | } |
109 | qCritical("%s" , end.toStdString().data()); |
110 | exit(EXIT_FAILURE); |
111 | } |
112 | |
113 | /*! |
114 | * \brief regSignal |
115 | * register sig signal handler. |
116 | * \param sig |
117 | */ |
118 | void regSignal(int sig) |
119 | { |
120 | signal(sig, logStackInfo); |
121 | } |
122 | |
123 | /*! |
124 | * \brief initbacktrace |
125 | * Register signal handler. |
126 | */ |
127 | void initbacktrace() |
128 | { |
129 | regSignal(SIGINT); /* Interactive attention signal. */ |
130 | regSignal(SIGILL); /* Illegal instruction. */ |
131 | regSignal(SIGABRT); /* Abnormal termination. */ |
132 | regSignal(SIGFPE); /* Erroneous arithmetic operation. */ |
133 | regSignal(SIGSEGV); /* Invalid access to storage. */ |
134 | regSignal(SIGTERM); /* Termination request. */ |
135 | } |
136 | } |
137 | DPF_END_NAMESPACE |
138 | |