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