Index: include/lldb/Target/NativeBreakpoint.h =================================================================== --- /dev/null +++ include/lldb/Target/NativeBreakpoint.h @@ -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_ Index: include/lldb/Target/NativeBreakpointList.h =================================================================== --- /dev/null +++ include/lldb/Target/NativeBreakpointList.h @@ -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 +#include + +namespace lldb_private +{ + class NativeBreakpointList + { + public: + typedef std::function 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 BreakpointMap; + + Mutex m_mutex; + BreakpointMap m_breakpoints; + }; +} + +#endif // ifndef liblldb_NativeBreakpointList_h_ Index: include/lldb/Target/NativeProcessProtocol.h =================================================================== --- /dev/null +++ include/lldb/Target/NativeProcessProtocol.h @@ -0,0 +1,343 @@ +//===-- 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 + +#include "lldb/lldb-private-forward.h" +#include "lldb/lldb-types.h" +#include "lldb/Core/Error.h" +#include "lldb/Host/Mutex.h" +#include "lldb/Target/NativeBreakpointList.h" + +namespace lldb_private +{ + class MemoryRegionInfo; + class ResumeActionList; + + //------------------------------------------------------------------ + // NativeProcessProtocol + //------------------------------------------------------------------ + class NativeProcessProtocol : + public std::enable_shared_from_this + { + 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. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + Signal (int signo) = 0; + + //------------------------------------------------------------------ + /// Tells a process to interrupt all operations as if by a Ctrl-C. + /// + /// The default implementation will send a local host's equivalent of + /// a SIGSTOP to the process via the NativeProcessProtocol::Signal() + /// operation. + /// + /// @return + /// Returns an error object. + //------------------------------------------------------------------ + virtual Error + Interrupt (); + + 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; + + virtual void + DidExec (NativeProcessProtocol *process) = 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 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 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; + + // ----------------------------------------------------------- + /// Notify the delegate that an exec occurred. + /// + /// Provide a mechanism for a delegate to clear out any exec- + /// sensitive data. + // ----------------------------------------------------------- + void + NotifyDidExec (); + + NativeThreadProtocolSP + GetThreadByIDUnlocked (lldb::tid_t tid); + + private: + + void + SynchronouslyNotifyProcessStateChanged (lldb::StateType state); + }; +} + +#endif // #ifndef liblldb_NativeProcessProtocol_h_ Index: include/lldb/Target/NativeThreadProtocol.h =================================================================== --- /dev/null +++ include/lldb/Target/NativeThreadProtocol.h @@ -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 + +#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 + { + public: + NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid); + + virtual ~NativeThreadProtocol() + { + } + + virtual std::string + GetName() = 0; + + virtual lldb::StateType + GetState () = 0; + + virtual NativeRegisterContextSP + GetRegisterContext () = 0; + + virtual Error + ReadRegister (uint32_t reg, RegisterValue ®_value); + + virtual Error + WriteRegister (uint32_t reg, const RegisterValue ®_value); + + virtual Error + SaveAllRegisters (lldb::DataBufferSP &data_sp); + + virtual Error + RestoreAllRegisters (lldb::DataBufferSP &data_sp); + + virtual bool + GetStopReason (ThreadStopInfo &stop_info) = 0; + + virtual uint32_t + TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const; + + lldb::tid_t + GetID() const + { + return m_tid; + } + + NativeProcessProtocolSP + GetProcess (); + + // --------------------------------------------------------------------- + // Thread-specific watchpoints + // --------------------------------------------------------------------- + virtual Error + SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0; + + virtual Error + RemoveWatchpoint (lldb::addr_t addr) = 0; + + protected: + NativeProcessProtocolWP m_process_wp; + lldb::tid_t m_tid; + }; +} + +#endif // #ifndef liblldb_NativeThreadProtocol_h_ Index: include/lldb/Target/Platform.h =================================================================== --- include/lldb/Target/Platform.h +++ include/lldb/Target/Platform.h @@ -23,12 +23,9 @@ #include "lldb/Core/ArchSpec.h" #include "lldb/Core/ConstString.h" #include "lldb/Core/PluginInterface.h" -#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" +#include "lldb/Interpreter/Options.h" +#include "lldb/Target/NativeProcessProtocol.h" namespace lldb_private { Index: include/lldb/Target/SoftwareBreakpoint.h =================================================================== --- /dev/null +++ include/lldb/Target/SoftwareBreakpoint.h @@ -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 "lldb/Target/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_ Index: lldb.xcodeproj/project.pbxproj =================================================================== --- lldb.xcodeproj/project.pbxproj +++ lldb.xcodeproj/project.pbxproj @@ -55,16 +55,6 @@ 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 */; }; 236124A41986B4E2004EFC37 /* IOObject.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 236124A21986B4E2004EFC37 /* IOObject.cpp */; }; @@ -581,6 +571,11 @@ 26FFC19C14FC072100087D58 /* DYLDRendezvous.h in Headers */ = {isa = PBXBuildFile; fileRef = 26FFC19614FC072100087D58 /* DYLDRendezvous.h */; }; 26FFC19D14FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */; }; 26FFC19E14FC072100087D58 /* DynamicLoaderPOSIXDYLD.h in Headers */ = {isa = PBXBuildFile; fileRef = 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */; }; + 3F6A92E01A095EAA005F2E60 /* NativeBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F6A92DB1A095EAA005F2E60 /* NativeBreakpoint.cpp */; }; + 3F6A92E11A095EAA005F2E60 /* NativeBreakpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F6A92DC1A095EAA005F2E60 /* NativeBreakpointList.cpp */; }; + 3F6A92E21A095EAA005F2E60 /* NativeProcessProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F6A92DD1A095EAA005F2E60 /* NativeProcessProtocol.cpp */; }; + 3F6A92E31A095EAA005F2E60 /* NativeThreadProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F6A92DE1A095EAA005F2E60 /* NativeThreadProtocol.cpp */; }; + 3F6A92E41A095EAA005F2E60 /* SoftwareBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F6A92DF1A095EAA005F2E60 /* SoftwareBreakpoint.cpp */; }; 3FDFDDBD199C3A06009756A7 /* FileAction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */; }; 3FDFDDBF199D345E009756A7 /* FileCache.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDBE199D345E009756A7 /* FileCache.cpp */; }; 3FDFDDC6199D37ED009756A7 /* FileSystem.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3FDFDDC5199D37ED009756A7 /* FileSystem.cpp */; }; @@ -967,16 +962,6 @@ 23059A0F1958B319007B8189 /* SBUnixSignals.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SBUnixSignals.cpp; path = source/API/SBUnixSignals.cpp; sourceTree = ""; }; 23059A111958B37B007B8189 /* SBUnixSignals.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SBUnixSignals.h; path = include/lldb/API/SBUnixSignals.h; sourceTree = ""; }; 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 = ""; }; - 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpoint.cpp; path = source/Host/common/NativeBreakpoint.cpp; sourceTree = ""; }; - 232CB60C191E00CC00EF39FC /* NativeBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = source/Host/common/NativeBreakpoint.h; sourceTree = ""; }; - 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpointList.cpp; path = source/Host/common/NativeBreakpointList.cpp; sourceTree = ""; }; - 232CB60E191E00CC00EF39FC /* NativeBreakpointList.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = source/Host/common/NativeBreakpointList.h; sourceTree = ""; }; - 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; lineEnding = 0; name = NativeProcessProtocol.cpp; path = source/Host/common/NativeProcessProtocol.cpp; sourceTree = ""; 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 = ""; }; - 232CB611191E00CC00EF39FC /* NativeThreadProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeThreadProtocol.cpp; path = source/Host/common/NativeThreadProtocol.cpp; sourceTree = ""; }; - 232CB612191E00CC00EF39FC /* NativeThreadProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = NativeThreadProtocol.h; path = source/Host/common/NativeThreadProtocol.h; sourceTree = ""; }; - 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareBreakpoint.cpp; path = source/Host/common/SoftwareBreakpoint.cpp; sourceTree = ""; }; - 232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = source/Host/common/SoftwareBreakpoint.h; sourceTree = ""; }; 232CB62B19213AC200EF39FC /* NativeProcessLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeProcessLinux.cpp; sourceTree = ""; }; 232CB62C19213AC200EF39FC /* NativeProcessLinux.h */ = {isa = PBXFileReference; explicitFileType = sourcecode.c.h; path = NativeProcessLinux.h; sourceTree = ""; }; 232CB62D19213AC200EF39FC /* NativeThreadLinux.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = NativeThreadLinux.cpp; sourceTree = ""; }; @@ -1790,6 +1775,16 @@ 26FFC19614FC072100087D58 /* DYLDRendezvous.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DYLDRendezvous.h; sourceTree = ""; }; 26FFC19714FC072100087D58 /* DynamicLoaderPOSIXDYLD.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = DynamicLoaderPOSIXDYLD.cpp; sourceTree = ""; }; 26FFC19814FC072100087D58 /* DynamicLoaderPOSIXDYLD.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = DynamicLoaderPOSIXDYLD.h; sourceTree = ""; }; + 3F6A92DB1A095EAA005F2E60 /* NativeBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpoint.cpp; path = source/Target/NativeBreakpoint.cpp; sourceTree = ""; }; + 3F6A92DC1A095EAA005F2E60 /* NativeBreakpointList.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpointList.cpp; path = source/Target/NativeBreakpointList.cpp; sourceTree = ""; }; + 3F6A92DD1A095EAA005F2E60 /* NativeProcessProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeProcessProtocol.cpp; path = source/Target/NativeProcessProtocol.cpp; sourceTree = ""; }; + 3F6A92DE1A095EAA005F2E60 /* NativeThreadProtocol.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeThreadProtocol.cpp; path = source/Target/NativeThreadProtocol.cpp; sourceTree = ""; }; + 3F6A92DF1A095EAA005F2E60 /* SoftwareBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareBreakpoint.cpp; path = source/Target/SoftwareBreakpoint.cpp; sourceTree = ""; }; + 3F6A92E51A095EC4005F2E60 /* NativeBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = include/lldb/Target/NativeBreakpoint.h; sourceTree = ""; }; + 3F6A92E61A095EC4005F2E60 /* NativeBreakpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = include/lldb/Target/NativeBreakpointList.h; sourceTree = ""; }; + 3F6A92E71A095EC4005F2E60 /* NativeProcessProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeProcessProtocol.h; path = include/lldb/Target/NativeProcessProtocol.h; sourceTree = ""; }; + 3F6A92E81A095EC4005F2E60 /* NativeThreadProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeThreadProtocol.h; path = include/lldb/Target/NativeThreadProtocol.h; sourceTree = ""; }; + 3F6A92E91A095EC4005F2E60 /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = include/lldb/Target/SoftwareBreakpoint.h; sourceTree = ""; }; 3FDFD6C3199C396E009756A7 /* FileAction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = FileAction.h; path = include/lldb/Target/FileAction.h; sourceTree = ""; }; 3FDFDDBC199C3A06009756A7 /* FileAction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileAction.cpp; path = source/Target/FileAction.cpp; sourceTree = ""; }; 3FDFDDBE199D345E009756A7 /* FileCache.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = FileCache.cpp; path = source/Host/common/FileCache.cpp; sourceTree = ""; }; @@ -3678,14 +3673,6 @@ 3FDFE57519AFABFD009756A7 /* HostThread.h */, 236124A61986B50E004EFC37 /* IOObject.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 */, 260A39A519647A3A004B4130 /* Pipe.h */, 26BC7DD610F1B7D500F91463 /* Predicate.h */, @@ -3693,8 +3680,6 @@ 236124A71986B50E004EFC37 /* Socket.h */, 26D7E45B13D5E2F9007FD12B /* SocketAddress.h */, 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */, - 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */, - 232CB614191E00CD00EF39FC /* SoftwareBreakpoint.h */, 2689B0A4113EE3CD00A4AEDB /* Symbols.h */, 268DA871130095D000C9483A /* Terminal.h */, 3FDFED0D19B7D269009756A7 /* ThisThread.cpp */, @@ -3833,6 +3818,14 @@ 8C2D6A54197A1EBE006989C9 /* MemoryHistory.h */, 8C2D6A52197A1EAF006989C9 /* MemoryHistory.cpp */, 2360092C193FB21500189DB1 /* MemoryRegionInfo.h */, + 3F6A92E51A095EC4005F2E60 /* NativeBreakpoint.h */, + 3F6A92DB1A095EAA005F2E60 /* NativeBreakpoint.cpp */, + 3F6A92E61A095EC4005F2E60 /* NativeBreakpointList.h */, + 3F6A92DC1A095EAA005F2E60 /* NativeBreakpointList.cpp */, + 3F6A92E71A095EC4005F2E60 /* NativeProcessProtocol.h */, + 3F6A92DD1A095EAA005F2E60 /* NativeProcessProtocol.cpp */, + 3F6A92E81A095EC4005F2E60 /* NativeThreadProtocol.h */, + 3F6A92DE1A095EAA005F2E60 /* NativeThreadProtocol.cpp */, 4CB443F612499B6E00C13DC2 /* ObjCLanguageRuntime.h */, 4CB443F212499B5000C13DC2 /* ObjCLanguageRuntime.cpp */, 495BBACF119A0DE700418BEA /* PathMappingList.h */, @@ -3858,6 +3851,8 @@ 262173A218395D4600C52091 /* SectionLoadHistory.cpp */, 2618D78F1240115500F2B8FE /* SectionLoadList.h */, 2618D7911240116900F2B8FE /* SectionLoadList.cpp */, + 3F6A92DF1A095EAA005F2E60 /* SoftwareBreakpoint.cpp */, + 3F6A92E91A095EC4005F2E60 /* SoftwareBreakpoint.h */, 26BC7DF510F1B81A00F91463 /* StackFrame.h */, 26BC7F3810F1B90C00F91463 /* StackFrame.cpp */, 26BC7DF610F1B81A00F91463 /* StackFrameList.h */, @@ -4573,7 +4568,6 @@ AF1F7B08189C904B0087DB9C /* AppleGetPendingItemsHandler.h in Headers */, AF77E0AA1A033D740096C0EA /* RegisterContextPOSIXCore_powerpc.h in Headers */, AF2BCA6D18C7EFDE005B4526 /* JITLoaderGDB.h in Headers */, - 232CB61E191E00CD00EF39FC /* SoftwareBreakpoint.h in Headers */, 26BC17B218C7F4CB00D2196D /* ThreadElfCore.h in Headers */, AF77E0A51A033D360096C0EA /* RegisterContextPOSIX_powerpc.h in Headers */, AF77E0A61A033D360096C0EA /* RegisterInfos_powerpc.h in Headers */, @@ -4594,7 +4588,6 @@ 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 */, @@ -4637,10 +4630,7 @@ 26474CC118D0CB2D0073DEBA /* RegisterContextMach_x86_64.h in Headers */, 4C73152219B7D71700F865A4 /* Iterable.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 */, @@ -5082,6 +5072,7 @@ 26474CC918D0CB5B0073DEBA /* RegisterContextMemory.cpp in Sources */, 8CF02AEA19DCC02100B14BE0 /* AddressSanitizerRuntime.cpp in Sources */, 26474CB218D0CB180073DEBA /* RegisterContextLinux_i386.cpp in Sources */, + 3F6A92E11A095EAA005F2E60 /* NativeBreakpointList.cpp in Sources */, 26474CCB18D0CB5B0073DEBA /* RegisterContextPOSIX_mips64.cpp in Sources */, 2689000B13353DB600698AC0 /* Stoppoint.cpp in Sources */, 2689000D13353DB600698AC0 /* StoppointCallbackContext.cpp in Sources */, @@ -5136,6 +5127,7 @@ 2689003813353E0400698AC0 /* DataExtractor.cpp in Sources */, 2689003913353E0400698AC0 /* Debugger.cpp in Sources */, 2689003A13353E0400698AC0 /* Disassembler.cpp in Sources */, + 3F6A92E31A095EAA005F2E60 /* NativeThreadProtocol.cpp in Sources */, 236124A51986B4E2004EFC37 /* Socket.cpp in Sources */, 3FDFDDBF199D345E009756A7 /* FileCache.cpp in Sources */, AF1729D7182C907200E0AB97 /* HistoryUnwind.cpp in Sources */, @@ -5204,6 +5196,7 @@ 2689006B13353E0E00698AC0 /* IRForTarget.cpp in Sources */, 2689006D13353E0E00698AC0 /* IRExecutionUnit.cpp in Sources */, 2689006E13353E1A00698AC0 /* File.cpp in Sources */, + 3F6A92E01A095EAA005F2E60 /* NativeBreakpoint.cpp in Sources */, 94D6A0AB16CEB55F00833B6E /* NSDictionary.cpp in Sources */, 2689006F13353E1A00698AC0 /* FileSpec.cpp in Sources */, 2689007013353E1A00698AC0 /* Condition.cpp in Sources */, @@ -5246,6 +5239,7 @@ 2689009713353E4200698AC0 /* ObjectContainerUniversalMachO.cpp in Sources */, 2689009813353E4200698AC0 /* ELFHeader.cpp in Sources */, 2689009913353E4200698AC0 /* ObjectFileELF.cpp in Sources */, + 3F6A92E41A095EAA005F2E60 /* SoftwareBreakpoint.cpp in Sources */, 2689009A13353E4200698AC0 /* ObjectFileMachO.cpp in Sources */, 2689009B13353E4200698AC0 /* PlatformMacOSX.cpp in Sources */, 2689009C13353E4200698AC0 /* PlatformRemoteiOS.cpp in Sources */, @@ -5344,19 +5338,15 @@ 268900F913353E6F00698AC0 /* Thread.cpp in Sources */, 268900FA13353E6F00698AC0 /* ThreadList.cpp in Sources */, 268900FB13353E6F00698AC0 /* ThreadPlan.cpp in Sources */, - 232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */, 8CF02AEF19DD16B100B14BE0 /* InstrumentationRuntimeStopInfo.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 */, 3FDFED2919BA6D96009756A7 /* ThreadLauncher.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 */, @@ -5396,6 +5386,7 @@ 26D5E163135BB054006EA0A7 /* OptionGroupPlatform.cpp in Sources */, 94CD131A19BA33B400DB7BED /* TypeValidator.cpp in Sources */, 26BD407F135D2AE000237D80 /* FileLineResolver.cpp in Sources */, + 3F6A92E21A095EAA005F2E60 /* NativeProcessProtocol.cpp in Sources */, 26A7A035135E6E4200FB369E /* OptionValue.cpp in Sources */, 9A22A161135E30370024DDC3 /* EmulateInstructionARM.cpp in Sources */, AF77E0971A033CC70096C0EA /* RegisterContextPOSIXProcessMonitor_powerpc.cpp in Sources */, @@ -5426,7 +5417,6 @@ 8C2D6A5E197A250F006989C9 /* MemoryHistoryASan.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 */, Index: source/Host/CMakeLists.txt =================================================================== --- source/Host/CMakeLists.txt +++ source/Host/CMakeLists.txt @@ -17,15 +17,10 @@ common/IOObject.cpp common/Mutex.cpp common/MonitoringProcessLauncher.cpp - common/NativeBreakpoint.cpp - common/NativeBreakpointList.cpp - common/NativeProcessProtocol.cpp - common/NativeThreadProtocol.cpp common/OptionParser.cpp common/ProcessRunLock.cpp common/Socket.cpp common/SocketAddress.cpp - common/SoftwareBreakpoint.cpp common/Symbols.cpp common/Terminal.cpp common/ThisThread.cpp Index: source/Host/common/NativeBreakpoint.h =================================================================== --- source/Host/common/NativeBreakpoint.h +++ /dev/null @@ -1,66 +0,0 @@ -//===-- 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_ Index: source/Host/common/NativeBreakpoint.cpp =================================================================== --- source/Host/common/NativeBreakpoint.cpp +++ /dev/null @@ -1,116 +0,0 @@ -//===-- 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; -} Index: source/Host/common/NativeBreakpointList.h =================================================================== --- source/Host/common/NativeBreakpointList.h +++ /dev/null @@ -1,53 +0,0 @@ -//===-- 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 -#include - -namespace lldb_private -{ - class NativeBreakpointList - { - public: - typedef std::function 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 BreakpointMap; - - Mutex m_mutex; - BreakpointMap m_breakpoints; - }; -} - -#endif // ifndef liblldb_NativeBreakpointList_h_ Index: source/Host/common/NativeBreakpointList.cpp =================================================================== --- source/Host/common/NativeBreakpointList.cpp +++ /dev/null @@ -1,199 +0,0 @@ -//===-- 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 (); -} - Index: source/Host/common/NativeProcessProtocol.h =================================================================== --- source/Host/common/NativeProcessProtocol.h +++ /dev/null @@ -1,344 +0,0 @@ -//===-- 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 - -#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 - { - 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. - /// - /// @return - /// Returns an error object. - //------------------------------------------------------------------ - virtual Error - Signal (int signo) = 0; - - //------------------------------------------------------------------ - /// Tells a process to interrupt all operations as if by a Ctrl-C. - /// - /// The default implementation will send a local host's equivalent of - /// a SIGSTOP to the process via the NativeProcessProtocol::Signal() - /// operation. - /// - /// @return - /// Returns an error object. - //------------------------------------------------------------------ - virtual Error - Interrupt (); - - 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; - - virtual void - DidExec (NativeProcessProtocol *process) = 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 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 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; - - // ----------------------------------------------------------- - /// Notify the delegate that an exec occurred. - /// - /// Provide a mechanism for a delegate to clear out any exec- - /// sensitive data. - // ----------------------------------------------------------- - void - NotifyDidExec (); - - NativeThreadProtocolSP - GetThreadByIDUnlocked (lldb::tid_t tid); - - private: - - void - SynchronouslyNotifyProcessStateChanged (lldb::StateType state); - }; -} - -#endif // #ifndef liblldb_NativeProcessProtocol_h_ Index: source/Host/common/NativeProcessProtocol.cpp =================================================================== --- source/Host/common/NativeProcessProtocol.cpp +++ /dev/null @@ -1,431 +0,0 @@ -//===-- 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/Host/Host.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::Interrupt () -{ - Error error; -#if !defined (SIGSTOP) - error.SetErrorString ("local host does not support signaling"); - return error; -#else - return Signal (SIGSTOP); -#endif -} - -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::GetThreadByIDUnlocked (lldb::tid_t tid) -{ - for (auto thread_sp : m_threads) - { - if (thread_sp->GetID() == tid) - return thread_sp; - } - return NativeThreadProtocolSP (); -} - -NativeThreadProtocolSP -NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) -{ - Mutex::Locker locker (m_threads_mutex); - return GetThreadByIDUnlocked (tid); -} - -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 (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 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 ()); - } - } -} - -void -NativeProcessProtocol::NotifyDidExec () -{ - Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); - if (log) - log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__); - - { - Mutex::Locker locker (m_delegates_mutex); - for (auto native_delegate: m_delegates) - native_delegate->DidExec (this); - } -} - - -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. -} Index: source/Host/common/NativeThreadProtocol.h =================================================================== --- source/Host/common/NativeThreadProtocol.h +++ /dev/null @@ -1,85 +0,0 @@ -//===-- 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 - -#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 - { - public: - NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid); - - virtual ~NativeThreadProtocol() - { - } - - virtual std::string - GetName() = 0; - - virtual lldb::StateType - GetState () = 0; - - virtual NativeRegisterContextSP - GetRegisterContext () = 0; - - virtual Error - ReadRegister (uint32_t reg, RegisterValue ®_value); - - virtual Error - WriteRegister (uint32_t reg, const RegisterValue ®_value); - - virtual Error - SaveAllRegisters (lldb::DataBufferSP &data_sp); - - virtual Error - RestoreAllRegisters (lldb::DataBufferSP &data_sp); - - virtual bool - GetStopReason (ThreadStopInfo &stop_info) = 0; - - virtual uint32_t - TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const; - - lldb::tid_t - GetID() const - { - return m_tid; - } - - NativeProcessProtocolSP - GetProcess (); - - // --------------------------------------------------------------------- - // Thread-specific watchpoints - // --------------------------------------------------------------------- - virtual Error - SetWatchpoint (lldb::addr_t addr, size_t size, uint32_t watch_flags, bool hardware) = 0; - - virtual Error - RemoveWatchpoint (lldb::addr_t addr) = 0; - - protected: - NativeProcessProtocolWP m_process_wp; - lldb::tid_t m_tid; - }; -} - -#endif // #ifndef liblldb_NativeThreadProtocol_h_ Index: source/Host/common/NativeThreadProtocol.cpp =================================================================== --- source/Host/common/NativeThreadProtocol.cpp +++ /dev/null @@ -1,97 +0,0 @@ -//===-- NativeThreadProtocol.cpp --------------------------------*- C++ -*-===// -// -// The LLVM Compiler Infrastructure -// -// This file is distributed under the University of Illinois Open Source -// License. See LICENSE.TXT for details. -// -//===----------------------------------------------------------------------===// - -#include "NativeThreadProtocol.h" - -#include "NativeProcessProtocol.h" -#include "lldb/Target/NativeRegisterContext.h" -#include "SoftwareBreakpoint.h" - -using namespace lldb; -using namespace lldb_private; - -NativeThreadProtocol::NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) : - m_process_wp (process->shared_from_this ()), - m_tid (tid) -{ -} - -Error -NativeThreadProtocol::ReadRegister (uint32_t reg, RegisterValue ®_value) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - - const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); - if (!reg_info) - return Error ("no register info for reg num %" PRIu32, reg); - - return register_context_sp->ReadRegister (reg_info, reg_value);; -} - -Error -NativeThreadProtocol::WriteRegister (uint32_t reg, const RegisterValue ®_value) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - - const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); - if (!reg_info) - return Error ("no register info for reg num %" PRIu32, reg); - - return register_context_sp->WriteRegister (reg_info, reg_value); -} - -Error -NativeThreadProtocol::SaveAllRegisters (lldb::DataBufferSP &data_sp) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - return register_context_sp->WriteAllRegisterValues (data_sp); -} - -Error -NativeThreadProtocol::RestoreAllRegisters (lldb::DataBufferSP &data_sp) -{ - NativeRegisterContextSP register_context_sp = GetRegisterContext (); - if (!register_context_sp) - return Error ("no register context"); - return register_context_sp->ReadAllRegisterValues (data_sp); -} - -NativeProcessProtocolSP -NativeThreadProtocol::GetProcess () -{ - return m_process_wp.lock (); -} - -uint32_t -NativeThreadProtocol::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const -{ - // Default: no translation. Do the real translation where there - // is access to the host signal numbers. - switch (stop_info.reason) - { - case eStopReasonSignal: - return stop_info.details.signal.signo; - break; - - case eStopReasonException: - // FIXME verify the way to specify pass-thru here. - return static_cast (stop_info.details.exception.type); - break; - - default: - assert (0 && "unexpected stop_info.reason found"); - return 0; - } -} Index: source/Host/common/SoftwareBreakpoint.h =================================================================== --- source/Host/common/SoftwareBreakpoint.h +++ /dev/null @@ -1,51 +0,0 @@ -//===-- 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_ Index: source/Host/common/SoftwareBreakpoint.cpp =================================================================== --- source/Host/common/SoftwareBreakpoint.cpp +++ /dev/null @@ -1,313 +0,0 @@ -//===-- 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 (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 (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); - } - - // Log what we read. - if (log) - { - int i = 0; - for (const uint8_t *read_byte = saved_opcode_bytes; read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) - { - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " ovewriting byte index %d (was 0x%x)", __FUNCTION__, addr, i++, static_cast (*read_byte)); - } - } - - // 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 (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 (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 (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 (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 breakpoint 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 (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 (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 (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) - { - int i = 0; - for (const uint8_t *verify_byte = verify_opcode; verify_byte < verify_opcode + m_opcode_size; ++verify_byte) - { - log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " replaced byte index %d with 0x%x", __FUNCTION__, m_addr, i++, static_cast (*verify_byte)); - } - 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; -} - Index: source/Plugins/Process/Linux/NativeProcessLinux.h =================================================================== --- source/Plugins/Process/Linux/NativeProcessLinux.h +++ source/Plugins/Process/Linux/NativeProcessLinux.h @@ -24,8 +24,7 @@ #include "lldb/Host/HostThread.h" #include "lldb/Host/Mutex.h" #include "lldb/Target/MemoryRegionInfo.h" - -#include "Host/common/NativeProcessProtocol.h" +#include "lldb/Target/NativeProcessProtocol.h" namespace lldb_private { Index: source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp =================================================================== --- source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp +++ source/Plugins/Process/Linux/NativeRegisterContextLinux_x86_64.cpp @@ -13,8 +13,8 @@ #include "lldb/Core/DataBufferHeap.h" #include "lldb/Core/Error.h" #include "lldb/Core/RegisterValue.h" -#include "Host/common/NativeProcessProtocol.h" -#include "Host/common/NativeThreadProtocol.h" +#include "lldb/Target/NativeProcessProtocol.h" +#include "lldb/Target/NativeThreadProtocol.h" #include "Plugins/Process/Linux/NativeProcessLinux.h" using namespace lldb_private; Index: source/Plugins/Process/Linux/NativeThreadLinux.h =================================================================== --- source/Plugins/Process/Linux/NativeThreadLinux.h +++ source/Plugins/Process/Linux/NativeThreadLinux.h @@ -11,7 +11,7 @@ #define liblldb_NativeThreadLinux_H_ #include "lldb/lldb-private-forward.h" -#include "../../../Host/common/NativeThreadProtocol.h" +#include "lldb/Target/NativeThreadProtocol.h" namespace lldb_private { Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.h @@ -20,11 +20,10 @@ #include "lldb/lldb-private-forward.h" #include "lldb/Core/Communication.h" #include "lldb/Host/Mutex.h" +#include "lldb/Target/NativeProcessProtocol.h" #include "lldb/Target/Process.h" #include "GDBRemoteCommunication.h" -#include "../../../Host/common/NativeProcessProtocol.h" - class ProcessGDBRemote; class StringExtractorGDBRemote; Index: source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp =================================================================== --- source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp +++ source/Plugins/Process/gdb-remote/GDBRemoteCommunicationServer.cpp @@ -38,9 +38,9 @@ #include "lldb/Target/FileAction.h" #include "lldb/Target/Platform.h" #include "lldb/Target/Process.h" +#include "lldb/Target/NativeProcessProtocol.h" #include "lldb/Target/NativeRegisterContext.h" -#include "Host/common/NativeProcessProtocol.h" -#include "Host/common/NativeThreadProtocol.h" +#include "lldb/Target/NativeThreadProtocol.h" // Project includes #include "Utility/StringExtractorGDBRemote.h" Index: source/Target/CMakeLists.txt =================================================================== --- source/Target/CMakeLists.txt +++ source/Target/CMakeLists.txt @@ -14,8 +14,12 @@ LanguageRuntime.cpp Memory.cpp MemoryHistory.cpp + NativeBreakpoint.cpp + NativeBreakpointList.cpp + NativeProcessProtocol.cpp NativeRegisterContext.cpp NativeRegisterContextRegisterInfo.cpp + NativeThreadProtocol.cpp ObjCLanguageRuntime.cpp OperatingSystem.cpp PathMappingList.cpp @@ -29,6 +33,7 @@ RegisterContext.cpp SectionLoadHistory.cpp SectionLoadList.cpp + SoftwareBreakpoint.cpp StackFrame.cpp StackFrameList.cpp StackID.cpp Index: source/Target/NativeBreakpoint.cpp =================================================================== --- /dev/null +++ source/Target/NativeBreakpoint.cpp @@ -0,0 +1,115 @@ +//===-- 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 "lldb/lldb-defines.h" +#include "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Target/NativeBreakpoint.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; +} Index: source/Target/NativeBreakpointList.cpp =================================================================== --- /dev/null +++ source/Target/NativeBreakpointList.cpp @@ -0,0 +1,198 @@ +//===-- 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 "lldb/Core/Log.h" + +#include "lldb/Target/NativeBreakpoint.h" +#include "lldb/Target/NativeBreakpointList.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 (); +} + Index: source/Target/NativeProcessProtocol.cpp =================================================================== --- /dev/null +++ source/Target/NativeProcessProtocol.cpp @@ -0,0 +1,429 @@ +//===-- 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 "lldb/lldb-enumerations.h" +#include "lldb/Core/ArchSpec.h" +#include "lldb/Core/Log.h" +#include "lldb/Core/State.h" +#include "lldb/Host/Host.h" +#include "lldb/Target/NativeProcessProtocol.h" +#include "lldb/Target/NativeRegisterContext.h" +#include "lldb/Target/NativeThreadProtocol.h" +#include "lldb/Target/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::Interrupt () +{ + Error error; +#if !defined (SIGSTOP) + error.SetErrorString ("local host does not support signaling"); + return error; +#else + return Signal (SIGSTOP); +#endif +} + +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::GetThreadByIDUnlocked (lldb::tid_t tid) +{ + for (auto thread_sp : m_threads) + { + if (thread_sp->GetID() == tid) + return thread_sp; + } + return NativeThreadProtocolSP (); +} + +NativeThreadProtocolSP +NativeProcessProtocol::GetThreadByID (lldb::tid_t tid) +{ + Mutex::Locker locker (m_threads_mutex); + return GetThreadByIDUnlocked (tid); +} + +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 (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 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 ()); + } + } +} + +void +NativeProcessProtocol::NotifyDidExec () +{ + Log *log (GetLogIfAllCategoriesSet (LIBLLDB_LOG_PROCESS)); + if (log) + log->Printf ("NativeProcessProtocol::%s - preparing to call delegates", __FUNCTION__); + + { + Mutex::Locker locker (m_delegates_mutex); + for (auto native_delegate: m_delegates) + native_delegate->DidExec (this); + } +} + + +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. +} Index: source/Target/NativeRegisterContext.cpp =================================================================== --- source/Target/NativeRegisterContext.cpp +++ source/Target/NativeRegisterContext.cpp @@ -7,15 +7,14 @@ // //===----------------------------------------------------------------------===// -#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" +#include "lldb/Target/NativeProcessProtocol.h" +#include "lldb/Target/NativeThreadProtocol.h" +#include "lldb/Target/NativeRegisterContext.h" using namespace lldb; using namespace lldb_private; Index: source/Target/NativeThreadProtocol.cpp =================================================================== --- /dev/null +++ source/Target/NativeThreadProtocol.cpp @@ -0,0 +1,96 @@ +//===-- 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 "lldb/Target/NativeProcessProtocol.h" +#include "lldb/Target/NativeRegisterContext.h" +#include "lldb/Target/NativeThreadProtocol.h" +#include "lldb/Target/SoftwareBreakpoint.h" + +using namespace lldb; +using namespace lldb_private; + +NativeThreadProtocol::NativeThreadProtocol (NativeProcessProtocol *process, lldb::tid_t tid) : + m_process_wp (process->shared_from_this ()), + m_tid (tid) +{ +} + +Error +NativeThreadProtocol::ReadRegister (uint32_t reg, RegisterValue ®_value) +{ + NativeRegisterContextSP register_context_sp = GetRegisterContext (); + if (!register_context_sp) + return Error ("no register context"); + + const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); + if (!reg_info) + return Error ("no register info for reg num %" PRIu32, reg); + + return register_context_sp->ReadRegister (reg_info, reg_value);; +} + +Error +NativeThreadProtocol::WriteRegister (uint32_t reg, const RegisterValue ®_value) +{ + NativeRegisterContextSP register_context_sp = GetRegisterContext (); + if (!register_context_sp) + return Error ("no register context"); + + const RegisterInfo *const reg_info = register_context_sp->GetRegisterInfoAtIndex (reg); + if (!reg_info) + return Error ("no register info for reg num %" PRIu32, reg); + + return register_context_sp->WriteRegister (reg_info, reg_value); +} + +Error +NativeThreadProtocol::SaveAllRegisters (lldb::DataBufferSP &data_sp) +{ + NativeRegisterContextSP register_context_sp = GetRegisterContext (); + if (!register_context_sp) + return Error ("no register context"); + return register_context_sp->WriteAllRegisterValues (data_sp); +} + +Error +NativeThreadProtocol::RestoreAllRegisters (lldb::DataBufferSP &data_sp) +{ + NativeRegisterContextSP register_context_sp = GetRegisterContext (); + if (!register_context_sp) + return Error ("no register context"); + return register_context_sp->ReadAllRegisterValues (data_sp); +} + +NativeProcessProtocolSP +NativeThreadProtocol::GetProcess () +{ + return m_process_wp.lock (); +} + +uint32_t +NativeThreadProtocol::TranslateStopInfoToGdbSignal (const ThreadStopInfo &stop_info) const +{ + // Default: no translation. Do the real translation where there + // is access to the host signal numbers. + switch (stop_info.reason) + { + case eStopReasonSignal: + return stop_info.details.signal.signo; + break; + + case eStopReasonException: + // FIXME verify the way to specify pass-thru here. + return static_cast (stop_info.details.exception.type); + break; + + default: + assert (0 && "unexpected stop_info.reason found"); + return 0; + } +} Index: source/Target/SoftwareBreakpoint.cpp =================================================================== --- /dev/null +++ source/Target/SoftwareBreakpoint.cpp @@ -0,0 +1,312 @@ +//===-- 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 "lldb/Core/Error.h" +#include "lldb/Core/Log.h" +#include "lldb/Host/Debug.h" +#include "lldb/Host/Mutex.h" + +#include "lldb/Target/NativeProcessProtocol.h" +#include "lldb/Target/SoftwareBreakpoint.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 (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 (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); + } + + // Log what we read. + if (log) + { + int i = 0; + for (const uint8_t *read_byte = saved_opcode_bytes; read_byte < saved_opcode_bytes + bp_opcode_size; ++read_byte) + { + log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " ovewriting byte index %d (was 0x%x)", __FUNCTION__, addr, i++, static_cast (*read_byte)); + } + } + + // 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 (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 (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 (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 (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 breakpoint 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 (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 (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 (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) + { + int i = 0; + for (const uint8_t *verify_byte = verify_opcode; verify_byte < verify_opcode + m_opcode_size; ++verify_byte) + { + log->Printf ("SoftwareBreakpoint::%s addr = 0x%" PRIx64 " replaced byte index %d with 0x%x", __FUNCTION__, m_addr, i++, static_cast (*verify_byte)); + } + 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; +} +