1 /*
2 * Copyright (c) 2021-2023 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_signal.h"
17
18 #include <map>
19 #include <securec.h>
20 #include <string>
21 #include "dfx_define.h"
22 #include "dfx_log.h"
23 #include "string_printf.h"
24
25 namespace OHOS {
26 namespace HiviewDFX {
27 namespace {
28 #undef LOG_DOMAIN
29 #undef LOG_TAG
30 #define LOG_DOMAIN 0xD002D11
31 #define LOG_TAG "DfxSignal"
32 }
33
IsAvailable() const34 bool DfxSignal::IsAvailable() const
35 {
36 struct sigaction prevAction;
37 if (sigaction(signal_, nullptr, &prevAction) < 0) {
38 return 0;
39 }
40 return static_cast<unsigned int>(prevAction.sa_flags) & SA_SIGINFO;
41 }
42
IsAddrAvailable() const43 bool DfxSignal::IsAddrAvailable() const
44 {
45 switch (signal_) {
46 case SIGABRT:
47 case SIGBUS:
48 case SIGILL:
49 case SIGSEGV:
50 case SIGTRAP:
51 return true;
52 default:
53 return false;
54 }
55 }
56
IsPidAvailable() const57 bool DfxSignal::IsPidAvailable() const
58 {
59 switch (signal_) {
60 case SI_USER:
61 case SI_QUEUE:
62 case SI_TIMER:
63 case SI_ASYNCIO:
64 case SI_MESGQ:
65 return true;
66 default:
67 return false;
68 }
69 }
70
PrintSignal(const siginfo_t & info)71 std::string DfxSignal::PrintSignal(const siginfo_t &info)
72 {
73 std::string sigString = StringPrintf("Signal:%s(%s)", FormatSignalName(info.si_signo).c_str(),\
74 FormatCodeName(info.si_signo, info.si_code).c_str());
75
76 DfxSignal signal(info.si_signo);
77 if (signal.IsAddrAvailable()) {
78 sigString = sigString + StringPrintf("@%" PRIX64_ADDR " ", (uint64_t)info.si_addr);
79 }
80
81 if ((info.si_code <= 0) && (info.si_pid != 0)) {
82 sigString = sigString + StringPrintf("from:%d:%u", info.si_pid, info.si_uid);
83 }
84
85 return sigString;
86 }
87
FormatSignalName(const int32_t signal)88 std::string DfxSignal::FormatSignalName(const int32_t signal)
89 {
90 std::map<int32_t, std::string> sigMaps = {
91 { SIGILL, std::string("SIGILL") },
92 { SIGTRAP, std::string("SIGTRAP") },
93 { SIGABRT, std::string("SIGABRT") },
94 { SIGALRM, std::string("SIGALRM") },
95 { SIGBUS, std::string("SIGBUS") },
96 { SIGFPE, std::string("SIGFPE") },
97 { SIGSEGV, std::string("SIGSEGV") },
98 { SIGSTKFLT, std::string("SIGSTKFLT") },
99 { SIGSYS, std::string("SIGSYS") },
100 { SIGDUMP, std::string("SIGDUMP") },
101 { SIGLEAK_STACK, std::string("DEBUG SIGNAL") },
102 };
103
104 if (sigMaps.find(signal) != sigMaps.end()) {
105 return sigMaps[signal];
106 }
107 return "Uncare Signal";
108 }
109
FormatCodeName(const int32_t signal,const int32_t signalCode)110 std::string DfxSignal::FormatCodeName(const int32_t signal, const int32_t signalCode)
111 {
112 switch (signal) {
113 case SIGILL:
114 return FormatSIGILLCodeName(signalCode);
115 case SIGBUS:
116 return FormatSIGBUSCodeName(signalCode);
117 case SIGFPE:
118 return FormatSIGFPECodeName(signalCode);
119 case SIGSEGV:
120 return FormatSIGSEGVCodeName(signalCode);
121 case SIGTRAP:
122 return FormatSIGTRAPCodeName(signalCode);
123 case SIGSYS:
124 return FormatSIGSYSCodeName(signalCode);
125 case SIGLEAK_STACK:
126 return FormatSIGLEAKCodeName(signalCode);
127 default:
128 break;
129 }
130 return DfxSignal::FormatCommonSignalCodeName(signalCode);
131 }
132
FormatSIGBUSCodeName(const int32_t signalCode)133 std::string DfxSignal::FormatSIGBUSCodeName(const int32_t signalCode)
134 {
135 switch (signalCode) {
136 case BUS_ADRALN:
137 return "BUS_ADRALN";
138 case BUS_ADRERR:
139 return "BUS_ADRERR";
140 case BUS_OBJERR:
141 return "BUS_OBJERR";
142 case BUS_MCEERR_AR:
143 return "BUS_MCEERR_AR";
144 case BUS_MCEERR_AO:
145 return "BUS_MCEERR_AO";
146 default:
147 return FormatCommonSignalCodeName(signalCode);
148 }
149 }
150
FormatSIGILLCodeName(const int32_t signalCode)151 std::string DfxSignal::FormatSIGILLCodeName(const int32_t signalCode)
152 {
153 switch (signalCode) {
154 case ILL_ILLOPC:
155 return "ILL_ILLOPC";
156 case ILL_ILLOPN:
157 return "ILL_ILLOPN";
158 case ILL_ILLADR:
159 return "ILL_ILLADR";
160 case ILL_ILLTRP:
161 return "ILL_ILLTRP";
162 case ILL_PRVOPC:
163 return "ILL_PRVOPC";
164 case ILL_PRVREG:
165 return "ILL_PRVREG";
166 case ILL_COPROC:
167 return "ILL_COPROC";
168 case ILL_BADSTK:
169 return "ILL_BADSTK";
170 default:
171 return FormatCommonSignalCodeName(signalCode);
172 }
173 }
174
FormatSIGFPECodeName(const int32_t signalCode)175 std::string DfxSignal::FormatSIGFPECodeName(const int32_t signalCode)
176 {
177 switch (signalCode) {
178 case FPE_INTDIV:
179 return "FPE_INTDIV";
180 case FPE_INTOVF:
181 return "FPE_INTOVF";
182 case FPE_FLTDIV:
183 return "FPE_FLTDIV";
184 case FPE_FLTOVF:
185 return "FPE_FLTOVF";
186 case FPE_FLTUND:
187 return "FPE_FLTUND";
188 case FPE_FLTRES:
189 return "FPE_FLTRES";
190 case FPE_FLTINV:
191 return "FPE_FLTINV";
192 case FPE_FLTSUB:
193 return "FPE_FLTSUB";
194 default:
195 return FormatCommonSignalCodeName(signalCode);
196 }
197 }
198
FormatSIGSEGVCodeName(const int32_t signalCode)199 std::string DfxSignal::FormatSIGSEGVCodeName(const int32_t signalCode)
200 {
201 switch (signalCode) {
202 case SEGV_MAPERR:
203 return "SEGV_MAPERR";
204 case SEGV_ACCERR:
205 return "SEGV_ACCERR";
206 default:
207 return FormatCommonSignalCodeName(signalCode);
208 }
209 }
210
FormatSIGTRAPCodeName(const int32_t signalCode)211 std::string DfxSignal::FormatSIGTRAPCodeName(const int32_t signalCode)
212 {
213 switch (signalCode) {
214 case TRAP_BRKPT:
215 return "TRAP_BRKPT";
216 case TRAP_TRACE:
217 return "TRAP_TRACE";
218 case TRAP_BRANCH:
219 return "TRAP_BRANCH";
220 case TRAP_HWBKPT:
221 return "TRAP_HWBKPT";
222 default:
223 return FormatCommonSignalCodeName(signalCode);
224 }
225 }
226
FormatSIGSYSCodeName(const int32_t signalCode)227 std::string DfxSignal::FormatSIGSYSCodeName(const int32_t signalCode)
228 {
229 switch (signalCode) {
230 case SYS_SECCOMP:
231 return "SYS_SECCOMP";
232 default:
233 return FormatCommonSignalCodeName(signalCode);
234 }
235 }
236
FormatSIGLEAKCodeName(const int32_t signalCode)237 std::string DfxSignal::FormatSIGLEAKCodeName(const int32_t signalCode)
238 {
239 switch (signalCode) {
240 case SIGLEAK_STACK_FDSAN:
241 return "FDSAN";
242 case SIGLEAK_STACK_JEMALLOC:
243 return "JEMALLOC";
244 case SIGLEAK_STACK_BADFD:
245 return "BADFD";
246 default:
247 return FormatCommonSignalCodeName(signalCode);
248 }
249 }
250
FormatCommonSignalCodeName(const int32_t signalCode)251 std::string DfxSignal::FormatCommonSignalCodeName(const int32_t signalCode)
252 {
253 switch (signalCode) {
254 case SI_USER:
255 return "SI_USER";
256 case SI_KERNEL:
257 return "SI_KERNEL";
258 case SI_QUEUE:
259 return "SI_QUEUE";
260 case SI_TIMER:
261 return "SI_TIMER";
262 case SI_MESGQ:
263 return "SI_MESGQ";
264 case SI_ASYNCIO:
265 return "SI_ASYNCIO";
266 case SI_SIGIO:
267 return "SI_SIGIO";
268 case SI_TKILL:
269 return "SI_TKILL";
270 default:
271 return "UNKNOWN";
272 }
273 }
274 } // namespace HiviewDFX
275 } // namespace OHOS
276