Index: lldb/trunk/include/lldb/Host/common/NativeBreakpoint.h =================================================================== --- lldb/trunk/include/lldb/Host/common/NativeBreakpoint.h +++ lldb/trunk/include/lldb/Host/common/NativeBreakpoint.h @@ -1,56 +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(); - - Status Enable(); - - Status 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 Status DoEnable() = 0; - - virtual Status DoDisable() = 0; - -private: - bool m_enabled; - - // ----------------------------------------------------------- interface for - // NativeBreakpointList - // ----------------------------------------------------------- - void AddRef(); - int32_t DecRef(); -}; -} - -#endif // ifndef liblldb_NativeBreakpoint_h_ Index: lldb/trunk/include/lldb/Host/common/NativeBreakpointList.h =================================================================== --- lldb/trunk/include/lldb/Host/common/NativeBreakpointList.h +++ lldb/trunk/include/lldb/Host/common/NativeBreakpointList.h @@ -10,13 +10,9 @@ #ifndef liblldb_NativeBreakpointList_h_ #define liblldb_NativeBreakpointList_h_ -#include "lldb/Utility/Status.h" #include "lldb/lldb-private-forward.h" -// #include "lldb/Host/NativeBreakpoint.h" - -#include +#include "lldb/lldb-types.h" #include -#include namespace lldb_private { @@ -26,35 +22,6 @@ }; using HardwareBreakpointMap = std::map; - -class NativeBreakpointList { -public: - typedef std::function - CreateBreakpointFunc; - - NativeBreakpointList(); - - Status AddRef(lldb::addr_t addr, size_t size_hint, bool hardware, - CreateBreakpointFunc create_func); - - Status DecRef(lldb::addr_t addr); - - Status EnableBreakpoint(lldb::addr_t addr); - - Status DisableBreakpoint(lldb::addr_t addr); - - Status GetBreakpoint(lldb::addr_t addr, NativeBreakpointSP &breakpoint_sp); - - Status RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, size_t size) const; - -private: - typedef std::map BreakpointMap; - - std::recursive_mutex m_mutex; - BreakpointMap m_breakpoints; -}; } #endif // ifndef liblldb_NativeBreakpointList_h_ Index: lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h =================================================================== --- lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h +++ lldb/trunk/include/lldb/Host/common/NativeProcessProtocol.h @@ -25,6 +25,8 @@ #include "llvm/ADT/StringRef.h" #include "llvm/Support/Error.h" #include "llvm/Support/MemoryBuffer.h" +#include +#include #include namespace lldb_private { @@ -35,8 +37,6 @@ // NativeProcessProtocol //------------------------------------------------------------------ class NativeProcessProtocol { - friend class SoftwareBreakpoint; - public: virtual ~NativeProcessProtocol() {} @@ -111,10 +111,6 @@ virtual Status RemoveBreakpoint(lldb::addr_t addr, bool hardware = false); - virtual Status EnableBreakpoint(lldb::addr_t addr); - - virtual Status DisableBreakpoint(lldb::addr_t addr); - //---------------------------------------------------------------------- // Hardware Breakpoint functions //---------------------------------------------------------------------- @@ -402,6 +398,13 @@ } protected: + struct SoftwareBreakpoint { + uint32_t ref_count; + llvm::SmallVector saved_opcodes; + llvm::ArrayRef breakpoint_opcodes; + }; + + std::unordered_map m_software_breakpoints; lldb::pid_t m_pid; std::vector> m_threads; @@ -415,7 +418,6 @@ std::recursive_mutex m_delegates_mutex; std::vector m_delegates; - NativeBreakpointList m_breakpoint_list; NativeWatchpointList m_watchpoint_list; HardwareBreakpointMap m_hw_breakpoints_map; int m_terminal_fd; @@ -446,7 +448,9 @@ // ----------------------------------------------------------- Internal // interface for software breakpoints // ----------------------------------------------------------- + Status SetSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint); + Status RemoveSoftwareBreakpoint(lldb::addr_t addr); virtual llvm::Expected> GetSoftwareBreakpointTrapOpcode(size_t size_hint); @@ -474,6 +478,8 @@ private: void SynchronouslyNotifyProcessStateChanged(lldb::StateType state); + llvm::Expected + EnableSoftwareBreakpoint(lldb::addr_t addr, uint32_t size_hint); }; } // namespace lldb_private Index: lldb/trunk/include/lldb/Host/common/SoftwareBreakpoint.h =================================================================== --- lldb/trunk/include/lldb/Host/common/SoftwareBreakpoint.h +++ lldb/trunk/include/lldb/Host/common/SoftwareBreakpoint.h @@ -1,53 +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 "NativeBreakpoint.h" -#include "lldb/lldb-private-forward.h" - -namespace lldb_private { -class SoftwareBreakpoint : public NativeBreakpoint { - friend class NativeBreakpointList; - -public: - static Status 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: - Status DoEnable() override; - - Status 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 Status 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/trunk/include/lldb/lldb-private-forward.h =================================================================== --- lldb/trunk/include/lldb/lldb-private-forward.h +++ lldb/trunk/include/lldb/lldb-private-forward.h @@ -10,26 +10,15 @@ #ifndef LLDB_lldb_private_forward_h_ #define LLDB_lldb_private_forward_h_ -#if defined(__cplusplus) - -#include - namespace lldb_private { // --------------------------------------------------------------- Class // forward decls. // --------------------------------------------------------------- -class NativeBreakpoint; -class NativeBreakpointList; class NativeProcessProtocol; class NativeRegisterContext; class NativeThreadProtocol; class ResumeActionList; class UnixSignals; - -// --------------------------------------------------------------- SP/WP decls. -// --------------------------------------------------------------- -typedef std::shared_ptr NativeBreakpointSP; } -#endif // #if defined(__cplusplus) #endif // #ifndef LLDB_lldb_private_forward_h_ Index: lldb/trunk/lldb.xcodeproj/project.pbxproj =================================================================== --- lldb/trunk/lldb.xcodeproj/project.pbxproj +++ lldb/trunk/lldb.xcodeproj/project.pbxproj @@ -523,8 +523,6 @@ 3F81691A1ABA2419001DA9DF /* NameMatches.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 3F8169181ABA2419001DA9DF /* NameMatches.cpp */; }; 9A3D43D81F3151C400EB767C /* NameMatchesTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 9A3D43CB1F3150D200EB767C /* NameMatchesTest.cpp */; }; 268900C913353E5F00698AC0 /* NameToDIE.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */; }; - 232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */; }; - 232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */; }; 232CB619191E00CD00EF39FC /* NativeProcessProtocol.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */; }; 267A47FB1B1411C40021A5BC /* NativeRegisterContext.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 267A47FA1B1411C40021A5BC /* NativeRegisterContext.cpp */; }; 23F4034D1926E0F60046DC9B /* NativeRegisterContextRegisterInfo.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 23F403481926CC250046DC9B /* NativeRegisterContextRegisterInfo.cpp */; }; @@ -870,7 +868,6 @@ 26D7E45D13D5E30A007FD12B /* SocketAddress.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */; }; 23CB15451D66DA9300EDDDE1 /* SocketAddressTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F9391BDD332400BA9A93 /* SocketAddressTest.cpp */; }; 23CB153B1D66DA9300EDDDE1 /* SocketTest.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 2321F93A1BDD332400BA9A93 /* SocketTest.cpp */; }; - 232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */; }; 26603879211CA90F00329572 /* SourceBreakpoint.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26603870211CA90D00329572 /* SourceBreakpoint.cpp */; }; 2689004C13353E0400698AC0 /* SourceManager.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7E8F10F1B85900F91463 /* SourceManager.cpp */; }; 268900F313353E6F00698AC0 /* StackFrame.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 26BC7F3810F1B90C00F91463 /* StackFrame.cpp */; }; @@ -2299,9 +2296,6 @@ 9A3D43CB1F3150D200EB767C /* NameMatchesTest.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NameMatchesTest.cpp; sourceTree = ""; }; 2618D9EA12406FE600F2B8FE /* NameToDIE.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = NameToDIE.cpp; sourceTree = ""; }; 2618D957124056C700F2B8FE /* NameToDIE.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NameToDIE.h; sourceTree = ""; }; - 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = NativeBreakpoint.cpp; path = source/Host/common/NativeBreakpoint.cpp; sourceTree = ""; }; - 267A47F31B14116E0021A5BC /* NativeBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpoint.h; path = include/lldb/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 = ""; }; 267A47F41B1411750021A5BC /* NativeBreakpointList.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeBreakpointList.h; path = include/lldb/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; }; 267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = NativeProcessProtocol.h; path = include/lldb/Host/common/NativeProcessProtocol.h; sourceTree = ""; }; @@ -2925,8 +2919,6 @@ 26D7E45B13D5E2F9007FD12B /* SocketAddress.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SocketAddress.h; path = include/lldb/Host/SocketAddress.h; sourceTree = ""; }; 2321F9391BDD332400BA9A93 /* SocketAddressTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SocketAddressTest.cpp; sourceTree = ""; }; 2321F93A1BDD332400BA9A93 /* SocketTest.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = SocketTest.cpp; sourceTree = ""; }; - 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SoftwareBreakpoint.cpp; path = source/Host/common/SoftwareBreakpoint.cpp; sourceTree = ""; }; - 267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = SoftwareBreakpoint.h; path = include/lldb/Host/common/SoftwareBreakpoint.h; sourceTree = ""; }; 26603870211CA90D00329572 /* SourceBreakpoint.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SourceBreakpoint.cpp; path = "tools/lldb-vscode/SourceBreakpoint.cpp"; sourceTree = ""; }; 2660386D211CA90C00329572 /* SourceBreakpoint.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = SourceBreakpoint.h; path = "tools/lldb-vscode/SourceBreakpoint.h"; sourceTree = ""; }; 26BC7E8F10F1B85900F91463 /* SourceManager.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = SourceManager.cpp; path = source/Core/SourceManager.cpp; sourceTree = ""; }; @@ -5486,10 +5478,7 @@ 3FDFED2119BA6D55009756A7 /* HostNativeThreadBase.h */, 3FDFE57419AFABFD009756A7 /* HostProcess.h */, 3FDFE57519AFABFD009756A7 /* HostThread.h */, - 267A47F31B14116E0021A5BC /* NativeBreakpoint.h */, - 232CB60B191E00CC00EF39FC /* NativeBreakpoint.cpp */, 267A47F41B1411750021A5BC /* NativeBreakpointList.h */, - 232CB60D191E00CC00EF39FC /* NativeBreakpointList.cpp */, 267A47F51B14117F0021A5BC /* NativeProcessProtocol.h */, 232CB60F191E00CC00EF39FC /* NativeProcessProtocol.cpp */, 267A47F61B14118F0021A5BC /* NativeRegisterContext.h */, @@ -5508,8 +5497,6 @@ 236124A71986B50E004EFC37 /* Socket.h */, 26D7E45B13D5E2F9007FD12B /* SocketAddress.h */, 26D7E45C13D5E30A007FD12B /* SocketAddress.cpp */, - 267A47F21B14115A0021A5BC /* SoftwareBreakpoint.h */, - 232CB613191E00CC00EF39FC /* SoftwareBreakpoint.cpp */, 2689B0A4113EE3CD00A4AEDB /* Symbols.h */, 6DEC6F3A1BD66D950091ABA6 /* TaskPool.h */, 6DEC6F381BD66D750091ABA6 /* TaskPool.cpp */, @@ -8277,11 +8264,9 @@ 2689010113353E6F00698AC0 /* ThreadPlanStepOut.cpp in Sources */, 2689010213353E6F00698AC0 /* ThreadPlanStepOverBreakpoint.cpp in Sources */, 3FDFED2919BA6D96009756A7 /* ThreadLauncher.cpp in Sources */, - 232CB617191E00CD00EF39FC /* NativeBreakpointList.cpp in Sources */, 4C719395207D235400FDF430 /* OptionArgParser.cpp in Sources */, 942829561A89614C00521B30 /* JSON.cpp in Sources */, 267F68531CC02E920086832B /* RegisterContextLinux_s390x.cpp in Sources */, - 232CB615191E00CD00EF39FC /* NativeBreakpoint.cpp in Sources */, 2689010313353E6F00698AC0 /* ThreadPlanStepRange.cpp in Sources */, 2689010413353E6F00698AC0 /* ThreadPlanStepInRange.cpp in Sources */, 2689010513353E6F00698AC0 /* ThreadPlanStepOverRange.cpp in Sources */, @@ -8369,7 +8354,6 @@ 26F006561B4DD86700B872E5 /* DynamicLoaderWindowsDYLD.cpp in Sources */, 26DB3E1C1379E7AD0080DC73 /* ABIMacOSX_i386.cpp in Sources */, 26DB3E1F1379E7AD0080DC73 /* ABISysV_x86_64.cpp in Sources */, - 232CB61D191E00CD00EF39FC /* SoftwareBreakpoint.cpp in Sources */, 26A69C5F137A17A500262477 /* RegisterValue.cpp in Sources */, 2690B3711381D5C300ECFBAE /* Memory.cpp in Sources */, 4C562CC71CC07DF700C52EAC /* PDBASTParser.cpp in Sources */, Index: lldb/trunk/source/Host/CMakeLists.txt =================================================================== --- lldb/trunk/source/Host/CMakeLists.txt +++ lldb/trunk/source/Host/CMakeLists.txt @@ -28,8 +28,6 @@ common/LockFileBase.cpp common/MainLoop.cpp common/MonitoringProcessLauncher.cpp - common/NativeBreakpoint.cpp - common/NativeBreakpointList.cpp common/NativeWatchpointList.cpp common/NativeProcessProtocol.cpp common/NativeRegisterContext.cpp @@ -40,7 +38,6 @@ common/PseudoTerminal.cpp common/Socket.cpp common/SocketAddress.cpp - common/SoftwareBreakpoint.cpp common/StringConvert.cpp common/Symbols.cpp common/TaskPool.cpp Index: lldb/trunk/source/Host/common/NativeBreakpoint.cpp =================================================================== --- lldb/trunk/source/Host/common/NativeBreakpoint.cpp +++ lldb/trunk/source/Host/common/NativeBreakpoint.cpp @@ -1,109 +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 "lldb/Host/common/NativeBreakpoint.h" - -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" -#include "lldb/lldb-defines.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; -} - -Status 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 Status(); - } - - // Log and enable. - if (log) - log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " enabling...", - __FUNCTION__, m_addr); - - Status 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; -} - -Status 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 Status(); - } - - // Log and disable. - if (log) - log->Printf("NativeBreakpoint::%s addr = 0x%" PRIx64 " disabling...", - __FUNCTION__, m_addr); - - Status 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: lldb/trunk/source/Host/common/NativeBreakpointList.cpp =================================================================== --- lldb/trunk/source/Host/common/NativeBreakpointList.cpp +++ lldb/trunk/source/Host/common/NativeBreakpointList.cpp @@ -1,240 +0,0 @@ -//===-- NativeBreakpointList.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/Host/common/NativeBreakpointList.h" - -#include "lldb/Utility/Log.h" - -#include "lldb/Host/common/NativeBreakpoint.h" -#include "lldb/Host/common/SoftwareBreakpoint.h" - -using namespace lldb; -using namespace lldb_private; - -NativeBreakpointList::NativeBreakpointList() : m_mutex() {} - -Status 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 = %zu, hardware = %s", - __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); - - std::lock_guard guard(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 Status(); - } - - // Create a new breakpoint using the given create func. - if (log) - log->Printf( - "NativeBreakpointList::%s creating breakpoint for addr = 0x%" PRIx64 - ", size_hint = %zu, hardware = %s", - __FUNCTION__, addr, size_hint, hardware ? "true" : "false"); - - NativeBreakpointSP breakpoint_sp; - Status 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 = %zu, 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; -} - -Status NativeBreakpointList::DecRef(lldb::addr_t addr) { - Status error; - - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, - addr); - - std::lock_guard guard(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; -} - -Status NativeBreakpointList::EnableBreakpoint(lldb::addr_t addr) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, - addr); - - std::lock_guard guard(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 Status("breakpoint not found"); - } - - // Enable it. - return iter->second->Enable(); -} - -Status NativeBreakpointList::DisableBreakpoint(lldb::addr_t addr) { - Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); - if (log) - log->Printf("NativeBreakpointList::%s addr = 0x%" PRIx64, __FUNCTION__, - addr); - - std::lock_guard guard(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 Status("breakpoint not found"); - } - - // Disable it. - return iter->second->Disable(); -} - -Status 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); - - std::lock_guard guard(m_mutex); - - // Ensure we have said breakpoint. - auto iter = m_breakpoints.find(addr); - if (iter == m_breakpoints.end()) { - // Not found! - breakpoint_sp.reset(); - return Status("breakpoint not found"); - } - - // Disable it. - breakpoint_sp = iter->second; - return Status(); -} - -Status NativeBreakpointList::RemoveTrapsFromBuffer(lldb::addr_t addr, void *buf, - size_t size) const { - auto data = llvm::makeMutableArrayRef(static_cast(buf), size); - for (const auto &map : m_breakpoints) { - const auto &bp_sp = map.second; - // Not software breakpoint, ignore - if (!bp_sp->IsSoftwareBreakpoint()) - continue; - auto software_bp_sp = std::static_pointer_cast(bp_sp); - - lldb::addr_t bp_addr = map.first; - auto opcode_size = software_bp_sp->m_opcode_size; - - // Breapoint not in range, ignore - if (bp_addr + opcode_size < addr || addr + size <= bp_addr) - continue; - - auto saved_opcodes = - llvm::makeArrayRef(software_bp_sp->m_saved_opcodes, opcode_size); - if (bp_addr < addr) { - saved_opcodes = saved_opcodes.drop_front(addr - bp_addr); - bp_addr = addr; - } - auto bp_data = data.drop_front(bp_addr - addr); - std::copy_n(saved_opcodes.begin(), - std::min(saved_opcodes.size(), bp_data.size()), - bp_data.begin()); - } - return Status(); -} Index: lldb/trunk/source/Host/common/NativeProcessProtocol.cpp =================================================================== --- lldb/trunk/source/Host/common/NativeProcessProtocol.cpp +++ lldb/trunk/source/Host/common/NativeProcessProtocol.cpp @@ -9,9 +9,9 @@ #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/Host.h" +#include "lldb/Host/common/NativeBreakpointList.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/common/NativeThreadProtocol.h" -#include "lldb/Host/common/SoftwareBreakpoint.h" #include "lldb/Utility/LLDBAssert.h" #include "lldb/Utility/Log.h" #include "lldb/Utility/State.h" @@ -359,17 +359,161 @@ Status 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); + LLDB_LOG(log, "addr = {0:x}, size_hint = {1}", addr, size_hint); + + auto it = m_software_breakpoints.find(addr); + if (it != m_software_breakpoints.end()) { + ++it->second.ref_count; + return Status(); + } + auto expected_bkpt = EnableSoftwareBreakpoint(addr, size_hint); + if (!expected_bkpt) + return Status(expected_bkpt.takeError()); - return m_breakpoint_list.AddRef( - addr, size_hint, false, - [this](lldb::addr_t addr, size_t size_hint, bool /* hardware */, - NativeBreakpointSP &breakpoint_sp) -> Status { - return SoftwareBreakpoint::CreateSoftwareBreakpoint( - *this, addr, size_hint, breakpoint_sp); - }); + m_software_breakpoints.emplace(addr, std::move(*expected_bkpt)); + return Status(); +} + +Status NativeProcessProtocol::RemoveSoftwareBreakpoint(lldb::addr_t addr) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + LLDB_LOG(log, "addr = {0:x}", addr); + auto it = m_software_breakpoints.find(addr); + if (it == m_software_breakpoints.end()) + return Status("Breakpoint not found."); + assert(it->second.ref_count > 0); + if (--it->second.ref_count > 0) + return Status(); + + // This is the last reference. Let's remove the breakpoint. + Status error; + + // Clear a software breakpoint instruction + llvm::SmallVector curr_break_op( + it->second.breakpoint_opcodes.size(), 0); + + // Read the breakpoint opcode + size_t bytes_read = 0; + error = + ReadMemory(addr, curr_break_op.data(), curr_break_op.size(), bytes_read); + if (error.Fail() || bytes_read < curr_break_op.size()) { + return Status("addr=0x%" PRIx64 + ": tried to read %zu bytes but only read %zu", + addr, curr_break_op.size(), bytes_read); + } + const auto &saved = it->second.saved_opcodes; + // Make sure the breakpoint opcode exists at this address + if (makeArrayRef(curr_break_op) != it->second.breakpoint_opcodes) { + if (curr_break_op != it->second.saved_opcodes) + return Status("Original breakpoint trap is no longer in memory."); + LLDB_LOG(log, + "Saved opcodes ({0:@[x]}) have already been restored at {1:x}.", + llvm::make_range(saved.begin(), saved.end()), addr); + } else { + // We found a valid breakpoint opcode at this address, now restore the + // saved opcode. + size_t bytes_written = 0; + error = WriteMemory(addr, saved.data(), saved.size(), bytes_written); + if (error.Fail() || bytes_written < saved.size()) { + return Status("addr=0x%" PRIx64 + ": tried to write %zu bytes but only wrote %zu", + addr, saved.size(), bytes_written); + } + + // Verify that our original opcode made it back to the inferior + llvm::SmallVector verify_opcode(saved.size(), 0); + size_t verify_bytes_read = 0; + error = ReadMemory(addr, verify_opcode.data(), verify_opcode.size(), + verify_bytes_read); + if (error.Fail() || verify_bytes_read < verify_opcode.size()) { + return Status("addr=0x%" PRIx64 + ": tried to read %zu verification bytes but only read %zu", + addr, verify_opcode.size(), verify_bytes_read); + } + if (verify_opcode != saved) + LLDB_LOG(log, "Restoring bytes at {0:x}: {1:@[x]}", addr, + llvm::make_range(saved.begin(), saved.end())); + } + + m_software_breakpoints.erase(it); + return Status(); +} + +llvm::Expected +NativeProcessProtocol::EnableSoftwareBreakpoint(lldb::addr_t addr, + uint32_t size_hint) { + Log *log(GetLogIfAnyCategoriesSet(LIBLLDB_LOG_BREAKPOINTS)); + + auto expected_trap = GetSoftwareBreakpointTrapOpcode(size_hint); + if (!expected_trap) + return expected_trap.takeError(); + + llvm::SmallVector saved_opcode_bytes(expected_trap->size(), 0); + // Save the original opcodes by reading them so we can restore later. + size_t bytes_read = 0; + Status error = ReadMemory(addr, saved_opcode_bytes.data(), + saved_opcode_bytes.size(), bytes_read); + if (error.Fail()) + return error.ToError(); + + // Ensure we read as many bytes as we expected. + if (bytes_read != saved_opcode_bytes.size()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed to read memory while attempting to set breakpoint: attempted " + "to read {0} bytes but only read {1}.", + saved_opcode_bytes.size(), bytes_read); + } + + LLDB_LOG( + log, "Overwriting bytes at {0:x}: {1:@[x]}", addr, + llvm::make_range(saved_opcode_bytes.begin(), saved_opcode_bytes.end())); + + // Write a software breakpoint in place of the original opcode. + size_t bytes_written = 0; + error = WriteMemory(addr, expected_trap->data(), expected_trap->size(), + bytes_written); + if (error.Fail()) + return error.ToError(); + + // Ensure we wrote as many bytes as we expected. + if (bytes_written != expected_trap->size()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed write memory while attempting to set " + "breakpoint: attempted to write {0} bytes but only wrote {1}", + expected_trap->size(), bytes_written); + } + + llvm::SmallVector verify_bp_opcode_bytes(expected_trap->size(), + 0); + size_t verify_bytes_read = 0; + error = ReadMemory(addr, verify_bp_opcode_bytes.data(), + verify_bp_opcode_bytes.size(), verify_bytes_read); + if (error.Fail()) + return error.ToError(); + + // Ensure we read as many verification bytes as we expected. + if (verify_bytes_read != verify_bp_opcode_bytes.size()) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Failed to read memory while " + "attempting to verify breakpoint: attempted to read {0} bytes " + "but only read {1}", + verify_bp_opcode_bytes.size(), verify_bytes_read); + } + + if (llvm::makeArrayRef(verify_bp_opcode_bytes.data(), verify_bytes_read) != + *expected_trap) { + return llvm::createStringError( + llvm::inconvertibleErrorCode(), + "Verification of software breakpoint " + "writing failed - trap opcodes not successfully read back " + "after writing when setting breakpoint at {0:x}", + addr); + } + + LLDB_LOG(log, "addr = {0:x}: SUCCESS"); + return SoftwareBreakpoint{1, saved_opcode_bytes, *expected_trap}; } llvm::Expected> @@ -455,27 +599,15 @@ if (breakpoint_addr >= breakpoint_size) breakpoint_addr -= breakpoint_size; - // Check if we stopped because of a breakpoint. - NativeBreakpointSP breakpoint_sp; - error = m_breakpoint_list.GetBreakpoint(breakpoint_addr, breakpoint_sp); - if (!error.Success() || !breakpoint_sp) { + if (m_software_breakpoints.count(breakpoint_addr) == 0) { // We didn't find one at a software probe location. Nothing to do. LLDB_LOG(log, - "pid {0} no lldb breakpoint found at current pc with " + "pid {0} no lldb software breakpoint found at current pc with " "adjustment: {1}", GetID(), breakpoint_addr); return; } - // If the breakpoint is not a software breakpoint, nothing to do. - if (!breakpoint_sp->IsSoftwareBreakpoint()) { - LLDB_LOG( - log, - "pid {0} breakpoint found at {1:x}, not software, nothing to adjust", - GetID(), breakpoint_addr); - return; - } - // // We have a software breakpoint and need to adjust the PC. // @@ -499,20 +631,7 @@ if (hardware) return RemoveHardwareBreakpoint(addr); else - return m_breakpoint_list.DecRef(addr); -} - -Status NativeProcessProtocol::EnableBreakpoint(lldb::addr_t addr) { - return m_breakpoint_list.EnableBreakpoint(addr); -} - -Status NativeProcessProtocol::DisableBreakpoint(lldb::addr_t addr) { - return m_breakpoint_list.DisableBreakpoint(addr); -} - -lldb::StateType NativeProcessProtocol::GetState() const { - std::lock_guard guard(m_state_mutex); - return m_state; + return RemoveSoftwareBreakpoint(addr); } Status NativeProcessProtocol::ReadMemoryWithoutTrap(lldb::addr_t addr, @@ -521,7 +640,31 @@ Status error = ReadMemory(addr, buf, size, bytes_read); if (error.Fail()) return error; - return m_breakpoint_list.RemoveTrapsFromBuffer(addr, buf, size); + + auto data = + llvm::makeMutableArrayRef(static_cast(buf), bytes_read); + for (const auto &pair : m_software_breakpoints) { + lldb::addr_t bp_addr = pair.first; + auto saved_opcodes = makeArrayRef(pair.second.saved_opcodes); + + if (bp_addr + saved_opcodes.size() < addr || addr + bytes_read <= bp_addr) + continue; // Breapoint not in range, ignore + + if (bp_addr < addr) { + saved_opcodes = saved_opcodes.drop_front(addr - bp_addr); + bp_addr = addr; + } + auto bp_data = data.drop_front(bp_addr - addr); + std::copy_n(saved_opcodes.begin(), + std::min(saved_opcodes.size(), bp_data.size()), + bp_data.begin()); + } + return Status(); +} + +lldb::StateType NativeProcessProtocol::GetState() const { + std::lock_guard guard(m_state_mutex); + return m_state; } void NativeProcessProtocol::SetState(lldb::StateType state, Index: lldb/trunk/source/Host/common/NativeThreadProtocol.cpp =================================================================== --- lldb/trunk/source/Host/common/NativeThreadProtocol.cpp +++ lldb/trunk/source/Host/common/NativeThreadProtocol.cpp @@ -11,7 +11,6 @@ #include "lldb/Host/common/NativeProcessProtocol.h" #include "lldb/Host/common/NativeRegisterContext.h" -#include "lldb/Host/common/SoftwareBreakpoint.h" using namespace lldb; using namespace lldb_private; Index: lldb/trunk/source/Host/common/SoftwareBreakpoint.cpp =================================================================== --- lldb/trunk/source/Host/common/SoftwareBreakpoint.cpp +++ lldb/trunk/source/Host/common/SoftwareBreakpoint.cpp @@ -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 "lldb/Host/common/SoftwareBreakpoint.h" - -#include "lldb/Host/Debug.h" -#include "lldb/Utility/Log.h" -#include "lldb/Utility/Status.h" - -#include "lldb/Host/common/NativeProcessProtocol.h" - -using namespace lldb_private; - -// ------------------------------------------------------------------- static -// members ------------------------------------------------------------------- - -Status 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 Status("SoftwareBreakpoint::%s invalid load address specified.", - __FUNCTION__); - - // Ask the NativeProcessProtocol subclass to fill in the correct software - // breakpoint trap for the breakpoint site. - auto expected_opcode = process.GetSoftwareBreakpointTrapOpcode(size_hint); - if (!expected_opcode) - return Status(expected_opcode.takeError()); - - assert(expected_opcode->size() > 0); - assert(expected_opcode->size() <= MAX_TRAP_OPCODE_SIZE); - - // Enable the breakpoint. - uint8_t saved_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; - Status error = - EnableSoftwareBreakpoint(process, addr, expected_opcode->size(), - expected_opcode->data(), 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, - expected_opcode->data(), - expected_opcode->size())); - return Status(); -} - -Status 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. - size_t bytes_read = 0; - - Status error = - process.ReadMemory(addr, saved_opcode_bytes, 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 != bp_opcode_size) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: attempted to read %zu bytes " - "but only read %zu", - __FUNCTION__, bp_opcode_size, bytes_read); - return Status("SoftwareBreakpoint::%s failed to read memory while " - "attempting to set breakpoint: attempted to read %zu bytes " - "but only read %zu", - __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%hhx)", - __FUNCTION__, addr, i++, *read_byte); - } - } - - // Write a software breakpoint in place of the original opcode. - size_t bytes_written = 0; - error = - process.WriteMemory(addr, bp_opcode_bytes, 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 != bp_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s failed write memory while attempting to set " - "breakpoint: attempted to write %zu bytes but only wrote %zu", - __FUNCTION__, bp_opcode_size, bytes_written); - if (log) - log->PutCString(error.AsCString()); - return error; - } - - uint8_t verify_bp_opcode_bytes[MAX_TRAP_OPCODE_SIZE]; - size_t verify_bytes_read = 0; - error = process.ReadMemory(addr, verify_bp_opcode_bytes, 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 != bp_opcode_size) { - if (log) - log->Printf("SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify breakpoint: attempted to read %zu " - "bytes but only read %zu", - __FUNCTION__, bp_opcode_size, verify_bytes_read); - return Status( - "SoftwareBreakpoint::%s failed to read memory while " - "attempting to verify breakpoint: attempted to read %zu bytes " - "but only read %zu", - __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 Status("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 Status(); -} - -// ------------------------------------------------------------------- -// 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); -} - -Status SoftwareBreakpoint::DoEnable() { - return EnableSoftwareBreakpoint(m_process, m_addr, m_opcode_size, - m_trap_opcodes, m_saved_opcodes); -} - -Status SoftwareBreakpoint::DoDisable() { - Status 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 - size_t bytes_read = 0; - error = - m_process.ReadMemory(m_addr, curr_break_op, m_opcode_size, bytes_read); - if (error.Success() && bytes_read < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpointr::%s addr=0x%" PRIx64 - ": tried to read %zu bytes but only read %zu", - __FUNCTION__, m_addr, m_opcode_size, bytes_read); - } - if (error.Success()) { - bool verify = false; - // Make sure the 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. - size_t bytes_written = 0; - error = m_process.WriteMemory(m_addr, m_saved_opcodes, m_opcode_size, - bytes_written); - if (error.Success() && bytes_written < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s addr=0x%" PRIx64 - ": tried to write %zu bytes but only wrote %zu", - __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 - - size_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 < m_opcode_size) { - error.SetErrorStringWithFormat( - "SoftwareBreakpoint::%s addr=0x%" PRIx64 - ": tried to read %zu verification bytes but only read %zu", - __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%hhx", - __FUNCTION__, m_addr, i++, *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: lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp +++ lldb/trunk/source/Plugins/Process/Linux/NativeProcessLinux.cpp @@ -29,7 +29,6 @@ #include "lldb/Host/HostProcess.h" #include "lldb/Host/PseudoTerminal.h" #include "lldb/Host/ThreadLauncher.h" -#include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/linux/Ptrace.h" #include "lldb/Host/linux/Uio.h" Index: lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp =================================================================== --- lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp +++ lldb/trunk/source/Plugins/Process/NetBSD/NativeProcessNetBSD.cpp @@ -16,7 +16,6 @@ // Other libraries and framework includes #include "Plugins/Process/POSIX/ProcessPOSIXLog.h" #include "lldb/Host/HostProcess.h" -#include "lldb/Host/common/NativeBreakpoint.h" #include "lldb/Host/common/NativeRegisterContext.h" #include "lldb/Host/posix/ProcessLauncherPosixFork.h" #include "lldb/Target/Process.h"