1 //===-- MachThread.h --------------------------------------------*- 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 //  Created by Greg Clayton on 6/19/07.
11 //
12 //===----------------------------------------------------------------------===//
13 
14 #ifndef __MachThread_h__
15 #define __MachThread_h__
16 
17 #include <string>
18 #include <vector>
19 
20 #include <libproc.h>
21 #include <mach/mach.h>
22 #include <pthread.h>
23 #include <sys/signal.h>
24 
25 #include "DNBArch.h"
26 #include "DNBRegisterInfo.h"
27 #include "MachException.h"
28 #include "PThreadCondition.h"
29 #include "PThreadMutex.h"
30 
31 #include "ThreadInfo.h"
32 
33 class DNBBreakpoint;
34 class MachProcess;
35 class MachThreadList;
36 
37 class MachThread {
38 public:
39   MachThread(MachProcess *process, bool is_64_bit,
40              uint64_t unique_thread_id = 0, thread_t mach_port_number = 0);
41   ~MachThread();
42 
43   MachProcess *Process() { return m_process; }
44   const MachProcess *Process() const { return m_process; }
45   nub_process_t ProcessID() const;
46   void Dump(uint32_t index);
47   uint64_t ThreadID() const { return m_unique_id; }
48   thread_t MachPortNumber() const { return m_mach_port_number; }
49   thread_t InferiorThreadID() const;
50 
51   uint32_t SequenceID() const { return m_seq_id; }
52   static bool ThreadIDIsValid(
53       uint64_t thread); // The 64-bit system-wide unique thread identifier
54   static bool MachPortNumberIsValid(thread_t thread); // The mach port # for
55                                                       // this thread in
56                                                       // debugserver namespace
57   void Resume(bool others_stopped);
58   void Suspend();
59   bool SetSuspendCountBeforeResume(bool others_stopped);
60   bool RestoreSuspendCountAfterStop();
61 
62   bool GetRegisterState(int flavor, bool force);
63   bool SetRegisterState(int flavor);
64   uint64_t
65   GetPC(uint64_t failValue = INVALID_NUB_ADDRESS); // Get program counter
66   bool SetPC(uint64_t value);                      // Set program counter
67   uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer
68 
69   DNBBreakpoint *CurrentBreakpoint();
70   uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *breakpoint);
71   uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *watchpoint,
72                                     bool also_set_on_task);
73   bool DisableHardwareBreakpoint(const DNBBreakpoint *breakpoint);
74   bool DisableHardwareWatchpoint(const DNBBreakpoint *watchpoint,
75                                  bool also_set_on_task);
76   uint32_t NumSupportedHardwareWatchpoints() const;
77   bool RollbackTransForHWP();
78   bool FinishTransForHWP();
79 
80   nub_state_t GetState();
81   void SetState(nub_state_t state);
82 
83   void ThreadWillResume(const DNBThreadResumeAction *thread_action,
84                         bool others_stopped = false);
85   bool ShouldStop(bool &step_more);
86   bool IsStepping();
87   bool ThreadDidStop();
88   bool NotifyException(MachException::Data &exc);
89   const MachException::Data &GetStopException() { return m_stop_exception; }
90 
91   nub_size_t GetNumRegistersInSet(nub_size_t regSet) const;
92   const char *GetRegisterSetName(nub_size_t regSet) const;
93   const DNBRegisterInfo *GetRegisterInfo(nub_size_t regSet,
94                                          nub_size_t regIndex) const;
95   void DumpRegisterState(nub_size_t regSet);
96   const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets) const;
97   bool GetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx,
98                         DNBRegisterValue *reg_value);
99   bool SetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx,
100                         const DNBRegisterValue *reg_value);
101   nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len);
102   nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len);
103   uint32_t SaveRegisterState();
104   bool RestoreRegisterState(uint32_t save_id);
105 
106   void NotifyBreakpointChanged(const DNBBreakpoint *bp) {}
107 
108   bool IsUserReady();
109   struct thread_basic_info *GetBasicInfo();
110   const char *GetBasicInfoAsString() const;
111   const char *GetName();
112 
113   DNBArchProtocol *GetArchProtocol() { return m_arch_ap.get(); }
114 
115   ThreadInfo::QoS GetRequestedQoS(nub_addr_t tsd, uint64_t dti_qos_class_index);
116   nub_addr_t GetPThreadT();
117   nub_addr_t GetDispatchQueueT();
118   nub_addr_t
119   GetTSDAddressForThread(uint64_t plo_pthread_tsd_base_address_offset,
120                          uint64_t plo_pthread_tsd_base_offset,
121                          uint64_t plo_pthread_tsd_entry_size);
122 
123   static uint64_t GetGloballyUniqueThreadIDForMachPortID(thread_t mach_port_id);
124 
125 protected:
126   static bool GetBasicInfo(thread_t threadID,
127                            struct thread_basic_info *basic_info);
128 
129   bool GetIdentifierInfo();
130 
131   //    const char *
132   //    GetDispatchQueueName();
133   //
134   MachProcess *m_process; // The process that owns this thread
135   uint64_t m_unique_id; // The globally unique ID for this thread (nub_thread_t)
136   thread_t m_mach_port_number; // The mach port # for this thread in debugserver
137                                // namesp.
138   uint32_t m_seq_id;   // A Sequential ID that increments with each new thread
139   nub_state_t m_state; // The state of our process
140   PThreadMutex m_state_mutex;            // Multithreaded protection for m_state
141   struct thread_basic_info m_basic_info; // Basic information for a thread used
142                                          // to see if a thread is valid
143   int32_t m_suspend_count; // The current suspend count > 0 means we have
144                            // suspended m_suspendCount times,
145   //                           < 0 means we have resumed it m_suspendCount
146   //                           times.
147   MachException::Data m_stop_exception; // The best exception that describes why
148                                         // this thread is stopped
149   std::unique_ptr<DNBArchProtocol>
150       m_arch_ap; // Arch specific information for register state and more
151   const DNBRegisterSetInfo
152       *m_reg_sets; // Register set information for this thread
153   nub_size_t m_num_reg_sets;
154   thread_identifier_info_data_t m_ident_info;
155   struct proc_threadinfo m_proc_threadinfo;
156   std::string m_dispatch_queue_name;
157   bool m_is_64_bit;
158 
159   // qos_class_t _pthread_qos_class_decode(pthread_priority_t priority, int *,
160   // unsigned long *);
161   unsigned int (*m_pthread_qos_class_decode)(unsigned long priority, int *,
162                                              unsigned long *);
163 
164 private:
165   friend class MachThreadList;
166 };
167 
168 typedef std::shared_ptr<MachThread> MachThreadSP;
169 
170 #endif
171