1 //===-- StopInfoMachException.cpp -------------------------------*- C++ -*-===// 2 // 3 // The LLVM Compiler Infrastructure 4 // 5 // This file is distributed under the University of Illinois Open Source 6 // License. See LICENSE.TXT for details. 7 // 8 //===----------------------------------------------------------------------===// 9 10 #include "StopInfoMachException.h" 11 12 // C Includes 13 // C++ Includes 14 // Other libraries and framework includes 15 // Project includes 16 #include "lldb/Core/ArchSpec.h" 17 #include "lldb/Core/StreamString.h" 18 #include "lldb/Target/Process.h" 19 #include "lldb/Target/RegisterContext.h" 20 #include "lldb/Target/Target.h" 21 #include "lldb/Target/Thread.h" 22 #include "lldb/Target/ThreadPlan.h" 23 #include "lldb/Target/UnixSignals.h" 24 25 using namespace lldb; 26 using namespace lldb_private; 27 28 const char * 29 StopInfoMachException::GetDescription () 30 { 31 if (m_description.empty() && m_value != 0) 32 { 33 const llvm::Triple::ArchType cpu = m_thread.GetProcess().GetTarget().GetArchitecture().GetMachine(); 34 35 const char *exc_desc = NULL; 36 const char *code_label = "code"; 37 const char *code_desc = NULL; 38 const char *subcode_label = "subcode"; 39 const char *subcode_desc = NULL; 40 switch (m_value) 41 { 42 case 1: // EXC_BAD_ACCESS 43 exc_desc = "EXC_BAD_ACCESS"; 44 subcode_label = "address"; 45 switch (cpu) 46 { 47 case llvm::Triple::arm: 48 switch (m_exc_code) 49 { 50 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; 51 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; 52 } 53 break; 54 55 case llvm::Triple::ppc: 56 case llvm::Triple::ppc64: 57 switch (m_exc_code) 58 { 59 case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break; 60 case 0x102: code_desc = "EXC_PPC_BADSPACE"; break; 61 case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break; 62 } 63 break; 64 65 default: 66 break; 67 } 68 break; 69 70 case 2: // EXC_BAD_INSTRUCTION 71 exc_desc = "EXC_BAD_INSTRUCTION"; 72 switch (cpu) 73 { 74 case llvm::Triple::x86: 75 case llvm::Triple::x86_64: 76 if (m_exc_code == 1) 77 code_desc = "EXC_I386_INVOP"; 78 break; 79 80 case llvm::Triple::ppc: 81 case llvm::Triple::ppc64: 82 switch (m_exc_code) 83 { 84 case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; 85 case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; 86 case 3: code_desc = "EXC_PPC_PRIVINST"; break; 87 case 4: code_desc = "EXC_PPC_PRIVREG"; break; 88 case 5: code_desc = "EXC_PPC_TRACE"; break; 89 case 6: code_desc = "EXC_PPC_PERFMON"; break; 90 } 91 break; 92 93 case llvm::Triple::arm: 94 if (m_exc_code == 1) 95 code_desc = "EXC_ARM_UNDEFINED"; 96 break; 97 98 default: 99 break; 100 } 101 break; 102 103 case 3: // EXC_ARITHMETIC 104 exc_desc = "EXC_ARITHMETIC"; 105 switch (cpu) 106 { 107 case llvm::Triple::x86: 108 case llvm::Triple::x86_64: 109 switch (m_exc_code) 110 { 111 case 1: code_desc = "EXC_I386_DIV"; break; 112 case 2: code_desc = "EXC_I386_INTO"; break; 113 case 3: code_desc = "EXC_I386_NOEXT"; break; 114 case 4: code_desc = "EXC_I386_EXTOVR"; break; 115 case 5: code_desc = "EXC_I386_EXTERR"; break; 116 case 6: code_desc = "EXC_I386_EMERR"; break; 117 case 7: code_desc = "EXC_I386_BOUND"; break; 118 case 8: code_desc = "EXC_I386_SSEEXTERR"; break; 119 } 120 break; 121 122 case llvm::Triple::ppc: 123 case llvm::Triple::ppc64: 124 switch (m_exc_code) 125 { 126 case 1: code_desc = "EXC_PPC_OVERFLOW"; break; 127 case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break; 128 case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break; 129 case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break; 130 case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break; 131 case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break; 132 case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break; 133 } 134 break; 135 136 default: 137 break; 138 } 139 break; 140 141 case 4: // EXC_EMULATION 142 exc_desc = "EXC_EMULATION"; 143 break; 144 145 146 case 5: // EXC_SOFTWARE 147 exc_desc = "EXC_SOFTWARE"; 148 if (m_exc_code == 0x10003) 149 { 150 subcode_desc = "EXC_SOFT_SIGNAL"; 151 subcode_label = "signo"; 152 } 153 break; 154 155 case 6: // EXC_BREAKPOINT 156 { 157 exc_desc = "EXC_BREAKPOINT"; 158 switch (cpu) 159 { 160 case llvm::Triple::x86: 161 case llvm::Triple::x86_64: 162 switch (m_exc_code) 163 { 164 case 1: code_desc = "EXC_I386_SGL"; break; 165 case 2: code_desc = "EXC_I386_BPT"; break; 166 } 167 break; 168 169 case llvm::Triple::ppc: 170 case llvm::Triple::ppc64: 171 switch (m_exc_code) 172 { 173 case 1: code_desc = "EXC_PPC_BREAKPOINT"; break; 174 } 175 break; 176 177 case llvm::Triple::arm: 178 switch (m_exc_code) 179 { 180 case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; 181 case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; 182 case 1: code_desc = "EXC_ARM_BREAKPOINT"; break; 183 } 184 break; 185 186 default: 187 break; 188 } 189 } 190 break; 191 192 case 7: 193 exc_desc = "EXC_SYSCALL"; 194 break; 195 196 case 8: 197 exc_desc = "EXC_MACH_SYSCALL"; 198 break; 199 200 case 9: 201 exc_desc = "EXC_RPC_ALERT"; 202 break; 203 204 case 10: 205 exc_desc = "EXC_CRASH"; 206 break; 207 } 208 209 StreamString strm; 210 211 if (exc_desc) 212 strm.PutCString(exc_desc); 213 else 214 strm.Printf("EXC_??? (%llu)", m_value); 215 216 if (m_exc_data_count >= 1) 217 { 218 if (code_desc) 219 strm.Printf(" (%s=%s", code_label, code_desc); 220 else 221 strm.Printf(" (%s=%llu", code_label, m_exc_code); 222 } 223 224 if (m_exc_data_count >= 2) 225 { 226 if (subcode_desc) 227 strm.Printf(", %s=%s", subcode_label, subcode_desc); 228 else 229 strm.Printf(", %s=0x%llx", subcode_label, m_exc_subcode); 230 } 231 232 if (m_exc_data_count > 0) 233 strm.PutChar(')'); 234 235 m_description.swap (strm.GetString()); 236 } 237 return m_description.c_str(); 238 } 239 240 241 StopInfoSP 242 StopInfoMachException::CreateStopReasonWithMachException 243 ( 244 Thread &thread, 245 uint32_t exc_type, 246 uint32_t exc_data_count, 247 uint64_t exc_code, 248 uint64_t exc_sub_code 249 ) 250 { 251 if (exc_type != 0) 252 { 253 const llvm::Triple::ArchType cpu = thread.GetProcess().GetTarget().GetArchitecture().GetMachine(); 254 255 switch (exc_type) 256 { 257 case 1: // EXC_BAD_ACCESS 258 break; 259 260 case 2: // EXC_BAD_INSTRUCTION 261 switch (cpu) 262 { 263 case llvm::Triple::ppc: 264 case llvm::Triple::ppc64: 265 switch (exc_code) 266 { 267 case 1: // EXC_PPC_INVALID_SYSCALL 268 case 2: // EXC_PPC_UNIPL_INST 269 case 3: // EXC_PPC_PRIVINST 270 case 4: // EXC_PPC_PRIVREG 271 break; 272 case 5: // EXC_PPC_TRACE 273 return StopInfo::CreateStopReasonToTrace (thread); 274 case 6: // EXC_PPC_PERFMON 275 break; 276 } 277 break; 278 279 default: 280 break; 281 } 282 break; 283 284 case 3: // EXC_ARITHMETIC 285 case 4: // EXC_EMULATION 286 break; 287 288 case 5: // EXC_SOFTWARE 289 if (exc_code == 0x10003) // EXC_SOFT_SIGNAL 290 return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code); 291 break; 292 293 case 6: // EXC_BREAKPOINT 294 { 295 bool is_software_breakpoint = false; 296 switch (cpu) 297 { 298 case llvm::Triple::x86: 299 case llvm::Triple::x86_64: 300 if (exc_code == 1) // EXC_I386_SGL 301 { 302 return StopInfo::CreateStopReasonToTrace(thread); 303 } 304 else if (exc_code == 2) // EXC_I386_BPT 305 { 306 is_software_breakpoint = true; 307 } 308 break; 309 310 case llvm::Triple::ppc: 311 case llvm::Triple::ppc64: 312 is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT 313 break; 314 315 case llvm::Triple::arm: 316 if (exc_code == 0x102) 317 { 318 // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS 319 return StopInfo::CreateStopReasonToTrace(thread); 320 } 321 else 322 is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT 323 break; 324 325 default: 326 break; 327 } 328 329 if (is_software_breakpoint) 330 { 331 addr_t pc = thread.GetRegisterContext()->GetPC(); 332 lldb::BreakpointSiteSP bp_site_sp = thread.GetProcess().GetBreakpointSiteList().FindByAddress(pc); 333 if (bp_site_sp) 334 { 335 // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, 336 // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that 337 // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. 338 if (bp_site_sp->ValidForThisThread (&thread)) 339 return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID()); 340 else 341 return StopInfoSP(); 342 } 343 else if (cpu == llvm::Triple::arm) 344 { 345 return StopInfo::CreateStopReasonToTrace (thread); 346 } 347 } 348 } 349 break; 350 351 case 7: // EXC_SYSCALL 352 case 8: // EXC_MACH_SYSCALL 353 case 9: // EXC_RPC_ALERT 354 case 10: // EXC_CRASH 355 break; 356 } 357 358 return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code)); 359 } 360 return StopInfoSP(); 361 } 362