diff --git a/app/src/main/cpp/skyline/common.h b/app/src/main/cpp/skyline/common.h index a3640fa2..ac5643cc 100644 --- a/app/src/main/cpp/skyline/common.h +++ b/app/src/main/cpp/skyline/common.h @@ -68,9 +68,6 @@ namespace skyline { }; namespace constant { - // Memory - constexpr u64 BaseAddress{0x8000000}; //!< The address space base - constexpr u64 DefaultStackSize{0x1E8480}; //!< The default amount of stack: 2 MB // Display constexpr u16 HandheldResolutionW{1280}; //!< The width component of the handheld resolution constexpr u16 HandheldResolutionH{720}; //!< The height component of the handheld resolution @@ -140,12 +137,12 @@ namespace skyline { template T PointerValue(T item) { return item; - }; + } template size_t PointerValue(T *item) { return reinterpret_cast(item); - }; + } /** * @return The value aligned up to the next multiple @@ -210,7 +207,7 @@ namespace skyline { return object; } - constexpr u8 HexDigitToByte(char digit) { + constexpr u8 HexDigitToNibble(char digit) { if (digit >= '0' && digit <= '9') return digit - '0'; else if (digit >= 'a' && digit <= 'f') @@ -221,17 +218,35 @@ namespace skyline { } template - constexpr std::array HexStringToArray(std::string_view hexString) { - if (hexString.size() != Size * 2) + constexpr std::array HexStringToArray(std::string_view string) { + if (string.size() != Size * 2) throw exception("Invalid size"); std::array result; for (size_t i{}; i < Size; i++) { - size_t hexStrIndex{i * 2}; - result[i] = (HexDigitToByte(hexString[hexStrIndex]) << 4) | HexDigitToByte(hexString[hexStrIndex + 1]); + size_t index{i * 2}; + result[i] = (HexDigitToNibble(string[index]) << 4) | HexDigitToNibble(string[index + 1]); } return result; } + template + constexpr Type HexStringToInt(std::string_view string) { + Type result{}; + size_t offset{(sizeof(Type) * 8) - 4}; + for (size_t index{}; index < std::min(sizeof(Type) * 2, string.size()); index++, offset -= 4) { + char digit{string[index]}; + if (digit >= '0' && digit <= '9') + result |= static_cast(digit - '0') << offset; + else if (digit >= 'a' && digit <= 'f') + result |= static_cast(digit - 'a' + 10) << offset; + else if (digit >= 'A' && digit <= 'F') + result |= static_cast(digit - 'A' + 10) << offset; + else + break; + } + return result >> (offset + 4); + } + /** * @brief A compile-time hash function as std::hash isn't constexpr */ diff --git a/app/src/main/cpp/skyline/kernel/memory.cpp b/app/src/main/cpp/skyline/kernel/memory.cpp index 66e0b9be..103fe711 100644 --- a/app/src/main/cpp/skyline/kernel/memory.cpp +++ b/app/src/main/cpp/skyline/kernel/memory.cpp @@ -15,16 +15,14 @@ namespace skyline::kernel { case memory::AddressSpaceType::AddressSpace36Bit: { addressSpace.address = 0; addressSpace.size = 1UL << 36; - base.address = constant::BaseAddress; - base.size = 0xFF8000000; + base.size = 0x78000000 + 0x180000000 + 0x180000000 + 0x180000000; break; } case memory::AddressSpaceType::AddressSpace39Bit: { addressSpace.address = 0; addressSpace.size = 1UL << 39; - base.address = constant::BaseAddress; - base.size = 0x7FF8000000; + base.size = 0x78000000 + 0x1000000000 + 0x180000000 + 0x80000000 + 0x1000000000; break; } @@ -32,6 +30,27 @@ namespace skyline::kernel { throw exception("VMM initialization with unknown address space"); } + std::ifstream mapsFile("/proc/self/maps"); + std::string maps((std::istreambuf_iterator(mapsFile)), std::istreambuf_iterator()); + size_t line{}, start{}, alignedStart{}; + do { + auto end{util::HexStringToInt(std::string_view(maps.data() + line, sizeof(u64) * 2))}; + if (end - start > base.size + (alignedStart - start)) { // We don't want to overflow if alignedStart > start + base.address = alignedStart; + break; + } + + start = util::HexStringToInt(std::string_view(maps.data() + maps.find_first_of('-', line) + 1, sizeof(u64) * 2)); + alignedStart = util::AlignUp(start, 1ULL << 21); + if (alignedStart + base.size > addressSpace.size) + break; + } while ((line = maps.find_first_of('\n', line)) != std::string::npos && line++); + + if (!base.address) + throw exception("Cannot find a suitable carveout for the guest address space"); + + mmap(reinterpret_cast(base.address), base.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); + chunks = {ChunkDescriptor{ .ptr = reinterpret_cast(addressSpace.address), .size = addressSpace.size, @@ -50,7 +69,7 @@ namespace skyline::kernel { alias.address = code.address + code.size; alias.size = 0x180000000; stack.address = alias.address; - stack.size = alias.size; + stack.size = 0x180000000; heap.address = alias.address + alias.size; heap.size = 0x180000000; tlsIo.address = code.address; @@ -59,8 +78,8 @@ namespace skyline::kernel { } case 1UL << 39: { - code.address = util::AlignDown(address, 0x200000); - code.size = util::AlignUp(address + size, 0x200000) - code.address; + code.address = base.address; + code.size = 0x78000000; alias.address = code.address + code.size; alias.size = 0x1000000000; heap.address = alias.address + alias.size; @@ -76,7 +95,10 @@ namespace skyline::kernel { throw exception("Regions initialized without VMM initialization"); } - state.logger->Debug("Region Map:\nCode Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nAlias Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nHeap Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nStack Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nTLS/IO Region: 0x{:X} - 0x{:X} (Size: 0x{:X})", code.address, code.address + code.size, code.size, alias.address, alias.address + alias.size, alias.size, heap.address, heap + if (size > code.size) + throw exception("Code region ({}) is smaller than mapped code size ({})", code.size, size); + + state.logger->Debug("Region Map:\nVMM Base: 0x{:X}\nCode Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nAlias Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nHeap Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nStack Region: 0x{:X} - 0x{:X} (Size: 0x{:X})\nTLS/IO Region: 0x{:X} - 0x{:X} (Size: 0x{:X})", base.address, code.address, code.address + code.size, code.size, alias.address, alias.address + alias.size, alias.size, heap.address, heap .address + heap.size, heap.size, stack.address, stack.address + stack.size, stack.size, tlsIo.address, tlsIo.address + tlsIo.size, tlsIo.size); } diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index c8cc4232..6fcd827a 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -674,15 +674,15 @@ namespace skyline::kernel::svc { break; case constant::infoState::TotalMemoryUsage: - out = state.process->heap->size + constant::DefaultStackSize + state.process->memory.GetProgramSize(); + out = state.process->heap->size + state.thread->stack->size + state.process->memory.GetProgramSize(); break; case constant::infoState::AddressSpaceBaseAddr: - out = state.process->memory.base.address; + out = state.process->memory.addressSpace.address; break; case constant::infoState::AddressSpaceSize: - out = state.process->memory.base.size; + out = state.process->memory.addressSpace.size; break; case constant::infoState::StackRegionBaseAddr: @@ -698,7 +698,7 @@ namespace skyline::kernel::svc { break; case constant::infoState::PersonalMmHeapUsage: - out = state.process->heap->size + constant::DefaultStackSize; + out = state.process->heap->size + state.thread->stack->size; break; case constant::infoState::TotalMemoryAvailableWithoutMmHeap: @@ -706,7 +706,7 @@ namespace skyline::kernel::svc { break; case constant::infoState::TotalMemoryUsedWithoutMmHeap: - out = state.process->heap->size + constant::DefaultStackSize; // TODO: Same as above + out = state.process->heap->size + state.thread->stack->size; // TODO: Same as above break; case constant::infoState::UserExceptionContextAddr: diff --git a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp index b3a89687..3ed9f503 100644 --- a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp @@ -8,16 +8,17 @@ #include "KProcess.h" namespace skyline::kernel::type { - KPrivateMemory::KPrivateMemory(const DeviceState &state, u8* ptr, size_t size, memory::Permission permission, memory::MemoryState memState) : size(size), permission(permission), memState(memState), KMemory(state, KType::KPrivateMemory) { - if (ptr && !util::PageAligned(ptr)) + KPrivateMemory::KPrivateMemory(const DeviceState &state, u8* ptr, size_t size, memory::Permission permission, memory::MemoryState memState) : ptr(ptr), size(size), permission(permission), memState(memState), KMemory(state, KType::KPrivateMemory) { + if (!state.process->memory.base.IsInside(ptr) || !state.process->memory.base.IsInside(ptr + size)) + throw exception("KPrivateMemory allocation isn't inside guest address space: 0x{:X} - 0x{:X}", ptr, ptr + size); + if (!util::PageAligned(ptr)) throw exception("KPrivateMemory was created with non-page-aligned address: 0x{:X}", ptr); - this->ptr = reinterpret_cast(mmap(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, (ptr ? MAP_FIXED : 0) | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0)); - if (this->ptr == MAP_FAILED) + if (mprotect(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) // We only need to reprotect as the allocation has already been reserved by the MemoryManager throw exception("An occurred while mapping private memory: {} with 0x{:X} @ 0x{:X}", strerror(errno), ptr, size); state.process->memory.InsertChunk(ChunkDescriptor{ - .ptr = this->ptr, + .ptr = ptr, .size = size, .permission = permission, .state = memState, @@ -25,8 +26,7 @@ namespace skyline::kernel::type { } void KPrivateMemory::Resize(size_t nSize) { - ptr = reinterpret_cast(mremap(ptr, size, nSize, 0)); - if (ptr == MAP_FAILED) + if (mprotect(ptr, nSize, PROT_READ | PROT_WRITE | PROT_EXEC) < 0) throw exception("An occurred while resizing private memory: {}", strerror(errno)); if (nSize < size) { @@ -48,6 +48,9 @@ namespace skyline::kernel::type { } void KPrivateMemory::UpdatePermission(u8* ptr, size_t size, memory::Permission permission) { + ptr = std::clamp(ptr, this->ptr, this->ptr + this->size); + size = std::min(size, static_cast((this->ptr + this->size) - ptr)); + if (ptr && !util::PageAligned(ptr)) throw exception("KPrivateMemory permission updated with a non-page-aligned address: 0x{:X}", ptr); @@ -64,7 +67,7 @@ namespace skyline::kernel::type { } KPrivateMemory::~KPrivateMemory() { - munmap(ptr, size); + mprotect(ptr, size, PROT_NONE); state.process->memory.InsertChunk(ChunkDescriptor{ .ptr = ptr, .size = size, diff --git a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h index b5136fd4..b8295098 100644 --- a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h +++ b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.h @@ -17,8 +17,8 @@ namespace skyline::kernel::type { memory::MemoryState memState; /** - * @param ptr The address to map to (If NULL then an arbitrary address is picked) * @param permission The permissions for the allocated memory (As reported to the application, host memory permissions aren't reflected by this) + * @note 'ptr' needs to be in guest-reserved address space */ KPrivateMemory(const DeviceState &state, u8* ptr, size_t size, memory::Permission permission, memory::MemoryState memState); diff --git a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp index 12755c71..24abd938 100644 --- a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp @@ -13,7 +13,7 @@ namespace skyline::kernel::type { if (fd < 0) throw exception("An error occurred while creating shared memory: {}", fd); - kernel.ptr = reinterpret_cast(mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd, 0)); + kernel.ptr = reinterpret_cast(mmap(nullptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED, fd, 0)); if (kernel.ptr == MAP_FAILED) throw exception("An occurred while mapping shared memory: {}", strerror(errno)); @@ -21,10 +21,12 @@ namespace skyline::kernel::type { } u8 *KSharedMemory::Map(u8 *ptr, u64 size, memory::Permission permission) { + if (!state.process->memory.base.IsInside(ptr) || !state.process->memory.base.IsInside(ptr + size)) + throw exception("KPrivateMemory allocation isn't inside guest address space: 0x{:X} - 0x{:X}", ptr, ptr + size); if (ptr && !util::PageAligned(ptr)) throw exception("KSharedMemory was mapped to a non-page-aligned address: 0x{:X}", ptr); - guest.ptr = reinterpret_cast(mmap(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | (ptr ? MAP_FIXED_NOREPLACE : 0), fd, 0)); + guest.ptr = reinterpret_cast(mmap(ptr, size, PROT_READ | PROT_WRITE | PROT_EXEC, MAP_SHARED | (ptr ? MAP_FIXED_NOREPLACE : 0), fd, 0)); if (guest.ptr == MAP_FAILED) throw exception("An error occurred while mapping shared memory in guest"); guest.size = size; @@ -39,7 +41,7 @@ namespace skyline::kernel::type { return guest.ptr; } - void KSharedMemory::UpdatePermission(u8* ptr, size_t size, memory::Permission permission) { + void KSharedMemory::UpdatePermission(u8 *ptr, size_t size, memory::Permission permission) { if (ptr && !util::PageAligned(ptr)) throw exception("KSharedMemory permission updated with a non-page-aligned address: 0x{:X}", ptr); @@ -63,7 +65,7 @@ namespace skyline::kernel::type { munmap(kernel.ptr, kernel.size); if (guest.Valid()) { - munmap(guest.ptr, guest.size); + mmap(guest.ptr, guest.size, PROT_NONE, MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); state.process->memory.InsertChunk(ChunkDescriptor{ .ptr = guest.ptr, .size = guest.size, diff --git a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h index b571a5d2..6327b620 100644 --- a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h +++ b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.h @@ -27,8 +27,7 @@ namespace skyline::kernel::type { KSharedMemory(const DeviceState &state, size_t size, memory::MemoryState memState = memory::states::SharedMemory, KType type = KType::KSharedMemory); /** - * @param ptr The address to map to (If NULL an arbitrary address is picked, it may be outside of the HOS address space) - * @return The address of the allocation + * @note 'ptr' needs to be in guest-reserved address space */ u8 *Map(u8 *ptr, u64 size, memory::Permission permission); diff --git a/app/src/main/cpp/skyline/kernel/types/KThread.cpp b/app/src/main/cpp/skyline/kernel/types/KThread.cpp index 96c96441..a90be954 100644 --- a/app/src/main/cpp/skyline/kernel/types/KThread.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KThread.cpp @@ -123,7 +123,8 @@ namespace skyline::kernel::type { state.logger->Debug("Starting thread #{}", id); if (!stack) { - stack = stack.make_shared(state, reinterpret_cast(state.process->memory.stack.address), constant::DefaultStackSize, memory::Permission{true, true, false}, memory::states::Stack); + constexpr u64 DefaultStackSize{0x1E8480}; //!< The default amount of stack: 2 MB + stack = stack.make_shared(state, reinterpret_cast(state.process->memory.stack.address), DefaultStackSize, memory::Permission{true, true, false}, memory::states::Stack); if (mprotect(stack->ptr, PAGE_SIZE, PROT_NONE)) throw exception("Failed to create guard page for thread stack at 0x{:X}", stack->ptr); } diff --git a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h index 30c94da1..1ad2614d 100644 --- a/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h +++ b/app/src/main/cpp/skyline/kernel/types/KTransferMemory.h @@ -11,6 +11,9 @@ namespace skyline::kernel::type { */ class KTransferMemory : public KSharedMemory { public: + /** + * @note 'ptr' needs to be in guest-reserved address space + */ KTransferMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState = memory::states::TransferMemory) : KSharedMemory(state, size, memState, KType::KTransferMemory) { std::memcpy(kernel.ptr, ptr, size); Map(ptr, size, permission); diff --git a/app/src/main/cpp/skyline/loader/loader.cpp b/app/src/main/cpp/skyline/loader/loader.cpp index cb5f96bb..cb9856d4 100644 --- a/app/src/main/cpp/skyline/loader/loader.cpp +++ b/app/src/main/cpp/skyline/loader/loader.cpp @@ -9,7 +9,7 @@ namespace skyline::loader { Loader::ExecutableLoadInfo Loader::LoadExecutable(const std::shared_ptr process, const DeviceState &state, Executable &executable, size_t offset) { - u8 *base{reinterpret_cast(constant::BaseAddress + offset)}; + u8 *base{reinterpret_cast(process->memory.base.address + offset)}; u64 textSize{executable.text.contents.size()}; u64 roSize{executable.ro.contents.size()}; @@ -45,6 +45,6 @@ namespace skyline::loader { std::memcpy(base + executable.data.offset, executable.data.contents.data(), dataSize - executable.bssSize); std::memcpy(base + patchOffset, patch.data(), patchSize); - return {base, patchOffset + patchSize + padding}; + return {base, patchOffset + patchSize + padding, base}; } } diff --git a/app/src/main/cpp/skyline/loader/loader.h b/app/src/main/cpp/skyline/loader/loader.h index 1fa80e0e..81c6d139 100644 --- a/app/src/main/cpp/skyline/loader/loader.h +++ b/app/src/main/cpp/skyline/loader/loader.h @@ -53,6 +53,7 @@ namespace skyline::loader { struct ExecutableLoadInfo { u8* base; //!< The base of the loaded executable size_t size; //!< The total size of the loaded executable + void* entry; //!< The entry point of the loaded executable }; /** @@ -74,6 +75,9 @@ namespace skyline::loader { return std::vector(); } - virtual void LoadProcessData(const std::shared_ptr process, const DeviceState &state) = 0; + /** + * @return Entry point to the start of the main executable in the ROM + */ + virtual void* LoadProcessData(const std::shared_ptr process, const DeviceState &state) = 0; }; } diff --git a/app/src/main/cpp/skyline/loader/nca.cpp b/app/src/main/cpp/skyline/loader/nca.cpp index 270e8197..b15b7f3c 100644 --- a/app/src/main/cpp/skyline/loader/nca.cpp +++ b/app/src/main/cpp/skyline/loader/nca.cpp @@ -12,7 +12,7 @@ namespace skyline::loader { throw exception("Only NCAs with an ExeFS can be loaded directly"); } - void NcaLoader::LoadExeFs(const std::shared_ptr &exeFs, const std::shared_ptr process, const DeviceState &state) { + void* NcaLoader::LoadExeFs(const std::shared_ptr &exeFs, const std::shared_ptr process, const DeviceState &state) { if (exeFs == nullptr) throw exception("Cannot load a null ExeFS"); @@ -25,6 +25,7 @@ namespace skyline::loader { auto loadInfo{NsoLoader::LoadNso(nsoFile, process, state)}; u64 offset{loadInfo.size}; u8* base{loadInfo.base}; + void* entry{loadInfo.entry}; state.logger->Info("Loaded nso 'rtld' at 0x{:X}", base); @@ -40,9 +41,11 @@ namespace skyline::loader { } state.process->memory.InitializeRegions(base, offset); + + return entry; } - void NcaLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { - LoadExeFs(nca.exeFs, process, state); + void* NcaLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { + return LoadExeFs(nca.exeFs, process, state); } } diff --git a/app/src/main/cpp/skyline/loader/nca.h b/app/src/main/cpp/skyline/loader/nca.h index b1d4854f..c2d34f38 100644 --- a/app/src/main/cpp/skyline/loader/nca.h +++ b/app/src/main/cpp/skyline/loader/nca.h @@ -23,8 +23,8 @@ namespace skyline::loader { * @param exefs A filesystem object containing the ExeFS filesystem to load into memory * @param process The process to load the ExeFS into */ - static void LoadExeFs(const std::shared_ptr &exefs, const std::shared_ptr process, const DeviceState &state); + static void* LoadExeFs(const std::shared_ptr &exefs, const std::shared_ptr process, const DeviceState &state); - void LoadProcessData(const std::shared_ptr process, const DeviceState &state); + void* LoadProcessData(const std::shared_ptr process, const DeviceState &state); }; } diff --git a/app/src/main/cpp/skyline/loader/nro.cpp b/app/src/main/cpp/skyline/loader/nro.cpp index a778b01c..755cc8d6 100644 --- a/app/src/main/cpp/skyline/loader/nro.cpp +++ b/app/src/main/cpp/skyline/loader/nro.cpp @@ -44,7 +44,7 @@ namespace skyline::loader { return buffer; } - void NroLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { + void* NroLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { Executable nroExecutable{}; nroExecutable.text.contents = GetSegment(header.text); @@ -61,5 +61,7 @@ namespace skyline::loader { state.process->memory.InitializeVmm(memory::AddressSpaceType::AddressSpace39Bit); auto loadInfo{LoadExecutable(process, state, nroExecutable)}; state.process->memory.InitializeRegions(loadInfo.base, loadInfo.size); + + return loadInfo.entry; } } diff --git a/app/src/main/cpp/skyline/loader/nro.h b/app/src/main/cpp/skyline/loader/nro.h index 0ed2ff3d..42360bf8 100644 --- a/app/src/main/cpp/skyline/loader/nro.h +++ b/app/src/main/cpp/skyline/loader/nro.h @@ -72,6 +72,6 @@ namespace skyline::loader { std::vector GetIcon(); - void LoadProcessData(const std::shared_ptr process, const DeviceState &state); + void* LoadProcessData(const std::shared_ptr process, const DeviceState &state); }; } diff --git a/app/src/main/cpp/skyline/loader/nso.cpp b/app/src/main/cpp/skyline/loader/nso.cpp index 64a45811..595800a5 100644 --- a/app/src/main/cpp/skyline/loader/nso.cpp +++ b/app/src/main/cpp/skyline/loader/nso.cpp @@ -54,9 +54,10 @@ namespace skyline::loader { return LoadExecutable(process, state, nsoExecutable, offset); } - void NsoLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { + void* NsoLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { state.process->memory.InitializeVmm(memory::AddressSpaceType::AddressSpace39Bit); auto loadInfo{LoadNso(backing, process, state)}; state.process->memory.InitializeRegions(loadInfo.base, loadInfo.size); + return loadInfo.entry; } } diff --git a/app/src/main/cpp/skyline/loader/nso.h b/app/src/main/cpp/skyline/loader/nso.h index 6dd689c8..3a0b68aa 100644 --- a/app/src/main/cpp/skyline/loader/nso.h +++ b/app/src/main/cpp/skyline/loader/nso.h @@ -83,6 +83,6 @@ namespace skyline::loader { */ static ExecutableLoadInfo LoadNso(const std::shared_ptr &backing, const std::shared_ptr process, const DeviceState &state, size_t offset = 0); - void LoadProcessData(const std::shared_ptr process, const DeviceState &state); + void* LoadProcessData(const std::shared_ptr process, const DeviceState &state); }; } diff --git a/app/src/main/cpp/skyline/loader/nsp.cpp b/app/src/main/cpp/skyline/loader/nsp.cpp index 86cdaf94..adabd78b 100644 --- a/app/src/main/cpp/skyline/loader/nsp.cpp +++ b/app/src/main/cpp/skyline/loader/nsp.cpp @@ -34,8 +34,8 @@ namespace skyline::loader { nacp = std::make_shared(controlRomFs->OpenFile("control.nacp")); } - void NspLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { - NcaLoader::LoadExeFs(programNca->exeFs, process, state); + void* NspLoader::LoadProcessData(const std::shared_ptr process, const DeviceState &state) { + return NcaLoader::LoadExeFs(programNca->exeFs, process, state); } std::vector NspLoader::GetIcon() { diff --git a/app/src/main/cpp/skyline/loader/nsp.h b/app/src/main/cpp/skyline/loader/nsp.h index b50d0a6b..974b32fb 100644 --- a/app/src/main/cpp/skyline/loader/nsp.h +++ b/app/src/main/cpp/skyline/loader/nsp.h @@ -26,6 +26,6 @@ namespace skyline::loader { std::vector GetIcon(); - void LoadProcessData(const std::shared_ptr process, const DeviceState &state); + void* LoadProcessData(const std::shared_ptr process, const DeviceState &state); }; } diff --git a/app/src/main/cpp/skyline/os.cpp b/app/src/main/cpp/skyline/os.cpp index 2bf8a7c6..0e14607f 100644 --- a/app/src/main/cpp/skyline/os.cpp +++ b/app/src/main/cpp/skyline/os.cpp @@ -30,9 +30,9 @@ namespace skyline::kernel { throw exception("Unsupported ROM extension."); process = std::make_shared(state); - state.loader->LoadProcessData(process, state); + auto entry{state.loader->LoadProcessData(process, state)}; process->InitializeHeap(); - process->CreateThread(reinterpret_cast(constant::BaseAddress))->Start(); + process->CreateThread(entry)->Start(); state.nce->Execute(); } diff --git a/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp b/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp index af4fcdc0..1c337776 100644 --- a/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp +++ b/app/src/main/cpp/skyline/services/fssrv/IFileSystemProxy.cpp @@ -59,7 +59,6 @@ namespace skyline::service::fssrv { manager.RegisterService(std::make_shared(std::make_shared(state.os->appFilesPath + "/switch" + saveDataPath), state, manager), session, response); return {}; - } Result IFileSystemProxy::OpenDataStorageByCurrentProcess(type::KSession &session, ipc::IpcRequest &request, ipc::IpcResponse &response) {