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 if (!exc_sub_code) 303 return StopInfo::CreateStopReasonToTrace(thread); 304 305 // It's a watchpoint, then. 306 lldb::WatchpointLocationSP wp_loc_sp = 307 thread.GetProcess().GetTarget().GetWatchpointLocationList().FindByAddress((lldb::addr_t)exc_sub_code); 308 if (wp_loc_sp) 309 return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_loc_sp->GetID()); 310 } 311 else if (exc_code == 2) // EXC_I386_BPT 312 { 313 is_software_breakpoint = true; 314 } 315 break; 316 317 case llvm::Triple::ppc: 318 case llvm::Triple::ppc64: 319 is_software_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT 320 break; 321 322 case llvm::Triple::arm: 323 if (exc_code == 0x102) 324 { 325 // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS 326 return StopInfo::CreateStopReasonToTrace(thread); 327 } 328 else 329 is_software_breakpoint = exc_code == 1; // EXC_ARM_BREAKPOINT 330 break; 331 332 default: 333 break; 334 } 335 336 if (is_software_breakpoint) 337 { 338 addr_t pc = thread.GetRegisterContext()->GetPC(); 339 lldb::BreakpointSiteSP bp_site_sp = thread.GetProcess().GetBreakpointSiteList().FindByAddress(pc); 340 if (bp_site_sp) 341 { 342 // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, 343 // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that 344 // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. 345 if (bp_site_sp->ValidForThisThread (&thread)) 346 return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID()); 347 else 348 return StopInfoSP(); 349 } 350 else if (cpu == llvm::Triple::arm) 351 { 352 return StopInfo::CreateStopReasonToTrace (thread); 353 } 354 } 355 } 356 break; 357 358 case 7: // EXC_SYSCALL 359 case 8: // EXC_MACH_SYSCALL 360 case 9: // EXC_RPC_ALERT 361 case 10: // EXC_CRASH 362 break; 363 } 364 365 return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code)); 366 } 367 return StopInfoSP(); 368 } 369