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