//===-- MachThread.h --------------------------------------------*- C++ -*-===// // // The LLVM Compiler Infrastructure // // This file is distributed under the University of Illinois Open Source // License. See LICENSE.TXT for details. // //===----------------------------------------------------------------------===// // // Created by Greg Clayton on 6/19/07. // //===----------------------------------------------------------------------===// #ifndef __MachThread_h__ #define __MachThread_h__ #include #include #include #include #include #include #include "DNBArch.h" #include "DNBRegisterInfo.h" #include "MachException.h" #include "PThreadCondition.h" #include "PThreadMutex.h" #include "ThreadInfo.h" class DNBBreakpoint; class MachProcess; class MachThreadList; class MachThread { public: MachThread(MachProcess *process, bool is_64_bit, uint64_t unique_thread_id = 0, thread_t mach_port_number = 0); ~MachThread(); MachProcess *Process() { return m_process; } const MachProcess *Process() const { return m_process; } nub_process_t ProcessID() const; void Dump(uint32_t index); uint64_t ThreadID() const { return m_unique_id; } thread_t MachPortNumber() const { return m_mach_port_number; } thread_t InferiorThreadID() const; uint32_t SequenceID() const { return m_seq_id; } static bool ThreadIDIsValid( uint64_t thread); // The 64-bit system-wide unique thread identifier static bool MachPortNumberIsValid(thread_t thread); // The mach port # for // this thread in // debugserver namespace void Resume(bool others_stopped); void Suspend(); bool SetSuspendCountBeforeResume(bool others_stopped); bool RestoreSuspendCountAfterStop(); bool GetRegisterState(int flavor, bool force); bool SetRegisterState(int flavor); uint64_t GetPC(uint64_t failValue = INVALID_NUB_ADDRESS); // Get program counter bool SetPC(uint64_t value); // Set program counter uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS); // Get stack pointer DNBBreakpoint *CurrentBreakpoint(); uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *breakpoint); uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *watchpoint, bool also_set_on_task); bool DisableHardwareBreakpoint(const DNBBreakpoint *breakpoint); bool DisableHardwareWatchpoint(const DNBBreakpoint *watchpoint, bool also_set_on_task); uint32_t NumSupportedHardwareWatchpoints() const; bool RollbackTransForHWP(); bool FinishTransForHWP(); nub_state_t GetState(); void SetState(nub_state_t state); void ThreadWillResume(const DNBThreadResumeAction *thread_action, bool others_stopped = false); bool ShouldStop(bool &step_more); bool IsStepping(); bool ThreadDidStop(); bool NotifyException(MachException::Data &exc); const MachException::Data &GetStopException() { return m_stop_exception; } nub_size_t GetNumRegistersInSet(nub_size_t regSet) const; const char *GetRegisterSetName(nub_size_t regSet) const; const DNBRegisterInfo *GetRegisterInfo(nub_size_t regSet, nub_size_t regIndex) const; void DumpRegisterState(nub_size_t regSet); const DNBRegisterSetInfo *GetRegisterSetInfo(nub_size_t *num_reg_sets) const; bool GetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx, DNBRegisterValue *reg_value); bool SetRegisterValue(uint32_t reg_set_idx, uint32_t reg_idx, const DNBRegisterValue *reg_value); nub_size_t GetRegisterContext(void *buf, nub_size_t buf_len); nub_size_t SetRegisterContext(const void *buf, nub_size_t buf_len); uint32_t SaveRegisterState(); bool RestoreRegisterState(uint32_t save_id); void NotifyBreakpointChanged(const DNBBreakpoint *bp) {} bool IsUserReady(); struct thread_basic_info *GetBasicInfo(); const char *GetBasicInfoAsString() const; const char *GetName(); DNBArchProtocol *GetArchProtocol() { return m_arch_ap.get(); } ThreadInfo::QoS GetRequestedQoS(nub_addr_t tsd, uint64_t dti_qos_class_index); nub_addr_t GetPThreadT(); nub_addr_t GetDispatchQueueT(); nub_addr_t GetTSDAddressForThread(uint64_t plo_pthread_tsd_base_address_offset, uint64_t plo_pthread_tsd_base_offset, uint64_t plo_pthread_tsd_entry_size); static uint64_t GetGloballyUniqueThreadIDForMachPortID(thread_t mach_port_id); protected: static bool GetBasicInfo(thread_t threadID, struct thread_basic_info *basic_info); bool GetIdentifierInfo(); // const char * // GetDispatchQueueName(); // MachProcess *m_process; // The process that owns this thread uint64_t m_unique_id; // The globally unique ID for this thread (nub_thread_t) thread_t m_mach_port_number; // The mach port # for this thread in debugserver // namesp. uint32_t m_seq_id; // A Sequential ID that increments with each new thread nub_state_t m_state; // The state of our process PThreadMutex m_state_mutex; // Multithreaded protection for m_state struct thread_basic_info m_basic_info; // Basic information for a thread used // to see if a thread is valid int32_t m_suspend_count; // The current suspend count > 0 means we have // suspended m_suspendCount times, // < 0 means we have resumed it m_suspendCount // times. MachException::Data m_stop_exception; // The best exception that describes why // this thread is stopped std::unique_ptr m_arch_ap; // Arch specific information for register state and more const DNBRegisterSetInfo *m_reg_sets; // Register set information for this thread nub_size_t m_num_reg_sets; thread_identifier_info_data_t m_ident_info; struct proc_threadinfo m_proc_threadinfo; std::string m_dispatch_queue_name; bool m_is_64_bit; // qos_class_t _pthread_qos_class_decode(pthread_priority_t priority, int *, // unsigned long *); unsigned int (*m_pthread_qos_class_decode)(unsigned long priority, int *, unsigned long *); private: friend class MachThreadList; }; typedef std::shared_ptr MachThreadSP; #endif