130fdc8d8SChris Lattner //===-- MachThread.h --------------------------------------------*- C++ -*-===//
230fdc8d8SChris Lattner //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
630fdc8d8SChris Lattner //
730fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
830fdc8d8SChris Lattner //
930fdc8d8SChris Lattner //  Created by Greg Clayton on 6/19/07.
1030fdc8d8SChris Lattner //
1130fdc8d8SChris Lattner //===----------------------------------------------------------------------===//
1230fdc8d8SChris Lattner 
13*cdc514e4SJonas Devlieghere #ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_MACHTHREAD_H
14*cdc514e4SJonas Devlieghere #define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_MACHTHREAD_H
1530fdc8d8SChris Lattner 
1630fdc8d8SChris Lattner #include <string>
1730fdc8d8SChris Lattner #include <vector>
1830fdc8d8SChris Lattner 
1930fdc8d8SChris Lattner #include <libproc.h>
2030fdc8d8SChris Lattner #include <mach/mach.h>
2130fdc8d8SChris Lattner #include <pthread.h>
2230fdc8d8SChris Lattner #include <sys/signal.h>
2330fdc8d8SChris Lattner 
2430fdc8d8SChris Lattner #include "DNBArch.h"
2530fdc8d8SChris Lattner #include "DNBRegisterInfo.h"
26b9c1b51eSKate Stone #include "MachException.h"
27b9c1b51eSKate Stone #include "PThreadCondition.h"
28b9c1b51eSKate Stone #include "PThreadMutex.h"
2930fdc8d8SChris Lattner 
30705b1809SJason Molenda #include "ThreadInfo.h"
31705b1809SJason Molenda 
3230fdc8d8SChris Lattner class DNBBreakpoint;
3330fdc8d8SChris Lattner class MachProcess;
34a9b68f4dSJohnny Chen class MachThreadList;
3530fdc8d8SChris Lattner 
36b9c1b51eSKate Stone class MachThread {
3730fdc8d8SChris Lattner public:
38b9c1b51eSKate Stone   MachThread(MachProcess *process, bool is_64_bit,
39b9c1b51eSKate Stone              uint64_t unique_thread_id = 0, thread_t mach_port_number = 0);
4030fdc8d8SChris Lattner   ~MachThread();
4130fdc8d8SChris Lattner 
Process()4230fdc8d8SChris Lattner   MachProcess *Process() { return m_process; }
Process()43b9c1b51eSKate Stone   const MachProcess *Process() const { return m_process; }
4430fdc8d8SChris Lattner   nub_process_t ProcessID() const;
4530fdc8d8SChris Lattner   void Dump(uint32_t index);
ThreadID()461c73911dSJason Molenda   uint64_t ThreadID() const { return m_unique_id; }
MachPortNumber()471c73911dSJason Molenda   thread_t MachPortNumber() const { return m_mach_port_number; }
4830fdc8d8SChris Lattner   thread_t InferiorThreadID() const;
4930fdc8d8SChris Lattner 
SequenceID()5030fdc8d8SChris Lattner   uint32_t SequenceID() const { return m_seq_id; }
51b9c1b51eSKate Stone   static bool ThreadIDIsValid(
52b9c1b51eSKate Stone       uint64_t thread); // The 64-bit system-wide unique thread identifier
53b9c1b51eSKate Stone   static bool MachPortNumberIsValid(thread_t thread); // The mach port # for
54b9c1b51eSKate Stone                                                       // this thread in
55b9c1b51eSKate Stone                                                       // debugserver namespace
569411ddb6SJim Ingham   void Resume(bool others_stopped);
579411ddb6SJim Ingham   void Suspend();
589411ddb6SJim Ingham   bool SetSuspendCountBeforeResume(bool others_stopped);
599411ddb6SJim Ingham   bool RestoreSuspendCountAfterStop();
60cdc7322bSGreg Clayton 
6130fdc8d8SChris Lattner   bool GetRegisterState(int flavor, bool force);
6230fdc8d8SChris Lattner   bool SetRegisterState(int flavor);
63b9c1b51eSKate Stone   uint64_t
64b9c1b51eSKate Stone   GetPC(uint64_t failValue = INVALID_NUB_ADDRESS); // Get program counter
6530fdc8d8SChris Lattner   bool SetPC(uint64_t value);                      // Set program counter
6630fdc8d8SChris Lattner   uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer
6730fdc8d8SChris Lattner 
68d8cf1a11SGreg Clayton   DNBBreakpoint *CurrentBreakpoint();
699902c8e3SJonas Devlieghere   uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *breakpoint,
709902c8e3SJonas Devlieghere                                     bool also_set_on_task);
71b9c1b51eSKate Stone   uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *watchpoint,
72b9c1b51eSKate Stone                                     bool also_set_on_task);
739902c8e3SJonas Devlieghere   bool DisableHardwareBreakpoint(const DNBBreakpoint *breakpoint,
749902c8e3SJonas Devlieghere                                  bool also_set_on_task);
75b9c1b51eSKate Stone   bool DisableHardwareWatchpoint(const DNBBreakpoint *watchpoint,
76b9c1b51eSKate Stone                                  bool also_set_on_task);
7764637205SJohnny Chen   uint32_t NumSupportedHardwareWatchpoints() const;
7884707560SJohnny Chen   bool RollbackTransForHWP();
7984707560SJohnny Chen   bool FinishTransForHWP();
8030fdc8d8SChris Lattner 
8130fdc8d8SChris Lattner   nub_state_t GetState();
8230fdc8d8SChris Lattner   void SetState(nub_state_t state);
8330fdc8d8SChris Lattner 
84b9c1b51eSKate Stone   void ThreadWillResume(const DNBThreadResumeAction *thread_action,
85b9c1b51eSKate Stone                         bool others_stopped = false);
8630fdc8d8SChris Lattner   bool ShouldStop(bool &step_more);
8730fdc8d8SChris Lattner   bool IsStepping();
8830fdc8d8SChris Lattner   bool ThreadDidStop();
8930fdc8d8SChris Lattner   bool NotifyException(MachException::Data &exc);
GetStopException()9030fdc8d8SChris Lattner   const MachException::Data &GetStopException() { return m_stop_exception; }
9130fdc8d8SChris Lattner 
92a026de05SBruce Mitchener   nub_size_t GetNumRegistersInSet(nub_size_t regSet) const;
93a026de05SBruce Mitchener   const char *GetRegisterSetName(nub_size_t regSet) const;
94b9c1b51eSKate Stone   const DNBRegisterInfo *GetRegisterInfo(nub_size_t regSet,
95b9c1b51eSKate Stone                                          nub_size_t regIndex) const;
96a026de05SBruce Mitchener   void DumpRegisterState(nub_size_t regSet);
97b9c1b51eSKate Stone   const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets) const;
98b9c1b51eSKate Stone   bool GetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx,
99b9c1b51eSKate Stone                         DNBRegisterValue *reg_value);
100b9c1b51eSKate Stone   bool SetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx,
101b9c1b51eSKate Stone                         const DNBRegisterValue *reg_value);
10230fdc8d8SChris Lattner   nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len);
10330fdc8d8SChris Lattner   nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len);
104f74cf86bSGreg Clayton   uint32_t SaveRegisterState();
105f74cf86bSGreg Clayton   bool RestoreRegisterState(uint32_t save_id);
106f74cf86bSGreg Clayton 
NotifyBreakpointChanged(const DNBBreakpoint * bp)107b9c1b51eSKate Stone   void NotifyBreakpointChanged(const DNBBreakpoint *bp) {}
1081b946bf6SGreg Clayton 
1091b946bf6SGreg Clayton   bool IsUserReady();
110b9c1b51eSKate Stone   struct thread_basic_info *GetBasicInfo();
11130fdc8d8SChris Lattner   const char *GetBasicInfoAsString() const;
11230fdc8d8SChris Lattner   const char *GetName();
1133af9ea56SGreg Clayton 
GetArchProtocol()114d5b44036SJonas Devlieghere   DNBArchProtocol *GetArchProtocol() { return m_arch_up.get(); }
1153af9ea56SGreg Clayton 
116705b1809SJason Molenda   ThreadInfo::QoS GetRequestedQoS(nub_addr_t tsd, uint64_t dti_qos_class_index);
117705b1809SJason Molenda   nub_addr_t GetPThreadT();
118705b1809SJason Molenda   nub_addr_t GetDispatchQueueT();
119b9c1b51eSKate Stone   nub_addr_t
120b9c1b51eSKate Stone   GetTSDAddressForThread(uint64_t plo_pthread_tsd_base_address_offset,
121b9c1b51eSKate Stone                          uint64_t plo_pthread_tsd_base_offset,
122b9c1b51eSKate Stone                          uint64_t plo_pthread_tsd_entry_size);
123705b1809SJason Molenda 
1241c73911dSJason Molenda   static uint64_t GetGloballyUniqueThreadIDForMachPortID(thread_t mach_port_id);
1251c73911dSJason Molenda 
12630fdc8d8SChris Lattner protected:
127b9c1b51eSKate Stone   static bool GetBasicInfo(thread_t threadID,
128b9c1b51eSKate Stone                            struct thread_basic_info *basic_info);
12930fdc8d8SChris Lattner 
130b9c1b51eSKate Stone   bool GetIdentifierInfo();
13130fdc8d8SChris Lattner 
13230fdc8d8SChris Lattner   //    const char *
13330fdc8d8SChris Lattner   //    GetDispatchQueueName();
13430fdc8d8SChris Lattner   //
13530fdc8d8SChris Lattner   MachProcess *m_process; // The process that owns this thread
1361c73911dSJason Molenda   uint64_t m_unique_id; // The globally unique ID for this thread (nub_thread_t)
137b9c1b51eSKate Stone   thread_t m_mach_port_number; // The mach port # for this thread in debugserver
138b9c1b51eSKate Stone                                // namesp.
13930fdc8d8SChris Lattner   uint32_t m_seq_id;   // A Sequential ID that increments with each new thread
14030fdc8d8SChris Lattner   nub_state_t m_state; // The state of our process
14130fdc8d8SChris Lattner   PThreadMutex m_state_mutex;            // Multithreaded protection for m_state
142b9c1b51eSKate Stone   struct thread_basic_info m_basic_info; // Basic information for a thread used
143b9c1b51eSKate Stone                                          // to see if a thread is valid
144b9c1b51eSKate Stone   int32_t m_suspend_count; // The current suspend count > 0 means we have
145b9c1b51eSKate Stone                            // suspended m_suspendCount times,
146b9c1b51eSKate Stone   //                           < 0 means we have resumed it m_suspendCount
147b9c1b51eSKate Stone   //                           times.
148b9c1b51eSKate Stone   MachException::Data m_stop_exception; // The best exception that describes why
149b9c1b51eSKate Stone                                         // this thread is stopped
150b9c1b51eSKate Stone   std::unique_ptr<DNBArchProtocol>
151d5b44036SJonas Devlieghere       m_arch_up; // Arch specific information for register state and more
152b9c1b51eSKate Stone   const DNBRegisterSetInfo
153b9c1b51eSKate Stone       *m_reg_sets; // Register set information for this thread
154c235ac76SGreg Clayton   nub_size_t m_num_reg_sets;
15530fdc8d8SChris Lattner   thread_identifier_info_data_t m_ident_info;
15630fdc8d8SChris Lattner   struct proc_threadinfo m_proc_threadinfo;
15730fdc8d8SChris Lattner   std::string m_dispatch_queue_name;
158705b1809SJason Molenda   bool m_is_64_bit;
159705b1809SJason Molenda 
160b9c1b51eSKate Stone   // qos_class_t _pthread_qos_class_decode(pthread_priority_t priority, int *,
161b9c1b51eSKate Stone   // unsigned long *);
162b9c1b51eSKate Stone   unsigned int (*m_pthread_qos_class_decode)(unsigned long priority, int *,
163b9c1b51eSKate Stone                                              unsigned long *);
16430fdc8d8SChris Lattner 
165a9b68f4dSJohnny Chen private:
166a9b68f4dSJohnny Chen   friend class MachThreadList;
16730fdc8d8SChris Lattner };
16830fdc8d8SChris Lattner 
1697b0992d9SGreg Clayton typedef std::shared_ptr<MachThread> MachThreadSP;
17030fdc8d8SChris Lattner 
17130fdc8d8SChris Lattner #endif
172