own port namepsace) as the thread identifier to using the system-wide globally unique thread id as the thread identifier number. MachThread.cpp keeps both the unique id and the mach port number for each thread. All layers outside MachThread class use the unique id with three exceptions: (1) Mach exceptions come in with the port number (thread_port) which needs to be translated, (2) any calls to low-level thread_get_state/thread_set_state/thread_suspend etc need to use the mach port number, (3) MachThreadList::UpdateThreadList which creates the MachThread objects gets the unique id and passes it to the MachThread ctor as an argument. In general, any time nub_thread_t is used, it is now referring to a unique thread id. Any time a thread_t is used, it is now referring to a mach port number. There was some interchangability of these types previously. nub_thread_t has also been changed to a 64-bit type which necessitated some printf specification string changes. I haven't been able to test these changes extensively yet but want to checkpoint the work. The scenarios I've been testing are all working correctly so while there may be some corner cases I haven't hit yet, I think it is substantially correct. <rdar://problem/12931414> llvm-svn: 175870
150 lines
6.5 KiB
C++
150 lines
6.5 KiB
C++
//===-- 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 <string>
|
|
#include <vector>
|
|
|
|
#include <libproc.h>
|
|
#include <mach/mach.h>
|
|
#include <pthread.h>
|
|
#include <sys/signal.h>
|
|
|
|
#include "PThreadCondition.h"
|
|
#include "PThreadMutex.h"
|
|
#include "MachException.h"
|
|
#include "DNBArch.h"
|
|
#include "DNBRegisterInfo.h"
|
|
|
|
class DNBBreakpoint;
|
|
class MachProcess;
|
|
class MachThreadList;
|
|
|
|
class MachThread
|
|
{
|
|
public:
|
|
|
|
MachThread (MachProcess *process, 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
|
|
|
|
nub_break_t CurrentBreakpoint();
|
|
uint32_t EnableHardwareBreakpoint (const DNBBreakpoint *breakpoint);
|
|
uint32_t EnableHardwareWatchpoint (const DNBBreakpoint *watchpoint);
|
|
bool DisableHardwareBreakpoint (const DNBBreakpoint *breakpoint);
|
|
bool DisableHardwareWatchpoint (const DNBBreakpoint *watchpoint);
|
|
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; }
|
|
|
|
uint32_t GetNumRegistersInSet(int regSet) const;
|
|
const char * GetRegisterSetName(int regSet) const;
|
|
const DNBRegisterInfo *
|
|
GetRegisterInfo(int regSet, int regIndex) const;
|
|
void DumpRegisterState(int 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);
|
|
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();
|
|
}
|
|
|
|
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
|
|
nub_break_t m_break_id; // Breakpoint that this thread is (stopped)/was(running) at (NULL for none)
|
|
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::auto_ptr<DNBArchProtocol> 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;
|
|
#ifdef THREAD_IDENTIFIER_INFO_COUNT
|
|
thread_identifier_info_data_t m_ident_info;
|
|
struct proc_threadinfo m_proc_threadinfo;
|
|
std::string m_dispatch_queue_name;
|
|
#endif
|
|
|
|
private:
|
|
friend class MachThreadList;
|
|
void HardwareWatchpointStateChanged(); // Provide a chance to update the global view of the hardware watchpoint state
|
|
};
|
|
|
|
typedef STD_SHARED_PTR(MachThread) MachThreadSP;
|
|
|
|
#endif
|