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 13 #if defined(__APPLE__) 14 // Needed for the EXC_RESOURCE interpretation macros 15 #include <kern/exc_resource.h> 16 #endif 17 18 #include "lldb/Breakpoint/Watchpoint.h" 19 #include "lldb/Symbol/Symbol.h" 20 #include "lldb/Target/DynamicLoader.h" 21 #include "lldb/Target/ExecutionContext.h" 22 #include "lldb/Target/Process.h" 23 #include "lldb/Target/RegisterContext.h" 24 #include "lldb/Target/Target.h" 25 #include "lldb/Target/Thread.h" 26 #include "lldb/Target/ThreadPlan.h" 27 #include "lldb/Target/UnixSignals.h" 28 #include "lldb/Utility/StreamString.h" 29 30 using namespace lldb; 31 using namespace lldb_private; 32 33 const char *StopInfoMachException::GetDescription() { 34 if (m_description.empty() && m_value != 0) { 35 ExecutionContext exe_ctx(m_thread_wp.lock()); 36 Target *target = exe_ctx.GetTargetPtr(); 37 const llvm::Triple::ArchType cpu = 38 target ? target->GetArchitecture().GetMachine() 39 : llvm::Triple::UnknownArch; 40 41 const char *exc_desc = NULL; 42 const char *code_label = "code"; 43 const char *code_desc = NULL; 44 const char *subcode_label = "subcode"; 45 const char *subcode_desc = NULL; 46 47 #if defined(__APPLE__) 48 char code_desc_buf[32]; 49 char subcode_desc_buf[32]; 50 #endif 51 52 switch (m_value) { 53 case 1: // EXC_BAD_ACCESS 54 exc_desc = "EXC_BAD_ACCESS"; 55 subcode_label = "address"; 56 switch (cpu) { 57 case llvm::Triple::x86: 58 case llvm::Triple::x86_64: 59 switch (m_exc_code) { 60 case 0xd: 61 code_desc = "EXC_I386_GPFLT"; 62 m_exc_data_count = 1; 63 break; 64 } 65 break; 66 case llvm::Triple::arm: 67 case llvm::Triple::thumb: 68 switch (m_exc_code) { 69 case 0x101: 70 code_desc = "EXC_ARM_DA_ALIGN"; 71 break; 72 case 0x102: 73 code_desc = "EXC_ARM_DA_DEBUG"; 74 break; 75 } 76 break; 77 78 case llvm::Triple::ppc: 79 case llvm::Triple::ppc64: 80 switch (m_exc_code) { 81 case 0x101: 82 code_desc = "EXC_PPC_VM_PROT_READ"; 83 break; 84 case 0x102: 85 code_desc = "EXC_PPC_BADSPACE"; 86 break; 87 case 0x103: 88 code_desc = "EXC_PPC_UNALIGNED"; 89 break; 90 } 91 break; 92 93 default: 94 break; 95 } 96 break; 97 98 case 2: // EXC_BAD_INSTRUCTION 99 exc_desc = "EXC_BAD_INSTRUCTION"; 100 switch (cpu) { 101 case llvm::Triple::x86: 102 case llvm::Triple::x86_64: 103 if (m_exc_code == 1) 104 code_desc = "EXC_I386_INVOP"; 105 break; 106 107 case llvm::Triple::ppc: 108 case llvm::Triple::ppc64: 109 switch (m_exc_code) { 110 case 1: 111 code_desc = "EXC_PPC_INVALID_SYSCALL"; 112 break; 113 case 2: 114 code_desc = "EXC_PPC_UNIPL_INST"; 115 break; 116 case 3: 117 code_desc = "EXC_PPC_PRIVINST"; 118 break; 119 case 4: 120 code_desc = "EXC_PPC_PRIVREG"; 121 break; 122 case 5: 123 code_desc = "EXC_PPC_TRACE"; 124 break; 125 case 6: 126 code_desc = "EXC_PPC_PERFMON"; 127 break; 128 } 129 break; 130 131 case llvm::Triple::arm: 132 case llvm::Triple::thumb: 133 if (m_exc_code == 1) 134 code_desc = "EXC_ARM_UNDEFINED"; 135 break; 136 137 default: 138 break; 139 } 140 break; 141 142 case 3: // EXC_ARITHMETIC 143 exc_desc = "EXC_ARITHMETIC"; 144 switch (cpu) { 145 case llvm::Triple::x86: 146 case llvm::Triple::x86_64: 147 switch (m_exc_code) { 148 case 1: 149 code_desc = "EXC_I386_DIV"; 150 break; 151 case 2: 152 code_desc = "EXC_I386_INTO"; 153 break; 154 case 3: 155 code_desc = "EXC_I386_NOEXT"; 156 break; 157 case 4: 158 code_desc = "EXC_I386_EXTOVR"; 159 break; 160 case 5: 161 code_desc = "EXC_I386_EXTERR"; 162 break; 163 case 6: 164 code_desc = "EXC_I386_EMERR"; 165 break; 166 case 7: 167 code_desc = "EXC_I386_BOUND"; 168 break; 169 case 8: 170 code_desc = "EXC_I386_SSEEXTERR"; 171 break; 172 } 173 break; 174 175 case llvm::Triple::ppc: 176 case llvm::Triple::ppc64: 177 switch (m_exc_code) { 178 case 1: 179 code_desc = "EXC_PPC_OVERFLOW"; 180 break; 181 case 2: 182 code_desc = "EXC_PPC_ZERO_DIVIDE"; 183 break; 184 case 3: 185 code_desc = "EXC_PPC_FLT_INEXACT"; 186 break; 187 case 4: 188 code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; 189 break; 190 case 5: 191 code_desc = "EXC_PPC_FLT_UNDERFLOW"; 192 break; 193 case 6: 194 code_desc = "EXC_PPC_FLT_OVERFLOW"; 195 break; 196 case 7: 197 code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; 198 break; 199 } 200 break; 201 202 default: 203 break; 204 } 205 break; 206 207 case 4: // EXC_EMULATION 208 exc_desc = "EXC_EMULATION"; 209 break; 210 211 case 5: // EXC_SOFTWARE 212 exc_desc = "EXC_SOFTWARE"; 213 if (m_exc_code == 0x10003) { 214 subcode_desc = "EXC_SOFT_SIGNAL"; 215 subcode_label = "signo"; 216 } 217 break; 218 219 case 6: // EXC_BREAKPOINT 220 { 221 exc_desc = "EXC_BREAKPOINT"; 222 switch (cpu) { 223 case llvm::Triple::x86: 224 case llvm::Triple::x86_64: 225 switch (m_exc_code) { 226 case 1: 227 code_desc = "EXC_I386_SGL"; 228 break; 229 case 2: 230 code_desc = "EXC_I386_BPT"; 231 break; 232 } 233 break; 234 235 case llvm::Triple::ppc: 236 case llvm::Triple::ppc64: 237 switch (m_exc_code) { 238 case 1: 239 code_desc = "EXC_PPC_BREAKPOINT"; 240 break; 241 } 242 break; 243 244 case llvm::Triple::arm: 245 case llvm::Triple::thumb: 246 switch (m_exc_code) { 247 case 0x101: 248 code_desc = "EXC_ARM_DA_ALIGN"; 249 break; 250 case 0x102: 251 code_desc = "EXC_ARM_DA_DEBUG"; 252 break; 253 case 1: 254 code_desc = "EXC_ARM_BREAKPOINT"; 255 break; 256 // FIXME temporary workaround, exc_code 0 does not really mean 257 // EXC_ARM_BREAKPOINT 258 case 0: 259 code_desc = "EXC_ARM_BREAKPOINT"; 260 break; 261 } 262 break; 263 264 default: 265 break; 266 } 267 } break; 268 269 case 7: 270 exc_desc = "EXC_SYSCALL"; 271 break; 272 273 case 8: 274 exc_desc = "EXC_MACH_SYSCALL"; 275 break; 276 277 case 9: 278 exc_desc = "EXC_RPC_ALERT"; 279 break; 280 281 case 10: 282 exc_desc = "EXC_CRASH"; 283 break; 284 case 11: 285 exc_desc = "EXC_RESOURCE"; 286 #if defined(__APPLE__) 287 { 288 int resource_type = EXC_RESOURCE_DECODE_RESOURCE_TYPE(m_exc_code); 289 290 code_label = "limit"; 291 code_desc = code_desc_buf; 292 subcode_label = "observed"; 293 subcode_desc = subcode_desc_buf; 294 295 switch (resource_type) { 296 case RESOURCE_TYPE_CPU: 297 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_CPU"; 298 snprintf(code_desc_buf, sizeof(code_desc_buf), "%d%%", 299 (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE(m_exc_code)); 300 snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d%%", 301 (int)EXC_RESOURCE_CPUMONITOR_DECODE_PERCENTAGE_OBSERVED(m_exc_subcode)); 302 break; 303 case RESOURCE_TYPE_WAKEUPS: 304 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_WAKEUPS"; 305 snprintf(code_desc_buf, sizeof(code_desc_buf), "%d w/s", 306 (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_PERMITTED(m_exc_code)); 307 snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d w/s", 308 (int)EXC_RESOURCE_CPUMONITOR_DECODE_WAKEUPS_OBSERVED(m_exc_subcode)); 309 break; 310 case RESOURCE_TYPE_MEMORY: 311 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_MEMORY"; 312 snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", 313 (int)EXC_RESOURCE_HWM_DECODE_LIMIT(m_exc_code)); 314 subcode_desc = nullptr; 315 subcode_label = "unused"; 316 break; 317 case RESOURCE_TYPE_IO: 318 exc_desc = "EXC_RESOURCE RESOURCE_TYPE_IO"; 319 snprintf(code_desc_buf, sizeof(code_desc_buf), "%d MB", 320 (int)EXC_RESOURCE_IO_DECODE_LIMIT(m_exc_code)); 321 snprintf(subcode_desc_buf, sizeof(subcode_desc_buf), "%d MB", 322 (int)EXC_RESOURCE_IO_OBSERVED(m_exc_subcode));; 323 break; 324 } 325 } 326 #endif 327 break; 328 case 12: 329 exc_desc = "EXC_GUARD"; 330 break; 331 } 332 333 StreamString strm; 334 335 if (exc_desc) 336 strm.PutCString(exc_desc); 337 else 338 strm.Printf("EXC_??? (%" PRIu64 ")", m_value); 339 340 if (m_exc_data_count >= 1) { 341 if (code_desc) 342 strm.Printf(" (%s=%s", code_label, code_desc); 343 else 344 strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); 345 } 346 347 if (m_exc_data_count >= 2) { 348 if (subcode_desc) 349 strm.Printf(", %s=%s", subcode_label, subcode_desc); 350 else 351 strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); 352 } 353 354 if (m_exc_data_count > 0) 355 strm.PutChar(')'); 356 357 m_description = strm.GetString(); 358 } 359 return m_description.c_str(); 360 } 361 362 StopInfoSP StopInfoMachException::CreateStopReasonWithMachException( 363 Thread &thread, uint32_t exc_type, uint32_t exc_data_count, 364 uint64_t exc_code, uint64_t exc_sub_code, uint64_t exc_sub_sub_code, 365 bool pc_already_adjusted, bool adjust_pc_if_needed) { 366 if (exc_type != 0) { 367 uint32_t pc_decrement = 0; 368 ExecutionContext exe_ctx(thread.shared_from_this()); 369 Target *target = exe_ctx.GetTargetPtr(); 370 const llvm::Triple::ArchType cpu = 371 target ? target->GetArchitecture().GetMachine() 372 : llvm::Triple::UnknownArch; 373 374 switch (exc_type) { 375 case 1: // EXC_BAD_ACCESS 376 break; 377 378 case 2: // EXC_BAD_INSTRUCTION 379 switch (cpu) { 380 case llvm::Triple::ppc: 381 case llvm::Triple::ppc64: 382 switch (exc_code) { 383 case 1: // EXC_PPC_INVALID_SYSCALL 384 case 2: // EXC_PPC_UNIPL_INST 385 case 3: // EXC_PPC_PRIVINST 386 case 4: // EXC_PPC_PRIVREG 387 break; 388 case 5: // EXC_PPC_TRACE 389 return StopInfo::CreateStopReasonToTrace(thread); 390 case 6: // EXC_PPC_PERFMON 391 break; 392 } 393 break; 394 395 default: 396 break; 397 } 398 break; 399 400 case 3: // EXC_ARITHMETIC 401 case 4: // EXC_EMULATION 402 break; 403 404 case 5: // EXC_SOFTWARE 405 if (exc_code == 0x10003) // EXC_SOFT_SIGNAL 406 { 407 if (exc_sub_code == 5) { 408 // On MacOSX, a SIGTRAP can signify that a process has called exec, 409 // so we should check with our dynamic loader to verify. 410 ProcessSP process_sp(thread.GetProcess()); 411 if (process_sp) { 412 DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); 413 if (dynamic_loader && dynamic_loader->ProcessDidExec()) { 414 // The program was re-exec'ed 415 return StopInfo::CreateStopReasonWithExec(thread); 416 } 417 // if (!process_did_exec) 418 // { 419 // // We have a SIGTRAP, make sure we 420 // didn't exec by checking 421 // // for the PC being at 422 // "_dyld_start"... 423 // lldb::StackFrameSP frame_sp 424 // (thread.GetStackFrameAtIndex(0)); 425 // if (frame_sp) 426 // { 427 // const Symbol *symbol = 428 // frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; 429 // if (symbol) 430 // { 431 // if (symbol->GetName() == 432 // ConstString("_dyld_start")) 433 // process_did_exec = true; 434 // } 435 // } 436 // } 437 } 438 } 439 return StopInfo::CreateStopReasonWithSignal(thread, exc_sub_code); 440 } 441 break; 442 443 case 6: // EXC_BREAKPOINT 444 { 445 bool is_actual_breakpoint = false; 446 bool is_trace_if_actual_breakpoint_missing = false; 447 switch (cpu) { 448 case llvm::Triple::x86: 449 case llvm::Triple::x86_64: 450 if (exc_code == 1) // EXC_I386_SGL 451 { 452 if (!exc_sub_code) { 453 // This looks like a plain trap. 454 // Have to check if there is a breakpoint here as well. When you 455 // single-step onto a trap, the single step stops you not to trap. 456 // Since we also do that check below, let's just use that logic. 457 is_actual_breakpoint = true; 458 is_trace_if_actual_breakpoint_missing = true; 459 } else { 460 461 // It's a watchpoint, then. 462 // The exc_sub_code indicates the data break address. 463 lldb::WatchpointSP wp_sp; 464 if (target) 465 wp_sp = target->GetWatchpointList().FindByAddress( 466 (lldb::addr_t)exc_sub_code); 467 if (wp_sp && wp_sp->IsEnabled()) { 468 // Debugserver may piggyback the hardware index of the fired 469 // watchpoint in the exception data. Set the hardware index if 470 // that's the case. 471 if (exc_data_count >= 3) 472 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 473 return StopInfo::CreateStopReasonWithWatchpointID(thread, 474 wp_sp->GetID()); 475 } 476 } 477 } else if (exc_code == 2 || // EXC_I386_BPT 478 exc_code == 3) // EXC_I386_BPTFLT 479 { 480 // KDP returns EXC_I386_BPTFLT for trace breakpoints 481 if (exc_code == 3) 482 is_trace_if_actual_breakpoint_missing = true; 483 484 is_actual_breakpoint = true; 485 if (!pc_already_adjusted) 486 pc_decrement = 1; 487 } 488 break; 489 490 case llvm::Triple::ppc: 491 case llvm::Triple::ppc64: 492 is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT 493 break; 494 495 case llvm::Triple::arm: 496 case llvm::Triple::thumb: 497 if (exc_code == 0x102) // EXC_ARM_DA_DEBUG 498 { 499 // It's a watchpoint, then, if the exc_sub_code indicates a 500 // known/enabled data break address from our watchpoint list. 501 lldb::WatchpointSP wp_sp; 502 if (target) 503 wp_sp = target->GetWatchpointList().FindByAddress( 504 (lldb::addr_t)exc_sub_code); 505 if (wp_sp && wp_sp->IsEnabled()) { 506 // Debugserver may piggyback the hardware index of the fired 507 // watchpoint in the exception data. Set the hardware index if 508 // that's the case. 509 if (exc_data_count >= 3) 510 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 511 return StopInfo::CreateStopReasonWithWatchpointID(thread, 512 wp_sp->GetID()); 513 } else { 514 is_actual_breakpoint = true; 515 is_trace_if_actual_breakpoint_missing = true; 516 } 517 } else if (exc_code == 1) // EXC_ARM_BREAKPOINT 518 { 519 is_actual_breakpoint = true; 520 is_trace_if_actual_breakpoint_missing = true; 521 } else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel 522 // is currently returning this so accept it 523 // as indicating a breakpoint until the 524 // kernel is fixed 525 { 526 is_actual_breakpoint = true; 527 is_trace_if_actual_breakpoint_missing = true; 528 } 529 break; 530 531 case llvm::Triple::aarch64: { 532 if (exc_code == 1 && exc_sub_code == 0) // EXC_ARM_BREAKPOINT 533 { 534 // This is hit when we single instruction step aka MDSCR_EL1 SS bit 0 535 // is set 536 is_actual_breakpoint = false; 537 is_trace_if_actual_breakpoint_missing = true; 538 } 539 if (exc_code == 0x102) // EXC_ARM_DA_DEBUG 540 { 541 // It's a watchpoint, then, if the exc_sub_code indicates a 542 // known/enabled data break address from our watchpoint list. 543 lldb::WatchpointSP wp_sp; 544 if (target) 545 wp_sp = target->GetWatchpointList().FindByAddress( 546 (lldb::addr_t)exc_sub_code); 547 if (wp_sp && wp_sp->IsEnabled()) { 548 // Debugserver may piggyback the hardware index of the fired 549 // watchpoint in the exception data. Set the hardware index if 550 // that's the case. 551 if (exc_data_count >= 3) 552 wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 553 return StopInfo::CreateStopReasonWithWatchpointID(thread, 554 wp_sp->GetID()); 555 } 556 // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as 557 // EXC_BAD_ACCESS 558 if (thread.GetTemporaryResumeState() == eStateStepping) 559 return StopInfo::CreateStopReasonToTrace(thread); 560 } 561 // It looks like exc_sub_code has the 4 bytes of the instruction that 562 // triggered the exception, i.e. our breakpoint opcode 563 is_actual_breakpoint = exc_code == 1; 564 break; 565 } 566 567 default: 568 break; 569 } 570 571 if (is_actual_breakpoint) { 572 RegisterContextSP reg_ctx_sp(thread.GetRegisterContext()); 573 addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; 574 575 ProcessSP process_sp(thread.CalculateProcess()); 576 577 lldb::BreakpointSiteSP bp_site_sp; 578 if (process_sp) 579 bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); 580 if (bp_site_sp && bp_site_sp->IsEnabled()) { 581 // Update the PC if we were asked to do so, but only do so if we find 582 // a breakpoint that we know about cause this could be a trap 583 // instruction in the code 584 if (pc_decrement > 0 && adjust_pc_if_needed) 585 reg_ctx_sp->SetPC(pc); 586 587 // If the breakpoint is for this thread, then we'll report the hit, 588 // but if it is for another thread, we can just report no reason. We 589 // don't need to worry about stepping over the breakpoint here, that 590 // will be taken care of when the thread resumes and notices that 591 // there's a breakpoint under the pc. If we have an operating system 592 // plug-in, we might have set a thread specific breakpoint using the 593 // operating system thread ID, so we can't make any assumptions about 594 // the thread ID so we must always report the breakpoint regardless 595 // of the thread. 596 if (bp_site_sp->ValidForThisThread(&thread) || 597 thread.GetProcess()->GetOperatingSystem() != NULL) 598 return StopInfo::CreateStopReasonWithBreakpointSiteID( 599 thread, bp_site_sp->GetID()); 600 else if (is_trace_if_actual_breakpoint_missing) 601 return StopInfo::CreateStopReasonToTrace(thread); 602 else 603 return StopInfoSP(); 604 } 605 606 // Don't call this a trace if we weren't single stepping this thread. 607 if (is_trace_if_actual_breakpoint_missing && 608 thread.GetTemporaryResumeState() == eStateStepping) { 609 return StopInfo::CreateStopReasonToTrace(thread); 610 } 611 } 612 } break; 613 614 case 7: // EXC_SYSCALL 615 case 8: // EXC_MACH_SYSCALL 616 case 9: // EXC_RPC_ALERT 617 case 10: // EXC_CRASH 618 break; 619 } 620 621 return StopInfoSP(new StopInfoMachException( 622 thread, exc_type, exc_data_count, exc_code, exc_sub_code)); 623 } 624 return StopInfoSP(); 625 } 626