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 };
102
103 if (sigMaps.find(signal) != sigMaps.end()) {
104 return sigMaps[signal];
105 }
106 return "Uncare Signal";
107 }
108
FormatCodeName(const int32_t signal, const int32_t signalCode)109 std::string DfxSignal::FormatCodeName(const int32_t signal, const int32_t signalCode)
110 {
111 switch (signal) {
112 case SIGILL:
113 return FormatSIGILLCodeName(signalCode);
114 case SIGBUS:
115 return FormatSIGBUSCodeName(signalCode);
116 case SIGFPE:
117 return FormatSIGFPECodeName(signalCode);
118 case SIGSEGV:
119 return FormatSIGSEGVCodeName(signalCode);
120 case SIGTRAP:
121 return FormatSIGTRAPCodeName(signalCode);
122 case SIGSYS:
123 return FormatSIGSYSCodeName(signalCode);
124 default:
125 break;
126 }
127 return DfxSignal::FormatCommonSignalCodeName(signalCode);
128 }
129
FormatSIGBUSCodeName(const int32_t signalCode)130 std::string DfxSignal::FormatSIGBUSCodeName(const int32_t signalCode)
131 {
132 switch (signalCode) {
133 case BUS_ADRALN:
134 return "BUS_ADRALN";
135 case BUS_ADRERR:
136 return "BUS_ADRERR";
137 case BUS_OBJERR:
138 return "BUS_OBJERR";
139 case BUS_MCEERR_AR:
140 return "BUS_MCEERR_AR";
141 case BUS_MCEERR_AO:
142 return "BUS_MCEERR_AO";
143 default:
144 return FormatCommonSignalCodeName(signalCode);
145 }
146 }
147
FormatSIGILLCodeName(const int32_t signalCode)148 std::string DfxSignal::FormatSIGILLCodeName(const int32_t signalCode)
149 {
150 switch (signalCode) {
151 case ILL_ILLOPC:
152 return "ILL_ILLOPC";
153 case ILL_ILLOPN:
154 return "ILL_ILLOPN";
155 case ILL_ILLADR:
156 return "ILL_ILLADR";
157 case ILL_ILLTRP:
158 return "ILL_ILLTRP";
159 case ILL_PRVOPC:
160 return "ILL_PRVOPC";
161 case ILL_PRVREG:
162 return "ILL_PRVREG";
163 case ILL_COPROC:
164 return "ILL_COPROC";
165 case ILL_BADSTK:
166 return "ILL_BADSTK";
167 default:
168 return FormatCommonSignalCodeName(signalCode);
169 }
170 }
171
FormatSIGFPECodeName(const int32_t signalCode)172 std::string DfxSignal::FormatSIGFPECodeName(const int32_t signalCode)
173 {
174 switch (signalCode) {
175 case FPE_INTDIV:
176 return "FPE_INTDIV";
177 case FPE_INTOVF:
178 return "FPE_INTOVF";
179 case FPE_FLTDIV:
180 return "FPE_FLTDIV";
181 case FPE_FLTOVF:
182 return "FPE_FLTOVF";
183 case FPE_FLTUND:
184 return "FPE_FLTUND";
185 case FPE_FLTRES:
186 return "FPE_FLTRES";
187 case FPE_FLTINV:
188 return "FPE_FLTINV";
189 case FPE_FLTSUB:
190 return "FPE_FLTSUB";
191 default:
192 return FormatCommonSignalCodeName(signalCode);
193 }
194 }
195
FormatSIGSEGVCodeName(const int32_t signalCode)196 std::string DfxSignal::FormatSIGSEGVCodeName(const int32_t signalCode)
197 {
198 switch (signalCode) {
199 case SEGV_MAPERR:
200 return "SEGV_MAPERR";
201 case SEGV_ACCERR:
202 return "SEGV_ACCERR";
203 default:
204 return FormatCommonSignalCodeName(signalCode);
205 }
206 }
207
FormatSIGTRAPCodeName(const int32_t signalCode)208 std::string DfxSignal::FormatSIGTRAPCodeName(const int32_t signalCode)
209 {
210 switch (signalCode) {
211 case TRAP_BRKPT:
212 return "TRAP_BRKPT";
213 case TRAP_TRACE:
214 return "TRAP_TRACE";
215 case TRAP_BRANCH:
216 return "TRAP_BRANCH";
217 case TRAP_HWBKPT:
218 return "TRAP_HWBKPT";
219 default:
220 return FormatCommonSignalCodeName(signalCode);
221 }
222 }
223
FormatSIGSYSCodeName(const int32_t signalCode)224 std::string DfxSignal::FormatSIGSYSCodeName(const int32_t signalCode)
225 {
226 switch (signalCode) {
227 case SYS_SECCOMP:
228 return "SYS_SECCOMP";
229 default:
230 return FormatCommonSignalCodeName(signalCode);
231 }
232 }
233
FormatCommonSignalCodeName(const int32_t signalCode)234 std::string DfxSignal::FormatCommonSignalCodeName(const int32_t signalCode)
235 {
236 switch (signalCode) {
237 case SI_USER:
238 return "SI_USER";
239 case SI_KERNEL:
240 return "SI_KERNEL";
241 case SI_QUEUE:
242 return "SI_QUEUE";
243 case SI_TIMER:
244 return "SI_TIMER";
245 case SI_MESGQ:
246 return "SI_MESGQ";
247 case SI_ASYNCIO:
248 return "SI_ASYNCIO";
249 case SI_SIGIO:
250 return "SI_SIGIO";
251 case SI_TKILL:
252 return "SI_TKILL";
253 default:
254 return "UNKNOWN";
255 }
256 }
257 } // namespace HiviewDFX
258 } // namespace OHOS
259