mirror of
https://github.com/Atmosphere-NX/Atmosphere-libs.git
synced 2025-06-21 19:12:42 +02:00
loader: use os apis for interacting with process memory
This commit is contained in:
parent
1ac83a92e5
commit
aecf739a7c
@ -25,6 +25,7 @@
|
|||||||
#include <stratosphere/os/os_virtual_address_memory.hpp>
|
#include <stratosphere/os/os_virtual_address_memory.hpp>
|
||||||
#include <stratosphere/os/os_native_handle.hpp>
|
#include <stratosphere/os/os_native_handle.hpp>
|
||||||
#include <stratosphere/os/os_process_handle_api.hpp>
|
#include <stratosphere/os/os_process_handle_api.hpp>
|
||||||
|
#include <stratosphere/os/os_process_memory_api.hpp>
|
||||||
#include <stratosphere/os/os_random.hpp>
|
#include <stratosphere/os/os_random.hpp>
|
||||||
#include <stratosphere/os/os_mutex.hpp>
|
#include <stratosphere/os/os_mutex.hpp>
|
||||||
#include <stratosphere/os/os_condition_variable.hpp>
|
#include <stratosphere/os/os_condition_variable.hpp>
|
||||||
|
@ -23,11 +23,13 @@ namespace ams::os {
|
|||||||
constexpr inline size_t MemoryBlockUnitSize = 0x200000;
|
constexpr inline size_t MemoryBlockUnitSize = 0x200000;
|
||||||
|
|
||||||
enum MemoryPermission {
|
enum MemoryPermission {
|
||||||
MemoryPermission_None = (0 << 0),
|
MemoryPermission_None = (0 << 0),
|
||||||
MemoryPermission_ReadOnly = (1 << 0),
|
MemoryPermission_ReadOnly = (1 << 0),
|
||||||
MemoryPermission_WriteOnly = (1 << 1),
|
MemoryPermission_WriteOnly = (1 << 1),
|
||||||
|
MemoryPermission_ExecuteOnly = (1 << 2),
|
||||||
|
|
||||||
MemoryPermission_ReadWrite = MemoryPermission_ReadOnly | MemoryPermission_WriteOnly,
|
MemoryPermission_ReadWrite = MemoryPermission_ReadOnly | MemoryPermission_WriteOnly,
|
||||||
|
MemoryPermission_ReadExecute = MemoryPermission_ReadOnly | MemoryPermission_ExecuteOnly,
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(ATMOSPHERE_OS_HORIZON)
|
#if defined(ATMOSPHERE_OS_HORIZON)
|
||||||
|
@ -0,0 +1,28 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere/os/os_native_handle.hpp>
|
||||||
|
#include <stratosphere/os/os_memory_common.hpp>
|
||||||
|
|
||||||
|
namespace ams::os {
|
||||||
|
|
||||||
|
Result MapProcessMemory(void **out, NativeHandle handle, u64 process_address, size_t process_size);
|
||||||
|
void UnmapProcessMemory(void *mapped_memory, NativeHandle handle, u64 process_address, size_t process_size);
|
||||||
|
|
||||||
|
Result SetProcessMemoryPermission(NativeHandle handle, u64 process_address, u64 process_size, MemoryPermission perm);
|
||||||
|
|
||||||
|
}
|
@ -46,10 +46,10 @@ namespace ams::os::impl {
|
|||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
uintptr_t AllocateSpace(size_t size) {
|
uintptr_t AllocateSpace(size_t size, size_t align_offset) {
|
||||||
/* Try to allocate a large-aligned space, if we can. */
|
/* Try to allocate a large-aligned space, if we can. */
|
||||||
if (size >= AslrSpaceLargeAlign) {
|
if (align_offset || size >= AslrSpaceLargeAlign) {
|
||||||
if (auto large_align = m_allocator.AllocateSpace(size, AslrSpaceLargeAlign, 0); large_align != 0) {
|
if (auto large_align = m_allocator.AllocateSpace(size, AslrSpaceLargeAlign, align_offset & (AslrSpaceLargeAlign - 1)); large_align != 0) {
|
||||||
return large_align;
|
return large_align;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -63,11 +63,11 @@ namespace ams::os::impl {
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<typename MapFunction, typename UnmapFunction>
|
template<typename MapFunction, typename UnmapFunction>
|
||||||
Result MapAtRandomAddress(uintptr_t *out, size_t size, MapFunction map_function, UnmapFunction unmap_function) {
|
Result MapAtRandomAddress(uintptr_t *out, MapFunction map_function, UnmapFunction unmap_function, size_t size, size_t align_offset) {
|
||||||
/* Try to map up to 64 times. */
|
/* Try to map up to 64 times. */
|
||||||
for (int i = 0; i < 64; ++i) {
|
for (int i = 0; i < 64; ++i) {
|
||||||
/* Reserve space to map the memory. */
|
/* Reserve space to map the memory. */
|
||||||
const uintptr_t map_address = this->AllocateSpace(size);
|
const uintptr_t map_address = this->AllocateSpace(size, align_offset);
|
||||||
if (map_address == 0) {
|
if (map_address == 0) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -59,7 +59,7 @@ namespace ams::os::impl {
|
|||||||
|
|
||||||
/* Map at a random address. */
|
/* Map at a random address. */
|
||||||
uintptr_t mapped_address;
|
uintptr_t mapped_address;
|
||||||
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address), size,
|
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address),
|
||||||
[handle, svc_perm](uintptr_t map_address, size_t map_size) -> Result {
|
[handle, svc_perm](uintptr_t map_address, size_t map_size) -> Result {
|
||||||
R_TRY_CATCH(svc::MapIoRegion(handle, map_address, map_size, svc_perm)) {
|
R_TRY_CATCH(svc::MapIoRegion(handle, map_address, map_size, svc_perm)) {
|
||||||
/* TODO: What's the correct result for these? */
|
/* TODO: What's the correct result for these? */
|
||||||
@ -73,7 +73,9 @@ namespace ams::os::impl {
|
|||||||
},
|
},
|
||||||
[handle](uintptr_t map_address, size_t map_size) -> void {
|
[handle](uintptr_t map_address, size_t map_size) -> void {
|
||||||
return IoRegionImpl::UnmapIoRegion(handle, reinterpret_cast<void *>(map_address), map_size);
|
return IoRegionImpl::UnmapIoRegion(handle, reinterpret_cast<void *>(map_address), map_size);
|
||||||
}
|
},
|
||||||
|
size,
|
||||||
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
/* Return the address we mapped at. */
|
/* Return the address we mapped at. */
|
||||||
|
29
libstratosphere/source/os/impl/os_process_memory_impl.hpp
Normal file
29
libstratosphere/source/os/impl/os_process_memory_impl.hpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
|
||||||
|
namespace ams::os::impl {
|
||||||
|
|
||||||
|
class ProcessMemoryImpl {
|
||||||
|
public:
|
||||||
|
static Result Map(void **out, NativeHandle handle, u64 process_address, size_t size);
|
||||||
|
static void Unmap(void *mapped_memory, NativeHandle handle, u64 process_address, size_t size);
|
||||||
|
|
||||||
|
static Result SetMemoryPermission(NativeHandle handle, u64 process_address, u64 size, MemoryPermission perm);
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "os_process_memory_impl.hpp"
|
||||||
|
#include "os_aslr_space_manager.hpp"
|
||||||
|
|
||||||
|
namespace ams::os::impl {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
svc::MemoryPermission ConvertToSvcMemoryPermission(os::MemoryPermission perm) {
|
||||||
|
switch (perm) {
|
||||||
|
case os::MemoryPermission_None: return svc::MemoryPermission_None;
|
||||||
|
case os::MemoryPermission_ReadOnly: return svc::MemoryPermission_Read;
|
||||||
|
case os::MemoryPermission_ReadWrite: return svc::MemoryPermission_ReadWrite;
|
||||||
|
case os::MemoryPermission_ReadExecute: return svc::MemoryPermission_ReadExecute;
|
||||||
|
AMS_UNREACHABLE_DEFAULT_CASE();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ProcessMemoryImpl::Map(void **out, NativeHandle handle, u64 process_address, size_t size) {
|
||||||
|
/* Map at a random address. */
|
||||||
|
uintptr_t mapped_address;
|
||||||
|
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address),
|
||||||
|
[handle, process_address](uintptr_t map_address, size_t map_size) -> Result {
|
||||||
|
R_TRY_CATCH(svc::MapProcessMemory(map_address, handle, process_address, map_size)) {
|
||||||
|
R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource())
|
||||||
|
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
||||||
|
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
},
|
||||||
|
[handle, process_address](uintptr_t map_address, size_t map_size) -> void {
|
||||||
|
return ProcessMemoryImpl::Unmap(reinterpret_cast<void *>(map_address), handle, process_address, map_size);
|
||||||
|
},
|
||||||
|
size,
|
||||||
|
process_address
|
||||||
|
));
|
||||||
|
|
||||||
|
/* Return the address we mapped at. */
|
||||||
|
*out = reinterpret_cast<void *>(mapped_address);
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ProcessMemoryImpl::Unmap(void *mapped_memory, NativeHandle handle, u64 process_address, size_t size) {
|
||||||
|
R_ABORT_UNLESS(svc::UnmapProcessMemory(reinterpret_cast<uintptr_t>(mapped_memory), handle, process_address, size));
|
||||||
|
}
|
||||||
|
|
||||||
|
Result ProcessMemoryImpl::SetMemoryPermission(NativeHandle handle, u64 process_address, u64 size, MemoryPermission perm) {
|
||||||
|
/* Set the process memory permission. */
|
||||||
|
R_TRY_CATCH(svc::SetProcessMemoryPermission(handle, process_address, size, ConvertToSvcMemoryPermission(perm))) {
|
||||||
|
R_CONVERT(svc::ResultOutOfResource, os::ResultOutOfResource())
|
||||||
|
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
||||||
|
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||||
|
|
||||||
|
R_SUCCEED();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -59,7 +59,7 @@ namespace ams::os::impl {
|
|||||||
|
|
||||||
/* Map at a random address. */
|
/* Map at a random address. */
|
||||||
uintptr_t mapped_address;
|
uintptr_t mapped_address;
|
||||||
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address), size,
|
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address),
|
||||||
[handle, svc_perm](uintptr_t map_address, size_t map_size) -> Result {
|
[handle, svc_perm](uintptr_t map_address, size_t map_size) -> Result {
|
||||||
R_TRY_CATCH(svc::MapSharedMemory(handle, map_address, map_size, svc_perm)) {
|
R_TRY_CATCH(svc::MapSharedMemory(handle, map_address, map_size, svc_perm)) {
|
||||||
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
R_CONVERT(svc::ResultInvalidCurrentMemory, os::ResultInvalidCurrentMemoryState())
|
||||||
@ -69,7 +69,9 @@ namespace ams::os::impl {
|
|||||||
},
|
},
|
||||||
[handle](uintptr_t map_address, size_t map_size) -> void {
|
[handle](uintptr_t map_address, size_t map_size) -> void {
|
||||||
return SharedMemoryImpl::Unmap(handle, reinterpret_cast<void *>(map_address), map_size);
|
return SharedMemoryImpl::Unmap(handle, reinterpret_cast<void *>(map_address), map_size);
|
||||||
}
|
},
|
||||||
|
size,
|
||||||
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
/* Return the address we mapped at. */
|
/* Return the address we mapped at. */
|
||||||
|
@ -58,7 +58,7 @@ namespace ams::os::impl {
|
|||||||
|
|
||||||
/* Map at a random address. */
|
/* Map at a random address. */
|
||||||
uintptr_t mapped_address;
|
uintptr_t mapped_address;
|
||||||
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address), size,
|
R_TRY(impl::GetAslrSpaceManager().MapAtRandomAddress(std::addressof(mapped_address),
|
||||||
[handle, svc_owner_perm](uintptr_t map_address, size_t map_size) -> Result {
|
[handle, svc_owner_perm](uintptr_t map_address, size_t map_size) -> Result {
|
||||||
R_TRY_CATCH(svc::MapTransferMemory(handle, map_address, map_size, svc_owner_perm)) {
|
R_TRY_CATCH(svc::MapTransferMemory(handle, map_address, map_size, svc_owner_perm)) {
|
||||||
R_CONVERT(svc::ResultInvalidHandle, os::ResultInvalidHandle())
|
R_CONVERT(svc::ResultInvalidHandle, os::ResultInvalidHandle())
|
||||||
@ -71,7 +71,9 @@ namespace ams::os::impl {
|
|||||||
},
|
},
|
||||||
[handle](uintptr_t map_address, size_t map_size) -> void {
|
[handle](uintptr_t map_address, size_t map_size) -> void {
|
||||||
return TransferMemoryImpl::Unmap(handle, reinterpret_cast<void *>(map_address), map_size);
|
return TransferMemoryImpl::Unmap(handle, reinterpret_cast<void *>(map_address), map_size);
|
||||||
}
|
},
|
||||||
|
size,
|
||||||
|
0
|
||||||
));
|
));
|
||||||
|
|
||||||
/* Return the address we mapped at. */
|
/* Return the address we mapped at. */
|
||||||
|
33
libstratosphere/source/os/os_process_memory.cpp
Normal file
33
libstratosphere/source/os/os_process_memory.cpp
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) Atmosphère-NX
|
||||||
|
*
|
||||||
|
* This program is free software; you can redistribute it and/or modify it
|
||||||
|
* under the terms and conditions of the GNU General Public License,
|
||||||
|
* version 2, as published by the Free Software Foundation.
|
||||||
|
*
|
||||||
|
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||||
|
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||||
|
* more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
#include <stratosphere.hpp>
|
||||||
|
#include "impl/os_process_memory_impl.hpp"
|
||||||
|
|
||||||
|
namespace ams::os {
|
||||||
|
|
||||||
|
Result MapProcessMemory(void **out, NativeHandle handle, u64 process_address, size_t process_size) {
|
||||||
|
R_RETURN(::ams::os::impl::ProcessMemoryImpl::Map(out, handle, process_address, process_size));
|
||||||
|
}
|
||||||
|
|
||||||
|
void UnmapProcessMemory(void *mapped_memory, NativeHandle handle, u64 process_address, size_t process_size) {
|
||||||
|
return ::ams::os::impl::ProcessMemoryImpl::Unmap(mapped_memory, handle, process_address, process_size);
|
||||||
|
}
|
||||||
|
|
||||||
|
Result SetProcessMemoryPermission(NativeHandle handle, u64 process_address, u64 process_size, MemoryPermission perm) {
|
||||||
|
R_RETURN(::ams::os::impl::ProcessMemoryImpl::SetMemoryPermission(handle, process_address, process_size, perm));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user