mirror of
https://github.com/RGBCube/serenity
synced 2025-05-17 15:55:07 +00:00
LibDebug: Add ProcessInspector base class
ProcessInspector is an abstract base class for an object that can inspect the address space of a process. Concrete sub classes need to implement methods for peeking & poking memory and walking the loaded libraries. It is currently only implemented by DebugSession.
This commit is contained in:
parent
38ddf301f6
commit
7950f5cb51
7 changed files with 173 additions and 118 deletions
|
@ -9,6 +9,7 @@ set(SOURCES
|
||||||
Dwarf/DwarfInfo.cpp
|
Dwarf/DwarfInfo.cpp
|
||||||
Dwarf/Expression.cpp
|
Dwarf/Expression.cpp
|
||||||
Dwarf/LineProgram.cpp
|
Dwarf/LineProgram.cpp
|
||||||
|
ProcessInspector.cpp
|
||||||
StackFrameUtils.cpp
|
StackFrameUtils.cpp
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -44,6 +44,15 @@ DebugSession::~DebugSession()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DebugSession::for_each_loaded_library(Function<IterationDecision(LoadedLibrary const&)> func) const
|
||||||
|
{
|
||||||
|
for (const auto& lib_name : m_loaded_libraries.keys()) {
|
||||||
|
const auto& lib = *m_loaded_libraries.get(lib_name).value();
|
||||||
|
if (func(lib) == IterationDecision::Break)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
OwnPtr<DebugSession> DebugSession::exec_and_attach(String const& command, String source_root)
|
OwnPtr<DebugSession> DebugSession::exec_and_attach(String const& command, String source_root)
|
||||||
{
|
{
|
||||||
auto pid = fork();
|
auto pid = fork();
|
||||||
|
@ -110,39 +119,39 @@ OwnPtr<DebugSession> DebugSession::exec_and_attach(String const& command, String
|
||||||
return debug_session;
|
return debug_session;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugSession::poke(u32* address, u32 data)
|
bool DebugSession::poke(void* address, FlatPtr data)
|
||||||
{
|
{
|
||||||
if (ptrace(PT_POKE, m_debuggee_pid, (void*)address, data) < 0) {
|
if (ptrace(PT_POKE, m_debuggee_pid, (void*)address, (void*)data) < 0) {
|
||||||
perror("PT_POKE");
|
perror("PT_POKE");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<u32> DebugSession::peek(u32* address) const
|
Optional<FlatPtr> DebugSession::peek(void* address) const
|
||||||
{
|
{
|
||||||
Optional<u32> result;
|
Optional<FlatPtr> result;
|
||||||
int rc = ptrace(PT_PEEK, m_debuggee_pid, (void*)address, 0);
|
auto rc = ptrace(PT_PEEK, m_debuggee_pid, address, nullptr);
|
||||||
if (errno == 0)
|
if (errno == 0)
|
||||||
result = static_cast<u32>(rc);
|
result = static_cast<FlatPtr>(rc);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DebugSession::poke_debug(u32 register_index, u32 data)
|
bool DebugSession::poke_debug(u32 register_index, FlatPtr data)
|
||||||
{
|
{
|
||||||
if (ptrace(PT_POKEDEBUG, m_debuggee_pid, reinterpret_cast<u32*>(register_index), data) < 0) {
|
if (ptrace(PT_POKEDEBUG, m_debuggee_pid, reinterpret_cast<void*>(register_index), (void*)data) < 0) {
|
||||||
perror("PT_POKEDEBUG");
|
perror("PT_POKEDEBUG");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<u32> DebugSession::peek_debug(u32 register_index) const
|
Optional<FlatPtr> DebugSession::peek_debug(u32 register_index) const
|
||||||
{
|
{
|
||||||
Optional<u32> result;
|
Optional<FlatPtr> result;
|
||||||
int rc = ptrace(PT_PEEKDEBUG, m_debuggee_pid, reinterpret_cast<u32*>(register_index), 0);
|
int rc = ptrace(PT_PEEKDEBUG, m_debuggee_pid, reinterpret_cast<FlatPtr*>(register_index), nullptr);
|
||||||
if (errno == 0)
|
if (errno == 0)
|
||||||
result = static_cast<u32>(rc);
|
result = static_cast<FlatPtr>(rc);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,7 +164,7 @@ bool DebugSession::insert_breakpoint(void* address)
|
||||||
if (m_breakpoints.contains(address))
|
if (m_breakpoints.contains(address))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto original_bytes = peek(reinterpret_cast<u32*>(address));
|
auto original_bytes = peek(reinterpret_cast<FlatPtr*>(address));
|
||||||
|
|
||||||
if (!original_bytes.has_value())
|
if (!original_bytes.has_value())
|
||||||
return false;
|
return false;
|
||||||
|
@ -175,7 +184,7 @@ bool DebugSession::disable_breakpoint(void* address)
|
||||||
{
|
{
|
||||||
auto breakpoint = m_breakpoints.get(address);
|
auto breakpoint = m_breakpoints.get(address);
|
||||||
VERIFY(breakpoint.has_value());
|
VERIFY(breakpoint.has_value());
|
||||||
if (!poke(reinterpret_cast<u32*>(reinterpret_cast<char*>(breakpoint.value().address)), breakpoint.value().original_first_word))
|
if (!poke(reinterpret_cast<FlatPtr*>(reinterpret_cast<char*>(breakpoint.value().address)), breakpoint.value().original_first_word))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto bp = m_breakpoints.get(breakpoint.value().address).value();
|
auto bp = m_breakpoints.get(breakpoint.value().address).value();
|
||||||
|
@ -191,7 +200,7 @@ bool DebugSession::enable_breakpoint(void* address)
|
||||||
|
|
||||||
VERIFY(breakpoint.value().state == BreakPointState::Disabled);
|
VERIFY(breakpoint.value().state == BreakPointState::Disabled);
|
||||||
|
|
||||||
if (!poke(reinterpret_cast<u32*>(breakpoint.value().address), (breakpoint.value().original_first_word & ~(uint32_t)0xff) | BREAKPOINT_INSTRUCTION))
|
if (!poke(reinterpret_cast<FlatPtr*>(breakpoint.value().address), (breakpoint.value().original_first_word & ~(FlatPtr)0xff) | BREAKPOINT_INSTRUCTION))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
auto bp = m_breakpoints.get(breakpoint.value().address).value();
|
auto bp = m_breakpoints.get(breakpoint.value().address).value();
|
||||||
|
@ -219,7 +228,8 @@ bool DebugSession::insert_watchpoint(void* address, u32 ebp)
|
||||||
auto current_register_status = peek_debug(DEBUG_CONTROL_REGISTER);
|
auto current_register_status = peek_debug(DEBUG_CONTROL_REGISTER);
|
||||||
if (!current_register_status.has_value())
|
if (!current_register_status.has_value())
|
||||||
return false;
|
return false;
|
||||||
u32 dr7_value = current_register_status.value();
|
// FIXME: 64 bit support
|
||||||
|
u32 dr7_value = static_cast<u32>(current_register_status.value());
|
||||||
u32 next_available_index;
|
u32 next_available_index;
|
||||||
for (next_available_index = 0; next_available_index < 4; next_available_index++) {
|
for (next_available_index = 0; next_available_index < 4; next_available_index++) {
|
||||||
auto bitmask = 1 << (next_available_index * 2);
|
auto bitmask = 1 << (next_available_index * 2);
|
||||||
|
@ -455,54 +465,4 @@ void DebugSession::update_loaded_libs()
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
const DebugSession::LoadedLibrary* DebugSession::library_at(FlatPtr address) const
|
|
||||||
{
|
|
||||||
const LoadedLibrary* result = nullptr;
|
|
||||||
for_each_loaded_library([&result, address](const auto& lib) {
|
|
||||||
if (address >= lib.base_address && address < lib.base_address + lib.debug_info->elf().size()) {
|
|
||||||
result = &lib;
|
|
||||||
return IterationDecision::Break;
|
|
||||||
}
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<DebugSession::SymbolicationResult> DebugSession::symbolicate(FlatPtr address) const
|
|
||||||
{
|
|
||||||
auto* lib = library_at(address);
|
|
||||||
if (!lib)
|
|
||||||
return {};
|
|
||||||
//FIXME: ELF::Image symlicate() API should return String::empty() if symbol is not found (It currently returns ??)
|
|
||||||
auto symbol = lib->debug_info->elf().symbolicate(address - lib->base_address);
|
|
||||||
return { { lib->name, symbol } };
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<DebugInfo::SourcePositionAndAddress> DebugSession::get_address_from_source_position(String const& file, size_t line) const
|
|
||||||
{
|
|
||||||
Optional<DebugInfo::SourcePositionAndAddress> result;
|
|
||||||
for_each_loaded_library([file, line, &result](auto& lib) {
|
|
||||||
// The loader contains its own definitions for LibC symbols, so we don't want to include it in the search.
|
|
||||||
if (lib.name == "Loader.so")
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
|
|
||||||
auto source_position_and_address = lib.debug_info->get_address_from_source_position(file, line);
|
|
||||||
if (!source_position_and_address.has_value())
|
|
||||||
return IterationDecision::Continue;
|
|
||||||
|
|
||||||
result = source_position_and_address;
|
|
||||||
result.value().address += lib.base_address;
|
|
||||||
return IterationDecision::Break;
|
|
||||||
});
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
Optional<DebugInfo::SourcePosition> DebugSession::get_source_position(FlatPtr address) const
|
|
||||||
{
|
|
||||||
auto* lib = library_at(address);
|
|
||||||
if (!lib)
|
|
||||||
return {};
|
|
||||||
return lib->debug_info->get_source_position(address - lib->base_address);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -15,6 +15,7 @@
|
||||||
#include <AK/String.h>
|
#include <AK/String.h>
|
||||||
#include <LibC/sys/arch/i386/regs.h>
|
#include <LibC/sys/arch/i386/regs.h>
|
||||||
#include <LibDebug/DebugInfo.h>
|
#include <LibDebug/DebugInfo.h>
|
||||||
|
#include <LibDebug/ProcessInspector.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
|
@ -23,19 +24,23 @@
|
||||||
|
|
||||||
namespace Debug {
|
namespace Debug {
|
||||||
|
|
||||||
class DebugSession {
|
class DebugSession : public ProcessInspector {
|
||||||
public:
|
public:
|
||||||
static OwnPtr<DebugSession> exec_and_attach(String const& command, String source_root = {});
|
static OwnPtr<DebugSession> exec_and_attach(String const& command, String source_root = {});
|
||||||
|
|
||||||
~DebugSession();
|
virtual ~DebugSession() override;
|
||||||
|
|
||||||
|
// ^Debug::ProcessInspector
|
||||||
|
virtual bool poke(void* address, FlatPtr data) override;
|
||||||
|
virtual Optional<FlatPtr> peek(void* address) const override;
|
||||||
|
virtual PtraceRegisters get_registers() const override;
|
||||||
|
virtual void set_registers(PtraceRegisters const&) override;
|
||||||
|
virtual void for_each_loaded_library(Function<IterationDecision(LoadedLibrary const&)>) const override;
|
||||||
|
|
||||||
int pid() const { return m_debuggee_pid; }
|
int pid() const { return m_debuggee_pid; }
|
||||||
|
|
||||||
bool poke(u32* address, u32 data);
|
bool poke_debug(u32 register_index, FlatPtr data);
|
||||||
Optional<u32> peek(u32* address) const;
|
Optional<FlatPtr> peek_debug(u32 register_index) const;
|
||||||
|
|
||||||
bool poke_debug(u32 register_index, u32 data);
|
|
||||||
Optional<u32> peek_debug(u32 register_index) const;
|
|
||||||
|
|
||||||
enum class BreakPointState {
|
enum class BreakPointState {
|
||||||
Enabled,
|
Enabled,
|
||||||
|
@ -44,7 +49,7 @@ public:
|
||||||
|
|
||||||
struct BreakPoint {
|
struct BreakPoint {
|
||||||
void* address { nullptr };
|
void* address { nullptr };
|
||||||
u32 original_first_word { 0 };
|
FlatPtr original_first_word { 0 };
|
||||||
BreakPointState state { BreakPointState::Disabled };
|
BreakPointState state { BreakPointState::Disabled };
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -88,9 +93,6 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
PtraceRegisters get_registers() const;
|
|
||||||
void set_registers(PtraceRegisters const&);
|
|
||||||
|
|
||||||
enum class ContinueType {
|
enum class ContinueType {
|
||||||
FreeRun,
|
FreeRun,
|
||||||
Syscall,
|
Syscall,
|
||||||
|
@ -126,45 +128,6 @@ public:
|
||||||
Exited,
|
Exited,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct LoadedLibrary {
|
|
||||||
String name;
|
|
||||||
NonnullRefPtr<MappedFile> file;
|
|
||||||
NonnullOwnPtr<ELF::Image> image;
|
|
||||||
NonnullOwnPtr<DebugInfo> debug_info;
|
|
||||||
FlatPtr base_address;
|
|
||||||
|
|
||||||
LoadedLibrary(String const& name, NonnullRefPtr<MappedFile> file, NonnullOwnPtr<ELF::Image> image, NonnullOwnPtr<DebugInfo>&& debug_info, FlatPtr base_address)
|
|
||||||
: name(name)
|
|
||||||
, file(move(file))
|
|
||||||
, image(move(image))
|
|
||||||
, debug_info(move(debug_info))
|
|
||||||
, base_address(base_address)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
template<typename Func>
|
|
||||||
void for_each_loaded_library(Func f) const
|
|
||||||
{
|
|
||||||
for (const auto& lib_name : m_loaded_libraries.keys()) {
|
|
||||||
const auto& lib = *m_loaded_libraries.get(lib_name).value();
|
|
||||||
if (f(lib) == IterationDecision::Break)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const LoadedLibrary* library_at(FlatPtr address) const;
|
|
||||||
|
|
||||||
struct SymbolicationResult {
|
|
||||||
String library_name;
|
|
||||||
String symbol;
|
|
||||||
};
|
|
||||||
Optional<SymbolicationResult> symbolicate(FlatPtr address) const;
|
|
||||||
|
|
||||||
Optional<DebugInfo::SourcePositionAndAddress> get_address_from_source_position(String const& file, size_t line) const;
|
|
||||||
|
|
||||||
Optional<DebugInfo::SourcePosition> get_source_position(FlatPtr address) const;
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
explicit DebugSession(pid_t, String source_root);
|
explicit DebugSession(pid_t, String source_root);
|
||||||
|
|
||||||
|
@ -180,7 +143,7 @@ private:
|
||||||
HashMap<void*, BreakPoint> m_breakpoints;
|
HashMap<void*, BreakPoint> m_breakpoints;
|
||||||
HashMap<void*, WatchPoint> m_watchpoints;
|
HashMap<void*, WatchPoint> m_watchpoints;
|
||||||
|
|
||||||
// Maps from base address to loaded library
|
// Maps from library name to LoadedLibrary obect
|
||||||
HashMap<String, NonnullOwnPtr<LoadedLibrary>> m_loaded_libraries;
|
HashMap<String, NonnullOwnPtr<LoadedLibrary>> m_loaded_libraries;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
32
Userland/Libraries/LibDebug/LoadedLibrary.h
Normal file
32
Userland/Libraries/LibDebug/LoadedLibrary.h
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "DebugInfo.h"
|
||||||
|
#include <AK/MappedFile.h>
|
||||||
|
#include <AK/Types.h>
|
||||||
|
#include <LibELF/Image.h>
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
struct LoadedLibrary {
|
||||||
|
String name;
|
||||||
|
NonnullRefPtr<MappedFile> file;
|
||||||
|
NonnullOwnPtr<ELF::Image> image;
|
||||||
|
NonnullOwnPtr<DebugInfo> debug_info;
|
||||||
|
FlatPtr base_address {};
|
||||||
|
|
||||||
|
LoadedLibrary(String const& name, NonnullRefPtr<MappedFile> file, NonnullOwnPtr<ELF::Image> image, NonnullOwnPtr<DebugInfo>&& debug_info, FlatPtr base_address)
|
||||||
|
: name(name)
|
||||||
|
, file(move(file))
|
||||||
|
, image(move(image))
|
||||||
|
, debug_info(move(debug_info))
|
||||||
|
, base_address(base_address)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
62
Userland/Libraries/LibDebug/ProcessInspector.cpp
Normal file
62
Userland/Libraries/LibDebug/ProcessInspector.cpp
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "ProcessInspector.h"
|
||||||
|
#include "DebugInfo.h"
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
|
||||||
|
const LoadedLibrary* ProcessInspector::library_at(FlatPtr address) const
|
||||||
|
{
|
||||||
|
const LoadedLibrary* result = nullptr;
|
||||||
|
for_each_loaded_library([&result, address](const auto& lib) {
|
||||||
|
if (address >= lib.base_address && address < lib.base_address + lib.debug_info->elf().size()) {
|
||||||
|
result = &lib;
|
||||||
|
return IterationDecision::Break;
|
||||||
|
}
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<ProcessInspector::SymbolicationResult> ProcessInspector::symbolicate(FlatPtr address) const
|
||||||
|
{
|
||||||
|
auto* lib = library_at(address);
|
||||||
|
if (!lib)
|
||||||
|
return {};
|
||||||
|
// FIXME: ELF::Image symlicate() API should return String::empty() if symbol is not found (It currently returns ??)
|
||||||
|
auto symbol = lib->debug_info->elf().symbolicate(address - lib->base_address);
|
||||||
|
return { { lib->name, symbol } };
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<DebugInfo::SourcePositionAndAddress> ProcessInspector::get_address_from_source_position(String const& file, size_t line) const
|
||||||
|
{
|
||||||
|
Optional<DebugInfo::SourcePositionAndAddress> result;
|
||||||
|
for_each_loaded_library([file, line, &result](auto& lib) {
|
||||||
|
// The loader contains its own definitions for LibC symbols, so we don't want to include it in the search.
|
||||||
|
if (lib.name == "Loader.so")
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
|
auto source_position_and_address = lib.debug_info->get_address_from_source_position(file, line);
|
||||||
|
if (!source_position_and_address.has_value())
|
||||||
|
return IterationDecision::Continue;
|
||||||
|
|
||||||
|
result = source_position_and_address;
|
||||||
|
result.value().address += lib.base_address;
|
||||||
|
return IterationDecision::Break;
|
||||||
|
});
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
Optional<DebugInfo::SourcePosition> ProcessInspector::get_source_position(FlatPtr address) const
|
||||||
|
{
|
||||||
|
auto* lib = library_at(address);
|
||||||
|
if (!lib)
|
||||||
|
return {};
|
||||||
|
return lib->debug_info->get_source_position(address - lib->base_address);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
37
Userland/Libraries/LibDebug/ProcessInspector.h
Normal file
37
Userland/Libraries/LibDebug/ProcessInspector.h
Normal file
|
@ -0,0 +1,37 @@
|
||||||
|
/*
|
||||||
|
* Copyright (c) 2021, Itamar S. <itamar8910@gmail.com>
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: BSD-2-Clause
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "LoadedLibrary.h"
|
||||||
|
#include <AK/Types.h>
|
||||||
|
#include <LibC/sys/arch/i386/regs.h>
|
||||||
|
|
||||||
|
namespace Debug {
|
||||||
|
|
||||||
|
class ProcessInspector {
|
||||||
|
public:
|
||||||
|
virtual ~ProcessInspector() { }
|
||||||
|
virtual bool poke(void* address, FlatPtr data) = 0;
|
||||||
|
virtual Optional<FlatPtr> peek(void* address) const = 0;
|
||||||
|
virtual PtraceRegisters get_registers() const = 0;
|
||||||
|
virtual void set_registers(PtraceRegisters const&) = 0;
|
||||||
|
virtual void for_each_loaded_library(Function<IterationDecision(LoadedLibrary const&)>) const = 0;
|
||||||
|
|
||||||
|
const LoadedLibrary* library_at(FlatPtr address) const;
|
||||||
|
struct SymbolicationResult {
|
||||||
|
String library_name;
|
||||||
|
String symbol;
|
||||||
|
};
|
||||||
|
Optional<SymbolicationResult> symbolicate(FlatPtr address) const;
|
||||||
|
Optional<DebugInfo::SourcePositionAndAddress> get_address_from_source_position(String const& file, size_t line) const;
|
||||||
|
Optional<DebugInfo::SourcePosition> get_source_position(FlatPtr address) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
ProcessInspector() = default;
|
||||||
|
};
|
||||||
|
|
||||||
|
};
|
|
@ -70,7 +70,7 @@ static void print_syscall(PtraceRegisters& regs, size_t depth)
|
||||||
static NonnullOwnPtr<HashMap<void*, X86::Instruction>> instrument_code()
|
static NonnullOwnPtr<HashMap<void*, X86::Instruction>> instrument_code()
|
||||||
{
|
{
|
||||||
auto instrumented = make<HashMap<void*, X86::Instruction>>();
|
auto instrumented = make<HashMap<void*, X86::Instruction>>();
|
||||||
g_debug_session->for_each_loaded_library([&](const Debug::DebugSession::LoadedLibrary& lib) {
|
g_debug_session->for_each_loaded_library([&](const Debug::LoadedLibrary& lib) {
|
||||||
lib.debug_info->elf().for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
|
lib.debug_info->elf().for_each_section_of_type(SHT_PROGBITS, [&](const ELF::Image::Section& section) {
|
||||||
if (section.name() != ".text")
|
if (section.name() != ".text")
|
||||||
return IterationDecision::Continue;
|
return IterationDecision::Continue;
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue