diff --git a/app/src/main/cpp/core/arm/cpu.cpp b/app/src/main/cpp/core/arm/cpu.cpp index a9ce288c..a8e23034 100644 --- a/app/src/main/cpp/core/arm/cpu.cpp +++ b/app/src/main/cpp/core/arm/cpu.cpp @@ -1,57 +1,83 @@ +#include #include "cpu.h" #include "memory.h" // TODO: Handle Unicorn errors -namespace core { - Cpu* currentContext; +namespace core::cpu { + uc_engine *uc; + void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data); - Cpu::Cpu() { + uint64_t GetRegister(uint32_t regid); + + void SetRegister(uint32_t regid, uint64_t value); + + bool Initialize() { uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); uc_hook hook{}; - uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)HookInterrupt, this, 1, 0); + uc_hook_add(uc, &hook, UC_HOOK_INTR, (void *) HookInterrupt, 0, 1, 0); // Map stack memory - memory::Map(uc, 0x3000000, 0x1000000, "stack"); + if (!memory::Map(0x3000000, 0x1000000, "stack")) return false; SetRegister(UC_ARM64_REG_SP, 0x3100000); - memory::Map(uc, 0x2000000, 0x1000, "tls"); + // Map TLS memory + if (!memory::Map(0x2000000, 0x1000, "tls")) return false; SetRegister(UC_ARM64_REG_TPIDRRO_EL0, 0x2000000); - currentContext = this; + return true; } - void Cpu::Run(uint64_t address) { + void Run(uint64_t address) { uc_err err = uc_emu_start(uc, address, 1ULL << 63, 0, 0); - if(err) + if (err) syslog(LOG_ERR, "uc_emu_start failed: %s", uc_strerror(err)); } - uint64_t Cpu::GetRegister(uint32_t regid) { + uint64_t GetRegister(uint32_t regid) { uint64_t registerValue; uc_reg_read(uc, regid, ®isterValue); return registerValue; } - void Cpu::SetRegister(uint32_t regid, uint64_t value) { + void SetRegister(uint32_t regid, uint64_t value) { uc_reg_write(uc, regid, &value); } void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data) { - syslog(LOG_WARNING, "Interrupt called at x%x", currentContext->GetRegister(UC_ARM64_REG_PC)); if (intno == 2) { uint32_t instr{}; - uc_mem_read(uc, currentContext->GetRegister(UC_ARM64_REG_PC) - 4, &instr, 4); + uc_mem_read(uc, GetRegister(UC_ARM64_REG_PC) - 4, &instr, 4); uint32_t svcId = instr >> 5 & 0xFF; // TODO: Handle SVCs syslog(LOG_DEBUG, "SVC 0x%x called!", svcId); + uc_close(uc); } else { syslog(LOG_ERR, "Unhandled interrupt #%i", intno); uc_close(uc); } } +} - Cpu* CpuContext() { return currentContext; } +// FIXME: Move this back to memory.cpp - zephyren25 +namespace core::memory { + bool Map(uint64_t address, size_t size, std::string label) { + void *ptr = mmap((void*)(address), size, PROT_EXEC | PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANON, 0, 0); + if (!ptr) { + syslog(LOG_ERR, "Failed mapping region '%s'", label.c_str()); + return false; + } + + uc_err err = uc_mem_map_ptr(core::cpu::uc, address, size, UC_PROT_ALL, (void*)(address)); + if (err) { + syslog(LOG_ERR, "UC map failed: %s", uc_strerror(err)); + return false; + } + + syslog(LOG_DEBUG, "Successfully mapped region '%s' to 0x%x", label.c_str(), address); + return true; + } } \ No newline at end of file diff --git a/app/src/main/cpp/core/arm/cpu.h b/app/src/main/cpp/core/arm/cpu.h index 056ee0bc..82cbc6ac 100644 --- a/app/src/main/cpp/core/arm/cpu.h +++ b/app/src/main/cpp/core/arm/cpu.h @@ -2,21 +2,12 @@ #include #include -namespace core { - class Cpu { - public: - Cpu(); - ~Cpu() { uc_close(uc); }; +namespace core::cpu { + bool Initialize(); + void Run(uint64_t address); - void Run(uint64_t address); + uint64_t GetRegister(uint32_t regid); + void SetRegister(uint32_t regid, uint64_t value); - uint64_t GetRegister(uint32_t regid); - void SetRegister(uint32_t regid, uint64_t value); - - uc_engine *uc; -// private: -// void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data); - }; - - Cpu* CpuContext(); +// bool MapUnicorn(uint64_t address, size_t size); } \ No newline at end of file diff --git a/app/src/main/cpp/core/arm/memory.cpp b/app/src/main/cpp/core/arm/memory.cpp index 367a9b40..778b351f 100644 --- a/app/src/main/cpp/core/arm/memory.cpp +++ b/app/src/main/cpp/core/arm/memory.cpp @@ -4,26 +4,24 @@ #include "memory.h" namespace core::memory { - std::vector memoryRegions; - - bool Map(uc_engine* uc, uint64_t address, size_t size, std::string label) { - void* ptr = mmap((void*)(address), size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0); - if (!ptr) return false; - - // Skipping this until the CPU implementation is working - if (uc) { - uc_err err = uc_mem_map_ptr(uc, address, size, UC_PROT_ALL, ptr); - if (err) { - syslog(LOG_ERR, "Memory map failed: %s", uc_strerror(err)); - return false; - } - } - - syslog(LOG_INFO, "Successfully mapped region '%s' to 0x%x", label.c_str(), address); - - memoryRegions.push_back({label, address, size, ptr}); - return true; - } +// std::vector memoryRegions; +// +// bool Map(uint64_t address, size_t size, std::string label) { +// void* ptr = mmap((void*)(address), size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0); +// if (!ptr) { +// syslog(LOG_ERR, "Failed mapping region '%s'", label.c_str()); +// return false; +// } +// +// syslog(LOG_INFO, "Mapping region '%s' to 0x%x, pointer %x", label.c_str(), address, (uint64_t)ptr); +// +// if (core::cpu::MapUnicorn(address, size, ptr)) return false; +// +// syslog(LOG_INFO, "Successfully mapped region '%s' to 0x%x", label.c_str(), address); +// +// memoryRegions.push_back({label, address, size, ptr}); +// return true; +// } // TODO: Boundary checks void Write(void* data, uint64_t offset, size_t size) { std::memcpy((void*)(offset), data, size); } diff --git a/app/src/main/cpp/core/arm/memory.h b/app/src/main/cpp/core/arm/memory.h index 17077a00..80808b21 100644 --- a/app/src/main/cpp/core/arm/memory.h +++ b/app/src/main/cpp/core/arm/memory.h @@ -12,7 +12,7 @@ namespace core::memory { void* ptr; }; - bool Map(uc_engine* uc, uint64_t address, size_t size, std::string label = {}); + bool Map(uint64_t address, size_t size, std::string label = {}); void Write(void* data, uint64_t offset, size_t size); diff --git a/app/src/main/cpp/core/hos/loaders/nro.cpp b/app/src/main/cpp/core/hos/loaders/nro.cpp index 4fbee9ed..bac4005b 100644 --- a/app/src/main/cpp/core/hos/loaders/nro.cpp +++ b/app/src/main/cpp/core/hos/loaders/nro.cpp @@ -36,11 +36,10 @@ namespace core::loader { ReadDataFromFile(file, reinterpret_cast(ro.data()), header.segments[1].fileOffset, header.segments[1].size); ReadDataFromFile(file, reinterpret_cast(data.data()), header.segments[2].fileOffset, header.segments[2].size); - uc_engine* uc = core::CpuContext()->uc; - if( !memory::Map(uc, BASE_ADDRESS, header.segments[0].size, ".text") || - !memory::Map(uc, BASE_ADDRESS + header.segments[0].size, header.segments[1].size, ".ro") || - !memory::Map(uc, BASE_ADDRESS + header.segments[0].size + header.segments[1].size, header.segments[2].size, ".data") || - !memory::Map(uc, BASE_ADDRESS + header.segments[0].size + header.segments[1].size + header.segments[2].size, header.bssSize, ".bss")) { + if( !memory::Map(BASE_ADDRESS, header.segments[0].size, ".text") || + !memory::Map(BASE_ADDRESS + header.segments[0].size, header.segments[1].size, ".ro") || + !memory::Map(BASE_ADDRESS + header.segments[0].size + header.segments[1].size, header.segments[2].size, ".data") || + !memory::Map(BASE_ADDRESS + header.segments[0].size + header.segments[1].size + header.segments[2].size, header.bssSize, ".bss")) { syslog(LOG_ERR, "Failed mapping regions for executable"); return false;