forked from OSchip/llvm-project
Add lldb-gdbserver support for Linux x86_64.
This change brings in lldb-gdbserver (llgs) specifically for Linux x86_64. (More architectures coming soon). Not every debugserver option is covered yet. Currently the lldb-gdbserver command line can start unattached, start attached to a pid (process-name attach not supported yet), or accept lldb attaching and launching a process or connecting by process id. The history of this large change can be found here: https://github.com/tfiala/lldb/tree/dev-tfiala-native-protocol-linux-x86_64 Until mid/late April, I was not sharing the work and continued to rebase it off of head (developed via id tfiala@google.com). I switched over to user todd.fiala@gmail.com in the middle, and once I went to github, I did merges rather than rebasing so I could share with others. llvm-svn: 212069
This commit is contained in:
parent
b201cf8883
commit
af245d115b
|
@ -25,3 +25,6 @@ build/
|
|||
llvm-build/
|
||||
*xcuserdata
|
||||
test/20*
|
||||
|
||||
# We should ignore Xcode-style embedding of llvm/ at lldb root dir.
|
||||
/llvm/
|
||||
|
|
|
@ -207,7 +207,7 @@ With LLDB, for register information, remote GDB servers can add
|
|||
support for the "qRegisterInfoN" packet where "N" is a zero based
|
||||
base16 register number that must start at zero and increase by one
|
||||
for each register that is supported. The response is done in typical
|
||||
GDB remote fashion where a serious of "KEY:VALUE;" pairs are returned.
|
||||
GDB remote fashion where a series of "KEY:VALUE;" pairs are returned.
|
||||
An example for the x86_64 registers is included below:
|
||||
|
||||
send packet: $qRegisterInfo0#00
|
||||
|
|
|
@ -19,12 +19,12 @@ namespace lldb_private {
|
|||
/// @class UserID UserID.h "lldb/Core/UserID.h"
|
||||
/// @brief A mix in class that contains a generic user ID.
|
||||
///
|
||||
/// UserID is desinged as a mix in class that can contain an integer
|
||||
/// based unique identifier for a varietly of objects in lldb.
|
||||
/// UserID is designed as a mix in class that can contain an integer
|
||||
/// based unique identifier for a variety of objects in lldb.
|
||||
///
|
||||
/// The value for this identifier is chosen by each parser plug-in. A
|
||||
/// value should be chosen that makes sense for each kind of object
|
||||
/// should and allows quick access to further and more in depth parsing.
|
||||
/// and should allow quick access to further and more in depth parsing.
|
||||
///
|
||||
/// Symbol table entries can use this to store the original symbol table
|
||||
/// index, functions can use it to store the symbol table index or the
|
||||
|
|
|
@ -10,14 +10,11 @@
|
|||
#ifndef liblldb_Debug_h_
|
||||
#define liblldb_Debug_h_
|
||||
|
||||
#include "lldb/lldb-private.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/StreamString.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
#include <vector>
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Tells a thread what it needs to do when the process is resumed.
|
||||
//------------------------------------------------------------------
|
||||
|
@ -27,7 +24,7 @@ namespace lldb_private {
|
|||
lldb::StateType state; // Valid values are eStateStopped/eStateSuspended, eStateRunning, and eStateStepping.
|
||||
int signal; // When resuming this thread, resume it with this signal if this value is > 0
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// A class that contains instructions for all threads for
|
||||
// NativeProcessProtocol::Resume(). Each thread can either run, stay
|
||||
|
@ -43,15 +40,14 @@ namespace lldb_private {
|
|||
m_signal_handled ()
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
ResumeActionList (lldb::StateType default_action, int signal) :
|
||||
m_actions(),
|
||||
m_signal_handled ()
|
||||
{
|
||||
SetDefaultThreadActionIfNeeded (default_action, signal);
|
||||
}
|
||||
|
||||
|
||||
|
||||
ResumeActionList (const ResumeAction *actions, size_t num_actions) :
|
||||
m_actions (),
|
||||
m_signal_handled ()
|
||||
|
@ -62,7 +58,7 @@ namespace lldb_private {
|
|||
m_signal_handled.assign (num_actions, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
~ResumeActionList()
|
||||
{
|
||||
}
|
||||
|
@ -72,14 +68,14 @@ namespace lldb_private {
|
|||
{
|
||||
return m_actions.empty();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Append (const ResumeAction &action)
|
||||
{
|
||||
m_actions.push_back (action);
|
||||
m_signal_handled.push_back (false);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AppendAction (lldb::tid_t tid,
|
||||
lldb::StateType state,
|
||||
|
@ -88,25 +84,25 @@ namespace lldb_private {
|
|||
ResumeAction action = { tid, state, signal };
|
||||
Append (action);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AppendResumeAll ()
|
||||
{
|
||||
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateRunning);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AppendSuspendAll ()
|
||||
{
|
||||
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStopped);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
AppendStepAll ()
|
||||
{
|
||||
AppendAction (LLDB_INVALID_THREAD_ID, lldb::eStateStepping);
|
||||
}
|
||||
|
||||
|
||||
const ResumeAction *
|
||||
GetActionForThread (lldb::tid_t tid, bool default_ok) const
|
||||
{
|
||||
|
@ -120,7 +116,7 @@ namespace lldb_private {
|
|||
return GetActionForThread (LLDB_INVALID_THREAD_ID, false);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
NumActionsWithState (lldb::StateType state) const
|
||||
{
|
||||
|
@ -133,7 +129,7 @@ namespace lldb_private {
|
|||
}
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
SetDefaultThreadActionIfNeeded (lldb::StateType action, int signal)
|
||||
{
|
||||
|
@ -147,7 +143,7 @@ namespace lldb_private {
|
|||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetSignalHandledForThread (lldb::tid_t tid) const
|
||||
{
|
||||
|
@ -161,26 +157,26 @@ namespace lldb_private {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
const ResumeAction *
|
||||
GetFirst() const
|
||||
{
|
||||
return m_actions.data();
|
||||
}
|
||||
|
||||
|
||||
size_t
|
||||
GetSize () const
|
||||
{
|
||||
return m_actions.size();
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Clear()
|
||||
{
|
||||
m_actions.clear();
|
||||
m_signal_handled.clear();
|
||||
}
|
||||
|
||||
|
||||
protected:
|
||||
std::vector<ResumeAction> m_actions;
|
||||
mutable std::vector<bool> m_signal_handled;
|
||||
|
@ -191,13 +187,13 @@ namespace lldb_private {
|
|||
lldb::StopReason reason;
|
||||
union
|
||||
{
|
||||
// eStopTypeSignal
|
||||
// eStopReasonSignal
|
||||
struct
|
||||
{
|
||||
uint32_t signo;
|
||||
} signal;
|
||||
|
||||
// eStopTypeException
|
||||
|
||||
// eStopReasonException
|
||||
struct
|
||||
{
|
||||
uint64_t type;
|
||||
|
@ -206,201 +202,5 @@ namespace lldb_private {
|
|||
} exception;
|
||||
} details;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NativeThreadProtocol
|
||||
//------------------------------------------------------------------
|
||||
class NativeThreadProtocol {
|
||||
|
||||
public:
|
||||
NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) :
|
||||
m_process (process),
|
||||
m_tid (tid)
|
||||
{
|
||||
}
|
||||
|
||||
virtual ~NativeThreadProtocol()
|
||||
{
|
||||
}
|
||||
virtual const char *GetName() = 0;
|
||||
virtual lldb::StateType GetState () = 0;
|
||||
virtual Error ReadRegister (uint32_t reg, RegisterValue ®_value) = 0;
|
||||
virtual Error WriteRegister (uint32_t reg, const RegisterValue ®_value) = 0;
|
||||
virtual Error SaveAllRegisters (lldb::DataBufferSP &data_sp) = 0;
|
||||
virtual Error RestoreAllRegisters (lldb::DataBufferSP &data_sp) = 0;
|
||||
virtual bool GetStopReason (ThreadStopInfo &stop_info) = 0;
|
||||
|
||||
lldb::tid_t
|
||||
GetID() const
|
||||
{
|
||||
return m_tid;
|
||||
}
|
||||
protected:
|
||||
NativeProcessProtocol *m_process;
|
||||
lldb::tid_t m_tid;
|
||||
};
|
||||
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NativeProcessProtocol
|
||||
//------------------------------------------------------------------
|
||||
class NativeProcessProtocol {
|
||||
public:
|
||||
|
||||
static NativeProcessProtocol *
|
||||
CreateInstance (lldb::pid_t pid);
|
||||
|
||||
// lldb_private::Host calls should be used to launch a process for debugging, and
|
||||
// then the process should be attached to. When attaching to a process
|
||||
// lldb_private::Host calls should be used to locate the process to attach to,
|
||||
// and then this function should be called.
|
||||
NativeProcessProtocol (lldb::pid_t pid) :
|
||||
m_pid (pid),
|
||||
m_threads(),
|
||||
m_threads_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_state (lldb::eStateInvalid),
|
||||
m_exit_status(0),
|
||||
m_exit_description()
|
||||
{
|
||||
}
|
||||
|
||||
public:
|
||||
virtual ~NativeProcessProtocol ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual Error Resume (const ResumeActionList &resume_actions) = 0;
|
||||
virtual Error Halt () = 0;
|
||||
virtual Error Detach () = 0;
|
||||
virtual Error Signal (int signo) = 0;
|
||||
virtual Error Kill () = 0;
|
||||
|
||||
virtual Error ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0;
|
||||
virtual Error WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0;
|
||||
virtual Error AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0;
|
||||
virtual Error DeallocateMemory (lldb::addr_t addr) = 0;
|
||||
|
||||
virtual lldb::addr_t GetSharedLibraryInfoAddress () = 0;
|
||||
|
||||
virtual bool IsAlive () = 0;
|
||||
virtual size_t UpdateThreads () = 0;
|
||||
virtual bool GetArchitecture (ArchSpec &arch) = 0;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Breakpoint functions
|
||||
//----------------------------------------------------------------------
|
||||
virtual Error SetBreakpoint (lldb::addr_t addr, size_t size, bool hardware) = 0;
|
||||
virtual Error RemoveBreakpoint (lldb::addr_t addr, size_t size) = 0;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Watchpoint functions
|
||||
//----------------------------------------------------------------------
|
||||
virtual uint32_t GetMaxWatchpoints () = 0;
|
||||
virtual Error SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0;
|
||||
virtual Error RemoveWatchpoint (lldb::addr_t addr) = 0;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Accessors
|
||||
//----------------------------------------------------------------------
|
||||
lldb::pid_t
|
||||
GetID() const
|
||||
{
|
||||
return m_pid;
|
||||
}
|
||||
|
||||
lldb::StateType
|
||||
GetState () const
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
bool
|
||||
IsRunning () const
|
||||
{
|
||||
return m_state == lldb::eStateRunning || IsStepping();
|
||||
}
|
||||
|
||||
bool
|
||||
IsStepping () const
|
||||
{
|
||||
return m_state == lldb::eStateStepping;
|
||||
}
|
||||
|
||||
bool
|
||||
CanResume () const
|
||||
{
|
||||
return m_state == lldb::eStateStopped;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
SetState (lldb::StateType state)
|
||||
{
|
||||
m_state = state;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Exit Status
|
||||
//----------------------------------------------------------------------
|
||||
virtual bool
|
||||
GetExitStatus (int *status)
|
||||
{
|
||||
if (m_state == lldb::eStateExited)
|
||||
{
|
||||
*status = m_exit_status;
|
||||
return true;
|
||||
}
|
||||
*status = 0;
|
||||
return false;
|
||||
}
|
||||
virtual bool
|
||||
SetExitStatus (int status, const char *exit_description)
|
||||
{
|
||||
// Exit status already set
|
||||
if (m_state == lldb::eStateExited)
|
||||
return false;
|
||||
m_state = lldb::eStateExited;
|
||||
m_exit_status = status;
|
||||
if (exit_description && exit_description[0])
|
||||
m_exit_description = exit_description;
|
||||
else
|
||||
m_exit_description.clear();
|
||||
return true;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Access to threads
|
||||
//----------------------------------------------------------------------
|
||||
lldb::NativeThreadProtocolSP
|
||||
GetThreadAtIndex (uint32_t idx)
|
||||
{
|
||||
Mutex::Locker locker(m_threads_mutex);
|
||||
if (idx < m_threads.size())
|
||||
return m_threads[idx];
|
||||
return lldb::NativeThreadProtocolSP();
|
||||
}
|
||||
|
||||
lldb::NativeThreadProtocolSP
|
||||
GetThreadByID (lldb::tid_t tid)
|
||||
{
|
||||
Mutex::Locker locker(m_threads_mutex);
|
||||
for (auto thread_sp : m_threads)
|
||||
{
|
||||
if (thread_sp->GetID() == tid)
|
||||
return thread_sp;
|
||||
}
|
||||
return lldb::NativeThreadProtocolSP();
|
||||
}
|
||||
|
||||
protected:
|
||||
lldb::pid_t m_pid;
|
||||
std::vector<lldb::NativeThreadProtocolSP> m_threads;
|
||||
mutable Mutex m_threads_mutex;
|
||||
lldb::StateType m_state;
|
||||
int m_exit_status;
|
||||
std::string m_exit_description;
|
||||
};
|
||||
|
||||
}
|
||||
#endif // #ifndef liblldb_Debug_h_
|
||||
|
|
|
@ -503,6 +503,9 @@ public:
|
|||
static lldb::DataBufferSP
|
||||
GetAuxvData (lldb_private::Process *process);
|
||||
|
||||
static lldb::DataBufferSP
|
||||
GetAuxvData (lldb::pid_t pid);
|
||||
|
||||
static lldb::TargetSP
|
||||
GetDummyTarget (Debugger &debugger);
|
||||
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
#ifndef lldb_MemoryRegionInfo_h
|
||||
#define lldb_MemoryRegionInfo_h
|
||||
|
||||
#include "lldb/Core/RangeMap.h"
|
||||
#include "lldb/Utility/Range.h"
|
||||
|
||||
namespace lldb_private
|
||||
|
|
|
@ -0,0 +1,190 @@
|
|||
//===-- NativeRegisterContext.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_NativeRegisterContext_h_
|
||||
#define liblldb_NativeRegisterContext_h_
|
||||
|
||||
// C Includes
|
||||
// C++ Includes
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/lldb-private.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
class NativeThreadProtocol;
|
||||
|
||||
class NativeRegisterContext:
|
||||
public std::enable_shared_from_this<NativeRegisterContext>
|
||||
{
|
||||
public:
|
||||
//------------------------------------------------------------------
|
||||
// Constructors and Destructors
|
||||
//------------------------------------------------------------------
|
||||
NativeRegisterContext (NativeThreadProtocol &thread, uint32_t concrete_frame_idx);
|
||||
|
||||
virtual
|
||||
~NativeRegisterContext ();
|
||||
|
||||
// void
|
||||
// InvalidateIfNeeded (bool force);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Subclasses must override these functions
|
||||
//------------------------------------------------------------------
|
||||
// virtual void
|
||||
// InvalidateAllRegisters () = 0;
|
||||
|
||||
virtual uint32_t
|
||||
GetRegisterCount () const = 0;
|
||||
|
||||
virtual const RegisterInfo *
|
||||
GetRegisterInfoAtIndex (uint32_t reg) const = 0;
|
||||
|
||||
const char *
|
||||
GetRegisterSetNameForRegisterAtIndex (uint32_t reg_index) const;
|
||||
|
||||
virtual uint32_t
|
||||
GetRegisterSetCount () const = 0;
|
||||
|
||||
virtual const RegisterSet *
|
||||
GetRegisterSet (uint32_t set_index) const = 0;
|
||||
|
||||
virtual Error
|
||||
ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) = 0;
|
||||
|
||||
virtual Error
|
||||
WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) = 0;
|
||||
|
||||
virtual Error
|
||||
ReadAllRegisterValues (lldb::DataBufferSP &data_sp) = 0;
|
||||
|
||||
virtual Error
|
||||
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) = 0;
|
||||
|
||||
uint32_t
|
||||
ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Subclasses can override these functions if desired
|
||||
//------------------------------------------------------------------
|
||||
virtual uint32_t
|
||||
NumSupportedHardwareBreakpoints ();
|
||||
|
||||
virtual uint32_t
|
||||
SetHardwareBreakpoint (lldb::addr_t addr, size_t size);
|
||||
|
||||
virtual bool
|
||||
ClearHardwareBreakpoint (uint32_t hw_idx);
|
||||
|
||||
virtual uint32_t
|
||||
NumSupportedHardwareWatchpoints ();
|
||||
|
||||
virtual uint32_t
|
||||
SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags);
|
||||
|
||||
virtual bool
|
||||
ClearHardwareWatchpoint (uint32_t hw_index);
|
||||
|
||||
virtual bool
|
||||
HardwareSingleStep (bool enable);
|
||||
|
||||
virtual Error
|
||||
ReadRegisterValueFromMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t src_addr, lldb::addr_t src_len, RegisterValue ®_value);
|
||||
|
||||
virtual Error
|
||||
WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, lldb::addr_t dst_len, const RegisterValue ®_value);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Subclasses should not override these
|
||||
//------------------------------------------------------------------
|
||||
virtual lldb::tid_t
|
||||
GetThreadID() const;
|
||||
|
||||
virtual NativeThreadProtocol &
|
||||
GetThread ()
|
||||
{
|
||||
return m_thread;
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
GetRegisterInfoByName (const char *reg_name, uint32_t start_idx = 0);
|
||||
|
||||
const RegisterInfo *
|
||||
GetRegisterInfo (uint32_t reg_kind, uint32_t reg_num);
|
||||
|
||||
lldb::addr_t
|
||||
GetPC (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS);
|
||||
|
||||
Error
|
||||
SetPC (lldb::addr_t pc);
|
||||
|
||||
lldb::addr_t
|
||||
GetSP (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS);
|
||||
|
||||
Error
|
||||
SetSP (lldb::addr_t sp);
|
||||
|
||||
lldb::addr_t
|
||||
GetFP (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS);
|
||||
|
||||
Error
|
||||
SetFP (lldb::addr_t fp);
|
||||
|
||||
const char *
|
||||
GetRegisterName (uint32_t reg);
|
||||
|
||||
lldb::addr_t
|
||||
GetReturnAddress (lldb::addr_t fail_value = LLDB_INVALID_ADDRESS);
|
||||
|
||||
lldb::addr_t
|
||||
GetFlags (lldb::addr_t fail_value = 0);
|
||||
|
||||
lldb::addr_t
|
||||
ReadRegisterAsUnsigned (uint32_t reg, lldb::addr_t fail_value);
|
||||
|
||||
lldb::addr_t
|
||||
ReadRegisterAsUnsigned (const RegisterInfo *reg_info, lldb::addr_t fail_value);
|
||||
|
||||
Error
|
||||
WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval);
|
||||
|
||||
Error
|
||||
WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval);
|
||||
|
||||
// uint32_t
|
||||
// GetStopID () const
|
||||
// {
|
||||
// return m_stop_id;
|
||||
// }
|
||||
|
||||
// void
|
||||
// SetStopID (uint32_t stop_id)
|
||||
// {
|
||||
// m_stop_id = stop_id;
|
||||
// }
|
||||
|
||||
protected:
|
||||
//------------------------------------------------------------------
|
||||
// Classes that inherit from RegisterContext can see and modify these
|
||||
//------------------------------------------------------------------
|
||||
NativeThreadProtocol &m_thread; // The thread that this register context belongs to.
|
||||
uint32_t m_concrete_frame_idx; // The concrete frame index for this register context
|
||||
// uint32_t m_stop_id; // The stop ID that any data in this context is valid for
|
||||
|
||||
private:
|
||||
//------------------------------------------------------------------
|
||||
// For RegisterContext only
|
||||
//------------------------------------------------------------------
|
||||
DISALLOW_COPY_AND_ASSIGN (NativeRegisterContext);
|
||||
};
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
#endif // liblldb_NativeRegisterContext_h_
|
|
@ -0,0 +1,44 @@
|
|||
//===-- NativeRegisterContextRegisterInfo.h ----------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef lldb_NativeRegisterContextRegisterInfo_h
|
||||
#define lldb_NativeRegisterContextRegisterInfo_h
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "NativeRegisterContext.h"
|
||||
#include "Plugins/Process/Utility/RegisterInfoInterface.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class NativeRegisterContextRegisterInfo: public NativeRegisterContext
|
||||
{
|
||||
public:
|
||||
///
|
||||
/// Construct a NativeRegisterContextRegisterInfo, taking ownership
|
||||
/// of the register_info_interface pointer.
|
||||
///
|
||||
NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread,
|
||||
uint32_t concrete_frame_idx,
|
||||
RegisterInfoInterface *register_info_interface);
|
||||
|
||||
uint32_t
|
||||
GetRegisterCount () const override;
|
||||
|
||||
const RegisterInfo *
|
||||
GetRegisterInfoAtIndex (uint32_t reg_index) const override;
|
||||
|
||||
const RegisterInfoInterface&
|
||||
GetRegisterInfoInterface () const;
|
||||
|
||||
private:
|
||||
std::unique_ptr<RegisterInfoInterface> m_register_info_interface_up;
|
||||
};
|
||||
}
|
||||
#endif
|
|
@ -18,6 +18,7 @@
|
|||
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "lldb/lldb-public.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/ConstString.h"
|
||||
|
@ -25,6 +26,10 @@
|
|||
#include "lldb/Interpreter/Options.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
|
||||
// TODO pull NativeDelegate class out of NativeProcessProtocol so we
|
||||
// can just forward ref the NativeDelegate rather than include it here.
|
||||
#include "../../../source/Host/common/NativeProcessProtocol.h"
|
||||
|
||||
namespace lldb_private {
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
|
@ -858,6 +863,65 @@ namespace lldb_private {
|
|||
virtual const std::vector<ConstString> &
|
||||
GetTrapHandlerSymbolNames ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Launch a process for debugging.
|
||||
///
|
||||
/// This differs from Launch in that it returns a NativeProcessProtocol.
|
||||
/// Currently used by lldb-gdbserver.
|
||||
///
|
||||
/// @param[in] launch_info
|
||||
/// Information required to launch the process.
|
||||
///
|
||||
/// @param[in] native_delegate
|
||||
/// The delegate that will receive messages regarding the
|
||||
/// inferior. Must outlive the NativeProcessProtocol
|
||||
/// instance.
|
||||
///
|
||||
/// @param[out] process_sp
|
||||
/// On successful return from the method, this parameter
|
||||
/// contains the shared pointer to the
|
||||
/// NativeProcessProtocol that can be used to manipulate
|
||||
/// the native process.
|
||||
///
|
||||
/// @return
|
||||
/// An error object indicating if the operation succeeded,
|
||||
/// and if not, what error occurred.
|
||||
//------------------------------------------------------------------
|
||||
virtual Error
|
||||
LaunchNativeProcess (
|
||||
ProcessLaunchInfo &launch_info,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Attach to an existing process on the given platform.
|
||||
///
|
||||
/// This method differs from Attach() in that it returns a
|
||||
/// NativeProcessProtocol. Currently this is used by lldb-gdbserver.
|
||||
///
|
||||
/// @param[in] pid
|
||||
/// pid of the process locatable by the platform.
|
||||
///
|
||||
/// @param[in] native_delegate
|
||||
/// The delegate that will receive messages regarding the
|
||||
/// inferior. Must outlive the NativeProcessProtocol
|
||||
/// instance.
|
||||
///
|
||||
/// @param[out] process_sp
|
||||
/// On successful return from the method, this parameter
|
||||
/// contains the shared pointer to the
|
||||
/// NativeProcessProtocol that can be used to manipulate
|
||||
/// the native process.
|
||||
///
|
||||
/// @return
|
||||
/// An error object indicating if the operation succeeded,
|
||||
/// and if not, what error occurred.
|
||||
//------------------------------------------------------------------
|
||||
virtual Error
|
||||
AttachNativeProcess (lldb::pid_t pid,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp);
|
||||
|
||||
protected:
|
||||
bool m_is_host;
|
||||
// Set to true when we are able to actually set the OS version while
|
||||
|
|
|
@ -1097,6 +1097,17 @@ public:
|
|||
virtual DynamicLoader *
|
||||
GetDynamicLoader ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// Returns AUXV structure found in many ELF-based environments.
|
||||
//
|
||||
// The default action is to return an empty data buffer.
|
||||
//
|
||||
// @return
|
||||
// A data buffer containing the contents of the AUXV data.
|
||||
//------------------------------------------------------------------
|
||||
virtual const lldb::DataBufferSP
|
||||
GetAuxvData();
|
||||
|
||||
protected:
|
||||
virtual JITLoaderList &
|
||||
GetJITLoaders ();
|
||||
|
|
|
@ -788,6 +788,27 @@ namespace lldb {
|
|||
} ExpressionEvaluationPhase;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Watchpoint Kind
|
||||
// Indicates what types of events cause the watchpoint to fire.
|
||||
// Used by Native*Protocol-related classes.
|
||||
//----------------------------------------------------------------------
|
||||
typedef enum WatchpointKind
|
||||
{
|
||||
eWatchpointKindRead = (1u << 0),
|
||||
eWatchpointKindWrite = (1u << 1)
|
||||
} WatchpointKind;
|
||||
|
||||
typedef enum GdbSignal
|
||||
{
|
||||
eGdbSignalBadAccess = 0x91,
|
||||
eGdbSignalBadInstruction = 0x92,
|
||||
eGdbSignalArithmetic = 0x93,
|
||||
eGdbSignalEmulation = 0x94,
|
||||
eGdbSignalSoftware = 0x95,
|
||||
eGdbSignalBreakpoint = 0x96
|
||||
} GdbRemoteSignal;
|
||||
|
||||
} // namespace lldb
|
||||
|
||||
|
||||
|
|
|
@ -246,6 +246,16 @@ enum class LineStatus {
|
|||
Done // Lines are complete
|
||||
};
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Exit Type for inferior processes
|
||||
//----------------------------------------------------------------------
|
||||
typedef enum ExitType {
|
||||
eExitTypeInvalid,
|
||||
eExitTypeExit, // The exit status represents the return code from normal program exit (i.e. WIFEXITED() was true)
|
||||
eExitTypeSignal, // The exit status represents the signal number that caused the program to exit (i.e. WIFSIGNALED() was true)
|
||||
eExitTypeStop, // The exit status represents the stop signal that caused the program to exit (i.e. WIFSTOPPED() was true)
|
||||
} ExitType;
|
||||
|
||||
} // namespace lldb_private
|
||||
|
||||
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
//===-- lldb-private-forward.h ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef LLDB_lldb_private_forward_h_
|
||||
#define LLDB_lldb_private_forward_h_
|
||||
|
||||
#if defined(__cplusplus)
|
||||
|
||||
#include <memory>
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
// ---------------------------------------------------------------
|
||||
// Class forward decls.
|
||||
// ---------------------------------------------------------------
|
||||
class NativeBreakpoint;
|
||||
class NativeBreakpointList;
|
||||
class NativeProcessProtocol;
|
||||
class NativeRegisterContext;
|
||||
class NativeThreadProtocol;
|
||||
|
||||
// ---------------------------------------------------------------
|
||||
// SP/WP decls.
|
||||
// ---------------------------------------------------------------
|
||||
typedef std::shared_ptr<NativeBreakpoint> NativeBreakpointSP;
|
||||
typedef std::shared_ptr<lldb_private::NativeProcessProtocol> NativeProcessProtocolSP;
|
||||
typedef std::weak_ptr<lldb_private::NativeProcessProtocol> NativeProcessProtocolWP;
|
||||
typedef std::shared_ptr<lldb_private::NativeRegisterContext> NativeRegisterContextSP;
|
||||
typedef std::shared_ptr<lldb_private::NativeThreadProtocol> NativeThreadProtocolSP;
|
||||
}
|
||||
|
||||
#endif // #if defined(__cplusplus)
|
||||
#endif // #ifndef LLDB_lldb_private_forward_h_
|
|
@ -51,20 +51,33 @@
|
|||
/* End PBXAggregateTarget section */
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
23059A0719532B96007B8189 /* LinuxSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23059A0519532B96007B8189 /* LinuxSignals.cpp */; };
|
||||
23059A101958B319007B8189 /* SBUnixSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23059A0F1958B319007B8189 /* SBUnixSignals.cpp */; };
|
||||
23059A121958B3B2007B8189 /* SBUnixSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = 23059A111958B37B007B8189 /* SBUnixSignals.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */; };
|
||||
232CB616191E00CD00EF39FC /* NativeBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */; };
|
||||
232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */; };
|
||||
232CB618191E00CD00EF39FC /* NativeBreakpointList.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB60E191E00CC00EF39FC /* NativeBreakpointList.h */; };
|
||||
232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */; };
|
||||
232CB61A191E00CD00EF39FC /* NativeProcessProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB610191E00CC00EF39FC /* NativeProcessProtocol.h */; };
|
||||
232CB61B191E00CD00EF39FC /* NativeThreadProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */; };
|
||||
232CB61C191E00CD00EF39FC /* NativeThreadProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */; };
|
||||
232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */; };
|
||||
232CB61E191E00CD00EF39FC /* SoftwareBreakpoint.h in Headers */ = {isa = PBXBuildFile; fileRef = 232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */; };
|
||||
233B007D1960C9F90090E598 /* ProcessInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007B1960C9E60090E598 /* ProcessInfo.cpp */; };
|
||||
233B007F1960CB280090E598 /* ProcessLaunchInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */; };
|
||||
233B009419610B1F0090E598 /* LinuxSignals.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008C19610B1F0090E598 /* LinuxSignals.cpp */; };
|
||||
233B009519610B1F0090E598 /* LinuxSignals.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008D19610B1F0090E598 /* LinuxSignals.h */; };
|
||||
233B009619610B1F0090E598 /* LinuxThread.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008E19610B1F0090E598 /* LinuxThread.cpp */; };
|
||||
233B009719610B1F0090E598 /* LinuxThread.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B008F19610B1F0090E598 /* LinuxThread.h */; };
|
||||
233B009819610B1F0090E598 /* ProcessLinux.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009019610B1F0090E598 /* ProcessLinux.cpp */; };
|
||||
233B009919610B1F0090E598 /* ProcessLinux.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009119610B1F0090E598 /* ProcessLinux.h */; };
|
||||
233B009A19610B1F0090E598 /* ProcessMonitor.cpp in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009219610B1F0090E598 /* ProcessMonitor.cpp */; };
|
||||
233B009B19610B1F0090E598 /* ProcessMonitor.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 233B009319610B1F0090E598 /* ProcessMonitor.h */; };
|
||||
239F5B2F19296DC500083917 /* NativeRegisterContextLinux_x86_64.h in Headers */ = {isa = PBXBuildFile; fileRef = 239F5B2E19296DC500083917 /* NativeRegisterContextLinux_x86_64.h */; };
|
||||
23EDE3321926843600F6A132 /* NativeRegisterContext.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 23EDE3311926843600F6A132 /* NativeRegisterContext.h */; };
|
||||
23EDE33319269E7C00F6A132 /* NativeRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */; };
|
||||
23EFE389193D1ABC00E54E54 /* SBTypeEnumMember.h in Headers */ = {isa = PBXBuildFile; fileRef = 23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */; settings = {ATTRIBUTES = (Public, ); }; };
|
||||
23EFE38B193D1AEC00E54E54 /* SBTypeEnumMember.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */; };
|
||||
23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */; };
|
||||
260157C61885F51C00F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
|
||||
260157C71885F52500F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
|
||||
260157C81885F53100F875CF /* libpanel.dylib in Frameworks */ = {isa = PBXBuildFile; fileRef = 260157C41885F4FF00F875CF /* libpanel.dylib */; };
|
||||
|
@ -692,7 +705,6 @@
|
|||
AF1F7B07189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF1F7B05189C904B0087DB9C /* AppleGetPendingItemsHandler.cpp */; };
|
||||
AF1F7B08189C904B0087DB9C /* AppleGetPendingItemsHandler.h in Headers */ = {isa = PBXBuildFile; fileRef = AF1F7B06189C904B0087DB9C /* AppleGetPendingItemsHandler.h */; };
|
||||
AF23B4DB19009C66003E2A58 /* FreeBSDSignals.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF23B4D919009C66003E2A58 /* FreeBSDSignals.cpp */; };
|
||||
AF23B4DC19009C66003E2A58 /* FreeBSDSignals.h in Headers */ = {isa = PBXBuildFile; fileRef = AF23B4DA19009C66003E2A58 /* FreeBSDSignals.h */; };
|
||||
AF254E31170CCC33007AE5C9 /* PlatformDarwinKernel.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF254E2F170CCC33007AE5C9 /* PlatformDarwinKernel.cpp */; };
|
||||
AF254E32170CCC33007AE5C9 /* PlatformDarwinKernel.h in Headers */ = {isa = PBXBuildFile; fileRef = AF254E30170CCC33007AE5C9 /* PlatformDarwinKernel.h */; };
|
||||
AF25AB26188F685C0030DEC3 /* AppleGetQueuesHandler.cpp in Sources */ = {isa = PBXBuildFile; fileRef = AF25AB24188F685C0030DEC3 /* AppleGetQueuesHandler.cpp */; };
|
||||
|
@ -861,14 +873,13 @@
|
|||
dstPath = "$(DEVELOPER_DIR)/usr/share/man/man1/";
|
||||
dstSubfolderSpec = 0;
|
||||
files = (
|
||||
23EDE3321926843600F6A132 /* NativeRegisterContext.h in CopyFiles */,
|
||||
233B009819610B1F0090E598 /* ProcessLinux.cpp in CopyFiles */,
|
||||
233B009619610B1F0090E598 /* LinuxThread.cpp in CopyFiles */,
|
||||
233B009A19610B1F0090E598 /* ProcessMonitor.cpp in CopyFiles */,
|
||||
233B009719610B1F0090E598 /* LinuxThread.h in CopyFiles */,
|
||||
233B009919610B1F0090E598 /* ProcessLinux.h in CopyFiles */,
|
||||
233B009B19610B1F0090E598 /* ProcessMonitor.h in CopyFiles */,
|
||||
233B009419610B1F0090E598 /* LinuxSignals.cpp in CopyFiles */,
|
||||
233B009519610B1F0090E598 /* LinuxSignals.h in CopyFiles */,
|
||||
AF90106515AB7D3600FF120D /* lldb.1 in CopyFiles */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 1;
|
||||
|
@ -891,14 +902,29 @@
|
|||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
23059A0519532B96007B8189 /* LinuxSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = LinuxSignals.cpp; path = Utility/LinuxSignals.cpp; sourceTree = "<group>"; };
|
||||
23059A0619532B96007B8189 /* LinuxSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = LinuxSignals.h; path = Utility/LinuxSignals.h; sourceTree = "<group>"; };
|
||||
23059A0F1958B319007B8189 /* SBUnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBUnixSignals.cpp; path = source/API/SBUnixSignals.cpp; sourceTree = "<group>"; };
|
||||
23059A111958B37B007B8189 /* SBUnixSignals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBUnixSignals.h; path = include/lldb/API/SBUnixSignals.h; sourceTree = "<group>"; };
|
||||
23173F8B192BA93F005C708F /* lldb-x86-register-enums.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = "lldb-x86-register-enums.h"; path = "Utility/lldb-x86-register-enums.h"; sourceTree = "<group>"; };
|
||||
232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpoint.cpp; path = source/Host/common/NativeBreakpoint.cpp; sourceTree = "<group>"; };
|
||||
232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = source/Host/common/NativeBreakpoint.h; sourceTree = "<group>"; };
|
||||
232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpointList.cpp; path = source/Host/common/NativeBreakpointList.cpp; sourceTree = "<group>"; };
|
||||
232CB60E191E00CC00EF39FC /* NativeBreakpointList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = source/Host/common/NativeBreakpointList.h; sourceTree = "<group>"; };
|
||||
232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = NativeProcessProtocol.cpp; path = source/Host/common/NativeProcessProtocol.cpp; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.cpp; };
|
||||
232CB610191E00CC00EF39FC /* NativeProcessProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeProcessProtocol.h; path = source/Host/common/NativeProcessProtocol.h; sourceTree = "<group>"; };
|
||||
232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeThreadProtocol.cpp; path = source/Host/common/NativeThreadProtocol.cpp; sourceTree = "<group>"; };
|
||||
232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeThreadProtocol.h; path = source/Host/common/NativeThreadProtocol.h; sourceTree = "<group>"; };
|
||||
232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareBreakpoint.cpp; path = source/Host/common/SoftwareBreakpoint.cpp; sourceTree = "<group>"; };
|
||||
232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = source/Host/common/SoftwareBreakpoint.h; sourceTree = "<group>"; };
|
||||
232CB62B19213AC200EF39FC /* NativeProcessLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeProcessLinux.cpp; sourceTree = "<group>"; };
|
||||
232CB62C19213AC200EF39FC /* NativeProcessLinux.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = NativeProcessLinux.h; sourceTree = "<group>"; };
|
||||
232CB62D19213AC200EF39FC /* NativeThreadLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeThreadLinux.cpp; sourceTree = "<group>"; };
|
||||
232CB62E19213AC200EF39FC /* NativeThreadLinux.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NativeThreadLinux.h; sourceTree = "<group>"; };
|
||||
233B007919609DB40090E598 /* ProcessLaunchInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessLaunchInfo.h; path = include/lldb/Target/ProcessLaunchInfo.h; sourceTree = "<group>"; };
|
||||
233B007A1960A0440090E598 /* ProcessInfo.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = ProcessInfo.h; path = include/lldb/Target/ProcessInfo.h; sourceTree = "<group>"; };
|
||||
233B007B1960C9E60090E598 /* ProcessInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessInfo.cpp; path = source/Target/ProcessInfo.cpp; sourceTree = "<group>"; };
|
||||
233B007E1960CB280090E598 /* ProcessLaunchInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = ProcessLaunchInfo.cpp; path = source/Target/ProcessLaunchInfo.cpp; sourceTree = "<group>"; };
|
||||
233B008C19610B1F0090E598 /* LinuxSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinuxSignals.cpp; sourceTree = "<group>"; };
|
||||
233B008D19610B1F0090E598 /* LinuxSignals.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinuxSignals.h; sourceTree = "<group>"; };
|
||||
233B008E19610B1F0090E598 /* LinuxThread.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = LinuxThread.cpp; sourceTree = "<group>"; };
|
||||
233B008F19610B1F0090E598 /* LinuxThread.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LinuxThread.h; sourceTree = "<group>"; };
|
||||
233B009019610B1F0090E598 /* ProcessLinux.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = ProcessLinux.cpp; sourceTree = "<group>"; };
|
||||
|
@ -909,9 +935,15 @@
|
|||
233B00A1196113730090E598 /* ProcFileReader.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = ProcFileReader.cpp; sourceTree = "<group>"; };
|
||||
233B00A2196113730090E598 /* ProcFileReader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ProcFileReader.h; sourceTree = "<group>"; };
|
||||
2360092C193FB21500189DB1 /* MemoryRegionInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MemoryRegionInfo.h; path = include/lldb/Target/MemoryRegionInfo.h; sourceTree = "<group>"; };
|
||||
239F5B2E19296DC500083917 /* NativeRegisterContextLinux_x86_64.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContextLinux_x86_64.h; path = Utility/NativeRegisterContextLinux_x86_64.h; sourceTree = "<group>"; };
|
||||
239F5B3019298D4600083917 /* NativeRegisterContextLinux_x86_64.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContextLinux_x86_64.cpp; path = Utility/NativeRegisterContextLinux_x86_64.cpp; sourceTree = "<group>"; };
|
||||
23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContext.cpp; path = source/Target/NativeRegisterContext.cpp; sourceTree = "<group>"; };
|
||||
23EDE3311926843600F6A132 /* NativeRegisterContext.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContext.h; path = include/lldb/Target/NativeRegisterContext.h; sourceTree = "<group>"; };
|
||||
23EDE3371926AAD500F6A132 /* RegisterInfoInterface.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = RegisterInfoInterface.h; path = Utility/RegisterInfoInterface.h; sourceTree = "<group>"; };
|
||||
23EFE388193D1ABC00E54E54 /* SBTypeEnumMember.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBTypeEnumMember.h; path = include/lldb/API/SBTypeEnumMember.h; sourceTree = "<group>"; };
|
||||
23EFE38A193D1AEC00E54E54 /* SBTypeEnumMember.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = SBTypeEnumMember.cpp; path = source/API/SBTypeEnumMember.cpp; sourceTree = "<group>"; };
|
||||
23F403471926C8D50046DC9B /* NativeRegisterContextRegisterInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeRegisterContextRegisterInfo.h; path = include/lldb/Target/NativeRegisterContextRegisterInfo.h; sourceTree = "<group>"; };
|
||||
23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeRegisterContextRegisterInfo.cpp; path = source/Target/NativeRegisterContextRegisterInfo.cpp; sourceTree = "<group>"; };
|
||||
260157C41885F4FF00F875CF /* libpanel.dylib */ = {isa = PBXFileReference; lastKnownFileType = "compiled.mach-o.dylib"; name = libpanel.dylib; path = /usr/lib/libpanel.dylib; sourceTree = "<absolute>"; };
|
||||
260223E7115F06D500A601A2 /* SBCommunication.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SBCommunication.h; path = include/lldb/API/SBCommunication.h; sourceTree = "<group>"; };
|
||||
260223E8115F06E500A601A2 /* SBCommunication.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBCommunication.cpp; path = source/API/SBCommunication.cpp; sourceTree = "<group>"; };
|
||||
|
@ -2186,10 +2218,12 @@
|
|||
233B008B196106E90090E598 /* Linux */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
233B008C19610B1F0090E598 /* LinuxSignals.cpp */,
|
||||
233B008D19610B1F0090E598 /* LinuxSignals.h */,
|
||||
233B008E19610B1F0090E598 /* LinuxThread.cpp */,
|
||||
233B008F19610B1F0090E598 /* LinuxThread.h */,
|
||||
232CB62B19213AC200EF39FC /* NativeProcessLinux.cpp */,
|
||||
232CB62C19213AC200EF39FC /* NativeProcessLinux.h */,
|
||||
232CB62D19213AC200EF39FC /* NativeThreadLinux.cpp */,
|
||||
232CB62E19213AC200EF39FC /* NativeThreadLinux.h */,
|
||||
233B009019610B1F0090E598 /* ProcessLinux.cpp */,
|
||||
233B009119610B1F0090E598 /* ProcessLinux.h */,
|
||||
233B009219610B1F0090E598 /* ProcessMonitor.cpp */,
|
||||
|
@ -2882,6 +2916,8 @@
|
|||
B28058A0139988B0002D96D0 /* InferiorCallPOSIX.cpp */,
|
||||
B28058A2139988C6002D96D0 /* InferiorCallPOSIX.h */,
|
||||
B2D3033612EFA5C500F84EB3 /* InstructionUtils.h */,
|
||||
23059A0519532B96007B8189 /* LinuxSignals.cpp */,
|
||||
23059A0619532B96007B8189 /* LinuxSignals.h */,
|
||||
26474C9E18D0CAEC0073DEBA /* RegisterContext_mips64.h */,
|
||||
26474C9F18D0CAEC0073DEBA /* RegisterContext_x86.h */,
|
||||
26957D9213D381C900670048 /* RegisterContextDarwin_arm.cpp */,
|
||||
|
@ -2939,6 +2975,9 @@
|
|||
26E3EEE411A9901300FBADB6 /* UnwindMacOSXFrameBackchain.h */,
|
||||
26E3EEE311A9901300FBADB6 /* UnwindMacOSXFrameBackchain.cpp */,
|
||||
23EDE3371926AAD500F6A132 /* RegisterInfoInterface.h */,
|
||||
239F5B2E19296DC500083917 /* NativeRegisterContextLinux_x86_64.h */,
|
||||
239F5B3019298D4600083917 /* NativeRegisterContextLinux_x86_64.cpp */,
|
||||
23173F8B192BA93F005C708F /* lldb-x86-register-enums.h */,
|
||||
);
|
||||
name = Utility;
|
||||
sourceTree = "<group>";
|
||||
|
@ -3376,10 +3415,20 @@
|
|||
26FA4315130103F400E71120 /* FileSpec.h */,
|
||||
26BC7DD410F1B7D500F91463 /* Host.h */,
|
||||
26BC7DD510F1B7D500F91463 /* Mutex.h */,
|
||||
232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */,
|
||||
232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */,
|
||||
232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */,
|
||||
232CB60E191E00CC00EF39FC /* NativeBreakpointList.h */,
|
||||
232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */,
|
||||
232CB610191E00CC00EF39FC /* NativeProcessProtocol.h */,
|
||||
232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */,
|
||||
232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */,
|
||||
A36FF33D17D8E98800244D40 /* OptionParser.h */,
|
||||
26BC7DD610F1B7D500F91463 /* Predicate.h */,
|
||||
26D7E45B13D5E2F9007FD12B /* SocketAddress.h */,
|
||||
26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */,
|
||||
232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */,
|
||||
232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */,
|
||||
2689B0A4113EE3CD00A4AEDB /* Symbols.h */,
|
||||
268DA871130095D000C9483A /* Terminal.h */,
|
||||
26B4E26E112F35F700AB3F64 /* TimeValue.h */,
|
||||
|
@ -3486,6 +3535,8 @@
|
|||
26BC7DEF10F1B80200F91463 /* Target */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
23EDE3311926843600F6A132 /* NativeRegisterContext.h */,
|
||||
23EDE3301926839700F6A132 /* NativeRegisterContext.cpp */,
|
||||
497E7B331188ED300065CCA1 /* ABI.h */,
|
||||
497E7B9D1188F6690065CCA1 /* ABI.cpp */,
|
||||
4CB443BB1249920C00C13DC2 /* CPPLanguageRuntime.h */,
|
||||
|
@ -3583,6 +3634,8 @@
|
|||
26E3EEBD11A9870400FBADB6 /* Unwind.h */,
|
||||
264D8D4E13661BCC003A368F /* UnwindAssembly.h */,
|
||||
264D8D4F13661BD7003A368F /* UnwindAssembly.cpp */,
|
||||
23F403471926C8D50046DC9B /* NativeRegisterContextRegisterInfo.h */,
|
||||
23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */,
|
||||
);
|
||||
name = Target;
|
||||
sourceTree = "<group>";
|
||||
|
@ -4103,6 +4156,7 @@
|
|||
26FFC19C14FC072100087D58 /* DYLDRendezvous.h in Headers */,
|
||||
AF1F7B08189C904B0087DB9C /* AppleGetPendingItemsHandler.h in Headers */,
|
||||
AF2BCA6D18C7EFDE005B4526 /* JITLoaderGDB.h in Headers */,
|
||||
232CB61E191E00CD00EF39FC /* SoftwareBreakpoint.h in Headers */,
|
||||
26BC17B218C7F4CB00D2196D /* ThreadElfCore.h in Headers */,
|
||||
26FFC19E14FC072100087D58 /* DynamicLoaderPOSIXDYLD.h in Headers */,
|
||||
AF254E32170CCC33007AE5C9 /* PlatformDarwinKernel.h in Headers */,
|
||||
|
@ -4120,6 +4174,7 @@
|
|||
260CC63115D04377002BF2E0 /* OptionValueProperties.h in Headers */,
|
||||
260CC63215D04377002BF2E0 /* OptionValueDictionary.h in Headers */,
|
||||
262173A118395D3800C52091 /* SectionLoadHistory.h in Headers */,
|
||||
232CB61A191E00CD00EF39FC /* NativeProcessProtocol.h in Headers */,
|
||||
260CC63315D04377002BF2E0 /* OptionValueEnumeration.h in Headers */,
|
||||
AF45FDE618A1F3AC0007051C /* AppleGetThreadItemInfoHandler.h in Headers */,
|
||||
260A63171861008E00FECF8E /* IOHandler.h in Headers */,
|
||||
|
@ -4147,15 +4202,18 @@
|
|||
260CC63A15D04377002BF2E0 /* OptionValueUUID.h in Headers */,
|
||||
260A248E15D06C50009981B0 /* OptionValues.h in Headers */,
|
||||
AF061F88182C97ED00B6A19C /* RegisterContextHistory.h in Headers */,
|
||||
239F5B2F19296DC500083917 /* NativeRegisterContextLinux_x86_64.h in Headers */,
|
||||
26DAED6015D327A200E15819 /* OptionValuePathMappings.h in Headers */,
|
||||
26ACEC2815E077AE00E94760 /* Property.h in Headers */,
|
||||
26491E3B15E1DB8600CBFFC2 /* OptionValueRegex.h in Headers */,
|
||||
2697A39515E404BA003E682C /* OptionValueArch.h in Headers */,
|
||||
AF23B4DC19009C66003E2A58 /* FreeBSDSignals.h in Headers */,
|
||||
26474CBF18D0CB2D0073DEBA /* RegisterContextMach_i386.h in Headers */,
|
||||
26474CC118D0CB2D0073DEBA /* RegisterContextMach_x86_64.h in Headers */,
|
||||
2698699D15E6CBD0002415FF /* OperatingSystemPython.h in Headers */,
|
||||
232CB618191E00CD00EF39FC /* NativeBreakpointList.h in Headers */,
|
||||
260D9B2715EC369500960137 /* ModuleSpec.h in Headers */,
|
||||
232CB61C191E00CD00EF39FC /* NativeThreadProtocol.h in Headers */,
|
||||
232CB616191E00CD00EF39FC /* NativeBreakpoint.h in Headers */,
|
||||
947A1D651616476B0017C8D1 /* CommandObjectPlugin.h in Headers */,
|
||||
262ED0051631FA2800879631 /* OptionGroupString.h in Headers */,
|
||||
26474CA918D0CB070073DEBA /* RegisterContextFreeBSD_i386.h in Headers */,
|
||||
|
@ -4606,6 +4664,7 @@
|
|||
2689001813353DDE00698AC0 /* CommandObjectExpression.cpp in Sources */,
|
||||
2689001A13353DDE00698AC0 /* CommandObjectFrame.cpp in Sources */,
|
||||
2689001B13353DDE00698AC0 /* CommandObjectHelp.cpp in Sources */,
|
||||
23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */,
|
||||
2689001D13353DDE00698AC0 /* CommandObjectLog.cpp in Sources */,
|
||||
262173A318395D4600C52091 /* SectionLoadHistory.cpp in Sources */,
|
||||
2689001E13353DDE00698AC0 /* CommandObjectMemory.cpp in Sources */,
|
||||
|
@ -4652,6 +4711,7 @@
|
|||
2689004313353E0400698AC0 /* Mangled.cpp in Sources */,
|
||||
2689004413353E0400698AC0 /* Module.cpp in Sources */,
|
||||
2689004513353E0400698AC0 /* ModuleChild.cpp in Sources */,
|
||||
23EDE33319269E7C00F6A132 /* NativeRegisterContext.cpp in Sources */,
|
||||
2689004613353E0400698AC0 /* ModuleList.cpp in Sources */,
|
||||
2689004713353E0400698AC0 /* PluginManager.cpp in Sources */,
|
||||
AF0C112818580CD800C4C45B /* QueueItem.cpp in Sources */,
|
||||
|
@ -4672,6 +4732,7 @@
|
|||
2689005313353E0400698AC0 /* UserID.cpp in Sources */,
|
||||
2689005413353E0400698AC0 /* UserSettingsController.cpp in Sources */,
|
||||
2689005513353E0400698AC0 /* UUID.cpp in Sources */,
|
||||
23059A0719532B96007B8189 /* LinuxSignals.cpp in Sources */,
|
||||
2689005613353E0400698AC0 /* Value.cpp in Sources */,
|
||||
2689005713353E0400698AC0 /* ValueObject.cpp in Sources */,
|
||||
2689005813353E0400698AC0 /* ValueObjectChild.cpp in Sources */,
|
||||
|
@ -4829,13 +4890,17 @@
|
|||
268900F913353E6F00698AC0 /* Thread.cpp in Sources */,
|
||||
268900FA13353E6F00698AC0 /* ThreadList.cpp in Sources */,
|
||||
268900FB13353E6F00698AC0 /* ThreadPlan.cpp in Sources */,
|
||||
232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */,
|
||||
268900FC13353E6F00698AC0 /* ThreadPlanBase.cpp in Sources */,
|
||||
268900FD13353E6F00698AC0 /* ThreadPlanCallFunction.cpp in Sources */,
|
||||
268900FE13353E6F00698AC0 /* ThreadPlanCallUserExpression.cpp in Sources */,
|
||||
268900FF13353E6F00698AC0 /* ThreadPlanShouldStopHere.cpp in Sources */,
|
||||
2689010013353E6F00698AC0 /* ThreadPlanStepInstruction.cpp in Sources */,
|
||||
232CB61B191E00CD00EF39FC /* NativeThreadProtocol.cpp in Sources */,
|
||||
2689010113353E6F00698AC0 /* ThreadPlanStepOut.cpp in Sources */,
|
||||
2689010213353E6F00698AC0 /* ThreadPlanStepOverBreakpoint.cpp in Sources */,
|
||||
232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */,
|
||||
232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */,
|
||||
2689010313353E6F00698AC0 /* ThreadPlanStepRange.cpp in Sources */,
|
||||
2689010413353E6F00698AC0 /* ThreadPlanStepInRange.cpp in Sources */,
|
||||
2689010513353E6F00698AC0 /* ThreadPlanStepOverRange.cpp in Sources */,
|
||||
|
@ -4894,6 +4959,7 @@
|
|||
26DB3E191379E7AD0080DC73 /* ABIMacOSX_arm64.cpp in Sources */,
|
||||
26DB3E1C1379E7AD0080DC73 /* ABIMacOSX_i386.cpp in Sources */,
|
||||
26DB3E1F1379E7AD0080DC73 /* ABISysV_x86_64.cpp in Sources */,
|
||||
232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */,
|
||||
26D1803E16CEBFD300EDFB5B /* KQueue.cpp in Sources */,
|
||||
26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */,
|
||||
2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */,
|
||||
|
|
|
@ -1003,6 +1003,7 @@ ModuleList::GetSharedModule
|
|||
file_spec.GetPath(path, sizeof(path));
|
||||
if (path[0] == '\0')
|
||||
module_file_spec.GetPath(path, sizeof(path));
|
||||
// How can this check ever be true? This branch it is false, and we haven't modified file_spec.
|
||||
if (file_spec.Exists())
|
||||
{
|
||||
std::string uuid_str;
|
||||
|
|
|
@ -249,6 +249,7 @@ IRMemoryMap::Allocation::Allocation (lldb::addr_t process_alloc,
|
|||
lldb::addr_t
|
||||
IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, AllocationPolicy policy, Error &error)
|
||||
{
|
||||
lldb_private::Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS));
|
||||
error.Clear();
|
||||
|
||||
lldb::ProcessSP process_sp;
|
||||
|
@ -280,6 +281,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
|
|||
break;
|
||||
case eAllocationPolicyMirror:
|
||||
process_sp = m_process_wp.lock();
|
||||
if (log)
|
||||
log->Printf ("IRMemoryMap::%s process_sp=0x%" PRIx64 ", process_sp->CanJIT()=%s, process_sp->IsAlive()=%s", __FUNCTION__, (lldb::addr_t) process_sp.get (), process_sp && process_sp->CanJIT () ? "true" : "false", process_sp && process_sp->IsAlive () ? "true" : "false");
|
||||
if (process_sp && process_sp->CanJIT() && process_sp->IsAlive())
|
||||
{
|
||||
allocation_address = process_sp->AllocateMemory(allocation_size, permissions, error);
|
||||
|
@ -288,6 +291,8 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
|
|||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("IRMemoryMap::%s switching to eAllocationPolicyHostOnly due to failed condition (see previous expr log message)", __FUNCTION__);
|
||||
policy = eAllocationPolicyHostOnly;
|
||||
allocation_address = FindSpace(allocation_size);
|
||||
if (allocation_address == LLDB_INVALID_ADDRESS)
|
||||
|
@ -335,7 +340,7 @@ IRMemoryMap::Malloc (size_t size, uint8_t alignment, uint32_t permissions, Alloc
|
|||
alignment,
|
||||
policy);
|
||||
|
||||
if (lldb_private::Log *log = lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_EXPRESSIONS))
|
||||
if (log)
|
||||
{
|
||||
const char * policy_string;
|
||||
|
||||
|
|
|
@ -8,9 +8,14 @@ add_lldb_library(lldbHostCommon
|
|||
FileSpec.cpp
|
||||
Host.cpp
|
||||
Mutex.cpp
|
||||
NativeBreakpoint.cpp
|
||||
NativeBreakpointList.cpp
|
||||
NativeProcessProtocol.cpp
|
||||
NativeThreadProtocol.cpp
|
||||
OptionParser.cpp
|
||||
ProcessRunLock.cpp
|
||||
SocketAddress.cpp
|
||||
SoftwareBreakpoint.cpp
|
||||
Symbols.cpp
|
||||
Terminal.cpp
|
||||
TimeValue.cpp
|
||||
|
|
|
@ -0,0 +1,116 @@
|
|||
//===-- NativeBreakpoint.cpp ------------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "NativeBreakpoint.h"
|
||||
|
||||
#include "lldb/lldb-defines.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
NativeBreakpoint::NativeBreakpoint (lldb::addr_t addr) :
|
||||
m_addr (addr),
|
||||
m_ref_count (1),
|
||||
m_enabled (true)
|
||||
{
|
||||
assert (addr != LLDB_INVALID_ADDRESS && "breakpoint set for invalid address");
|
||||
}
|
||||
|
||||
NativeBreakpoint::~NativeBreakpoint ()
|
||||
{
|
||||
}
|
||||
|
||||
void
|
||||
NativeBreakpoint::AddRef ()
|
||||
{
|
||||
++m_ref_count;
|
||||
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " bumped up, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count);
|
||||
}
|
||||
|
||||
int32_t
|
||||
NativeBreakpoint::DecRef ()
|
||||
{
|
||||
--m_ref_count;
|
||||
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " ref count decremented, new ref count %" PRIu32, __FUNCTION__, m_addr, m_ref_count);
|
||||
|
||||
return m_ref_count;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeBreakpoint::Enable ()
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
|
||||
if (m_enabled)
|
||||
{
|
||||
// We're already enabled. Just log and exit.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already enabled, ignoring.", __FUNCTION__, m_addr);
|
||||
return Error ();
|
||||
}
|
||||
|
||||
// Log and enable.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", __FUNCTION__, m_addr);
|
||||
|
||||
Error error = DoEnable ();
|
||||
if (error.Success ())
|
||||
{
|
||||
m_enabled = true;
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable SUCCESS.", __FUNCTION__, m_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " enable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ());
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeBreakpoint::Disable ()
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
|
||||
if (!m_enabled)
|
||||
{
|
||||
// We're already disabled. Just log and exit.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " already disabled, ignoring.", __FUNCTION__, m_addr);
|
||||
return Error ();
|
||||
}
|
||||
|
||||
// Log and disable.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", __FUNCTION__, m_addr);
|
||||
|
||||
Error error = DoDisable ();
|
||||
if (error.Success ())
|
||||
{
|
||||
m_enabled = false;
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable SUCCESS.", __FUNCTION__, m_addr);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpoint::%s addr = 0x%" PRIx64 " disable FAIL: %s", __FUNCTION__, m_addr, error.AsCString ());
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
//===-- NativeBreakpoint.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_NativeBreakpoint_h_
|
||||
#define liblldb_NativeBreakpoint_h_
|
||||
|
||||
#include "lldb/lldb-types.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class NativeBreakpointList;
|
||||
|
||||
class NativeBreakpoint
|
||||
{
|
||||
friend class NativeBreakpointList;
|
||||
|
||||
public:
|
||||
// The assumption is that derived breakpoints are enabled when created.
|
||||
NativeBreakpoint (lldb::addr_t addr);
|
||||
|
||||
virtual
|
||||
~NativeBreakpoint ();
|
||||
|
||||
Error
|
||||
Enable ();
|
||||
|
||||
Error
|
||||
Disable ();
|
||||
|
||||
lldb::addr_t
|
||||
GetAddress () const { return m_addr; }
|
||||
|
||||
bool
|
||||
IsEnabled () const { return m_enabled; }
|
||||
|
||||
virtual bool
|
||||
IsSoftwareBreakpoint () const = 0;
|
||||
|
||||
protected:
|
||||
const lldb::addr_t m_addr;
|
||||
int32_t m_ref_count;
|
||||
|
||||
virtual Error
|
||||
DoEnable () = 0;
|
||||
|
||||
virtual Error
|
||||
DoDisable () = 0;
|
||||
|
||||
private:
|
||||
bool m_enabled;
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// interface for NativeBreakpointList
|
||||
// -----------------------------------------------------------
|
||||
void AddRef ();
|
||||
int32_t DecRef ();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef liblldb_NativeBreakpoint_h_
|
|
@ -0,0 +1,199 @@
|
|||
//===-- NativeBreakpointList.h ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "NativeBreakpointList.h"
|
||||
|
||||
#include "lldb/Core/Log.h"
|
||||
|
||||
#include "NativeBreakpoint.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
NativeBreakpointList::NativeBreakpointList () :
|
||||
m_mutex (Mutex::eMutexTypeRecursive)
|
||||
{
|
||||
}
|
||||
|
||||
Error
|
||||
NativeBreakpointList::AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func)
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
|
||||
|
||||
Mutex::Locker locker (m_mutex);
|
||||
|
||||
// Check if the breakpoint is already set.
|
||||
auto iter = m_breakpoints.find (addr);
|
||||
if (iter != m_breakpoints.end ())
|
||||
{
|
||||
// Yes - bump up ref count.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already enabled, upping ref count", __FUNCTION__, addr);
|
||||
|
||||
iter->second->AddRef ();
|
||||
return Error ();
|
||||
}
|
||||
|
||||
// Create a new breakpoint using the given create func.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false");
|
||||
|
||||
NativeBreakpointSP breakpoint_sp;
|
||||
Error error = create_func (addr, size_hint, hardware, breakpoint_sp);
|
||||
if (error.Fail ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 ", size_hint = %lu, hardware = %s -- FAILED: %s", __FUNCTION__, addr, size_hint, hardware ? "true" : "false", error.AsCString ());
|
||||
return error;
|
||||
}
|
||||
|
||||
// Remember the breakpoint.
|
||||
assert (breakpoint_sp && "NativeBreakpoint create function succeeded but returned NULL breakpoint");
|
||||
m_breakpoints.insert (BreakpointMap::value_type (addr, breakpoint_sp));
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeBreakpointList::DecRef (lldb::addr_t addr)
|
||||
{
|
||||
Error error;
|
||||
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
|
||||
|
||||
Mutex::Locker locker (m_mutex);
|
||||
|
||||
// Check if the breakpoint is already set.
|
||||
auto iter = m_breakpoints.find (addr);
|
||||
if (iter == m_breakpoints.end ())
|
||||
{
|
||||
// Not found!
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr);
|
||||
error.SetErrorString ("breakpoint not found");
|
||||
return error;
|
||||
}
|
||||
|
||||
// Decrement ref count.
|
||||
const int32_t new_ref_count = iter->second->DecRef ();
|
||||
assert (new_ref_count >= 0 && "NativeBreakpoint ref count went negative");
|
||||
|
||||
if (new_ref_count > 0)
|
||||
{
|
||||
// Still references to this breakpoint. Leave it alone.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- new breakpoint ref count %" PRIu32, __FUNCTION__, addr, new_ref_count);
|
||||
return error;
|
||||
}
|
||||
|
||||
// Breakpoint has no more references. Disable it if it's not
|
||||
// already disabled.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removing due to no remaining references", __FUNCTION__, addr);
|
||||
|
||||
// If it's enabled, we need to disable it.
|
||||
if (iter->second->IsEnabled ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- currently enabled, now disabling", __FUNCTION__, addr);
|
||||
error = iter->second->Disable ();
|
||||
if (error.Fail ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removal FAILED: %s", __FUNCTION__, addr, error.AsCString ());
|
||||
// Continue since we still want to take it out of the breakpoint list.
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- already disabled, nothing to do", __FUNCTION__, addr);
|
||||
}
|
||||
|
||||
// Take the breakpoint out of the list.
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- removed from breakpoint map", __FUNCTION__, addr);
|
||||
|
||||
m_breakpoints.erase (iter);
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeBreakpointList::EnableBreakpoint (lldb::addr_t addr)
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
|
||||
|
||||
Mutex::Locker locker (m_mutex);
|
||||
|
||||
// Ensure we have said breakpoint.
|
||||
auto iter = m_breakpoints.find (addr);
|
||||
if (iter == m_breakpoints.end ())
|
||||
{
|
||||
// Not found!
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr);
|
||||
return Error ("breakpoint not found");
|
||||
}
|
||||
|
||||
// Enable it.
|
||||
return iter->second->Enable ();
|
||||
}
|
||||
|
||||
Error
|
||||
NativeBreakpointList::DisableBreakpoint (lldb::addr_t addr)
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
|
||||
|
||||
Mutex::Locker locker (m_mutex);
|
||||
|
||||
// Ensure we have said breakpoint.
|
||||
auto iter = m_breakpoints.find (addr);
|
||||
if (iter == m_breakpoints.end ())
|
||||
{
|
||||
// Not found!
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64 " -- NOT FOUND", __FUNCTION__, addr);
|
||||
return Error ("breakpoint not found");
|
||||
}
|
||||
|
||||
// Disable it.
|
||||
return iter->second->Disable ();
|
||||
}
|
||||
|
||||
Error
|
||||
NativeBreakpointList::GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp)
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
|
||||
|
||||
Mutex::Locker locker (m_mutex);
|
||||
|
||||
// Ensure we have said breakpoint.
|
||||
auto iter = m_breakpoints.find (addr);
|
||||
if (iter == m_breakpoints.end ())
|
||||
{
|
||||
// Not found!
|
||||
breakpoint_sp.reset ();
|
||||
return Error ("breakpoint not found");
|
||||
}
|
||||
|
||||
// Disable it.
|
||||
breakpoint_sp = iter->second;
|
||||
return Error ();
|
||||
}
|
||||
|
|
@ -0,0 +1,53 @@
|
|||
//===-- NativeBreakpointList.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_NativeBreakpointList_h_
|
||||
#define liblldb_NativeBreakpointList_h_
|
||||
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
// #include "lldb/Host/NativeBreakpoint.h"
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class NativeBreakpointList
|
||||
{
|
||||
public:
|
||||
typedef std::function<Error (lldb::addr_t addr, size_t size_hint, bool hardware, NativeBreakpointSP &breakpoint_sp)> CreateBreakpointFunc;
|
||||
|
||||
NativeBreakpointList ();
|
||||
|
||||
Error
|
||||
AddRef (lldb::addr_t addr, size_t size_hint, bool hardware, CreateBreakpointFunc create_func);
|
||||
|
||||
Error
|
||||
DecRef (lldb::addr_t addr);
|
||||
|
||||
Error
|
||||
EnableBreakpoint (lldb::addr_t addr);
|
||||
|
||||
Error
|
||||
DisableBreakpoint (lldb::addr_t addr);
|
||||
|
||||
Error
|
||||
GetBreakpoint (lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp);
|
||||
|
||||
private:
|
||||
typedef std::map<lldb::addr_t, NativeBreakpointSP> BreakpointMap;
|
||||
|
||||
Mutex m_mutex;
|
||||
BreakpointMap m_breakpoints;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // ifndef liblldb_NativeBreakpointList_h_
|
|
@ -0,0 +1,397 @@
|
|||
//===-- NativeProcessProtocol.cpp -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "NativeProcessProtocol.h"
|
||||
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Target/NativeRegisterContext.h"
|
||||
|
||||
#include "NativeThreadProtocol.h"
|
||||
#include "SoftwareBreakpoint.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
// -----------------------------------------------------------------------------
|
||||
// NativeProcessProtocol Members
|
||||
// -----------------------------------------------------------------------------
|
||||
|
||||
NativeProcessProtocol::NativeProcessProtocol (lldb::pid_t pid) :
|
||||
m_pid (pid),
|
||||
m_threads (),
|
||||
m_current_thread_id (LLDB_INVALID_THREAD_ID),
|
||||
m_threads_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_state (lldb::eStateInvalid),
|
||||
m_state_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_exit_type (eExitTypeInvalid),
|
||||
m_exit_status (0),
|
||||
m_exit_description (),
|
||||
m_delegates_mutex (Mutex::eMutexTypeRecursive),
|
||||
m_delegates (),
|
||||
m_breakpoint_list (),
|
||||
m_terminal_fd (-1),
|
||||
m_stop_id (0)
|
||||
{
|
||||
}
|
||||
|
||||
lldb_private::Error
|
||||
NativeProcessProtocol::GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info)
|
||||
{
|
||||
// Default: not implemented.
|
||||
return Error ("not implemented");
|
||||
}
|
||||
|
||||
bool
|
||||
NativeProcessProtocol::GetExitStatus (ExitType *exit_type, int *status, std::string &exit_description)
|
||||
{
|
||||
if (m_state == lldb::eStateExited)
|
||||
{
|
||||
*exit_type = m_exit_type;
|
||||
*status = m_exit_status;
|
||||
exit_description = m_exit_description;
|
||||
return true;
|
||||
}
|
||||
|
||||
*status = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeProcessProtocol::SetExitStatus (ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange)
|
||||
{
|
||||
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
|
||||
if (log)
|
||||
log->Printf ("NativeProcessProtocol::%s(%d, %d, %s, %s) called",
|
||||
__FUNCTION__,
|
||||
exit_type,
|
||||
status,
|
||||
exit_description ? exit_description : "nullptr",
|
||||
bNotifyStateChange ? "true" : "false");
|
||||
|
||||
// Exit status already set
|
||||
if (m_state == lldb::eStateExited)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeProcessProtocol::%s exit status already set to %d, ignoring new set to %d", __FUNCTION__, m_exit_status, status);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_state = lldb::eStateExited;
|
||||
|
||||
m_exit_type = exit_type;
|
||||
m_exit_status = status;
|
||||
if (exit_description && exit_description[0])
|
||||
m_exit_description = exit_description;
|
||||
else
|
||||
m_exit_description.clear();
|
||||
|
||||
if (bNotifyStateChange)
|
||||
SynchronouslyNotifyProcessStateChanged (lldb::eStateExited);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
NativeThreadProtocolSP
|
||||
NativeProcessProtocol::GetThreadAtIndex (uint32_t idx)
|
||||
{
|
||||
Mutex::Locker locker (m_threads_mutex);
|
||||
if (idx < m_threads.size ())
|
||||
return m_threads[idx];
|
||||
return NativeThreadProtocolSP ();
|
||||
}
|
||||
|
||||
NativeThreadProtocolSP
|
||||
NativeProcessProtocol::GetThreadByID (lldb::tid_t tid)
|
||||
{
|
||||
Mutex::Locker locker (m_threads_mutex);
|
||||
for (auto thread_sp : m_threads)
|
||||
{
|
||||
if (thread_sp->GetID() == tid)
|
||||
return thread_sp;
|
||||
}
|
||||
return NativeThreadProtocolSP ();
|
||||
}
|
||||
|
||||
bool
|
||||
NativeProcessProtocol::IsAlive () const
|
||||
{
|
||||
return m_state != eStateDetached
|
||||
&& m_state != eStateExited
|
||||
&& m_state != eStateInvalid
|
||||
&& m_state != eStateUnloaded;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeProcessProtocol::GetByteOrder (lldb::ByteOrder &byte_order) const
|
||||
{
|
||||
ArchSpec process_arch;
|
||||
if (!GetArchitecture (process_arch))
|
||||
return false;
|
||||
byte_order = process_arch.GetByteOrder ();
|
||||
return true;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeProcessProtocol::GetMaxWatchpoints () const
|
||||
{
|
||||
// This default implementation will return the number of
|
||||
// *hardware* breakpoints available. MacOSX and other OS
|
||||
// implementations that support software breakpoints will want to
|
||||
// override this correctly for their implementation.
|
||||
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
|
||||
|
||||
// get any thread
|
||||
NativeThreadProtocolSP thread_sp (const_cast<NativeProcessProtocol*> (this)->GetThreadAtIndex (0));
|
||||
if (!thread_sp)
|
||||
{
|
||||
if (log)
|
||||
log->Warning ("NativeProcessProtocol::%s (): failed to find a thread to grab a NativeRegisterContext!", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
NativeRegisterContextSP reg_ctx_sp (thread_sp->GetRegisterContext ());
|
||||
if (!reg_ctx_sp)
|
||||
{
|
||||
if (log)
|
||||
log->Warning ("NativeProcessProtocol::%s (): failed to get a RegisterContextNativeProcess from the first thread!", __FUNCTION__);
|
||||
return 0;
|
||||
}
|
||||
|
||||
return reg_ctx_sp->NumSupportedHardwareWatchpoints ();
|
||||
}
|
||||
|
||||
Error
|
||||
NativeProcessProtocol::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
|
||||
{
|
||||
// This default implementation assumes setting the watchpoint for
|
||||
// the process will require setting the watchpoint for each of the
|
||||
// threads. Furthermore, it will track watchpoints set for the
|
||||
// process and will add them to each thread that is attached to
|
||||
// via the (FIXME implement) OnThreadAttached () method.
|
||||
|
||||
Log *log (lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
|
||||
|
||||
// FIXME save the watchpoint on the set of process watchpoint vars
|
||||
// so we can add them to a thread each time a new thread is registered.
|
||||
|
||||
// Update the thread list
|
||||
UpdateThreads ();
|
||||
|
||||
// Keep track of the threads we successfully set the watchpoint
|
||||
// for. If one of the thread watchpoint setting operations fails,
|
||||
// back off and remove the watchpoint for all the threads that
|
||||
// were successfully set so we get back to a consistent state.
|
||||
std::vector<NativeThreadProtocolSP> watchpoint_established_threads;
|
||||
|
||||
// Tell each thread to set a watchpoint. In the event that
|
||||
// hardware watchpoints are requested but the SetWatchpoint fails,
|
||||
// try to set a software watchpoint as a fallback. It's
|
||||
// conceivable that if there are more threads than hardware
|
||||
// watchpoints available, some of the threads will fail to set
|
||||
// hardware watchpoints while software ones may be available.
|
||||
Mutex::Locker locker (m_threads_mutex);
|
||||
for (auto thread_sp : m_threads)
|
||||
{
|
||||
assert (thread_sp && "thread list should not have a NULL thread!");
|
||||
if (!thread_sp)
|
||||
continue;
|
||||
|
||||
Error thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, hardware);
|
||||
if (thread_error.Fail () && hardware)
|
||||
{
|
||||
// Try software watchpoints since we failed on hardware watchpoint setting
|
||||
// and we may have just run out of hardware watchpoints.
|
||||
thread_error = thread_sp->SetWatchpoint (addr, size, watch_flags, false);
|
||||
if (thread_error.Success ())
|
||||
{
|
||||
if (log)
|
||||
log->Warning ("hardware watchpoint requested but software watchpoint set");
|
||||
}
|
||||
}
|
||||
|
||||
if (thread_error.Success ())
|
||||
{
|
||||
// Remember that we set this watchpoint successfully in
|
||||
// case we need to clear it later.
|
||||
watchpoint_established_threads.push_back (thread_sp);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Unset the watchpoint for each thread we successfully
|
||||
// set so that we get back to a consistent state of "not
|
||||
// set" for the watchpoint.
|
||||
for (auto unwatch_thread_sp : watchpoint_established_threads)
|
||||
{
|
||||
Error remove_error = unwatch_thread_sp->RemoveWatchpoint (addr);
|
||||
if (remove_error.Fail () && log)
|
||||
{
|
||||
log->Warning ("NativeProcessProtocol::%s (): RemoveWatchpoint failed for pid=%" PRIu64 ", tid=%" PRIu64 ": %s",
|
||||
__FUNCTION__, GetID (), unwatch_thread_sp->GetID (), remove_error.AsCString ());
|
||||
}
|
||||
}
|
||||
|
||||
return thread_error;
|
||||
}
|
||||
}
|
||||
return Error ();
|
||||
}
|
||||
|
||||
Error
|
||||
NativeProcessProtocol::RemoveWatchpoint (lldb::addr_t addr)
|
||||
{
|
||||
// FIXME remove the watchpoint on the set of process watchpoint vars
|
||||
// so we can add them to a thread each time a new thread is registered.
|
||||
|
||||
// Update the thread list
|
||||
UpdateThreads ();
|
||||
|
||||
Error overall_error;
|
||||
|
||||
Mutex::Locker locker (m_threads_mutex);
|
||||
for (auto thread_sp : m_threads)
|
||||
{
|
||||
assert (thread_sp && "thread list should not have a NULL thread!");
|
||||
if (!thread_sp)
|
||||
continue;
|
||||
|
||||
const Error thread_error = thread_sp->RemoveWatchpoint (addr);
|
||||
if (thread_error.Fail ())
|
||||
{
|
||||
// Keep track of the first thread error if any threads
|
||||
// fail. We want to try to remove the watchpoint from
|
||||
// every thread, though, even if one or more have errors.
|
||||
if (!overall_error.Fail ())
|
||||
overall_error = thread_error;
|
||||
}
|
||||
}
|
||||
return overall_error;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeProcessProtocol::RegisterNativeDelegate (NativeDelegate &native_delegate)
|
||||
{
|
||||
Mutex::Locker locker (m_delegates_mutex);
|
||||
if (std::find (m_delegates.begin (), m_delegates.end (), &native_delegate) != m_delegates.end ())
|
||||
return false;
|
||||
|
||||
m_delegates.push_back (&native_delegate);
|
||||
native_delegate.InitializeDelegate (this);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeProcessProtocol::UnregisterNativeDelegate (NativeDelegate &native_delegate)
|
||||
{
|
||||
Mutex::Locker locker (m_delegates_mutex);
|
||||
|
||||
const auto initial_size = m_delegates.size ();
|
||||
m_delegates.erase (remove (m_delegates.begin (), m_delegates.end (), &native_delegate), m_delegates.end ());
|
||||
|
||||
// We removed the delegate if the count of delegates shrank after
|
||||
// removing all copies of the given native_delegate from the vector.
|
||||
return m_delegates.size () < initial_size;
|
||||
}
|
||||
|
||||
void
|
||||
NativeProcessProtocol::SynchronouslyNotifyProcessStateChanged (lldb::StateType state)
|
||||
{
|
||||
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
|
||||
|
||||
Mutex::Locker locker (m_delegates_mutex);
|
||||
for (auto native_delegate: m_delegates)
|
||||
native_delegate->ProcessStateChanged (this, state);
|
||||
|
||||
if (log)
|
||||
{
|
||||
if (!m_delegates.empty ())
|
||||
{
|
||||
log->Printf ("NativeProcessProtocol::%s: sent state notification [%s] from process %" PRIu64,
|
||||
__FUNCTION__, lldb_private::StateAsCString (state), GetID ());
|
||||
}
|
||||
else
|
||||
{
|
||||
log->Printf ("NativeProcessProtocol::%s: would send state notification [%s] from process %" PRIu64 ", but no delegates",
|
||||
__FUNCTION__, lldb_private::StateAsCString (state), GetID ());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Error
|
||||
NativeProcessProtocol::SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint)
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("NativeProcessProtocol::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
|
||||
|
||||
return m_breakpoint_list.AddRef (addr, size_hint, false,
|
||||
[this] (lldb::addr_t addr, size_t size_hint, bool /* hardware */, NativeBreakpointSP &breakpoint_sp)->Error
|
||||
{ return SoftwareBreakpoint::CreateSoftwareBreakpoint (*this, addr, size_hint, breakpoint_sp); });
|
||||
}
|
||||
|
||||
Error
|
||||
NativeProcessProtocol::RemoveBreakpoint (lldb::addr_t addr)
|
||||
{
|
||||
return m_breakpoint_list.DecRef (addr);
|
||||
}
|
||||
|
||||
Error
|
||||
NativeProcessProtocol::EnableBreakpoint (lldb::addr_t addr)
|
||||
{
|
||||
return m_breakpoint_list.EnableBreakpoint (addr);
|
||||
}
|
||||
|
||||
Error
|
||||
NativeProcessProtocol::DisableBreakpoint (lldb::addr_t addr)
|
||||
{
|
||||
return m_breakpoint_list.DisableBreakpoint (addr);
|
||||
}
|
||||
|
||||
lldb::StateType
|
||||
NativeProcessProtocol::GetState () const
|
||||
{
|
||||
Mutex::Locker locker (m_state_mutex);
|
||||
return m_state;
|
||||
}
|
||||
|
||||
void
|
||||
NativeProcessProtocol::SetState (lldb::StateType state, bool notify_delegates)
|
||||
{
|
||||
Mutex::Locker locker (m_state_mutex);
|
||||
m_state = state;
|
||||
|
||||
if (StateIsStoppedState (state, false))
|
||||
{
|
||||
++m_stop_id;
|
||||
|
||||
// Give process a chance to do any stop id bump processing, such as
|
||||
// clearing cached data that is invalidated each time the process runs.
|
||||
// Note if/when we support some threads running, we'll end up needing
|
||||
// to manage this per thread and per process.
|
||||
DoStopIDBumped (m_stop_id);
|
||||
}
|
||||
|
||||
// Optionally notify delegates of the state change.
|
||||
if (notify_delegates)
|
||||
SynchronouslyNotifyProcessStateChanged (state);
|
||||
}
|
||||
|
||||
uint32_t NativeProcessProtocol::GetStopID () const
|
||||
{
|
||||
Mutex::Locker locker (m_state_mutex);
|
||||
return m_stop_id;
|
||||
}
|
||||
|
||||
void
|
||||
NativeProcessProtocol::DoStopIDBumped (uint32_t /* newBumpId */)
|
||||
{
|
||||
// Default implementation does nothing.
|
||||
}
|
|
@ -0,0 +1,321 @@
|
|||
//===-- NativeProcessProtocol.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_NativeProcessProtocol_h_
|
||||
#define liblldb_NativeProcessProtocol_h_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "lldb/lldb-types.h"
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
|
||||
#include "NativeBreakpointList.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class MemoryRegionInfo;
|
||||
class ResumeActionList;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NativeProcessProtocol
|
||||
//------------------------------------------------------------------
|
||||
class NativeProcessProtocol :
|
||||
public std::enable_shared_from_this<NativeProcessProtocol>
|
||||
{
|
||||
friend class SoftwareBreakpoint;
|
||||
|
||||
public:
|
||||
static NativeProcessProtocol *
|
||||
CreateInstance (lldb::pid_t pid);
|
||||
|
||||
// lldb_private::Host calls should be used to launch a process for debugging, and
|
||||
// then the process should be attached to. When attaching to a process
|
||||
// lldb_private::Host calls should be used to locate the process to attach to,
|
||||
// and then this function should be called.
|
||||
NativeProcessProtocol (lldb::pid_t pid);
|
||||
|
||||
public:
|
||||
virtual ~NativeProcessProtocol ()
|
||||
{
|
||||
}
|
||||
|
||||
virtual Error
|
||||
Resume (const ResumeActionList &resume_actions) = 0;
|
||||
|
||||
virtual Error
|
||||
Halt () = 0;
|
||||
|
||||
virtual Error
|
||||
Detach () = 0;
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Sends a process a UNIX signal \a signal.
|
||||
///
|
||||
/// Implementer note: the WillSignal ()/DidSignal () calls
|
||||
/// from the Process class are not replicated here since no
|
||||
/// concrete classes implemented any behavior for those and
|
||||
/// put all the work in DoSignal (...).
|
||||
///
|
||||
/// @return
|
||||
/// Returns an error object.
|
||||
//------------------------------------------------------------------
|
||||
virtual Error
|
||||
Signal (int signo) = 0;
|
||||
|
||||
virtual Error
|
||||
Kill () = 0;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Memory and memory region functions
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
virtual Error
|
||||
GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info);
|
||||
|
||||
virtual Error
|
||||
ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) = 0;
|
||||
|
||||
virtual Error
|
||||
WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) = 0;
|
||||
|
||||
virtual Error
|
||||
AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) = 0;
|
||||
|
||||
virtual Error
|
||||
DeallocateMemory (lldb::addr_t addr) = 0;
|
||||
|
||||
virtual lldb::addr_t
|
||||
GetSharedLibraryInfoAddress () = 0;
|
||||
|
||||
virtual bool
|
||||
IsAlive () const;
|
||||
|
||||
virtual size_t
|
||||
UpdateThreads () = 0;
|
||||
|
||||
virtual bool
|
||||
GetArchitecture (ArchSpec &arch) const = 0;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Breakpoint functions
|
||||
//----------------------------------------------------------------------
|
||||
virtual Error
|
||||
SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) = 0;
|
||||
|
||||
virtual Error
|
||||
RemoveBreakpoint (lldb::addr_t addr);
|
||||
|
||||
virtual Error
|
||||
EnableBreakpoint (lldb::addr_t addr);
|
||||
|
||||
virtual Error
|
||||
DisableBreakpoint (lldb::addr_t addr);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Watchpoint functions
|
||||
//----------------------------------------------------------------------
|
||||
virtual uint32_t
|
||||
GetMaxWatchpoints () const;
|
||||
|
||||
virtual Error
|
||||
SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware);
|
||||
|
||||
virtual Error
|
||||
RemoveWatchpoint (lldb::addr_t addr);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Accessors
|
||||
//----------------------------------------------------------------------
|
||||
lldb::pid_t
|
||||
GetID() const
|
||||
{
|
||||
return m_pid;
|
||||
}
|
||||
|
||||
lldb::StateType
|
||||
GetState () const;
|
||||
|
||||
bool
|
||||
IsRunning () const
|
||||
{
|
||||
return m_state == lldb::eStateRunning || IsStepping();
|
||||
}
|
||||
|
||||
bool
|
||||
IsStepping () const
|
||||
{
|
||||
return m_state == lldb::eStateStepping;
|
||||
}
|
||||
|
||||
bool
|
||||
CanResume () const
|
||||
{
|
||||
return m_state == lldb::eStateStopped;
|
||||
}
|
||||
|
||||
bool
|
||||
GetByteOrder (lldb::ByteOrder &byte_order) const;
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Exit Status
|
||||
//----------------------------------------------------------------------
|
||||
virtual bool
|
||||
GetExitStatus (lldb_private::ExitType *exit_type, int *status, std::string &exit_description);
|
||||
|
||||
virtual bool
|
||||
SetExitStatus (lldb_private::ExitType exit_type, int status, const char *exit_description, bool bNotifyStateChange);
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Access to threads
|
||||
//----------------------------------------------------------------------
|
||||
NativeThreadProtocolSP
|
||||
GetThreadAtIndex (uint32_t idx);
|
||||
|
||||
NativeThreadProtocolSP
|
||||
GetThreadByID (lldb::tid_t tid);
|
||||
|
||||
void
|
||||
SetCurrentThreadID (lldb::tid_t tid)
|
||||
{
|
||||
m_current_thread_id = tid;
|
||||
}
|
||||
|
||||
lldb::tid_t
|
||||
GetCurrentThreadID ()
|
||||
{
|
||||
return m_current_thread_id;
|
||||
}
|
||||
|
||||
NativeThreadProtocolSP
|
||||
GetCurrentThread ()
|
||||
{
|
||||
return GetThreadByID (m_current_thread_id);
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Access to inferior stdio
|
||||
//----------------------------------------------------------------------
|
||||
virtual
|
||||
int GetTerminalFileDescriptor ()
|
||||
{
|
||||
return m_terminal_fd;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Stop id interface
|
||||
//----------------------------------------------------------------------
|
||||
|
||||
uint32_t
|
||||
GetStopID () const;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Callbacks for low-level process state changes
|
||||
// ---------------------------------------------------------------------
|
||||
class NativeDelegate
|
||||
{
|
||||
public:
|
||||
virtual
|
||||
~NativeDelegate () {}
|
||||
|
||||
virtual void
|
||||
InitializeDelegate (NativeProcessProtocol *process) = 0;
|
||||
|
||||
virtual void
|
||||
ProcessStateChanged (NativeProcessProtocol *process, lldb::StateType state) = 0;
|
||||
};
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Register a native delegate.
|
||||
///
|
||||
/// Clients can register nofication callbacks by passing in a
|
||||
/// NativeDelegate impl and passing it into this function.
|
||||
///
|
||||
/// Note: it is required that the lifetime of the
|
||||
/// native_delegate outlive the NativeProcessProtocol.
|
||||
///
|
||||
/// @param[in] native_delegate
|
||||
/// A NativeDelegate impl to be called when certain events
|
||||
/// happen within the NativeProcessProtocol or related threads.
|
||||
///
|
||||
/// @return
|
||||
/// true if the delegate was registered successfully;
|
||||
/// false if the delegate was already registered.
|
||||
///
|
||||
/// @see NativeProcessProtocol::NativeDelegate.
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
RegisterNativeDelegate (NativeDelegate &native_delegate);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Unregister a native delegate previously registered.
|
||||
///
|
||||
/// @param[in] native_delegate
|
||||
/// A NativeDelegate impl previously registered with this process.
|
||||
///
|
||||
/// @return Returns \b true if the NativeDelegate was
|
||||
/// successfully removed from the process, \b false otherwise.
|
||||
///
|
||||
/// @see NativeProcessProtocol::NativeDelegate
|
||||
//------------------------------------------------------------------
|
||||
bool
|
||||
UnregisterNativeDelegate (NativeDelegate &native_delegate);
|
||||
|
||||
protected:
|
||||
lldb::pid_t m_pid;
|
||||
|
||||
std::vector<NativeThreadProtocolSP> m_threads;
|
||||
lldb::tid_t m_current_thread_id;
|
||||
mutable Mutex m_threads_mutex;
|
||||
|
||||
lldb::StateType m_state;
|
||||
mutable Mutex m_state_mutex;
|
||||
|
||||
lldb_private::ExitType m_exit_type;
|
||||
int m_exit_status;
|
||||
std::string m_exit_description;
|
||||
Mutex m_delegates_mutex;
|
||||
std::vector<NativeDelegate*> m_delegates;
|
||||
NativeBreakpointList m_breakpoint_list;
|
||||
int m_terminal_fd;
|
||||
uint32_t m_stop_id;
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Internal interface for state handling
|
||||
// -----------------------------------------------------------
|
||||
void
|
||||
SetState (lldb::StateType state, bool notify_delegates = true);
|
||||
|
||||
// Derived classes need not impelment this. It can be used as a
|
||||
// hook to clear internal caches that should be invalidated when
|
||||
// stop ids change.
|
||||
//
|
||||
// Note this function is called with the state mutex obtained
|
||||
// by the caller.
|
||||
virtual void
|
||||
DoStopIDBumped (uint32_t newBumpId);
|
||||
|
||||
// -----------------------------------------------------------
|
||||
// Internal interface for software breakpoints
|
||||
// -----------------------------------------------------------
|
||||
Error
|
||||
SetSoftwareBreakpoint (lldb::addr_t addr, uint32_t size_hint);
|
||||
|
||||
virtual Error
|
||||
GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) = 0;
|
||||
|
||||
private:
|
||||
|
||||
void
|
||||
SynchronouslyNotifyProcessStateChanged (lldb::StateType state);
|
||||
};
|
||||
}
|
||||
|
||||
#endif // #ifndef liblldb_NativeProcessProtocol_h_
|
|
@ -0,0 +1,97 @@
|
|||
//===-- NativeThreadProtocol.cpp --------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "NativeThreadProtocol.h"
|
||||
|
||||
#include "NativeProcessProtocol.h"
|
||||
#include "lldb/Target/NativeRegisterContext.h"
|
||||
#include "SoftwareBreakpoint.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
NativeThreadProtocol::NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) :
|
||||
m_process_wp (process->shared_from_this ()),
|
||||
m_tid (tid)
|
||||
{
|
||||
}
|
||||
|
||||
Error
|
||||
NativeThreadProtocol::ReadRegister (uint32_t reg, RegisterValue ®_value)
|
||||
{
|
||||
NativeRegisterContextSP register_context_sp = GetRegisterContext ();
|
||||
if (!register_context_sp)
|
||||
return Error ("no register context");
|
||||
|
||||
const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg);
|
||||
if (!reg_info)
|
||||
return Error ("no register info for reg num %" PRIu32, reg);
|
||||
|
||||
return register_context_sp->ReadRegister (reg_info, reg_value);;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeThreadProtocol::WriteRegister (uint32_t reg, const RegisterValue ®_value)
|
||||
{
|
||||
NativeRegisterContextSP register_context_sp = GetRegisterContext ();
|
||||
if (!register_context_sp)
|
||||
return Error ("no register context");
|
||||
|
||||
const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg);
|
||||
if (!reg_info)
|
||||
return Error ("no register info for reg num %" PRIu32, reg);
|
||||
|
||||
return register_context_sp->WriteRegister (reg_info, reg_value);
|
||||
}
|
||||
|
||||
Error
|
||||
NativeThreadProtocol::SaveAllRegisters (lldb::DataBufferSP &data_sp)
|
||||
{
|
||||
NativeRegisterContextSP register_context_sp = GetRegisterContext ();
|
||||
if (!register_context_sp)
|
||||
return Error ("no register context");
|
||||
return register_context_sp->WriteAllRegisterValues (data_sp);
|
||||
}
|
||||
|
||||
Error
|
||||
NativeThreadProtocol::RestoreAllRegisters (lldb::DataBufferSP &data_sp)
|
||||
{
|
||||
NativeRegisterContextSP register_context_sp = GetRegisterContext ();
|
||||
if (!register_context_sp)
|
||||
return Error ("no register context");
|
||||
return register_context_sp->ReadAllRegisterValues (data_sp);
|
||||
}
|
||||
|
||||
NativeProcessProtocolSP
|
||||
NativeThreadProtocol::GetProcess ()
|
||||
{
|
||||
return m_process_wp.lock ();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeThreadProtocol::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const
|
||||
{
|
||||
// Default: no translation. Do the real translation where there
|
||||
// is access to the host signal numbers.
|
||||
switch (stop_info.reason)
|
||||
{
|
||||
case eStopReasonSignal:
|
||||
return stop_info.details.signal.signo;
|
||||
break;
|
||||
|
||||
case eStopReasonException:
|
||||
// FIXME verify the way to specify pass-thru here.
|
||||
return static_cast<uint32_t> (stop_info.details.exception.type);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert (0 && "unexpected stop_info.reason found");
|
||||
return 0;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
//===-- NativeThreadProtocol.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_NativeThreadProtocol_h_
|
||||
#define liblldb_NativeThreadProtocol_h_
|
||||
|
||||
#include <memory>
|
||||
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "lldb/lldb-types.h"
|
||||
#include "lldb/Host/Debug.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
//------------------------------------------------------------------
|
||||
// NativeThreadProtocol
|
||||
//------------------------------------------------------------------
|
||||
class NativeThreadProtocol:
|
||||
public std::enable_shared_from_this<NativeThreadProtocol>
|
||||
{
|
||||
public:
|
||||
NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid);
|
||||
|
||||
virtual ~NativeThreadProtocol()
|
||||
{
|
||||
}
|
||||
|
||||
virtual const char *
|
||||
GetName() = 0;
|
||||
|
||||
virtual lldb::StateType
|
||||
GetState () = 0;
|
||||
|
||||
virtual NativeRegisterContextSP
|
||||
GetRegisterContext () = 0;
|
||||
|
||||
virtual Error
|
||||
ReadRegister (uint32_t reg, RegisterValue ®_value);
|
||||
|
||||
virtual Error
|
||||
WriteRegister (uint32_t reg, const RegisterValue ®_value);
|
||||
|
||||
virtual Error
|
||||
SaveAllRegisters (lldb::DataBufferSP &data_sp);
|
||||
|
||||
virtual Error
|
||||
RestoreAllRegisters (lldb::DataBufferSP &data_sp);
|
||||
|
||||
virtual bool
|
||||
GetStopReason (ThreadStopInfo &stop_info) = 0;
|
||||
|
||||
virtual uint32_t
|
||||
TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const;
|
||||
|
||||
lldb::tid_t
|
||||
GetID() const
|
||||
{
|
||||
return m_tid;
|
||||
}
|
||||
|
||||
NativeProcessProtocolSP
|
||||
GetProcess ();
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Thread-specific watchpoints
|
||||
// ---------------------------------------------------------------------
|
||||
virtual Error
|
||||
SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0;
|
||||
|
||||
virtual Error
|
||||
RemoveWatchpoint (lldb::addr_t addr) = 0;
|
||||
|
||||
protected:
|
||||
NativeProcessProtocolWP m_process_wp;
|
||||
lldb::tid_t m_tid;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // #ifndef liblldb_NativeThreadProtocol_h_
|
|
@ -0,0 +1,296 @@
|
|||
//===-- SoftwareBreakpoint.cpp ----------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "SoftwareBreakpoint.h"
|
||||
|
||||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Host/Debug.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
|
||||
#include "NativeProcessProtocol.h"
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// static members
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
Error
|
||||
SoftwareBreakpoint::CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_sp)
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
|
||||
|
||||
// Validate the address.
|
||||
if (addr == LLDB_INVALID_ADDRESS)
|
||||
return Error ("SoftwareBreakpoint::%s invalid load address specified.", __FUNCTION__);
|
||||
|
||||
// Ask the NativeProcessProtocol subclass to fill in the correct software breakpoint
|
||||
// trap for the breakpoint site.
|
||||
size_t bp_opcode_size = 0;
|
||||
const uint8_t *bp_opcode_bytes = NULL;
|
||||
Error error = process.GetSoftwareBreakpointTrapOpcode (size_hint, bp_opcode_size, bp_opcode_bytes);
|
||||
|
||||
if (error.Fail ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to retrieve software breakpoint trap opcode: %s", __FUNCTION__, error.AsCString ());
|
||||
return error;
|
||||
}
|
||||
|
||||
// Validate size of trap opcode.
|
||||
if (bp_opcode_size == 0)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to retrieve any trap opcodes", __FUNCTION__);
|
||||
return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned zero, unable to get breakpoint trap for address 0x%" PRIx64, addr);
|
||||
}
|
||||
|
||||
if (bp_opcode_size > MAX_TRAP_OPCODE_SIZE)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s cannot support %lu trapcode bytes, max size is %lu", __FUNCTION__, bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
|
||||
return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned too many trap opcode bytes: requires %lu but we only support a max of %lu", bp_opcode_size, MAX_TRAP_OPCODE_SIZE);
|
||||
}
|
||||
|
||||
// Validate that we received opcodes.
|
||||
if (!bp_opcode_bytes)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to retrieve trap opcode bytes", __FUNCTION__);
|
||||
return Error ("SoftwareBreakpoint::GetSoftwareBreakpointTrapOpcode() returned NULL trap opcode bytes, unable to get breakpoint trap for address 0x%" PRIx64, addr);
|
||||
}
|
||||
|
||||
// Enable the breakpoint.
|
||||
uint8_t saved_opcode_bytes [MAX_TRAP_OPCODE_SIZE];
|
||||
error = EnableSoftwareBreakpoint (process, addr, bp_opcode_size, bp_opcode_bytes, saved_opcode_bytes);
|
||||
if (error.Fail ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s: failed to enable new breakpoint at 0x%" PRIx64 ": %s", __FUNCTION__, addr, error.AsCString ());
|
||||
return error;
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr);
|
||||
|
||||
// Set the breakpoint and verified it was written properly. Now
|
||||
// create a breakpoint remover that understands how to undo this
|
||||
// breakpoint.
|
||||
breakpoint_sp.reset (new SoftwareBreakpoint (process, addr, saved_opcode_bytes, bp_opcode_bytes, bp_opcode_size));
|
||||
return Error ();
|
||||
}
|
||||
|
||||
Error
|
||||
SoftwareBreakpoint::EnableSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes)
|
||||
{
|
||||
assert (bp_opcode_size <= MAX_TRAP_OPCODE_SIZE && "bp_opcode_size out of valid range");
|
||||
assert (bp_opcode_bytes && "bp_opcode_bytes is NULL");
|
||||
assert (saved_opcode_bytes && "saved_opcode_bytes is NULL");
|
||||
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, addr);
|
||||
|
||||
// Save the original opcodes by reading them so we can restore later.
|
||||
lldb::addr_t bytes_read = 0;
|
||||
|
||||
Error error = process.ReadMemory(addr, saved_opcode_bytes, static_cast<lldb::addr_t> (bp_opcode_size), bytes_read);
|
||||
if (error.Fail ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ());
|
||||
return error;
|
||||
}
|
||||
|
||||
// Ensure we read as many bytes as we expected.
|
||||
if (bytes_read != static_cast<lldb::addr_t> (bp_opcode_size))
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, bytes_read);
|
||||
return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to set breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, bytes_read);
|
||||
}
|
||||
|
||||
// Write a software breakpoint in place of the original opcode.
|
||||
lldb::addr_t bytes_written = 0;
|
||||
error = process.WriteMemory (addr, bp_opcode_bytes, static_cast<lldb::addr_t> (bp_opcode_size), bytes_written);
|
||||
if (error.Fail ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to write memory while attempting to set breakpoint: %s", __FUNCTION__, error.AsCString ());
|
||||
return error;
|
||||
}
|
||||
|
||||
// Ensure we wrote as many bytes as we expected.
|
||||
if (bytes_written != static_cast<lldb::addr_t> (bp_opcode_size))
|
||||
{
|
||||
error.SetErrorStringWithFormat("SoftwareBreakpoint::%s failed write memory while attempting to set breakpoint: attempted to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, bp_opcode_size, bytes_written);
|
||||
if (log)
|
||||
log->PutCString (error.AsCString ());
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t verify_bp_opcode_bytes [MAX_TRAP_OPCODE_SIZE];
|
||||
lldb::addr_t verify_bytes_read = 0;
|
||||
error = process.ReadMemory(addr, verify_bp_opcode_bytes, static_cast<lldb::addr_t> (bp_opcode_size), verify_bytes_read);
|
||||
if (error.Fail ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify the breakpoint set: %s", __FUNCTION__, error.AsCString ());
|
||||
return error;
|
||||
}
|
||||
|
||||
// Ensure we read as many verification bytes as we expected.
|
||||
if (verify_bytes_read != static_cast<lldb::addr_t> (bp_opcode_size))
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, verify_bytes_read);
|
||||
return Error ("SoftwareBreakpoint::%s failed to read memory while attempting to verify breakpoint: attempted to read %lu bytes but only read %" PRIu64, __FUNCTION__, bp_opcode_size, verify_bytes_read);
|
||||
}
|
||||
|
||||
if (::memcmp(bp_opcode_bytes, verify_bp_opcode_bytes, bp_opcode_size) != 0)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr);
|
||||
return Error ("SoftwareBreakpoint::%s: verification of software breakpoint writing failed - trap opcodes not successfully read back after writing when setting breakpoint at 0x%" PRIx64, __FUNCTION__, addr);
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, addr);
|
||||
|
||||
return Error ();
|
||||
}
|
||||
|
||||
// -------------------------------------------------------------------
|
||||
// instance-level members
|
||||
// -------------------------------------------------------------------
|
||||
|
||||
SoftwareBreakpoint::SoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, const uint8_t *saved_opcodes, const uint8_t *trap_opcodes, size_t opcode_size) :
|
||||
NativeBreakpoint (addr),
|
||||
m_process (process),
|
||||
m_saved_opcodes (),
|
||||
m_trap_opcodes (),
|
||||
m_opcode_size (opcode_size)
|
||||
{
|
||||
assert ( opcode_size > 0 && "setting software breakpoint with no trap opcodes");
|
||||
assert ( opcode_size <= MAX_TRAP_OPCODE_SIZE && "trap opcode size too large");
|
||||
|
||||
::memcpy (m_saved_opcodes, saved_opcodes, opcode_size);
|
||||
::memcpy (m_trap_opcodes, trap_opcodes, opcode_size);
|
||||
}
|
||||
|
||||
Error
|
||||
SoftwareBreakpoint::DoEnable ()
|
||||
{
|
||||
return EnableSoftwareBreakpoint (m_process, m_addr, m_opcode_size, m_trap_opcodes, m_saved_opcodes);
|
||||
}
|
||||
|
||||
Error
|
||||
SoftwareBreakpoint::DoDisable ()
|
||||
{
|
||||
Error error;
|
||||
assert (m_addr && (m_addr != LLDB_INVALID_ADDRESS) && "can't remove a software breakpoint for an invalid address");
|
||||
|
||||
Log *log (GetLogIfAnyCategoriesSet (LIBLLDB_LOG_BREAKPOINTS));
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64, __FUNCTION__, m_addr);
|
||||
|
||||
assert ( (m_opcode_size > 0) && "cannot restore opcodes when there are no opcodes");
|
||||
|
||||
if (m_opcode_size > 0)
|
||||
{
|
||||
// Clear a software breakoint instruction
|
||||
uint8_t curr_break_op [MAX_TRAP_OPCODE_SIZE];
|
||||
bool break_op_found = false;
|
||||
assert (m_opcode_size <= sizeof (curr_break_op));
|
||||
|
||||
// Read the breakpoint opcode
|
||||
lldb::addr_t bytes_read = 0;
|
||||
error = m_process.ReadMemory (m_addr, curr_break_op, m_opcode_size, bytes_read);
|
||||
if (error.Success () && (bytes_read < static_cast<lldb::addr_t> (m_opcode_size)))
|
||||
{
|
||||
error.SetErrorStringWithFormat ("SoftwareBreakpointr::%s addr=0x%" PRIx64 ": tried to read %lu bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, bytes_read);
|
||||
}
|
||||
if (error.Success ())
|
||||
{
|
||||
bool verify = false;
|
||||
// Make sure we have the a breakpoint opcode exists at this address
|
||||
if (::memcmp (curr_break_op, m_trap_opcodes, m_opcode_size) == 0)
|
||||
{
|
||||
break_op_found = true;
|
||||
// We found a valid breakpoint opcode at this address, now restore
|
||||
// the saved opcode.
|
||||
lldb::addr_t bytes_written = 0;
|
||||
error = m_process.WriteMemory (m_addr, m_saved_opcodes, m_opcode_size, bytes_written);
|
||||
if (error.Success () && (bytes_written < static_cast<lldb::addr_t> (m_opcode_size)))
|
||||
{
|
||||
error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to write %lu bytes but only wrote %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, bytes_written);
|
||||
}
|
||||
if (error.Success ())
|
||||
{
|
||||
verify = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
error.SetErrorString("Original breakpoint trap is no longer in memory.");
|
||||
// Set verify to true and so we can check if the original opcode has already been restored
|
||||
verify = true;
|
||||
}
|
||||
|
||||
if (verify)
|
||||
{
|
||||
uint8_t verify_opcode [MAX_TRAP_OPCODE_SIZE];
|
||||
assert (m_opcode_size <= sizeof (verify_opcode));
|
||||
// Verify that our original opcode made it back to the inferior
|
||||
|
||||
lldb::addr_t verify_bytes_read = 0;
|
||||
error = m_process.ReadMemory (m_addr, verify_opcode, m_opcode_size, verify_bytes_read);
|
||||
if (error.Success () && (verify_bytes_read < static_cast<lldb::addr_t> (m_opcode_size)))
|
||||
{
|
||||
error.SetErrorStringWithFormat ("SoftwareBreakpoint::%s addr=0x%" PRIx64 ": tried to read %lu verification bytes but only read %" PRIu64, __FUNCTION__, m_addr, m_opcode_size, verify_bytes_read);
|
||||
}
|
||||
if (error.Success ())
|
||||
{
|
||||
// compare the memory we just read with the original opcode
|
||||
if (::memcmp (m_saved_opcodes, verify_opcode, m_opcode_size) == 0)
|
||||
{
|
||||
// SUCCESS
|
||||
if (log)
|
||||
log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- SUCCESS", __FUNCTION__, m_addr);
|
||||
return error;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (break_op_found)
|
||||
error.SetErrorString("Failed to restore original opcode.");
|
||||
}
|
||||
}
|
||||
else
|
||||
error.SetErrorString("Failed to read memory to verify that breakpoint trap was restored.");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (log && error.Fail ())
|
||||
log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " -- FAILED: %s",
|
||||
__FUNCTION__,
|
||||
m_addr,
|
||||
error.AsCString());
|
||||
return error;
|
||||
}
|
||||
|
||||
bool
|
||||
SoftwareBreakpoint::IsSoftwareBreakpoint () const
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
|
@ -0,0 +1,51 @@
|
|||
//===-- SoftwareBreakpoint.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_SoftwareBreakpoint_h_
|
||||
#define liblldb_SoftwareBreakpoint_h_
|
||||
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "NativeBreakpoint.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class SoftwareBreakpoint : public NativeBreakpoint
|
||||
{
|
||||
public:
|
||||
static Error
|
||||
CreateSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t size_hint, NativeBreakpointSP &breakpoint_spn);
|
||||
|
||||
SoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, const uint8_t *saved_opcodes, const uint8_t *trap_opcodes, size_t opcode_size);
|
||||
|
||||
protected:
|
||||
Error
|
||||
DoEnable () override;
|
||||
|
||||
Error
|
||||
DoDisable () override;
|
||||
|
||||
bool
|
||||
IsSoftwareBreakpoint () const override;
|
||||
|
||||
private:
|
||||
/// Max number of bytes that a software trap opcode sequence can occupy.
|
||||
static const size_t MAX_TRAP_OPCODE_SIZE = 8;
|
||||
|
||||
NativeProcessProtocol &m_process;
|
||||
uint8_t m_saved_opcodes [MAX_TRAP_OPCODE_SIZE];
|
||||
uint8_t m_trap_opcodes [MAX_TRAP_OPCODE_SIZE];
|
||||
const size_t m_opcode_size;
|
||||
|
||||
static Error
|
||||
EnableSoftwareBreakpoint (NativeProcessProtocol &process, lldb::addr_t addr, size_t bp_opcode_size, const uint8_t *bp_opcode_bytes, uint8_t *saved_opcode_bytes);
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
#endif // #ifndef liblldb_SoftwareBreakpoint_h_
|
|
@ -175,6 +175,12 @@ Host::GetAuxvData(lldb_private::Process *process)
|
|||
return ProcFileReader::ReadIntoDataBuffer (process->GetID(), "auxv");
|
||||
}
|
||||
|
||||
lldb::DataBufferSP
|
||||
Host::GetAuxvData (lldb::pid_t pid)
|
||||
{
|
||||
return ProcFileReader::ReadIntoDataBuffer (pid, "auxv");
|
||||
}
|
||||
|
||||
static bool
|
||||
IsDirNumeric(const char *dname)
|
||||
{
|
||||
|
|
|
@ -57,11 +57,10 @@ ParseAuxvEntry(DataExtractor &data,
|
|||
DataBufferSP
|
||||
AuxVector::GetAuxvData()
|
||||
{
|
||||
#if defined(__linux__) || defined(__FreeBSD__)
|
||||
if (m_process->GetPluginName() == ProcessElfCore::GetPluginNameStatic())
|
||||
return static_cast<ProcessElfCore *>(m_process)->GetAuxvData();
|
||||
#endif
|
||||
return lldb_private::Host::GetAuxvData(m_process);
|
||||
if (m_process)
|
||||
return m_process->GetAuxvData ();
|
||||
else
|
||||
return DataBufferSP ();
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
#include "lldb/Core/Error.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/Module.h"
|
||||
#include "lldb/Symbol/ObjectFile.h"
|
||||
#include "lldb/Symbol/Symbol.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "lldb/Target/Target.h"
|
||||
|
@ -28,21 +29,61 @@ using namespace lldb_private;
|
|||
static addr_t
|
||||
ResolveRendezvousAddress(Process *process)
|
||||
{
|
||||
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
|
||||
addr_t info_location;
|
||||
addr_t info_addr;
|
||||
Error error;
|
||||
|
||||
// Try to get it from our process. This might be a remote process and might
|
||||
// grab it via some remote-specific mechanism.
|
||||
info_location = process->GetImageInfoAddress();
|
||||
if (log)
|
||||
log->Printf ("%s info_location = 0x%" PRIx64, __FUNCTION__, info_location);
|
||||
|
||||
// If the process fails to return an address, fall back to seeing if the local object file can help us find it.
|
||||
if (info_location == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
Target *target = process ? &process->GetTarget() : nullptr;
|
||||
if (target)
|
||||
{
|
||||
ObjectFile *obj_file = target->GetExecutableModule()->GetObjectFile();
|
||||
Address addr = obj_file->GetImageInfoAddress(target);
|
||||
|
||||
if (addr.IsValid())
|
||||
{
|
||||
info_location = addr.GetLoadAddress(target);
|
||||
if (log)
|
||||
log->Printf ("%s resolved via direct object file approach to 0x%" PRIx64, __FUNCTION__, info_location);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("%s FAILED - direct object file approach did not yield a valid address", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (info_location == LLDB_INVALID_ADDRESS)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("%s FAILED - invalid info address", __FUNCTION__);
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
info_addr = process->ReadPointerFromMemory(info_location, error);
|
||||
if (error.Fail())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("%s FAILED - could not read from the info location: %s", __FUNCTION__, error.AsCString ());
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
if (info_addr == 0)
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("%s FAILED - the rendezvous address contained at 0x%" PRIx64 " returned a null value", __FUNCTION__, info_location);
|
||||
return LLDB_INVALID_ADDRESS;
|
||||
}
|
||||
|
||||
return info_addr;
|
||||
}
|
||||
|
@ -56,6 +97,8 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
|
|||
m_added_soentries(),
|
||||
m_removed_soentries()
|
||||
{
|
||||
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
|
||||
|
||||
m_thread_info.valid = false;
|
||||
|
||||
// Cache a copy of the executable path
|
||||
|
@ -63,13 +106,24 @@ DYLDRendezvous::DYLDRendezvous(Process *process)
|
|||
{
|
||||
Module *exe_mod = m_process->GetTarget().GetExecutableModulePointer();
|
||||
if (exe_mod)
|
||||
{
|
||||
exe_mod->GetFileSpec().GetPath(m_exe_path, PATH_MAX);
|
||||
if (log)
|
||||
log->Printf ("DYLDRendezvous::%s exe module executable path set: '%s'", __FUNCTION__, m_exe_path);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("DYLDRendezvous::%s cannot cache exe module path: null executable module pointer", __FUNCTION__);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool
|
||||
DYLDRendezvous::Resolve()
|
||||
{
|
||||
Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_DYNAMIC_LOADER));
|
||||
|
||||
const size_t word_size = 4;
|
||||
Rendezvous info;
|
||||
size_t address_size;
|
||||
|
@ -79,12 +133,16 @@ DYLDRendezvous::Resolve()
|
|||
|
||||
address_size = m_process->GetAddressByteSize();
|
||||
padding = address_size - word_size;
|
||||
if (log)
|
||||
log->Printf ("DYLDRendezvous::%s address size: %zu, padding %zu", __FUNCTION__, address_size, padding);
|
||||
|
||||
if (m_rendezvous_addr == LLDB_INVALID_ADDRESS)
|
||||
cursor = info_addr = ResolveRendezvousAddress(m_process);
|
||||
else
|
||||
cursor = info_addr = m_rendezvous_addr;
|
||||
|
||||
if (log)
|
||||
log->Printf ("DYLDRendezvous::%s cursor = 0x%" PRIx64, __FUNCTION__, cursor);
|
||||
|
||||
if (cursor == LLDB_INVALID_ADDRESS)
|
||||
return false;
|
||||
|
||||
|
|
|
@ -33,6 +33,10 @@
|
|||
#include "lldb/Target/Target.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
|
||||
#if defined(__linux__)
|
||||
#include "../../Process/Linux/NativeProcessLinux.h"
|
||||
#endif
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
|
@ -487,3 +491,58 @@ PlatformLinux::CalculateTrapHandlerSymbolNames ()
|
|||
{
|
||||
m_trap_handlers.push_back (ConstString ("_sigtramp"));
|
||||
}
|
||||
|
||||
Error
|
||||
PlatformLinux::LaunchNativeProcess (
|
||||
ProcessLaunchInfo &launch_info,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp)
|
||||
{
|
||||
#if !defined(__linux__)
|
||||
return Error("only implemented on Linux hosts");
|
||||
#else
|
||||
if (!IsHost ())
|
||||
return Error("PlatformLinux::%s (): cannot launch a debug process when not the host", __FUNCTION__);
|
||||
|
||||
// Retrieve the exe module.
|
||||
lldb::ModuleSP exe_module_sp;
|
||||
|
||||
Error error = ResolveExecutable (
|
||||
launch_info.GetExecutableFile (),
|
||||
launch_info.GetArchitecture (),
|
||||
exe_module_sp,
|
||||
NULL);
|
||||
|
||||
if (!error.Success ())
|
||||
return error;
|
||||
|
||||
if (!exe_module_sp)
|
||||
return Error("exe_module_sp could not be resolved for %s", launch_info.GetExecutableFile ().GetPath ().c_str ());
|
||||
|
||||
// Launch it for debugging
|
||||
error = NativeProcessLinux::LaunchProcess (
|
||||
exe_module_sp.get (),
|
||||
launch_info,
|
||||
native_delegate,
|
||||
process_sp);
|
||||
|
||||
return error;
|
||||
#endif
|
||||
}
|
||||
|
||||
Error
|
||||
PlatformLinux::AttachNativeProcess (lldb::pid_t pid,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp)
|
||||
{
|
||||
#if !defined(__linux__)
|
||||
return Error("only implemented on Linux hosts");
|
||||
#else
|
||||
if (!IsHost ())
|
||||
return Error("PlatformLinux::%s (): cannot attach to a debug process when not the host", __FUNCTION__);
|
||||
|
||||
// Launch it for debugging
|
||||
return NativeProcessLinux::AttachToProcess (pid, native_delegate, process_sp);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
@ -103,9 +103,20 @@ namespace lldb_private {
|
|||
virtual void
|
||||
CalculateTrapHandlerSymbolNames ();
|
||||
|
||||
Error
|
||||
LaunchNativeProcess (
|
||||
ProcessLaunchInfo &launch_info,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp) override;
|
||||
|
||||
Error
|
||||
AttachNativeProcess (lldb::pid_t pid,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp) override;
|
||||
|
||||
protected:
|
||||
lldb::PlatformSP m_remote_platform_sp; // Allow multiple ways to connect to a remote darwin OS
|
||||
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN (PlatformLinux);
|
||||
};
|
||||
|
|
|
@ -5,10 +5,11 @@ include_directories(../POSIX)
|
|||
include_directories(../Utility)
|
||||
|
||||
add_lldb_library(lldbPluginProcessLinux
|
||||
NativeProcessLinux.cpp
|
||||
NativeThreadLinux.cpp
|
||||
ProcessLinux.cpp
|
||||
ProcessMonitor.cpp
|
||||
ProcFileReader.cpp
|
||||
LinuxSignals.cpp
|
||||
LinuxThread.cpp
|
||||
)
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,379 @@
|
|||
//===-- NativeProcessLinux.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_NativeProcessLinux_H_
|
||||
#define liblldb_NativeProcessLinux_H_
|
||||
|
||||
// C Includes
|
||||
#include <semaphore.h>
|
||||
#include <signal.h>
|
||||
|
||||
// C++ Includes
|
||||
#include <unordered_set>
|
||||
|
||||
// Other libraries and framework includes
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
#include "lldb/lldb-types.h"
|
||||
#include "lldb/Host/Debug.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
#include "lldb/Target/MemoryRegionInfo.h"
|
||||
|
||||
#include "Host/common/NativeProcessProtocol.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class Error;
|
||||
class Module;
|
||||
class Scalar;
|
||||
|
||||
/// @class NativeProcessLinux
|
||||
/// @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 broadcasted.
|
||||
class NativeProcessLinux: public NativeProcessProtocol
|
||||
{
|
||||
public:
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Public Static Methods
|
||||
// ---------------------------------------------------------------------
|
||||
static lldb_private::Error
|
||||
LaunchProcess (
|
||||
Module *exe_module,
|
||||
ProcessLaunchInfo &launch_info,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &native_process_sp);
|
||||
|
||||
static lldb_private::Error
|
||||
AttachToProcess (
|
||||
lldb::pid_t pid,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &native_process_sp);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Public Instance Methods
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
~NativeProcessLinux() override;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// NativeProcessProtocol Interface
|
||||
// ---------------------------------------------------------------------
|
||||
Error
|
||||
Resume (const ResumeActionList &resume_actions) override;
|
||||
|
||||
Error
|
||||
Halt () override;
|
||||
|
||||
Error
|
||||
Detach () override;
|
||||
|
||||
Error
|
||||
Signal (int signo) override;
|
||||
|
||||
Error
|
||||
Kill () override;
|
||||
|
||||
Error
|
||||
GetMemoryRegionInfo (lldb::addr_t load_addr, MemoryRegionInfo &range_info) override;
|
||||
|
||||
Error
|
||||
ReadMemory (lldb::addr_t addr, void *buf, lldb::addr_t size, lldb::addr_t &bytes_read) override;
|
||||
|
||||
Error
|
||||
WriteMemory (lldb::addr_t addr, const void *buf, lldb::addr_t size, lldb::addr_t &bytes_written) override;
|
||||
|
||||
Error
|
||||
AllocateMemory (lldb::addr_t size, uint32_t permissions, lldb::addr_t &addr) override;
|
||||
|
||||
Error
|
||||
DeallocateMemory (lldb::addr_t addr) override;
|
||||
|
||||
lldb::addr_t
|
||||
GetSharedLibraryInfoAddress () override;
|
||||
|
||||
size_t
|
||||
UpdateThreads () override;
|
||||
|
||||
bool
|
||||
GetArchitecture (ArchSpec &arch) const override;
|
||||
|
||||
Error
|
||||
SetBreakpoint (lldb::addr_t addr, uint32_t size, bool hardware) override;
|
||||
|
||||
void
|
||||
DoStopIDBumped (uint32_t newBumpId) override;
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Interface used by NativeRegisterContext-derived classes.
|
||||
// ---------------------------------------------------------------------
|
||||
|
||||
/// Reads the contents from the register identified by the given (architecture
|
||||
/// dependent) offset.
|
||||
///
|
||||
/// This method is provided for use by RegisterContextLinux 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 RegisterContextLinux derivatives.
|
||||
bool
|
||||
WriteRegisterValue(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 generic 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.
|
||||
/// For instance, the extended floating-point register set.
|
||||
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 generic 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.
|
||||
/// For instance, the extended floating-point register set.
|
||||
bool
|
||||
WriteRegisterSet(lldb::tid_t tid, void *buf, size_t buf_size, unsigned int regset);
|
||||
|
||||
protected:
|
||||
// ---------------------------------------------------------------------
|
||||
// NativeProcessProtocol protected interface
|
||||
// ---------------------------------------------------------------------
|
||||
Error
|
||||
GetSoftwareBreakpointTrapOpcode (size_t trap_opcode_size_hint, size_t &actual_opcode_size, const uint8_t *&trap_opcode_bytes) override;
|
||||
|
||||
private:
|
||||
|
||||
lldb_private::ArchSpec m_arch;
|
||||
|
||||
lldb::thread_t m_operation_thread;
|
||||
lldb::thread_t m_monitor_thread;
|
||||
|
||||
// current operation which must be executed on the priviliged thread
|
||||
void *m_operation;
|
||||
lldb_private::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;
|
||||
|
||||
// Set of tids we're waiting to stop before we notify the delegate of
|
||||
// the stopped state. We only notify the delegate after all threads
|
||||
// ordered to stop have signaled their stop.
|
||||
std::unordered_set<lldb::tid_t> m_wait_for_stop_tids;
|
||||
lldb_private::Mutex m_wait_for_stop_tids_mutex;
|
||||
|
||||
lldb_private::LazyBool m_supports_mem_region;
|
||||
std::vector<MemoryRegionInfo> m_mem_region_cache;
|
||||
lldb_private::Mutex m_mem_region_cache_mutex;
|
||||
|
||||
|
||||
struct OperationArgs
|
||||
{
|
||||
OperationArgs(NativeProcessLinux *monitor);
|
||||
|
||||
~OperationArgs();
|
||||
|
||||
NativeProcessLinux *m_monitor; // The monitor performing the attach.
|
||||
sem_t m_semaphore; // Posted to once operation complete.
|
||||
lldb_private::Error 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(NativeProcessLinux *monitor,
|
||||
lldb_private::Module *module,
|
||||
char const **argv,
|
||||
char const **envp,
|
||||
const char *stdin_path,
|
||||
const char *stdout_path,
|
||||
const char *stderr_path,
|
||||
const char *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 char *m_stdin_path; // Redirect stdin or NULL.
|
||||
const char *m_stdout_path; // Redirect stdout or NULL.
|
||||
const char *m_stderr_path; // Redirect stderr or NULL.
|
||||
const char *m_working_dir; // Working directory or NULL.
|
||||
};
|
||||
|
||||
struct AttachArgs : OperationArgs
|
||||
{
|
||||
AttachArgs(NativeProcessLinux *monitor,
|
||||
lldb::pid_t pid);
|
||||
|
||||
~AttachArgs();
|
||||
|
||||
lldb::pid_t m_pid; // pid of the process to be attached.
|
||||
};
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Private Instance Methods
|
||||
// ---------------------------------------------------------------------
|
||||
NativeProcessLinux ();
|
||||
|
||||
/// Launches an inferior process ready for debugging. Forms the
|
||||
/// implementation of Process::DoLaunch.
|
||||
void
|
||||
LaunchInferior (
|
||||
Module *module,
|
||||
char const *argv[],
|
||||
char const *envp[],
|
||||
const char *stdin_path,
|
||||
const char *stdout_path,
|
||||
const char *stderr_path,
|
||||
const char *working_dir,
|
||||
Error &error);
|
||||
|
||||
/// Attaches to an existing process. Forms the
|
||||
/// implementation of Process::DoLaunch.
|
||||
void
|
||||
AttachToInferior (lldb::pid_t pid, Error &error);
|
||||
|
||||
void
|
||||
StartLaunchOpThread(LaunchArgs *args, lldb_private::Error &error);
|
||||
|
||||
static void *
|
||||
LaunchOpThread(void *arg);
|
||||
|
||||
static bool
|
||||
Launch(LaunchArgs *args);
|
||||
|
||||
void
|
||||
StartAttachOpThread(AttachArgs *args, lldb_private::Error &error);
|
||||
|
||||
static void *
|
||||
AttachOpThread(void *args);
|
||||
|
||||
static bool
|
||||
Attach(AttachArgs *args);
|
||||
|
||||
static bool
|
||||
SetDefaultPtraceOpts(const lldb::pid_t);
|
||||
|
||||
static void
|
||||
ServeOperation(OperationArgs *args);
|
||||
|
||||
static bool
|
||||
DupDescriptor(const char *path, int fd, int flags);
|
||||
|
||||
static bool
|
||||
MonitorCallback(void *callback_baton,
|
||||
lldb::pid_t pid, bool exited, int signal, int status);
|
||||
|
||||
void
|
||||
MonitorSIGTRAP(const siginfo_t *info, lldb::pid_t pid);
|
||||
|
||||
void
|
||||
MonitorSignal(const siginfo_t *info, lldb::pid_t pid, bool exited);
|
||||
|
||||
#if 0
|
||||
static ::ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGSEGV(const siginfo_t *info);
|
||||
|
||||
static ::ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGILL(const siginfo_t *info);
|
||||
|
||||
static ::ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGFPE(const siginfo_t *info);
|
||||
|
||||
static ::ProcessMessage::CrashReason
|
||||
GetCrashReasonForSIGBUS(const siginfo_t *info);
|
||||
#endif
|
||||
|
||||
void
|
||||
DoOperation(void *op);
|
||||
|
||||
/// Stops the child monitor thread.
|
||||
void
|
||||
StopMonitoringChildProcess();
|
||||
|
||||
/// Stops the operation thread used to attach/launch a process.
|
||||
void
|
||||
StopOpThread();
|
||||
|
||||
/// Stops monitoring the child process thread.
|
||||
void
|
||||
StopMonitor();
|
||||
|
||||
bool
|
||||
HasThreadNoLock (lldb::tid_t thread_id);
|
||||
|
||||
NativeThreadProtocolSP
|
||||
MaybeGetThreadNoLock (lldb::tid_t thread_id);
|
||||
|
||||
bool
|
||||
StopTrackingThread (lldb::tid_t thread_id);
|
||||
|
||||
NativeThreadProtocolSP
|
||||
AddThread (lldb::tid_t thread_id);
|
||||
|
||||
NativeThreadProtocolSP
|
||||
GetOrCreateThread (lldb::tid_t thread_id, bool &created);
|
||||
|
||||
Error
|
||||
GetSoftwareBreakpointSize (NativeRegisterContextSP context_sp, uint32_t &actual_opcode_size);
|
||||
|
||||
Error
|
||||
FixupBreakpointPCAsNeeded (NativeThreadProtocolSP &thread_sp);
|
||||
|
||||
/// Writes a siginfo_t structure corresponding to the given thread ID to the
|
||||
/// memory region pointed to by @p siginfo.
|
||||
bool
|
||||
GetSignalInfo(lldb::tid_t tid, void *siginfo, int &ptrace_err);
|
||||
|
||||
/// Writes the raw event message code (vis-a-vis PTRACE_GETEVENTMSG)
|
||||
/// corresponding to the given thread ID to the memory pointed to by @p
|
||||
/// message.
|
||||
bool
|
||||
GetEventMessage(lldb::tid_t tid, unsigned long *message);
|
||||
|
||||
/// Resumes the given thread. If @p signo is anything but
|
||||
/// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
|
||||
bool
|
||||
Resume(lldb::tid_t tid, uint32_t signo);
|
||||
|
||||
/// Single steps the given thread. If @p signo is anything but
|
||||
/// LLDB_INVALID_SIGNAL_NUMBER, deliver that signal to the thread.
|
||||
bool
|
||||
SingleStep(lldb::tid_t tid, uint32_t signo);
|
||||
|
||||
lldb_private::Error
|
||||
Detach(lldb::tid_t tid);
|
||||
};
|
||||
} // End lldb_private namespace.
|
||||
|
||||
#endif // #ifndef liblldb_NativeProcessLinux_H_
|
|
@ -0,0 +1,363 @@
|
|||
//===-- NativeThreadLinux.cpp --------------------------------- -*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#include "NativeThreadLinux.h"
|
||||
|
||||
#include <signal.h>
|
||||
|
||||
#include "NativeProcessLinux.h"
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/State.h"
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "lldb/lldb-enumerations.h"
|
||||
#include "lldb/lldb-private-log.h"
|
||||
#include "Plugins/Process/Utility/NativeRegisterContextLinux_x86_64.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
|
||||
#include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
|
||||
#include "Plugins/Process/Utility/RegisterInfoInterface.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
namespace
|
||||
{
|
||||
void LogThreadStopInfo (Log &log, const ThreadStopInfo &stop_info, const char *const header)
|
||||
{
|
||||
switch (stop_info.reason)
|
||||
{
|
||||
case eStopReasonSignal:
|
||||
log.Printf ("%s: %s: signal 0x%" PRIx32, __FUNCTION__, header, stop_info.details.signal.signo);
|
||||
return;
|
||||
case eStopReasonException:
|
||||
log.Printf ("%s: %s: exception type 0x%" PRIx64, __FUNCTION__, header, stop_info.details.exception.type);
|
||||
return;
|
||||
default:
|
||||
log.Printf ("%s: %s: invalid stop reason %" PRIu32, __FUNCTION__, header, static_cast<uint32_t> (stop_info.reason));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
NativeThreadLinux::NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid) :
|
||||
NativeThreadProtocol (process, tid),
|
||||
m_state (StateType::eStateInvalid),
|
||||
m_stop_info (),
|
||||
m_reg_context_sp ()
|
||||
{
|
||||
}
|
||||
|
||||
const char *
|
||||
NativeThreadLinux::GetName()
|
||||
{
|
||||
NativeProcessProtocolSP process_sp = m_process_wp.lock ();
|
||||
if (!process_sp)
|
||||
return "<unknown: no process>";
|
||||
|
||||
// const NativeProcessLinux *const process = reinterpret_cast<NativeProcessLinux*> (process_sp->get ());
|
||||
return Host::GetThreadName (process_sp->GetID (), GetID ()).c_str ();
|
||||
}
|
||||
|
||||
lldb::StateType
|
||||
NativeThreadLinux::GetState ()
|
||||
{
|
||||
return m_state;
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
NativeThreadLinux::GetStopReason (ThreadStopInfo &stop_info)
|
||||
{
|
||||
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
|
||||
switch (m_state)
|
||||
{
|
||||
case eStateStopped:
|
||||
case eStateCrashed:
|
||||
case eStateExited:
|
||||
case eStateSuspended:
|
||||
case eStateUnloaded:
|
||||
if (log)
|
||||
LogThreadStopInfo (*log, m_stop_info, "m_stop_info in thread: ");
|
||||
stop_info = m_stop_info;
|
||||
if (log)
|
||||
LogThreadStopInfo (*log, stop_info, "returned stop_info: ");
|
||||
return true;
|
||||
|
||||
case eStateInvalid:
|
||||
case eStateConnected:
|
||||
case eStateAttaching:
|
||||
case eStateLaunching:
|
||||
case eStateRunning:
|
||||
case eStateStepping:
|
||||
case eStateDetached:
|
||||
default:
|
||||
if (log)
|
||||
{
|
||||
log->Printf ("NativeThreadLinux::%s tid %" PRIu64 " in state %s cannot answer stop reason",
|
||||
__FUNCTION__, GetID (), StateAsCString (m_state));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
lldb_private::NativeRegisterContextSP
|
||||
NativeThreadLinux::GetRegisterContext ()
|
||||
{
|
||||
// Return the register context if we already created it.
|
||||
if (m_reg_context_sp)
|
||||
return m_reg_context_sp;
|
||||
|
||||
// First select the appropriate RegisterInfoInterface.
|
||||
RegisterInfoInterface *reg_interface = nullptr;
|
||||
NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
|
||||
if (!m_process_sp)
|
||||
return NativeRegisterContextSP ();
|
||||
|
||||
ArchSpec target_arch;
|
||||
if (!m_process_sp->GetArchitecture (target_arch))
|
||||
return NativeRegisterContextSP ();
|
||||
|
||||
switch (target_arch.GetTriple().getOS())
|
||||
{
|
||||
case llvm::Triple::Linux:
|
||||
switch (target_arch.GetMachine())
|
||||
{
|
||||
case llvm::Triple::x86:
|
||||
case llvm::Triple::x86_64:
|
||||
if (Host::GetArchitecture().GetAddressByteSize() == 4)
|
||||
{
|
||||
// 32-bit hosts run with a RegisterContextLinux_i386 context.
|
||||
reg_interface = static_cast<RegisterInfoInterface*>(new RegisterContextLinux_i386(target_arch));
|
||||
}
|
||||
else
|
||||
{
|
||||
assert((Host::GetArchitecture ().GetAddressByteSize () == 8) && "Register setting path assumes this is a 64-bit host");
|
||||
// X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the x86_64 register context.
|
||||
reg_interface = static_cast<RegisterInfoInterface*> (new RegisterContextLinux_x86_64 (target_arch));
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
assert(reg_interface && "OS or CPU not supported!");
|
||||
if (!reg_interface)
|
||||
return NativeRegisterContextSP ();
|
||||
|
||||
// Now create the register context.
|
||||
switch (target_arch.GetMachine())
|
||||
{
|
||||
#if 0
|
||||
case llvm::Triple::mips64:
|
||||
{
|
||||
RegisterContextPOSIXProcessMonitor_mips64 *reg_ctx = new RegisterContextPOSIXProcessMonitor_mips64(*this, 0, reg_interface);
|
||||
m_posix_thread = reg_ctx;
|
||||
m_reg_context_sp.reset(reg_ctx);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
#if 0
|
||||
case llvm::Triple::x86:
|
||||
#endif
|
||||
case llvm::Triple::x86_64:
|
||||
{
|
||||
const uint32_t concrete_frame_idx = 0;
|
||||
m_reg_context_sp.reset (new NativeRegisterContextLinux_x86_64(*this, concrete_frame_idx, reg_interface));
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return m_reg_context_sp;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeThreadLinux::SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware)
|
||||
{
|
||||
// TODO implement
|
||||
return Error ("not implemented");
|
||||
}
|
||||
|
||||
Error
|
||||
NativeThreadLinux::RemoveWatchpoint (lldb::addr_t addr)
|
||||
{
|
||||
// TODO implement
|
||||
return Error ("not implemented");
|
||||
}
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetLaunching ()
|
||||
{
|
||||
const StateType new_state = StateType::eStateLaunching;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
// Also mark it as stopped since launching temporarily stops the newly created thread
|
||||
// in the ptrace machinery.
|
||||
m_stop_info.reason = StopReason::eStopReasonSignal;
|
||||
m_stop_info.details.signal.signo = SIGSTOP;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetRunning ()
|
||||
{
|
||||
const StateType new_state = StateType::eStateRunning;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
m_stop_info.reason = StopReason::eStopReasonNone;
|
||||
}
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetStepping ()
|
||||
{
|
||||
const StateType new_state = StateType::eStateStepping;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
m_stop_info.reason = StopReason::eStopReasonNone;
|
||||
}
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetStoppedBySignal (uint32_t signo)
|
||||
{
|
||||
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
|
||||
if (log)
|
||||
log->Printf ("NativeThreadLinux::%s called with signal 0x%" PRIx32, __FUNCTION__, signo);
|
||||
|
||||
const StateType new_state = StateType::eStateStopped;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
m_stop_info.reason = StopReason::eStopReasonSignal;
|
||||
m_stop_info.details.signal.signo = signo;
|
||||
}
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetStoppedByBreakpoint ()
|
||||
{
|
||||
const StateType new_state = StateType::eStateStopped;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
m_stop_info.reason = StopReason::eStopReasonSignal;
|
||||
m_stop_info.details.signal.signo = SIGTRAP;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeThreadLinux::IsStoppedAtBreakpoint ()
|
||||
{
|
||||
// Are we stopped? If not, this can't be a breakpoint.
|
||||
if (GetState () != StateType::eStateStopped)
|
||||
return false;
|
||||
|
||||
// Was the stop reason a signal with signal number SIGTRAP? If not, not a breakpoint.
|
||||
return (m_stop_info.reason == StopReason::eStopReasonSignal) &&
|
||||
(m_stop_info.details.signal.signo == SIGTRAP);
|
||||
}
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetCrashedWithException (uint64_t exception_type, lldb::addr_t exception_addr)
|
||||
{
|
||||
const StateType new_state = StateType::eStateCrashed;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
m_stop_info.reason = StopReason::eStopReasonException;
|
||||
m_stop_info.details.exception.type = exception_type;
|
||||
m_stop_info.details.exception.data_count = 1;
|
||||
m_stop_info.details.exception.data[0] = exception_addr;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetSuspended ()
|
||||
{
|
||||
const StateType new_state = StateType::eStateSuspended;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
// FIXME what makes sense here? Do we need a suspended StopReason?
|
||||
m_stop_info.reason = StopReason::eStopReasonNone;
|
||||
}
|
||||
|
||||
void
|
||||
NativeThreadLinux::SetExited ()
|
||||
{
|
||||
const StateType new_state = StateType::eStateExited;
|
||||
MaybeLogStateChange (new_state);
|
||||
m_state = new_state;
|
||||
|
||||
m_stop_info.reason = StopReason::eStopReasonThreadExiting;
|
||||
}
|
||||
|
||||
void
|
||||
NativeThreadLinux::MaybeLogStateChange (lldb::StateType new_state)
|
||||
{
|
||||
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
|
||||
// If we're not logging, we're done.
|
||||
if (!log)
|
||||
return;
|
||||
|
||||
// If this is a state change to the same state, we're done.
|
||||
lldb::StateType old_state = m_state;
|
||||
if (new_state == old_state)
|
||||
return;
|
||||
|
||||
NativeProcessProtocolSP m_process_sp = m_process_wp.lock ();
|
||||
lldb::pid_t pid = m_process_sp ? m_process_sp->GetID () : LLDB_INVALID_PROCESS_ID;
|
||||
|
||||
// Log it.
|
||||
log->Printf ("NativeThreadLinux: thread (pid=%" PRIu64 ", tid=%" PRIu64 ") changing from state %s to %s", pid, GetID (), StateAsCString (old_state), StateAsCString (new_state));
|
||||
}
|
||||
|
||||
static
|
||||
uint32_t MaybeTranslateHostSignoToGdbSigno (uint32_t host_signo)
|
||||
{
|
||||
switch (host_signo)
|
||||
{
|
||||
case SIGSEGV: return eGdbSignalBadAccess;
|
||||
case SIGILL: return eGdbSignalBadInstruction;
|
||||
case SIGFPE: return eGdbSignalArithmetic;
|
||||
// NOTE: debugserver sends SIGTRAP through unmodified. Do the same here.
|
||||
// case SIGTRAP: return eGdbSignalBreakpoint;
|
||||
|
||||
// Nothing for eGdbSignalSoftware (0x95).
|
||||
// Nothing for eGdbSignalEmulation (0x94).
|
||||
|
||||
default:
|
||||
// No translations.
|
||||
return host_signo;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeThreadLinux::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const
|
||||
{
|
||||
switch (stop_info.reason)
|
||||
{
|
||||
case eStopReasonSignal:
|
||||
return MaybeTranslateHostSignoToGdbSigno (stop_info.details.signal.signo);
|
||||
break;
|
||||
|
||||
case eStopReasonException:
|
||||
// FIXME verify how we handle exception type.
|
||||
return MaybeTranslateHostSignoToGdbSigno (static_cast<uint32_t> (stop_info.details.exception.type));
|
||||
break;
|
||||
|
||||
default:
|
||||
assert (0 && "unexpected stop_info.reason found");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,97 @@
|
|||
//===-- NativeThreadLinux.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_NativeThreadLinux_H_
|
||||
#define liblldb_NativeThreadLinux_H_
|
||||
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "../../../Host/common/NativeThreadProtocol.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class NativeProcessLinux;
|
||||
|
||||
class NativeThreadLinux : public NativeThreadProtocol
|
||||
{
|
||||
friend class NativeProcessLinux;
|
||||
|
||||
public:
|
||||
NativeThreadLinux (NativeProcessLinux *process, lldb::tid_t tid);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// NativeThreadProtocol Interface
|
||||
// ---------------------------------------------------------------------
|
||||
const char *
|
||||
GetName() override;
|
||||
|
||||
lldb::StateType
|
||||
GetState () override;
|
||||
|
||||
bool
|
||||
GetStopReason (ThreadStopInfo &stop_info) override;
|
||||
|
||||
NativeRegisterContextSP
|
||||
GetRegisterContext () override;
|
||||
|
||||
Error
|
||||
SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) override;
|
||||
|
||||
Error
|
||||
RemoveWatchpoint (lldb::addr_t addr) override;
|
||||
|
||||
uint32_t
|
||||
TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const override;
|
||||
|
||||
private:
|
||||
// ---------------------------------------------------------------------
|
||||
// Interface for friend classes
|
||||
// ---------------------------------------------------------------------
|
||||
void
|
||||
SetLaunching ();
|
||||
|
||||
void
|
||||
SetRunning ();
|
||||
|
||||
void
|
||||
SetStepping ();
|
||||
|
||||
void
|
||||
SetStoppedBySignal (uint32_t signo);
|
||||
|
||||
void
|
||||
SetStoppedByBreakpoint ();
|
||||
|
||||
bool
|
||||
IsStoppedAtBreakpoint ();
|
||||
|
||||
void
|
||||
SetCrashedWithException (uint64_t exception_type, lldb::addr_t exception_addr);
|
||||
|
||||
void
|
||||
SetSuspended ();
|
||||
|
||||
void
|
||||
SetExited ();
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Private interface
|
||||
// ---------------------------------------------------------------------
|
||||
void
|
||||
MaybeLogStateChange (lldb::StateType new_state);
|
||||
|
||||
// ---------------------------------------------------------------------
|
||||
// Member Variables
|
||||
// ---------------------------------------------------------------------
|
||||
lldb::StateType m_state;
|
||||
ThreadStopInfo m_stop_info;
|
||||
NativeRegisterContextSP m_reg_context_sp;
|
||||
};
|
||||
}
|
||||
|
||||
#endif // #ifndef liblldb_NativeThreadLinux_H_
|
|
@ -17,10 +17,11 @@
|
|||
|
||||
// Other libraries and framework includes
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "LinuxSignals.h"
|
||||
#include "ProcessMessage.h"
|
||||
#include "ProcessPOSIX.h"
|
||||
|
||||
#include "Plugins/Process/Utility/LinuxSignals.h"
|
||||
|
||||
class ProcessMonitor;
|
||||
|
||||
class ProcessLinux :
|
||||
|
@ -107,7 +108,7 @@ public:
|
|||
private:
|
||||
|
||||
/// Linux-specific signal set.
|
||||
LinuxSignals m_linux_signals;
|
||||
process_linux::LinuxSignals m_linux_signals;
|
||||
|
||||
lldb_private::FileSpec *m_core_file;
|
||||
|
||||
|
|
|
@ -1228,8 +1228,12 @@ ProcessMonitor::Launch(LaunchArgs *args)
|
|||
|
||||
// Wait for the child process to to trap on its call to execve.
|
||||
lldb::pid_t wpid;
|
||||
::pid_t raw_pid;
|
||||
int status;
|
||||
if ((wpid = waitpid(pid, &status, 0)) < 0)
|
||||
|
||||
raw_pid = waitpid(pid, &status, 0);
|
||||
wpid = static_cast <lldb::pid_t> (raw_pid);
|
||||
if (raw_pid < 0)
|
||||
{
|
||||
args->m_error.SetErrorToErrno();
|
||||
goto FINISH;
|
||||
|
|
|
@ -934,3 +934,16 @@ ProcessPOSIX::IsAThreadRunning()
|
|||
}
|
||||
return is_running;
|
||||
}
|
||||
|
||||
const DataBufferSP
|
||||
ProcessPOSIX::GetAuxvData ()
|
||||
{
|
||||
// If we're the local platform, we can ask the host for auxv data.
|
||||
PlatformSP platform_sp = m_target.GetPlatform ();
|
||||
if (platform_sp && platform_sp->IsHost ())
|
||||
return lldb_private::Host::GetAuxvData(this);
|
||||
|
||||
// Somewhat unexpected - the process is not running locally or we don't have a platform.
|
||||
assert (false && "no platform or not the host - how did we get here with ProcessPOSIX?");
|
||||
return DataBufferSP ();
|
||||
}
|
||||
|
|
|
@ -141,6 +141,9 @@ public:
|
|||
virtual size_t
|
||||
PutSTDIN(const char *buf, size_t len, lldb_private::Error &error);
|
||||
|
||||
const lldb::DataBufferSP
|
||||
GetAuxvData () override;
|
||||
|
||||
//--------------------------------------------------------------------------
|
||||
// ProcessPOSIX internal API.
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ add_lldb_library(lldbPluginProcessUtility
|
|||
HistoryThread.cpp
|
||||
HistoryUnwind.cpp
|
||||
InferiorCallPOSIX.cpp
|
||||
LinuxSignals.cpp
|
||||
NativeRegisterContextLinux_x86_64.cpp
|
||||
RegisterContextDarwin_arm.cpp
|
||||
RegisterContextDarwin_arm64.cpp
|
||||
RegisterContextDarwin_i386.cpp
|
||||
|
|
|
@ -15,6 +15,8 @@
|
|||
// Project includes
|
||||
#include "LinuxSignals.h"
|
||||
|
||||
using namespace process_linux;
|
||||
|
||||
LinuxSignals::LinuxSignals()
|
||||
: UnixSignals()
|
||||
{
|
||||
|
@ -26,6 +28,10 @@ LinuxSignals::Reset()
|
|||
{
|
||||
m_signals.clear();
|
||||
|
||||
// FIXME we now need *Signals classes on systems that are different OSes (e.g. LinuxSignals
|
||||
// needed on MacOSX to debug Linux from MacOSX, and similar scenarios, used by ProcessGDBRemote). These must be defined
|
||||
// not based on OS includes and defines.
|
||||
|
||||
#define ADDSIGNAL(S, SUPPRESS, STOP, NOTIFY, DESCRIPTION) \
|
||||
AddSignal(SIG ## S, "SIG" #S, #S, SUPPRESS, STOP, NOTIFY, DESCRIPTION)
|
||||
|
||||
|
@ -60,9 +66,13 @@ LinuxSignals::Reset()
|
|||
ADDSIGNAL(VTALRM, false, true, true, "virtual alarm");
|
||||
ADDSIGNAL(PROF, false, true, true, "profiling alarm");
|
||||
ADDSIGNAL(WINCH, false, true, true, "window size change");
|
||||
#ifdef SIGPOLL
|
||||
ADDSIGNAL(POLL, false, true, true, "pollable event");
|
||||
#endif
|
||||
ADDSIGNAL(IO, false, true, true, "input/output ready");
|
||||
#ifdef SIGPWR
|
||||
ADDSIGNAL(PWR, false, true, true, "power failure");
|
||||
#endif
|
||||
ADDSIGNAL(SYS, false, true, true, "invalid system call");
|
||||
|
||||
#undef ADDSIGNAL
|
|
@ -16,16 +16,20 @@
|
|||
// Project includes
|
||||
#include "lldb/Target/UnixSignals.h"
|
||||
|
||||
/// Linux specific set of Unix signals.
|
||||
class LinuxSignals
|
||||
: public lldb_private::UnixSignals
|
||||
namespace process_linux
|
||||
{
|
||||
public:
|
||||
LinuxSignals();
|
||||
|
||||
private:
|
||||
void
|
||||
Reset();
|
||||
};
|
||||
/// Linux specific set of Unix signals.
|
||||
class LinuxSignals
|
||||
: public lldb_private::UnixSignals
|
||||
{
|
||||
public:
|
||||
LinuxSignals();
|
||||
|
||||
private:
|
||||
void
|
||||
Reset();
|
||||
};
|
||||
}
|
||||
|
||||
#endif
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,135 @@
|
|||
//===-- NativeRegisterContextLinux_x86_64.h ---------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
|
||||
#ifndef lldb_NativeRegisterContextLinux_x86_64_h
|
||||
#define lldb_NativeRegisterContextLinux_x86_64_h
|
||||
|
||||
#include "lldb/Target/NativeRegisterContextRegisterInfo.h"
|
||||
#include "RegisterContext_x86.h"
|
||||
#include "lldb-x86-register-enums.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
class NativeProcessLinux;
|
||||
|
||||
class NativeRegisterContextLinux_x86_64 : public NativeRegisterContextRegisterInfo
|
||||
{
|
||||
public:
|
||||
NativeRegisterContextLinux_x86_64 (NativeThreadProtocol &native_thread, uint32_t concrete_frame_idx, RegisterInfoInterface *reg_info_interface_p);
|
||||
|
||||
uint32_t
|
||||
GetRegisterSetCount () const override;
|
||||
|
||||
const RegisterSet *
|
||||
GetRegisterSet (uint32_t set_index) const override;
|
||||
|
||||
Error
|
||||
ReadRegister (const RegisterInfo *reg_info, RegisterValue ®_value) override;
|
||||
|
||||
Error
|
||||
WriteRegister (const RegisterInfo *reg_info, const RegisterValue ®_value) override;
|
||||
|
||||
Error
|
||||
ReadAllRegisterValues (lldb::DataBufferSP &data_sp) override;
|
||||
|
||||
Error
|
||||
WriteAllRegisterValues (const lldb::DataBufferSP &data_sp) override;
|
||||
|
||||
private:
|
||||
|
||||
// Private member types.
|
||||
enum FPRType
|
||||
{
|
||||
eFPRTypeNotValid = 0,
|
||||
eFPRTypeFXSAVE,
|
||||
eFPRTypeXSAVE
|
||||
};
|
||||
|
||||
// Info about register ranges.
|
||||
struct RegInfo
|
||||
{
|
||||
uint32_t num_registers;
|
||||
uint32_t num_gpr_registers;
|
||||
uint32_t num_fpr_registers;
|
||||
uint32_t num_avx_registers;
|
||||
|
||||
uint32_t last_gpr;
|
||||
uint32_t first_fpr;
|
||||
uint32_t last_fpr;
|
||||
|
||||
uint32_t first_st;
|
||||
uint32_t last_st;
|
||||
uint32_t first_mm;
|
||||
uint32_t last_mm;
|
||||
uint32_t first_xmm;
|
||||
uint32_t last_xmm;
|
||||
uint32_t first_ymm;
|
||||
uint32_t last_ymm;
|
||||
|
||||
uint32_t first_dr;
|
||||
uint32_t gpr_flags;
|
||||
};
|
||||
|
||||
// Private member variables.
|
||||
mutable FPRType m_fpr_type;
|
||||
FPR m_fpr;
|
||||
IOVEC m_iovec;
|
||||
YMM m_ymm_set;
|
||||
RegInfo m_reg_info;
|
||||
uint64_t m_gpr_x86_64[k_num_gpr_registers_x86_64];
|
||||
|
||||
// Private member methods.
|
||||
lldb_private::Error
|
||||
WriteRegister(const uint32_t reg, const RegisterValue &value);
|
||||
|
||||
bool IsRegisterSetAvailable (uint32_t set_index) const;
|
||||
|
||||
lldb::ByteOrder
|
||||
GetByteOrder() const;
|
||||
|
||||
bool
|
||||
IsGPR(uint32_t reg_index) const;
|
||||
|
||||
FPRType
|
||||
GetFPRType () const;
|
||||
|
||||
bool
|
||||
IsFPR(uint32_t reg_index) const;
|
||||
|
||||
bool
|
||||
WriteFPR();
|
||||
|
||||
bool IsFPR(uint32_t reg_index, FPRType fpr_type) const;
|
||||
|
||||
bool
|
||||
CopyXSTATEtoYMM (uint32_t reg_index, lldb::ByteOrder byte_order);
|
||||
|
||||
bool
|
||||
CopyYMMtoXSTATE(uint32_t reg, lldb::ByteOrder byte_order);
|
||||
|
||||
bool
|
||||
IsAVX (uint32_t reg_index) const;
|
||||
|
||||
bool
|
||||
ReadFPR ();
|
||||
|
||||
lldb_private::Error
|
||||
ReadRegisterRaw (uint32_t reg_index, RegisterValue ®_value);
|
||||
|
||||
bool
|
||||
ReadGPR();
|
||||
|
||||
bool
|
||||
WriteGPR();
|
||||
};
|
||||
}
|
||||
|
||||
#endif // #ifndef lldb_NativeRegisterContextLinux_x86_64_h
|
||||
|
|
@ -62,18 +62,14 @@ RegisterContextFreeBSD_i386::RegisterContextFreeBSD_i386(const ArchSpec &target_
|
|||
{
|
||||
}
|
||||
|
||||
RegisterContextFreeBSD_i386::~RegisterContextFreeBSD_i386()
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
RegisterContextFreeBSD_i386::GetGPRSize()
|
||||
RegisterContextFreeBSD_i386::GetGPRSize() const
|
||||
{
|
||||
return sizeof(GPR);
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
RegisterContextFreeBSD_i386::GetRegisterInfo()
|
||||
RegisterContextFreeBSD_i386::GetRegisterInfo() const
|
||||
{
|
||||
switch (m_target_arch.GetMachine())
|
||||
{
|
||||
|
@ -84,3 +80,9 @@ RegisterContextFreeBSD_i386::GetRegisterInfo()
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RegisterContextFreeBSD_i386::GetRegisterCount () const
|
||||
{
|
||||
return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0]));
|
||||
}
|
||||
|
|
|
@ -17,13 +17,15 @@ class RegisterContextFreeBSD_i386
|
|||
{
|
||||
public:
|
||||
RegisterContextFreeBSD_i386(const lldb_private::ArchSpec &target_arch);
|
||||
virtual ~RegisterContextFreeBSD_i386();
|
||||
|
||||
size_t
|
||||
GetGPRSize();
|
||||
GetGPRSize() const override;
|
||||
|
||||
const lldb_private::RegisterInfo *
|
||||
GetRegisterInfo();
|
||||
GetRegisterInfo() const override;
|
||||
|
||||
uint32_t
|
||||
GetRegisterCount () const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -71,20 +71,23 @@ RegisterContextFreeBSD_mips64::RegisterContextFreeBSD_mips64(const ArchSpec &tar
|
|||
{
|
||||
}
|
||||
|
||||
RegisterContextFreeBSD_mips64::~RegisterContextFreeBSD_mips64()
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
RegisterContextFreeBSD_mips64::GetGPRSize()
|
||||
RegisterContextFreeBSD_mips64::GetGPRSize() const
|
||||
{
|
||||
return sizeof(GPR);
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
RegisterContextFreeBSD_mips64::GetRegisterInfo()
|
||||
RegisterContextFreeBSD_mips64::GetRegisterInfo() const
|
||||
{
|
||||
assert (m_target_arch.GetCore() == ArchSpec::eCore_mips64);
|
||||
return g_register_infos_mips64;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RegisterContextFreeBSD_mips64::GetRegisterCount () const
|
||||
{
|
||||
return static_cast<uint32_t> (sizeof (g_register_infos_mips64) / sizeof (g_register_infos_mips64 [0]));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,13 +17,15 @@ class RegisterContextFreeBSD_mips64:
|
|||
{
|
||||
public:
|
||||
RegisterContextFreeBSD_mips64(const lldb_private::ArchSpec &target_arch);
|
||||
virtual ~RegisterContextFreeBSD_mips64();
|
||||
|
||||
size_t
|
||||
GetGPRSize();
|
||||
GetGPRSize() const override;
|
||||
|
||||
const lldb_private::RegisterInfo *
|
||||
GetRegisterInfo();
|
||||
GetRegisterInfo() const override;
|
||||
|
||||
uint32_t
|
||||
GetRegisterCount () const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -67,10 +67,17 @@ struct dbreg {
|
|||
#include "RegisterInfos_x86_64.h"
|
||||
#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
|
||||
|
||||
static std::vector<lldb_private::RegisterInfo>&
|
||||
GetSharedRegisterInfoVector ()
|
||||
{
|
||||
static std::vector<lldb_private::RegisterInfo> register_infos;
|
||||
return register_infos;
|
||||
}
|
||||
|
||||
static const RegisterInfo *
|
||||
GetRegisterInfo_i386(const lldb_private::ArchSpec& arch)
|
||||
{
|
||||
static std::vector<lldb_private::RegisterInfo> g_register_infos;
|
||||
static std::vector<lldb_private::RegisterInfo> g_register_infos (GetSharedRegisterInfoVector ());
|
||||
|
||||
// Allocate RegisterInfo only once
|
||||
if (g_register_infos.empty())
|
||||
|
@ -92,33 +99,61 @@ GetRegisterInfo_i386(const lldb_private::ArchSpec& arch)
|
|||
return &g_register_infos[0];
|
||||
}
|
||||
|
||||
RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) :
|
||||
lldb_private::RegisterInfoInterface(target_arch)
|
||||
static const RegisterInfo *
|
||||
PrivateGetRegisterInfoPtr (const lldb_private::ArchSpec& target_arch)
|
||||
{
|
||||
switch (target_arch.GetMachine())
|
||||
{
|
||||
case llvm::Triple::x86:
|
||||
return GetRegisterInfo_i386 (target_arch);
|
||||
case llvm::Triple::x86_64:
|
||||
return g_register_infos_x86_64;
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RegisterContextFreeBSD_x86_64::~RegisterContextFreeBSD_x86_64()
|
||||
static uint32_t
|
||||
PrivateGetRegisterCount (const lldb_private::ArchSpec& target_arch)
|
||||
{
|
||||
switch (target_arch.GetMachine())
|
||||
{
|
||||
case llvm::Triple::x86:
|
||||
// This vector should have already been filled.
|
||||
assert (!GetSharedRegisterInfoVector ().empty () && "i386 register info vector not filled.");
|
||||
return static_cast<uint32_t> (GetSharedRegisterInfoVector().size ());
|
||||
case llvm::Triple::x86_64:
|
||||
return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0]));
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RegisterContextFreeBSD_x86_64::RegisterContextFreeBSD_x86_64(const ArchSpec &target_arch) :
|
||||
lldb_private::RegisterInfoInterface(target_arch),
|
||||
m_register_info_p (PrivateGetRegisterInfoPtr (target_arch)),
|
||||
m_register_count (PrivateGetRegisterCount (target_arch))
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
RegisterContextFreeBSD_x86_64::GetGPRSize()
|
||||
RegisterContextFreeBSD_x86_64::GetGPRSize() const
|
||||
{
|
||||
return sizeof(GPR);
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
RegisterContextFreeBSD_x86_64::GetRegisterInfo()
|
||||
RegisterContextFreeBSD_x86_64::GetRegisterInfo() const
|
||||
{
|
||||
switch (m_target_arch.GetMachine())
|
||||
{
|
||||
case llvm::Triple::x86:
|
||||
return GetRegisterInfo_i386 (m_target_arch);
|
||||
case llvm::Triple::x86_64:
|
||||
return g_register_infos_x86_64;
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return NULL;
|
||||
}
|
||||
return m_register_info_p;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RegisterContextFreeBSD_x86_64::GetRegisterCount () const
|
||||
{
|
||||
return m_register_count;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -17,13 +17,19 @@ class RegisterContextFreeBSD_x86_64:
|
|||
{
|
||||
public:
|
||||
RegisterContextFreeBSD_x86_64(const lldb_private::ArchSpec &target_arch);
|
||||
virtual ~RegisterContextFreeBSD_x86_64();
|
||||
|
||||
size_t
|
||||
GetGPRSize();
|
||||
GetGPRSize() const override;
|
||||
|
||||
const lldb_private::RegisterInfo *
|
||||
GetRegisterInfo();
|
||||
GetRegisterInfo() const override;
|
||||
|
||||
uint32_t
|
||||
GetRegisterCount () const override;
|
||||
|
||||
private:
|
||||
const lldb_private::RegisterInfo *m_register_info_p;
|
||||
const uint32_t m_register_count;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -100,18 +100,14 @@ RegisterContextLinux_i386::RegisterContextLinux_i386(const ArchSpec &target_arch
|
|||
{
|
||||
}
|
||||
|
||||
RegisterContextLinux_i386::~RegisterContextLinux_i386()
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
RegisterContextLinux_i386::GetGPRSize()
|
||||
RegisterContextLinux_i386::GetGPRSize() const
|
||||
{
|
||||
return sizeof(GPR);
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
RegisterContextLinux_i386::GetRegisterInfo()
|
||||
RegisterContextLinux_i386::GetRegisterInfo() const
|
||||
{
|
||||
switch (m_target_arch.GetMachine())
|
||||
{
|
||||
|
@ -122,3 +118,10 @@ RegisterContextLinux_i386::GetRegisterInfo()
|
|||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RegisterContextLinux_i386::GetRegisterCount () const
|
||||
{
|
||||
return static_cast<uint32_t> (sizeof (g_register_infos_i386) / sizeof (g_register_infos_i386 [0]));
|
||||
}
|
||||
|
||||
|
|
|
@ -17,13 +17,15 @@ class RegisterContextLinux_i386
|
|||
{
|
||||
public:
|
||||
RegisterContextLinux_i386(const lldb_private::ArchSpec &target_arch);
|
||||
virtual ~RegisterContextLinux_i386();
|
||||
|
||||
size_t
|
||||
GetGPRSize();
|
||||
GetGPRSize() const override;
|
||||
|
||||
const lldb_private::RegisterInfo *
|
||||
GetRegisterInfo();
|
||||
GetRegisterInfo() const override;
|
||||
|
||||
uint32_t
|
||||
GetRegisterCount () const override;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -80,10 +80,17 @@ struct UserArea
|
|||
#include "RegisterInfos_x86_64.h"
|
||||
#undef DECLARE_REGISTER_INFOS_X86_64_STRUCT
|
||||
|
||||
static std::vector<lldb_private::RegisterInfo>&
|
||||
GetPrivateRegisterInfoVector ()
|
||||
{
|
||||
static std::vector<lldb_private::RegisterInfo> g_register_infos;
|
||||
return g_register_infos;
|
||||
}
|
||||
|
||||
static const RegisterInfo *
|
||||
GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
|
||||
{
|
||||
static std::vector<lldb_private::RegisterInfo> g_register_infos;
|
||||
static std::vector<lldb_private::RegisterInfo> g_register_infos (GetPrivateRegisterInfoVector ());
|
||||
|
||||
// Allocate RegisterInfo only once
|
||||
if (g_register_infos.empty())
|
||||
|
@ -105,33 +112,60 @@ GetRegisterInfo_i386(const lldb_private::ArchSpec &arch)
|
|||
return &g_register_infos[0];
|
||||
}
|
||||
|
||||
RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
|
||||
lldb_private::RegisterInfoInterface(target_arch)
|
||||
static const RegisterInfo *
|
||||
GetRegisterInfoPtr (const ArchSpec &target_arch)
|
||||
{
|
||||
switch (target_arch.GetMachine())
|
||||
{
|
||||
case llvm::Triple::x86:
|
||||
return GetRegisterInfo_i386 (target_arch);
|
||||
case llvm::Triple::x86_64:
|
||||
return g_register_infos_x86_64;
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
RegisterContextLinux_x86_64::~RegisterContextLinux_x86_64()
|
||||
static uint32_t
|
||||
GetRegisterInfoCount (const ArchSpec &target_arch)
|
||||
{
|
||||
switch (target_arch.GetMachine())
|
||||
{
|
||||
case llvm::Triple::x86:
|
||||
{
|
||||
assert (!GetPrivateRegisterInfoVector ().empty () && "i386 register info not yet filled.");
|
||||
return static_cast<uint32_t> (GetPrivateRegisterInfoVector ().size ());
|
||||
}
|
||||
case llvm::Triple::x86_64:
|
||||
return static_cast<uint32_t> (sizeof (g_register_infos_x86_64) / sizeof (g_register_infos_x86_64 [0]));
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
RegisterContextLinux_x86_64::RegisterContextLinux_x86_64(const ArchSpec &target_arch) :
|
||||
lldb_private::RegisterInfoInterface(target_arch),
|
||||
m_register_info_p (GetRegisterInfoPtr (target_arch)),
|
||||
m_register_info_count (GetRegisterInfoCount (target_arch))
|
||||
{
|
||||
}
|
||||
|
||||
size_t
|
||||
RegisterContextLinux_x86_64::GetGPRSize()
|
||||
RegisterContextLinux_x86_64::GetGPRSize() const
|
||||
{
|
||||
return sizeof(GPR);
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
RegisterContextLinux_x86_64::GetRegisterInfo()
|
||||
RegisterContextLinux_x86_64::GetRegisterInfo() const
|
||||
{
|
||||
switch (m_target_arch.GetMachine())
|
||||
{
|
||||
case llvm::Triple::x86:
|
||||
return GetRegisterInfo_i386 (m_target_arch);
|
||||
case llvm::Triple::x86_64:
|
||||
return g_register_infos_x86_64;
|
||||
default:
|
||||
assert(false && "Unhandled target architecture.");
|
||||
return NULL;
|
||||
}
|
||||
return m_register_info_p;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
RegisterContextLinux_x86_64::GetRegisterCount () const
|
||||
{
|
||||
return m_register_info_count;
|
||||
}
|
||||
|
|
|
@ -17,13 +17,19 @@ class RegisterContextLinux_x86_64
|
|||
{
|
||||
public:
|
||||
RegisterContextLinux_x86_64(const lldb_private::ArchSpec &target_arch);
|
||||
virtual ~RegisterContextLinux_x86_64();
|
||||
|
||||
size_t
|
||||
GetGPRSize();
|
||||
GetGPRSize() const override;
|
||||
|
||||
const lldb_private::RegisterInfo *
|
||||
GetRegisterInfo();
|
||||
GetRegisterInfo() const override;
|
||||
|
||||
uint32_t
|
||||
GetRegisterCount () const override;
|
||||
|
||||
private:
|
||||
const lldb_private::RegisterInfo *m_register_info_p;
|
||||
uint32_t m_register_info_count;
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -10,6 +10,8 @@
|
|||
#ifndef lldb_RegisterInfoInterface_h
|
||||
#define lldb_RegisterInfoInterface_h
|
||||
|
||||
#include "lldb/Core/ArchSpec.h"
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
|
||||
|
@ -25,12 +27,20 @@ namespace lldb_private
|
|||
virtual ~RegisterInfoInterface () {}
|
||||
|
||||
virtual size_t
|
||||
GetGPRSize () = 0;
|
||||
GetGPRSize () const = 0;
|
||||
|
||||
virtual const lldb_private::RegisterInfo *
|
||||
GetRegisterInfo () = 0;
|
||||
GetRegisterInfo () const = 0;
|
||||
|
||||
virtual uint32_t
|
||||
GetRegisterCount () const = 0;
|
||||
|
||||
const lldb_private::ArchSpec&
|
||||
GetTargetArchitecture() const
|
||||
{ return m_target_arch; }
|
||||
|
||||
public:
|
||||
// FIXME make private.
|
||||
lldb_private::ArchSpec m_target_arch;
|
||||
};
|
||||
|
||||
|
|
|
@ -0,0 +1,292 @@
|
|||
//===-- lldb-x86-register-enums.h -------------------------------*- C++ -*-===//
|
||||
//
|
||||
// The LLVM Compiler Infrastructure
|
||||
//
|
||||
// This file is distributed under the University of Illinois Open Source
|
||||
// License. See LICENSE.TXT for details.
|
||||
//
|
||||
//===----------------------------------------------------------------------===//
|
||||
|
||||
#ifndef lldb_x86_register_enums_h
|
||||
#define lldb_x86_register_enums_h
|
||||
|
||||
namespace lldb_private
|
||||
{
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internal codes for all i386 registers.
|
||||
//---------------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
k_first_gpr_i386,
|
||||
gpr_eax_i386 = k_first_gpr_i386,
|
||||
gpr_ebx_i386,
|
||||
gpr_ecx_i386,
|
||||
gpr_edx_i386,
|
||||
gpr_edi_i386,
|
||||
gpr_esi_i386,
|
||||
gpr_ebp_i386,
|
||||
gpr_esp_i386,
|
||||
gpr_eip_i386,
|
||||
gpr_eflags_i386,
|
||||
gpr_cs_i386,
|
||||
gpr_fs_i386,
|
||||
gpr_gs_i386,
|
||||
gpr_ss_i386,
|
||||
gpr_ds_i386,
|
||||
gpr_es_i386,
|
||||
|
||||
k_first_alias_i386,
|
||||
gpr_ax_i386 = k_first_alias_i386,
|
||||
gpr_bx_i386,
|
||||
gpr_cx_i386,
|
||||
gpr_dx_i386,
|
||||
gpr_di_i386,
|
||||
gpr_si_i386,
|
||||
gpr_bp_i386,
|
||||
gpr_sp_i386,
|
||||
gpr_ah_i386,
|
||||
gpr_bh_i386,
|
||||
gpr_ch_i386,
|
||||
gpr_dh_i386,
|
||||
gpr_al_i386,
|
||||
gpr_bl_i386,
|
||||
gpr_cl_i386,
|
||||
gpr_dl_i386,
|
||||
k_last_alias_i386 = gpr_dl_i386,
|
||||
|
||||
k_last_gpr_i386 = k_last_alias_i386,
|
||||
|
||||
k_first_fpr_i386,
|
||||
fpu_fctrl_i386 = k_first_fpr_i386,
|
||||
fpu_fstat_i386,
|
||||
fpu_ftag_i386,
|
||||
fpu_fop_i386,
|
||||
fpu_fiseg_i386,
|
||||
fpu_fioff_i386,
|
||||
fpu_foseg_i386,
|
||||
fpu_fooff_i386,
|
||||
fpu_mxcsr_i386,
|
||||
fpu_mxcsrmask_i386,
|
||||
fpu_st0_i386,
|
||||
fpu_st1_i386,
|
||||
fpu_st2_i386,
|
||||
fpu_st3_i386,
|
||||
fpu_st4_i386,
|
||||
fpu_st5_i386,
|
||||
fpu_st6_i386,
|
||||
fpu_st7_i386,
|
||||
fpu_mm0_i386,
|
||||
fpu_mm1_i386,
|
||||
fpu_mm2_i386,
|
||||
fpu_mm3_i386,
|
||||
fpu_mm4_i386,
|
||||
fpu_mm5_i386,
|
||||
fpu_mm6_i386,
|
||||
fpu_mm7_i386,
|
||||
fpu_xmm0_i386,
|
||||
fpu_xmm1_i386,
|
||||
fpu_xmm2_i386,
|
||||
fpu_xmm3_i386,
|
||||
fpu_xmm4_i386,
|
||||
fpu_xmm5_i386,
|
||||
fpu_xmm6_i386,
|
||||
fpu_xmm7_i386,
|
||||
k_last_fpr_i386 = fpu_xmm7_i386,
|
||||
|
||||
k_first_avx_i386,
|
||||
fpu_ymm0_i386 = k_first_avx_i386,
|
||||
fpu_ymm1_i386,
|
||||
fpu_ymm2_i386,
|
||||
fpu_ymm3_i386,
|
||||
fpu_ymm4_i386,
|
||||
fpu_ymm5_i386,
|
||||
fpu_ymm6_i386,
|
||||
fpu_ymm7_i386,
|
||||
k_last_avx_i386 = fpu_ymm7_i386,
|
||||
|
||||
dr0_i386,
|
||||
dr1_i386,
|
||||
dr2_i386,
|
||||
dr3_i386,
|
||||
dr4_i386,
|
||||
dr5_i386,
|
||||
dr6_i386,
|
||||
dr7_i386,
|
||||
|
||||
k_num_registers_i386,
|
||||
k_num_gpr_registers_i386 = k_last_gpr_i386 - k_first_gpr_i386 + 1,
|
||||
k_num_fpr_registers_i386 = k_last_fpr_i386 - k_first_fpr_i386 + 1,
|
||||
k_num_avx_registers_i386 = k_last_avx_i386 - k_first_avx_i386 + 1
|
||||
};
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
// Internal codes for all x86_64 registers.
|
||||
//---------------------------------------------------------------------------
|
||||
enum
|
||||
{
|
||||
k_first_gpr_x86_64,
|
||||
gpr_rax_x86_64 = k_first_gpr_x86_64,
|
||||
gpr_rbx_x86_64,
|
||||
gpr_rcx_x86_64,
|
||||
gpr_rdx_x86_64,
|
||||
gpr_rdi_x86_64,
|
||||
gpr_rsi_x86_64,
|
||||
gpr_rbp_x86_64,
|
||||
gpr_rsp_x86_64,
|
||||
gpr_r8_x86_64,
|
||||
gpr_r9_x86_64,
|
||||
gpr_r10_x86_64,
|
||||
gpr_r11_x86_64,
|
||||
gpr_r12_x86_64,
|
||||
gpr_r13_x86_64,
|
||||
gpr_r14_x86_64,
|
||||
gpr_r15_x86_64,
|
||||
gpr_rip_x86_64,
|
||||
gpr_rflags_x86_64,
|
||||
gpr_cs_x86_64,
|
||||
gpr_fs_x86_64,
|
||||
gpr_gs_x86_64,
|
||||
gpr_ss_x86_64,
|
||||
gpr_ds_x86_64,
|
||||
gpr_es_x86_64,
|
||||
|
||||
k_first_alias_x86_64,
|
||||
gpr_eax_x86_64 = k_first_alias_x86_64,
|
||||
gpr_ebx_x86_64,
|
||||
gpr_ecx_x86_64,
|
||||
gpr_edx_x86_64,
|
||||
gpr_edi_x86_64,
|
||||
gpr_esi_x86_64,
|
||||
gpr_ebp_x86_64,
|
||||
gpr_esp_x86_64,
|
||||
gpr_r8d_x86_64, // Low 32 bits of r8
|
||||
gpr_r9d_x86_64, // Low 32 bits of r9
|
||||
gpr_r10d_x86_64, // Low 32 bits of r10
|
||||
gpr_r11d_x86_64, // Low 32 bits of r11
|
||||
gpr_r12d_x86_64, // Low 32 bits of r12
|
||||
gpr_r13d_x86_64, // Low 32 bits of r13
|
||||
gpr_r14d_x86_64, // Low 32 bits of r14
|
||||
gpr_r15d_x86_64, // Low 32 bits of r15
|
||||
gpr_ax_x86_64,
|
||||
gpr_bx_x86_64,
|
||||
gpr_cx_x86_64,
|
||||
gpr_dx_x86_64,
|
||||
gpr_di_x86_64,
|
||||
gpr_si_x86_64,
|
||||
gpr_bp_x86_64,
|
||||
gpr_sp_x86_64,
|
||||
gpr_r8w_x86_64, // Low 16 bits of r8
|
||||
gpr_r9w_x86_64, // Low 16 bits of r9
|
||||
gpr_r10w_x86_64, // Low 16 bits of r10
|
||||
gpr_r11w_x86_64, // Low 16 bits of r11
|
||||
gpr_r12w_x86_64, // Low 16 bits of r12
|
||||
gpr_r13w_x86_64, // Low 16 bits of r13
|
||||
gpr_r14w_x86_64, // Low 16 bits of r14
|
||||
gpr_r15w_x86_64, // Low 16 bits of r15
|
||||
gpr_ah_x86_64,
|
||||
gpr_bh_x86_64,
|
||||
gpr_ch_x86_64,
|
||||
gpr_dh_x86_64,
|
||||
gpr_al_x86_64,
|
||||
gpr_bl_x86_64,
|
||||
gpr_cl_x86_64,
|
||||
gpr_dl_x86_64,
|
||||
gpr_dil_x86_64,
|
||||
gpr_sil_x86_64,
|
||||
gpr_bpl_x86_64,
|
||||
gpr_spl_x86_64,
|
||||
gpr_r8l_x86_64, // Low 8 bits of r8
|
||||
gpr_r9l_x86_64, // Low 8 bits of r9
|
||||
gpr_r10l_x86_64, // Low 8 bits of r10
|
||||
gpr_r11l_x86_64, // Low 8 bits of r11
|
||||
gpr_r12l_x86_64, // Low 8 bits of r12
|
||||
gpr_r13l_x86_64, // Low 8 bits of r13
|
||||
gpr_r14l_x86_64, // Low 8 bits of r14
|
||||
gpr_r15l_x86_64, // Low 8 bits of r15
|
||||
k_last_alias_x86_64 = gpr_r15l_x86_64,
|
||||
|
||||
k_last_gpr_x86_64 = k_last_alias_x86_64,
|
||||
|
||||
k_first_fpr_x86_64,
|
||||
fpu_fctrl_x86_64 = k_first_fpr_x86_64,
|
||||
fpu_fstat_x86_64,
|
||||
fpu_ftag_x86_64,
|
||||
fpu_fop_x86_64,
|
||||
fpu_fiseg_x86_64,
|
||||
fpu_fioff_x86_64,
|
||||
fpu_foseg_x86_64,
|
||||
fpu_fooff_x86_64,
|
||||
fpu_mxcsr_x86_64,
|
||||
fpu_mxcsrmask_x86_64,
|
||||
fpu_st0_x86_64,
|
||||
fpu_st1_x86_64,
|
||||
fpu_st2_x86_64,
|
||||
fpu_st3_x86_64,
|
||||
fpu_st4_x86_64,
|
||||
fpu_st5_x86_64,
|
||||
fpu_st6_x86_64,
|
||||
fpu_st7_x86_64,
|
||||
fpu_mm0_x86_64,
|
||||
fpu_mm1_x86_64,
|
||||
fpu_mm2_x86_64,
|
||||
fpu_mm3_x86_64,
|
||||
fpu_mm4_x86_64,
|
||||
fpu_mm5_x86_64,
|
||||
fpu_mm6_x86_64,
|
||||
fpu_mm7_x86_64,
|
||||
fpu_xmm0_x86_64,
|
||||
fpu_xmm1_x86_64,
|
||||
fpu_xmm2_x86_64,
|
||||
fpu_xmm3_x86_64,
|
||||
fpu_xmm4_x86_64,
|
||||
fpu_xmm5_x86_64,
|
||||
fpu_xmm6_x86_64,
|
||||
fpu_xmm7_x86_64,
|
||||
fpu_xmm8_x86_64,
|
||||
fpu_xmm9_x86_64,
|
||||
fpu_xmm10_x86_64,
|
||||
fpu_xmm11_x86_64,
|
||||
fpu_xmm12_x86_64,
|
||||
fpu_xmm13_x86_64,
|
||||
fpu_xmm14_x86_64,
|
||||
fpu_xmm15_x86_64,
|
||||
k_last_fpr_x86_64 = fpu_xmm15_x86_64,
|
||||
|
||||
k_first_avx_x86_64,
|
||||
fpu_ymm0_x86_64 = k_first_avx_x86_64,
|
||||
fpu_ymm1_x86_64,
|
||||
fpu_ymm2_x86_64,
|
||||
fpu_ymm3_x86_64,
|
||||
fpu_ymm4_x86_64,
|
||||
fpu_ymm5_x86_64,
|
||||
fpu_ymm6_x86_64,
|
||||
fpu_ymm7_x86_64,
|
||||
fpu_ymm8_x86_64,
|
||||
fpu_ymm9_x86_64,
|
||||
fpu_ymm10_x86_64,
|
||||
fpu_ymm11_x86_64,
|
||||
fpu_ymm12_x86_64,
|
||||
fpu_ymm13_x86_64,
|
||||
fpu_ymm14_x86_64,
|
||||
fpu_ymm15_x86_64,
|
||||
k_last_avx_x86_64 = fpu_ymm15_x86_64,
|
||||
|
||||
dr0_x86_64,
|
||||
dr1_x86_64,
|
||||
dr2_x86_64,
|
||||
dr3_x86_64,
|
||||
dr4_x86_64,
|
||||
dr5_x86_64,
|
||||
dr6_x86_64,
|
||||
dr7_x86_64,
|
||||
|
||||
k_num_registers_x86_64,
|
||||
k_num_gpr_registers_x86_64 = k_last_gpr_x86_64 - k_first_gpr_x86_64 + 1,
|
||||
k_num_fpr_registers_x86_64 = k_last_fpr_x86_64 - k_first_fpr_x86_64 + 1,
|
||||
k_num_avx_registers_x86_64 = k_last_avx_x86_64 - k_first_avx_x86_64 + 1
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif // #ifndef lldb_x86_register_enums_h
|
|
@ -132,7 +132,7 @@ public:
|
|||
|
||||
// Returns AUXV structure found in the core file
|
||||
const lldb::DataBufferSP
|
||||
GetAuxvData();
|
||||
GetAuxvData() override;
|
||||
|
||||
protected:
|
||||
void
|
||||
|
|
|
@ -1586,6 +1586,8 @@ GDBRemoteCommunicationClient::GetGDBServerProgramVersion()
|
|||
bool
|
||||
GDBRemoteCommunicationClient::GetHostInfo (bool force)
|
||||
{
|
||||
Log *log (ProcessGDBRemoteLog::GetLogIfAnyCategoryIsSet (GDBR_LOG_PROCESS));
|
||||
|
||||
if (force || m_qHostInfo_is_valid == eLazyBoolCalculate)
|
||||
{
|
||||
m_qHostInfo_is_valid = eLazyBoolNo;
|
||||
|
@ -1819,6 +1821,9 @@ GDBRemoteCommunicationClient::GetHostInfo (bool force)
|
|||
{
|
||||
assert (byte_order == m_host_arch.GetByteOrder());
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf ("GDBRemoteCommunicationClient::%s parsed host architecture as %s, triple as %s from triple text %s", __FUNCTION__, m_host_arch.GetArchitectureName () ? m_host_arch.GetArchitectureName () : "<null-arch-name>", m_host_arch.GetTriple ().getTriple ().c_str(), triple.c_str ());
|
||||
}
|
||||
if (!distribution_id.empty ())
|
||||
m_host_arch.SetDistributionId (distribution_id.c_str ());
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -14,16 +14,23 @@
|
|||
// C++ Includes
|
||||
#include <vector>
|
||||
#include <set>
|
||||
#include <unordered_map>
|
||||
// Other libraries and framework includes
|
||||
// Project includes
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "lldb/Core/Communication.h"
|
||||
#include "lldb/Host/Mutex.h"
|
||||
#include "lldb/Target/Process.h"
|
||||
#include "GDBRemoteCommunication.h"
|
||||
|
||||
#include "../../../Host/common/NativeProcessProtocol.h"
|
||||
|
||||
class ProcessGDBRemote;
|
||||
class StringExtractorGDBRemote;
|
||||
|
||||
class GDBRemoteCommunicationServer : public GDBRemoteCommunication
|
||||
class GDBRemoteCommunicationServer :
|
||||
public GDBRemoteCommunication,
|
||||
public lldb_private::NativeProcessProtocol::NativeDelegate
|
||||
{
|
||||
public:
|
||||
typedef std::map<uint16_t, lldb::pid_t> PortMap;
|
||||
|
@ -38,12 +45,13 @@ public:
|
|||
GDBRemoteCommunicationServer(bool is_platform);
|
||||
|
||||
GDBRemoteCommunicationServer(bool is_platform,
|
||||
const lldb::PlatformSP& platform_sp);
|
||||
const lldb::PlatformSP& platform_sp,
|
||||
lldb::DebuggerSP& debugger_sp);
|
||||
|
||||
virtual
|
||||
~GDBRemoteCommunicationServer();
|
||||
|
||||
bool
|
||||
PacketResult
|
||||
GetPacketAndSendResponse (uint32_t timeout_usec,
|
||||
lldb_private::Error &error,
|
||||
bool &interrupt,
|
||||
|
@ -188,6 +196,28 @@ public:
|
|||
lldb_private::Error
|
||||
LaunchProcess ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
/// Attach to a process.
|
||||
///
|
||||
/// This method supports attaching llgs to a process accessible via the
|
||||
/// configured Platform.
|
||||
///
|
||||
/// @return
|
||||
/// An Error object indicating the success or failure of the
|
||||
/// attach operation.
|
||||
//------------------------------------------------------------------
|
||||
lldb_private::Error
|
||||
AttachToProcess (lldb::pid_t pid);
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// NativeProcessProtocol::NativeDelegate overrides
|
||||
//------------------------------------------------------------------
|
||||
void
|
||||
InitializeDelegate (lldb_private::NativeProcessProtocol *process) override;
|
||||
|
||||
void
|
||||
ProcessStateChanged (lldb_private::NativeProcessProtocol *process, lldb::StateType state) override;
|
||||
|
||||
protected:
|
||||
lldb::PlatformSP m_platform_sp;
|
||||
lldb::thread_t m_async_thread;
|
||||
|
@ -199,7 +229,20 @@ protected:
|
|||
uint32_t m_proc_infos_index;
|
||||
PortMap m_port_map;
|
||||
uint16_t m_port_offset;
|
||||
|
||||
lldb::tid_t m_current_tid;
|
||||
lldb::tid_t m_continue_tid;
|
||||
lldb_private::Mutex m_debugged_process_mutex;
|
||||
lldb_private::NativeProcessProtocolSP m_debugged_process_sp;
|
||||
lldb::DebuggerSP m_debugger_sp;
|
||||
Communication m_stdio_communication;
|
||||
bool m_exit_now; // use in asynchronous handling to indicate process should exit.
|
||||
lldb::StateType m_inferior_prev_state;
|
||||
bool m_thread_suffix_supported;
|
||||
bool m_list_threads_in_stop_reply;
|
||||
lldb::DataBufferSP m_active_auxv_buffer_sp;
|
||||
lldb_private::Mutex m_saved_registers_mutex;
|
||||
std::unordered_map<uint32_t, lldb::DataBufferSP> m_saved_registers_map;
|
||||
uint32_t m_next_saved_registers_id;
|
||||
|
||||
PacketResult
|
||||
SendUnimplementedResponse (const char *packet);
|
||||
|
@ -207,9 +250,24 @@ protected:
|
|||
PacketResult
|
||||
SendErrorResponse (uint8_t error);
|
||||
|
||||
PacketResult
|
||||
SendIllFormedResponse (const StringExtractorGDBRemote &packet, const char *error_message);
|
||||
|
||||
PacketResult
|
||||
SendOKResponse ();
|
||||
|
||||
PacketResult
|
||||
SendONotification (const char *buffer, uint32_t len);
|
||||
|
||||
PacketResult
|
||||
SendWResponse (lldb_private::NativeProcessProtocol *process);
|
||||
|
||||
PacketResult
|
||||
SendStopReplyPacketForThread (lldb::tid_t tid);
|
||||
|
||||
PacketResult
|
||||
SendStopReasonForState (lldb::StateType process_state, bool flush_on_exit);
|
||||
|
||||
PacketResult
|
||||
Handle_A (StringExtractorGDBRemote &packet);
|
||||
|
||||
|
@ -233,7 +291,10 @@ protected:
|
|||
|
||||
PacketResult
|
||||
Handle_qPlatform_chmod (StringExtractorGDBRemote &packet);
|
||||
|
||||
|
||||
PacketResult
|
||||
Handle_qProcessInfo (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qProcessInfoPID (StringExtractorGDBRemote &packet);
|
||||
|
||||
|
@ -284,7 +345,22 @@ protected:
|
|||
|
||||
PacketResult
|
||||
Handle_QSetSTDERR (StringExtractorGDBRemote &packet);
|
||||
|
||||
|
||||
PacketResult
|
||||
Handle_C (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_c (StringExtractorGDBRemote &packet, bool skip_file_pos_adjustment = false);
|
||||
|
||||
PacketResult
|
||||
Handle_vCont (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_vCont_actions (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_stop_reason (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_vFile_Open (StringExtractorGDBRemote &packet);
|
||||
|
||||
|
@ -321,6 +397,84 @@ protected:
|
|||
PacketResult
|
||||
Handle_qPlatform_shell (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qRegisterInfo (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qfThreadInfo (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qsThreadInfo (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_p (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_P (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_H (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_interrupt (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_m (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_M (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qMemoryRegionInfoSupported (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qMemoryRegionInfo (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_Z (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_z (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_s (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qSupported (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_QThreadSuffixSupported (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_QListThreadsInStopReply (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_qXfer_auxv_read (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_QSaveRegisterState (StringExtractorGDBRemote &packet);
|
||||
|
||||
PacketResult
|
||||
Handle_QRestoreRegisterState (StringExtractorGDBRemote &packet);
|
||||
|
||||
void
|
||||
SetCurrentThreadID (lldb::tid_t tid);
|
||||
|
||||
lldb::tid_t
|
||||
GetCurrentThreadID () const;
|
||||
|
||||
void
|
||||
SetContinueThreadID (lldb::tid_t tid);
|
||||
|
||||
lldb::tid_t
|
||||
GetContinueThreadID () const { return m_continue_tid; }
|
||||
|
||||
lldb_private::Error
|
||||
SetSTDIOFileDescriptor (int fd);
|
||||
|
||||
static void
|
||||
STDIOReadThreadBytesReceived (void *baton, const void *src, size_t src_len);
|
||||
|
||||
private:
|
||||
bool
|
||||
DebugserverProcessReaped (lldb::pid_t pid);
|
||||
|
@ -345,6 +499,38 @@ private:
|
|||
bool
|
||||
KillSpawnedProcess (lldb::pid_t pid);
|
||||
|
||||
bool
|
||||
IsGdbServer ()
|
||||
{
|
||||
return !m_is_platform;
|
||||
}
|
||||
|
||||
/// Launch a process from lldb-gdbserver
|
||||
lldb_private::Error
|
||||
LaunchDebugServerProcess ();
|
||||
|
||||
/// Launch a process from lldb-platform
|
||||
lldb_private::Error
|
||||
LaunchPlatformProcess ();
|
||||
|
||||
void
|
||||
HandleInferiorState_Exited (lldb_private::NativeProcessProtocol *process);
|
||||
|
||||
void
|
||||
HandleInferiorState_Stopped (lldb_private::NativeProcessProtocol *process);
|
||||
|
||||
void
|
||||
FlushInferiorOutput ();
|
||||
|
||||
lldb_private::NativeThreadProtocolSP
|
||||
GetThreadFromSuffix (StringExtractorGDBRemote &packet);
|
||||
|
||||
uint32_t
|
||||
GetNextSavedRegistersID ();
|
||||
|
||||
void
|
||||
MaybeCloseInferiorTerminalConnection ();
|
||||
|
||||
//------------------------------------------------------------------
|
||||
// For GDBRemoteCommunicationServer only
|
||||
//------------------------------------------------------------------
|
||||
|
|
|
@ -61,7 +61,9 @@
|
|||
|
||||
// Project includes
|
||||
#include "lldb/Host/Host.h"
|
||||
#include "Plugins/Process/Utility/FreeBSDSignals.h"
|
||||
#include "Plugins/Process/Utility/InferiorCallPOSIX.h"
|
||||
#include "Plugins/Process/Utility/LinuxSignals.h"
|
||||
#include "Plugins/Process/Utility/StopInfoMachException.h"
|
||||
#include "Plugins/Platform/MacOSX/PlatformRemoteiOS.h"
|
||||
#include "Utility/StringExtractorGDBRemote.h"
|
||||
|
@ -285,7 +287,8 @@ ProcessGDBRemote::ProcessGDBRemote(Target& target, Listener &listener) :
|
|||
m_waiting_for_attach (false),
|
||||
m_destroy_tried_resuming (false),
|
||||
m_command_sp (),
|
||||
m_breakpoint_pc_offset (0)
|
||||
m_breakpoint_pc_offset (0),
|
||||
m_unix_signals_sp (new UnixSignals ())
|
||||
{
|
||||
m_async_broadcaster.SetEventName (eBroadcastBitAsyncThreadShouldExit, "async thread should exit");
|
||||
m_async_broadcaster.SetEventName (eBroadcastBitAsyncContinue, "async thread continue");
|
||||
|
@ -628,6 +631,7 @@ ProcessGDBRemote::WillAttachToProcessWithName (const char *process_name, bool wa
|
|||
Error
|
||||
ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
|
||||
{
|
||||
Log *log (ProcessGDBRemoteLog::GetLogIfAllCategoriesSet (GDBR_LOG_PROCESS));
|
||||
Error error (WillLaunchOrAttach ());
|
||||
|
||||
if (error.Fail())
|
||||
|
@ -678,7 +682,11 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
|
|||
error.SetErrorStringWithFormat ("Process %" PRIu64 " was reported after connecting to '%s', but no stop reply packet was received", pid, remote_url);
|
||||
}
|
||||
|
||||
if (error.Success()
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalizing target architecture initial triple: %s (GetTarget().GetArchitecture().IsValid() %s, m_gdb_comm.GetHostArchitecture().IsValid(): %s)", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str (), GetTarget ().GetArchitecture ().IsValid () ? "true" : "false", m_gdb_comm.GetHostArchitecture ().IsValid () ? "true" : "false");
|
||||
|
||||
|
||||
if (error.Success()
|
||||
&& !GetTarget().GetArchitecture().IsValid()
|
||||
&& m_gdb_comm.GetHostArchitecture().IsValid())
|
||||
{
|
||||
|
@ -689,6 +697,42 @@ ProcessGDBRemote::DoConnectRemote (Stream *strm, const char *remote_url)
|
|||
GetTarget().SetArchitecture(m_gdb_comm.GetHostArchitecture());
|
||||
}
|
||||
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": normalized target architecture triple: %s", __FUNCTION__, GetID (), GetTarget ().GetArchitecture ().GetTriple ().getTriple ().c_str ());
|
||||
|
||||
// Set the Unix signals properly for the target.
|
||||
// FIXME Add a gdb-remote packet to discover dynamically.
|
||||
if (error.Success ())
|
||||
{
|
||||
const ArchSpec arch_spec = GetTarget ().GetArchitecture ();
|
||||
if (arch_spec.IsValid ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::%s pid %" PRIu64 ": determining unix signals type based on architecture %s, triple %s", __FUNCTION__, GetID (), arch_spec.GetArchitectureName () ? arch_spec.GetArchitectureName () : "<null>", arch_spec.GetTriple ().getTriple ().c_str ());
|
||||
|
||||
switch (arch_spec.GetTriple ().getOS ())
|
||||
{
|
||||
case llvm::Triple::Linux:
|
||||
m_unix_signals_sp.reset (new process_linux::LinuxSignals ());
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::%s using Linux unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
|
||||
break;
|
||||
case llvm::Triple::OpenBSD:
|
||||
case llvm::Triple::FreeBSD:
|
||||
case llvm::Triple::NetBSD:
|
||||
m_unix_signals_sp.reset (new FreeBSDSignals ());
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::%s using *BSD unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
|
||||
break;
|
||||
default:
|
||||
m_unix_signals_sp.reset (new UnixSignals ());
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::%s using generic unix signals type for pid %" PRIu64, __FUNCTION__, GetID ());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
|
@ -1040,6 +1084,13 @@ ProcessGDBRemote::DidLaunch ()
|
|||
DidLaunchOrAttach ();
|
||||
}
|
||||
|
||||
UnixSignals&
|
||||
ProcessGDBRemote::GetUnixSignals ()
|
||||
{
|
||||
assert (m_unix_signals_sp && "m_unix_signals_sp is null");
|
||||
return *m_unix_signals_sp;
|
||||
}
|
||||
|
||||
Error
|
||||
ProcessGDBRemote::DoAttachToProcessWithID (lldb::pid_t attach_pid)
|
||||
{
|
||||
|
@ -2231,6 +2282,7 @@ ProcessGDBRemote::DoWriteMemory (addr_t addr, const void *buf, size_t size, Erro
|
|||
lldb::addr_t
|
||||
ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &error)
|
||||
{
|
||||
lldb_private::Log *log (lldb_private::GetLogIfAnyCategoriesSet (LIBLLDB_LOG_PROCESS|LIBLLDB_LOG_EXPRESSIONS));
|
||||
addr_t allocated_addr = LLDB_INVALID_ADDRESS;
|
||||
|
||||
LazyBool supported = m_gdb_comm.SupportsAllocDeallocMemory();
|
||||
|
@ -2256,7 +2308,11 @@ ProcessGDBRemote::DoAllocateMemory (size_t size, uint32_t permissions, Error &er
|
|||
eMmapFlagsAnon | eMmapFlagsPrivate, -1, 0))
|
||||
m_addr_to_mmap_size[allocated_addr] = size;
|
||||
else
|
||||
{
|
||||
allocated_addr = LLDB_INVALID_ADDRESS;
|
||||
if (log)
|
||||
log->Printf ("ProcessGDBRemote::%s no direct stub support for memory allocation, and InferiorCallMmap also failed - is stub missing register context save/restore capability?", __FUNCTION__);
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
|
@ -91,6 +91,9 @@ public:
|
|||
virtual void
|
||||
DidLaunch ();
|
||||
|
||||
lldb_private::UnixSignals&
|
||||
GetUnixSignals () override;
|
||||
|
||||
virtual lldb_private::Error
|
||||
WillAttachToProcessWithID (lldb::pid_t pid);
|
||||
|
||||
|
@ -305,8 +308,8 @@ protected:
|
|||
bool
|
||||
ParseRegisters(lldb_private::ScriptInterpreterObject *registers_array);
|
||||
|
||||
virtual const lldb::DataBufferSP
|
||||
GetAuxvData();
|
||||
const lldb::DataBufferSP
|
||||
GetAuxvData() override;
|
||||
|
||||
lldb_private::StructuredData::ObjectSP
|
||||
GetExtendedInfoForThread (lldb::tid_t tid);
|
||||
|
@ -357,7 +360,9 @@ protected:
|
|||
bool m_destroy_tried_resuming;
|
||||
lldb::CommandObjectSP m_command_sp;
|
||||
int64_t m_breakpoint_pc_offset;
|
||||
|
||||
std::shared_ptr<lldb_private::UnixSignals> m_unix_signals_sp;
|
||||
|
||||
|
||||
bool
|
||||
StartAsyncThread ();
|
||||
|
||||
|
|
|
@ -10,6 +10,8 @@ add_lldb_library(lldbTarget
|
|||
JITLoaderList.cpp
|
||||
LanguageRuntime.cpp
|
||||
Memory.cpp
|
||||
NativeRegisterContext.cpp
|
||||
NativeRegisterContextRegisterInfo.cpp
|
||||
ObjCLanguageRuntime.cpp
|
||||
OperatingSystem.cpp
|
||||
PathMappingList.cpp
|
||||
|
|
|
@ -0,0 +1,470 @@
|
|||
//===-- NativeRegisterContext.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/Target/NativeRegisterContext.h"
|
||||
|
||||
#include "lldb/Core/Log.h"
|
||||
#include "lldb/Core/RegisterValue.h"
|
||||
|
||||
#include "lldb/lldb-private-log.h"
|
||||
|
||||
#include "Host/common/NativeProcessProtocol.h"
|
||||
#include "Host/common/NativeThreadProtocol.h"
|
||||
|
||||
using namespace lldb;
|
||||
using namespace lldb_private;
|
||||
|
||||
NativeRegisterContext::NativeRegisterContext (NativeThreadProtocol &thread, uint32_t concrete_frame_idx) :
|
||||
m_thread (thread),
|
||||
m_concrete_frame_idx (concrete_frame_idx)
|
||||
{
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Destructor
|
||||
//----------------------------------------------------------------------
|
||||
NativeRegisterContext::~NativeRegisterContext()
|
||||
{
|
||||
}
|
||||
|
||||
// FIXME revisit invalidation, process stop ids, etc. Right now we don't
|
||||
// support caching in NativeRegisterContext. We can do this later by
|
||||
// utilizing NativeProcessProtocol::GetStopID () and adding a stop id to
|
||||
// NativeRegisterContext.
|
||||
|
||||
// void
|
||||
// NativeRegisterContext::InvalidateIfNeeded (bool force)
|
||||
// {
|
||||
// ProcessSP process_sp (m_thread.GetProcess());
|
||||
// bool invalidate = force;
|
||||
// uint32_t process_stop_id = UINT32_MAX;
|
||||
|
||||
// if (process_sp)
|
||||
// process_stop_id = process_sp->GetStopID();
|
||||
// else
|
||||
// invalidate = true;
|
||||
|
||||
// if (!invalidate)
|
||||
// invalidate = process_stop_id != GetStopID();
|
||||
|
||||
// if (invalidate)
|
||||
// {
|
||||
// InvalidateAllRegisters ();
|
||||
// SetStopID (process_stop_id);
|
||||
// }
|
||||
// }
|
||||
|
||||
|
||||
const RegisterInfo *
|
||||
NativeRegisterContext::GetRegisterInfoByName (const char *reg_name, uint32_t start_idx)
|
||||
{
|
||||
if (reg_name && reg_name[0])
|
||||
{
|
||||
const uint32_t num_registers = GetRegisterCount();
|
||||
for (uint32_t reg = start_idx; reg < num_registers; ++reg)
|
||||
{
|
||||
const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
|
||||
|
||||
if ((reg_info->name != nullptr && ::strcasecmp (reg_info->name, reg_name) == 0) ||
|
||||
(reg_info->alt_name != nullptr && ::strcasecmp (reg_info->alt_name, reg_name) == 0))
|
||||
{
|
||||
return reg_info;
|
||||
}
|
||||
}
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
NativeRegisterContext::GetRegisterInfo (uint32_t kind, uint32_t num)
|
||||
{
|
||||
const uint32_t reg_num = ConvertRegisterKindToRegisterNumber(kind, num);
|
||||
if (reg_num == LLDB_INVALID_REGNUM)
|
||||
return nullptr;
|
||||
return GetRegisterInfoAtIndex (reg_num);
|
||||
}
|
||||
|
||||
const char *
|
||||
NativeRegisterContext::GetRegisterName (uint32_t reg)
|
||||
{
|
||||
const RegisterInfo * reg_info = GetRegisterInfoAtIndex(reg);
|
||||
if (reg_info)
|
||||
return reg_info->name;
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const char*
|
||||
NativeRegisterContext::GetRegisterSetNameForRegisterAtIndex (uint32_t reg_index) const
|
||||
{
|
||||
const RegisterInfo *const reg_info = GetRegisterInfoAtIndex(reg_index);
|
||||
if (!reg_info)
|
||||
return nullptr;
|
||||
|
||||
for (uint32_t set_index = 0; set_index < GetRegisterSetCount (); ++set_index)
|
||||
{
|
||||
const RegisterSet *const reg_set = GetRegisterSet (set_index);
|
||||
if (!reg_set)
|
||||
continue;
|
||||
|
||||
for (uint32_t reg_num_index = 0; reg_num_index < reg_set->num_registers; ++reg_num_index)
|
||||
{
|
||||
const uint32_t reg_num = reg_set->registers[reg_num_index];
|
||||
// FIXME double check we're checking the right register kind here.
|
||||
if (reg_info->kinds[RegisterKind::eRegisterKindLLDB] == reg_num)
|
||||
{
|
||||
// The given register is a member of this register set. Return the register set name.
|
||||
return reg_set->name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Didn't find it.
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
NativeRegisterContext::GetPC (lldb::addr_t fail_value)
|
||||
{
|
||||
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
|
||||
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
|
||||
if (log)
|
||||
log->Printf ("NativeRegisterContext::%s using reg index %" PRIu32 " (default %" PRIu64 ")", __FUNCTION__, reg, fail_value);
|
||||
|
||||
const uint64_t retval = ReadRegisterAsUnsigned (reg, fail_value);
|
||||
|
||||
if (log)
|
||||
log->Printf ("NativeRegisterContext::%s " PRIu32 " retval %" PRIu64, __FUNCTION__, retval);
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContext::SetPC (lldb::addr_t pc)
|
||||
{
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_PC);
|
||||
return WriteRegisterFromUnsigned (reg, pc);
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
NativeRegisterContext::GetSP (lldb::addr_t fail_value)
|
||||
{
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
|
||||
return ReadRegisterAsUnsigned (reg, fail_value);
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContext::SetSP (lldb::addr_t sp)
|
||||
{
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_SP);
|
||||
return WriteRegisterFromUnsigned (reg, sp);
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
NativeRegisterContext::GetFP (lldb::addr_t fail_value)
|
||||
{
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
|
||||
return ReadRegisterAsUnsigned (reg, fail_value);
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContext::SetFP (lldb::addr_t fp)
|
||||
{
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FP);
|
||||
return WriteRegisterFromUnsigned (reg, fp);
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
NativeRegisterContext::GetReturnAddress (lldb::addr_t fail_value)
|
||||
{
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_RA);
|
||||
return ReadRegisterAsUnsigned (reg, fail_value);
|
||||
}
|
||||
|
||||
lldb::addr_t
|
||||
NativeRegisterContext::GetFlags (lldb::addr_t fail_value)
|
||||
{
|
||||
uint32_t reg = ConvertRegisterKindToRegisterNumber (eRegisterKindGeneric, LLDB_REGNUM_GENERIC_FLAGS);
|
||||
return ReadRegisterAsUnsigned (reg, fail_value);
|
||||
}
|
||||
|
||||
|
||||
lldb::addr_t
|
||||
NativeRegisterContext::ReadRegisterAsUnsigned (uint32_t reg, lldb::addr_t fail_value)
|
||||
{
|
||||
if (reg != LLDB_INVALID_REGNUM)
|
||||
return ReadRegisterAsUnsigned (GetRegisterInfoAtIndex (reg), fail_value);
|
||||
return fail_value;
|
||||
}
|
||||
|
||||
uint64_t
|
||||
NativeRegisterContext::ReadRegisterAsUnsigned (const RegisterInfo *reg_info, lldb::addr_t fail_value)
|
||||
{
|
||||
Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_THREAD));
|
||||
|
||||
if (reg_info)
|
||||
{
|
||||
RegisterValue value;
|
||||
Error error = ReadRegister (reg_info, value);
|
||||
if (error.Success ())
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeRegisterContext::%s ReadRegister() succeeded, value %" PRIu64, __FUNCTION__, value.GetAsUInt64());
|
||||
return value.GetAsUInt64();
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeRegisterContext::%s ReadRegister() failed, error %s", __FUNCTION__, error.AsCString ());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (log)
|
||||
log->Printf ("NativeRegisterContext::%s ReadRegister() null reg_info", __FUNCTION__);
|
||||
}
|
||||
return fail_value;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContext::WriteRegisterFromUnsigned (uint32_t reg, uint64_t uval)
|
||||
{
|
||||
if (reg == LLDB_INVALID_REGNUM)
|
||||
return Error ("NativeRegisterContext::%s (): reg is invalid", __FUNCTION__);
|
||||
return WriteRegisterFromUnsigned (GetRegisterInfoAtIndex (reg), uval);
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContext::WriteRegisterFromUnsigned (const RegisterInfo *reg_info, uint64_t uval)
|
||||
{
|
||||
assert (reg_info);
|
||||
if (!reg_info)
|
||||
return Error ("reg_info is nullptr");
|
||||
|
||||
RegisterValue value;
|
||||
if (!value.SetUInt(uval, reg_info->byte_size))
|
||||
return Error ("RegisterValue::SetUInt () failed");
|
||||
|
||||
return WriteRegister (reg_info, value);
|
||||
}
|
||||
|
||||
lldb::tid_t
|
||||
NativeRegisterContext::GetThreadID() const
|
||||
{
|
||||
return m_thread.GetID();
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeRegisterContext::NumSupportedHardwareBreakpoints ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeRegisterContext::SetHardwareBreakpoint (lldb::addr_t addr, size_t size)
|
||||
{
|
||||
return LLDB_INVALID_INDEX32;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeRegisterContext::ClearHardwareBreakpoint (uint32_t hw_idx)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
uint32_t
|
||||
NativeRegisterContext::NumSupportedHardwareWatchpoints ()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeRegisterContext::SetHardwareWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags)
|
||||
{
|
||||
return LLDB_INVALID_INDEX32;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeRegisterContext::ClearHardwareWatchpoint (uint32_t hw_index)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
bool
|
||||
NativeRegisterContext::HardwareSingleStep (bool enable)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContext::ReadRegisterValueFromMemory (
|
||||
const RegisterInfo *reg_info,
|
||||
lldb::addr_t src_addr,
|
||||
lldb::addr_t src_len,
|
||||
RegisterValue ®_value)
|
||||
{
|
||||
Error error;
|
||||
if (reg_info == nullptr)
|
||||
{
|
||||
error.SetErrorString ("invalid register info argument.");
|
||||
return error;
|
||||
}
|
||||
|
||||
|
||||
// Moving from addr into a register
|
||||
//
|
||||
// Case 1: src_len == dst_len
|
||||
//
|
||||
// |AABBCCDD| Address contents
|
||||
// |AABBCCDD| Register contents
|
||||
//
|
||||
// Case 2: src_len > dst_len
|
||||
//
|
||||
// Error! (The register should always be big enough to hold the data)
|
||||
//
|
||||
// Case 3: src_len < dst_len
|
||||
//
|
||||
// |AABB| Address contents
|
||||
// |AABB0000| Register contents [on little-endian hardware]
|
||||
// |0000AABB| Register contents [on big-endian hardware]
|
||||
if (src_len > RegisterValue::kMaxRegisterByteSize)
|
||||
{
|
||||
error.SetErrorString ("register too small to receive memory data");
|
||||
return error;
|
||||
}
|
||||
|
||||
const lldb::addr_t dst_len = reg_info->byte_size;
|
||||
|
||||
if (src_len > dst_len)
|
||||
{
|
||||
error.SetErrorStringWithFormat("%" PRIu64 " bytes is too big to store in register %s (%" PRIu64 " bytes)", src_len, reg_info->name, dst_len);
|
||||
return error;
|
||||
}
|
||||
|
||||
NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
|
||||
if (!process_sp)
|
||||
{
|
||||
error.SetErrorString("invalid process");
|
||||
return error;
|
||||
}
|
||||
|
||||
uint8_t src[RegisterValue::kMaxRegisterByteSize];
|
||||
|
||||
// Read the memory
|
||||
lldb::addr_t bytes_read;
|
||||
error = process_sp->ReadMemory (src_addr, src, src_len, bytes_read);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
// Make sure the memory read succeeded...
|
||||
if (bytes_read != src_len)
|
||||
{
|
||||
// This might happen if we read _some_ bytes but not all
|
||||
error.SetErrorStringWithFormat("read %" PRIu64 " of %" PRIu64 " bytes", bytes_read, src_len);
|
||||
return error;
|
||||
}
|
||||
|
||||
// We now have a memory buffer that contains the part or all of the register
|
||||
// value. Set the register value using this memory data.
|
||||
// TODO: we might need to add a parameter to this function in case the byte
|
||||
// order of the memory data doesn't match the process. For now we are assuming
|
||||
// they are the same.
|
||||
lldb::ByteOrder byte_order;
|
||||
if (!process_sp->GetByteOrder (byte_order))
|
||||
{
|
||||
error.SetErrorString ( "NativeProcessProtocol::GetByteOrder () failed");
|
||||
return error;
|
||||
}
|
||||
|
||||
reg_value.SetFromMemoryData (
|
||||
reg_info,
|
||||
src,
|
||||
src_len,
|
||||
byte_order,
|
||||
error);
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
Error
|
||||
NativeRegisterContext::WriteRegisterValueToMemory (
|
||||
const RegisterInfo *reg_info,
|
||||
lldb::addr_t dst_addr,
|
||||
lldb::addr_t dst_len,
|
||||
const RegisterValue ®_value)
|
||||
{
|
||||
|
||||
uint8_t dst[RegisterValue::kMaxRegisterByteSize];
|
||||
|
||||
Error error;
|
||||
|
||||
NativeProcessProtocolSP process_sp (m_thread.GetProcess ());
|
||||
if (process_sp)
|
||||
{
|
||||
|
||||
// TODO: we might need to add a parameter to this function in case the byte
|
||||
// order of the memory data doesn't match the process. For now we are assuming
|
||||
// they are the same.
|
||||
lldb::ByteOrder byte_order;
|
||||
if (!process_sp->GetByteOrder (byte_order))
|
||||
return Error ("NativeProcessProtocol::GetByteOrder () failed");
|
||||
|
||||
const lldb::addr_t bytes_copied = reg_value.GetAsMemoryData (
|
||||
reg_info,
|
||||
dst,
|
||||
dst_len,
|
||||
byte_order,
|
||||
error);
|
||||
|
||||
if (error.Success())
|
||||
{
|
||||
if (bytes_copied == 0)
|
||||
{
|
||||
error.SetErrorString("byte copy failed.");
|
||||
}
|
||||
else
|
||||
{
|
||||
lldb::addr_t bytes_written;
|
||||
error = process_sp->WriteMemory (dst_addr, dst, bytes_copied, bytes_written);
|
||||
if (error.Fail ())
|
||||
return error;
|
||||
|
||||
if (bytes_written != bytes_copied)
|
||||
{
|
||||
// This might happen if we read _some_ bytes but not all
|
||||
error.SetErrorStringWithFormat("only wrote %" PRIu64 " of %" PRIu64 " bytes", bytes_written, bytes_copied);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
error.SetErrorString("invalid process");
|
||||
|
||||
return error;
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeRegisterContext::ConvertRegisterKindToRegisterNumber (uint32_t kind, uint32_t num) const
|
||||
{
|
||||
const uint32_t num_regs = GetRegisterCount();
|
||||
|
||||
assert (kind < kNumRegisterKinds);
|
||||
for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
|
||||
{
|
||||
const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
|
||||
|
||||
if (reg_info->kinds[kind] == num)
|
||||
return reg_idx;
|
||||
}
|
||||
|
||||
return LLDB_INVALID_REGNUM;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,44 @@
|
|||
//===-- NativeRegisterContex.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/lldb-types.h"
|
||||
#include "lldb/lldb-private-forward.h"
|
||||
#include "lldb/Target/NativeRegisterContextRegisterInfo.h"
|
||||
|
||||
using namespace lldb_private;
|
||||
|
||||
NativeRegisterContextRegisterInfo::NativeRegisterContextRegisterInfo (NativeThreadProtocol &thread,
|
||||
uint32_t concrete_frame_idx,
|
||||
RegisterInfoInterface *register_info_interface) :
|
||||
NativeRegisterContext (thread, concrete_frame_idx),
|
||||
m_register_info_interface_up (register_info_interface)
|
||||
{
|
||||
assert (register_info_interface && "null register_info_interface");
|
||||
}
|
||||
|
||||
uint32_t
|
||||
NativeRegisterContextRegisterInfo::GetRegisterCount () const
|
||||
{
|
||||
return m_register_info_interface_up->GetRegisterCount ();
|
||||
}
|
||||
|
||||
const RegisterInfo *
|
||||
NativeRegisterContextRegisterInfo::GetRegisterInfoAtIndex (uint32_t reg_index) const
|
||||
{
|
||||
if (reg_index <= GetRegisterCount ())
|
||||
return m_register_info_interface_up->GetRegisterInfo () + reg_index;
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
const RegisterInfoInterface&
|
||||
NativeRegisterContextRegisterInfo::GetRegisterInfoInterface () const
|
||||
{
|
||||
return *m_register_info_interface_up;
|
||||
}
|
|
@ -527,12 +527,10 @@ RecurseCopy_Callback (void *baton,
|
|||
case FileSpec::eFileTypeInvalid:
|
||||
case FileSpec::eFileTypeOther:
|
||||
case FileSpec::eFileTypeUnknown:
|
||||
default:
|
||||
rc_baton->error.SetErrorStringWithFormat("invalid file detected during copy: %s", src.GetPath().c_str());
|
||||
return FileSpec::eEnumerateDirectoryResultQuit; // got an error, bail out
|
||||
break;
|
||||
default:
|
||||
return FileSpec::eEnumerateDirectoryResultQuit; // unsupported file type, bail out
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1189,6 +1187,27 @@ Platform::CalculateMD5 (const FileSpec& file_spec,
|
|||
return false;
|
||||
}
|
||||
|
||||
Error
|
||||
Platform::LaunchNativeProcess (
|
||||
ProcessLaunchInfo &launch_info,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp)
|
||||
{
|
||||
// Platforms should override this implementation if they want to
|
||||
// support lldb-gdbserver.
|
||||
return Error("unimplemented");
|
||||
}
|
||||
|
||||
Error
|
||||
Platform::AttachNativeProcess (lldb::pid_t pid,
|
||||
lldb_private::NativeProcessProtocol::NativeDelegate &native_delegate,
|
||||
NativeProcessProtocolSP &process_sp)
|
||||
{
|
||||
// Platforms should override this implementation if they want to
|
||||
// support lldb-gdbserver.
|
||||
return Error("unimplemented");
|
||||
}
|
||||
|
||||
void
|
||||
Platform::SetLocalCacheDirectory (const char* local)
|
||||
{
|
||||
|
|
|
@ -2529,6 +2529,7 @@ Process::CanJIT ()
|
|||
{
|
||||
if (m_can_jit == eCanJITDontKnow)
|
||||
{
|
||||
Log *log(lldb_private::GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS));
|
||||
Error err;
|
||||
|
||||
uint64_t allocated_memory = AllocateMemory(8,
|
||||
|
@ -2536,9 +2537,17 @@ Process::CanJIT ()
|
|||
err);
|
||||
|
||||
if (err.Success())
|
||||
{
|
||||
m_can_jit = eCanJITYes;
|
||||
if (log)
|
||||
log->Printf ("Process::%s pid %" PRIu64 " allocation test passed, CanJIT () is true", __FUNCTION__, GetID ());
|
||||
}
|
||||
else
|
||||
{
|
||||
m_can_jit = eCanJITNo;
|
||||
if (log)
|
||||
log->Printf ("Process::%s pid %" PRIu64 " allocation test failed, CanJIT () is false: %s", __FUNCTION__, GetID (), err.AsCString ());
|
||||
}
|
||||
|
||||
DeallocateMemory (allocated_memory);
|
||||
}
|
||||
|
@ -2788,6 +2797,12 @@ Process::GetDynamicLoader ()
|
|||
return m_dyld_ap.get();
|
||||
}
|
||||
|
||||
const lldb::DataBufferSP
|
||||
Process::GetAuxvData()
|
||||
{
|
||||
return DataBufferSP ();
|
||||
}
|
||||
|
||||
JITLoaderList &
|
||||
Process::GetJITLoaders ()
|
||||
{
|
||||
|
|
|
@ -418,6 +418,18 @@ StringExtractor::GetHexByteString (std::string &str)
|
|||
return str.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
StringExtractor::GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length)
|
||||
{
|
||||
str.clear();
|
||||
|
||||
uint32_t nibble_count = 0;
|
||||
for (const char *pch = Peek(); (nibble_count < nibble_length) && (pch != nullptr); str.append(1, GetHexU8(0, false)), pch = Peek (), nibble_count += 2)
|
||||
{}
|
||||
|
||||
return str.size();
|
||||
}
|
||||
|
||||
size_t
|
||||
StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
|
||||
char terminator)
|
||||
|
@ -428,6 +440,7 @@ StringExtractor::GetHexByteStringTerminatedBy (std::string &str,
|
|||
str.append(1, ch);
|
||||
if (Peek() && *Peek() == terminator)
|
||||
return str.size();
|
||||
|
||||
str.clear();
|
||||
return str.size();
|
||||
}
|
||||
|
|
|
@ -128,6 +128,9 @@ public:
|
|||
size_t
|
||||
GetHexByteString (std::string &str);
|
||||
|
||||
size_t
|
||||
GetHexByteStringFixedLength (std::string &str, uint32_t nibble_length);
|
||||
|
||||
size_t
|
||||
GetHexByteStringTerminatedBy (std::string &str,
|
||||
char terminator);
|
||||
|
|
|
@ -179,6 +179,7 @@ StringExtractorGDBRemote::GetServerPacketType () const
|
|||
if (PACKET_STARTS_WITH ("qSpeedTest:")) return eServerPacketType_qSpeedTest;
|
||||
if (PACKET_MATCHES ("qShlibInfoAddr")) return eServerPacketType_qShlibInfoAddr;
|
||||
if (PACKET_MATCHES ("qStepPacketSupported")) return eServerPacketType_qStepPacketSupported;
|
||||
if (PACKET_STARTS_WITH ("qSupported")) return eServerPacketType_qSupported;
|
||||
if (PACKET_MATCHES ("qSyncThreadStateSupported")) return eServerPacketType_qSyncThreadStateSupported;
|
||||
break;
|
||||
|
||||
|
@ -199,6 +200,10 @@ StringExtractorGDBRemote::GetServerPacketType () const
|
|||
if (PACKET_STARTS_WITH ("qWatchpointSupportInfo:")) return eServerPacketType_qWatchpointSupportInfo;
|
||||
if (PACKET_MATCHES ("qWatchpointSupportInfo")) return eServerPacketType_qWatchpointSupportInfoSupported;
|
||||
break;
|
||||
|
||||
case 'X':
|
||||
if (PACKET_STARTS_WITH ("qXfer:auxv:read::")) return eServerPacketType_qXfer_auxv_read;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'v':
|
||||
|
|
|
@ -106,12 +106,14 @@ public:
|
|||
eServerPacketType_qRegisterInfo,
|
||||
eServerPacketType_qShlibInfoAddr,
|
||||
eServerPacketType_qStepPacketSupported,
|
||||
eServerPacketType_qSupported,
|
||||
eServerPacketType_qSyncThreadStateSupported,
|
||||
eServerPacketType_qThreadExtraInfo,
|
||||
eServerPacketType_qThreadStopInfo,
|
||||
eServerPacketType_qVAttachOrWaitSupported,
|
||||
eServerPacketType_qWatchpointSupportInfo,
|
||||
eServerPacketType_qWatchpointSupportInfoSupported,
|
||||
eServerPacketType_qXfer_auxv_read,
|
||||
|
||||
eServerPacketType_vAttach,
|
||||
eServerPacketType_vAttachWait,
|
||||
|
|
|
@ -86,7 +86,6 @@ class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_supports_auxv_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -111,7 +110,6 @@ class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_auxv_data_is_correct_size_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -152,7 +150,6 @@ class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_auxv_keys_look_valid_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -200,7 +197,6 @@ class TestGdbRemoteAuxvSupport(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_auxv_chunked_reads_work_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
|
|
@ -62,7 +62,6 @@ class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_stop_notification_contains_any_registers_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -87,7 +86,6 @@ class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_stop_notification_contains_no_duplicate_registers_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -107,7 +105,6 @@ class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_stop_notification_contains_pc_register_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -127,7 +124,6 @@ class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_stop_notification_contains_fp_register_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -147,7 +143,6 @@ class TestGdbRemoteExpeditedRegisters(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_stop_notification_contains_sp_register_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
|
|
@ -100,7 +100,6 @@ class TestGdbRemoteRegisterState(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_grp_register_save_restore_works_with_suffix_llgs_dwarf(self):
|
||||
USE_THREAD_SUFFIX = True
|
||||
self.init_llgs_test()
|
||||
|
@ -119,7 +118,6 @@ class TestGdbRemoteRegisterState(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_grp_register_save_restore_works_no_suffix_llgs_dwarf(self):
|
||||
USE_THREAD_SUFFIX = False
|
||||
self.init_llgs_test()
|
||||
|
|
|
@ -15,7 +15,6 @@ class TestGdbRemoteSingleStep(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_single_step_only_steps_one_instruction_with_s_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
|
|
@ -83,7 +83,6 @@ class TestGdbRemoteThreadsInStopReply(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_QListThreadsInStopReply_supported_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -105,7 +104,6 @@ class TestGdbRemoteThreadsInStopReply(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_stop_reply_reports_multiple_threads_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -127,8 +125,7 @@ class TestGdbRemoteThreadsInStopReply(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_no_QThreadsInStopReply_supplies_no_threads_llgs_dwarf(self):
|
||||
def test_no_QListThreadsInStopReply_supplies_no_threads_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
self.set_inferior_startup_launch()
|
||||
|
@ -164,7 +161,6 @@ class TestGdbRemoteThreadsInStopReply(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_stop_reply_reports_correct_threads_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
|
|
@ -41,8 +41,6 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
self.vCont_supports_c()
|
||||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_vCont_supports_c_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -57,7 +55,6 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_vCont_supports_C_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -72,7 +69,6 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_vCont_supports_s_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -87,7 +83,6 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_vCont_supports_S_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -103,7 +98,6 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_single_step_only_steps_one_instruction_with_Hc_vCont_s_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -120,7 +114,6 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_single_step_only_steps_one_instruction_with_vCont_s_thread_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -128,7 +121,5 @@ class TestGdbRemote_vCont(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
self.single_step_only_steps_one_instruction(use_Hc_packet=False, step_instruction="vCont;s:{thread}")
|
||||
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest2.main()
|
||||
|
|
|
@ -63,7 +63,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
self.thread_suffix_supported()
|
||||
|
||||
@llgs_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_thread_suffix_supported_llgs(self):
|
||||
self.init_llgs_test()
|
||||
self.thread_suffix_supported()
|
||||
|
@ -85,7 +84,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
self.list_threads_in_stop_reply_supported()
|
||||
|
||||
@llgs_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_list_threads_in_stop_reply_supported_llgs(self):
|
||||
self.init_llgs_test()
|
||||
self.list_threads_in_stop_reply_supported()
|
||||
|
@ -143,7 +141,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_inferior_exit_0_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -176,7 +173,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_inferior_exit_42_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -207,7 +203,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_c_packet_works_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -240,7 +235,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_inferior_print_exit_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -272,7 +266,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_first_launch_stop_reply_thread_matches_first_qC_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -308,7 +301,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qProcessInfo_returns_running_process_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -343,7 +335,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_attach_commandline_qProcessInfo_reports_correct_pid_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -376,7 +367,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qProcessInfo_reports_valid_endian_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -410,7 +400,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_attach_commandline_continue_app_exits_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -445,7 +434,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_attach_commandline_kill_after_initial_stop_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -484,7 +472,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qRegisterInfo_returns_one_valid_result_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -519,7 +506,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qRegisterInfo_returns_all_valid_results_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -568,7 +554,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qRegisterInfo_contains_required_generics_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -606,7 +591,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qRegisterInfo_contains_at_least_one_register_set_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -635,10 +619,8 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
register_sets = { reg_info['set']:1 for reg_info in reg_infos if 'set' in reg_info }
|
||||
self.assertTrue("Advanced Vector Extensions" in register_sets)
|
||||
|
||||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qRegisterInfo_contains_avx_registers_on_linux_x86_64_llgs_dwarf(self):
|
||||
# Skip this test if not Linux x86_64.
|
||||
if platform.system() != "Linux" or platform.processor() != "x86_64":
|
||||
|
@ -673,7 +655,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qThreadInfo_contains_thread_launch_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -690,7 +671,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qThreadInfo_contains_thread_attach_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -735,7 +715,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qThreadInfo_matches_qC_launch_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -752,7 +731,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qThreadInfo_matches_qC_attach_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -810,7 +788,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_p_returns_correct_data_size_for_each_qRegisterInfo_launch_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -827,7 +804,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_p_returns_correct_data_size_for_each_qRegisterInfo_attach_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -873,7 +849,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_Hg_switches_to_3_threads_launch_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -890,7 +865,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_Hg_switches_to_3_threads_attach_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1010,7 +984,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_Hc_then_Csignal_signals_correct_thread_launch_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1073,7 +1046,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_m_packet_reads_memory_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1101,7 +1073,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qMemoryRegionInfo_is_supported_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1165,7 +1136,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qMemoryRegionInfo_reports_code_address_as_executable_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1229,7 +1199,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qMemoryRegionInfo_reports_stack_address_as_readable_writeable_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1294,7 +1263,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qMemoryRegionInfo_reports_heap_address_as_readable_writeable_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1411,7 +1379,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_software_breakpoint_set_and_remove_work_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1442,7 +1409,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_qSupported_returns_known_stub_features_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1503,7 +1469,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_written_M_content_reads_back_correctly_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1550,7 +1515,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_P_writes_all_gpr_registers_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
@ -1659,7 +1623,6 @@ class LldbGdbServerTestCase(gdbremote_testcase.GdbRemoteTestCaseBase):
|
|||
|
||||
@llgs_test
|
||||
@dwarf_test
|
||||
@unittest2.expectedFailure()
|
||||
def test_P_and_p_thread_suffix_work_llgs_dwarf(self):
|
||||
self.init_llgs_test()
|
||||
self.buildDwarf()
|
||||
|
|
|
@ -1024,3 +1024,4 @@ class GdbRemoteTestCaseBase(TestBase):
|
|||
(state_reached, step_count) = self.count_single_steps_until_true(main_thread_id, self.g_c1_c2_contents_are, args, max_step_count=5, use_Hc_packet=use_Hc_packet, step_instruction=step_instruction)
|
||||
self.assertTrue(state_reached)
|
||||
self.assertEquals(step_count, 1)
|
||||
|
||||
|
|
|
@ -92,9 +92,12 @@ signal_handler (int signo)
|
|||
switch (signo)
|
||||
{
|
||||
case SIGSEGV:
|
||||
// Fix up the pointer we're writing to. This needs to happen if nothing intercepts the SIGSEGV
|
||||
// (i.e. if somebody runs this from the command line).
|
||||
longjmp(g_jump_buffer, 1);
|
||||
if (g_is_segfaulting)
|
||||
{
|
||||
// Fix up the pointer we're writing to. This needs to happen if nothing intercepts the SIGSEGV
|
||||
// (i.e. if somebody runs this from the command line).
|
||||
longjmp(g_jump_buffer, 1);
|
||||
}
|
||||
break;
|
||||
case SIGUSR1:
|
||||
if (g_is_segfaulting)
|
||||
|
|
|
@ -2326,6 +2326,7 @@ RNBRemote::SendStopReplyPacketForThread (nub_thread_t tid)
|
|||
{
|
||||
size_t thread_name_len = strlen(thread_name);
|
||||
|
||||
|
||||
if (::strcspn (thread_name, "$#+-;:") == thread_name_len)
|
||||
ostrm << std::hex << "name:" << thread_name << ';';
|
||||
else
|
||||
|
|
|
@ -52,6 +52,7 @@ static struct option g_long_options[] =
|
|||
{ "lldb-command", required_argument, NULL, 'c' },
|
||||
{ "log-file", required_argument, NULL, 'l' },
|
||||
{ "log-flags", required_argument, NULL, 'f' },
|
||||
{ "attach", required_argument, NULL, 'a' },
|
||||
{ NULL, 0, NULL, 0 }
|
||||
};
|
||||
|
||||
|
@ -59,21 +60,38 @@ static struct option g_long_options[] =
|
|||
//----------------------------------------------------------------------
|
||||
// Watch for signals
|
||||
//----------------------------------------------------------------------
|
||||
int g_sigpipe_received = 0;
|
||||
static int g_sigpipe_received = 0;
|
||||
static int g_sighup_received_count = 0;
|
||||
|
||||
void
|
||||
signal_handler(int signo)
|
||||
{
|
||||
Log *log (GetLogIfAnyCategoriesSet(LIBLLDB_LOG_PROCESS));
|
||||
|
||||
fprintf (stderr, "lldb-gdbserver:%s received signal %d\n", __FUNCTION__, signo);
|
||||
if (log)
|
||||
log->Printf ("lldb-gdbserver:%s received signal %d", __FUNCTION__, signo);
|
||||
|
||||
switch (signo)
|
||||
{
|
||||
case SIGPIPE:
|
||||
g_sigpipe_received = 1;
|
||||
break;
|
||||
case SIGHUP:
|
||||
#if 1
|
||||
++g_sighup_received_count;
|
||||
|
||||
// For now, swallow SIGHUP.
|
||||
if (log)
|
||||
log->Printf ("lldb-gdbserver:%s swallowing SIGHUP (receive count=%d)", __FUNCTION__, g_sighup_received_count);
|
||||
signal (SIGHUP, signal_handler);
|
||||
#else
|
||||
// Use SIGINT first, if that does not work, use SIGHUP as a last resort.
|
||||
// And we should not call exit() here because it results in the global destructors
|
||||
// to be invoked and wreaking havoc on the threads still running.
|
||||
Host::SystemLog(Host::eSystemLogWarning, "SIGHUP received, exiting lldb-gdbserver...\n");
|
||||
abort();
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
@ -124,21 +142,221 @@ terminate_lldb_gdbserver ()
|
|||
PluginManager::Terminate ();
|
||||
}
|
||||
|
||||
static void
|
||||
run_lldb_commands (const lldb::DebuggerSP &debugger_sp, const std::vector<std::string> lldb_commands)
|
||||
{
|
||||
for (const auto &lldb_command : lldb_commands)
|
||||
{
|
||||
printf("(lldb) %s\n", lldb_command.c_str ());
|
||||
|
||||
lldb_private::CommandReturnObject result;
|
||||
debugger_sp->GetCommandInterpreter ().HandleCommand (lldb_command.c_str (), eLazyBoolNo, result);
|
||||
const char *output = result.GetOutputData ();
|
||||
if (output && output[0])
|
||||
puts (output);
|
||||
}
|
||||
}
|
||||
|
||||
static lldb::PlatformSP
|
||||
setup_platform (const std::string platform_name)
|
||||
{
|
||||
lldb::PlatformSP platform_sp;
|
||||
|
||||
if (platform_name.empty())
|
||||
{
|
||||
printf ("using the default platform: ");
|
||||
platform_sp = Platform::GetDefaultPlatform ();
|
||||
printf ("%s\n", platform_sp->GetPluginName ().AsCString ());
|
||||
return platform_sp;
|
||||
}
|
||||
|
||||
Error error;
|
||||
platform_sp = Platform::Create (platform_name.c_str(), error);
|
||||
if (error.Fail ())
|
||||
{
|
||||
// the host platform isn't registered with that name (at
|
||||
// least, not always. Check if the given name matches
|
||||
// the default platform name. If so, use it.
|
||||
if ( Platform::GetDefaultPlatform () && ( Platform::GetDefaultPlatform ()->GetPluginName () == ConstString (platform_name.c_str()) ) )
|
||||
{
|
||||
platform_sp = Platform::GetDefaultPlatform ();
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: failed to create platform with name '%s'\n", platform_name.c_str());
|
||||
dump_available_platforms (stderr);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
printf ("using platform: %s\n", platform_name.c_str ());
|
||||
|
||||
return platform_sp;
|
||||
}
|
||||
|
||||
void
|
||||
handle_attach_to_pid (GDBRemoteCommunicationServer &gdb_server, lldb::pid_t pid)
|
||||
{
|
||||
Error error = gdb_server.AttachToProcess (pid);
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "error: failed to attach to pid %" PRIu64 ": %s\n", pid, error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
handle_attach_to_process_name (GDBRemoteCommunicationServer &gdb_server, const std::string &process_name)
|
||||
{
|
||||
// FIXME implement.
|
||||
}
|
||||
|
||||
void
|
||||
handle_attach (GDBRemoteCommunicationServer &gdb_server, const std::string &attach_target)
|
||||
{
|
||||
assert (!attach_target.empty () && "attach_target cannot be empty");
|
||||
|
||||
// First check if the attach_target is convertable to a long. If so, we'll use it as a pid.
|
||||
char *end_p = nullptr;
|
||||
const long int pid = strtol (attach_target.c_str (), &end_p, 10);
|
||||
|
||||
// We'll call it a match if the entire argument is consumed.
|
||||
if (end_p && static_cast<size_t> (end_p - attach_target.c_str ()) == attach_target.size ())
|
||||
handle_attach_to_pid (gdb_server, static_cast<lldb::pid_t> (pid));
|
||||
else
|
||||
handle_attach_to_process_name (gdb_server, attach_target);
|
||||
}
|
||||
|
||||
void
|
||||
handle_launch (GDBRemoteCommunicationServer &gdb_server, int argc, const char *const argv[])
|
||||
{
|
||||
Error error;
|
||||
error = gdb_server.SetLaunchArguments (argv, argc);
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "error: failed to set launch args for '%s': %s\n", argv[0], error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
unsigned int launch_flags = eLaunchFlagStopAtEntry | eLaunchFlagDebug;
|
||||
|
||||
error = gdb_server.SetLaunchFlags (launch_flags);
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "error: failed to set launch flags for '%s': %s\n", argv[0], error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
error = gdb_server.LaunchProcess ();
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "error: failed to launch '%s': %s\n", argv[0], error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
start_listener (GDBRemoteCommunicationServer &gdb_server, const char *const host_and_port, const char *const progname)
|
||||
{
|
||||
Error error;
|
||||
|
||||
if (host_and_port && host_and_port[0])
|
||||
{
|
||||
std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
|
||||
if (conn_ap.get())
|
||||
{
|
||||
std::string final_host_and_port;
|
||||
std::string listening_host;
|
||||
std::string listening_port;
|
||||
|
||||
// If host_and_port starts with ':', default the host to be "localhost" and expect the remainder to be the port.
|
||||
if (host_and_port[0] == ':')
|
||||
final_host_and_port.append ("localhost");
|
||||
final_host_and_port.append (host_and_port);
|
||||
|
||||
const std::string::size_type colon_pos = final_host_and_port.find(':');
|
||||
if (colon_pos != std::string::npos)
|
||||
{
|
||||
listening_host = final_host_and_port.substr(0, colon_pos);
|
||||
listening_port = final_host_and_port.substr(colon_pos + 1);
|
||||
}
|
||||
|
||||
std::string connect_url ("listen://");
|
||||
connect_url.append (final_host_and_port);
|
||||
|
||||
printf ("Listening to port %s for a connection from %s...\n", listening_port.c_str (), listening_host.c_str ());
|
||||
if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
|
||||
{
|
||||
printf ("Connection established.\n");
|
||||
gdb_server.SetConnection (conn_ap.release());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ());
|
||||
display_usage (progname);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (gdb_server.IsConnected())
|
||||
{
|
||||
// After we connected, we need to get an initial ack from...
|
||||
if (gdb_server.HandshakeWithClient(&error))
|
||||
{
|
||||
// We'll use a half a second timeout interval so that an exit conditions can
|
||||
// be checked that often.
|
||||
const uint32_t TIMEOUT_USEC = 500000;
|
||||
|
||||
bool interrupt = false;
|
||||
bool done = false;
|
||||
while (!interrupt && !done && (g_sighup_received_count < 1))
|
||||
{
|
||||
const GDBRemoteCommunication::PacketResult result = gdb_server.GetPacketAndSendResponse (TIMEOUT_USEC, error, interrupt, done);
|
||||
if ((result != GDBRemoteCommunication::PacketResult::Success) &&
|
||||
(result != GDBRemoteCommunication::PacketResult::ErrorReplyTimeout))
|
||||
{
|
||||
// We're bailing out - we only support successful handling and timeouts.
|
||||
fprintf(stderr, "leaving packet loop due to PacketResult %d\n", result);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (error.Fail())
|
||||
{
|
||||
fprintf(stderr, "error: %s\n", error.AsCString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "error: handshake with client failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "no connection information provided, unable to run\n");
|
||||
display_usage (progname);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// main
|
||||
//----------------------------------------------------------------------
|
||||
int
|
||||
main (int argc, char *argv[])
|
||||
{
|
||||
const char *progname = argv[0];
|
||||
// Setup signal handlers first thing.
|
||||
signal (SIGPIPE, signal_handler);
|
||||
signal (SIGHUP, signal_handler);
|
||||
|
||||
const char *progname = argv[0];
|
||||
int long_option_index = 0;
|
||||
StreamSP log_stream_sp;
|
||||
Args log_args;
|
||||
Error error;
|
||||
int ch;
|
||||
std::string platform_name;
|
||||
std::string attach_target;
|
||||
|
||||
initialize_lldb_gdbserver ();
|
||||
|
||||
|
@ -215,6 +433,11 @@ main (int argc, char *argv[])
|
|||
platform_name = optarg;
|
||||
break;
|
||||
|
||||
case 'a': // attach {pid|process_name}
|
||||
if (optarg && optarg[0])
|
||||
attach_target = optarg;
|
||||
break;
|
||||
|
||||
case 'h': /* fall-through is intentional */
|
||||
case '?':
|
||||
show_usage = true;
|
||||
|
@ -235,7 +458,7 @@ main (int argc, char *argv[])
|
|||
ProcessGDBRemoteLog::EnableLog (log_stream_sp, 0,log_args.GetConstArgumentVector(), log_stream_sp.get());
|
||||
}
|
||||
|
||||
// Skip any options we consumed with getopt_long_only
|
||||
// Skip any options we consumed with getopt_long_only.
|
||||
argc -= optind;
|
||||
argv += optind;
|
||||
|
||||
|
@ -245,155 +468,29 @@ main (int argc, char *argv[])
|
|||
exit(255);
|
||||
}
|
||||
|
||||
// Run any commands requested
|
||||
for (const auto &lldb_command : lldb_commands)
|
||||
{
|
||||
printf("(lldb) %s\n", lldb_command.c_str ());
|
||||
// Run any commands requested.
|
||||
run_lldb_commands (debugger_sp, lldb_commands);
|
||||
|
||||
lldb_private::CommandReturnObject result;
|
||||
debugger_sp->GetCommandInterpreter ().HandleCommand (lldb_command.c_str (), eLazyBoolNo, result);
|
||||
const char *output = result.GetOutputData ();
|
||||
if (output && output[0])
|
||||
puts (output);
|
||||
}
|
||||
|
||||
// setup the platform that GDBRemoteCommunicationServer will use
|
||||
lldb::PlatformSP platform_sp;
|
||||
if (platform_name.empty())
|
||||
{
|
||||
printf ("using the default platform: ");
|
||||
platform_sp = Platform::GetDefaultPlatform ();
|
||||
printf ("%s\n", platform_sp->GetPluginName ().AsCString ());
|
||||
}
|
||||
else
|
||||
{
|
||||
Error error;
|
||||
platform_sp = Platform::Create (platform_name.c_str(), error);
|
||||
if (error.Fail ())
|
||||
{
|
||||
// the host platform isn't registered with that name (at
|
||||
// least, not always. Check if the given name matches
|
||||
// the default platform name. If so, use it.
|
||||
if ( Platform::GetDefaultPlatform () && ( Platform::GetDefaultPlatform ()->GetPluginName () == ConstString (platform_name.c_str()) ) )
|
||||
{
|
||||
platform_sp = Platform::GetDefaultPlatform ();
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "error: failed to create platform with name '%s'\n", platform_name.c_str());
|
||||
dump_available_platforms (stderr);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
printf ("using platform: %s\n", platform_name.c_str ());
|
||||
}
|
||||
// Setup the platform that GDBRemoteCommunicationServer will use.
|
||||
lldb::PlatformSP platform_sp = setup_platform (platform_name);
|
||||
|
||||
const bool is_platform = false;
|
||||
GDBRemoteCommunicationServer gdb_server (is_platform, platform_sp);
|
||||
GDBRemoteCommunicationServer gdb_server (is_platform, platform_sp, debugger_sp);
|
||||
|
||||
const char *host_and_port = argv[0];
|
||||
const char *const host_and_port = argv[0];
|
||||
argc -= 1;
|
||||
argv += 1;
|
||||
|
||||
// Any arguments left over are for the the program that we need to launch. If there
|
||||
// are no arguments, then the GDB server will start up and wait for an 'A' packet
|
||||
// to launch a program, or a vAttach packet to attach to an existing process.
|
||||
if (argc > 0)
|
||||
{
|
||||
error = gdb_server.SetLaunchArguments (argv, argc);
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "error: failed to set launch args for '%s': %s\n", argv[0], error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
// to launch a program, or a vAttach packet to attach to an existing process, unless
|
||||
// explicitly asked to attach with the --attach={pid|program_name} form.
|
||||
if (!attach_target.empty ())
|
||||
handle_attach (gdb_server, attach_target);
|
||||
else if (argc > 0)
|
||||
handle_launch (gdb_server, argc, argv);
|
||||
|
||||
unsigned int launch_flags = eLaunchFlagStopAtEntry;
|
||||
#if !defined(__linux__)
|
||||
// linux doesn't yet handle eLaunchFlagDebug
|
||||
launch_flags |= eLaunchFlagDebug;
|
||||
#endif
|
||||
error = gdb_server.SetLaunchFlags (launch_flags);
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "error: failed to set launch flags for '%s': %s\n", argv[0], error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
error = gdb_server.LaunchProcess ();
|
||||
if (error.Fail ())
|
||||
{
|
||||
fprintf (stderr, "error: failed to launch '%s': %s\n", argv[0], error.AsCString());
|
||||
exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
if (host_and_port && host_and_port[0])
|
||||
{
|
||||
std::unique_ptr<ConnectionFileDescriptor> conn_ap(new ConnectionFileDescriptor());
|
||||
if (conn_ap.get())
|
||||
{
|
||||
std::string final_host_and_port;
|
||||
std::string listening_host;
|
||||
std::string listening_port;
|
||||
|
||||
// If host_and_port starts with ':', default the host to be "localhost" and expect the remainder to be the port.
|
||||
if (host_and_port[0] == ':')
|
||||
final_host_and_port.append ("localhost");
|
||||
final_host_and_port.append (host_and_port);
|
||||
|
||||
const std::string::size_type colon_pos = final_host_and_port.find(':');
|
||||
if (colon_pos != std::string::npos)
|
||||
{
|
||||
listening_host = final_host_and_port.substr(0, colon_pos);
|
||||
listening_port = final_host_and_port.substr(colon_pos + 1);
|
||||
}
|
||||
|
||||
std::string connect_url ("listen://");
|
||||
connect_url.append (final_host_and_port);
|
||||
|
||||
printf ("Listening to port %s for a connection from %s...\n", listening_port.c_str (), listening_host.c_str ());
|
||||
if (conn_ap->Connect(connect_url.c_str(), &error) == eConnectionStatusSuccess)
|
||||
{
|
||||
printf ("Connection established.\n");
|
||||
gdb_server.SetConnection (conn_ap.release());
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "failed to connect to '%s': %s\n", final_host_and_port.c_str (), error.AsCString ());
|
||||
display_usage (progname);
|
||||
exit (1);
|
||||
}
|
||||
}
|
||||
|
||||
if (gdb_server.IsConnected())
|
||||
{
|
||||
// After we connected, we need to get an initial ack from...
|
||||
if (gdb_server.HandshakeWithClient(&error))
|
||||
{
|
||||
bool interrupt = false;
|
||||
bool done = false;
|
||||
while (!interrupt && !done)
|
||||
{
|
||||
if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
|
||||
break;
|
||||
}
|
||||
|
||||
if (error.Fail())
|
||||
{
|
||||
fprintf(stderr, "error: %s\n", error.AsCString());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf(stderr, "error: handshake with client failed\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf (stderr, "no connection information provided, unable to run\n");
|
||||
display_usage (progname);
|
||||
exit (1);
|
||||
}
|
||||
start_listener (gdb_server, host_and_port, progname);
|
||||
|
||||
terminate_lldb_gdbserver ();
|
||||
|
||||
|
|
|
@ -286,7 +286,7 @@ main (int argc, char *argv[])
|
|||
bool done = false;
|
||||
while (!interrupt && !done)
|
||||
{
|
||||
if (!gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done))
|
||||
if (gdb_server.GetPacketAndSendResponse (UINT32_MAX, error, interrupt, done) != GDBRemoteCommunication::PacketResult::Success)
|
||||
break;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue