fxos/lib/vspace.cpp

182 lines
4.9 KiB
C++

//---------------------------------------------------------------------------//
// 1100101 |_ mov #0, r4 __ //
// 11 |_ <0xb380 %5c4> / _|_ _____ ___ //
// 0110 |_ 3.50 -> 3.60 | _\ \ / _ (_-< //
// |_ base# + offset |_| /_\_\___/__/ //
//---------------------------------------------------------------------------//
#include <fxos/vspace.h>
#include <fxos/os.h>
#include <cstring>
namespace FxOS {
//=== AbstractMemory ===//
bool AbstractMemory::covers(uint32_t addr, int size) const
{
return (this->translate(addr, size) != nullptr);
}
bool AbstractMemory::covers(MemoryRegion const &region) const
{
return this->covers(region.start, region.size());
}
char const *AbstractMemory::translate(uint32_t addr, int size) const
{
int actual_size;
char const *ptr = this->translate_dynamic(addr, &actual_size);
return (ptr && actual_size >= size) ? ptr : nullptr;
}
Addressable<int8_t> AbstractMemory::read_i8(uint32_t addr) const
{
int8_t *i8 = (int8_t *)this->translate(addr, 1);
if(!i8)
return Addressable((int8_t)-1);
return Addressable(addr, *i8);
}
Addressable<uint8_t> AbstractMemory::read_u8(uint32_t addr) const
{
uint8_t *u8 = (uint8_t *)this->translate(addr, 1);
if(!u8)
return Addressable((uint8_t)-1);
return Addressable(addr, *u8);
}
Addressable<int16_t> AbstractMemory::read_i16(uint32_t addr) const
{
uint8_t *i16 = (uint8_t *)this->translate(addr, 2);
if(!i16)
return Addressable((int16_t)-1);
int16_t v = (i16[0] << 8) | i16[1];
return Addressable(addr, v);
}
Addressable<uint16_t> AbstractMemory::read_u16(uint32_t addr) const
{
uint8_t *u16 = (uint8_t *)this->translate(addr, 2);
if(!u16)
return Addressable((uint16_t)-1);
uint16_t v = (u16[0] << 8) | u16[1];
return Addressable(addr, v);
}
Addressable<int32_t> AbstractMemory::read_i32(uint32_t addr) const
{
uint8_t *i32 = (uint8_t *)this->translate(addr, 4);
if(!i32)
return Addressable((int32_t)-1);
int32_t v = (i32[0] << 24) | (i32[1] << 16) | (i32[2] << 8) | i32[3];
return Addressable(addr, v);
}
Addressable<uint32_t> AbstractMemory::read_u32(uint32_t addr) const
{
uint8_t *u32 = (uint8_t *)this->translate(addr, 4);
if(!u32)
return Addressable((uint32_t)-1);
uint32_t v = (u32[0] << 24) | (u32[1] << 16) | (u32[2] << 8) | u32[3];
return Addressable(addr, v);
}
Addressable<std::string> AbstractMemory::read_str(
uint32_t addr, size_t len) const
{
char const *str = this->translate(addr, len);
if(!str)
return Addressable(std::string());
return Addressable(addr, std::string(str, len));
}
uint32_t AbstractMemory::search(
uint32_t start, uint32_t end, void const *pattern, int size) const
{
void const *data = translate(start, end - start);
if(!data)
return end;
void const *occurrence = memmem(data, end - start, pattern, size);
if(!occurrence)
return end;
return start + ((char *)occurrence - (char *)data);
}
//=== Binding ===//
Binding::Binding(MemoryRegion source_region, Buffer const &source_buffer):
region {source_region}, buffer {source_buffer, region.size()}
{
}
BSON Binding::serialize() const
{
return BSON::mkDocument({
{"*", BSON::mkString("Binding")},
{"start", BSON::mkI32(region.start)},
{"end", BSON::mkI32(region.end)},
{"buffer", buffer.serialize()},
});
}
Binding::Binding(BSON const &b)
{
assert(b.isDocument() && b["*"].getString() == "Binding");
u32 start = b["start"].getI32();
u32 end = b["end"].getI32();
region = MemoryRegion("<anonymous>", start, end, false);
buffer.deserialize(b["buffer"]);
}
char const *Binding::translate_dynamic(uint32_t addr, int *size) const
{
if(addr >= region.start && addr < region.end) {
*size = region.end - addr;
return buffer.data.get() + (addr - region.start);
}
return nullptr;
}
//=== VirtualSpace ===//
VirtualSpace::VirtualSpace(): bindings {}, disasm {*this}
{
}
BSON VirtualSpace::serialize() const
{
BSON b = BSON::mkArray(this->bindings.size());
for(uint i = 0; i < this->bindings.size(); i++)
b[i] = this->bindings[i].serialize();
return b;
}
void VirtualSpace::deserialize(BSON const &b)
{
assert(b.isArray());
for(uint i = 0; i < b.size(); i++)
this->bindings.push_back(Binding(b[i]));
}
void VirtualSpace::bind_region(MemoryRegion const &region, Buffer const &buf)
{
this->bindings.emplace(this->bindings.begin(), region, buf);
}
char const *VirtualSpace::translate_dynamic(uint32_t addr, int *size) const
{
for(auto &b: this->bindings) {
char const *ptr = b.translate_dynamic(addr, size);
if(ptr)
return ptr;
}
return nullptr;
}
} /* namespace FxOS */