1 //===-- NativeThreadDarwin.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 "NativeThreadDarwin.h" 11 12 // C includes 13 #include <libproc.h> 14 15 // LLDB includes 16 #include "lldb/Utility/Stream.h" 17 18 #include "NativeProcessDarwin.h" 19 20 using namespace lldb; 21 using namespace lldb_private; 22 using namespace lldb_private::process_darwin; 23 24 uint64_t NativeThreadDarwin::GetGloballyUniqueThreadIDForMachPortID( 25 ::thread_t mach_port_id) { 26 thread_identifier_info_data_t tident; 27 mach_msg_type_number_t tident_count = THREAD_IDENTIFIER_INFO_COUNT; 28 29 auto mach_err = ::thread_info(mach_port_id, THREAD_IDENTIFIER_INFO, 30 (thread_info_t)&tident, &tident_count); 31 if (mach_err != KERN_SUCCESS) { 32 // When we fail to get thread info for the supposed port, assume it is 33 // really a globally unique thread id already, or return the best thing we 34 // can, which is the thread port. 35 return mach_port_id; 36 } 37 return tident.thread_id; 38 } 39 40 NativeThreadDarwin::NativeThreadDarwin(NativeProcessDarwin *process, 41 bool is_64_bit, 42 lldb::tid_t unique_thread_id, 43 ::thread_t mach_thread_port) 44 : NativeThreadProtocol(process, unique_thread_id), 45 m_mach_thread_port(mach_thread_port), m_basic_info(), 46 m_proc_threadinfo() {} 47 48 bool NativeThreadDarwin::GetIdentifierInfo() { 49 // Don't try to get the thread info once and cache it for the life of the 50 // thread. It changes over time, for instance if the thread name changes, 51 // then the thread_handle also changes... So you have to refetch it every 52 // time. 53 mach_msg_type_number_t count = THREAD_IDENTIFIER_INFO_COUNT; 54 kern_return_t kret = ::thread_info(m_mach_thread_port, THREAD_IDENTIFIER_INFO, 55 (thread_info_t)&m_ident_info, &count); 56 return kret == KERN_SUCCESS; 57 58 return false; 59 } 60 61 std::string NativeThreadDarwin::GetName() { 62 std::string name; 63 64 if (GetIdentifierInfo()) { 65 auto process_sp = GetProcess(); 66 if (!process_sp) { 67 name = "<unavailable>"; 68 return name; 69 } 70 71 int len = ::proc_pidinfo(process_sp->GetID(), PROC_PIDTHREADINFO, 72 m_ident_info.thread_handle, &m_proc_threadinfo, 73 sizeof(m_proc_threadinfo)); 74 75 if (len && m_proc_threadinfo.pth_name[0]) 76 name = m_proc_threadinfo.pth_name; 77 } 78 return name; 79 } 80 81 lldb::StateType NativeThreadDarwin::GetState() { 82 // TODO implement 83 return eStateInvalid; 84 } 85 86 bool NativeThreadDarwin::GetStopReason(ThreadStopInfo &stop_info, 87 std::string &description) { 88 // TODO implement 89 return false; 90 } 91 92 NativeRegisterContextSP NativeThreadDarwin::GetRegisterContext() { 93 // TODO implement 94 return NativeRegisterContextSP(); 95 } 96 97 Status NativeThreadDarwin::SetWatchpoint(lldb::addr_t addr, size_t size, 98 uint32_t watch_flags, bool hardware) { 99 Status error; 100 error.SetErrorString("not yet implemented"); 101 return error; 102 } 103 104 Status NativeThreadDarwin::RemoveWatchpoint(lldb::addr_t addr) { 105 Status error; 106 error.SetErrorString("not yet implemented"); 107 return error; 108 } 109 110 void NativeThreadDarwin::Dump(Stream &stream) const { 111 // This is what we really want once we have the thread class wired up. 112 #if 0 113 DNBLogThreaded("[%3u] #%3u tid: 0x%8.8" PRIx64 ", pc: 0x%16.16" PRIx64 ", sp: 0x%16.16" PRIx64 ", user: %d.%6.6d, system: %d.%6.6d, cpu: %2d, policy: %2d, run_state: %2d (%s), flags: %2d, suspend_count: %2d (current %2d), sleep_time: %d", 114 index, 115 m_seq_id, 116 m_unique_id, 117 GetPC(INVALID_NUB_ADDRESS), 118 GetSP(INVALID_NUB_ADDRESS), 119 m_basic_info.user_time.seconds, m_basic_info.user_time.microseconds, 120 m_basic_info.system_time.seconds, m_basic_info.system_time.microseconds, 121 m_basic_info.cpu_usage, 122 m_basic_info.policy, 123 m_basic_info.run_state, 124 thread_run_state, 125 m_basic_info.flags, 126 m_basic_info.suspend_count, m_suspend_count, 127 m_basic_info.sleep_time); 128 129 #else 130 // Here's all we have right now. 131 stream.Printf("tid: 0x%8.8" PRIx64 ", thread port: 0x%4.4x", GetID(), 132 m_mach_thread_port); 133 #endif 134 } 135 136 bool NativeThreadDarwin::NotifyException(MachException::Data &exc) { 137 // TODO implement this. 138 #if 0 139 // Allow the arch specific protocol to process (MachException::Data &)exc 140 // first before possible reassignment of m_stop_exception with exc. See 141 // also MachThread::GetStopException(). 142 bool handled = m_arch_ap->NotifyException(exc); 143 144 if (m_stop_exception.IsValid()) 145 { 146 // We may have more than one exception for a thread, but we need to 147 // only remember the one that we will say is the reason we stopped. We 148 // may have been single stepping and also gotten a signal exception, so 149 // just remember the most pertinent one. 150 if (m_stop_exception.IsBreakpoint()) 151 m_stop_exception = exc; 152 } 153 else 154 { 155 m_stop_exception = exc; 156 } 157 158 return handled; 159 #else 160 // Pretend we handled it. 161 return true; 162 #endif 163 } 164 165 bool NativeThreadDarwin::ShouldStop(bool &step_more) const { 166 // TODO: implement this 167 #if 0 168 // See if this thread is at a breakpoint? 169 DNBBreakpoint *bp = CurrentBreakpoint(); 170 171 if (bp) 172 { 173 // This thread is sitting at a breakpoint, ask the breakpoint if we 174 // should be stopping here. 175 return true; 176 } 177 else 178 { 179 if (m_arch_ap->StepNotComplete()) 180 { 181 step_more = true; 182 return false; 183 } 184 // The thread state is used to let us know what the thread was trying 185 // to do. MachThread::ThreadWillResume() will set the thread state to 186 // various values depending if the thread was the current thread and if 187 // it was to be single stepped, or resumed. 188 if (GetState() == eStateRunning) 189 { 190 // If our state is running, then we should continue as we are in 191 // the process of stepping over a breakpoint. 192 return false; 193 } 194 else 195 { 196 // Stop if we have any kind of valid exception for this thread. 197 if (GetStopException().IsValid()) 198 return true; 199 } 200 } 201 return false; 202 #else 203 return false; 204 #endif 205 } 206 207 void NativeThreadDarwin::ThreadDidStop() { 208 // TODO implement this. 209 #if 0 210 // This thread has existed prior to resuming under debug nub control, and 211 // has just been stopped. Do any cleanup that needs to be done after 212 // running. 213 214 // The thread state and breakpoint will still have the same values as they 215 // had prior to resuming the thread, so it makes it easy to check if we 216 // were trying to step a thread, or we tried to resume while being at a 217 // breakpoint. 218 219 // When this method gets called, the process state is still in the state it 220 // was in while running so we can act accordingly. 221 m_arch_ap->ThreadDidStop(); 222 223 224 // We may have suspended this thread so the primary thread could step 225 // without worrying about race conditions, so lets restore our suspend 226 // count. 227 RestoreSuspendCountAfterStop(); 228 229 // Update the basic information for a thread 230 MachThread::GetBasicInfo(m_mach_port_number, &m_basic_info); 231 232 if (m_basic_info.suspend_count > 0) 233 SetState(eStateSuspended); 234 else 235 SetState(eStateStopped); 236 #endif 237 } 238 239 bool NativeThreadDarwin::MachPortNumberIsValid(::thread_t thread) { 240 return thread != (::thread_t)(0); 241 } 242 243 const struct thread_basic_info *NativeThreadDarwin::GetBasicInfo() const { 244 if (GetBasicInfo(m_mach_thread_port, &m_basic_info)) 245 return &m_basic_info; 246 return NULL; 247 } 248 249 bool NativeThreadDarwin::GetBasicInfo(::thread_t thread, 250 struct thread_basic_info *basicInfoPtr) { 251 if (MachPortNumberIsValid(thread)) { 252 unsigned int info_count = THREAD_BASIC_INFO_COUNT; 253 kern_return_t err = ::thread_info(thread, THREAD_BASIC_INFO, 254 (thread_info_t)basicInfoPtr, &info_count); 255 if (err == KERN_SUCCESS) 256 return true; 257 } 258 ::memset(basicInfoPtr, 0, sizeof(struct thread_basic_info)); 259 return false; 260 } 261 262 bool NativeThreadDarwin::IsUserReady() const { 263 if (m_basic_info.run_state == 0) 264 GetBasicInfo(); 265 266 switch (m_basic_info.run_state) { 267 default: 268 case TH_STATE_UNINTERRUPTIBLE: 269 break; 270 271 case TH_STATE_RUNNING: 272 case TH_STATE_STOPPED: 273 case TH_STATE_WAITING: 274 case TH_STATE_HALTED: 275 return true; 276 } 277 return false; 278 } 279 280 NativeProcessDarwinSP NativeThreadDarwin::GetNativeProcessDarwinSP() { 281 return std::static_pointer_cast<NativeProcessDarwin>(GetProcess()); 282 } 283