Fix interrupt hook and memory maps

This commit is contained in:
Ryan Teal 2019-06-30 22:07:10 +01:00
parent 75c608fd25
commit 4310ffd4dd
No known key found for this signature in database
GPG Key ID: 8DBEE0F12C7E2D23
3 changed files with 29 additions and 10 deletions

View File

@ -1,16 +1,27 @@
#include "cpu.h" #include "cpu.h"
#include "memory.h"
// TODO: Handle Unicorn errors // TODO: Handle Unicorn errors
namespace core { namespace core {
Cpu* currentContext;
void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data);
Cpu::Cpu() { Cpu::Cpu() {
uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc); uc_open(UC_ARCH_ARM64, UC_MODE_ARM, &uc);
uc_hook hook{}; uc_hook hook{};
uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)HookInterrupt, this, 0, -1); uc_hook_add(uc, &hook, UC_HOOK_INTR, (void*)HookInterrupt, this, 1, 0);
// Map stack memory
memory::Map(uc, 0x3000000, 0x1000000, "stack");
SetRegister(UC_ARM64_REG_SP, 0x3100000);
currentContext = this;
} }
void Cpu::Run(uint64_t address) { void Cpu::Run(uint64_t address) {
uc_emu_start(uc, address, 1ULL << 63, 0, 0); uc_err err = uc_emu_start(uc, address, 1ULL << 63, 0, 0);
if(err)
syslog(LOG_ERR, "uc_emu_start failed: %s", uc_strerror(err));
} }
uint64_t Cpu::GetRegister(uint32_t regid) { uint64_t Cpu::GetRegister(uint32_t regid) {
@ -23,17 +34,21 @@ namespace core {
uc_reg_write(uc, regid, &value); uc_reg_write(uc, regid, &value);
} }
void Cpu::HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data) { 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) { if (intno == 2) {
uint32_t instr{}; uint32_t instr{};
uc_mem_read(uc, GetRegister(UC_ARM64_REG_PC) - 4, &instr, 4); uc_mem_read(uc, currentContext->GetRegister(UC_ARM64_REG_PC) - 4, &instr, 4);
uint32_t svcId = instr >> 5 & 0xFF; uint32_t svcId = instr >> 5 & 0xFF;
// TODO: Handle SVCs // TODO: Handle SVCs
syslog(LOG_DEBUG, "SVC 0x%x called!", svcId);
} else { } else {
syslog(LOG_ERR, "Unhandled interrupt #%i", intno); syslog(LOG_ERR, "Unhandled interrupt #%i", intno);
uc_close(uc); uc_close(uc);
} }
} }
Cpu* CpuContext() { return currentContext; }
} }

View File

@ -14,7 +14,9 @@ namespace core {
void SetRegister(uint32_t regid, uint64_t value); void SetRegister(uint32_t regid, uint64_t value);
uc_engine *uc; uc_engine *uc;
private: // private:
void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data); // void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data);
}; };
Cpu* CpuContext();
} }

View File

@ -2,6 +2,7 @@
#include <syslog.h> #include <syslog.h>
#include <sys/mman.h> #include <sys/mman.h>
#include <vector> #include <vector>
#include "../../arm/cpu.h"
#include "../../arm/memory.h" #include "../../arm/memory.h"
#include "nro.h" #include "nro.h"
@ -35,10 +36,11 @@ namespace core::loader {
ReadDataFromFile(file, reinterpret_cast<char *>(ro.data()), header.segments[1].fileOffset, header.segments[1].size); ReadDataFromFile(file, reinterpret_cast<char *>(ro.data()), header.segments[1].fileOffset, header.segments[1].size);
ReadDataFromFile(file, reinterpret_cast<char *>(data.data()), header.segments[2].fileOffset, header.segments[2].size); ReadDataFromFile(file, reinterpret_cast<char *>(data.data()), header.segments[2].fileOffset, header.segments[2].size);
if( !memory::Map(nullptr, BASE_ADDRESS, header.segments[0].size, ".text") || uc_engine* uc = core::CpuContext()->uc;
!memory::Map(nullptr, BASE_ADDRESS + header.segments[0].size, header.segments[1].size, ".ro") || if( !memory::Map(uc, BASE_ADDRESS, header.segments[0].size, ".text") ||
!memory::Map(nullptr, 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, ".ro") ||
!memory::Map(nullptr, BASE_ADDRESS + header.segments[0].size + header.segments[1].size + header.segments[2].size, header.bssSize, ".bss")) { !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")) {
syslog(LOG_ERR, "Failed mapping regions for executable"); syslog(LOG_ERR, "Failed mapping regions for executable");
return false; return false;