Support hardware breakpoints

This commit is contained in:
momo5502
2024-09-01 20:10:10 +02:00
parent 5254a28519
commit 405a53ccef
4 changed files with 89 additions and 25 deletions

View File

@@ -24,6 +24,25 @@ namespace
throw std::runtime_error("Bad action");
}
breakpoint_type map_breakpoint_type(const bp_type_t type)
{
switch (type)
{
case BP_SOFTWARE:
return breakpoint_type::software;
case BP_HARDWARE_EXEC:
return breakpoint_type::hardware_exec;
case BP_HARDWARE_WRITE:
return breakpoint_type::hardware_write;
case BP_HARDWARE_READ:
return breakpoint_type::hardware_read;
case BP_HARDWARE_READ_WRITE:
return breakpoint_type::hardware_read_write;
}
throw std::runtime_error("Bad breakpoint type");
}
gdb_stub_handler& get_handler(void* args)
{
return *static_cast<gdb_stub_handler*>(args);
@@ -59,20 +78,14 @@ namespace
return get_handler(args).write_mem(addr, len, val) ? 0 : 1;
}
bool set_bp(void* args, const size_t addr, const bp_type_t type)
bool set_bp(void* args, const size_t addr, const bp_type_t type, const size_t size)
{
(void)type;
assert(type == BP_SOFTWARE);
return get_handler(args).set_bp(addr);
return get_handler(args).set_bp(map_breakpoint_type(type), addr, size);
}
bool del_bp(void* args, const size_t addr, const bp_type_t type)
bool del_bp(void* args, const size_t addr, const bp_type_t type, const size_t size)
{
(void)type;
assert(type == BP_SOFTWARE);
return get_handler(args).del_bp(addr);
return get_handler(args).del_bp(map_breakpoint_type(type), addr, size);
}
void on_interrupt(void* args)

View File

@@ -7,6 +7,15 @@ enum class gdb_action : uint8_t
shutdown,
};
enum class breakpoint_type : uint8_t
{
software,
hardware_exec,
hardware_write,
hardware_read,
hardware_read_write,
};
struct gdb_stub_handler
{
virtual ~gdb_stub_handler() = default;
@@ -20,8 +29,8 @@ struct gdb_stub_handler
virtual bool read_mem(size_t addr, size_t len, void* val) = 0;
virtual bool write_mem(size_t addr, size_t len, void* val) = 0;
virtual bool set_bp(size_t addr) = 0;
virtual bool del_bp(size_t addr) = 0;
virtual bool set_bp(breakpoint_type type, size_t addr, size_t size) = 0;
virtual bool del_bp(breakpoint_type type, size_t addr, size_t size) = 0;
virtual void on_interrupt() = 0;
};

View File

@@ -21,11 +21,34 @@
#define IA32_GS_BASE_MSR 0xC0000101
#define STACK_SIZE 0x40000
#define STACK_ADDRESS (0x800000000000 - STACK_SIZE)
#define STACK_ADDRESS (0x80000000000 - STACK_SIZE)
#define KUSD_ADDRESS 0x7ffe0000
bool use_gdb = false;
bool use_gdb = true;
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);
}
};
namespace
{
@@ -352,6 +375,24 @@ namespace
{gdb_registers::eflags, x64_register::rflags},
};
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");
}
}
class scoped_emulator_hook
{
public:
@@ -499,15 +540,16 @@ namespace
}
}
bool set_bp(const size_t addr) override
bool set_bp(const breakpoint_type type, const size_t addr, const size_t size) override
{
try
{
this->hooks_[addr] = scoped_emulator_hook(*this->emu_, this->emu_->hook_memory_execution(
addr, 1, [this](uint64_t, size_t)
{
this->on_interrupt();
}));
this->hooks_[{addr, size, type}] = scoped_emulator_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;
}
@@ -517,11 +559,11 @@ namespace
}
}
bool del_bp(const size_t addr) override
bool del_bp(const breakpoint_type type, const size_t addr, const size_t size) override
{
try
{
const auto entry = this->hooks_.find(addr);
const auto entry = this->hooks_.find({addr, size, type});
if (entry == this->hooks_.end())
{
return false;
@@ -544,7 +586,7 @@ namespace
private:
x64_emulator* emu_{};
std::unordered_map<size_t, scoped_emulator_hook> hooks_{};
std::unordered_map<breakpoint_key, scoped_emulator_hook> hooks_{};
};
uint64_t find_exported_function(const std::vector<exported_symbol>& exports, const std::string_view name)