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