1254721Semaste//===-- StopInfoMachException.cpp -------------------------------*- C++ -*-===// 2254721Semaste// 3254721Semaste// The LLVM Compiler Infrastructure 4254721Semaste// 5254721Semaste// This file is distributed under the University of Illinois Open Source 6254721Semaste// License. See LICENSE.TXT for details. 7254721Semaste// 8254721Semaste//===----------------------------------------------------------------------===// 9254721Semaste 10254721Semaste#include "StopInfoMachException.h" 11254721Semaste 12254721Semaste// C Includes 13254721Semaste// C++ Includes 14254721Semaste// Other libraries and framework includes 15254721Semaste// Project includes 16254721Semaste#include "lldb/Breakpoint/Watchpoint.h" 17254721Semaste#include "lldb/Core/ArchSpec.h" 18254721Semaste#include "lldb/Core/StreamString.h" 19254721Semaste#include "lldb/Symbol/Symbol.h" 20254721Semaste#include "lldb/Target/DynamicLoader.h" 21254721Semaste#include "lldb/Target/ExecutionContext.h" 22254721Semaste#include "lldb/Target/Process.h" 23254721Semaste#include "lldb/Target/RegisterContext.h" 24254721Semaste#include "lldb/Target/Target.h" 25254721Semaste#include "lldb/Target/Thread.h" 26254721Semaste#include "lldb/Target/ThreadPlan.h" 27254721Semaste#include "lldb/Target/UnixSignals.h" 28254721Semaste 29254721Semasteusing namespace lldb; 30254721Semasteusing namespace lldb_private; 31254721Semaste 32254721Semasteconst char * 33254721SemasteStopInfoMachException::GetDescription () 34254721Semaste{ 35254721Semaste if (m_description.empty() && m_value != 0) 36254721Semaste { 37254721Semaste ExecutionContext exe_ctx (m_thread_wp.lock()); 38254721Semaste Target *target = exe_ctx.GetTargetPtr(); 39254721Semaste const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch; 40254721Semaste 41254721Semaste const char *exc_desc = NULL; 42254721Semaste const char *code_label = "code"; 43254721Semaste const char *code_desc = NULL; 44254721Semaste const char *subcode_label = "subcode"; 45254721Semaste const char *subcode_desc = NULL; 46254721Semaste switch (m_value) 47254721Semaste { 48254721Semaste case 1: // EXC_BAD_ACCESS 49254721Semaste exc_desc = "EXC_BAD_ACCESS"; 50254721Semaste subcode_label = "address"; 51254721Semaste switch (cpu) 52254721Semaste { 53254721Semaste case llvm::Triple::x86: 54254721Semaste case llvm::Triple::x86_64: 55254721Semaste switch (m_exc_code) 56254721Semaste { 57254721Semaste case 0xd: code_desc = "EXC_I386_GPFLT"; m_exc_data_count = 1; break; 58254721Semaste } 59254721Semaste break; 60254721Semaste case llvm::Triple::arm: 61254721Semaste switch (m_exc_code) 62254721Semaste { 63254721Semaste case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; 64254721Semaste case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; 65254721Semaste } 66254721Semaste break; 67254721Semaste 68254721Semaste case llvm::Triple::ppc: 69254721Semaste case llvm::Triple::ppc64: 70254721Semaste switch (m_exc_code) 71254721Semaste { 72254721Semaste case 0x101: code_desc = "EXC_PPC_VM_PROT_READ"; break; 73254721Semaste case 0x102: code_desc = "EXC_PPC_BADSPACE"; break; 74254721Semaste case 0x103: code_desc = "EXC_PPC_UNALIGNED"; break; 75254721Semaste } 76254721Semaste break; 77254721Semaste 78254721Semaste default: 79254721Semaste break; 80254721Semaste } 81254721Semaste break; 82254721Semaste 83254721Semaste case 2: // EXC_BAD_INSTRUCTION 84254721Semaste exc_desc = "EXC_BAD_INSTRUCTION"; 85254721Semaste switch (cpu) 86254721Semaste { 87254721Semaste case llvm::Triple::x86: 88254721Semaste case llvm::Triple::x86_64: 89254721Semaste if (m_exc_code == 1) 90254721Semaste code_desc = "EXC_I386_INVOP"; 91254721Semaste break; 92254721Semaste 93254721Semaste case llvm::Triple::ppc: 94254721Semaste case llvm::Triple::ppc64: 95254721Semaste switch (m_exc_code) 96254721Semaste { 97254721Semaste case 1: code_desc = "EXC_PPC_INVALID_SYSCALL"; break; 98254721Semaste case 2: code_desc = "EXC_PPC_UNIPL_INST"; break; 99254721Semaste case 3: code_desc = "EXC_PPC_PRIVINST"; break; 100254721Semaste case 4: code_desc = "EXC_PPC_PRIVREG"; break; 101254721Semaste case 5: code_desc = "EXC_PPC_TRACE"; break; 102254721Semaste case 6: code_desc = "EXC_PPC_PERFMON"; break; 103254721Semaste } 104254721Semaste break; 105254721Semaste 106254721Semaste case llvm::Triple::arm: 107254721Semaste if (m_exc_code == 1) 108254721Semaste code_desc = "EXC_ARM_UNDEFINED"; 109254721Semaste break; 110254721Semaste 111254721Semaste default: 112254721Semaste break; 113254721Semaste } 114254721Semaste break; 115254721Semaste 116254721Semaste case 3: // EXC_ARITHMETIC 117254721Semaste exc_desc = "EXC_ARITHMETIC"; 118254721Semaste switch (cpu) 119254721Semaste { 120254721Semaste case llvm::Triple::x86: 121254721Semaste case llvm::Triple::x86_64: 122254721Semaste switch (m_exc_code) 123254721Semaste { 124254721Semaste case 1: code_desc = "EXC_I386_DIV"; break; 125254721Semaste case 2: code_desc = "EXC_I386_INTO"; break; 126254721Semaste case 3: code_desc = "EXC_I386_NOEXT"; break; 127254721Semaste case 4: code_desc = "EXC_I386_EXTOVR"; break; 128254721Semaste case 5: code_desc = "EXC_I386_EXTERR"; break; 129254721Semaste case 6: code_desc = "EXC_I386_EMERR"; break; 130254721Semaste case 7: code_desc = "EXC_I386_BOUND"; break; 131254721Semaste case 8: code_desc = "EXC_I386_SSEEXTERR"; break; 132254721Semaste } 133254721Semaste break; 134254721Semaste 135254721Semaste case llvm::Triple::ppc: 136254721Semaste case llvm::Triple::ppc64: 137254721Semaste switch (m_exc_code) 138254721Semaste { 139254721Semaste case 1: code_desc = "EXC_PPC_OVERFLOW"; break; 140254721Semaste case 2: code_desc = "EXC_PPC_ZERO_DIVIDE"; break; 141254721Semaste case 3: code_desc = "EXC_PPC_FLT_INEXACT"; break; 142254721Semaste case 4: code_desc = "EXC_PPC_FLT_ZERO_DIVIDE"; break; 143254721Semaste case 5: code_desc = "EXC_PPC_FLT_UNDERFLOW"; break; 144254721Semaste case 6: code_desc = "EXC_PPC_FLT_OVERFLOW"; break; 145254721Semaste case 7: code_desc = "EXC_PPC_FLT_NOT_A_NUMBER"; break; 146254721Semaste } 147254721Semaste break; 148254721Semaste 149254721Semaste default: 150254721Semaste break; 151254721Semaste } 152254721Semaste break; 153254721Semaste 154254721Semaste case 4: // EXC_EMULATION 155254721Semaste exc_desc = "EXC_EMULATION"; 156254721Semaste break; 157254721Semaste 158254721Semaste 159254721Semaste case 5: // EXC_SOFTWARE 160254721Semaste exc_desc = "EXC_SOFTWARE"; 161254721Semaste if (m_exc_code == 0x10003) 162254721Semaste { 163254721Semaste subcode_desc = "EXC_SOFT_SIGNAL"; 164254721Semaste subcode_label = "signo"; 165254721Semaste } 166254721Semaste break; 167254721Semaste 168254721Semaste case 6: // EXC_BREAKPOINT 169254721Semaste { 170254721Semaste exc_desc = "EXC_BREAKPOINT"; 171254721Semaste switch (cpu) 172254721Semaste { 173254721Semaste case llvm::Triple::x86: 174254721Semaste case llvm::Triple::x86_64: 175254721Semaste switch (m_exc_code) 176254721Semaste { 177254721Semaste case 1: code_desc = "EXC_I386_SGL"; break; 178254721Semaste case 2: code_desc = "EXC_I386_BPT"; break; 179254721Semaste } 180254721Semaste break; 181254721Semaste 182254721Semaste case llvm::Triple::ppc: 183254721Semaste case llvm::Triple::ppc64: 184254721Semaste switch (m_exc_code) 185254721Semaste { 186254721Semaste case 1: code_desc = "EXC_PPC_BREAKPOINT"; break; 187254721Semaste } 188254721Semaste break; 189254721Semaste 190254721Semaste case llvm::Triple::arm: 191254721Semaste switch (m_exc_code) 192254721Semaste { 193254721Semaste case 0x101: code_desc = "EXC_ARM_DA_ALIGN"; break; 194254721Semaste case 0x102: code_desc = "EXC_ARM_DA_DEBUG"; break; 195254721Semaste case 1: code_desc = "EXC_ARM_BREAKPOINT"; break; 196254721Semaste // FIXME temporary workaround, exc_code 0 does not really mean EXC_ARM_BREAKPOINT 197254721Semaste case 0: code_desc = "EXC_ARM_BREAKPOINT"; break; 198254721Semaste } 199254721Semaste break; 200254721Semaste 201254721Semaste default: 202254721Semaste break; 203254721Semaste } 204254721Semaste } 205254721Semaste break; 206254721Semaste 207254721Semaste case 7: 208254721Semaste exc_desc = "EXC_SYSCALL"; 209254721Semaste break; 210254721Semaste 211254721Semaste case 8: 212254721Semaste exc_desc = "EXC_MACH_SYSCALL"; 213254721Semaste break; 214254721Semaste 215254721Semaste case 9: 216254721Semaste exc_desc = "EXC_RPC_ALERT"; 217254721Semaste break; 218254721Semaste 219254721Semaste case 10: 220254721Semaste exc_desc = "EXC_CRASH"; 221254721Semaste break; 222254721Semaste case 11: 223254721Semaste exc_desc = "EXC_RESOURCE"; 224254721Semaste break; 225254721Semaste case 12: 226254721Semaste exc_desc = "EXC_GUARD"; 227254721Semaste break; 228254721Semaste } 229254721Semaste 230254721Semaste StreamString strm; 231254721Semaste 232254721Semaste if (exc_desc) 233254721Semaste strm.PutCString(exc_desc); 234254721Semaste else 235254721Semaste strm.Printf("EXC_??? (%" PRIu64 ")", m_value); 236254721Semaste 237254721Semaste if (m_exc_data_count >= 1) 238254721Semaste { 239254721Semaste if (code_desc) 240254721Semaste strm.Printf(" (%s=%s", code_label, code_desc); 241254721Semaste else 242254721Semaste strm.Printf(" (%s=%" PRIu64, code_label, m_exc_code); 243254721Semaste } 244254721Semaste 245254721Semaste if (m_exc_data_count >= 2) 246254721Semaste { 247254721Semaste if (subcode_desc) 248254721Semaste strm.Printf(", %s=%s", subcode_label, subcode_desc); 249254721Semaste else 250254721Semaste strm.Printf(", %s=0x%" PRIx64, subcode_label, m_exc_subcode); 251254721Semaste } 252254721Semaste 253254721Semaste if (m_exc_data_count > 0) 254254721Semaste strm.PutChar(')'); 255254721Semaste 256254721Semaste m_description.swap (strm.GetString()); 257254721Semaste } 258254721Semaste return m_description.c_str(); 259254721Semaste} 260254721Semaste 261254721Semaste 262254721Semaste 263254721Semaste 264254721Semaste 265254721SemasteStopInfoSP 266254721SemasteStopInfoMachException::CreateStopReasonWithMachException 267254721Semaste( 268254721Semaste Thread &thread, 269254721Semaste uint32_t exc_type, 270254721Semaste uint32_t exc_data_count, 271254721Semaste uint64_t exc_code, 272254721Semaste uint64_t exc_sub_code, 273254721Semaste uint64_t exc_sub_sub_code, 274254721Semaste bool pc_already_adjusted, 275254721Semaste bool adjust_pc_if_needed 276254721Semaste) 277254721Semaste{ 278254721Semaste if (exc_type != 0) 279254721Semaste { 280254721Semaste uint32_t pc_decrement = 0; 281254721Semaste ExecutionContext exe_ctx (thread.shared_from_this()); 282254721Semaste Target *target = exe_ctx.GetTargetPtr(); 283254721Semaste const llvm::Triple::ArchType cpu = target ? target->GetArchitecture().GetMachine() : llvm::Triple::UnknownArch; 284254721Semaste 285254721Semaste switch (exc_type) 286254721Semaste { 287254721Semaste case 1: // EXC_BAD_ACCESS 288254721Semaste break; 289254721Semaste 290254721Semaste case 2: // EXC_BAD_INSTRUCTION 291254721Semaste switch (cpu) 292254721Semaste { 293254721Semaste case llvm::Triple::ppc: 294254721Semaste case llvm::Triple::ppc64: 295254721Semaste switch (exc_code) 296254721Semaste { 297254721Semaste case 1: // EXC_PPC_INVALID_SYSCALL 298254721Semaste case 2: // EXC_PPC_UNIPL_INST 299254721Semaste case 3: // EXC_PPC_PRIVINST 300254721Semaste case 4: // EXC_PPC_PRIVREG 301254721Semaste break; 302254721Semaste case 5: // EXC_PPC_TRACE 303254721Semaste return StopInfo::CreateStopReasonToTrace (thread); 304254721Semaste case 6: // EXC_PPC_PERFMON 305254721Semaste break; 306254721Semaste } 307254721Semaste break; 308254721Semaste 309254721Semaste default: 310254721Semaste break; 311254721Semaste } 312254721Semaste break; 313254721Semaste 314254721Semaste case 3: // EXC_ARITHMETIC 315254721Semaste case 4: // EXC_EMULATION 316254721Semaste break; 317254721Semaste 318254721Semaste case 5: // EXC_SOFTWARE 319254721Semaste if (exc_code == 0x10003) // EXC_SOFT_SIGNAL 320254721Semaste { 321254721Semaste if (exc_sub_code == 5) 322254721Semaste { 323254721Semaste // On MacOSX, a SIGTRAP can signify that a process has called 324254721Semaste // exec, so we should check with our dynamic loader to verify. 325254721Semaste ProcessSP process_sp (thread.GetProcess()); 326254721Semaste if (process_sp) 327254721Semaste { 328254721Semaste DynamicLoader *dynamic_loader = process_sp->GetDynamicLoader(); 329254721Semaste if (dynamic_loader && dynamic_loader->ProcessDidExec()) 330254721Semaste { 331254721Semaste // The program was re-exec'ed 332254721Semaste return StopInfo::CreateStopReasonWithExec (thread); 333254721Semaste } 334254721Semaste// if (!process_did_exec) 335254721Semaste// { 336254721Semaste// // We have a SIGTRAP, make sure we didn't exec by checking 337254721Semaste// // for the PC being at "_dyld_start"... 338254721Semaste// lldb::StackFrameSP frame_sp (thread.GetStackFrameAtIndex(0)); 339254721Semaste// if (frame_sp) 340254721Semaste// { 341254721Semaste// const Symbol *symbol = frame_sp->GetSymbolContext(eSymbolContextSymbol).symbol; 342254721Semaste// if (symbol) 343254721Semaste// { 344254721Semaste// if (symbol->GetName() == ConstString("_dyld_start")) 345254721Semaste// process_did_exec = true; 346254721Semaste// } 347254721Semaste// } 348254721Semaste// } 349254721Semaste } 350254721Semaste } 351254721Semaste return StopInfo::CreateStopReasonWithSignal (thread, exc_sub_code); 352254721Semaste } 353254721Semaste break; 354254721Semaste 355254721Semaste case 6: // EXC_BREAKPOINT 356254721Semaste { 357254721Semaste bool is_actual_breakpoint = false; 358254721Semaste bool is_trace_if_actual_breakpoint_missing = false; 359254721Semaste switch (cpu) 360254721Semaste { 361254721Semaste case llvm::Triple::x86: 362254721Semaste case llvm::Triple::x86_64: 363254721Semaste if (exc_code == 1) // EXC_I386_SGL 364254721Semaste { 365254721Semaste if (!exc_sub_code) 366254721Semaste return StopInfo::CreateStopReasonToTrace(thread); 367254721Semaste 368254721Semaste // It's a watchpoint, then. 369254721Semaste // The exc_sub_code indicates the data break address. 370254721Semaste lldb::WatchpointSP wp_sp; 371254721Semaste if (target) 372254721Semaste wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); 373254721Semaste if (wp_sp && wp_sp->IsEnabled()) 374254721Semaste { 375254721Semaste // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data. 376254721Semaste // Set the hardware index if that's the case. 377254721Semaste if (exc_data_count >=3) 378254721Semaste wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 379254721Semaste return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); 380254721Semaste } 381254721Semaste } 382254721Semaste else if (exc_code == 2 || // EXC_I386_BPT 383254721Semaste exc_code == 3) // EXC_I386_BPTFLT 384254721Semaste { 385254721Semaste // KDP returns EXC_I386_BPTFLT for trace breakpoints 386254721Semaste if (exc_code == 3) 387254721Semaste is_trace_if_actual_breakpoint_missing = true; 388254721Semaste 389254721Semaste is_actual_breakpoint = true; 390254721Semaste if (!pc_already_adjusted) 391254721Semaste pc_decrement = 1; 392254721Semaste } 393254721Semaste break; 394254721Semaste 395254721Semaste case llvm::Triple::ppc: 396254721Semaste case llvm::Triple::ppc64: 397254721Semaste is_actual_breakpoint = exc_code == 1; // EXC_PPC_BREAKPOINT 398254721Semaste break; 399254721Semaste 400254721Semaste case llvm::Triple::arm: 401254721Semaste if (exc_code == 0x102) // EXC_ARM_DA_DEBUG 402254721Semaste { 403254721Semaste // It's a watchpoint, then, if the exc_sub_code indicates a known/enabled 404254721Semaste // data break address from our watchpoint list. 405254721Semaste lldb::WatchpointSP wp_sp; 406254721Semaste if (target) 407254721Semaste wp_sp = target->GetWatchpointList().FindByAddress((lldb::addr_t)exc_sub_code); 408254721Semaste if (wp_sp && wp_sp->IsEnabled()) 409254721Semaste { 410254721Semaste // Debugserver may piggyback the hardware index of the fired watchpoint in the exception data. 411254721Semaste // Set the hardware index if that's the case. 412254721Semaste if (exc_data_count >=3) 413254721Semaste wp_sp->SetHardwareIndex((uint32_t)exc_sub_sub_code); 414254721Semaste return StopInfo::CreateStopReasonWithWatchpointID(thread, wp_sp->GetID()); 415254721Semaste } 416254721Semaste // EXC_ARM_DA_DEBUG seems to be reused for EXC_BREAKPOINT as well as EXC_BAD_ACCESS 417254721Semaste if (thread.GetTemporaryResumeState() == eStateStepping) 418254721Semaste return StopInfo::CreateStopReasonToTrace(thread); 419254721Semaste } 420254721Semaste else if (exc_code == 1) // EXC_ARM_BREAKPOINT 421254721Semaste { 422254721Semaste is_actual_breakpoint = true; 423254721Semaste is_trace_if_actual_breakpoint_missing = true; 424254721Semaste } 425254721Semaste else if (exc_code == 0) // FIXME not EXC_ARM_BREAKPOINT but a kernel is currently returning this so accept it as indicating a breakpoint until the kernel is fixed 426254721Semaste { 427254721Semaste is_actual_breakpoint = true; 428254721Semaste is_trace_if_actual_breakpoint_missing = true; 429254721Semaste } 430254721Semaste break; 431254721Semaste 432254721Semaste default: 433254721Semaste break; 434254721Semaste } 435254721Semaste 436254721Semaste if (is_actual_breakpoint) 437254721Semaste { 438254721Semaste RegisterContextSP reg_ctx_sp (thread.GetRegisterContext()); 439254721Semaste addr_t pc = reg_ctx_sp->GetPC() - pc_decrement; 440254721Semaste 441254721Semaste ProcessSP process_sp (thread.CalculateProcess()); 442254721Semaste 443254721Semaste lldb::BreakpointSiteSP bp_site_sp; 444254721Semaste if (process_sp) 445254721Semaste bp_site_sp = process_sp->GetBreakpointSiteList().FindByAddress(pc); 446254721Semaste if (bp_site_sp && bp_site_sp->IsEnabled()) 447254721Semaste { 448254721Semaste // Update the PC if we were asked to do so, but only do 449254721Semaste // so if we find a breakpoint that we know about cause 450254721Semaste // this could be a trap instruction in the code 451254721Semaste if (pc_decrement > 0 && adjust_pc_if_needed) 452254721Semaste reg_ctx_sp->SetPC (pc); 453254721Semaste 454254721Semaste // If the breakpoint is for this thread, then we'll report the hit, but if it is for another thread, 455254721Semaste // we can just report no reason. We don't need to worry about stepping over the breakpoint here, that 456254721Semaste // will be taken care of when the thread resumes and notices that there's a breakpoint under the pc. 457254721Semaste if (bp_site_sp->ValidForThisThread (&thread)) 458254721Semaste return StopInfo::CreateStopReasonWithBreakpointSiteID (thread, bp_site_sp->GetID()); 459254721Semaste else 460254721Semaste return StopInfoSP(); 461254721Semaste } 462254721Semaste 463254721Semaste // Don't call this a trace if we weren't single stepping this thread. 464254721Semaste if (is_trace_if_actual_breakpoint_missing && thread.GetTemporaryResumeState() == eStateStepping) 465254721Semaste { 466254721Semaste return StopInfo::CreateStopReasonToTrace (thread); 467254721Semaste } 468254721Semaste } 469254721Semaste } 470254721Semaste break; 471254721Semaste 472254721Semaste case 7: // EXC_SYSCALL 473254721Semaste case 8: // EXC_MACH_SYSCALL 474254721Semaste case 9: // EXC_RPC_ALERT 475254721Semaste case 10: // EXC_CRASH 476254721Semaste break; 477254721Semaste } 478254721Semaste 479254721Semaste return StopInfoSP(new StopInfoMachException (thread, exc_type, exc_data_count, exc_code, exc_sub_code)); 480254721Semaste } 481254721Semaste return StopInfoSP(); 482254721Semaste} 483