mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-11-22 20:39:20 +01:00
Minor code cleanup
This commit is contained in:
parent
e108d4a0be
commit
040121340a
@ -9,48 +9,56 @@ namespace core::cpu {
|
|||||||
|
|
||||||
void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data);
|
void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data);
|
||||||
|
|
||||||
bool Initialize() {
|
bool Initialize()
|
||||||
|
{
|
||||||
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, 0, 1, 0);
|
uc_hook_add(uc, &hook, UC_HOOK_INTR, (void *) HookInterrupt, 0, 1, 0);
|
||||||
|
|
||||||
// Map stack memory
|
// Map stack memory
|
||||||
if (!memory::Map(0x3000000, 0x1000000, "stack")) return false;
|
if (!memory::Map(0x3000000, 0x1000000, "Stack")) return false;
|
||||||
SetRegister(UC_ARM64_REG_SP, 0x3100000);
|
SetRegister(UC_ARM64_REG_SP, 0x3100000);
|
||||||
|
|
||||||
// Map TLS memory
|
// Map TLS memory
|
||||||
if (!memory::Map(0x2000000, 0x1000, "tls")) return false;
|
if (!memory::Map(0x2000000, 0x1000, "TLS")) return false;
|
||||||
SetRegister(UC_ARM64_REG_TPIDRRO_EL0, 0x2000000);
|
SetRegister(UC_ARM64_REG_TPIDRRO_EL0, 0x2000000);
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Run(uint64_t address) {
|
void Run(uint64_t address)
|
||||||
|
{
|
||||||
uc_err err = uc_emu_start(uc, address, 1ULL << 63, 0, 0);
|
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));
|
||||||
syslog(LOG_ERR, "uc_emu_start failed: %s", uc_strerror(err));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t GetRegister(uint32_t regid) {
|
uint64_t GetRegister(uint32_t regid)
|
||||||
|
{
|
||||||
uint64_t registerValue;
|
uint64_t registerValue;
|
||||||
uc_reg_read(uc, regid, ®isterValue);
|
uc_reg_read(uc, regid, ®isterValue);
|
||||||
return registerValue;
|
return registerValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetRegister(uint32_t regid, uint64_t value) {
|
void SetRegister(uint32_t regid, uint64_t value)
|
||||||
|
{
|
||||||
uc_reg_write(uc, regid, &value);
|
uc_reg_write(uc, regid, &value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data) {
|
void HookInterrupt(uc_engine *uc, uint32_t intno, void *user_data)
|
||||||
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, GetRegister(UC_ARM64_REG_PC) - 4, &instr, 4);
|
||||||
|
|
||||||
uint32_t svcId = instr >> 5 & 0xFF;
|
uint32_t svcId = instr >> 5 & 0xFF;
|
||||||
|
|
||||||
if(core::kernel::SvcHandler(svcId) == 0x177202)
|
if (core::kernel::SvcHandler(svcId) == 0x177202)
|
||||||
uc_close(uc);
|
uc_close(uc);
|
||||||
} else {
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Unhandled interrupt #%i", intno);
|
syslog(LOG_ERR, "Unhandled interrupt #%i", intno);
|
||||||
uc_close(uc);
|
uc_close(uc);
|
||||||
}
|
}
|
||||||
@ -62,13 +70,15 @@ namespace core::memory {
|
|||||||
bool Map(uint64_t address, size_t size, std::string label) {
|
bool Map(uint64_t address, size_t size, std::string label) {
|
||||||
void *ptr = mmap((void*)(address), size, PROT_EXEC | PROT_READ | PROT_WRITE,
|
void *ptr = mmap((void*)(address), size, PROT_EXEC | PROT_READ | PROT_WRITE,
|
||||||
MAP_PRIVATE | MAP_ANON, 0, 0);
|
MAP_PRIVATE | MAP_ANON, 0, 0);
|
||||||
if (!ptr) {
|
if (!ptr)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Failed mapping region '%s'", label.c_str());
|
syslog(LOG_ERR, "Failed mapping region '%s'", label.c_str());
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
uc_err err = uc_mem_map_ptr(core::cpu::uc, address, size, UC_PROT_ALL, (void*)(address));
|
uc_err err = uc_mem_map_ptr(core::cpu::uc, address, size, UC_PROT_ALL, (void*)(address));
|
||||||
if (err) {
|
if (err)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "UC map failed: %s", uc_strerror(err));
|
syslog(LOG_ERR, "UC map failed: %s", uc_strerror(err));
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -4,24 +4,24 @@
|
|||||||
#include "memory.h"
|
#include "memory.h"
|
||||||
|
|
||||||
namespace core::memory {
|
namespace core::memory {
|
||||||
// std::vector<MemoryRegion> memoryRegions;
|
/*std::vector<MemoryRegion> memoryRegions;
|
||||||
//
|
|
||||||
// bool Map(uint64_t address, size_t size, std::string label) {
|
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);
|
void* ptr = mmap((void*)(address), size, PROT_EXEC | PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, 0, 0);
|
||||||
// if (!ptr) {
|
if (!ptr) {
|
||||||
// syslog(LOG_ERR, "Failed mapping region '%s'", label.c_str());
|
syslog(LOG_ERR, "Failed mapping region '%s'", label.c_str());
|
||||||
// return false;
|
return false;
|
||||||
// }
|
}
|
||||||
//
|
|
||||||
// syslog(LOG_INFO, "Mapping region '%s' to 0x%x, pointer %x", label.c_str(), address, (uint64_t)ptr);
|
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;
|
if (core::cpu::MapUnicorn(address, size, ptr)) return false;
|
||||||
//
|
|
||||||
// syslog(LOG_INFO, "Successfully mapped region '%s' to 0x%x", label.c_str(), address);
|
syslog(LOG_INFO, "Successfully mapped region '%s' to 0x%x", label.c_str(), address);
|
||||||
//
|
|
||||||
// memoryRegions.push_back({label, address, size, ptr});
|
memoryRegions.push_back({label, address, size, ptr});
|
||||||
// return true;
|
return true;
|
||||||
// }
|
}*/
|
||||||
|
|
||||||
// TODO: Boundary checks
|
// TODO: Boundary checks
|
||||||
void Write(void* data, uint64_t offset, size_t size) { std::memcpy((void*)(offset), data, size); }
|
void Write(void* data, uint64_t offset, size_t size) { std::memcpy((void*)(offset), data, size); }
|
||||||
|
@ -5,25 +5,25 @@
|
|||||||
#define BASE_ADDRESS 0x80000000
|
#define BASE_ADDRESS 0x80000000
|
||||||
|
|
||||||
namespace core::memory {
|
namespace core::memory {
|
||||||
struct MemoryRegion {
|
/*struct MemoryRegion {
|
||||||
std::string label;
|
std::string label;
|
||||||
uint64_t address;
|
uint64_t address;
|
||||||
size_t size;
|
size_t size;
|
||||||
void* ptr;
|
void* ptr;
|
||||||
};
|
};*/
|
||||||
|
|
||||||
bool Map(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);
|
void Write(void* data, uint64_t offset, size_t size);
|
||||||
|
|
||||||
void WriteU8 (uint8_t value, uint64_t offset);
|
void WriteU8(uint8_t value, uint64_t offset);
|
||||||
void WriteU16(uint16_t value, uint64_t offset);
|
void WriteU16(uint16_t value, uint64_t offset);
|
||||||
void WriteU32(uint32_t value, uint64_t offset);
|
void WriteU32(uint32_t value, uint64_t offset);
|
||||||
void WriteU64(uint64_t value, uint64_t offset);
|
void WriteU64(uint64_t value, uint64_t offset);
|
||||||
|
|
||||||
void Read(void* destination, uint64_t offset, size_t size);
|
void Read(void* destination, uint64_t offset, size_t size);
|
||||||
|
|
||||||
uint8_t ReadU8 (uint64_t offset);
|
uint8_t ReadU8(uint64_t offset);
|
||||||
uint16_t ReadU16(uint64_t offset);
|
uint16_t ReadU16(uint64_t offset);
|
||||||
uint32_t ReadU32(uint64_t offset);
|
uint32_t ReadU32(uint64_t offset);
|
||||||
uint64_t ReadU64(uint64_t offset);
|
uint64_t ReadU64(uint64_t offset);
|
||||||
|
@ -8,7 +8,8 @@
|
|||||||
|
|
||||||
using namespace core::cpu;
|
using namespace core::cpu;
|
||||||
namespace core::kernel {
|
namespace core::kernel {
|
||||||
static uint32_t OutputDebugString() {
|
static uint32_t OutputDebugString()
|
||||||
|
{
|
||||||
std::string debug(GetRegister(UC_ARM64_REG_X1), '\0');
|
std::string debug(GetRegister(UC_ARM64_REG_X1), '\0');
|
||||||
memory::Read((void*)debug.data(), GetRegister(UC_ARM64_REG_X0), GetRegister(UC_ARM64_REG_X1));
|
memory::Read((void*)debug.data(), GetRegister(UC_ARM64_REG_X0), GetRegister(UC_ARM64_REG_X1));
|
||||||
|
|
||||||
@ -152,7 +153,7 @@ namespace core::kernel {
|
|||||||
{
|
{
|
||||||
std::pair<int, uint32_t(*)()>* result = &(svcTable[svc]);
|
std::pair<int, uint32_t(*)()>* result = &(svcTable[svc]);
|
||||||
|
|
||||||
if(result->second)
|
if (result->second)
|
||||||
return result->second();
|
return result->second();
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -17,12 +17,14 @@ void ReadDataFromFile(std::string file, char* output, uint32_t offset, size_t si
|
|||||||
}
|
}
|
||||||
|
|
||||||
namespace core::loader {
|
namespace core::loader {
|
||||||
bool LoadNro(std::string file) {
|
bool LoadNro(std::string filePath)
|
||||||
syslog(LOG_INFO, "Loading NRO file %s\n", file.c_str());
|
{
|
||||||
|
syslog(LOG_INFO, "Loading NRO file %s\n", filePath.c_str());
|
||||||
|
|
||||||
NroHeader header;
|
NroHeader header;
|
||||||
ReadDataFromFile(file, reinterpret_cast<char *>(&header), 0x0, sizeof(NroHeader));
|
ReadDataFromFile(filePath, reinterpret_cast<char *>(&header), 0x0, sizeof(NroHeader));
|
||||||
if (header.magic != 0x304F524E) {
|
if (header.magic != 0x304F524E)
|
||||||
|
{
|
||||||
syslog(LOG_ERR, "Invalid NRO magic 0x%x\n", header.magic);
|
syslog(LOG_ERR, "Invalid NRO magic 0x%x\n", header.magic);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -32,21 +34,21 @@ namespace core::loader {
|
|||||||
ro.resize (header.segments[1].size);
|
ro.resize (header.segments[1].size);
|
||||||
data.resize(header.segments[2].size);
|
data.resize(header.segments[2].size);
|
||||||
|
|
||||||
ReadDataFromFile(file, reinterpret_cast<char *>(text.data()), header.segments[0].fileOffset, header.segments[0].size);
|
ReadDataFromFile(filePath, reinterpret_cast<char *>(text.data()), header.segments[0].fileOffset, header.segments[0].size);
|
||||||
ReadDataFromFile(file, reinterpret_cast<char *>(ro.data()), header.segments[1].fileOffset, header.segments[1].size);
|
ReadDataFromFile(filePath, 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(filePath, reinterpret_cast<char *>(data.data()), header.segments[2].fileOffset, header.segments[2].size);
|
||||||
|
|
||||||
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")) {
|
|
||||||
|
|
||||||
|
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");
|
syslog(LOG_ERR, "Failed mapping regions for executable");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
memory::Write(text.data(), BASE_ADDRESS, text.size());
|
memory::Write(text.data(), BASE_ADDRESS, text.size());
|
||||||
memory::Write(ro.data(), BASE_ADDRESS + header.segments[0].size, ro.size());
|
memory::Write(ro.data(), BASE_ADDRESS + header.segments[0].size, ro.size());
|
||||||
memory::Write(data.data(), BASE_ADDRESS + header.segments[0].size + header.segments[1].size, data.size());
|
memory::Write(data.data(), BASE_ADDRESS + header.segments[0].size + header.segments[1].size, data.size());
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
@ -27,5 +27,5 @@ namespace core::loader {
|
|||||||
NroSegmentHeader extraSegments[3];
|
NroSegmentHeader extraSegments[3];
|
||||||
};
|
};
|
||||||
|
|
||||||
bool LoadNro(std::string file);
|
bool LoadNro(std::string filePath);
|
||||||
}
|
}
|
@ -1,12 +1,19 @@
|
|||||||
#include <jni.h>
|
#include <jni.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <syslog.h>
|
#include <syslog.h>
|
||||||
|
#include <core/arm/cpu.h>
|
||||||
|
#include <core/hos/loaders/nro.h>
|
||||||
|
#include <core/arm/memory.h>
|
||||||
|
|
||||||
extern "C" JNIEXPORT jstring JNICALL
|
extern "C" JNIEXPORT jstring JNICALL
|
||||||
Java_gq_cyuubi_lightswitch_MainActivity_stringFromJNI(
|
Java_gq_cyuubi_lightswitch_MainActivity_stringFromJNI(
|
||||||
JNIEnv *env,
|
JNIEnv *env,
|
||||||
jobject /* this */) {
|
jobject /* this */) {
|
||||||
|
|
||||||
|
core::cpu::Initialize();
|
||||||
|
core::loader::LoadNro("/sdcard/test.nro");
|
||||||
|
core::cpu::Run(BASE_ADDRESS);
|
||||||
|
|
||||||
std::string finished = "finished!";
|
std::string finished = "finished!";
|
||||||
return env->NewStringUTF(finished.c_str());
|
return env->NewStringUTF(finished.c_str());
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user