Properly read and write registers

This commit is contained in:
momo5502
2025-01-19 10:18:45 +01:00
parent 192d5687ff
commit 77b4ee5e1e
7 changed files with 43 additions and 47 deletions

View File

@@ -109,7 +109,7 @@ namespace utils::string
return to_hex_string(&i, sizeof(Integer), uppercase);
}
inline std::string to_hex_string(const std::span<std::byte> data, const bool uppercase = false)
inline std::string to_hex_string(const std::span<const std::byte> data, const bool uppercase = false)
{
return to_hex_string(data.data(), data.size(), uppercase);
}

View File

@@ -12,8 +12,8 @@ struct cpu_interface
virtual void start(uint64_t start, uint64_t end = 0, std::chrono::nanoseconds timeout = {}, size_t count = 0) = 0;
virtual void stop() = 0;
virtual void read_raw_register(int reg, void* value, size_t size) = 0;
virtual void write_raw_register(int reg, const void* value, size_t size) = 0;
virtual size_t read_raw_register(int reg, void* value, size_t size) = 0;
virtual size_t write_raw_register(int reg, const void* value, size_t size) = 0;
virtual std::vector<std::byte> save_registers() = 0;
virtual void restore_registers(const std::vector<std::byte>& register_data) = 0;

View File

@@ -20,14 +20,14 @@ class typed_emulator : public emulator
this->start(this->read_instruction_pointer(), 0, timeout, count);
}
void write_register(registers reg, const void* value, const size_t size)
size_t write_register(registers reg, const void* value, const size_t size)
{
this->write_raw_register(static_cast<int>(reg), value, size);
return this->write_raw_register(static_cast<int>(reg), value, size);
}
void read_register(registers reg, void* value, const size_t size)
size_t read_register(registers reg, void* value, const size_t size)
{
this->read_raw_register(static_cast<int>(reg), value, size);
return this->read_raw_register(static_cast<int>(reg), value, size);
}
template <typename T = pointer_type>
@@ -90,6 +90,6 @@ class typed_emulator : public emulator
private:
emulator_hook* hook_instruction(int instruction_type, instruction_hook_callback callback) override = 0;
void read_raw_register(int reg, void* value, size_t size) override = 0;
void write_raw_register(int reg, const void* value, size_t size) override = 0;
size_t read_raw_register(int reg, void* value, size_t size) override = 0;
size_t write_raw_register(int reg, const void* value, size_t size) override = 0;
};

View File

@@ -209,16 +209,16 @@ namespace gdb_stub
for (size_t i = 0; i < registers; ++i)
{
memset(data.data(), 0, data.size());
const auto res = handler.read_register(i, data.data(), data.size());
const auto size = handler.read_register(i, data.data(), data.size());
if (!res)
if (!size)
{
connection.send_reply("E01");
return;
}
response.append(utils::string::to_hex_string(data));
const std::span register_data(data.data(), size);
response.append(utils::string::to_hex_string(register_data));
}
connection.send_reply(response);
@@ -231,20 +231,21 @@ namespace gdb_stub
const auto registers = handler.get_register_count();
const auto register_size = handler.get_max_register_size();
size_t offset = 0;
for (size_t i = 0; i < registers; ++i)
{
const auto offset = i * register_size;
const auto end_offset = offset + register_size;
if (data.size() < end_offset)
if (offset >= data.size())
{
connection.send_reply("E01");
return;
}
const auto res = handler.write_register(i, data.data() + offset, register_size);
const auto max_size = std::min(register_size, data.size() - offset);
const auto size = handler.write_register(i, data.data() + offset, max_size);
if (!res)
offset += size;
if (!size)
{
connection.send_reply("E01");
return;
@@ -263,11 +264,12 @@ namespace gdb_stub
std::vector<std::byte> data{};
data.resize(handler.get_max_register_size());
const auto res = handler.read_register(reg, data.data(), data.size());
const auto size = handler.read_register(reg, data.data(), data.size());
if (res)
if (size)
{
connection.send_reply(utils::string::to_hex_string(data));
const std::span register_data(data.data(), size);
connection.send_reply(utils::string::to_hex_string(register_data));
}
else
{
@@ -283,12 +285,8 @@ namespace gdb_stub
size_t register_index{};
rt_assert(sscanf_s(std::string(reg).c_str(), "%zx", &register_index) == 1);
const auto register_size = handler.get_max_register_size();
const auto data = utils::string::from_hex_string(hex_data);
const auto res = register_size <= data.size() && //
handler.write_register(register_index, data.data(), register_size);
const auto res = handler.write_register(register_index, data.data(), data.size()) > 0;
connection.send_reply(res ? "OK" : "E01");
}

View File

@@ -31,8 +31,8 @@ namespace gdb_stub
virtual size_t get_register_count() = 0;
virtual size_t get_max_register_size() = 0;
virtual bool read_register(size_t reg, void* data, size_t max_length) = 0;
virtual bool write_register(size_t reg, const void* data, size_t size) = 0;
virtual size_t read_register(size_t reg, void* data, size_t max_length) = 0;
virtual size_t write_register(size_t reg, const void* data, size_t size) = 0;
virtual bool read_memory(uint64_t address, void* data, size_t length) = 0;
virtual bool write_memory(uint64_t address, const void* data, size_t length) = 0;

View File

@@ -301,9 +301,9 @@ namespace unicorn
uce(uc_emu_stop(*this));
}
void write_raw_register(const int reg, const void* value, const size_t size) override
size_t write_raw_register(const int reg, const void* value, const size_t size) override
{
size_t result_size = size;
auto result_size = size;
uce(uc_reg_write2(*this, reg, value, &result_size));
if (size < result_size)
@@ -311,9 +311,11 @@ namespace unicorn
throw std::runtime_error("Register size mismatch: " + std::to_string(size) +
" != " + std::to_string(result_size));
}
return result_size;
}
void read_raw_register(const int reg, void* value, const size_t size) override
size_t read_raw_register(const int reg, void* value, const size_t size) override
{
size_t result_size = size;
memset(value, 0, size);
@@ -324,6 +326,8 @@ namespace unicorn
throw std::runtime_error("Register size mismatch: " + std::to_string(size) +
" != " + std::to_string(result_size));
}
return result_size;
}
void map_mmio(const uint64_t address, const size_t size, mmio_read_callback read_cb,

View File

@@ -105,46 +105,40 @@ class x64_gdb_stub_handler : public gdb_stub::debugging_handler
size_t get_max_register_size() override
{
// return 256 / 8;
return 64 / 8;
return 512 / 8;
}
bool read_register(const size_t reg, void* data, const size_t max_length) override
size_t read_register(const size_t reg, void* data, const size_t max_length) override
{
try
{
if (reg >= gdb_registers.size())
{
// TODO: Fix
return true;
return 0;
}
this->emu_->read_register(gdb_registers[reg], data, max_length);
return true;
return this->emu_->read_register(gdb_registers[reg], data, max_length);
}
catch (...)
{
// TODO: Fix
return true;
return 0;
}
}
bool write_register(const size_t reg, const void* data, const size_t size) override
size_t write_register(const size_t reg, const void* data, const size_t size) override
{
try
{
if (reg >= gdb_registers.size())
{
// TODO: Fix
return true;
return 0;
}
this->emu_->write_register(gdb_registers[reg], data, size);
return true;
return this->emu_->write_register(gdb_registers[reg], data, size);
}
catch (...)
{
return false;
return 0;
}
}