Skip to content

Commit

Permalink
Cleanup gdb stub and module mapping
Browse files Browse the repository at this point in the history
  • Loading branch information
momo5502 committed Sep 9, 2024
1 parent 9472ee4 commit 73b1555
Show file tree
Hide file tree
Showing 13 changed files with 437 additions and 374 deletions.
54 changes: 54 additions & 0 deletions src/emulator/scoped_hook.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
#pragma once
#include "emulator.hpp"

class scoped_hook
{
public:
scoped_hook() = default;

scoped_hook(emulator& emu, emulator_hook* hook)
: emu_(&emu)
, hook_(hook)
{
}

~scoped_hook()
{
this->remove();
}

scoped_hook(const scoped_hook&) = delete;
scoped_hook& operator=(const scoped_hook&) = delete;

scoped_hook(scoped_hook&& obj) noexcept
{
this->operator=(std::move(obj));
}

scoped_hook& operator=(scoped_hook&& obj) noexcept
{
if (this != &obj)
{
this->remove();
this->emu_ = obj.emu_;
this->hook_ = obj.hook_;

obj.hook_ = {};
}

return *this;
}

void remove()
{
if (this->hook_)
{
this->emu_->delete_hook(this->hook_);
this->hook_ = {};
}
}

private:
emulator* emu_{};
emulator_hook* hook_{};
};
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#include "std_include.hpp"
#include "../std_include.hpp"
#include "gdb_stub.hpp"

#include <utils/finally.hpp>
Expand Down
File renamed without changes.
215 changes: 215 additions & 0 deletions src/windows_emulator/debugging/x64_gdb_stub_handler.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,215 @@
#pragma once
#include <x64_emulator.hpp>
#include "gdb_stub.hpp"
#include "scoped_hook.hpp"

inline std::vector gdb_registers{
x64_register::rax,
x64_register::rbx,
x64_register::rcx,
x64_register::rdx,
x64_register::rsi,
x64_register::rdi,
x64_register::rbp,
x64_register::rsp,
x64_register::r8,
x64_register::r9,
x64_register::r10,
x64_register::r11,
x64_register::r12,
x64_register::r13,
x64_register::r14,
x64_register::r15,
x64_register::rip,
x64_register::rflags,
/*x64_register::cs,
x64_register::ss,
x64_register::ds,
x64_register::es,
x64_register::fs,
x64_register::gs,*/
};

inline memory_operation map_breakpoint_type(const breakpoint_type type)
{
switch (type)
{
case breakpoint_type::software:
case breakpoint_type::hardware_exec:
return memory_operation::exec;
case breakpoint_type::hardware_read:
return memory_permission::read;
case breakpoint_type::hardware_write:
return memory_permission::write;
case breakpoint_type::hardware_read_write:
return memory_permission::read_write;
default:
throw std::runtime_error("Bad bp type");
}
}

struct breakpoint_key
{
size_t addr{};
size_t size{};
breakpoint_type type{};

bool operator==(const breakpoint_key& other) const
{
return this->addr == other.addr && this->size == other.size && this->type == other.type;
}
};

template <>
struct std::hash<breakpoint_key>
{
std::size_t operator()(const breakpoint_key& k) const noexcept
{
return ((std::hash<size_t>()(k.addr)
^ (std::hash<size_t>()(k.size) << 1)) >> 1)
^ (std::hash<size_t>()(static_cast<size_t>(k.type)) << 1);
}
};

class x64_gdb_stub_handler : public gdb_stub_handler
{
public:
x64_gdb_stub_handler(x64_emulator& emu)
: emu_(&emu)
{
}

~x64_gdb_stub_handler() override = default;

gdb_action cont() override
{
try
{
this->emu_->start_from_ip();
}
catch (const std::exception& e)
{
puts(e.what());
}

return gdb_action::resume;
}

gdb_action stepi() override
{
try
{
this->emu_->start_from_ip({}, 1);
}
catch (const std::exception& e)
{
puts(e.what());
}

return gdb_action::resume;
}

bool read_reg(const int regno, size_t* value) override
{
*value = 0;

try
{
if (static_cast<size_t>(regno) >= gdb_registers.size())
{
return true;
}

this->emu_->read_register(gdb_registers[regno], value, sizeof(*value));
return true;
}
catch (...)
{
return true;
}
}

bool write_reg(const int regno, const size_t value) override
{
try
{
if (static_cast<size_t>(regno) >= gdb_registers.size())
{
return true;
}

this->emu_->write_register(gdb_registers[regno], &value, sizeof(value));
return true;
}
catch (...)
{
return false;
}
}

bool read_mem(const size_t addr, const size_t len, void* val) override
{
return this->emu_->try_read_memory(addr, val, len);
}

bool write_mem(const size_t addr, const size_t len, void* val) override
{
try
{
this->emu_->write_memory(addr, val, len);
return true;
}
catch (...)
{
return false;
}
}

bool set_bp(const breakpoint_type type, const size_t addr, const size_t size) override
{
try
{
this->hooks_[{addr, size, type}] = scoped_hook(*this->emu_, this->emu_->hook_memory_access(
addr, size, map_breakpoint_type(type),
[this](uint64_t, size_t, memory_operation)
{
this->on_interrupt();
}));

return true;
}
catch (...)
{
return false;
}
}

bool del_bp(const breakpoint_type type, const size_t addr, const size_t size) override
{
try
{
const auto entry = this->hooks_.find({addr, size, type});
if (entry == this->hooks_.end())
{
return false;
}

this->hooks_.erase(entry);

return true;
}
catch (...)
{
return false;
}
}

void on_interrupt() override
{
this->emu_->stop();
}

private:
x64_emulator* emu_{};
std::unordered_map<breakpoint_key, scoped_hook> hooks_{};
};
Loading

0 comments on commit 73b1555

Please sign in to comment.