Address CR Comments #2

This commit is contained in:
◱ PixelyIon 2020-11-22 23:51:35 +05:30
parent fbf9f06244
commit 8564edcb16
16 changed files with 116 additions and 99 deletions

View File

@ -37,7 +37,6 @@ namespace skyline {
std::lock_guard guard(mtx);
logFile << "0|" << str << "\n";
logFile.flush();
}
void Logger::Write(LogLevel level, std::string str) {
@ -55,7 +54,6 @@ namespace skyline {
std::lock_guard guard(mtx);
logFile << "1|" << levelCharacter[static_cast<u8>(level)] << '|' << threadName << '|' << str << '\n';
logFile.flush();
}
DeviceState::DeviceState(kernel::OS *os, std::shared_ptr<JvmManager> jvmManager, std::shared_ptr<Settings> settings, std::shared_ptr<Logger> logger)

View File

@ -96,7 +96,7 @@ namespace skyline {
* @note There's the exception of signed char pointers as they represent C Strings
* @note This does not cover std::shared_ptr or std::unique_ptr and those will have to be explicitly casted to uintptr_t or passed through fmt::ptr
*/
template<class T>
template<typename T>
constexpr auto FmtCast(T object) {
if constexpr (std::is_pointer<T>::value)
if constexpr (std::is_same<char, typename std::remove_cv<typename std::remove_pointer<T>::type>::type>::value)
@ -147,12 +147,12 @@ namespace skyline {
/**
* @brief A way to implicitly convert a pointer to uintptr_t and leave it unaffected if it isn't a pointer
*/
template<class T>
template<typename T>
T PointerValue(T item) {
return item;
}
template<class T>
template<typename T>
uintptr_t PointerValue(T *item) {
return reinterpret_cast<uintptr_t>(item);
}
@ -160,7 +160,7 @@ namespace skyline {
/**
* @brief A way to implicitly convert an integral to a pointer, if the return type is a pointer
*/
template<class Return, class T>
template<typename Return, typename T>
Return ValuePointer(T item) {
if constexpr (std::is_pointer<Return>::value)
return reinterpret_cast<Return>(item);
@ -253,7 +253,7 @@ namespace skyline {
return result;
}
template<class Type>
template<typename Type>
constexpr Type HexStringToInt(std::string_view string) {
if (string.size() > sizeof(Type) * 2)
throw exception("String size larger than type: {} (sizeof(Type): {})", string.size(), sizeof(Type));
@ -299,7 +299,7 @@ namespace skyline {
/**
* @brief We want to support implicitly casting from std::string_view -> span as it is just a specialization of a data view which span is a generic form of, the opposite doesn't hold true as not all data held by a span is string data therefore the conversion isn't implicit there
*/
template<class Traits>
template<typename Traits>
constexpr span(const std::basic_string_view<T, Traits> &string) : std::span<T, Extent>(const_cast<T *>(string.data()), string.size()) {}
template<typename Out>
@ -375,21 +375,21 @@ namespace skyline {
/**
* @brief Deduction guides required for arguments to span, CTAD will fail for iterators, arrays and containers without this
*/
template<class It, class End, size_t Extent = std::dynamic_extent>
template<typename It, typename End, size_t Extent = std::dynamic_extent>
span(It, End) -> span<typename std::iterator_traits<It>::value_type, Extent>;
template<class T, size_t Size>
template<typename T, size_t Size>
span(T (&)[Size]) -> span<T, Size>;
template<class T, size_t Size>
template<typename T, size_t Size>
span(std::array<T, Size> &) -> span<T, Size>;
template<class T, size_t Size>
template<typename T, size_t Size>
span(const std::array<T, Size> &) -> span<const T, Size>;
template<class Container>
template<typename Container>
span(Container &) -> span<typename Container::value_type>;
template<class Container>
template<typename Container>
span(const Container &) -> span<const typename Container::value_type>;
/**
* @brief The Logger class is to write log output to file and logcat
* @brief A wrapper around writing logs into a log file and logcat using Android Log APIs
*/
class Logger {
private:

View File

@ -21,6 +21,9 @@ namespace skyline {
std::condition_variable produceCondition;
public:
/**
* @note The internal allocation is an item larger as we require a sentinel value
*/
inline CircularQueue(size_t size) : vector((size + 1) * sizeof(Type)) {}
inline CircularQueue(const CircularQueue &) = delete;

View File

@ -46,7 +46,7 @@ namespace skyline::signal {
void ExceptionalSignalHandler(int signal, siginfo *info, ucontext *context) {
SignalException signalException;
signalException.signal = signal;
signalException.pc = context->uc_mcontext.pc;
signalException.pc = reinterpret_cast<void *>(context->uc_mcontext.pc);
if (signal == SIGSEGV)
signalException.fault = info->si_addr;
SignalExceptionPtr = std::make_exception_ptr(signalException);

View File

@ -14,14 +14,14 @@ namespace skyline::signal {
class SignalException {
public:
int signal{};
u64 pc{};
void* pc{};
void *fault{};
inline std::string what() const {
if (!fault)
return fmt::format("Signal: {} (PC: 0x{:X})", strsignal(signal), pc);
return fmt::format("Signal: {} (PC: 0x{:X})", strsignal(signal), reinterpret_cast<uintptr_t>(pc));
else
return fmt::format("Signal: {} @ 0x{:X} (PC: 0x{:X})", strsignal(signal), reinterpret_cast<uintptr_t>(fault), pc);
return fmt::format("Signal: {} @ 0x{:X} (PC: 0x{:X})", strsignal(signal), reinterpret_cast<uintptr_t>(fault), reinterpret_cast<uintptr_t>(pc));
}
};

View File

@ -94,7 +94,7 @@ namespace skyline::kernel::ipc {
payloadOffset = cmdArg;
if (payload->magic != util::MakeMagic<u32>("SFCI") && (header->type != CommandType::Control && header->type != CommandType::ControlWithContext)) // SFCI is the magic in received IPC messages
if (payload->magic != util::MakeMagic<u32>("SFCI") && (header->type != CommandType::Control && header->type != CommandType::ControlWithContext && header->type != CommandType::Close) && (!domain || domain->command != DomainCommand::CloseVHandle)) // SFCI is the magic in received IPC messages
state.logger->Debug("Unexpected Magic in PayloadHeader: 0x{:X}", static_cast<u32>(payload->magic));
pointer += constant::IpcPaddingSum - padding + cBufferLengthSize;

View File

@ -7,12 +7,17 @@
namespace skyline {
namespace memory {
struct Permission {
union Permission {
/**
* @brief Initializes all permissions to false
*/
constexpr Permission() : r(), w(), x() {}
/**
* @brief Initializes permissions where the first three bits correspond to RWX
*/
constexpr explicit Permission(u8 raw) : raw(raw) {}
/**
* @param read If memory has read permission
* @param write If memory has write permission
@ -38,10 +43,14 @@ namespace skyline {
return perm;
}
bool r; //!< The permission to read
bool w; //!< The permission to write
bool x; //!< The permission to execute
struct {
bool r : 1; //!< The permission to read
bool w : 1; //!< The permission to write
bool x : 1; //!< The permission to execute
};
u8 raw;
};
static_assert(sizeof(Permission) == sizeof(u8));
/**
* @url https://switchbrew.org/wiki/SVC#MemoryAttribute

View File

@ -419,7 +419,7 @@ namespace skyline::kernel::svc {
return;
}
auto permission{*reinterpret_cast<memory::Permission *>(&state.ctx->gpr.w3)};
memory::Permission permission(state.ctx->gpr.w3);
if ((permission.w && !permission.r) || (permission.x && !permission.r)) {
state.logger->Warn("svcMapSharedMemory: 'permission' invalid: {}{}{}", permission.r ? 'R' : '-', permission.w ? 'W' : '-', permission.x ? 'X' : '-');
state.ctx->gpr.w0 = result::InvalidNewMemoryPermission;
@ -452,7 +452,7 @@ namespace skyline::kernel::svc {
return;
}
auto permission{*reinterpret_cast<memory::Permission *>(&state.ctx->gpr.w3)};
memory::Permission permission(state.ctx->gpr.w3);
if ((permission.w && !permission.r) || (permission.x && !permission.r)) {
state.logger->Warn("svcCreateTransferMemory: 'permission' invalid: {}{}{}", permission.r ? 'R' : '-', permission.w ? 'W' : '-', permission.x ? 'X' : '-');
state.ctx->gpr.w0 = result::InvalidNewMemoryPermission;

View File

@ -62,7 +62,7 @@ namespace skyline::kernel::type {
"MOV LR, %x2\n\t" // Store entry in Link Register so it is jumped to on return
"MOV X0, %x3\n\t" // Store the argument in X0
"MOV X1, %x4\n\t" // Store the thread handle in X1, NCA applications require this
"MOV X2, XZR\n\t"
"MOV X2, XZR\n\t" // Zero out other GP and SIMD registers, not doing this will break applications
"MOV X3, XZR\n\t"
"MOV X4, XZR\n\t"
"MOV X5, XZR\n\t"

View File

@ -27,7 +27,7 @@ namespace skyline::loader {
u8 *base{loadInfo.base};
void *entry{loadInfo.entry};
state.logger->Info("Loaded nso 'rtld' at 0x{:X} (.text @ 0x{:X})", base, entry);
state.logger->Info("Loaded 'rtld.nso' at 0x{:X} (.text @ 0x{:X})", base, entry);
for (const auto &nso : {"main", "subsdk0", "subsdk1", "subsdk2", "subsdk3", "subsdk4", "subsdk5", "subsdk6", "subsdk7", "sdk"}) {
if (exeFs->FileExists(nso))

View File

@ -45,8 +45,9 @@ namespace skyline::nce {
}
}
void NCE::SignalHandler(int signal, siginfo *info, ucontext *context, void **tls) {
void NCE::SignalHandler(int signal, siginfo *info, ucontext *ctx, void **tls) {
if (*tls) {
auto &mctx{ctx->uc_mcontext};
const auto &state{*reinterpret_cast<ThreadContext *>(*tls)->state};
if (signal != SIGINT) {
state.logger->Warn("Thread #{} has crashed due to signal: {}", state.thread->id, strsignal(signal));
@ -55,15 +56,14 @@ namespace skyline::nce {
std::string trace;
std::string cpuContext;
const auto &ctx{reinterpret_cast<ucontext *>(context)->uc_mcontext};
constexpr u16 instructionCount{20}; // The amount of previous instructions to print
auto offset{ctx.pc - (instructionCount * sizeof(u32)) + (2 * sizeof(u32))};
auto offset{mctx.pc - (instructionCount * sizeof(u32)) + (2 * sizeof(u32))};
span instructions(reinterpret_cast<u32 *>(offset), instructionCount);
if (mprotect(util::AlignDown(instructions.data(), PAGE_SIZE), util::AlignUp(instructions.size_bytes(), PAGE_SIZE), PROT_READ | PROT_WRITE | PROT_EXEC) == 0) {
for (auto &instruction : instructions) {
instruction = __builtin_bswap32(instruction);
if (offset == ctx.pc)
if (offset == mctx.pc)
trace += fmt::format("\n-> 0x{:X} : 0x{:08X}", offset, instruction);
else
trace += fmt::format("\n 0x{:X} : 0x{:08X}", offset, instruction);
@ -75,28 +75,28 @@ namespace skyline::nce {
state.logger->Debug("Process Trace:{}", trace);
state.logger->Debug("Raw Instructions: 0x{}", raw);
} else {
cpuContext += fmt::format("\nPC: 0x{:X} ('mprotect' failed with '{}')", ctx.pc, strerror(errno));
cpuContext += fmt::format("\nPC: 0x{:X} ('mprotect' failed with '{}')", mctx.pc, strerror(errno));
}
if (ctx.fault_address)
cpuContext += fmt::format("\nFault Address: 0x{:X}", ctx.fault_address);
if (mctx.fault_address)
cpuContext += fmt::format("\nFault Address: 0x{:X}", mctx.fault_address);
if (ctx.sp)
cpuContext += fmt::format("\nStack Pointer: 0x{:X}", ctx.sp);
if (mctx.sp)
cpuContext += fmt::format("\nStack Pointer: 0x{:X}", mctx.sp);
for (u8 index{}; index < ((sizeof(mcontext_t::regs) / sizeof(u64)) - 2); index += 2)
cpuContext += fmt::format("\n{}X{}: 0x{:<16X} {}{}: 0x{:X}", index < 10 ? ' ' : '\0', index, ctx.regs[index], index < 10 ? 'X' : '\0', index + 1, ctx.regs[index]);
cpuContext += fmt::format("\n{}X{}: 0x{:<16X} {}{}: 0x{:X}", index < 10 ? ' ' : '\0', index, mctx.regs[index], index < 10 ? 'X' : '\0', index + 1, mctx.regs[index]);
state.logger->Debug("CPU Context:{}", cpuContext);
}
context->uc_mcontext.pc = reinterpret_cast<skyline::u64>(&std::longjmp);
context->uc_mcontext.regs[0] = reinterpret_cast<u64>(state.thread->originalCtx);
context->uc_mcontext.regs[1] = true;
mctx.pc = reinterpret_cast<skyline::u64>(&std::longjmp);
mctx.regs[0] = reinterpret_cast<u64>(state.thread->originalCtx);
mctx.regs[1] = true;
*tls = nullptr;
} else {
signal::ExceptionalSignalHandler(signal, info, context); //!< Delegate throwing a host exception to the exceptional signal handler
signal::ExceptionalSignalHandler(signal, info, ctx); //!< Delegate throwing a host exception to the exceptional signal handler
}
}
@ -131,16 +131,16 @@ namespace skyline::nce {
auto start{reinterpret_cast<const u32 *>(text.data())}, end{reinterpret_cast<const u32 *>(text.data() + text.size())};
for (const u32 *instruction{start}; instruction < end; instruction++) {
auto svc{*reinterpret_cast<const instr::Svc *>(instruction)};
auto mrs{*reinterpret_cast<const instr::Mrs *>(instruction)};
auto msr{*reinterpret_cast<const instr::Msr *>(instruction)};
auto svc{*reinterpret_cast<const instructions::Svc *>(instruction)};
auto mrs{*reinterpret_cast<const instructions::Mrs *>(instruction)};
auto msr{*reinterpret_cast<const instructions::Msr *>(instruction)};
if (svc.Verify()) {
size += 7;
offsets.push_back(instruction - start);
} else if (mrs.Verify()) {
if (mrs.srcReg == TpidrroEl0 || mrs.srcReg == TpidrEl0) {
size += ((mrs.destReg != regs::X0) ? 6 : 3);
size += ((mrs.destReg != registers::X0) ? 6 : 3);
offsets.push_back(instruction - start);
} else {
if (rescaleClock) {
@ -189,7 +189,7 @@ namespace skyline::nce {
*patch++ = 0xA9BF0BE1; // STP X1, X2, [SP, #-16]!
/* Jump to SvcHandler */
for (const auto &mov : instr::MoveRegister(regs::X2, reinterpret_cast<u64>(&NCE::SvcHandler)))
for (const auto &mov : instructions::MoveRegister(registers::X2, reinterpret_cast<u64>(&NCE::SvcHandler)))
if (mov)
*patch++ = mov;
*patch++ = 0xD63F0040; // BLR X2
@ -213,39 +213,39 @@ namespace skyline::nce {
for (auto offset : offsets) {
u32 *instruction{reinterpret_cast<u32 *>(text.data()) + offset};
auto svc{*reinterpret_cast<instr::Svc *>(instruction)};
auto mrs{*reinterpret_cast<instr::Mrs *>(instruction)};
auto msr{*reinterpret_cast<instr::Msr *>(instruction)};
auto svc{*reinterpret_cast<instructions::Svc *>(instruction)};
auto mrs{*reinterpret_cast<instructions::Mrs *>(instruction)};
auto msr{*reinterpret_cast<instructions::Msr *>(instruction)};
if (svc.Verify()) {
/* Per-SVC Trampoline */
/* Rewrite SVC with B to trampoline */
*instruction = instr::B((end - patch) + offset, true).raw;
*instruction = instructions::B((end - patch) + offset, true).raw;
/* Save Context */
*patch++ = 0xF81F0FFE; // STR LR, [SP, #-16]!
*patch = instr::BL(start - patch).raw;
*patch = instructions::BL(start - patch).raw;
patch++;
/* Jump to main SVC trampoline */
*patch++ = instr::Movz(regs::W0, static_cast<u16>(svc.value)).raw;
*patch = instr::BL((start - patch) + guest::SaveCtxSize).raw;
*patch++ = instructions::Movz(registers::W0, static_cast<u16>(svc.value)).raw;
*patch = instructions::BL((start - patch) + guest::SaveCtxSize).raw;
patch++;
/* Restore Context and Return */
*patch = instr::BL((start - patch) + guest::SaveCtxSize + MainSvcTrampolineSize).raw;
*patch = instructions::BL((start - patch) + guest::SaveCtxSize + MainSvcTrampolineSize).raw;
patch++;
*patch++ = 0xF84107FE; // LDR LR, [SP], #16
*patch = instr::B((end - patch) + offset + 1).raw;
*patch = instructions::B((end - patch) + offset + 1).raw;
patch++;
} else if (mrs.Verify()) {
if (mrs.srcReg == TpidrroEl0 || mrs.srcReg == TpidrEl0) {
/* Emulated TLS Register Load */
/* Rewrite MRS with B to trampoline */
*instruction = instr::B((end - patch) + offset, true).raw;
*instruction = instructions::B((end - patch) + offset, true).raw;
/* Allocate Scratch Register */
if (mrs.destReg != regs::X0)
if (mrs.destReg != registers::X0)
*patch++ = 0xF81F0FE0; // STR X0, [SP, #-16]!
/* Retrieve emulated TLS register from ThreadContext */
@ -256,66 +256,66 @@ namespace skyline::nce {
*patch++ = 0xF9415C00; // LDR X0, [X0, #0x2B8] (ThreadContext::tpidrEl0)
/* Restore Scratch Register and Return */
if (mrs.destReg != regs::X0) {
*patch++ = instr::Mov(regs::X(mrs.destReg), regs::X0).raw;
if (mrs.destReg != registers::X0) {
*patch++ = instructions::Mov(registers::X(mrs.destReg), registers::X0).raw;
*patch++ = 0xF84107E0; // LDR X0, [SP], #16
}
*patch = instr::B((end - patch) + offset + 1).raw;
*patch = instructions::B((end - patch) + offset + 1).raw;
patch++;
} else {
if (rescaleClock) {
if (mrs.srcReg == CntpctEl0) {
/* Physical Counter Load Emulation (With Rescaling) */
/* Rewrite MRS with B to trampoline */
*instruction = instr::B((end - patch) + offset, true).raw;
*instruction = instructions::B((end - patch) + offset, true).raw;
/* Rescale host clock */
std::memcpy(patch, reinterpret_cast<void *>(&guest::RescaleClock), guest::RescaleClockSize * sizeof(u32));
patch += guest::RescaleClockSize;
/* Load result from stack into destination register */
instr::Ldr ldr(0xF94003E0); // LDR XOUT, [SP]
instructions::Ldr ldr(0xF94003E0); // LDR XOUT, [SP]
ldr.destReg = mrs.destReg;
*patch++ = ldr.raw;
/* Free 32B stack allocation by RescaleClock and Return */
*patch++ = {0x910083FF}; // ADD SP, SP, #32
*patch = instr::B((end - patch) + offset + 1).raw;
*patch = instructions::B((end - patch) + offset + 1).raw;
patch++;
} else if (mrs.srcReg == CntfrqEl0) {
/* Physical Counter Frequency Load Emulation */
/* Rewrite MRS with B to trampoline */
*instruction = instr::B((end - patch) + offset, true).raw;
*instruction = instructions::B((end - patch) + offset, true).raw;
/* Write back Tegra X1 Counter Frequency and Return */
for (const auto &mov : instr::MoveRegister(regs::X(mrs.destReg), TegraX1Freq))
for (const auto &mov : instructions::MoveRegister(registers::X(mrs.destReg), TegraX1Freq))
*patch++ = mov;
*patch = instr::B((end - patch) + offset + 1).raw;
*patch = instructions::B((end - patch) + offset + 1).raw;
patch++;
}
} else if (mrs.srcReg == CntpctEl0) {
/* Physical Counter Load Emulation (Without Rescaling) */
// We just convert CNTPCT_EL0 -> CNTVCT_EL0 as Linux doesn't allow access to the physical counter
*instruction = instr::Mrs(CntvctEl0, regs::X(mrs.destReg)).raw;
*instruction = instructions::Mrs(CntvctEl0, registers::X(mrs.destReg)).raw;
}
}
} else if (msr.Verify() && msr.destReg == TpidrEl0) {
/* Emulated TLS Register Store */
/* Rewrite MSR with B to trampoline */
*instruction = instr::B((end - patch) + offset, true).raw;
*instruction = instructions::B((end - patch) + offset, true).raw;
/* Allocate Scratch Registers */
bool x0x1{mrs.srcReg != regs::X0 && mrs.srcReg != regs::X1};
bool x0x1{mrs.srcReg != registers::X0 && mrs.srcReg != registers::X1};
*patch++ = x0x1 ? 0xA9BF07E0 : 0xA9BF0FE2; // STP X(0/2), X(1/3), [SP, #-16]!
/* Store new TLS value into ThreadContext */
*patch++ = x0x1 ? 0xD53BD040 : 0xD53BD042; // MRS X(0/2), TPIDR_EL0
*patch++ = instr::Mov(x0x1 ? regs::X1 : regs::X3, regs::X(msr.srcReg)).raw;
*patch++ = instructions::Mov(x0x1 ? registers::X1 : registers::X3, registers::X(msr.srcReg)).raw;
*patch++ = x0x1 ? 0xF9015C01 : 0xF9015C03; // STR X(1/3), [X0, #0x4B8] (ThreadContext::tpidrEl0)
/* Restore Scratch Registers and Return */
*patch++ = x0x1 ? 0xA8C107E0 : 0xA8C10FE2; // LDP X(0/2), X(1/3), [SP], #16
*patch = instr::B((end - patch) + offset + 1).raw;
*patch = instructions::B((end - patch) + offset + 1).raw;
patch++;
}
}

View File

@ -17,7 +17,7 @@ namespace skyline::nce {
static void SvcHandler(u16 svc, ThreadContext *ctx);
public:
static void SignalHandler(int signal, siginfo *info, ucontext *context, void **tls);
static void SignalHandler(int signal, siginfo *info, ucontext *ctx, void **tls);
NCE(const DeviceState &state);

View File

@ -4,12 +4,15 @@
#include <common.h>
namespace skyline::nce {
namespace regs {
enum X { X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30 };
enum W { W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16, W17, W18, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, W30 };
/**
* @note We use unscoped enumerations to leak all register enumerations into the registers namespace
*/
namespace registers {
enum X : u8 { X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19, X20, X21, X22, X23, X24, X25, X26, X27, X28, X29, X30 };
enum W : u8 { W0, W1, W2, W3, W4, W5, W6, W7, W8, W9, W10, W11, W12, W13, W14, W15, W16, W17, W18, W19, W20, W21, W22, W23, W24, W25, W26, W27, W28, W29, W30 };
}
namespace instr {
namespace instructions {
/**
* @url https://developer.arm.com/docs/ddi0596/latest/base-instructions-alphabetic-order/brk-breakpoint-instruction
*/
@ -66,7 +69,7 @@ namespace skyline::nce {
* @param srcReg The source system register
* @param dstReg The destination Xn register
*/
constexpr Mrs(u32 srcReg, regs::X dstReg) {
constexpr Mrs(u32 srcReg, registers::X dstReg) {
this->srcReg = srcReg;
this->destReg = dstReg;
sig = 0xD53;
@ -184,7 +187,7 @@ namespace skyline::nce {
* @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at
*/
constexpr Movz(regs::X destReg, u16 imm16, u8 shift = 0) {
constexpr Movz(registers::X destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = shift;
@ -197,7 +200,7 @@ namespace skyline::nce {
* @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at
*/
constexpr Movz(regs::W destReg, u16 imm16, u8 shift = 0) {
constexpr Movz(registers::W destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = shift;
@ -239,7 +242,7 @@ namespace skyline::nce {
* @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at
*/
constexpr Movk(regs::X destReg, u16 imm16, u8 shift = 0) {
constexpr Movk(registers::X destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = shift;
@ -252,7 +255,7 @@ namespace skyline::nce {
* @param imm16 The 16-bit value to store
* @param shift The offset (in units of 16-bits) in the register to store the value at
*/
constexpr Movk(regs::W destReg, u16 imm16, u8 shift = 0) {
constexpr Movk(registers::W destReg, u16 imm16, u8 shift = 0) {
this->destReg = static_cast<u8>(destReg);
this->imm16 = imm16;
hw = shift;
@ -291,7 +294,7 @@ namespace skyline::nce {
* @note 0 is returned for any instruction that isn't required
*/
template<typename Type>
constexpr std::array<u32, sizeof(Type) / sizeof(u16)> MoveRegister(regs::X destination, Type value) {
constexpr std::array<u32, sizeof(Type) / sizeof(u16)> MoveRegister(registers::X destination, Type value) {
std::array<u32, sizeof(Type) / sizeof(u16)> instructions;
auto valuePointer{reinterpret_cast<u16 *>(&value)};
@ -302,9 +305,9 @@ namespace skyline::nce {
auto offsetValue{*(valuePointer + offset)};
if (offsetValue) {
if (zeroed) {
instruction = instr::Movk(destination, offsetValue, offset).raw;
instruction = instructions::Movk(destination, offsetValue, offset).raw;
} else {
instruction = instr::Movz(destination, offsetValue, offset).raw;
instruction = instructions::Movz(destination, offsetValue, offset).raw;
zeroed = true;
}
} else {
@ -326,7 +329,7 @@ namespace skyline::nce {
* @param destReg The destination Xn register to store the value in
* @param srcReg The source Xn register to retrieve the value from
*/
constexpr Mov(regs::X destReg, regs::X srcReg) {
constexpr Mov(registers::X destReg, registers::X srcReg) {
this->destReg = static_cast<u8>(destReg);
sig0 = 0x1F;
imm = 0;
@ -340,7 +343,7 @@ namespace skyline::nce {
* @param destReg The destination Wn register to store the value in
* @param srcReg The source Wn register to retrieve the value from
*/
constexpr Mov(regs::W destReg, regs::W srcReg) {
constexpr Mov(registers::W destReg, registers::W srcReg) {
this->destReg = static_cast<u8>(destReg);
sig0 = 0x1F;
imm = 0;

View File

@ -18,16 +18,20 @@ namespace skyline::kernel {
auto romFile{std::make_shared<vfs::OsBacking>(romFd)};
auto keyStore{std::make_shared<crypto::KeyStore>(appFilesPath)};
if (romType == loader::RomFormat::NRO)
state.loader = std::make_shared<loader::NroLoader>(romFile);
else if (romType == loader::RomFormat::NSO)
state.loader = std::make_shared<loader::NsoLoader>(romFile);
else if (romType == loader::RomFormat::NCA)
state.loader = std::make_shared<loader::NcaLoader>(romFile, keyStore);
else if (romType == loader::RomFormat::NSP)
state.loader = std::make_shared<loader::NspLoader>(romFile, keyStore);
else
state.loader = [=]() -> std::shared_ptr<loader::Loader> {
switch (romType) {
case loader::RomFormat::NRO:
return std::make_shared<loader::NroLoader>(romFile);
case loader::RomFormat::NSO:
return std::make_shared<loader::NsoLoader>(romFile);
case loader::RomFormat::NCA:
return std::make_shared<loader::NcaLoader>(romFile, keyStore);
case loader::RomFormat::NSP:
return std::make_shared<loader::NspLoader>(romFile, keyStore);
default:
throw exception("Unsupported ROM extension.");
}
}();
auto &process{state.process};
process = std::make_shared<kernel::type::KProcess>(state);

View File

@ -47,7 +47,7 @@ namespace skyline::vfs {
/**
* @brief Implicit casting for reading into spans of different types
*/
template<class T, typename std::enable_if<!std::is_same_v<T, u8>, bool>::type = true>
template<typename T, typename std::enable_if<!std::is_same_v<T, u8>, bool>::type = true>
inline size_t Read(span <T> output, size_t offset = 0) {
return Read(output.template cast<u8>(), offset);
}

View File

@ -18,7 +18,7 @@ namespace skyline {
u32 offset;
u32 size;
template<class T>
template<typename T>
inline T Read(const std::shared_ptr<vfs::Backing> &backing, size_t baseOffset = 0) {
if (sizeof(T) > size)
throw exception("Section size ({}) smaller than Read type size ({})", size, sizeof(T));