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