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
25namespace OHOS {
26namespace HiviewDFX {
27namespace {
28#undef LOG_DOMAIN
29#undef LOG_TAG
30#define LOG_DOMAIN 0xD002D11
31#define LOG_TAG "DfxSignal"
32}
33
34bool 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
43bool 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
57bool 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
71std::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
88std::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
109std::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
130std::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
148std::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
172std::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
196std::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
208std::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
224std::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
234std::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