Change RAMBlock logic

This commit is contained in:
rkx1209 2018-04-19 22:26:12 +09:00
parent 1e5f0c3acf
commit f822b1d4a1
8 changed files with 143 additions and 43 deletions

View file

@ -15,26 +15,25 @@ uint64_t GvaToHva(const uint64_t gva) {
template<typename T>
static T ReadFromRAM(const uint64_t gpa) {
T value = 0;
//ns_print("ReadFromRAM: 0x%lx, (%d)\n", gpa, sizeof(T));
uint8_t *emu_mem = static_cast<uint8_t *>(Memory::GetRawPtr(gpa, sizeof(T)));
debug_print("ReadFromRAM: 0x%lx, (%d)\n", gpa, sizeof(T));
for (uint64_t addr = gpa; addr < gpa + sizeof(T); addr++) {
uint8_t byte;
std::memcpy (&byte, &Memory::pRAM[addr], sizeof(uint8_t));
std::memcpy (&byte, &emu_mem[addr - gpa], sizeof(uint8_t));
value = value | ((uint64_t)byte << (8 * (addr - gpa)));
}
uint8_t *ptr = &Memory::pRAM[gpa];
bindump (ptr, sizeof(T));
return value;
}
template<typename T>
static void WriteToRAM(const uint64_t gpa, T value) {
uint8_t *emu_mem = static_cast<uint8_t *>(Memory::GetRawPtr(gpa, sizeof(T)));
debug_print("WriteToRAM: 0x%lx, (%d)\n", gpa, sizeof(T));
for (uint64_t addr = gpa; addr < gpa + sizeof(T); addr++) {
uint8_t byte = value & 0xff;
std::memcpy (&Memory::pRAM[addr], &byte, sizeof(uint8_t));
std::memcpy (&emu_mem[addr - gpa], &byte, sizeof(uint8_t));
value >>= 8;
}
uint8_t *ptr = &Memory::pRAM[gpa];
bindump (ptr, sizeof(T));
}
void ReadBytes(uint64_t gva, uint8_t *ptr, int size) {

View file

@ -29,7 +29,7 @@ State GetState() {
}
void DumpMachine() {
//ARMv8::Dump ();
ARMv8::Dump ();
if (TraceOut)
ARMv8::DumpJson (TraceOut);
}

View file

@ -2,7 +2,7 @@
#include <sys/mman.h>
#include "Nsemu.hpp"
RAMBlock::RAMBlock (std::string _name, uint64_t _addr, size_t _length, int _perm) {
RAMBlock::RAMBlock (std::string _name, uint64_t _addr, size_t _length, int _perm) : block(nullptr){
int page = getpagesize ();
name = _name;
length = _length;
@ -12,14 +12,28 @@ RAMBlock::RAMBlock (std::string _name, uint64_t _addr, size_t _length, int _perm
}
addr = _addr;
}
RAMBlock::RAMBlock(std::string _name, uint64_t _addr, size_t _length, uint8_t *raw, int _perm) {
int page = getpagesize ();
name = _name;
length = _length;
perm = _perm;
if (addr & (page - 1)) {
addr = addr & ~(page - 1);
}
addr = _addr;
block = raw;
}
namespace Memory
{
uint64_t heap_base = 0x9000000;
uint64_t heap_size = 0x2000000;
uint64_t heap_size = 0x1000000;
//uint64_t heap_size = 0x0;
uint8_t *pRAM; // XXX: Replace raw pointer to View wrapper.
static RAMBlock mem_map[] =
size_t ram_size = 0x10000000;
uint64_t straight_max = heap_base + heap_size;
std::vector<RAMBlock*> regions;
static RAMBlock mem_map_straight[] =
{
RAMBlock (".text", 0x0, 0x1000000, PROT_READ | PROT_WRITE | PROT_EXEC),
RAMBlock (".rdata", 0x1000000, 0x1000000, PROT_READ | PROT_WRITE),
@ -28,33 +42,79 @@ static RAMBlock mem_map[] =
RAMBlock ("[heap]", heap_base, heap_size, PROT_READ | PROT_WRITE),
};
static bool inline IsStraight(uint64_t addr, size_t len) {
return addr + len <= straight_max;
}
static RAMBlock* FindRamBlock(uint64_t addr, size_t len) {
for (int i = 0; i < regions.size(); i++) {
if (regions[i]->addr <= addr && addr + len <= regions[i]->addr + regions[i]->length) {
return regions[i];
}
}
return nullptr;
}
static void AddAnonStraight(uint64_t addr, size_t len, int perm) {
//ns_print("Add anonymous fixed region [0x%lx, %d]\n", addr, len);
RAMBlock *new_ram = new RAMBlock("[anon]", addr, len, perm) ;
regions.push_back(new_ram);
}
static void AddAnonRamBlock(uint64_t addr, size_t len, int perm) {
uint8_t *raw = new uint8_t[len];
if (!raw) {
ns_abort("Failed to allocate new RAM Block\n");
}
RAMBlock *new_ram = new RAMBlock("[anon]", addr, len, raw, perm);
//ns_print("Add anonymous region [0x%lx, %d]\n", new_ram->addr, new_ram->length);
regions.push_back(new_ram);
}
void AddMemmap(uint64_t addr, size_t len) {
if (IsStraight(addr, len)) {
/* Within straight regions */
AddAnonStraight(addr, len, PROT_READ | PROT_WRITE);
return;
}
// if (ExistOverlap(addr, len))
/* TODO Detect overlapped areas */
/* Necessary to extend memory area */
AddAnonRamBlock(addr, len, PROT_READ | PROT_WRITE);
}
void DelMemmap(uint64_t addr, size_t len) {
auto it = regions.begin();
while (it != regions.end()) {
RAMBlock *ram = *it;
if (addr <= ram->addr && ram->addr + ram->length <= addr + len) {
delete ram;
it = regions.erase(it);
} else {
++it;
}
}
}
void InitMemmap(Nsemu *nsemu) {
void *data;
if ((data = mmap (nullptr, 0x10000000, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) {
if ((data = mmap (nullptr, ram_size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)) == MAP_FAILED) {
ns_abort ("Failed to allocate host memory\n");
}
pRAM = (uint8_t *) data;
}
RAMBlock *FindRAMBlock(Nsemu *nsemu, uint64_t addr, size_t len) {
RAMBlock *as;
std::map<std::string, RAMBlock>::iterator it = nsemu->rams.begin ();
for (; it != nsemu->rams.end (); it++) {
as = &it->second;
if (as->addr <= addr && addr + len <= as->addr + as->length) {
return as;
}
}
return nullptr;
for (int i = 0; i < sizeof(mem_map_straight) / sizeof(RAMBlock); i++) {
regions.push_back(&mem_map_straight[i]);
}
}
std::list<std::tuple<uint64_t,uint64_t, int>> GetRegions() {
std::list<std::tuple<uint64_t,uint64_t, int>> ret;
uint64_t last;
for (int i = 0; i < sizeof(mem_map) / sizeof(RAMBlock); i++) {
uint64_t addr = mem_map[i].addr;
size_t length = mem_map[i].length;
int perm = mem_map[i].perm;
for (int i = 0; i < regions.size(); i++) {
uint64_t addr = regions[i]->addr;
size_t length = regions[i]->length;
int perm = regions[i]->perm;
ret.push_back(make_tuple(addr, addr + length, perm));
last = addr + length + 1;
}
@ -62,8 +122,26 @@ std::list<std::tuple<uint64_t,uint64_t, int>> GetRegions() {
return ret;
}
void *GetRawPtr(uint64_t gpa, size_t len) {
void *emu_mem;
if (IsStraight(gpa, len)) {
emu_mem = (void *)&pRAM[gpa];
}
else {
RAMBlock *ram = FindRamBlock (gpa, len);
if (!ram) {
return nullptr;
}
emu_mem = (void *)&ram->block[gpa - ram->addr];
}
return emu_mem;
}
static bool _CopyMemEmu(void *data, uint64_t gpa, size_t len, bool load) {
void *emu_mem = (void *)&pRAM[gpa];
void *emu_mem = GetRawPtr (gpa, len);
if (!emu_mem) {
return false;
}
if (load) {
memcpy (emu_mem, data, len);
} else {

View file

@ -41,11 +41,12 @@ int Nso::load(Nsemu *nsemu) {
ns_abort ("Failed to copy to .text\n");
}
/* --- For test --- */
// uint8_t *txt_dump = new uint8_t[hdr.textSize];
// Memory::CopyfromEmuByName (nsemu, (void *) txt_dump, ".text", hdr.textSize);
// bindump (txt_dump, 105);
// /* ---------------- */
// delete[] text;
uint8_t *txt_dump = new uint8_t[hdr.textSize];
Memory::CopyfromEmu (nsemu, (void *) txt_dump, base + hdr.textLoc, hdr.textSize);
bindump ((uint8_t*)text, 105);
bindump (txt_dump, 105);
/* ---------------- */
delete[] text;
ns_print(".text[0x%x] size = 0x%x\n", hdr.textOff, hdr.textSize);
ns_print(".rdata[0x%x] size = 0x%x\n", hdr.rdataOff, hdr.rdataSize);
ns_print(".data[0x%x] size = 0x%x\n", hdr.dataOff, hdr.dataSize);

14
Svc.cpp
View file

@ -113,10 +113,24 @@ uint64_t SetMemoryAttribute(uint64_t addr, uint64_t size, uint64_t state0, uint6
}
uint64_t MirrorStack(uint64_t dest, uint64_t src, uint64_t size) {
ns_print("MirrorStack 0x%lx 0x%lx 0x%lx\n", dest, src, size);
Memory::AddMemmap (dest, size);
uint8_t *temp = new uint8_t[size];
ARMv8::ReadBytes(src, temp, size);
bindump(temp, size / 10);
ns_print("#############\n");
ARMv8::WriteBytes(dest, temp, size);
ns_print("hoge\n");
ARMv8::ReadBytes(dest, temp, size);
bindump(temp, size / 10);
ns_print("#############\n");
delete[] temp;
return 0;
}
uint64_t UnmapMemory(uint64_t dest, uint64_t src, uint64_t size) {
ns_print("UnmapMemory 0x%lx 0x%lx 0x%lx\n", dest, src, size);
Memory::DelMemmap(dest, size);
return 0;
}

View file

@ -12,8 +12,15 @@ std::string name;
size_t length;
int perm;
uint64_t addr; //gpa (guest physical address)
RAMBlock() {}
RAMBlock(std::string _name, uint64_t _addr, size_t _length, int _perm);
uint8_t *block;
RAMBlock() { block = nullptr; }
RAMBlock(std::string _name, uint64_t _addr, size_t _length, int _perm); //straight mapping
RAMBlock(std::string _name, uint64_t _addr, size_t _length, uint8_t *raw, int _perm);
~RAMBlock() {
if (block) {
delete[] block;
}
}
bool operator<(const RAMBlock &as) {
return name < as.name;
}
@ -27,12 +34,14 @@ extern uint64_t heap_base;
extern uint64_t heap_size;
void InitMemmap(Nsemu *nsemu);
RAMBlock *FindRAMBlock(Nsemu *nsemu, uint64_t addr, size_t len);
void AddMemmap(uint64_t addr, size_t len);
void DelMemmap(uint64_t addr, size_t len);
std::list<std::tuple<uint64_t,uint64_t, int>> GetRegions();
void *GetRawPtr(uint64_t gpa, size_t len);
bool CopytoEmu(Nsemu *nsemu, void *data, uint64_t addr, size_t len);
bool CopytoEmuByName(Nsemu *nsemu, void *data, std::string name, size_t len);
bool CopyfromEmu(Nsemu *nsemu, void *data, uint64_t addr, size_t len);
bool CopyfromEmuByName(Nsemu *nsemu, void *data, std::string name, size_t len);
}
#endif

View file

@ -39,7 +39,6 @@ Nsemu() = default;
static Nsemu *inst;
public:
std::map<std::string, RAMBlock> rams;
public:
Nsemu(const Nsemu&) = delete;
Nsemu& operator=(const Nsemu&) = delete;

View file

@ -39,16 +39,16 @@ static void util_print(RunLevel level, FILE *fp, const char *format, ...) {
inline void bindump(uint8_t *ptr, size_t size) {
int i = 0;
while (i < size) {
debug_print ("%02x", ptr[i]);
ns_print ("%02x", ptr[i]);
if ((i + 1) % LINE_BREAK == 0) {
debug_print ("\n");
ns_print ("\n");
} else {
debug_print (" ");
ns_print (" ");
}
i++;
}
if (i % LINE_BREAK != 0) {
debug_print ("\n");
ns_print ("\n");
}
}