Imported Upstream version 6.10.0.49

Former-commit-id: 1d6753294b2993e1fbf92de9366bb9544db4189b
This commit is contained in:
Xamarin Public Jenkins (auto-signing)
2020-01-16 16:38:04 +00:00
parent d94e79959b
commit 468663ddbb
48518 changed files with 2789335 additions and 61176 deletions

View File

@ -0,0 +1,28 @@
include_directories(.)
include_directories(../POSIX)
include_directories(../Utility)
add_lldb_library(lldbPluginProcessFreeBSD PLUGIN
ProcessFreeBSD.cpp
FreeBSDThread.cpp
ProcessMonitor.cpp
POSIXStopInfo.cpp
RegisterContextPOSIXProcessMonitor_arm.cpp
RegisterContextPOSIXProcessMonitor_arm64.cpp
RegisterContextPOSIXProcessMonitor_powerpc.cpp
RegisterContextPOSIXProcessMonitor_x86.cpp
RegisterContextPOSIXProcessMonitor_mips64.cpp
LINK_LIBS
lldbBreakpoint
lldbCore
lldbHost
lldbSymbol
lldbTarget
lldbUtility
lldbPluginProcessUtility
lldbPluginProcessPOSIX
LINK_COMPONENTS
Support
)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,123 @@
//===-- FreeBSDThread.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_FreeBSDThread_H_
#define liblldb_FreeBSDThread_H_
// C++ Includes
#include <memory>
#include <string>
// Other libraries and framework includes
#include "RegisterContextPOSIX.h"
#include "lldb/Target/Thread.h"
class ProcessMessage;
class ProcessMonitor;
class POSIXBreakpointProtocol;
//------------------------------------------------------------------------------
// @class FreeBSDThread
// @brief Abstraction of a FreeBSD thread.
class FreeBSDThread : public lldb_private::Thread {
public:
//------------------------------------------------------------------
// Constructors and destructors
//------------------------------------------------------------------
FreeBSDThread(lldb_private::Process &process, lldb::tid_t tid);
virtual ~FreeBSDThread();
// POSIXThread
void RefreshStateAfterStop() override;
// This notifies the thread when a private stop occurs.
void DidStop() override;
const char *GetInfo() override;
void SetName(const char *name) override;
const char *GetName() override;
lldb::RegisterContextSP GetRegisterContext() override;
lldb::RegisterContextSP
CreateRegisterContextForFrame(lldb_private::StackFrame *frame) override;
lldb::addr_t GetThreadPointer() override;
//--------------------------------------------------------------------------
// These functions provide a mapping from the register offset
// back to the register index or name for use in debugging or log
// output.
unsigned GetRegisterIndexFromOffset(unsigned offset);
const char *GetRegisterName(unsigned reg);
const char *GetRegisterNameFromOffset(unsigned offset);
//--------------------------------------------------------------------------
// These methods form a specialized interface to POSIX threads.
//
bool Resume();
void Notify(const ProcessMessage &message);
//--------------------------------------------------------------------------
// These methods provide an interface to watchpoints
//
bool EnableHardwareWatchpoint(lldb_private::Watchpoint *wp);
bool DisableHardwareWatchpoint(lldb_private::Watchpoint *wp);
uint32_t NumSupportedHardwareWatchpoints();
uint32_t FindVacantWatchpointIndex();
protected:
POSIXBreakpointProtocol *GetPOSIXBreakpointProtocol() {
if (!m_reg_context_sp)
m_reg_context_sp = GetRegisterContext();
return m_posix_thread;
}
std::unique_ptr<lldb_private::StackFrame> m_frame_ap;
lldb::BreakpointSiteSP m_breakpoint;
bool m_thread_name_valid;
std::string m_thread_name;
POSIXBreakpointProtocol *m_posix_thread;
ProcessMonitor &GetMonitor();
bool CalculateStopInfo() override;
void BreakNotify(const ProcessMessage &message);
void WatchNotify(const ProcessMessage &message);
virtual void TraceNotify(const ProcessMessage &message);
void LimboNotify(const ProcessMessage &message);
void SignalNotify(const ProcessMessage &message);
void SignalDeliveredNotify(const ProcessMessage &message);
void CrashNotify(const ProcessMessage &message);
void ExitNotify(const ProcessMessage &message);
void ExecNotify(const ProcessMessage &message);
lldb_private::Unwind *GetUnwinder() override;
//--------------------------------------------------------------------------
// FreeBSDThread internal API.
// POSIXThread override
virtual void WillResume(lldb::StateType resume_state) override;
};
#endif // #ifndef liblldb_FreeBSDThread_H_

View File

@ -0,0 +1,45 @@
//===-- POSIXStopInfo.cpp ---------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "POSIXStopInfo.h"
using namespace lldb;
using namespace lldb_private;
//===----------------------------------------------------------------------===//
// POSIXLimboStopInfo
POSIXLimboStopInfo::~POSIXLimboStopInfo() {}
lldb::StopReason POSIXLimboStopInfo::GetStopReason() const {
return lldb::eStopReasonThreadExiting;
}
const char *POSIXLimboStopInfo::GetDescription() { return "thread exiting"; }
bool POSIXLimboStopInfo::ShouldStop(Event *event_ptr) { return false; }
bool POSIXLimboStopInfo::ShouldNotify(Event *event_ptr) { return false; }
//===----------------------------------------------------------------------===//
// POSIXNewThreadStopInfo
POSIXNewThreadStopInfo::~POSIXNewThreadStopInfo() {}
lldb::StopReason POSIXNewThreadStopInfo::GetStopReason() const {
return lldb::eStopReasonNone;
}
const char *POSIXNewThreadStopInfo::GetDescription() {
return "thread spawned";
}
bool POSIXNewThreadStopInfo::ShouldStop(Event *event_ptr) { return false; }
bool POSIXNewThreadStopInfo::ShouldNotify(Event *event_ptr) { return false; }

View File

@ -0,0 +1,67 @@
//===-- POSIXStopInfo.h -----------------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_POSIXStopInfo_H_
#define liblldb_POSIXStopInfo_H_
#include "FreeBSDThread.h"
#include "Plugins/Process/POSIX/CrashReason.h"
#include "lldb/Target/StopInfo.h"
#include <string>
//===----------------------------------------------------------------------===//
/// @class POSIXStopInfo
/// @brief Simple base class for all POSIX-specific StopInfo objects.
///
class POSIXStopInfo : public lldb_private::StopInfo {
public:
POSIXStopInfo(lldb_private::Thread &thread, uint32_t status)
: StopInfo(thread, status) {}
};
//===----------------------------------------------------------------------===//
/// @class POSIXLimboStopInfo
/// @brief Represents the stop state of a process ready to exit.
///
class POSIXLimboStopInfo : public POSIXStopInfo {
public:
POSIXLimboStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {}
~POSIXLimboStopInfo();
lldb::StopReason GetStopReason() const;
const char *GetDescription();
bool ShouldStop(lldb_private::Event *event_ptr);
bool ShouldNotify(lldb_private::Event *event_ptr);
};
//===----------------------------------------------------------------------===//
/// @class POSIXNewThreadStopInfo
/// @brief Represents the stop state of process when a new thread is spawned.
///
class POSIXNewThreadStopInfo : public POSIXStopInfo {
public:
POSIXNewThreadStopInfo(FreeBSDThread &thread) : POSIXStopInfo(thread, 0) {}
~POSIXNewThreadStopInfo();
lldb::StopReason GetStopReason() const;
const char *GetDescription();
bool ShouldStop(lldb_private::Event *event_ptr);
bool ShouldNotify(lldb_private::Event *event_ptr);
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,230 @@
//===-- ProcessFreeBSD.h ------------------------------------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ProcessFreeBSD_H_
#define liblldb_ProcessFreeBSD_H_
#include "Plugins/Process/POSIX/ProcessMessage.h"
#include "lldb/Target/Process.h"
#include "lldb/Target/ThreadList.h"
#include <mutex>
#include <queue>
#include <set>
class ProcessMonitor;
class FreeBSDThread;
class ProcessFreeBSD : public lldb_private::Process {
public:
//------------------------------------------------------------------
// Static functions.
//------------------------------------------------------------------
static lldb::ProcessSP
CreateInstance(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
const lldb_private::FileSpec *crash_file_path);
static void Initialize();
static void Terminate();
static lldb_private::ConstString GetPluginNameStatic();
static const char *GetPluginDescriptionStatic();
//------------------------------------------------------------------
// Constructors and destructors
//------------------------------------------------------------------
ProcessFreeBSD(lldb::TargetSP target_sp, lldb::ListenerSP listener_sp,
lldb::UnixSignalsSP &unix_signals_sp);
~ProcessFreeBSD();
virtual lldb_private::Status WillResume() override;
//------------------------------------------------------------------
// PluginInterface protocol
//------------------------------------------------------------------
virtual lldb_private::ConstString GetPluginName() override;
virtual uint32_t GetPluginVersion() override;
public:
//------------------------------------------------------------------
// Process protocol.
//------------------------------------------------------------------
void Finalize() override;
bool CanDebug(lldb::TargetSP target_sp,
bool plugin_specified_by_name) override;
lldb_private::Status WillLaunch(lldb_private::Module *module) override;
lldb_private::Status DoAttachToProcessWithID(
lldb::pid_t pid,
const lldb_private::ProcessAttachInfo &attach_info) override;
lldb_private::Status
DoLaunch(lldb_private::Module *exe_module,
lldb_private::ProcessLaunchInfo &launch_info) override;
void DidLaunch() override;
lldb_private::Status DoResume() override;
lldb_private::Status DoHalt(bool &caused_stop) override;
lldb_private::Status DoDetach(bool keep_stopped) override;
lldb_private::Status DoSignal(int signal) override;
lldb_private::Status DoDestroy() override;
void DoDidExec() override;
void RefreshStateAfterStop() override;
bool IsAlive() override;
size_t DoReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
lldb_private::Status &error) override;
size_t DoWriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
lldb_private::Status &error) override;
lldb::addr_t DoAllocateMemory(size_t size, uint32_t permissions,
lldb_private::Status &error) override;
lldb_private::Status DoDeallocateMemory(lldb::addr_t ptr) override;
virtual size_t
GetSoftwareBreakpointTrapOpcode(lldb_private::BreakpointSite *bp_site);
lldb_private::Status
EnableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
lldb_private::Status
DisableBreakpointSite(lldb_private::BreakpointSite *bp_site) override;
lldb_private::Status EnableWatchpoint(lldb_private::Watchpoint *wp,
bool notify = true) override;
lldb_private::Status DisableWatchpoint(lldb_private::Watchpoint *wp,
bool notify = true) override;
lldb_private::Status GetWatchpointSupportInfo(uint32_t &num) override;
lldb_private::Status GetWatchpointSupportInfo(uint32_t &num,
bool &after) override;
virtual uint32_t UpdateThreadListIfNeeded();
bool UpdateThreadList(lldb_private::ThreadList &old_thread_list,
lldb_private::ThreadList &new_thread_list) override;
virtual lldb::ByteOrder GetByteOrder() const;
lldb::addr_t GetImageInfoAddress() override;
size_t PutSTDIN(const char *buf, size_t len,
lldb_private::Status &error) override;
const lldb::DataBufferSP GetAuxvData() override;
//--------------------------------------------------------------------------
// ProcessFreeBSD internal API.
/// Registers the given message with this process.
virtual void SendMessage(const ProcessMessage &message);
ProcessMonitor &GetMonitor() {
assert(m_monitor);
return *m_monitor;
}
lldb_private::FileSpec
GetFileSpec(const lldb_private::FileAction *file_action,
const lldb_private::FileSpec &default_file_spec,
const lldb_private::FileSpec &dbg_pts_file_spec);
/// Adds the thread to the list of threads for which we have received the
/// initial stopping signal.
/// The \p stop_tid parameter indicates the thread which the stop happened
/// for.
bool AddThreadForInitialStopIfNeeded(lldb::tid_t stop_tid);
bool WaitingForInitialStop(lldb::tid_t stop_tid);
virtual FreeBSDThread *CreateNewFreeBSDThread(lldb_private::Process &process,
lldb::tid_t tid);
static bool SingleStepBreakpointHit(
void *baton, lldb_private::StoppointCallbackContext *context,
lldb::user_id_t break_id, lldb::user_id_t break_loc_id);
lldb_private::Status SetupSoftwareSingleStepping(lldb::tid_t tid);
lldb_private::Status SetSoftwareSingleStepBreakpoint(lldb::tid_t tid,
lldb::addr_t addr);
bool IsSoftwareStepBreakpoint(lldb::tid_t tid);
bool SupportHardwareSingleStepping() const;
typedef std::vector<lldb::tid_t> tid_collection;
tid_collection &GetStepTids() { return m_step_tids; }
protected:
static const size_t MAX_TRAP_OPCODE_SIZE = 8;
/// Target byte order.
lldb::ByteOrder m_byte_order;
/// Process monitor;
ProcessMonitor *m_monitor;
/// The module we are executing.
lldb_private::Module *m_module;
/// Message queue notifying this instance of inferior process state changes.
std::recursive_mutex m_message_mutex;
std::queue<ProcessMessage> m_message_queue;
/// Drive any exit events to completion.
bool m_exit_now;
/// Returns true if the process has exited.
bool HasExited();
/// Returns true if the process is stopped.
bool IsStopped();
/// Returns true if at least one running is currently running
bool IsAThreadRunning();
typedef std::map<lldb::addr_t, lldb::addr_t> MMapMap;
MMapMap m_addr_to_mmap_size;
typedef std::set<lldb::tid_t> ThreadStopSet;
/// Every thread begins with a stop signal. This keeps track
/// of the threads for which we have received the stop signal.
ThreadStopSet m_seen_initial_stop;
friend class FreeBSDThread;
tid_collection m_suspend_tids;
tid_collection m_run_tids;
tid_collection m_step_tids;
std::map<lldb::tid_t, lldb::break_id_t> m_threads_stepping_with_breakpoint;
int m_resume_signo;
};
#endif // liblldb_ProcessFreeBSD_H_

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,284 @@
//===-- ProcessMonitor.h -------------------------------------- -*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_ProcessMonitor_H_
#define liblldb_ProcessMonitor_H_
// C Includes
#include <semaphore.h>
#include <signal.h>
// C++ Includes
#include <mutex>
// Other libraries and framework includes
#include "lldb/Host/HostThread.h"
#include "lldb/Utility/FileSpec.h"
#include "lldb/lldb-types.h"
namespace lldb_private {
class Status;
class Module;
class Scalar;
} // End lldb_private namespace.
class ProcessFreeBSD;
class Operation;
/// @class ProcessMonitor
/// @brief Manages communication with the inferior (debugee) process.
///
/// Upon construction, this class prepares and launches an inferior process for
/// debugging.
///
/// Changes in the inferior process state are propagated to the associated
/// ProcessFreeBSD instance by calling ProcessFreeBSD::SendMessage with the
/// appropriate ProcessMessage events.
///
/// A purposely minimal set of operations are provided to interrogate and change
/// the inferior process state.
class ProcessMonitor {
public:
/// Launches an inferior process ready for debugging. Forms the
/// implementation of Process::DoLaunch.
ProcessMonitor(ProcessFreeBSD *process, lldb_private::Module *module,
char const *argv[], char const *envp[],
const lldb_private::FileSpec &stdin_file_spec,
const lldb_private::FileSpec &stdout_file_spec,
const lldb_private::FileSpec &stderr_file_spec,
const lldb_private::FileSpec &working_dir,
const lldb_private::ProcessLaunchInfo &launch_info,
lldb_private::Status &error);
ProcessMonitor(ProcessFreeBSD *process, lldb::pid_t pid,
lldb_private::Status &error);
~ProcessMonitor();
/// Provides the process number of debugee.
lldb::pid_t GetPID() const { return m_pid; }
/// Returns the process associated with this ProcessMonitor.
ProcessFreeBSD &GetProcess() { return *m_process; }
/// Returns a file descriptor to the controlling terminal of the inferior
/// process.
///
/// Reads from this file descriptor yield both the standard output and
/// standard error of this debugee. Even if stderr and stdout were
/// redirected on launch it may still happen that data is available on this
/// descriptor (if the inferior process opens /dev/tty, for example). This
/// descriptor is
/// closed after a call to StopMonitor().
///
/// If this monitor was attached to an existing process this method returns
/// -1.
int GetTerminalFD() const { return m_terminal_fd; }
/// Reads @p size bytes from address @vm_adder in the inferior process
/// address space.
///
/// This method is provided to implement Process::DoReadMemory.
size_t ReadMemory(lldb::addr_t vm_addr, void *buf, size_t size,
lldb_private::Status &error);
/// Writes @p size bytes from address @p vm_adder in the inferior process
/// address space.
///
/// This method is provided to implement Process::DoWriteMemory.
size_t WriteMemory(lldb::addr_t vm_addr, const void *buf, size_t size,
lldb_private::Status &error);
/// Reads the contents from the register identified by the given (architecture
/// dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool ReadRegisterValue(lldb::tid_t tid, unsigned offset, const char *reg_name,
unsigned size, lldb_private::RegisterValue &value);
/// Writes the given value to the register identified by the given
/// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool WriteRegisterValue(lldb::tid_t tid, unsigned offset,
const char *reg_name,
const lldb_private::RegisterValue &value);
/// Reads the contents from the debug register identified by the given
/// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool ReadDebugRegisterValue(lldb::tid_t tid, unsigned offset,
const char *reg_name, unsigned size,
lldb_private::RegisterValue &value);
/// Writes the given value to the debug register identified by the given
/// (architecture dependent) offset.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool WriteDebugRegisterValue(lldb::tid_t tid, unsigned offset,
const char *reg_name,
const lldb_private::RegisterValue &value);
/// Reads all general purpose registers into the specified buffer.
bool ReadGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Reads all floating point registers into the specified buffer.
bool ReadFPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Reads the specified register set into the specified buffer.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool ReadRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size,
unsigned int regset);
/// Writes all general purpose registers into the specified buffer.
bool WriteGPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Writes all floating point registers into the specified buffer.
bool WriteFPR(lldb::tid_t tid, void *buf, size_t buf_size);
/// Writes the specified register set into the specified buffer.
///
/// This method is provided for use by RegisterContextFreeBSD derivatives.
bool WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size,
unsigned int regset);
/// Reads the value of the thread-specific pointer for a given thread ID.
bool ReadThreadPointer(lldb::tid_t tid, lldb::addr_t &value);
/// Returns current thread IDs in process
size_t GetCurrentThreadIDs(std::vector<lldb::tid_t> &thread_ids);
/// Writes a ptrace_lwpinfo structure corresponding to the given thread ID
/// to the memory region pointed to by @p lwpinfo.
bool GetLwpInfo(lldb::tid_t tid, void *lwpinfo, int &error_no);
/// Suspends or unsuspends a thread prior to process resume or step.
bool ThreadSuspend(lldb::tid_t tid, bool suspend);
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
/// corresponding to the given thread IDto the memory pointed to by @p
/// message.
bool GetEventMessage(lldb::tid_t tid, unsigned long *message);
/// Resumes the process. If @p signo is anything but
/// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
bool Resume(lldb::tid_t unused, uint32_t signo);
/// Single steps the process. If @p signo is anything but
/// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the process.
bool SingleStep(lldb::tid_t unused, uint32_t signo);
/// Terminate the traced process.
bool Kill();
lldb_private::Status Detach(lldb::tid_t tid);
void StopMonitor();
// Waits for the initial stop message from a new thread.
bool WaitForInitialTIDStop(lldb::tid_t tid);
private:
ProcessFreeBSD *m_process;
lldb_private::HostThread m_operation_thread;
lldb_private::HostThread m_monitor_thread;
lldb::pid_t m_pid;
int m_terminal_fd;
// current operation which must be executed on the privileged thread
Operation *m_operation;
std::mutex m_operation_mutex;
// semaphores notified when Operation is ready to be processed and when
// the operation is complete.
sem_t m_operation_pending;
sem_t m_operation_done;
struct OperationArgs {
OperationArgs(ProcessMonitor *monitor);
~OperationArgs();
ProcessMonitor *m_monitor; // The monitor performing the attach.
sem_t m_semaphore; // Posted to once operation complete.
lldb_private::Status m_error; // Set if process operation failed.
};
/// @class LauchArgs
///
/// @brief Simple structure to pass data to the thread responsible for
/// launching a child process.
struct LaunchArgs : OperationArgs {
LaunchArgs(ProcessMonitor *monitor, lldb_private::Module *module,
char const **argv, char const **envp,
const lldb_private::FileSpec &stdin_file_spec,
const lldb_private::FileSpec &stdout_file_spec,
const lldb_private::FileSpec &stderr_file_spec,
const lldb_private::FileSpec &working_dir);
~LaunchArgs();
lldb_private::Module *m_module; // The executable image to launch.
char const **m_argv; // Process arguments.
char const **m_envp; // Process environment.
const lldb_private::FileSpec m_stdin_file_spec; // Redirect stdin or empty.
const lldb_private::FileSpec
m_stdout_file_spec; // Redirect stdout or empty.
const lldb_private::FileSpec
m_stderr_file_spec; // Redirect stderr or empty.
const lldb_private::FileSpec m_working_dir; // Working directory or empty.
};
void StartLaunchOpThread(LaunchArgs *args, lldb_private::Status &error);
static void *LaunchOpThread(void *arg);
static bool Launch(LaunchArgs *args);
struct AttachArgs : OperationArgs {
AttachArgs(ProcessMonitor *monitor, lldb::pid_t pid);
~AttachArgs();
lldb::pid_t m_pid; // pid of the process to be attached.
};
void StartAttachOpThread(AttachArgs *args, lldb_private::Status &error);
static void *AttachOpThread(void *args);
static void Attach(AttachArgs *args);
static void ServeOperation(OperationArgs *args);
static bool DupDescriptor(const lldb_private::FileSpec &file_spec, int fd,
int flags);
static bool MonitorCallback(ProcessMonitor *monitor, lldb::pid_t pid,
bool exited, int signal, int status);
static ProcessMessage MonitorSIGTRAP(ProcessMonitor *monitor,
const siginfo_t *info, lldb::pid_t pid);
static ProcessMessage MonitorSignal(ProcessMonitor *monitor,
const siginfo_t *info, lldb::pid_t pid);
void DoOperation(Operation *op);
/// Stops the child monitor thread.
void StopMonitoringChildProcess();
/// Stops the operation thread used to attach/launch a process.
void StopOpThread();
};
#endif // #ifndef liblldb_ProcessMonitor_H_

View File

@ -0,0 +1,68 @@
//===-- RegisterContextPOSIX.h --------------------------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextPOSIX_H_
#define liblldb_RegisterContextPOSIX_H_
// C Includes
// C++ Includes
// Other libraries and framework includes
#include "RegisterInfoInterface.h"
#include "lldb/Target/RegisterContext.h"
#include "lldb/Utility/ArchSpec.h"
//------------------------------------------------------------------------------
/// @class POSIXBreakpointProtocol
///
/// @brief Extends RegisterClass with a few virtual operations useful on POSIX.
class POSIXBreakpointProtocol {
public:
POSIXBreakpointProtocol() { m_watchpoints_initialized = false; }
virtual ~POSIXBreakpointProtocol() {}
/// Updates the register state of the associated thread after hitting a
/// breakpoint (if that make sense for the architecture). Default
/// implementation simply returns true for architectures which do not
/// require any update.
///
/// @return
/// True if the operation succeeded and false otherwise.
virtual bool UpdateAfterBreakpoint() = 0;
/// Determines the index in lldb's register file given a kernel byte offset.
virtual unsigned GetRegisterIndexFromOffset(unsigned offset) = 0;
// Checks to see if a watchpoint specified by hw_index caused the inferior
// to stop.
virtual bool IsWatchpointHit(uint32_t hw_index) = 0;
// Resets any watchpoints that have been hit.
virtual bool ClearWatchpointHits() = 0;
// Returns the watchpoint address associated with a watchpoint hardware
// index.
virtual lldb::addr_t GetWatchpointAddress(uint32_t hw_index) = 0;
virtual bool IsWatchpointVacant(uint32_t hw_index) = 0;
virtual bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size,
bool read, bool write,
uint32_t hw_index) = 0;
// From lldb_private::RegisterContext
virtual uint32_t NumSupportedHardwareWatchpoints() = 0;
// Force m_watchpoints_initialized to TRUE
void ForceWatchpointsInitialized() { m_watchpoints_initialized = true; }
protected:
bool m_watchpoints_initialized;
};
#endif // #ifndef liblldb_RegisterContextPOSIX_H_

View File

@ -0,0 +1,260 @@
//===-- RegisterContextPOSIXProcessMonitor_arm.cpp -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm.h"
#include "RegisterContextPOSIX_arm.h"
using namespace lldb_private;
using namespace lldb;
#define REG_CONTEXT_SIZE (GetGPRSize())
RegisterContextPOSIXProcessMonitor_arm::RegisterContextPOSIXProcessMonitor_arm(
Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_arm(thread, concrete_frame_idx, register_info) {}
ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm::GetMonitor() {
ProcessSP base = CalculateProcess();
ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
return process->GetMonitor();
}
bool RegisterContextPOSIXProcessMonitor_arm::ReadGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_arm::ReadFPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
}
bool RegisterContextPOSIXProcessMonitor_arm::WriteGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_arm::WriteFPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof(m_fpr));
}
bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister(
const unsigned reg, RegisterValue &value) {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
GetRegisterName(reg), GetRegisterSize(reg),
value);
}
bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister(
const unsigned reg, const RegisterValue &value) {
unsigned reg_to_write = reg;
RegisterValue value_to_write = value;
// Check if this is a subregister of a full register.
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
if (reg_info->invalidate_regs &&
(reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
RegisterValue full_value;
uint32_t full_reg = reg_info->invalidate_regs[0];
const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
// Read the full register.
if (ReadRegister(full_reg_info, full_value)) {
Status error;
ByteOrder byte_order = GetByteOrder();
uint8_t dst[RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the full register.
const uint32_t dest_size = full_value.GetAsMemoryData(
full_reg_info, dst, sizeof(dst), byte_order, error);
if (error.Success() && dest_size) {
uint8_t src[RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the source data.
const uint32_t src_size = value.GetAsMemoryData(
reg_info, src, sizeof(src), byte_order, error);
if (error.Success() && src_size && (src_size < dest_size)) {
// Copy the src bytes to the destination.
memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
// Set this full register as the value to write.
value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
value_to_write.SetType(full_reg_info);
reg_to_write = full_reg;
}
}
}
}
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteRegisterValue(
m_thread.GetID(), GetRegisterOffset(reg_to_write),
GetRegisterName(reg_to_write), value_to_write);
}
bool RegisterContextPOSIXProcessMonitor_arm::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
if (!reg_info)
return false;
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (IsFPR(reg)) {
if (!ReadFPR())
return false;
} else {
return ReadRegister(reg, value);
}
// Get pointer to m_fpr variable and set the data from it.
assert(reg_info->byte_offset < sizeof m_fpr);
uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
switch (reg_info->byte_size) {
case 2:
value.SetUInt16(*(uint16_t *)src);
return true;
case 4:
value.SetUInt32(*(uint32_t *)src);
return true;
case 8:
value.SetUInt64(*(uint64_t *)src);
return true;
default:
assert(false && "Unhandled data size.");
return false;
}
}
bool RegisterContextPOSIXProcessMonitor_arm::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (IsGPR(reg)) {
return WriteRegister(reg, value);
} else if (IsFPR(reg)) {
return WriteFPR();
}
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm::ReadAllRegisterValues(
DataBufferSP &data_sp) {
bool success = false;
data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
if (data_sp && ReadGPR() && ReadFPR()) {
uint8_t *dst = data_sp->GetBytes();
success = dst != 0;
if (success) {
::memcpy(dst, &m_gpr_arm, GetGPRSize());
dst += GetGPRSize();
::memcpy(dst, &m_fpr, sizeof(m_fpr));
}
}
return success;
}
bool RegisterContextPOSIXProcessMonitor_arm::WriteAllRegisterValues(
const DataBufferSP &data_sp) {
bool success = false;
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
uint8_t *src = data_sp->GetBytes();
if (src) {
::memcpy(&m_gpr_arm, src, GetGPRSize());
if (WriteGPR()) {
src += GetGPRSize();
::memcpy(&m_fpr, src, sizeof(m_fpr));
success = WriteFPR();
}
}
}
return success;
}
uint32_t RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpoint(
addr_t addr, size_t size, bool read, bool write) {
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
uint32_t hw_index;
for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
if (IsWatchpointVacant(hw_index))
return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
}
return LLDB_INVALID_INDEX32;
}
bool RegisterContextPOSIXProcessMonitor_arm::ClearHardwareWatchpoint(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm::HardwareSingleStep(bool enable) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm::UpdateAfterBreakpoint() {
lldb::addr_t pc;
if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
return false;
return true;
}
unsigned RegisterContextPOSIXProcessMonitor_arm::GetRegisterIndexFromOffset(
unsigned offset) {
unsigned reg;
for (reg = 0; reg < k_num_registers_arm; reg++) {
if (GetRegisterInfo()[reg].byte_offset == offset)
break;
}
assert(reg < k_num_registers_arm && "Invalid register offset.");
return reg;
}
bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointHit(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm::ClearWatchpointHits() {
return false;
}
addr_t RegisterContextPOSIXProcessMonitor_arm::GetWatchpointAddress(
uint32_t hw_index) {
return LLDB_INVALID_ADDRESS;
}
bool RegisterContextPOSIXProcessMonitor_arm::IsWatchpointVacant(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm::SetHardwareWatchpointWithIndex(
addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
return false;
}
uint32_t
RegisterContextPOSIXProcessMonitor_arm::NumSupportedHardwareWatchpoints() {
return 0;
}

View File

@ -0,0 +1,77 @@
//===-- RegisterContextPOSIXProcessMonitor_arm.h --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_arm_H_
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm.h"
#include "RegisterContextPOSIX.h"
class RegisterContextPOSIXProcessMonitor_arm : public RegisterContextPOSIX_arm,
public POSIXBreakpointProtocol {
public:
RegisterContextPOSIXProcessMonitor_arm(
lldb_private::Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
protected:
bool ReadGPR();
bool ReadFPR();
bool WriteGPR();
bool WriteFPR();
// lldb_private::RegisterContext
bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
bool WriteRegister(const unsigned reg,
const lldb_private::RegisterValue &value);
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value);
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value);
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
bool write);
bool ClearHardwareWatchpoint(uint32_t hw_index);
bool HardwareSingleStep(bool enable);
// POSIXBreakpointProtocol
bool UpdateAfterBreakpoint();
unsigned GetRegisterIndexFromOffset(unsigned offset);
bool IsWatchpointHit(uint32_t hw_index);
bool ClearWatchpointHits();
lldb::addr_t GetWatchpointAddress(uint32_t hw_index);
bool IsWatchpointVacant(uint32_t hw_index);
bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
bool write, uint32_t hw_index);
uint32_t NumSupportedHardwareWatchpoints();
private:
ProcessMonitor &GetMonitor();
};
#endif

View File

@ -0,0 +1,265 @@
//===-- RegisterContextPOSIXProcessMonitor_arm64.cpp -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===---------------------------------------------------------------------===//
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_arm64.h"
#define REG_CONTEXT_SIZE (GetGPRSize())
using namespace lldb;
using namespace lldb_private;
RegisterContextPOSIXProcessMonitor_arm64::
RegisterContextPOSIXProcessMonitor_arm64(
lldb_private::Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_arm64(thread, concrete_frame_idx, register_info) {}
ProcessMonitor &RegisterContextPOSIXProcessMonitor_arm64::GetMonitor() {
lldb::ProcessSP base = CalculateProcess();
ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
return process->GetMonitor();
}
bool RegisterContextPOSIXProcessMonitor_arm64::ReadGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_arm64::ReadFPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
}
bool RegisterContextPOSIXProcessMonitor_arm64::WriteGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteGPR(m_thread.GetID(), &m_gpr_arm64, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_arm64::WriteFPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteFPR(m_thread.GetID(), &m_fpr, sizeof m_fpr);
}
bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(
const unsigned reg, lldb_private::RegisterValue &value) {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
GetRegisterName(reg), GetRegisterSize(reg),
value);
}
bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(
const unsigned reg, const lldb_private::RegisterValue &value) {
unsigned reg_to_write = reg;
lldb_private::RegisterValue value_to_write = value;
// Check if this is a subregister of a full register.
const lldb_private::RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
if (reg_info->invalidate_regs &&
(reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
lldb_private::RegisterValue full_value;
uint32_t full_reg = reg_info->invalidate_regs[0];
const lldb_private::RegisterInfo *full_reg_info =
GetRegisterInfoAtIndex(full_reg);
// Read the full register.
if (ReadRegister(full_reg_info, full_value)) {
lldb_private::Status error;
lldb::ByteOrder byte_order = GetByteOrder();
uint8_t dst[lldb_private::RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the full register.
const uint32_t dest_size = full_value.GetAsMemoryData(
full_reg_info, dst, sizeof(dst), byte_order, error);
if (error.Success() && dest_size) {
uint8_t src[lldb_private::RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the source data.
const uint32_t src_size = value.GetAsMemoryData(
reg_info, src, sizeof(src), byte_order, error);
if (error.Success() && src_size && (src_size < dest_size)) {
// Copy the src bytes to the destination.
::memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
// Set this full register as the value to write.
value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
value_to_write.SetType(full_reg_info);
reg_to_write = full_reg;
}
}
}
}
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteRegisterValue(
m_thread.GetID(), GetRegisterOffset(reg_to_write),
GetRegisterName(reg_to_write), value_to_write);
}
bool RegisterContextPOSIXProcessMonitor_arm64::ReadRegister(
const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value) {
if (!reg_info)
return false;
const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
if (IsFPR(reg)) {
if (!ReadFPR())
return false;
} else {
uint32_t full_reg = reg;
bool is_subreg = reg_info->invalidate_regs &&
(reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
if (is_subreg) {
// Read the full aligned 64-bit register.
full_reg = reg_info->invalidate_regs[0];
}
return ReadRegister(full_reg, value);
}
// Get pointer to m_fpr variable and set the data from it.
assert(reg_info->byte_offset < sizeof m_fpr);
uint8_t *src = (uint8_t *)&m_fpr + reg_info->byte_offset;
switch (reg_info->byte_size) {
case 2:
value.SetUInt16(*(uint16_t *)src);
return true;
case 4:
value.SetUInt32(*(uint32_t *)src);
return true;
case 8:
value.SetUInt64(*(uint64_t *)src);
return true;
default:
assert(false && "Unhandled data size.");
return false;
}
}
bool RegisterContextPOSIXProcessMonitor_arm64::WriteRegister(
const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value) {
const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
if (IsGPR(reg))
return WriteRegister(reg, value);
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm64::ReadAllRegisterValues(
lldb::DataBufferSP &data_sp) {
bool success = false;
data_sp.reset(new lldb_private::DataBufferHeap(REG_CONTEXT_SIZE, 0));
if (data_sp && ReadGPR() && ReadFPR()) {
uint8_t *dst = data_sp->GetBytes();
success = dst != 0;
if (success) {
::memcpy(dst, &m_gpr_arm64, GetGPRSize());
dst += GetGPRSize();
::memcpy(dst, &m_fpr, sizeof m_fpr);
}
}
return success;
}
bool RegisterContextPOSIXProcessMonitor_arm64::WriteAllRegisterValues(
const lldb::DataBufferSP &data_sp) {
bool success = false;
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
uint8_t *src = data_sp->GetBytes();
if (src) {
::memcpy(&m_gpr_arm64, src, GetGPRSize());
if (WriteGPR()) {
src += GetGPRSize();
::memcpy(&m_fpr, src, sizeof m_fpr);
success = WriteFPR();
}
}
}
return success;
}
uint32_t RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpoint(
lldb::addr_t addr, size_t size, bool read, bool write) {
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
uint32_t hw_index;
for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
if (IsWatchpointVacant(hw_index))
return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
}
return LLDB_INVALID_INDEX32;
}
bool RegisterContextPOSIXProcessMonitor_arm64::ClearHardwareWatchpoint(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm64::HardwareSingleStep(bool enable) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm64::UpdateAfterBreakpoint() {
if (GetPC() == LLDB_INVALID_ADDRESS)
return false;
return true;
}
unsigned RegisterContextPOSIXProcessMonitor_arm64::GetRegisterIndexFromOffset(
unsigned offset) {
unsigned reg;
for (reg = 0; reg < k_num_registers_arm64; reg++) {
if (GetRegisterInfo()[reg].byte_offset == offset)
break;
}
assert(reg < k_num_registers_arm64 && "Invalid register offset.");
return reg;
}
bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointHit(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm64::ClearWatchpointHits() {
return false;
}
lldb::addr_t RegisterContextPOSIXProcessMonitor_arm64::GetWatchpointAddress(
uint32_t hw_index) {
return LLDB_INVALID_ADDRESS;
}
bool RegisterContextPOSIXProcessMonitor_arm64::IsWatchpointVacant(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_arm64::SetHardwareWatchpointWithIndex(
lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
return false;
}
uint32_t
RegisterContextPOSIXProcessMonitor_arm64::NumSupportedHardwareWatchpoints() {
return 0;
}

View File

@ -0,0 +1,78 @@
//===-- RegisterContextPOSIXProcessMonitor_arm64.h --------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_arm64_H_
#include "Plugins/Process/Utility/RegisterContextPOSIX_arm64.h"
#include "RegisterContextPOSIX.h"
class RegisterContextPOSIXProcessMonitor_arm64
: public RegisterContextPOSIX_arm64,
public POSIXBreakpointProtocol {
public:
RegisterContextPOSIXProcessMonitor_arm64(
lldb_private::Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
protected:
bool ReadGPR();
bool ReadFPR();
bool WriteGPR();
bool WriteFPR();
// lldb_private::RegisterContext
bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
bool WriteRegister(const unsigned reg,
const lldb_private::RegisterValue &value);
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value);
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value);
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
bool write);
bool ClearHardwareWatchpoint(uint32_t hw_index);
bool HardwareSingleStep(bool enable);
// POSIXBreakpointProtocol
bool UpdateAfterBreakpoint();
unsigned GetRegisterIndexFromOffset(unsigned offset);
bool IsWatchpointHit(uint32_t hw_index);
bool ClearWatchpointHits();
lldb::addr_t GetWatchpointAddress(uint32_t hw_index);
bool IsWatchpointVacant(uint32_t hw_index);
bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
bool write, uint32_t hw_index);
uint32_t NumSupportedHardwareWatchpoints();
private:
ProcessMonitor &GetMonitor();
};
#endif

View File

@ -0,0 +1,263 @@
//===-- RegisterContextPOSIXProcessMonitor_mips64.cpp -----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_mips64.h"
using namespace lldb_private;
using namespace lldb;
#define REG_CONTEXT_SIZE (GetGPRSize())
RegisterContextPOSIXProcessMonitor_mips64::
RegisterContextPOSIXProcessMonitor_mips64(
Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_mips64(thread, concrete_frame_idx, register_info) {}
ProcessMonitor &RegisterContextPOSIXProcessMonitor_mips64::GetMonitor() {
ProcessSP base = CalculateProcess();
ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
return process->GetMonitor();
}
bool RegisterContextPOSIXProcessMonitor_mips64::ReadGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_mips64::ReadFPR() {
// XXX not yet implemented
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::WriteGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteGPR(m_thread.GetID(), &m_gpr_mips64, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_mips64::WriteFPR() {
// XXX not yet implemented
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
const unsigned reg, RegisterValue &value) {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
GetRegisterName(reg), GetRegisterSize(reg),
value);
}
bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(
const unsigned reg, const RegisterValue &value) {
unsigned reg_to_write = reg;
RegisterValue value_to_write = value;
// Check if this is a subregister of a full register.
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
if (reg_info->invalidate_regs &&
(reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
RegisterValue full_value;
uint32_t full_reg = reg_info->invalidate_regs[0];
const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
// Read the full register.
if (ReadRegister(full_reg_info, full_value)) {
Status error;
ByteOrder byte_order = GetByteOrder();
uint8_t dst[RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the full register.
const uint32_t dest_size = full_value.GetAsMemoryData(
full_reg_info, dst, sizeof(dst), byte_order, error);
if (error.Success() && dest_size) {
uint8_t src[RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the source data.
const uint32_t src_size = value.GetAsMemoryData(
reg_info, src, sizeof(src), byte_order, error);
if (error.Success() && src_size && (src_size < dest_size)) {
// Copy the src bytes to the destination.
memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
// Set this full register as the value to write.
value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
value_to_write.SetType(full_reg_info);
reg_to_write = full_reg;
}
}
}
}
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteRegisterValue(
m_thread.GetID(), GetRegisterOffset(reg_to_write),
GetRegisterName(reg_to_write), value_to_write);
}
bool RegisterContextPOSIXProcessMonitor_mips64::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
if (!reg_info)
return false;
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (IsFPR(reg)) {
if (!ReadFPR())
return false;
} else {
uint32_t full_reg = reg;
bool is_subreg = reg_info->invalidate_regs &&
(reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
if (is_subreg) {
// Read the full aligned 64-bit register.
full_reg = reg_info->invalidate_regs[0];
}
bool success = ReadRegister(full_reg, value);
if (success) {
// If our read was not aligned (for ah,bh,ch,dh), shift our returned value
// one byte to the right.
if (is_subreg && (reg_info->byte_offset & 0x1))
value.SetUInt64(value.GetAsUInt64() >> 8);
// If our return byte size was greater than the return value reg size,
// then
// use the type specified by reg_info rather than the uint64_t default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
return success;
}
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (IsGPR(reg))
return WriteRegister(reg, value);
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::ReadAllRegisterValues(
DataBufferSP &data_sp) {
bool success = false;
data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
if (data_sp && ReadGPR() && ReadFPR()) {
uint8_t *dst = data_sp->GetBytes();
success = dst != 0;
if (success) {
::memcpy(dst, &m_gpr_mips64, GetGPRSize());
}
}
return success;
}
bool RegisterContextPOSIXProcessMonitor_mips64::WriteAllRegisterValues(
const DataBufferSP &data_sp) {
bool success = false;
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
uint8_t *src = data_sp->GetBytes();
if (src) {
::memcpy(&m_gpr_mips64, src, GetGPRSize());
if (WriteGPR()) {
src += GetGPRSize();
}
}
}
return success;
}
uint32_t RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpoint(
addr_t addr, size_t size, bool read, bool write) {
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
uint32_t hw_index;
for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
if (IsWatchpointVacant(hw_index))
return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
}
return LLDB_INVALID_INDEX32;
}
bool RegisterContextPOSIXProcessMonitor_mips64::ClearHardwareWatchpoint(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::HardwareSingleStep(
bool enable) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::UpdateAfterBreakpoint() {
// PC points one byte past the int3 responsible for the breakpoint.
lldb::addr_t pc;
if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
return false;
SetPC(pc - 1);
return true;
}
unsigned RegisterContextPOSIXProcessMonitor_mips64::GetRegisterIndexFromOffset(
unsigned offset) {
unsigned reg;
for (reg = 0; reg < k_num_registers_mips64; reg++) {
if (GetRegisterInfo()[reg].byte_offset == offset)
break;
}
assert(reg < k_num_registers_mips64 && "Invalid register offset.");
return reg;
}
bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointHit(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::ClearWatchpointHits() {
return false;
}
addr_t RegisterContextPOSIXProcessMonitor_mips64::GetWatchpointAddress(
uint32_t hw_index) {
return LLDB_INVALID_ADDRESS;
}
bool RegisterContextPOSIXProcessMonitor_mips64::IsWatchpointVacant(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_mips64::SetHardwareWatchpointWithIndex(
addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
return false;
}
uint32_t
RegisterContextPOSIXProcessMonitor_mips64::NumSupportedHardwareWatchpoints() {
return 0;
}

View File

@ -0,0 +1,81 @@
//===-- RegisterContextPOSIXProcessMonitor_mips64.h -------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_mips64_H_
#include "Plugins/Process/Utility/RegisterContextPOSIX_mips64.h"
#include "Plugins/Process/Utility/lldb-mips-freebsd-register-enums.h"
#include "RegisterContextPOSIX.h"
class RegisterContextPOSIXProcessMonitor_mips64
: public RegisterContextPOSIX_mips64,
public POSIXBreakpointProtocol {
public:
RegisterContextPOSIXProcessMonitor_mips64(
lldb_private::Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
protected:
bool ReadGPR();
bool ReadFPR();
bool WriteGPR();
bool WriteFPR();
// lldb_private::RegisterContext
bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
bool WriteRegister(const unsigned reg,
const lldb_private::RegisterValue &value);
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value);
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value);
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
bool write);
bool ClearHardwareWatchpoint(uint32_t hw_index);
bool HardwareSingleStep(bool enable);
// POSIXBreakpointProtocol
bool UpdateAfterBreakpoint();
unsigned GetRegisterIndexFromOffset(unsigned offset);
bool IsWatchpointHit(uint32_t hw_index);
bool ClearWatchpointHits();
lldb::addr_t GetWatchpointAddress(uint32_t hw_index);
bool IsWatchpointVacant(uint32_t hw_index);
bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
bool write, uint32_t hw_index);
uint32_t NumSupportedHardwareWatchpoints();
private:
uint64_t
m_gpr_mips64[k_num_gpr_registers_mips64]; // general purpose registers.
ProcessMonitor &GetMonitor();
};
#endif

View File

@ -0,0 +1,275 @@
//===-- RegisterContextPOSIXProcessMonitor_powerpc.cpp ----------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "lldb/Core/RegisterValue.h"
#include "lldb/Target/Thread.h"
#include "lldb/Utility/DataBufferHeap.h"
#include "ProcessFreeBSD.h"
#include "ProcessMonitor.h"
#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
#include "RegisterContextPOSIX_powerpc.h"
using namespace lldb_private;
using namespace lldb;
#define REG_CONTEXT_SIZE (GetGPRSize())
RegisterContextPOSIXProcessMonitor_powerpc::
RegisterContextPOSIXProcessMonitor_powerpc(
Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info)
: RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info) {}
ProcessMonitor &RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor() {
ProcessSP base = CalculateProcess();
ProcessFreeBSD *process = static_cast<ProcessFreeBSD *>(base.get());
return process->GetMonitor();
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadFPR(m_thread.GetID(), &m_fpr_powerpc,
sizeof(m_fpr_powerpc));
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ReadVMX() {
// XXX: Need a way to read/write process VMX registers with ptrace.
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
}
bool RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR() {
ProcessMonitor &monitor = GetMonitor();
return monitor.WriteFPR(m_thread.GetID(), &m_fpr_powerpc,
sizeof(m_fpr_powerpc));
}
bool RegisterContextPOSIXProcessMonitor_powerpc::WriteVMX() {
// XXX: Need a way to read/write process VMX registers with ptrace.
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
const unsigned reg, RegisterValue &value) {
ProcessMonitor &monitor = GetMonitor();
return monitor.ReadRegisterValue(m_thread.GetID(), GetRegisterOffset(reg),
GetRegisterName(reg), GetRegisterSize(reg),
value);
}
bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
const unsigned reg, const RegisterValue &value) {
unsigned reg_to_write = reg;
RegisterValue value_to_write = value;
// Check if this is a subregister of a full register.
const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
if (reg_info->invalidate_regs &&
(reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM)) {
RegisterValue full_value;
uint32_t full_reg = reg_info->invalidate_regs[0];
const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
// Read the full register.
if (ReadRegister(full_reg_info, full_value)) {
Status error;
ByteOrder byte_order = GetByteOrder();
uint8_t dst[RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the full register.
const uint32_t dest_size = full_value.GetAsMemoryData(
full_reg_info, dst, sizeof(dst), byte_order, error);
if (error.Success() && dest_size) {
uint8_t src[RegisterValue::kMaxRegisterByteSize];
// Get the bytes for the source data.
const uint32_t src_size = value.GetAsMemoryData(
reg_info, src, sizeof(src), byte_order, error);
if (error.Success() && src_size && (src_size < dest_size)) {
// Copy the src bytes to the destination.
memcpy(dst + (reg_info->byte_offset & 0x1), src, src_size);
// Set this full register as the value to write.
value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
value_to_write.SetType(full_reg_info);
reg_to_write = full_reg;
}
}
}
}
ProcessMonitor &monitor = GetMonitor();
// Account for the fact that 32-bit targets on powerpc64 really use 64-bit
// registers in ptrace, but expose here 32-bit registers with a higher
// offset.
uint64_t offset = GetRegisterOffset(reg_to_write);
offset &= ~(sizeof(uintptr_t) - 1);
return monitor.WriteRegisterValue(
m_thread.GetID(), offset, GetRegisterName(reg_to_write), value_to_write);
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(
const RegisterInfo *reg_info, RegisterValue &value) {
if (!reg_info)
return false;
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (IsFPR(reg)) {
if (!ReadFPR())
return false;
uint8_t *src = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
value.SetUInt64(*(uint64_t *)src);
} else if (IsGPR(reg)) {
bool success = ReadRegister(reg, value);
if (success) {
// If our return byte size was greater than the return value reg size,
// then
// use the type specified by reg_info rather than the uint64_t default
if (value.GetByteSize() > reg_info->byte_size)
value.SetType(reg_info);
}
return success;
}
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(
const RegisterInfo *reg_info, const RegisterValue &value) {
const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
if (IsGPR(reg)) {
return WriteRegister(reg, value);
} else if (IsFPR(reg)) {
assert(reg_info->byte_offset < sizeof(m_fpr_powerpc));
uint8_t *dst = (uint8_t *)&m_fpr_powerpc + reg_info->byte_offset;
*(uint64_t *)dst = value.GetAsUInt64();
return WriteFPR();
}
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(
DataBufferSP &data_sp) {
bool success = false;
data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
if (data_sp && ReadGPR() && ReadFPR()) {
uint8_t *dst = data_sp->GetBytes();
success = dst != 0;
if (success) {
::memcpy(dst, &m_gpr_powerpc, GetGPRSize());
dst += GetGPRSize();
}
}
return success;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(
const DataBufferSP &data_sp) {
bool success = false;
if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE) {
uint8_t *src = data_sp->GetBytes();
if (src) {
::memcpy(&m_gpr_powerpc, src, GetGPRSize());
if (WriteGPR()) {
src += GetGPRSize();
::memcpy(&m_fpr_powerpc, src, sizeof(m_fpr_powerpc));
success = WriteFPR();
}
}
}
return success;
}
uint32_t RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(
addr_t addr, size_t size, bool read, bool write) {
const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
uint32_t hw_index;
for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index) {
if (IsWatchpointVacant(hw_index))
return SetHardwareWatchpointWithIndex(addr, size, read, write, hw_index);
}
return LLDB_INVALID_INDEX32;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(
bool enable) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint() {
lldb::addr_t pc;
if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
return false;
return true;
}
unsigned RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(
unsigned offset) {
unsigned reg;
for (reg = 0; reg < k_num_registers_powerpc; reg++) {
if (GetRegisterInfo()[reg].byte_offset == offset)
break;
}
assert(reg < k_num_registers_powerpc && "Invalid register offset.");
return reg;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits() {
return false;
}
addr_t RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(
uint32_t hw_index) {
return LLDB_INVALID_ADDRESS;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(
uint32_t hw_index) {
return false;
}
bool RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(
addr_t addr, size_t size, bool read, bool write, uint32_t hw_index) {
return false;
}
uint32_t
RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints() {
return 0;
}

View File

@ -0,0 +1,85 @@
//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- C++
//-*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
#include "RegisterContextPOSIX.h"
class RegisterContextPOSIXProcessMonitor_powerpc
: public RegisterContextPOSIX_powerpc,
public POSIXBreakpointProtocol {
public:
RegisterContextPOSIXProcessMonitor_powerpc(
lldb_private::Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
protected:
bool IsVMX();
bool ReadGPR();
bool ReadFPR();
bool ReadVMX();
bool WriteGPR();
bool WriteFPR();
bool WriteVMX();
// lldb_private::RegisterContext
bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
bool WriteRegister(const unsigned reg,
const lldb_private::RegisterValue &value);
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value);
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value);
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
bool write);
bool ClearHardwareWatchpoint(uint32_t hw_index);
bool HardwareSingleStep(bool enable);
// POSIXBreakpointProtocol
bool UpdateAfterBreakpoint();
unsigned GetRegisterIndexFromOffset(unsigned offset);
bool IsWatchpointHit(uint32_t hw_index);
bool ClearWatchpointHits();
lldb::addr_t GetWatchpointAddress(uint32_t hw_index);
bool IsWatchpointVacant(uint32_t hw_index);
bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
bool write, uint32_t hw_index);
uint32_t NumSupportedHardwareWatchpoints();
private:
ProcessMonitor &GetMonitor();
};
#endif

View File

@ -0,0 +1,82 @@
//===-- RegisterContextPOSIXProcessMonitor_x86.h ----------------*- C++ -*-===//
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#ifndef liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
#define liblldb_RegisterContextPOSIXProcessMonitor_x86_H_
#include "Plugins/Process/Utility/RegisterContextPOSIX_x86.h"
#include "RegisterContextPOSIX.h"
#include <sys/uio.h>
class RegisterContextPOSIXProcessMonitor_x86_64
: public RegisterContextPOSIX_x86,
public POSIXBreakpointProtocol {
public:
RegisterContextPOSIXProcessMonitor_x86_64(
lldb_private::Thread &thread, uint32_t concrete_frame_idx,
lldb_private::RegisterInfoInterface *register_info);
protected:
bool ReadGPR();
bool ReadFPR();
bool WriteGPR();
bool WriteFPR();
// lldb_private::RegisterContext
bool ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
bool WriteRegister(const unsigned reg,
const lldb_private::RegisterValue &value);
bool ReadRegister(const lldb_private::RegisterInfo *reg_info,
lldb_private::RegisterValue &value);
bool WriteRegister(const lldb_private::RegisterInfo *reg_info,
const lldb_private::RegisterValue &value);
bool ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
bool WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
uint32_t SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read,
bool write);
bool ClearHardwareWatchpoint(uint32_t hw_index);
bool HardwareSingleStep(bool enable);
// POSIXBreakpointProtocol
bool UpdateAfterBreakpoint();
unsigned GetRegisterIndexFromOffset(unsigned offset);
bool IsWatchpointHit(uint32_t hw_index);
bool ClearWatchpointHits();
lldb::addr_t GetWatchpointAddress(uint32_t hw_index);
bool IsWatchpointVacant(uint32_t hw_index);
bool SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read,
bool write, uint32_t hw_index);
uint32_t NumSupportedHardwareWatchpoints();
private:
ProcessMonitor &GetMonitor();
uint32_t
m_fctrl_offset_in_userarea; // Offset of 'fctrl' in 'UserArea' Structure
struct iovec m_iovec;
};
#endif