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  
25  namespace OHOS {
26  namespace HiviewDFX {
27  namespace {
28  #undef LOG_DOMAIN
29  #undef LOG_TAG
30  #define LOG_DOMAIN 0xD002D11
31  #define LOG_TAG "DfxSignal"
32  }
33  
IsAvailable() const34  bool 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  
IsAddrAvailable() const43  bool 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  
IsPidAvailable() const57  bool 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  
PrintSignal(const siginfo_t & info)71  std::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  #if defined(__LP64__)
79          sigString = sigString + StringPrintf("@%#018lx ", (uint64_t)info.si_addr);
80  #else
81          sigString = sigString + StringPrintf("@%#010llx ", (uint64_t)info.si_addr);
82  #endif
83      }
84  
85      if ((info.si_code <= 0) && (info.si_pid != 0)) {
86          sigString = sigString + StringPrintf("from:%d:%u", info.si_pid, info.si_uid);
87      }
88  
89      return sigString;
90  }
91  
FormatSignalName(const int32_t signal)92  std::string DfxSignal::FormatSignalName(const int32_t signal)
93  {
94      std::map<int32_t, std::string> sigMaps = {
95          { SIGILL, std::string("SIGILL") },
96          { SIGTRAP, std::string("SIGTRAP") },
97          { SIGABRT, std::string("SIGABRT") },
98          { SIGALRM, std::string("SIGALRM") },
99          { SIGBUS, std::string("SIGBUS") },
100          { SIGFPE, std::string("SIGFPE") },
101          { SIGSEGV, std::string("SIGSEGV") },
102          { SIGSTKFLT, std::string("SIGSTKFLT") },
103          { SIGSYS, std::string("SIGSYS") },
104          { SIGDUMP, std::string("SIGDUMP") },
105      };
106  
107      if (sigMaps.find(signal) != sigMaps.end()) {
108          return sigMaps[signal];
109      }
110      return "Uncare Signal";
111  }
112  
FormatCodeName(const int32_t signal,const int32_t signalCode)113  std::string DfxSignal::FormatCodeName(const int32_t signal, const int32_t signalCode)
114  {
115      switch (signal) {
116          case SIGILL:
117              return FormatSIGILLCodeName(signalCode);
118          case SIGBUS:
119              return FormatSIGBUSCodeName(signalCode);
120          case SIGFPE:
121              return FormatSIGFPECodeName(signalCode);
122          case SIGSEGV:
123              return FormatSIGSEGVCodeName(signalCode);
124          case SIGTRAP:
125              return FormatSIGTRAPCodeName(signalCode);
126          default:
127              break;
128      }
129      return DfxSignal::FormatCommonSignalCodeName(signalCode);
130  }
131  
FormatSIGBUSCodeName(const int32_t signalCode)132  std::string DfxSignal::FormatSIGBUSCodeName(const int32_t signalCode)
133  {
134      switch (signalCode) {
135          case BUS_ADRALN:
136              return "BUS_ADRALN";
137          case BUS_ADRERR:
138              return "BUS_ADRERR";
139          case BUS_OBJERR:
140              return "BUS_OBJERR";
141          case BUS_MCEERR_AR:
142              return "BUS_MCEERR_AR";
143          case BUS_MCEERR_AO:
144              return "BUS_MCEERR_AO";
145          default:
146              return FormatCommonSignalCodeName(signalCode);
147      }
148  }
149  
FormatSIGILLCodeName(const int32_t signalCode)150  std::string DfxSignal::FormatSIGILLCodeName(const int32_t signalCode)
151  {
152      switch (signalCode) {
153          case ILL_ILLOPC:
154              return "ILL_ILLOPC";
155          case ILL_ILLOPN:
156              return "ILL_ILLOPN";
157          case ILL_ILLADR:
158              return "ILL_ILLADR";
159          case ILL_ILLTRP:
160              return "ILL_ILLTRP";
161          case ILL_PRVOPC:
162              return "ILL_PRVOPC";
163          case ILL_PRVREG:
164              return "ILL_PRVREG";
165          case ILL_COPROC:
166              return "ILL_COPROC";
167          case ILL_BADSTK:
168              return "ILL_BADSTK";
169          default:
170              return FormatCommonSignalCodeName(signalCode);
171      }
172  }
173  
FormatSIGFPECodeName(const int32_t signalCode)174  std::string DfxSignal::FormatSIGFPECodeName(const int32_t signalCode)
175  {
176      switch (signalCode) {
177          case FPE_INTDIV:
178              return "FPE_INTDIV";
179          case FPE_INTOVF:
180              return "FPE_INTOVF";
181          case FPE_FLTDIV:
182              return "FPE_FLTDIV";
183          case FPE_FLTOVF:
184              return "FPE_FLTOVF";
185          case FPE_FLTUND:
186              return "FPE_FLTUND";
187          case FPE_FLTRES:
188              return "FPE_FLTRES";
189          case FPE_FLTINV:
190              return "FPE_FLTINV";
191          case FPE_FLTSUB:
192              return "FPE_FLTSUB";
193          default:
194              return FormatCommonSignalCodeName(signalCode);
195      }
196  }
197  
FormatSIGSEGVCodeName(const int32_t signalCode)198  std::string DfxSignal::FormatSIGSEGVCodeName(const int32_t signalCode)
199  {
200      switch (signalCode) {
201          case SEGV_MAPERR:
202              return "SEGV_MAPERR";
203          case SEGV_ACCERR:
204              return "SEGV_ACCERR";
205          default:
206              return FormatCommonSignalCodeName(signalCode);
207      }
208  }
209  
FormatSIGTRAPCodeName(const int32_t signalCode)210  std::string DfxSignal::FormatSIGTRAPCodeName(const int32_t signalCode)
211  {
212      switch (signalCode) {
213          case TRAP_BRKPT:
214              return "TRAP_BRKPT";
215          case TRAP_TRACE:
216              return "TRAP_TRACE";
217          case TRAP_BRANCH:
218              return "TRAP_BRANCH";
219          case TRAP_HWBKPT:
220              return "TRAP_HWBKPT";
221          default:
222              return FormatCommonSignalCodeName(signalCode);
223      }
224  }
225  
FormatCommonSignalCodeName(const int32_t signalCode)226  std::string DfxSignal::FormatCommonSignalCodeName(const int32_t signalCode)
227  {
228      switch (signalCode) {
229          case SI_USER:
230              return "SI_USER";
231          case SI_KERNEL:
232              return "SI_KERNEL";
233          case SI_QUEUE:
234              return "SI_QUEUE";
235          case SI_TIMER:
236              return "SI_TIMER";
237          case SI_MESGQ:
238              return "SI_MESGQ";
239          case SI_ASYNCIO:
240              return "SI_ASYNCIO";
241          case SI_SIGIO:
242              return "SI_SIGIO";
243          case SI_TKILL:
244              return "SI_TKILL";
245          default:
246              return "UNKNOWN";
247      }
248  }
249  } // namespace HiviewDFX
250  } // namespace OHOS
251