From 92a21ea616c4f6c841ef8f2642f0af20dd55ede9 Mon Sep 17 00:00:00 2001 From: PixelyIon Date: Fri, 22 Oct 2021 15:32:18 +0530 Subject: [PATCH] Cleanup & Use C++ Concepts in `utils.h` --- app/src/main/cpp/skyline/common/utils.h | 46 ++++++++++--------- app/src/main/cpp/skyline/kernel/svc.cpp | 42 ++++++++--------- .../skyline/kernel/types/KPrivateMemory.cpp | 6 +-- .../skyline/kernel/types/KSharedMemory.cpp | 7 ++- app/src/main/cpp/skyline/loader/loader.cpp | 4 +- app/src/main/cpp/skyline/vfs/npdm.cpp | 2 +- 6 files changed, 55 insertions(+), 52 deletions(-) diff --git a/app/src/main/cpp/skyline/common/utils.h b/app/src/main/cpp/skyline/common/utils.h index 24da688e..2f5f5e5a 100644 --- a/app/src/main/cpp/skyline/common/utils.h +++ b/app/src/main/cpp/skyline/common/utils.h @@ -55,6 +55,9 @@ namespace skyline::util { return item; } + template + concept IsPointerOrIntegral = std::is_integral_v || std::is_pointer_v; + /** * @return The value aligned up to the next multiple * @note The multiple needs to be a power of 2 @@ -78,6 +81,7 @@ namespace skyline::util { * @return If the address is aligned with the multiple */ template + requires (IsPointerOrIntegral && IsPointerOrIntegral) constexpr bool IsAligned(TypeVal value, TypeMul multiple) { if ((multiple & (multiple - 1)) == 0) return !(PointerValue(value) & (multiple - 1U)); @@ -85,19 +89,15 @@ namespace skyline::util { return (PointerValue(value) % multiple) == 0; } - /** - * @return If the value is page aligned - */ template - constexpr bool PageAligned(TypeVal value) { + requires IsPointerOrIntegral + constexpr bool IsPageAligned(TypeVal value) { return IsAligned(value, PAGE_SIZE); } - /** - * @return If the value is word aligned - */ template - constexpr bool WordAligned(TypeVal value) { + requires IsPointerOrIntegral + constexpr bool IsWordAligned(TypeVal value) { return IsAligned(value, WORD_BIT / 8); } @@ -106,6 +106,7 @@ namespace skyline::util { * @return The magic of the supplied string */ template + requires std::is_integral_v constexpr Type MakeMagic(std::string_view string) { Type object{}; size_t offset{}; @@ -129,10 +130,10 @@ namespace skyline::util { } template - constexpr std::array HexStringToArray(std::string_view string) { + constexpr std::array HexStringToArray(std::string_view string) { if (string.size() != Size * 2) throw exception("String size: {} (Expected {})", string.size(), Size); - std::array result; + std::array result; for (size_t i{}; i < Size; i++) { size_t index{i * 2}; result[i] = (HexDigitToNibble(string[index]) << 4) | HexDigitToNibble(string[index + 1]); @@ -141,6 +142,7 @@ namespace skyline::util { } template + requires std::is_integral_v 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)); @@ -161,7 +163,7 @@ namespace skyline::util { } template - constexpr std::array SwapEndianness(std::array in) { + constexpr std::array SwapEndianness(std::array in) { std::reverse(in.begin(), in.end()); return in; } @@ -190,13 +192,13 @@ namespace skyline::util { */ template struct IntegerFor { - using type = std::conditional_t - > + using Type = std::conditional_t + > >; - static constexpr size_t count{sizeof(T) / sizeof(type)}; + static constexpr size_t Count{sizeof(T) / sizeof(Type)}; }; namespace detail { @@ -207,22 +209,24 @@ namespace skyline::util { * @brief Fills an array with random data from a Mersenne Twister pseudo-random generator * @note The generator is seeded with the the current time in ticks */ - template requires (std::is_integral_v) + template + requires std::is_integral_v void FillRandomBytes(std::span in) { std::independent_bits_engine::digits, T> gen(detail::generator); std::generate(in.begin(), in.end(), gen); } - template requires (!std::is_integral_v && std::is_trivially_copyable_v) + template + requires (!std::is_integral_v && std::is_trivially_copyable_v) void FillRandomBytes(T &object) { - FillRandomBytes(std::span(reinterpret_cast::type *>(&object), IntegerFor::count)); + FillRandomBytes(std::span(reinterpret_cast::Type *>(&object), IntegerFor::Count)); } /** * @brief A temporary shim for C++ 20's bit_cast to make transitioning to it easier */ template - To BitCast(const From& from) { - return *reinterpret_cast(&from); + To BitCast(const From &from) { + return *reinterpret_cast(&from); } } diff --git a/app/src/main/cpp/skyline/kernel/svc.cpp b/app/src/main/cpp/skyline/kernel/svc.cpp index cf4d48b8..88129414 100644 --- a/app/src/main/cpp/skyline/kernel/svc.cpp +++ b/app/src/main/cpp/skyline/kernel/svc.cpp @@ -32,14 +32,14 @@ namespace skyline::kernel::svc { void SetMemoryAttribute(const DeviceState &state) { auto pointer{reinterpret_cast(state.ctx->gpr.x0)}; - if (!util::PageAligned(pointer)) { + if (!util::IsPageAligned(pointer)) { state.ctx->gpr.w0 = result::InvalidAddress; state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer); return; } size_t size{state.ctx->gpr.x1}; - if (!util::PageAligned(size)) { + if (!util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -83,13 +83,13 @@ namespace skyline::kernel::svc { auto source{reinterpret_cast(state.ctx->gpr.x1)}; size_t size{state.ctx->gpr.x2}; - if (!util::PageAligned(destination) || !util::PageAligned(source)) { + if (!util::IsPageAligned(destination) || !util::IsPageAligned(source)) { state.ctx->gpr.w0 = result::InvalidAddress; state.logger->Warn("Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size); return; } - if (!util::PageAligned(size)) { + if (!util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -131,13 +131,13 @@ namespace skyline::kernel::svc { auto destination{reinterpret_cast(state.ctx->gpr.x1)}; size_t size{state.ctx->gpr.x2}; - if (!util::PageAligned(destination) || !util::PageAligned(source)) { + if (!util::IsPageAligned(destination) || !util::IsPageAligned(source)) { state.ctx->gpr.w0 = result::InvalidAddress; state.logger->Warn("Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size); return; } - if (!util::PageAligned(size)) { + if (!util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -477,14 +477,14 @@ namespace skyline::kernel::svc { auto object{state.process->GetHandle(handle)}; auto pointer{reinterpret_cast(state.ctx->gpr.x1)}; - if (!util::PageAligned(pointer)) { + if (!util::IsPageAligned(pointer)) { state.ctx->gpr.w0 = result::InvalidAddress; state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer); return; } size_t size{state.ctx->gpr.x2}; - if (!util::PageAligned(size)) { + if (!util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -514,14 +514,14 @@ namespace skyline::kernel::svc { auto object{state.process->GetHandle(handle)}; auto pointer{reinterpret_cast(state.ctx->gpr.x1)}; - if (!util::PageAligned(pointer)) { + if (!util::IsPageAligned(pointer)) { state.ctx->gpr.w0 = result::InvalidAddress; state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer); return; } size_t size{state.ctx->gpr.x2}; - if (!util::PageAligned(size)) { + if (!util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -540,14 +540,14 @@ namespace skyline::kernel::svc { void CreateTransferMemory(const DeviceState &state) { auto pointer{reinterpret_cast(state.ctx->gpr.x1)}; - if (!util::PageAligned(pointer)) { + if (!util::IsPageAligned(pointer)) { state.ctx->gpr.w0 = result::InvalidAddress; state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer); return; } size_t size{state.ctx->gpr.x2}; - if (!util::PageAligned(size)) { + if (!util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size); return; @@ -741,7 +741,7 @@ namespace skyline::kernel::svc { void ArbitrateLock(const DeviceState &state) { auto mutex{reinterpret_cast(state.ctx->gpr.x1)}; - if (!util::WordAligned(mutex)) { + if (!util::IsWordAligned(mutex)) { state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex); state.ctx->gpr.w0 = result::InvalidAddress; return; @@ -764,7 +764,7 @@ namespace skyline::kernel::svc { void ArbitrateUnlock(const DeviceState &state) { auto mutex{reinterpret_cast(state.ctx->gpr.x0)}; - if (!util::WordAligned(mutex)) { + if (!util::IsWordAligned(mutex)) { state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex); state.ctx->gpr.w0 = result::InvalidAddress; return; @@ -779,7 +779,7 @@ namespace skyline::kernel::svc { void WaitProcessWideKeyAtomic(const DeviceState &state) { auto mutex{reinterpret_cast(state.ctx->gpr.x0)}; - if (!util::WordAligned(mutex)) { + if (!util::IsWordAligned(mutex)) { state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex); state.ctx->gpr.w0 = result::InvalidAddress; return; @@ -1016,12 +1016,12 @@ namespace skyline::kernel::svc { auto pointer{reinterpret_cast(state.ctx->gpr.x0)}; size_t size{state.ctx->gpr.x1}; - if (!util::PageAligned(pointer)) { + if (!util::IsPageAligned(pointer)) { state.ctx->gpr.w0 = result::InvalidAddress; return; } - if (!size || !util::PageAligned(size)) { + if (!size || !util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; return; } @@ -1040,12 +1040,12 @@ namespace skyline::kernel::svc { auto pointer{reinterpret_cast(state.ctx->gpr.x0)}; size_t size{state.ctx->gpr.x1}; - if (!util::PageAligned(pointer)) { + if (!util::IsPageAligned(pointer)) { state.ctx->gpr.w0 = result::InvalidAddress; return; } - if (!size || !util::PageAligned(size)) { + if (!size || !util::IsPageAligned(size)) { state.ctx->gpr.w0 = result::InvalidSize; return; } @@ -1087,7 +1087,7 @@ namespace skyline::kernel::svc { void WaitForAddress(const DeviceState &state) { auto address{reinterpret_cast(state.ctx->gpr.x0)}; - if (!util::WordAligned(address)) [[unlikely]] { + if (!util::IsWordAligned(address)) [[unlikely]] { state.logger->Warn("'address' not word aligned: 0x{:X}", address); state.ctx->gpr.w0 = result::InvalidAddress; return; @@ -1149,7 +1149,7 @@ namespace skyline::kernel::svc { void SignalToAddress(const DeviceState &state) { auto address{reinterpret_cast(state.ctx->gpr.x0)}; - if (!util::WordAligned(address)) [[unlikely]] { + if (!util::IsWordAligned(address)) [[unlikely]] { state.logger->Warn("'address' not word aligned: 0x{:X}", address); state.ctx->gpr.w0 = result::InvalidAddress; return; diff --git a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp index c16297e4..e18b6d5e 100644 --- a/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KPrivateMemory.cpp @@ -11,7 +11,7 @@ namespace skyline::kernel::type { KPrivateMemory::KPrivateMemory(const DeviceState &state, u8 *ptr, size_t size, memory::Permission permission, memory::MemoryState memState) : ptr(ptr), size(size), permission(permission), memoryState(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) || !util::PageAligned(size)) + if (!util::IsPageAligned(ptr) || !util::IsPageAligned(size)) throw exception("KPrivateMemory mapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size); 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 @@ -50,7 +50,7 @@ namespace skyline::kernel::type { void KPrivateMemory::Remap(u8 *nPtr, size_t nSize) { if (!state.process->memory.base.IsInside(nPtr) || !state.process->memory.base.IsInside(nPtr + nSize)) throw exception("KPrivateMemory remapping isn't inside guest address space: 0x{:X} - 0x{:X}", nPtr, nPtr + nSize); - if (!util::PageAligned(nPtr) || !util::PageAligned(nSize)) + if (!util::IsPageAligned(nPtr) || !util::IsPageAligned(nSize)) throw exception("KPrivateMemory remapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", nPtr, nPtr + nSize, nSize); if (mprotect(ptr, size, PROT_NONE) < 0) @@ -64,7 +64,7 @@ namespace skyline::kernel::type { pPtr = std::clamp(pPtr, ptr, ptr + size); pSize = std::min(pSize, static_cast((ptr + size) - pPtr)); - if (pPtr && !util::PageAligned(pPtr)) + if (pPtr && !util::IsPageAligned(pPtr)) throw exception("KPrivateMemory permission updated with a non-page-aligned address: 0x{:X}", pPtr); // If a static code region has been mapped as writable it needs to be changed to mutable diff --git a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp index 1ce38ad4..a7229123 100644 --- a/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp +++ b/app/src/main/cpp/skyline/kernel/types/KSharedMemory.cpp @@ -23,7 +23,7 @@ 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 (!util::PageAligned(ptr) || !util::PageAligned(size)) + if (!util::IsPageAligned(ptr) || !util::IsPageAligned(size)) throw exception("KSharedMemory mapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size); if (guest.Valid()) throw exception("Mapping KSharedMemory multiple times on guest is not supported: Requested Mapping: 0x{:X} - 0x{:X} (0x{:X}), Current Mapping: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size, guest.ptr, guest.ptr + guest.size, guest.size); @@ -49,7 +49,7 @@ namespace skyline::kernel::type { void KSharedMemory::Unmap(u8 *ptr, u64 size) { 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) || !util::PageAligned(size)) + if (!util::IsPageAligned(ptr) || !util::IsPageAligned(size)) throw exception("KSharedMemory mapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size); if (guest.ptr != ptr && guest.size != size) throw exception("Unmapping KSharedMemory partially is not supported: Requested Unmap: 0x{:X} - 0x{:X} (0x{:X}), Current Mapping: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size, guest.ptr, guest.ptr + guest.size, guest.size); @@ -66,7 +66,7 @@ namespace skyline::kernel::type { } void KSharedMemory::UpdatePermission(u8 *ptr, size_t size, memory::Permission permission) { - if (ptr && !util::PageAligned(ptr)) + if (ptr && !util::IsPageAligned(ptr)) throw exception("KSharedMemory permission updated with a non-page-aligned address: 0x{:X}", ptr); if (guest.Valid()) { @@ -100,7 +100,6 @@ namespace skyline::kernel::type { constexpr memory::Permission UnborrowPermission{true, true, false}; if (mmap(guest.ptr, guest.size, UnborrowPermission.Get(), MAP_ANONYMOUS | MAP_PRIVATE | MAP_FIXED, -1, 0) == MAP_FAILED) - // It is likely that these exceptions will end up as asserts as the destructor is implicitly noexcept but we want to be notified about these not working so that's fine as it can be discovered in the debugger state.logger->Warn("An error occurred while remapping transfer memory as anonymous memory in guest: {}", strerror(errno)); else if (!host.Valid()) state.logger->Warn("Expected host mapping of transfer memory to be valid during KTransferMemory destruction"); diff --git a/app/src/main/cpp/skyline/loader/loader.cpp b/app/src/main/cpp/skyline/loader/loader.cpp index c856d4df..4f27921a 100644 --- a/app/src/main/cpp/skyline/loader/loader.cpp +++ b/app/src/main/cpp/skyline/loader/loader.cpp @@ -17,10 +17,10 @@ namespace skyline::loader { u64 roSize{executable.ro.contents.size()}; u64 dataSize{executable.data.contents.size() + executable.bssSize}; - if (!util::PageAligned(textSize) || !util::PageAligned(roSize) || !util::PageAligned(dataSize)) + if (!util::IsPageAligned(textSize) || !util::IsPageAligned(roSize) || !util::IsPageAligned(dataSize)) throw exception("LoadProcessData: Sections are not aligned with page size: 0x{:X}, 0x{:X}, 0x{:X}", textSize, roSize, dataSize); - if (!util::PageAligned(executable.text.offset) || !util::PageAligned(executable.ro.offset) || !util::PageAligned(executable.data.offset)) + if (!util::IsPageAligned(executable.text.offset) || !util::IsPageAligned(executable.ro.offset) || !util::IsPageAligned(executable.data.offset)) throw exception("LoadProcessData: Section offsets are not aligned with page size: 0x{:X}, 0x{:X}, 0x{:X}", executable.text.offset, executable.ro.offset, executable.data.offset); auto patch{state.nce->GetPatchData(executable.text.contents)}; diff --git a/app/src/main/cpp/skyline/vfs/npdm.cpp b/app/src/main/cpp/skyline/vfs/npdm.cpp index e4c79dac..f82f0ab2 100644 --- a/app/src/main/cpp/skyline/vfs/npdm.cpp +++ b/app/src/main/cpp/skyline/vfs/npdm.cpp @@ -40,7 +40,7 @@ namespace skyline::vfs { meta = backing->Read(); if (meta.magic != MetaMagic) throw exception("NPDM Meta Magic isn't correct: 0x{:X} (\"META\" = 0x{:X})", meta.magic, MetaMagic); - if (!util::PageAligned(meta.mainThreadStackSize)) + if (!util::IsPageAligned(meta.mainThreadStackSize)) throw exception("NPDM Main Thread Stack isn't page aligned: 0x{:X}", meta.mainThreadStackSize); aci0 = meta.aci0.Read(backing);