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