mirror of
https://github.com/skyline-emu/skyline.git
synced 2024-12-29 00:05:37 +03:00
Cleanup & Use C++ Concepts in utils.h
This commit is contained in:
parent
ea2626bcc6
commit
92a21ea616
@ -55,6 +55,9 @@ namespace skyline::util {
|
|||||||
return item;
|
return item;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
template <typename T>
|
||||||
|
concept IsPointerOrIntegral = std::is_integral_v<T> || std::is_pointer_v<T>;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return The value aligned up to the next multiple
|
* @return The value aligned up to the next multiple
|
||||||
* @note The multiple needs to be a power of 2
|
* @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
|
* @return If the address is aligned with the multiple
|
||||||
*/
|
*/
|
||||||
template<typename TypeVal, typename TypeMul>
|
template<typename TypeVal, typename TypeMul>
|
||||||
|
requires (IsPointerOrIntegral<TypeVal> && IsPointerOrIntegral<TypeMul>)
|
||||||
constexpr bool IsAligned(TypeVal value, TypeMul multiple) {
|
constexpr bool IsAligned(TypeVal value, TypeMul multiple) {
|
||||||
if ((multiple & (multiple - 1)) == 0)
|
if ((multiple & (multiple - 1)) == 0)
|
||||||
return !(PointerValue(value) & (multiple - 1U));
|
return !(PointerValue(value) & (multiple - 1U));
|
||||||
@ -85,19 +89,15 @@ namespace skyline::util {
|
|||||||
return (PointerValue(value) % multiple) == 0;
|
return (PointerValue(value) % multiple) == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the value is page aligned
|
|
||||||
*/
|
|
||||||
template<typename TypeVal>
|
template<typename TypeVal>
|
||||||
constexpr bool PageAligned(TypeVal value) {
|
requires IsPointerOrIntegral<TypeVal>
|
||||||
|
constexpr bool IsPageAligned(TypeVal value) {
|
||||||
return IsAligned(value, PAGE_SIZE);
|
return IsAligned(value, PAGE_SIZE);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @return If the value is word aligned
|
|
||||||
*/
|
|
||||||
template<typename TypeVal>
|
template<typename TypeVal>
|
||||||
constexpr bool WordAligned(TypeVal value) {
|
requires IsPointerOrIntegral<TypeVal>
|
||||||
|
constexpr bool IsWordAligned(TypeVal value) {
|
||||||
return IsAligned(value, WORD_BIT / 8);
|
return IsAligned(value, WORD_BIT / 8);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -106,6 +106,7 @@ namespace skyline::util {
|
|||||||
* @return The magic of the supplied string
|
* @return The magic of the supplied string
|
||||||
*/
|
*/
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
requires std::is_integral_v<Type>
|
||||||
constexpr Type MakeMagic(std::string_view string) {
|
constexpr Type MakeMagic(std::string_view string) {
|
||||||
Type object{};
|
Type object{};
|
||||||
size_t offset{};
|
size_t offset{};
|
||||||
@ -129,10 +130,10 @@ namespace skyline::util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<size_t Size>
|
template<size_t Size>
|
||||||
constexpr std::array <u8, Size> HexStringToArray(std::string_view string) {
|
constexpr std::array<u8, Size> HexStringToArray(std::string_view string) {
|
||||||
if (string.size() != Size * 2)
|
if (string.size() != Size * 2)
|
||||||
throw exception("String size: {} (Expected {})", string.size(), Size);
|
throw exception("String size: {} (Expected {})", string.size(), Size);
|
||||||
std::array <u8, Size> result;
|
std::array<u8, Size> result;
|
||||||
for (size_t i{}; i < Size; i++) {
|
for (size_t i{}; i < Size; i++) {
|
||||||
size_t index{i * 2};
|
size_t index{i * 2};
|
||||||
result[i] = (HexDigitToNibble(string[index]) << 4) | HexDigitToNibble(string[index + 1]);
|
result[i] = (HexDigitToNibble(string[index]) << 4) | HexDigitToNibble(string[index + 1]);
|
||||||
@ -141,6 +142,7 @@ namespace skyline::util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename Type>
|
template<typename Type>
|
||||||
|
requires std::is_integral_v<Type>
|
||||||
constexpr Type HexStringToInt(std::string_view string) {
|
constexpr Type HexStringToInt(std::string_view string) {
|
||||||
if (string.size() > sizeof(Type) * 2)
|
if (string.size() > sizeof(Type) * 2)
|
||||||
throw exception("String size larger than type: {} (sizeof(Type): {})", string.size(), sizeof(Type));
|
throw exception("String size larger than type: {} (sizeof(Type): {})", string.size(), sizeof(Type));
|
||||||
@ -161,7 +163,7 @@ namespace skyline::util {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<size_t N>
|
template<size_t N>
|
||||||
constexpr std::array <u8, N> SwapEndianness(std::array <u8, N> in) {
|
constexpr std::array<u8, N> SwapEndianness(std::array<u8, N> in) {
|
||||||
std::reverse(in.begin(), in.end());
|
std::reverse(in.begin(), in.end());
|
||||||
return in;
|
return in;
|
||||||
}
|
}
|
||||||
@ -190,13 +192,13 @@ namespace skyline::util {
|
|||||||
*/
|
*/
|
||||||
template<class T>
|
template<class T>
|
||||||
struct IntegerFor {
|
struct IntegerFor {
|
||||||
using type = std::conditional_t<sizeof(T) % sizeof(u64) == 0, u64,
|
using Type = std::conditional_t<sizeof(T) % sizeof(u64) == 0, u64,
|
||||||
std::conditional_t<sizeof(T) % sizeof(u32) == 0, u32,
|
std::conditional_t<sizeof(T) % sizeof(u32) == 0, u32,
|
||||||
std::conditional_t<sizeof(T) % sizeof(u16) == 0, u16, u8>
|
std::conditional_t<sizeof(T) % sizeof(u16) == 0, u16, u8>
|
||||||
>
|
>
|
||||||
>;
|
>;
|
||||||
|
|
||||||
static constexpr size_t count{sizeof(T) / sizeof(type)};
|
static constexpr size_t Count{sizeof(T) / sizeof(Type)};
|
||||||
};
|
};
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
@ -207,22 +209,24 @@ namespace skyline::util {
|
|||||||
* @brief Fills an array with random data from a Mersenne Twister pseudo-random generator
|
* @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
|
* @note The generator is seeded with the the current time in ticks
|
||||||
*/
|
*/
|
||||||
template<typename T> requires (std::is_integral_v<T>)
|
template<typename T>
|
||||||
|
requires std::is_integral_v<T>
|
||||||
void FillRandomBytes(std::span<T> in) {
|
void FillRandomBytes(std::span<T> in) {
|
||||||
std::independent_bits_engine<std::mt19937_64, std::numeric_limits<T>::digits, T> gen(detail::generator);
|
std::independent_bits_engine<std::mt19937_64, std::numeric_limits<T>::digits, T> gen(detail::generator);
|
||||||
std::generate(in.begin(), in.end(), gen);
|
std::generate(in.begin(), in.end(), gen);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class T> requires (!std::is_integral_v<T> && std::is_trivially_copyable_v<T>)
|
template<class T>
|
||||||
|
requires (!std::is_integral_v<T> && std::is_trivially_copyable_v<T>)
|
||||||
void FillRandomBytes(T &object) {
|
void FillRandomBytes(T &object) {
|
||||||
FillRandomBytes(std::span(reinterpret_cast<typename IntegerFor<T>::type *>(&object), IntegerFor<T>::count));
|
FillRandomBytes(std::span(reinterpret_cast<typename IntegerFor<T>::Type *>(&object), IntegerFor<T>::Count));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief A temporary shim for C++ 20's bit_cast to make transitioning to it easier
|
* @brief A temporary shim for C++ 20's bit_cast to make transitioning to it easier
|
||||||
*/
|
*/
|
||||||
template<typename To, typename From>
|
template<typename To, typename From>
|
||||||
To BitCast(const From& from) {
|
To BitCast(const From &from) {
|
||||||
return *reinterpret_cast<const To*>(&from);
|
return *reinterpret_cast<const To *>(&from);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,14 +32,14 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void SetMemoryAttribute(const DeviceState &state) {
|
void SetMemoryAttribute(const DeviceState &state) {
|
||||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x0)};
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x0)};
|
||||||
if (!util::PageAligned(pointer)) {
|
if (!util::IsPageAligned(pointer)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size{state.ctx->gpr.x1};
|
size_t size{state.ctx->gpr.x1};
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -83,13 +83,13 @@ namespace skyline::kernel::svc {
|
|||||||
auto source{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
auto source{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||||
size_t size{state.ctx->gpr.x2};
|
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.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);
|
state.logger->Warn("Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -131,13 +131,13 @@ namespace skyline::kernel::svc {
|
|||||||
auto destination{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
auto destination{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||||
size_t size{state.ctx->gpr.x2};
|
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.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);
|
state.logger->Warn("Addresses not page aligned: Source: 0x{:X}, Destination: 0x{:X} (Size: 0x{:X} bytes)", source, destination, size);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -477,14 +477,14 @@ namespace skyline::kernel::svc {
|
|||||||
auto object{state.process->GetHandle<type::KSharedMemory>(handle)};
|
auto object{state.process->GetHandle<type::KSharedMemory>(handle)};
|
||||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||||
|
|
||||||
if (!util::PageAligned(pointer)) {
|
if (!util::IsPageAligned(pointer)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size{state.ctx->gpr.x2};
|
size_t size{state.ctx->gpr.x2};
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -514,14 +514,14 @@ namespace skyline::kernel::svc {
|
|||||||
auto object{state.process->GetHandle<type::KSharedMemory>(handle)};
|
auto object{state.process->GetHandle<type::KSharedMemory>(handle)};
|
||||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||||
|
|
||||||
if (!util::PageAligned(pointer)) {
|
if (!util::IsPageAligned(pointer)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size{state.ctx->gpr.x2};
|
size_t size{state.ctx->gpr.x2};
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -540,14 +540,14 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void CreateTransferMemory(const DeviceState &state) {
|
void CreateTransferMemory(const DeviceState &state) {
|
||||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x1)};
|
||||||
if (!util::PageAligned(pointer)) {
|
if (!util::IsPageAligned(pointer)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
state.logger->Warn("'pointer' not page aligned: 0x{:X}", pointer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t size{state.ctx->gpr.x2};
|
size_t size{state.ctx->gpr.x2};
|
||||||
if (!util::PageAligned(size)) {
|
if (!util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
state.logger->Warn("'size' {}: 0x{:X}", size ? "not page aligned" : "is zero", size);
|
||||||
return;
|
return;
|
||||||
@ -741,7 +741,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void ArbitrateLock(const DeviceState &state) {
|
void ArbitrateLock(const DeviceState &state) {
|
||||||
auto mutex{reinterpret_cast<u32 *>(state.ctx->gpr.x1)};
|
auto mutex{reinterpret_cast<u32 *>(state.ctx->gpr.x1)};
|
||||||
if (!util::WordAligned(mutex)) {
|
if (!util::IsWordAligned(mutex)) {
|
||||||
state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex);
|
state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex);
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
@ -764,7 +764,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void ArbitrateUnlock(const DeviceState &state) {
|
void ArbitrateUnlock(const DeviceState &state) {
|
||||||
auto mutex{reinterpret_cast<u32 *>(state.ctx->gpr.x0)};
|
auto mutex{reinterpret_cast<u32 *>(state.ctx->gpr.x0)};
|
||||||
if (!util::WordAligned(mutex)) {
|
if (!util::IsWordAligned(mutex)) {
|
||||||
state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex);
|
state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex);
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
@ -779,7 +779,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void WaitProcessWideKeyAtomic(const DeviceState &state) {
|
void WaitProcessWideKeyAtomic(const DeviceState &state) {
|
||||||
auto mutex{reinterpret_cast<u32 *>(state.ctx->gpr.x0)};
|
auto mutex{reinterpret_cast<u32 *>(state.ctx->gpr.x0)};
|
||||||
if (!util::WordAligned(mutex)) {
|
if (!util::IsWordAligned(mutex)) {
|
||||||
state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex);
|
state.logger->Warn("'mutex' not word aligned: 0x{:X}", mutex);
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
@ -1016,12 +1016,12 @@ namespace skyline::kernel::svc {
|
|||||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x0)};
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x0)};
|
||||||
size_t size{state.ctx->gpr.x1};
|
size_t size{state.ctx->gpr.x1};
|
||||||
|
|
||||||
if (!util::PageAligned(pointer)) {
|
if (!util::IsPageAligned(pointer)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!size || !util::PageAligned(size)) {
|
if (!size || !util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1040,12 +1040,12 @@ namespace skyline::kernel::svc {
|
|||||||
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x0)};
|
auto pointer{reinterpret_cast<u8 *>(state.ctx->gpr.x0)};
|
||||||
size_t size{state.ctx->gpr.x1};
|
size_t size{state.ctx->gpr.x1};
|
||||||
|
|
||||||
if (!util::PageAligned(pointer)) {
|
if (!util::IsPageAligned(pointer)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!size || !util::PageAligned(size)) {
|
if (!size || !util::IsPageAligned(size)) {
|
||||||
state.ctx->gpr.w0 = result::InvalidSize;
|
state.ctx->gpr.w0 = result::InvalidSize;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -1087,7 +1087,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void WaitForAddress(const DeviceState &state) {
|
void WaitForAddress(const DeviceState &state) {
|
||||||
auto address{reinterpret_cast<u32 *>(state.ctx->gpr.x0)};
|
auto address{reinterpret_cast<u32 *>(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.logger->Warn("'address' not word aligned: 0x{:X}", address);
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
@ -1149,7 +1149,7 @@ namespace skyline::kernel::svc {
|
|||||||
|
|
||||||
void SignalToAddress(const DeviceState &state) {
|
void SignalToAddress(const DeviceState &state) {
|
||||||
auto address{reinterpret_cast<u32 *>(state.ctx->gpr.x0)};
|
auto address{reinterpret_cast<u32 *>(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.logger->Warn("'address' not word aligned: 0x{:X}", address);
|
||||||
state.ctx->gpr.w0 = result::InvalidAddress;
|
state.ctx->gpr.w0 = result::InvalidAddress;
|
||||||
return;
|
return;
|
||||||
|
@ -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) {
|
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))
|
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);
|
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);
|
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
|
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) {
|
void KPrivateMemory::Remap(u8 *nPtr, size_t nSize) {
|
||||||
if (!state.process->memory.base.IsInside(nPtr) || !state.process->memory.base.IsInside(nPtr + 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);
|
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);
|
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)
|
if (mprotect(ptr, size, PROT_NONE) < 0)
|
||||||
@ -64,7 +64,7 @@ namespace skyline::kernel::type {
|
|||||||
pPtr = std::clamp(pPtr, ptr, ptr + size);
|
pPtr = std::clamp(pPtr, ptr, ptr + size);
|
||||||
pSize = std::min(pSize, static_cast<size_t>((ptr + size) - pPtr));
|
pSize = std::min(pSize, static_cast<size_t>((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);
|
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
|
// If a static code region has been mapped as writable it needs to be changed to mutable
|
||||||
|
@ -23,7 +23,7 @@ namespace skyline::kernel::type {
|
|||||||
u8 *KSharedMemory::Map(u8 *ptr, u64 size, memory::Permission permission) {
|
u8 *KSharedMemory::Map(u8 *ptr, u64 size, memory::Permission permission) {
|
||||||
if (!state.process->memory.base.IsInside(ptr) || !state.process->memory.base.IsInside(ptr + 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);
|
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);
|
throw exception("KSharedMemory mapping isn't page-aligned: 0x{:X} - 0x{:X} (0x{:X})", ptr, ptr + size, size);
|
||||||
if (guest.Valid())
|
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);
|
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) {
|
void KSharedMemory::Unmap(u8 *ptr, u64 size) {
|
||||||
if (!state.process->memory.base.IsInside(ptr) || !state.process->memory.base.IsInside(ptr + 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);
|
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);
|
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)
|
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);
|
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) {
|
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);
|
throw exception("KSharedMemory permission updated with a non-page-aligned address: 0x{:X}", ptr);
|
||||||
|
|
||||||
if (guest.Valid()) {
|
if (guest.Valid()) {
|
||||||
@ -100,7 +100,6 @@ namespace skyline::kernel::type {
|
|||||||
constexpr memory::Permission UnborrowPermission{true, true, false};
|
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)
|
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));
|
state.logger->Warn("An error occurred while remapping transfer memory as anonymous memory in guest: {}", strerror(errno));
|
||||||
else if (!host.Valid())
|
else if (!host.Valid())
|
||||||
state.logger->Warn("Expected host mapping of transfer memory to be valid during KTransferMemory destruction");
|
state.logger->Warn("Expected host mapping of transfer memory to be valid during KTransferMemory destruction");
|
||||||
|
@ -17,10 +17,10 @@ namespace skyline::loader {
|
|||||||
u64 roSize{executable.ro.contents.size()};
|
u64 roSize{executable.ro.contents.size()};
|
||||||
u64 dataSize{executable.data.contents.size() + executable.bssSize};
|
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);
|
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);
|
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)};
|
auto patch{state.nce->GetPatchData(executable.text.contents)};
|
||||||
|
@ -40,7 +40,7 @@ namespace skyline::vfs {
|
|||||||
meta = backing->Read<NpdmMeta>();
|
meta = backing->Read<NpdmMeta>();
|
||||||
if (meta.magic != MetaMagic)
|
if (meta.magic != MetaMagic)
|
||||||
throw exception("NPDM Meta Magic isn't correct: 0x{:X} (\"META\" = 0x{:X})", 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);
|
throw exception("NPDM Main Thread Stack isn't page aligned: 0x{:X}", meta.mainThreadStackSize);
|
||||||
|
|
||||||
aci0 = meta.aci0.Read<NpdmAci0>(backing);
|
aci0 = meta.aci0.Read<NpdmAci0>(backing);
|
||||||
|
Loading…
Reference in New Issue
Block a user