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