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