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