1 /*
2  * Copyright (c) 2021 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 "signal_info.h"
17 
18 #include <csignal>
19 #include <iomanip>
20 #include <sstream>
21 
22 namespace OHOS {
23 namespace HiviewDFX {
FormatSignalInfo(std::stringstream & ss,const siginfo_t & siginfo)24 void SignalInfo::FormatSignalInfo(std::stringstream &ss, const siginfo_t &siginfo)
25 {
26     int32_t signo = siginfo.si_signo;
27     int32_t code = siginfo.si_code;
28     ss << "Signal:" << FormatSignalName(signo) << "(" << FormatCodeName(signo, code) << ")";
29     if (IsSignalAddrAvaliable(signo)) {
30         ss << "@" << std::setw(8) << std::setfill('0') << std::hex << siginfo.si_addr << " "; // 8 : bit width
31     }
32 
33     if (SI_FROMUSER(&siginfo) && (siginfo.si_pid != 0)) {
34         ss << "form:" << std::to_string(siginfo.si_pid) << ":" << std::to_string(siginfo.si_uid);
35     }
36 }
37 
IsSignalInfoAvaliable(int32_t signal)38 bool SignalInfo::IsSignalInfoAvaliable(int32_t signal)
39 {
40     struct sigaction previousAction;
41     if (sigaction(signal, nullptr, &previousAction) < 0) {
42         return false;
43     }
44     return (static_cast<uint32_t>(previousAction.sa_flags) & SA_SIGINFO) != 0;
45 }
46 
IsSignalAddrAvaliable(int32_t signal)47 bool SignalInfo::IsSignalAddrAvaliable(int32_t signal)
48 {
49     return ((signal == SIGABRT) || (signal == SIGBUS) || (signal == SIGILL)
50         || (signal == SIGSEGV) || (signal == SIGTRAP));
51 }
52 
IsSignalPidAvaliable(int32_t sigCode)53 bool SignalInfo::IsSignalPidAvaliable(int32_t sigCode)
54 {
55     switch (sigCode) {
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 
FormatSignalName(int32_t signal)67 std::string SignalInfo::FormatSignalName(int32_t signal)
68 {
69     switch (signal) {
70         case SIGABRT:
71             return "SIGABRT";
72         case SIGALRM:
73             return "SIGALRM";
74         case SIGBUS:
75             return "SIGBUS";
76         case SIGFPE:
77             return "SIGFPE";
78         case SIGILL:
79             return "SIGILL";
80         case SIGSEGV:
81             return "SIGSEGV";
82         case SIGSYS:
83             return "SIGSYS";
84         case SIGTRAP:
85             return "SIGTRAP";
86         default:
87             return "Uncare Signal";
88     }
89 }
90 
FormatSIGBUSCodeName(int32_t signalCode)91 std::string SignalInfo::FormatSIGBUSCodeName(int32_t signalCode)
92 {
93     std::stringstream codeName;
94     switch (signalCode) {
95         case BUS_ADRALN:
96             codeName << "BUS_ADRALN";
97             break;
98         case BUS_ADRERR:
99             codeName << "BUS_ADRERR";
100             break;
101         case BUS_OBJERR:
102             codeName << "BUS_OBJERR";
103             break;
104         case BUS_MCEERR_AR:
105             codeName << "BUS_MCEERR_AR";
106             break;
107         case BUS_MCEERR_AO:
108             codeName << "BUS_MCEERR_AO";
109             break;
110         default:
111             codeName << FormatCommonSignalCodeName(signalCode);
112             break;
113     }
114     return codeName.str();
115 }
116 
FormatSIGILLCodeName(int32_t signalCode)117 std::string SignalInfo::FormatSIGILLCodeName(int32_t signalCode)
118 {
119     std::stringstream codeName;
120     switch (signalCode) {
121         case ILL_ILLOPC:
122             codeName << "ILL_ILLOPC";
123             break;
124         case ILL_ILLOPN:
125             codeName << "ILL_ILLOPN";
126             break;
127         case ILL_ILLADR:
128             codeName << "ILL_ILLADR";
129             break;
130         case ILL_ILLTRP:
131             codeName << "ILL_ILLTRP";
132             break;
133         case ILL_PRVOPC:
134             codeName << "ILL_PRVOPC";
135             break;
136         case ILL_PRVREG:
137             codeName << "ILL_PRVREG";
138             break;
139         case ILL_COPROC:
140             codeName << "ILL_COPROC";
141             break;
142         case ILL_BADSTK:
143             codeName << "ILL_BADSTK";
144             break;
145         default:
146             codeName << FormatCommonSignalCodeName(signalCode);
147             break;
148     }
149     return codeName.str();
150 }
151 
FormatSIGFPECodeName(int32_t signalCode)152 std::string SignalInfo::FormatSIGFPECodeName(int32_t signalCode)
153 {
154     std::stringstream codeName;
155     switch (signalCode) {
156         case FPE_INTDIV:
157             codeName << "FPE_INTDIV";
158             break;
159         case FPE_INTOVF:
160             codeName << "FPE_INTOVF";
161             break;
162         case FPE_FLTDIV:
163             codeName << "FPE_FLTDIV";
164             break;
165         case FPE_FLTOVF:
166             codeName << "FPE_FLTOVF";
167             break;
168         case FPE_FLTUND:
169             codeName << "FPE_FLTUND";
170             break;
171         case FPE_FLTRES:
172             codeName << "FPE_FLTRES";
173             break;
174         case FPE_FLTINV:
175             codeName << "FPE_FLTINV";
176             break;
177         case FPE_FLTSUB:
178             codeName << "FPE_FLTSUB";
179             break;
180         default:
181             codeName << FormatCommonSignalCodeName(signalCode);
182             break;
183     }
184     return codeName.str();
185 }
186 
FormatSIGSEGVCodeName(int32_t signalCode)187 std::string SignalInfo::FormatSIGSEGVCodeName(int32_t signalCode)
188 {
189     std::stringstream codeName;
190     switch (signalCode) {
191         case SEGV_MAPERR:
192             codeName << "SEGV_MAPERR";
193             break;
194         case SEGV_ACCERR:
195             codeName << "SEGV_ACCERR";
196             break;
197         default:
198             codeName << FormatCommonSignalCodeName(signalCode);
199             break;
200     }
201     return codeName.str();
202 }
203 
FormatSIGTRAPCodeName(int32_t signalCode)204 std::string SignalInfo::FormatSIGTRAPCodeName(int32_t signalCode)
205 {
206     std::stringstream codeName;
207     switch (signalCode) {
208         case TRAP_BRKPT:
209             codeName << "TRAP_BRKPT";
210             break;
211         case TRAP_TRACE:
212             codeName << "TRAP_TRACE";
213             break;
214         case TRAP_BRANCH:
215             codeName << "TRAP_BRANCH";
216             break;
217         case TRAP_HWBKPT:
218             codeName << "TRAP_HWBKPT";
219             break;
220         default:
221             codeName << FormatCommonSignalCodeName(signalCode);
222             break;
223     }
224     return codeName.str();
225 }
226 
FormatCommonSignalCodeName(int32_t signalCode)227 std::string SignalInfo::FormatCommonSignalCodeName(int32_t signalCode)
228 {
229     std::stringstream codeName;
230     switch (signalCode) {
231         case SI_USER:
232             codeName << "SI_USER";
233             break;
234         case SI_KERNEL:
235             codeName << "SI_KERNEL";
236             break;
237         case SI_QUEUE:
238             codeName << "SI_QUEUE";
239             break;
240         case SI_TIMER:
241             codeName << "SI_TIMER";
242             break;
243         case SI_MESGQ:
244             codeName << "SI_MESGQ";
245             break;
246         case SI_ASYNCIO:
247             codeName << "SI_ASYNCIO";
248             break;
249         case SI_SIGIO:
250             codeName << "SI_SIGIO";
251             break;
252         case SI_TKILL:
253             codeName << "SI_TKILL";
254             break;
255         default:
256             codeName << "Unknown Code:" << signalCode;
257             break;
258     }
259     return codeName.str();
260 }
261 
FormatCodeName(int32_t signal,int32_t signalCode)262 std::string SignalInfo::FormatCodeName(int32_t signal, int32_t signalCode)
263 {
264     switch (signal) {
265         case SIGILL:
266             return FormatSIGILLCodeName(signalCode);
267         case SIGBUS:
268             return FormatSIGBUSCodeName(signalCode);
269         case SIGFPE:
270             return FormatSIGFPECodeName(signalCode);
271         case SIGSEGV:
272             return FormatSIGSEGVCodeName(signalCode);
273         case SIGTRAP:
274             return FormatSIGTRAPCodeName(signalCode);
275         default:
276             break;
277     }
278     return FormatCommonSignalCodeName(signalCode);
279 }
280 }  // namespace HiviewDFX
281 }  // namespace OHOS
282