#ifndef LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_MACHTHREAD_H
#define LLDB_TOOLS_DEBUGSERVER_SOURCE_MACOSX_MACHTHREAD_H
#include <string>
#include <vector>
#include <libproc.h>
#include <mach/mach.h>
#include <pthread.h>
#include <sys/signal.h>
#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);
static bool MachPortNumberIsValid(thread_t thread);
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);
bool SetPC(uint64_t value);
uint64_t GetSP(uint64_t failValue = INVALID_NUB_ADDRESS);
DNBBreakpoint *CurrentBreakpoint();
uint32_t EnableHardwareBreakpoint(const DNBBreakpoint *breakpoint,
bool also_set_on_task);
uint32_t EnableHardwareWatchpoint(const DNBBreakpoint *watchpoint,
bool also_set_on_task);
bool DisableHardwareBreakpoint(const DNBBreakpoint *breakpoint,
bool also_set_on_task);
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_up.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();
MachProcess *m_process;
uint64_t m_unique_id;
thread_t m_mach_port_number;
uint32_t m_seq_id;
nub_state_t m_state;
PThreadMutex m_state_mutex;
struct thread_basic_info m_basic_info;
int32_t m_suspend_count;
MachException::Data m_stop_exception;
std::unique_ptr<DNBArchProtocol>
m_arch_up;
const DNBRegisterSetInfo
*m_reg_sets;
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;
unsigned int (*m_pthread_qos_class_decode)(unsigned long priority, int *,
unsigned long *);
private:
friend class MachThreadList;
};
typedef std::shared_ptr<MachThread> MachThreadSP;
#endif