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:
Todd Fiala 2014-06-30 21:05:18 +00:00
parent b201cf8883
commit af245d115b
85 changed files with 12074 additions and 617 deletions

3
lldb/.gitignore vendored
View File

@ -25,3 +25,6 @@ build/
llvm-build/
*xcuserdata
test/20*
# We should ignore Xcode-style embedding of llvm/ at lldb root dir.
/llvm/

View File

@ -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

View File

@ -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

View File

@ -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 &reg_value) = 0;
virtual Error WriteRegister (uint32_t reg, const RegisterValue &reg_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_

View File

@ -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);

View File

@ -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

View File

@ -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 &reg_value) = 0;
virtual Error
WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_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 &reg_value);
virtual Error
WriteRegisterValueToMemory (const lldb_private::RegisterInfo *reg_info, lldb::addr_t dst_addr, lldb::addr_t dst_len, const RegisterValue &reg_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_

View File

@ -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

View File

@ -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

View File

@ -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 ();

View File

@ -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

View File

@ -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

View File

@ -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_

View File

@ -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 */,

View File

@ -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;

View File

@ -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;

View File

@ -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

View File

@ -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;
}

View File

@ -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_

View File

@ -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 ();
}

View File

@ -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_

View File

@ -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.
}

View File

@ -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_

View File

@ -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 &reg_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 &reg_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;
}
}

View File

@ -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 &reg_value);
virtual Error
WriteRegister (uint32_t reg, const RegisterValue &reg_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_

View File

@ -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;
}

View File

@ -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_

View File

@ -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)
{

View File

@ -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

View File

@ -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;

View File

@ -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
}

View File

@ -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);
};

View File

@ -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

View File

@ -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_

View File

@ -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;
}
}

View File

@ -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_

View File

@ -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;

View 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;

View File

@ -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 ();
}

View File

@ -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.

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 &reg_value) override;
Error
WriteRegister (const RegisterInfo *reg_info, const RegisterValue &reg_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 &reg_value);
bool
ReadGPR();
bool
WriteGPR();
};
}
#endif // #ifndef lldb_NativeRegisterContextLinux_x86_64_h

View File

@ -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]));
}

View File

@ -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

View File

@ -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]));
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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]));
}

View File

@ -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

View File

@ -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;
}

View File

@ -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

View File

@ -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;
};

View File

@ -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

View File

@ -132,7 +132,7 @@ public:
// Returns AUXV structure found in the core file
const lldb::DataBufferSP
GetAuxvData();
GetAuxvData() override;
protected:
void

View File

@ -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 ());

View File

@ -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
//------------------------------------------------------------------

View File

@ -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;
}

View File

@ -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 ();

View File

@ -10,6 +10,8 @@ add_lldb_library(lldbTarget
JITLoaderList.cpp
LanguageRuntime.cpp
Memory.cpp
NativeRegisterContext.cpp
NativeRegisterContextRegisterInfo.cpp
ObjCLanguageRuntime.cpp
OperatingSystem.cpp
PathMappingList.cpp

View File

@ -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 &reg_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 &reg_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;
}

View File

@ -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;
}

View File

@ -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)
{

View File

@ -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 ()
{

View File

@ -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();
}

View File

@ -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);

View File

@ -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':

View File

@ -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,

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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()

View File

@ -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)

View File

@ -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)

View File

@ -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

View File

@ -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 ();

View File

@ -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;
}