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
22namespace OHOS {
23namespace HiviewDFX {
24void 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
38bool 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
47bool SignalInfo::IsSignalAddrAvaliable(int32_t signal)
48{
49    return ((signal == SIGABRT) || (signal == SIGBUS) || (signal == SIGILL)
50        || (signal == SIGSEGV) || (signal == SIGTRAP));
51}
52
53bool 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
67std::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
91std::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
117std::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
152std::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
187std::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
204std::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
227std::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
262std::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