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