1 //===-- ThreadMachCore.cpp ------------------------------------------------===// 2 // 3 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. 4 // See https://llvm.org/LICENSE.txt for license information. 5 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception 6 // 7 //===----------------------------------------------------------------------===// 8 9 #include "ThreadMachCore.h" 10 11 #include "lldb/Breakpoint/Watchpoint.h" 12 #include "lldb/Host/SafeMachO.h" 13 #include "lldb/Symbol/ObjectFile.h" 14 #include "lldb/Target/AppleArm64ExceptionClass.h" 15 #include "lldb/Target/Process.h" 16 #include "lldb/Target/RegisterContext.h" 17 #include "lldb/Target/StopInfo.h" 18 #include "lldb/Target/Target.h" 19 #include "lldb/Target/Unwind.h" 20 #include "lldb/Utility/ArchSpec.h" 21 #include "lldb/Utility/DataExtractor.h" 22 #include "lldb/Utility/RegisterValue.h" 23 #include "lldb/Utility/State.h" 24 #include "lldb/Utility/StreamString.h" 25 26 #include "ProcessMachCore.h" 27 //#include "RegisterContextKDP_arm.h" 28 //#include "RegisterContextKDP_i386.h" 29 //#include "RegisterContextKDP_x86_64.h" 30 31 using namespace lldb; 32 using namespace lldb_private; 33 34 // Thread Registers 35 36 ThreadMachCore::ThreadMachCore(Process &process, lldb::tid_t tid) 37 : Thread(process, tid), m_thread_name(), m_dispatch_queue_name(), 38 m_thread_dispatch_qaddr(LLDB_INVALID_ADDRESS), m_thread_reg_ctx_sp() {} 39 40 ThreadMachCore::~ThreadMachCore() { DestroyThread(); } 41 42 const char *ThreadMachCore::GetName() { 43 if (m_thread_name.empty()) 44 return nullptr; 45 return m_thread_name.c_str(); 46 } 47 48 void ThreadMachCore::RefreshStateAfterStop() { 49 // Invalidate all registers in our register context. We don't set "force" to 50 // true because the stop reply packet might have had some register values 51 // that were expedited and these will already be copied into the register 52 // context by the time this function gets called. The KDPRegisterContext 53 // class has been made smart enough to detect when it needs to invalidate 54 // which registers are valid by putting hooks in the register read and 55 // register supply functions where they check the process stop ID and do the 56 // right thing. 57 const bool force = false; 58 GetRegisterContext()->InvalidateIfNeeded(force); 59 } 60 61 bool ThreadMachCore::ThreadIDIsValid(lldb::tid_t thread) { return thread != 0; } 62 63 lldb::RegisterContextSP ThreadMachCore::GetRegisterContext() { 64 if (!m_reg_context_sp) 65 m_reg_context_sp = CreateRegisterContextForFrame(nullptr); 66 return m_reg_context_sp; 67 } 68 69 lldb::RegisterContextSP 70 ThreadMachCore::CreateRegisterContextForFrame(StackFrame *frame) { 71 lldb::RegisterContextSP reg_ctx_sp; 72 uint32_t concrete_frame_idx = 0; 73 74 if (frame) 75 concrete_frame_idx = frame->GetConcreteFrameIndex(); 76 77 if (concrete_frame_idx == 0) { 78 if (!m_thread_reg_ctx_sp) { 79 ProcessSP process_sp(GetProcess()); 80 81 ObjectFile *core_objfile = 82 static_cast<ProcessMachCore *>(process_sp.get())->GetCoreObjectFile(); 83 if (core_objfile) 84 m_thread_reg_ctx_sp = 85 core_objfile->GetThreadContextAtIndex(GetID(), *this); 86 } 87 reg_ctx_sp = m_thread_reg_ctx_sp; 88 } else { 89 reg_ctx_sp = GetUnwinder().CreateRegisterContextForFrame(frame); 90 } 91 return reg_ctx_sp; 92 } 93 94 static bool IsCrashExceptionClass(AppleArm64ExceptionClass EC) { 95 switch (EC) { 96 case AppleArm64ExceptionClass::ESR_EC_UNCATEGORIZED: 97 case AppleArm64ExceptionClass::ESR_EC_SVC_32: 98 case AppleArm64ExceptionClass::ESR_EC_SVC_64: 99 // In the ARM exception model, a process takes an exception when asking the 100 // kernel to service a system call. Don't treat this like a crash. 101 return false; 102 default: 103 return true; 104 } 105 } 106 107 bool ThreadMachCore::CalculateStopInfo() { 108 ProcessSP process_sp(GetProcess()); 109 if (process_sp) { 110 StopInfoSP stop_info; 111 RegisterContextSP reg_ctx_sp = GetRegisterContext(); 112 113 if (reg_ctx_sp) { 114 Target &target = process_sp->GetTarget(); 115 const ArchSpec arch_spec = target.GetArchitecture(); 116 const uint32_t cputype = arch_spec.GetMachOCPUType(); 117 118 if (cputype == llvm::MachO::CPU_TYPE_ARM64 || 119 cputype == llvm::MachO::CPU_TYPE_ARM64_32) { 120 const RegisterInfo *esr_info = reg_ctx_sp->GetRegisterInfoByName("esr"); 121 const RegisterInfo *far_info = reg_ctx_sp->GetRegisterInfoByName("far"); 122 RegisterValue esr, far; 123 if (reg_ctx_sp->ReadRegister(esr_info, esr) && 124 reg_ctx_sp->ReadRegister(far_info, far)) { 125 const uint32_t esr_val = esr.GetAsUInt32(); 126 const AppleArm64ExceptionClass exception_class = 127 getAppleArm64ExceptionClass(esr_val); 128 if (IsCrashExceptionClass(exception_class)) { 129 StreamString S; 130 S.Printf("%s (fault address: 0x%" PRIx64 ")", 131 toString(exception_class), far.GetAsUInt64()); 132 stop_info = 133 StopInfo::CreateStopReasonWithException(*this, S.GetData()); 134 } 135 } 136 } 137 } 138 139 // Set a stop reason for crashing threads only so that they get selected 140 // preferentially. 141 if (stop_info) 142 SetStopInfo(stop_info); 143 return true; 144 } 145 return false; 146 } 147