From f5389ddbfb6ee63368746d8abdde6ae03496fc56 Mon Sep 17 00:00:00 2001 From: Xusheng Date: Mon, 22 Apr 2024 12:48:28 +0800 Subject: [PATCH] Use the MemoryMap API to represent the memory regions for the debugger. Fix https://github.com/Vector35/debugger/issues/213 --- api/debuggerapi.h | 5 + api/debuggercontroller.cpp | 18 +++ api/ffi.h | 5 + core/debugger.cpp | 2 - core/debuggercontroller.cpp | 163 ++++++++++++------------- core/debuggercontroller.h | 32 +++-- core/debuggerfileaccessor.cpp | 111 +++++++++++++++++ core/debuggerfileaccessor.h | 50 ++++++++ core/debuggerstate.cpp | 5 + core/debuggerstate.h | 1 - core/ffi.cpp | 26 ++-- core/processview.cpp | 222 ---------------------------------- core/processview.h | 95 --------------- ui/breakpointswidget.cpp | 13 +- ui/ui.cpp | 107 ++++++---------- ui/ui.h | 1 + 16 files changed, 358 insertions(+), 498 deletions(-) create mode 100644 core/debuggerfileaccessor.cpp create mode 100644 core/debuggerfileaccessor.h delete mode 100644 core/processview.cpp delete mode 100644 core/processview.h diff --git a/api/debuggerapi.h b/api/debuggerapi.h index 9ca912c..5c702b3 100644 --- a/api/debuggerapi.h +++ b/api/debuggerapi.h @@ -593,6 +593,11 @@ namespace BinaryNinjaDebuggerAPI { bool IsTTD(); void PostDebuggerEvent(const DebuggerEvent& event); + + bool RemoveDebuggerMemoryRegion(); + bool ReAddDebuggerMemoryRegion(); + + uint64_t GetViewFileSegmentsStart(); }; diff --git a/api/debuggercontroller.cpp b/api/debuggercontroller.cpp index b8d26bd..259a630 100644 --- a/api/debuggercontroller.cpp +++ b/api/debuggercontroller.cpp @@ -912,3 +912,21 @@ void DebuggerController::PostDebuggerEvent(const DebuggerEvent &event) BNDebuggerFreeString(evt->data.messageData.message); delete evt; } + + +bool DebuggerController::RemoveDebuggerMemoryRegion() +{ + return BNDebuggerRemoveMemoryRegion(m_object); +} + + +bool DebuggerController::ReAddDebuggerMemoryRegion() +{ + return BNDebuggerReAddMemoryRegion(m_object); +} + + +uint64_t DebuggerController::GetViewFileSegmentsStart() +{ + return BNDebuggerGetViewFileSegmentsStart(m_object); +} diff --git a/api/ffi.h b/api/ffi.h index de00d43..ce22a40 100644 --- a/api/ffi.h +++ b/api/ffi.h @@ -491,6 +491,11 @@ extern "C" DEBUGGER_FFI_API void BNDebuggerPostDebuggerEvent(BNDebuggerController* controller, BNDebuggerEvent* event); + DEBUGGER_FFI_API bool BNDebuggerRemoveMemoryRegion(BNDebuggerController* controller); + DEBUGGER_FFI_API bool BNDebuggerReAddMemoryRegion(BNDebuggerController* controller); + + DEBUGGER_FFI_API uint64_t BNDebuggerGetViewFileSegmentsStart(BNDebuggerController* controller); + // DebugAdapterType DEBUGGER_FFI_API BNDebugAdapterType* BNGetDebugAdapterTypeByName(const char* name); DEBUGGER_FFI_API bool BNDebugAdapterTypeCanExecute(BNDebugAdapterType* adapter, BNBinaryView* data); diff --git a/core/debugger.cpp b/core/debugger.cpp index edfac23..bc0e090 100644 --- a/core/debugger.cpp +++ b/core/debugger.cpp @@ -15,7 +15,6 @@ limitations under the License. */ #include -#include "processview.h" #include "adapters/lldbadapter.h" #ifdef WIN32 #include "adapters/dbgengadapter.h" @@ -181,7 +180,6 @@ extern "C" LogDebug("Native debugger loaded!"); RegisterSettings(); InitDebugAdapterTypes(); - InitDebugProcessViewType(); return true; } } diff --git a/core/debuggercontroller.cpp b/core/debuggercontroller.cpp index 8c850a0..cea40cf 100644 --- a/core/debuggercontroller.cpp +++ b/core/debuggercontroller.cpp @@ -19,6 +19,7 @@ limitations under the License. #include "lowlevelilinstruction.h" #include "mediumlevelilinstruction.h" #include "highlevelilinstruction.h" +#include "debuggerfileaccessor.h" using namespace BinaryNinjaDebugger; @@ -27,7 +28,9 @@ DebuggerController::DebuggerController(BinaryViewRef data) INIT_DEBUGGER_API_OBJECT(); m_file = data->GetFile(); - m_viewName = data->GetTypeName(); + m_data = data; + m_data->RegisterNotification(this); + m_viewStart = m_data->GetStart(); m_state = new DebuggerState(data, this); m_adapter = nullptr; @@ -39,7 +42,6 @@ DebuggerController::DebuggerController(BinaryViewRef data) DebuggerController::~DebuggerController() { m_file = nullptr; - m_liveView = nullptr; if (m_state) { @@ -394,7 +396,7 @@ DebugStopReason DebuggerController::StepIntoIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -404,7 +406,7 @@ DebugStopReason DebuggerController::StepIntoIL(BNFunctionGraphType il) if (!llil) return SingleStep; - size_t start = llil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = llil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < llil->GetInstructionCount()) { if (llil->GetInstruction(start).address == newRemoteRip) @@ -424,7 +426,7 @@ DebugStopReason DebuggerController::StepIntoIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -434,7 +436,7 @@ DebugStopReason DebuggerController::StepIntoIL(BNFunctionGraphType il) if (!mlil) return SingleStep; - size_t start = mlil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = mlil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < mlil->GetInstructionCount()) { if (mlil->GetInstruction(start).address == newRemoteRip) @@ -455,7 +457,7 @@ DebugStopReason DebuggerController::StepIntoIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -499,7 +501,7 @@ DebugStopReason DebuggerController::StepIntoReverseIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -509,7 +511,7 @@ DebugStopReason DebuggerController::StepIntoReverseIL(BNFunctionGraphType il) if (!llil) return SingleStep; - size_t start = llil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = llil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < llil->GetInstructionCount()) { if (llil->GetInstruction(start).address == newRemoteRip) @@ -529,7 +531,7 @@ DebugStopReason DebuggerController::StepIntoReverseIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -539,7 +541,7 @@ DebugStopReason DebuggerController::StepIntoReverseIL(BNFunctionGraphType il) if (!mlil) return SingleStep; - size_t start = mlil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = mlil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < mlil->GetInstructionCount()) { if (mlil->GetInstruction(start).address == newRemoteRip) @@ -560,7 +562,7 @@ DebugStopReason DebuggerController::StepIntoReverseIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -657,7 +659,7 @@ DebugStopReason DebuggerController::StepOverIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -667,7 +669,7 @@ DebugStopReason DebuggerController::StepOverIL(BNFunctionGraphType il) if (!llil) return SingleStep; - size_t start = llil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = llil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < llil->GetInstructionCount()) { if (llil->GetInstruction(start).address == newRemoteRip) @@ -686,7 +688,7 @@ DebugStopReason DebuggerController::StepOverIL(BNFunctionGraphType il) if (!ExpectSingleStep(reason)) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -696,7 +698,7 @@ DebugStopReason DebuggerController::StepOverIL(BNFunctionGraphType il) if (!mlil) return SingleStep; - size_t start = mlil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = mlil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < mlil->GetInstructionCount()) { if (mlil->GetInstruction(start).address == newRemoteRip) @@ -717,7 +719,7 @@ DebugStopReason DebuggerController::StepOverIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -760,7 +762,7 @@ DebugStopReason DebuggerController::StepOverReverseIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -770,7 +772,7 @@ DebugStopReason DebuggerController::StepOverReverseIL(BNFunctionGraphType il) if (!llil) return SingleStep; - size_t start = llil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = llil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < llil->GetInstructionCount()) { if (llil->GetInstruction(start).address == newRemoteRip) @@ -789,7 +791,7 @@ DebugStopReason DebuggerController::StepOverReverseIL(BNFunctionGraphType il) if (!ExpectSingleStep(reason)) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -799,7 +801,7 @@ DebugStopReason DebuggerController::StepOverReverseIL(BNFunctionGraphType il) if (!mlil) return SingleStep; - size_t start = mlil->GetInstructionStart(m_liveView->GetDefaultArchitecture(), newRemoteRip); + size_t start = mlil->GetInstructionStart(GetData()->GetDefaultArchitecture(), newRemoteRip); if (start < mlil->GetInstructionCount()) { if (mlil->GetInstruction(start).address == newRemoteRip) @@ -820,7 +822,7 @@ DebugStopReason DebuggerController::StepOverReverseIL(BNFunctionGraphType il) return reason; uint64_t newRemoteRip = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(newRemoteRip); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(newRemoteRip); if (functions.empty()) return SingleStep; @@ -899,7 +901,7 @@ DebugStopReason DebuggerController::StepOverReverseAndWait(BNFunctionGraphType i DebugStopReason DebuggerController::EmulateStepReturnAndWait() { uint64_t address = m_state->IP(); - std::vector functions = m_liveView->GetAnalysisFunctionsContainingAddress(address); + std::vector functions = GetData()->GetAnalysisFunctionsContainingAddress(address); if (functions.empty()) return InternalError; @@ -1049,24 +1051,9 @@ DebugStopReason DebuggerController::RunToAndWait(const std::vector& re bool DebuggerController::CreateDebuggerBinaryView() { - BinaryViewTypeRef viewType = BinaryViewType::GetByName("Debugger"); - if (!viewType) - return false; - - BinaryViewRef liveView = viewType->Create(GetData()); - if (!liveView) - return false; - BinaryViewRef data = GetData(); - if (!data->GetDefaultArchitecture() || !data->GetDefaultPlatform()) - { - LogWarn("Fail to create debugger view. The input view must have an architecture and platform"); - return false; - } - liveView->SetDefaultArchitecture(data->GetDefaultArchitecture()); - liveView->SetDefaultPlatform(data->GetDefaultPlatform()); - SetLiveView(liveView); - + m_accessor = new DebuggerFileAccessor(data); + data->GetMemoryMap()->AddRemoteMemoryRegion("debugger", 0, m_accessor); return true; } @@ -1092,7 +1079,7 @@ void DebuggerController::DetectLoadedModule() } else { - if (remoteBase != GetData()->GetStart()) + if (remoteBase != GetViewFileSegmentsStart()) { // remote base is different from the local base, first need a rebase if (!m_file->Rebase(GetData(), remoteBase, [&](size_t cur, size_t total) { return true; })) @@ -1100,15 +1087,9 @@ void DebuggerController::DetectLoadedModule() LogWarn("rebase failed"); } } - - Ref rebasedView = m_file->GetViewOfType(m_viewName); - - bool ok = m_file->CreateSnapshotedView(rebasedView, "Debugger", [&](size_t cur, size_t total) { return true; }); - if (!ok) - LogWarn("create snapshoted view failed"); } - m_liveView->UpdateAnalysis(); + GetData()->UpdateAnalysis(); m_inputFileLoaded = true; } @@ -1549,12 +1530,14 @@ void DebuggerController::EventHandler(const DebuggerEvent& event) { m_inputFileLoaded = false; m_initialBreakpointSeen = false; - // The m_liveView can be nullptr if the launch attempt fails because of the safe mode - if (m_liveView) - m_liveView->GetFile()->UnregisterViewOfType("Debugger", m_liveView); - SetLiveView(nullptr); + RemoveDebuggerMemoryRegion(); + if (m_accessor) + { + delete m_accessor; + m_accessor = nullptr; + } + m_lastIP = m_currentIP; m_currentIP = 0; - m_lastIP = 0; m_state->SetConnectionStatus(DebugAdapterNotConnectedStatus); m_state->SetExecutionStatus(DebugAdapterInvalidStatus); break; @@ -1726,7 +1709,7 @@ void DebuggerController::NotifyEvent(DebuggerEventType eventType) // We should call these two function instead of DebugAdapter::ReadMemory(), which will skip the memory cache DataBuffer DebuggerController::ReadMemory(std::uintptr_t address, std::size_t size) { - if (!m_liveView) + if (!GetData()) return DataBuffer {}; if (!m_state->IsConnected()) @@ -1745,7 +1728,7 @@ DataBuffer DebuggerController::ReadMemory(std::uintptr_t address, std::size_t si bool DebuggerController::WriteMemory(std::uintptr_t address, const DataBuffer& buffer) { - if (!m_liveView) + if (!GetData()) return false; if (!m_state->IsConnected()) @@ -1871,11 +1854,11 @@ void DebuggerController::ProcessOneVariable(uint64_t varAddress, ConfidenceDefineDataVariable(varAddress, type); + GetData()->DefineDataVariable(varAddress, type); if (!name.empty()) { SymbolRef sym = new Symbol(DataSymbol, name, name, name, varAddress); - m_liveView->DefineUserSymbol(sym); + GetData()->DefineUserSymbol(sym); } m_debuggerVariables[varAddress] = varNameAndType; } @@ -1894,10 +1877,10 @@ void DebuggerController::ProcessOneVariable(uint64_t varAddress, Confidence> type) { - size_t addressSize = m_liveView->GetAddressSize(); + size_t addressSize = GetData()->GetAddressSize(); if (type->IsPointer()) { - auto reader = BinaryReader(m_liveView); + auto reader = BinaryReader(GetData()); reader.Seek(address); uint64_t targetAddress = 0; bool readOk = false; @@ -1948,16 +1931,16 @@ void DebuggerController::UpdateStackVariables() if (!m_shouldAnnotateStackVariable) return; - if (!m_liveView) + if (!GetData()) return; - auto id = m_liveView->BeginUndoActions(); + auto id = GetData()->BeginUndoActions(); std::vector threads = GetAllThreads(); uint64_t frameAdjustment = 0; - if (!m_liveView->GetDefaultArchitecture()) + if (!GetData()->GetDefaultArchitecture()) return; - std::string archName = m_liveView->GetDefaultArchitecture()->GetName(); + std::string archName = GetData()->GetDefaultArchitecture()->GetName(); if ((archName == "x86") || (archName == "x86_64")) frameAdjustment = 8; @@ -1975,7 +1958,7 @@ void DebuggerController::UpdateStackVariables() const DebugFrame& frame = frames[i]; const DebugFrame& prevFrame = frames[i + 1]; // If there is no function at a stacktrace function start, add one - auto functions = m_liveView->GetAnalysisFunctionsForAddress(frame.m_functionStart); + auto functions = GetData()->GetAnalysisFunctionsForAddress(frame.m_functionStart); if (functions.empty()) continue; @@ -2000,8 +1983,8 @@ void DebuggerController::UpdateStackVariables() for (const DebugFrame& frame : frames) { // Annotate the stack pointer and the frame pointer, using the current stack frame - m_liveView->SetCommentForAddress(frame.m_sp, fmt::format("Stack #{}\n====================", frame.m_index)); - m_liveView->SetCommentForAddress(frame.m_fp, fmt::format("Frame #{}", frame.m_index)); + GetData()->SetCommentForAddress(frame.m_sp, fmt::format("Stack #{}\n====================", frame.m_index)); + GetData()->SetCommentForAddress(frame.m_fp, fmt::format("Frame #{}", frame.m_index)); m_addressesWithComment.insert(frame.m_sp); m_addressesWithComment.insert(frame.m_fp); @@ -2021,17 +2004,17 @@ void DebuggerController::UpdateStackVariables() if (iter != m_addressesWithVariable.end()) m_addressesWithVariable.erase(iter); - m_liveView->UndefineDataVariable(address); - auto symbol = m_liveView->GetSymbolByAddress(address); + GetData()->UndefineDataVariable(address); + auto symbol = GetData()->GetSymbolByAddress(address); if (symbol) - m_liveView->UndefineUserSymbol(symbol); + GetData()->UndefineUserSymbol(symbol); } for (uint64_t address : oldAddressWithComment) { - m_liveView->SetCommentForAddress(address, ""); + GetData()->SetCommentForAddress(address, ""); } - m_liveView->ForgetUndoActions(id); + GetData()->ForgetUndoActions(id); } @@ -2049,7 +2032,7 @@ void DebuggerController::AddRegisterValuesToExpressionParser() values.emplace_back(reg.m_value); } - m_liveView->AddExpressionParserMagicValues(names, values); + GetData()->AddExpressionParserMagicValues(names, values); } @@ -2239,11 +2222,9 @@ DebugStopReason DebuggerController::ExecuteAdapterAndWait(const DebugAdapterOper operationRequested = m_adapter->BreakInto(); break; case DebugAdapterQuit: - m_liveView->AbortAnalysis(); m_adapter->Quit(); break; case DebugAdapterDetach: - m_liveView->AbortAnalysis(); m_adapter->Detach(); break; case DebugAdapterLaunch: @@ -2470,8 +2451,8 @@ std::string DebuggerController::GetAddressInformation(uint64_t address) return result; // Check pointer to strings - auto buffer = m_liveView->ReadBuffer(address, m_liveView->GetAddressSize()); - if (buffer.GetLength() == m_liveView->GetAddressSize()) + auto buffer = GetData()->ReadBuffer(address, GetData()->GetAddressSize()); + if (buffer.GetLength() == GetData()->GetAddressSize()) { uint64_t pointerValue = *reinterpret_cast(buffer.GetData()); if (pointerValue != 0) @@ -2485,7 +2466,7 @@ std::string DebuggerController::GetAddressInformation(uint64_t address) // Look for functions starting at the address - auto func = m_liveView->GetAnalysisFunction(m_liveView->GetDefaultPlatform(), address); + auto func = GetData()->GetAnalysisFunction(GetData()->GetDefaultPlatform(), address); if (func) { auto sym = func->GetSymbol(); @@ -2494,7 +2475,7 @@ std::string DebuggerController::GetAddressInformation(uint64_t address) } // Look for functions containing the address - for (const auto& func: m_liveView->GetAnalysisFunctionsContainingAddress(address)) + for (const auto& func: GetData()->GetAnalysisFunctionsContainingAddress(address)) { auto sym = func->GetSymbol(); if (sym) @@ -2504,7 +2485,7 @@ std::string DebuggerController::GetAddressInformation(uint64_t address) } // Look for symbols - auto sym = m_liveView->GetSymbolByAddress(address); + auto sym = GetData()->GetSymbolByAddress(address); if (sym) { return sym->GetShortName(); @@ -2512,9 +2493,9 @@ std::string DebuggerController::GetAddressInformation(uint64_t address) // Look for data variables DataVariable var; - if (m_liveView->GetDataVariableAtAddress(address, var)) + if (GetData()->GetDataVariableAtAddress(address, var)) { - sym = m_liveView->GetSymbolByAddress(var.address); + sym = GetData()->GetSymbolByAddress(var.address); if (sym) { return fmt::format("{} + 0x{:x}", sym->GetShortName(), address - var.address); @@ -2549,3 +2530,23 @@ bool DebuggerController::IsTTD() return false; return m_adapter->SupportFeature(DebugAdapterSupportTTD); } + + +bool DebuggerController::RemoveDebuggerMemoryRegion() +{ + bool ret = GetData()->GetMemoryMap()->RemoveMemoryRegion("debugger"); + if (!ret) + return false; + + auto segment = m_data->GetSegmentAt(0); + if (segment) + m_data->RemoveAutoSegment(segment->GetStart(), segment->GetLength()); + + return true; +} + + +bool DebuggerController::ReAddDebuggerMemoryRegion() +{ + return GetData()->GetMemoryMap()->AddRemoteMemoryRegion("debugger", 0, GetMemoryAccessor()); +} diff --git a/core/debuggercontroller.h b/core/debuggercontroller.h index 5ff4abc..3fe752b 100644 --- a/core/debuggercontroller.h +++ b/core/debuggercontroller.h @@ -22,6 +22,7 @@ limitations under the License. #include #include "ffi_global.h" #include "refcountobject.h" +#include "debuggerfileaccessor.h" DECLARE_DEBUGGER_API_OBJECT(BNDebuggerController, DebuggerController); @@ -54,7 +55,7 @@ namespace BinaryNinjaDebugger { // This is the controller class of the debugger. It receives the input from the UI/API, and then route them to // the state and UI, etc. Most actions should reach here. - class DebuggerController : public DbgRefCountObject + class DebuggerController : public DbgRefCountObject, BinaryNinja::BinaryDataNotification { IMPLEMENT_DEBUGGER_API_OBJECT(BNDebuggerController); @@ -62,8 +63,12 @@ namespace BinaryNinjaDebugger { DebugAdapter* m_adapter; DebuggerState* m_state; FileMetadataRef m_file; - std::string m_viewName; - BinaryViewRef m_liveView; + BinaryViewRef m_data; + DebuggerFileAccessor* m_accessor; + // This is the start address of the first file segments in the m_data. Unlike the return value of GetStart(), + // this does not change even if we add the debugger memory region. In the future, this should be provided by + // the binary view -- we will no longer need to track it ourselves + uint64_t m_viewStart; // inline static std::vector> g_debuggerControllers; static DbgRef* g_debuggerControllers; @@ -103,8 +108,6 @@ namespace BinaryNinjaDebugger { bool CreateDebugAdapter(); bool CreateDebuggerBinaryView(); - void SetLiveView(BinaryViewRef view) { m_liveView = view; } - DebugStopReason StepIntoIL(BNFunctionGraphType il); DebugStopReason StepIntoReverseIL(BNFunctionGraphType il); DebugStopReason StepOverIL(BNFunctionGraphType il); @@ -271,10 +274,11 @@ namespace BinaryNinjaDebugger { // getters DebugAdapter* GetAdapter() { return m_adapter; } DebuggerState* GetState() { return m_state; } - BinaryViewRef GetData() { return m_file->GetViewOfType(m_viewName); } + BinaryViewRef GetData() { return m_data; } FileMetadataRef GetFile() { return m_file; } void SetData(BinaryViewRef view) {} - BinaryViewRef GetLiveView() const { return m_liveView; } + BinaryViewRef GetLiveView() const { return m_data; } + DebuggerFileAccessor* GetMemoryAccessor() const { return m_accessor; } uint32_t GetExitCode(); @@ -295,5 +299,19 @@ namespace BinaryNinjaDebugger { bool IsFirstLaunch(); bool IsTTD(); + + void OnRebased(BinaryView* oldView, BinaryView* newView) override { + m_data = newView; + m_viewStart = newView->GetStart(); + // UnregisterNotification() is not designed to be called from one of the callbacks, so we cannot call it + // here. Also, there is no need to do so -- the oldView is about to be deleted + // oldView->UnregisterNotification(this); + newView->RegisterNotification(this); + } + + bool RemoveDebuggerMemoryRegion(); + bool ReAddDebuggerMemoryRegion(); + + uint64_t GetViewFileSegmentsStart() { return m_viewStart; } }; }; // namespace BinaryNinjaDebugger diff --git a/core/debuggerfileaccessor.cpp b/core/debuggerfileaccessor.cpp new file mode 100644 index 0000000..11a81c5 --- /dev/null +++ b/core/debuggerfileaccessor.cpp @@ -0,0 +1,111 @@ +/* +Copyright 2020-2024 Vector 35 Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#include "debuggerfileaccessor.h" +#include "debuggercontroller.h" + +using namespace BinaryNinja; +using namespace BinaryNinjaDebugger; + +DebuggerFileAccessor::DebuggerFileAccessor(BinaryView* parent) +{ + auto addressSize = parent->GetAddressSize(); + auto bits = addressSize * 8; + if (bits >= 64) + m_length = UINT64_MAX; + else + m_length = (1ULL << bits) - 1; + + m_controller = DebuggerController::GetController(parent); + m_eventCallback = m_controller->RegisterEventCallback([this](const DebuggerEvent& event){ + eventHandler(event); + }, "Process View"); +} + + +DebuggerFileAccessor::~DebuggerFileAccessor() +{ + if (m_controller) + m_controller->RemoveEventCallback(m_eventCallback); +} + + +uint64_t DebuggerFileAccessor::GetLength() const +{ + return m_length; +} + + +size_t DebuggerFileAccessor::Read(void *dest, uint64_t offset, size_t len) +{ + DataBuffer buffer = m_controller->ReadMemory(offset, len); + memcpy(dest, buffer.GetData(), buffer.GetLength()); + + return buffer.GetLength(); +} + + +size_t DebuggerFileAccessor::Write(uint64_t offset, const void *src, size_t len) +{ + if (m_controller->WriteMemory(offset, DataBuffer(src, len))) + { + m_controller->GetData()->NotifyDataWritten(offset, len); + return len; + } + + return 0; +} + + + +void DebuggerFileAccessor::MarkDirty() +{ + // This hack will let the views (linear/graph) update its display + if (m_aggressiveAnalysisUpdate) + { + m_controller->GetData()->NotifyDataWritten(0, GetLength()); + } + else + { + // This ensures or the BinaryDataListener, e.g, the linear view, refreshes its display. But it avoids any + // functions get marked as update required + m_controller->GetData()->NotifyDataWritten(0xdeadbeefdeadbeef, 0); + } +} + + +void DebuggerFileAccessor::ForceMemoryCacheUpdate() +{ + m_controller->GetData()->NotifyDataWritten(0, GetLength()); +} + + +void DebuggerFileAccessor::eventHandler(const DebuggerEvent &event) +{ + switch (event.type) + { + case TargetStoppedEventType: + // We should not call MarkDirty() in case of a TargetExitedEvent, since the debugger binary view is about to be + // deleted. And it can cause a crash in certain cases. + MarkDirty(); + break; + case ForceMemoryCacheUpdateEvent: + ForceMemoryCacheUpdate(); + break; + default: + break; + } +} diff --git a/core/debuggerfileaccessor.h b/core/debuggerfileaccessor.h new file mode 100644 index 0000000..7533ebd --- /dev/null +++ b/core/debuggerfileaccessor.h @@ -0,0 +1,50 @@ +/* +Copyright 2020-2024 Vector 35 Inc. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + +http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +#pragma once + +#include "binaryninjaapi.h" +#include "debuggerevent.h" +#include "refcountobject.h" + +using namespace BinaryNinja; + +namespace BinaryNinjaDebugger +{ + class DebuggerController; + + class DebuggerFileAccessor: public FileAccessor + { + uint64_t m_length; + + DbgRef m_controller; + size_t m_eventCallback; + + bool m_aggressiveAnalysisUpdate; + + public: + DebuggerFileAccessor(BinaryView* parent); + ~DebuggerFileAccessor(); + bool IsValid() const override { return true; } + uint64_t GetLength() const override; + size_t Read(void* dest, uint64_t offset, size_t len) override; + size_t Write(uint64_t offset, const void* src, size_t len) override; + + void MarkDirty(); + void ForceMemoryCacheUpdate(); + void eventHandler(const DebuggerEvent& event); + }; +} diff --git a/core/debuggerstate.cpp b/core/debuggerstate.cpp index 2bdf97a..090fe42 100644 --- a/core/debuggerstate.cpp +++ b/core/debuggerstate.cpp @@ -411,6 +411,11 @@ uint64_t DebuggerModules::RelativeAddressToAbsolute(const ModuleNameAndOffset& r return module.m_address + relativeAddress.offset; } } + if (DebugModule::IsSameBaseModule(m_state->GetController()->GetData()->GetFile()->GetOriginalFilename(), + relativeAddress.module)) + { + return m_state->GetController()->GetViewFileSegmentsStart() + relativeAddress.offset; + } } return relativeAddress.offset; diff --git a/core/debuggerstate.h b/core/debuggerstate.h index b0caadf..6886472 100644 --- a/core/debuggerstate.h +++ b/core/debuggerstate.h @@ -18,7 +18,6 @@ limitations under the License. #include "binaryninjaapi.h" #include "ui/uitypes.h" -#include "processview.h" #include "debugadaptertype.h" #include "debuggercommon.h" #include "semaphore.h" diff --git a/core/ffi.cpp b/core/ffi.cpp index bc6dfb6..c5f71de 100644 --- a/core/ffi.cpp +++ b/core/ffi.cpp @@ -777,14 +777,6 @@ BNDebugBreakpoint* BNDebuggerGetBreakpoints(BNDebuggerController* controller, si { uint64_t remoteAddress = state->GetModules()->RelativeAddressToAbsolute(breakpoints[i]); bool enabled = false; - //for (const DebugBreakpoint& bp: remoteList) - //{ - // if (bp.m_address == remoteAddress) - // { - // enabled = true; - // break; - // } - //} result[i].module = BNDebuggerAllocString(breakpoints[i].module.c_str()); result[i].offset = breakpoints[i].offset; result[i].address = remoteAddress; @@ -1056,3 +1048,21 @@ void BNDebuggerPostDebuggerEvent(BNDebuggerController* controller, BNDebuggerEve controller->object->PostDebuggerEvent(evt); } + + +bool BNDebuggerRemoveMemoryRegion(BNDebuggerController* controller) +{ + return controller->object->RemoveDebuggerMemoryRegion(); +} + + +bool BNDebuggerReAddMemoryRegion(BNDebuggerController* controller) +{ + return controller->object->ReAddDebuggerMemoryRegion(); +} + + +uint64_t BNDebuggerGetViewFileSegmentsStart(BNDebuggerController* controller) +{ + return controller->object->GetViewFileSegmentsStart(); +} diff --git a/core/processview.cpp b/core/processview.cpp deleted file mode 100644 index e49a97f..0000000 --- a/core/processview.cpp +++ /dev/null @@ -1,222 +0,0 @@ -/* -Copyright 2020-2024 Vector 35 Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#include "processview.h" -#include "debuggerstate.h" -#include "debuggercontroller.h" - -using namespace BinaryNinja; -using namespace BinaryNinjaDebugger; - -static DebugProcessViewType* g_debugProcessViewType = nullptr; - - -DebugProcessView::DebugProcessView(DebugNullView* nullView, BinaryView* parent): - BinaryView("Debugger", parent->GetFile(), nullView) -{ - m_arch = parent->GetDefaultArchitecture(); - m_platform = parent->GetDefaultPlatform(); - m_addressSize = parent->GetAddressSize(); - auto bits = m_addressSize * 8; - if (bits >= 64) - m_length = UINT64_MAX; - else - m_length = (1ULL << bits) - 1; - - m_endian = parent->GetDefaultEndianness(); - - // TODO: Read segments from debugger - uint64_t length = PerformGetLength(); - // If we do not add any segments, BN will malfunction. If we add a binary view that is large, e.g., 0xffffffff, - // it will be truncated to the size of the parent view. And the region from 0x0 to the size of the parent view will - // be unreadable, because BN will try to read the byte values from the parent view, rather from the debug process - // view, which eventually reads from the debug adapter backend. So, as a workaround, we add a segment that has size - // 0x1, which minimizes the unreadable regions. - // See https://github.com/Vector35/debugger/issues/334 for more details. - AddAutoSegment(0, 1, 0, 1, SegmentReadable | SegmentWritable | SegmentExecutable); - AddAutoSection("Memory", 0, length); - - m_aggressiveAnalysisUpdate = Settings::Instance()->Get("debugger.aggressiveAnalysisUpdate"); - - m_controller = DebuggerController::GetController(parent); - m_eventCallback = m_controller->RegisterEventCallback([this](const DebuggerEvent& event){ - eventHandler(event); - }, "Process View"); -} - - -DebugProcessView::~DebugProcessView() -{ - if (m_controller) - m_controller->RemoveEventCallback(m_eventCallback); -} - - -bool DebugProcessView::Init() -{ - return true; -} - - -uint64_t DebugProcessView::PerformGetEntryPoint() const -{ - return 0; -} - - -BNEndianness DebugProcessView::PerformGetDefaultEndianness() const -{ - return m_endian; -} - - -size_t DebugProcessView::PerformGetAddressSize() const -{ - return m_addressSize; -} - - -uint64_t DebugProcessView::PerformGetLength() const -{ - return m_length; -} - - -DebugProcessViewType::DebugProcessViewType() : BinaryViewType("Debugger", "Debugger") {} - - -Ref DebugProcessViewType::Create(BinaryView* data) -{ - try - { - // the null view must be ref-counted, otherwise there will be a memory leak - Ref nullView = new DebugNullView(data); - return new DebugProcessView(nullView, data); - } - catch (std::exception& e) - { - LogError("%s failed to create view! '%s'", GetName().c_str(), e.what()); - return nullptr; - } -} - - -Ref DebugProcessViewType::Parse(BinaryView* data) -{ - try - { - // the null view must be ref-counted, otherwise there will be a memory leak - Ref nullView = new DebugNullView(data); - return new DebugProcessView(nullView, data); - } - catch (std::exception& e) - { - LogError("%s failed to create view! '%s'", GetName().c_str(), e.what()); - return nullptr; - } -} - - -void BinaryNinjaDebugger::InitDebugProcessViewType() -{ - static DebugProcessViewType type; - BinaryViewType::Register(&type); - g_debugProcessViewType = &type; -} - - -size_t DebugProcessView::PerformRead(void* dest, uint64_t offset, size_t len) -{ - DataBuffer buffer = m_controller->ReadMemory(offset, len); - memcpy(dest, buffer.GetData(), buffer.GetLength()); - - return buffer.GetLength(); -} - - -size_t DebugProcessView::PerformWrite(uint64_t offset, const void* data, size_t len) -{ - if (m_controller->WriteMemory(offset, DataBuffer(data, len))) - { - BinaryView::NotifyDataWritten(offset, len); - return len; - } - - return 0; -} - - -void DebugProcessView::MarkDirty() -{ - // This hack will let the views (linear/graph) update its display - if (m_aggressiveAnalysisUpdate) - { - BinaryView::NotifyDataWritten(0, GetLength()); - } - else - { - // This ensures or the BinaryDataListener, e.g, the linear view, refreshes its display. But it avoids any - // functions get marked as update required - BinaryView::NotifyDataWritten(0xdeadbeefdeadbeef, 0); - } -} - - -void DebugProcessView::ForceMemoryCacheUpdate() -{ - BinaryView::NotifyDataWritten(0, GetLength()); -} - - -void DebugProcessView::eventHandler(const DebuggerEvent &event) -{ - switch (event.type) - { - case TargetStoppedEventType: - // We should not call MarkDirty() in case of a TargetExitedEvent, since the debugger binary view is about to be - // deleted. And it can cause a crash in certain cases. - MarkDirty(); - break; - case ForceMemoryCacheUpdateEvent: - ForceMemoryCacheUpdate(); - break; - default: - break; - } -} - - -DebugNullView::DebugNullView(BinaryView* parent) : - BinaryView("Debugger Null", parent->GetFile(), nullptr) -{ -} - - -DebugNullView::~DebugNullView() -{ -} - - -uint64_t DebugNullView::PerformGetLength() const -{ - return 1; -} - - -bool DebugNullView::PerformIsOffsetBackedByFile(uint64_t offset) -{ - return offset == 0; -} diff --git a/core/processview.h b/core/processview.h deleted file mode 100644 index 3d7f6b4..0000000 --- a/core/processview.h +++ /dev/null @@ -1,95 +0,0 @@ -/* -Copyright 2020-2024 Vector 35 Inc. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -#pragma once - -#include "binaryninjaapi.h" -#include "debuggerevent.h" -#include "refcountobject.h" - -using namespace BinaryNinja; - -namespace BinaryNinjaDebugger -{ - class DebuggerController; - class DebugNullView; - - class DebugProcessView : public BinaryView - { - size_t m_addressSize; - BNEndianness m_endian; - Ref m_arch; - Ref m_platform; - uint64_t m_length; - - DbgRef m_controller; - size_t m_eventCallback; - - bool m_aggressiveAnalysisUpdate; - - virtual uint64_t PerformGetEntryPoint() const override; - - virtual bool PerformIsExecutable() const override { return true; } - virtual BNEndianness PerformGetDefaultEndianness() const override; - virtual bool PerformIsRelocatable() const override { return true; }; - virtual size_t PerformGetAddressSize() const override; - virtual bool PerformIsValidOffset(uint64_t addr) override { return true; } - virtual uint64_t PerformGetLength() const override; - - virtual size_t PerformRead(void* dest, uint64_t offset, size_t len) override; - virtual size_t PerformWrite(uint64_t offset, const void* data, size_t len) override; - - public: - DebugProcessView(DebugNullView* nullView, BinaryView* data); - virtual ~DebugProcessView(); - virtual bool Init() override; - - void MarkDirty(); - void ForceMemoryCacheUpdate(); - void eventHandler(const DebuggerEvent& event); - }; - - - class DebugProcessViewType : public BinaryViewType - { - public: - DebugProcessViewType(); - virtual Ref Create(BinaryView* data) override; - virtual Ref Parse(BinaryView* data) override; - virtual bool IsTypeValidForData(BinaryView* data) override { return true; } - virtual Ref GetLoadSettingsForData(BinaryView* data) override { return nullptr; } - // Here we abuse (smartly use) the IsDeprecated() API to achieve our goal of stopping BN to construct - // the DebugProcessView for any data. We can still construct it manually, as done within the debugger. - // Any alternative way to do is to have IsTypeValidForData() return false. However, it does not work well, - // because the DataTypeList widget will refuse to list the Debugger view. - // TODO: we should probably create a different API, or rename the IsDeprecated() API. - virtual bool IsDeprecated() override { return true; }; - }; - - - class DebugNullView : public BinaryView - { - virtual uint64_t PerformGetLength() const override; - bool PerformIsOffsetBackedByFile(uint64_t offset) override; - - public: - DebugNullView(BinaryView* data); - virtual ~DebugNullView(); - }; - - - void InitDebugProcessViewType(); -}; diff --git a/ui/breakpointswidget.cpp b/ui/breakpointswidget.cpp index d48838f..0827fba 100644 --- a/ui/breakpointswidget.cpp +++ b/ui/breakpointswidget.cpp @@ -319,19 +319,10 @@ void DebugBreakpointsWidget::jump() return; BreakpointItem bp = m_model->getRow(sel[0].row()); - - auto address_or_offset = bp.address(); - Ref view = m_controller->GetData(); - const auto is_absolute = m_controller->IsConnected(); - if (!is_absolute) - address_or_offset += view->GetStart(); - UIContext* context = UIContext::contextForWidget(this); ViewFrame* frame = context->getCurrentViewFrame(); if (m_controller->GetLiveView()) - frame->navigate(m_controller->GetLiveView(), address_or_offset, true, true); - else - frame->navigate(m_controller->GetData(), address_or_offset, true, true); + frame->navigate(m_controller->GetLiveView(), bp.address(), true, true); } @@ -365,7 +356,7 @@ void DebugBreakpointsWidget::add() else { std::string filename = m_controller->GetInputFile(); - uint64_t offset = address - view->GetStart(); + uint64_t offset = address - m_controller->GetViewFileSegmentsStart(); ModuleNameAndOffset info = {filename, offset}; m_controller->AddBreakpoint(info); } diff --git a/ui/ui.cpp b/ui/ui.cpp index 3d912f4..8ca06e6 100644 --- a/ui/ui.cpp +++ b/ui/ui.cpp @@ -73,8 +73,7 @@ static void BreakpointToggleCallback(BinaryView* view, uint64_t addr) { auto controller = DebuggerController::GetController(view); bool isAbsoluteAddress = false; - // TODO: check if this works - if (view->GetTypeName() == "Debugger") + if (controller->IsConnected()) isAbsoluteAddress = true; if (isAbsoluteAddress) @@ -91,7 +90,7 @@ static void BreakpointToggleCallback(BinaryView* view, uint64_t addr) else { std::string filename = controller->GetInputFile(); - uint64_t offset = addr - view->GetStart(); + uint64_t offset = addr - controller->GetViewFileSegmentsStart(); ModuleNameAndOffset info = {filename, offset}; if (controller->ContainsBreakpoint(info)) { @@ -1037,7 +1036,7 @@ void DebuggerUI::openDebuggerSideBar(ViewFrame* frame) } -void DebuggerUI::updateIPHighlight() +void DebuggerUI::removeOldIPHighlight() { uint64_t lastIP = m_controller->GetLastIP(); uint64_t address = m_controller->IP(); @@ -1053,7 +1052,7 @@ void DebuggerUI::updateIPHighlight() { ModuleNameAndOffset addr; addr.module = m_controller->GetInputFile(); - addr.offset = lastIP - data->GetStart(); + addr.offset = lastIP - m_controller->GetViewFileSegmentsStart(); BNHighlightStandardColor oldColor = NoHighlightColor; if (m_controller->ContainsBreakpoint(addr)) @@ -1070,6 +1069,21 @@ void DebuggerUI::updateIPHighlight() data->ForgetUndoActions(id); } } +} + + +void DebuggerUI::updateIPHighlight() +{ + removeOldIPHighlight(); + + uint64_t lastIP = m_controller->GetLastIP(); + uint64_t address = m_controller->IP(); + if (address == lastIP) + return; + + BinaryViewRef data = m_controller->GetLiveView(); + if (!data) + return; // Add new instruction pointer highlight for (FunctionRef func : data->GetAnalysisFunctionsContainingAddress(address)) @@ -1143,41 +1157,12 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) case QuitDebuggingEventType: case TargetExitedEventType: { + removeOldIPHighlight(); ViewFrame* frame = m_context->getCurrentViewFrame(); - if (!frame) - break; - - // Workaround for https://github.com/Vector35/debugger/issues/367 - auto settings = Settings::Instance(); - bool oldRestoreView = false; - if (settings->Contains("ui.files.restore.viewState")) - { - oldRestoreView = settings->Get("ui.files.restore.viewState"); - if (oldRestoreView) - settings->Set("ui.files.restore.viewState", false); - } - FileContext* fileContext = frame->getFileContext(); - auto tab = m_context->getTabForFile(fileContext); - ViewFrame* newFrame = m_context->openFileContext(fileContext); + fileContext->refreshDataViewCache(); + m_context->recreateViewFrames(fileContext); QCoreApplication::processEvents(); - - if (newFrame) - { - newFrame->navigate(m_controller->GetData(), m_controller->GetData()->GetEntryPoint(), true, true); - m_context->closeTab(tab); - fileContext->refreshDataViewCache(); - openDebuggerSideBar(newFrame); - QCoreApplication::processEvents(); - } - else - { - LogWarn("fail to navigate to the original view"); - } - - if (oldRestoreView) - settings->Set("ui.files.restore.viewState", true); - break; } @@ -1197,21 +1182,7 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) if (!liveView) break; - if (event.type == TargetStoppedEventType - && event.data.targetStoppedData.reason == DebugStopReason::InitialBreakpoint) - { - ViewFrame* frame = m_context->getCurrentViewFrame(); - FileContext* fileContext = frame->getFileContext(); - fileContext->refreshDataViewCache(); - m_context->recreateViewFrames(fileContext); - navigateToCurrentIP(); - QCoreApplication::processEvents(); - } - else - { - navigateToCurrentIP(); - } - + navigateToCurrentIP(); updateIPHighlight(); checkFocusDebuggerConsole(); break; @@ -1224,8 +1195,9 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) FileMetadataRef fileMetadata = data->GetFile(); ViewFrame* frame = m_context->getCurrentViewFrame(); - if (remoteBase != data->GetStart()) + if (remoteBase != m_controller->GetViewFileSegmentsStart()) { + m_controller->RemoveDebuggerMemoryRegion(); bool result = false; QString text = QString("Rebasing the input view..."); ProgressTask* task = @@ -1239,22 +1211,15 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) LogWarn("failed to rebase the input view"); break; } - } - Ref rebasedView = fileMetadata->GetViewOfType(data->GetTypeName()); + m_controller->ReAddDebuggerMemoryRegion(); - bool result = false; - QString text = QString("Adding the input view into the debugger view..."); - ProgressTask* task = - new ProgressTask(frame, "Adding view", text, "Cancel", [&](std::function progress) { - result = fileMetadata->CreateSnapshotedView(rebasedView, "Debugger", progress); - }); - task->wait(); - - if (!result) - { - LogWarn("failed add the input view into the debugger view"); - break; + ViewFrame* frame = m_context->getCurrentViewFrame(); + FileContext* fileContext = frame->getFileContext(); + fileContext->refreshDataViewCache(); + m_context->recreateViewFrames(fileContext); + navigateToCurrentIP(); + QCoreApplication::processEvents(); } break; @@ -1270,7 +1235,7 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) if (DebugModule::IsSameBaseModule(event.data.relativeAddress.module, m_controller->GetInputFile())) { - dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetData()->GetStart() + event.data.relativeAddress.offset); + dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetViewFileSegmentsStart() + event.data.relativeAddress.offset); } for (auto& [data, addr] : dataAndAddress) @@ -1310,7 +1275,7 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) ModuleNameAndOffset relative = m_controller->AbsoluteAddressToRelative(address); if (DebugModule::IsSameBaseModule(relative.module, m_controller->GetInputFile())) { - dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetData()->GetStart() + relative.offset); + dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetViewFileSegmentsStart() + relative.offset); } for (auto& [data, address] : dataAndAddress) @@ -1348,7 +1313,7 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) if (DebugModule::IsSameBaseModule(event.data.relativeAddress.module, m_controller->GetInputFile())) { - dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetData()->GetStart() + event.data.relativeAddress.offset); + dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetViewFileSegmentsStart() + event.data.relativeAddress.offset); } for (auto& [data, address] : dataAndAddress) @@ -1381,7 +1346,7 @@ void DebuggerUI::updateUI(const DebuggerEvent& event) ModuleNameAndOffset relative = m_controller->AbsoluteAddressToRelative(address); if (DebugModule::IsSameBaseModule(relative.module, m_controller->GetInputFile())) { - dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetData()->GetStart() + relative.offset); + dataAndAddress.emplace_back(m_controller->GetData(), m_controller->GetViewFileSegmentsStart() + relative.offset); } for (auto& [data, address] : dataAndAddress) diff --git a/ui/ui.h b/ui/ui.h index fb08346..18e56d0 100644 --- a/ui/ui.h +++ b/ui/ui.h @@ -83,6 +83,7 @@ class DebuggerUI : public QObject void navigateDebugger(uint64_t address); void openDebuggerSideBar(ViewFrame* frame = nullptr); + void removeOldIPHighlight(); void updateIPHighlight(); void navigateToCurrentIP(); void checkFocusDebuggerConsole();