mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-12-22 20:31:14 +00:00
strat: use svc:: over ::svc
This commit is contained in:
parent
77fe5cf6f5
commit
6f680fe63b
47 changed files with 557 additions and 563 deletions
|
@ -22,7 +22,7 @@ namespace ams::fssystem {
|
||||||
|
|
||||||
fs::fsa::IFileSystem *GetExternalCodeFileSystem(ncm::ProgramId program_id);
|
fs::fsa::IFileSystem *GetExternalCodeFileSystem(ncm::ProgramId program_id);
|
||||||
|
|
||||||
Result CreateExternalCode(Handle *out, ncm::ProgramId program_id);
|
Result CreateExternalCode(os::NativeHandle *out, ncm::ProgramId program_id);
|
||||||
void DestroyExternalCode(ncm::ProgramId program_id);
|
void DestroyExternalCode(ncm::ProgramId program_id);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -152,7 +152,7 @@ namespace ams::fssystem {
|
||||||
NX_INLINE Result RetryFinitelyForTargetLocked(F f) {
|
NX_INLINE Result RetryFinitelyForTargetLocked(F f) {
|
||||||
/* Retry up to 10 times, 100ms between retries. */
|
/* Retry up to 10 times, 100ms between retries. */
|
||||||
constexpr s32 MaxRetryCount = 10;
|
constexpr s32 MaxRetryCount = 10;
|
||||||
constexpr u64 RetryWaitTime = 100'000'000ul;
|
constexpr TimeSpan RetryWaitTime = TimeSpan::FromMilliSeconds(100);
|
||||||
|
|
||||||
s32 remaining_retries = MaxRetryCount;
|
s32 remaining_retries = MaxRetryCount;
|
||||||
while (true) {
|
while (true) {
|
||||||
|
@ -161,7 +161,7 @@ namespace ams::fssystem {
|
||||||
R_UNLESS(remaining_retries > 0, fs::ResultTargetLocked());
|
R_UNLESS(remaining_retries > 0, fs::ResultTargetLocked());
|
||||||
|
|
||||||
remaining_retries--;
|
remaining_retries--;
|
||||||
svcSleepThread(RetryWaitTime);
|
os::SleepThread(RetryWaitTime);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
} R_END_TRY_CATCH;
|
} R_END_TRY_CATCH;
|
||||||
|
|
|
@ -20,9 +20,9 @@
|
||||||
namespace ams::map {
|
namespace ams::map {
|
||||||
|
|
||||||
/* Public API. */
|
/* Public API. */
|
||||||
Result GetProcessAddressSpaceInfo(AddressSpaceInfo *out, Handle process_h);
|
Result GetProcessAddressSpaceInfo(AddressSpaceInfo *out, os::NativeHandle process_h);
|
||||||
Result LocateMappableSpace(uintptr_t *out_address, size_t size);
|
Result LocateMappableSpace(uintptr_t *out_address, size_t size);
|
||||||
Result MapCodeMemoryInProcess(MappedCodeMemory &out_mcm, Handle process_handle, uintptr_t base_address, size_t size);
|
Result MapCodeMemoryInProcess(MappedCodeMemory &out_mcm, os::NativeHandle process_handle, uintptr_t base_address, size_t size);
|
||||||
bool CanAddGuardRegionsInProcess(Handle process_handle, uintptr_t address, size_t size);
|
bool CanAddGuardRegionsInProcess(os::NativeHandle process_handle, uintptr_t address, size_t size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
#include <vapours.hpp>
|
#include <vapours.hpp>
|
||||||
|
#include <stratosphere/os/os_native_handle.hpp>
|
||||||
|
|
||||||
namespace ams::map {
|
namespace ams::map {
|
||||||
|
|
||||||
|
@ -41,19 +42,19 @@ namespace ams::map {
|
||||||
|
|
||||||
class AutoCloseMap {
|
class AutoCloseMap {
|
||||||
private:
|
private:
|
||||||
Handle process_handle;
|
os::NativeHandle process_handle;
|
||||||
Result result;
|
Result result;
|
||||||
void *mapped_address;
|
uintptr_t mapped_address;
|
||||||
uintptr_t base_address;
|
uintptr_t base_address;
|
||||||
size_t size;
|
size_t size;
|
||||||
public:
|
public:
|
||||||
AutoCloseMap(uintptr_t mp, Handle p_h, uintptr_t ba, size_t sz) : process_handle(p_h), mapped_address(reinterpret_cast<void *>(mp)), base_address(ba), size(sz) {
|
AutoCloseMap(uintptr_t mp, os::NativeHandle p_h, uintptr_t ba, size_t sz) : process_handle(p_h), mapped_address(mp), base_address(ba), size(sz) {
|
||||||
this->result = svcMapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size);
|
this->result = svc::MapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
~AutoCloseMap() {
|
~AutoCloseMap() {
|
||||||
if (this->process_handle != INVALID_HANDLE && R_SUCCEEDED(this->result)) {
|
if (this->process_handle != os::InvalidNativeHandle && R_SUCCEEDED(this->result)) {
|
||||||
R_ABORT_UNLESS(svcUnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size));
|
R_ABORT_UNLESS(svc::UnmapProcessMemory(this->mapped_address, this->process_handle, this->base_address, this->size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -66,7 +67,7 @@ namespace ams::map {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Invalidate() {
|
void Invalidate() {
|
||||||
this->process_handle = INVALID_HANDLE;
|
this->process_handle = os::InvalidNativeHandle;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -78,17 +79,17 @@ namespace ams::map {
|
||||||
uintptr_t src_address;
|
uintptr_t src_address;
|
||||||
size_t size;
|
size_t size;
|
||||||
public:
|
public:
|
||||||
MappedCodeMemory(Result init_res) : process_handle(INVALID_HANDLE), result(init_res), dst_address(0), src_address(0), size(0) {
|
MappedCodeMemory(Result init_res) : process_handle(os::InvalidNativeHandle), result(init_res), dst_address(0), src_address(0), size(0) {
|
||||||
/* ... */
|
/* ... */
|
||||||
}
|
}
|
||||||
|
|
||||||
MappedCodeMemory(Handle p_h, uintptr_t dst, uintptr_t src, size_t sz) : process_handle(p_h), dst_address(dst), src_address(src), size(sz) {
|
MappedCodeMemory(Handle p_h, uintptr_t dst, uintptr_t src, size_t sz) : process_handle(p_h), dst_address(dst), src_address(src), size(sz) {
|
||||||
this->result = svcMapProcessCodeMemory(this->process_handle, this->dst_address, this->src_address, this->size);
|
this->result = svc::MapProcessCodeMemory(this->process_handle, this->dst_address, this->src_address, this->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
~MappedCodeMemory() {
|
~MappedCodeMemory() {
|
||||||
if (this->process_handle != INVALID_HANDLE && R_SUCCEEDED(this->result) && this->size > 0) {
|
if (this->process_handle != os::InvalidNativeHandle && R_SUCCEEDED(this->result) && this->size > 0) {
|
||||||
R_ABORT_UNLESS(svcUnmapProcessCodeMemory(this->process_handle, this->dst_address, this->src_address, this->size));
|
R_ABORT_UNLESS(svc::UnmapProcessCodeMemory(this->process_handle, this->dst_address, this->src_address, this->size));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,7 +106,7 @@ namespace ams::map {
|
||||||
}
|
}
|
||||||
|
|
||||||
void Invalidate() {
|
void Invalidate() {
|
||||||
this->process_handle = INVALID_HANDLE;
|
this->process_handle = os::InvalidNativeHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
MappedCodeMemory &operator=(MappedCodeMemory &&o) {
|
MappedCodeMemory &operator=(MappedCodeMemory &&o) {
|
||||||
|
|
|
@ -26,8 +26,8 @@ namespace ams::pm::dmnt {
|
||||||
Result StartProcess(os::ProcessId process_id);
|
Result StartProcess(os::ProcessId process_id);
|
||||||
Result GetProcessId(os::ProcessId *out_process_id, const ncm::ProgramId program_id);
|
Result GetProcessId(os::ProcessId *out_process_id, const ncm::ProgramId program_id);
|
||||||
Result GetApplicationProcessId(os::ProcessId *out_process_id);
|
Result GetApplicationProcessId(os::ProcessId *out_process_id);
|
||||||
Result HookToCreateApplicationProcess(Handle *out_handle);
|
Result HookToCreateApplicationProcess(os::NativeHandle *out_handle);
|
||||||
Result AtmosphereGetProcessInfo(Handle *out_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id);
|
Result AtmosphereGetProcessInfo(os::NativeHandle *out_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id);
|
||||||
Result AtmosphereGetCurrentLimitInfo(u64 *out_current_value, u64 *out_limit_value, ResourceLimitGroup group, LimitableResource resource);
|
Result AtmosphereGetCurrentLimitInfo(u64 *out_current_value, u64 *out_limit_value, ResourceLimitGroup group, LimitableResource resource);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -28,13 +28,13 @@ namespace ams::sf::hipc {
|
||||||
NeedsRetry,
|
NeedsRetry,
|
||||||
};
|
};
|
||||||
|
|
||||||
void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, Handle port);
|
void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, os::NativeHandle port);
|
||||||
void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, Handle request);
|
void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, os::NativeHandle request);
|
||||||
|
|
||||||
Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer);
|
Result Receive(ReceiveResult *out_recv_result, os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer);
|
||||||
Result Receive(bool *out_closed, Handle session_handle, const cmif::PointerAndSize &message_buffer);
|
Result Receive(bool *out_closed, os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer);
|
||||||
Result Reply(Handle session_handle, const cmif::PointerAndSize &message_buffer);
|
Result Reply(os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer);
|
||||||
|
|
||||||
Result CreateSession(Handle *out_server_handle, Handle *out_client_handle);
|
Result CreateSession(os::NativeHandle *out_server_handle, os::NativeHandle *out_client_handle);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,11 +49,11 @@ namespace ams::sf::hipc {
|
||||||
cmif::PointerAndSize pointer_buffer;
|
cmif::PointerAndSize pointer_buffer;
|
||||||
cmif::PointerAndSize saved_message;
|
cmif::PointerAndSize saved_message;
|
||||||
std::shared_ptr<::Service> forward_service;
|
std::shared_ptr<::Service> forward_service;
|
||||||
Handle session_handle;
|
os::NativeHandle session_handle;
|
||||||
bool is_closed;
|
bool is_closed;
|
||||||
bool has_received;
|
bool has_received;
|
||||||
public:
|
public:
|
||||||
ServerSession(Handle h, cmif::ServiceObjectHolder &&obj) : srv_obj_holder(std::move(obj)), session_handle(h) {
|
ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj) : srv_obj_holder(std::move(obj)), session_handle(h) {
|
||||||
hipc::AttachMultiWaitHolderForReply(this, h);
|
hipc::AttachMultiWaitHolderForReply(this, h);
|
||||||
this->is_closed = false;
|
this->is_closed = false;
|
||||||
this->has_received = false;
|
this->has_received = false;
|
||||||
|
@ -61,7 +61,7 @@ namespace ams::sf::hipc {
|
||||||
AMS_ABORT_UNLESS(!this->IsMitmSession());
|
AMS_ABORT_UNLESS(!this->IsMitmSession());
|
||||||
}
|
}
|
||||||
|
|
||||||
ServerSession(Handle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : srv_obj_holder(std::move(obj)), session_handle(h) {
|
ServerSession(os::NativeHandle h, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) : srv_obj_holder(std::move(obj)), session_handle(h) {
|
||||||
hipc::AttachMultiWaitHolderForReply(this, h);
|
hipc::AttachMultiWaitHolderForReply(this, h);
|
||||||
this->is_closed = false;
|
this->is_closed = false;
|
||||||
this->has_received = false;
|
this->has_received = false;
|
||||||
|
@ -117,55 +117,55 @@ namespace ams::sf::hipc {
|
||||||
|
|
||||||
Result ReceiveRequestImpl(ServerSession *session, const cmif::PointerAndSize &message);
|
Result ReceiveRequestImpl(ServerSession *session, const cmif::PointerAndSize &message);
|
||||||
void CloseSessionImpl(ServerSession *session);
|
void CloseSessionImpl(ServerSession *session);
|
||||||
Result RegisterSessionImpl(ServerSession *session_memory, Handle session_handle, cmif::ServiceObjectHolder &&obj);
|
Result RegisterSessionImpl(ServerSession *session_memory, os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj);
|
||||||
Result AcceptSessionImpl(ServerSession *session_memory, Handle port_handle, cmif::ServiceObjectHolder &&obj);
|
Result AcceptSessionImpl(ServerSession *session_memory, os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj);
|
||||||
Result RegisterMitmSessionImpl(ServerSession *session_memory, Handle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
Result RegisterMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||||
Result AcceptMitmSessionImpl(ServerSession *session_memory, Handle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
Result AcceptMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||||
|
|
||||||
Result ReceiveRequest(ServerSession *session, const cmif::PointerAndSize &message) {
|
Result ReceiveRequest(ServerSession *session, const cmif::PointerAndSize &message) {
|
||||||
return this->ReceiveRequestImpl(session, message);
|
return this->ReceiveRequestImpl(session, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result RegisterSession(ServerSession **out, Handle session_handle, cmif::ServiceObjectHolder &&obj) {
|
Result RegisterSession(ServerSession **out, os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj) {
|
||||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||||
return this->RegisterSessionImpl(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
return this->RegisterSessionImpl(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
||||||
};
|
};
|
||||||
return this->CreateSessionImpl(out, ctor);
|
return this->CreateSessionImpl(out, ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AcceptSession(ServerSession **out, Handle port_handle, cmif::ServiceObjectHolder &&obj) {
|
Result AcceptSession(ServerSession **out, os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj) {
|
||||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||||
return this->AcceptSessionImpl(session_memory, port_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
return this->AcceptSessionImpl(session_memory, port_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
||||||
};
|
};
|
||||||
return this->CreateSessionImpl(out, ctor);
|
return this->CreateSessionImpl(out, ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result RegisterMitmSession(ServerSession **out, Handle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
Result RegisterMitmSession(ServerSession **out, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||||
return this->RegisterMitmSessionImpl(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
return this->RegisterMitmSessionImpl(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||||
};
|
};
|
||||||
return this->CreateSessionImpl(out, ctor);
|
return this->CreateSessionImpl(out, ctor);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AcceptMitmSession(ServerSession **out, Handle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
Result AcceptMitmSession(ServerSession **out, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||||
auto ctor = [&](ServerSession *session_memory) -> Result {
|
auto ctor = [&](ServerSession *session_memory) -> Result {
|
||||||
return this->AcceptMitmSessionImpl(session_memory, mitm_port_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
return this->AcceptMitmSessionImpl(session_memory, mitm_port_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||||
};
|
};
|
||||||
return this->CreateSessionImpl(out, ctor);
|
return this->CreateSessionImpl(out, ctor);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
Result RegisterSession(Handle session_handle, cmif::ServiceObjectHolder &&obj);
|
Result RegisterSession(os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj);
|
||||||
Result AcceptSession(Handle port_handle, cmif::ServiceObjectHolder &&obj);
|
Result AcceptSession(os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj);
|
||||||
Result RegisterMitmSession(Handle session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
Result RegisterMitmSession(os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||||
Result AcceptMitmSession(Handle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
Result AcceptMitmSession(os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv);
|
||||||
|
|
||||||
template<typename Interface>
|
template<typename Interface>
|
||||||
Result AcceptSession(Handle port_handle, SharedPointer<Interface> obj) {
|
Result AcceptSession(os::NativeHandle port_handle, SharedPointer<Interface> obj) {
|
||||||
return this->AcceptSession(port_handle, cmif::ServiceObjectHolder(std::move(obj)));
|
return this->AcceptSession(port_handle, cmif::ServiceObjectHolder(std::move(obj)));
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename Interface>
|
template<typename Interface>
|
||||||
Result AcceptMitmSession(Handle mitm_port_handle, SharedPointer<Interface> obj, std::shared_ptr<::Service> &&fsrv) {
|
Result AcceptMitmSession(os::NativeHandle mitm_port_handle, SharedPointer<Interface> obj, std::shared_ptr<::Service> &&fsrv) {
|
||||||
return this->AcceptMitmSession(mitm_port_handle, cmif::ServiceObjectHolder(std::move(obj)), std::forward<std::shared_ptr<::Service>>(fsrv));
|
return this->AcceptMitmSession(mitm_port_handle, cmif::ServiceObjectHolder(std::move(obj)), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -837,12 +837,12 @@ namespace ams::sf::impl {
|
||||||
private:
|
private:
|
||||||
template<size_t Index>
|
template<size_t Index>
|
||||||
NX_CONSTEXPR void SetOutObjectImpl(const HipcRequest &response, hipc::ServerSessionManager *manager, cmif::ServiceObjectHolder &&object) {
|
NX_CONSTEXPR void SetOutObjectImpl(const HipcRequest &response, hipc::ServerSessionManager *manager, cmif::ServiceObjectHolder &&object) {
|
||||||
/* If no object, write INVALID_HANDLE. This is what official software does. */
|
/* If no object, write os::InvalidNativeHandle. This is what official software does. */
|
||||||
if (!object) {
|
if (!object) {
|
||||||
response.move_handles[Index] = INVALID_HANDLE;
|
response.move_handles[Index] = os::InvalidNativeHandle;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
Handle server_handle, client_handle;
|
os::NativeHandle server_handle, client_handle;
|
||||||
R_ABORT_UNLESS(sf::hipc::CreateSession(&server_handle, &client_handle));
|
R_ABORT_UNLESS(sf::hipc::CreateSession(&server_handle, &client_handle));
|
||||||
R_ABORT_UNLESS(manager->RegisterSession(server_handle, std::move(object)));
|
R_ABORT_UNLESS(manager->RegisterSession(server_handle, std::move(object)));
|
||||||
response.move_handles[Index] = client_handle;
|
response.move_handles[Index] = client_handle;
|
||||||
|
|
|
@ -28,17 +28,17 @@ namespace ams::sf {
|
||||||
|
|
||||||
template<u32 Attribute>
|
template<u32 Attribute>
|
||||||
struct InHandle : public InHandleTag {
|
struct InHandle : public InHandleTag {
|
||||||
::Handle handle;
|
os::NativeHandle handle;
|
||||||
|
|
||||||
constexpr InHandle() : handle(INVALID_HANDLE) { /* ... */ }
|
constexpr InHandle() : handle(os::InvalidNativeHandle) { /* ... */ }
|
||||||
constexpr InHandle(::Handle h) : handle(h) { /* ... */ }
|
constexpr InHandle(os::NativeHandle h) : handle(h) { /* ... */ }
|
||||||
constexpr InHandle(const InHandle &o) : handle(o.handle) { /* ... */ }
|
constexpr InHandle(const InHandle &o) : handle(o.handle) { /* ... */ }
|
||||||
|
|
||||||
constexpr void operator=(const ::Handle &h) { this->handle = h; }
|
constexpr void operator=(const os::NativeHandle &h) { this->handle = h; }
|
||||||
constexpr void operator=(const InHandle &o) { this->handle = o.handle; }
|
constexpr void operator=(const InHandle &o) { this->handle = o.handle; }
|
||||||
|
|
||||||
constexpr /* TODO: explicit? */ operator ::Handle() const { return this->handle; }
|
constexpr /* TODO: explicit? */ operator os::NativeHandle() const { return this->handle; }
|
||||||
constexpr ::Handle GetValue() const { return this->handle; }
|
constexpr os::NativeHandle GetValue() const { return this->handle; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -49,7 +49,7 @@ namespace ams::sf {
|
||||||
public:
|
public:
|
||||||
constexpr OutHandleImpl(T *p) : ptr(p) { /* ... */ }
|
constexpr OutHandleImpl(T *p) : ptr(p) { /* ... */ }
|
||||||
|
|
||||||
constexpr void SetValue(const Handle &value) {
|
constexpr void SetValue(const os::NativeHandle &value) {
|
||||||
*this->ptr = value;
|
*this->ptr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ namespace ams::sf {
|
||||||
return this->ptr;
|
return this->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Handle *GetHandlePointer() const {
|
constexpr os::NativeHandle *GetHandlePointer() const {
|
||||||
return &this->ptr->handle;
|
return &this->ptr->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -83,8 +83,8 @@ namespace ams::sf {
|
||||||
using MoveHandle = typename impl::InHandle<SfOutHandleAttr_HipcMove>;
|
using MoveHandle = typename impl::InHandle<SfOutHandleAttr_HipcMove>;
|
||||||
using CopyHandle = typename impl::InHandle<SfOutHandleAttr_HipcCopy>;
|
using CopyHandle = typename impl::InHandle<SfOutHandleAttr_HipcCopy>;
|
||||||
|
|
||||||
static_assert(sizeof(MoveHandle) == sizeof(::Handle), "sizeof(MoveHandle)");
|
static_assert(sizeof(MoveHandle) == sizeof(os::NativeHandle), "sizeof(MoveHandle)");
|
||||||
static_assert(sizeof(CopyHandle) == sizeof(::Handle), "sizeof(CopyHandle)");
|
static_assert(sizeof(CopyHandle) == sizeof(os::NativeHandle), "sizeof(CopyHandle)");
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
class IsOutForceEnabled<MoveHandle> : public std::true_type{};
|
class IsOutForceEnabled<MoveHandle> : public std::true_type{};
|
||||||
|
@ -99,7 +99,7 @@ namespace ams::sf {
|
||||||
public:
|
public:
|
||||||
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
||||||
|
|
||||||
constexpr void SetValue(const Handle &value) {
|
constexpr void SetValue(const os::NativeHandle &value) {
|
||||||
Base::SetValue(value);
|
Base::SetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,7 +115,7 @@ namespace ams::sf {
|
||||||
return Base::GetPointer();
|
return Base::GetPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Handle *GetHandlePointer() const {
|
constexpr os::NativeHandle *GetHandlePointer() const {
|
||||||
return Base::GetHandlePointer();
|
return Base::GetHandlePointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -139,7 +139,7 @@ namespace ams::sf {
|
||||||
constexpr Out<T>(T *p) : Base(p), m_managed(nullptr) { /* ... */ }
|
constexpr Out<T>(T *p) : Base(p), m_managed(nullptr) { /* ... */ }
|
||||||
constexpr Out<T>(T *p, bool *m) : Base(p), m_managed(m) { /* ... */ }
|
constexpr Out<T>(T *p, bool *m) : Base(p), m_managed(m) { /* ... */ }
|
||||||
|
|
||||||
constexpr void SetValue(const Handle &value) {
|
constexpr void SetValue(const os::NativeHandle &value) {
|
||||||
Base::SetValue(value);
|
Base::SetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -160,7 +160,7 @@ namespace ams::sf {
|
||||||
return Base::GetPointer();
|
return Base::GetPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Handle *GetHandlePointer() const {
|
constexpr os::NativeHandle *GetHandlePointer() const {
|
||||||
return Base::GetHandlePointer();
|
return Base::GetHandlePointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -390,6 +390,10 @@
|
||||||
return ::svcContinueDebugEvent(debug_handle, flags, const_cast<u64 *>(thread_ids.GetPointerUnsafe()), num_thread_ids);
|
return ::svcContinueDebugEvent(debug_handle, flags, const_cast<u64 *>(thread_ids.GetPointerUnsafe()), num_thread_ids);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ALWAYS_INLINE Result LegacyContinueDebugEvent(::ams::svc::Handle debug_handle, uint32_t flags, uint64_t thread_id) {
|
||||||
|
return ::svcLegacyContinueDebugEvent(debug_handle, flags, thread_id);
|
||||||
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE Result GetProcessList(int32_t *out_num_processes, ::ams::svc::UserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {
|
ALWAYS_INLINE Result GetProcessList(int32_t *out_num_processes, ::ams::svc::UserPointer<uint64_t *> out_process_ids, int32_t max_out_count) {
|
||||||
return ::svcGetProcessList(out_num_processes, out_process_ids.GetPointerUnsafe(), max_out_count);
|
return ::svcGetProcessList(out_num_processes, out_process_ids.GetPointerUnsafe(), max_out_count);
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,17 +27,17 @@ namespace ams::tipc {
|
||||||
|
|
||||||
template<u32 Attribute>
|
template<u32 Attribute>
|
||||||
struct InHandle : public InHandleTag {
|
struct InHandle : public InHandleTag {
|
||||||
::Handle handle;
|
os::NativeHandle handle;
|
||||||
|
|
||||||
constexpr InHandle() : handle(INVALID_HANDLE) { /* ... */ }
|
constexpr InHandle() : handle(os::InvalidNativeHandle) { /* ... */ }
|
||||||
constexpr InHandle(::Handle h) : handle(h) { /* ... */ }
|
constexpr InHandle(os::NativeHandle h) : handle(h) { /* ... */ }
|
||||||
constexpr InHandle(const InHandle &o) : handle(o.handle) { /* ... */ }
|
constexpr InHandle(const InHandle &o) : handle(o.handle) { /* ... */ }
|
||||||
|
|
||||||
constexpr void operator=(const ::Handle &h) { this->handle = h; }
|
constexpr void operator=(const os::NativeHandle &h) { this->handle = h; }
|
||||||
constexpr void operator=(const InHandle &o) { this->handle = o.handle; }
|
constexpr void operator=(const InHandle &o) { this->handle = o.handle; }
|
||||||
|
|
||||||
constexpr /* TODO: explicit? */ operator ::Handle() const { return this->handle; }
|
constexpr /* TODO: explicit? */ operator os::NativeHandle() const { return this->handle; }
|
||||||
constexpr ::Handle GetValue() const { return this->handle; }
|
constexpr os::NativeHandle GetValue() const { return this->handle; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
@ -48,7 +48,7 @@ namespace ams::tipc {
|
||||||
public:
|
public:
|
||||||
constexpr OutHandleImpl(T *p) : ptr(p) { /* ... */ }
|
constexpr OutHandleImpl(T *p) : ptr(p) { /* ... */ }
|
||||||
|
|
||||||
constexpr void SetValue(const Handle &value) {
|
constexpr void SetValue(const os::NativeHandle &value) {
|
||||||
*this->ptr = value;
|
*this->ptr = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -64,7 +64,7 @@ namespace ams::tipc {
|
||||||
return this->ptr;
|
return this->ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Handle *GetHandlePointer() const {
|
constexpr os::NativeHandle *GetHandlePointer() const {
|
||||||
return &this->ptr->handle;
|
return &this->ptr->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -82,8 +82,8 @@ namespace ams::tipc {
|
||||||
using MoveHandle = typename impl::InHandle<SfOutHandleAttr_HipcMove>;
|
using MoveHandle = typename impl::InHandle<SfOutHandleAttr_HipcMove>;
|
||||||
using CopyHandle = typename impl::InHandle<SfOutHandleAttr_HipcCopy>;
|
using CopyHandle = typename impl::InHandle<SfOutHandleAttr_HipcCopy>;
|
||||||
|
|
||||||
static_assert(sizeof(MoveHandle) == sizeof(::Handle), "sizeof(MoveHandle)");
|
static_assert(sizeof(MoveHandle) == sizeof(os::NativeHandle), "sizeof(MoveHandle)");
|
||||||
static_assert(sizeof(CopyHandle) == sizeof(::Handle), "sizeof(CopyHandle)");
|
static_assert(sizeof(CopyHandle) == sizeof(os::NativeHandle), "sizeof(CopyHandle)");
|
||||||
|
|
||||||
template<>
|
template<>
|
||||||
class IsOutForceEnabled<MoveHandle> : public std::true_type{};
|
class IsOutForceEnabled<MoveHandle> : public std::true_type{};
|
||||||
|
@ -98,7 +98,7 @@ namespace ams::tipc {
|
||||||
public:
|
public:
|
||||||
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
||||||
|
|
||||||
constexpr void SetValue(const Handle &value) {
|
constexpr void SetValue(const os::NativeHandle &value) {
|
||||||
Base::SetValue(value);
|
Base::SetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ namespace ams::tipc {
|
||||||
return Base::GetPointer();
|
return Base::GetPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Handle *GetHandlePointer() const {
|
constexpr os::NativeHandle *GetHandlePointer() const {
|
||||||
return Base::GetHandlePointer();
|
return Base::GetHandlePointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ namespace ams::tipc {
|
||||||
public:
|
public:
|
||||||
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
constexpr Out<T>(T *p) : Base(p) { /* ... */ }
|
||||||
|
|
||||||
constexpr void SetValue(const Handle &value) {
|
constexpr void SetValue(const os::NativeHandle &value) {
|
||||||
Base::SetValue(value);
|
Base::SetValue(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -151,7 +151,7 @@ namespace ams::tipc {
|
||||||
return Base::GetPointer();
|
return Base::GetPointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr Handle *GetHandlePointer() const {
|
constexpr os::NativeHandle *GetHandlePointer() const {
|
||||||
return Base::GetHandlePointer();
|
return Base::GetHandlePointer();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -141,7 +141,7 @@ namespace ams {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Grab 0x100 of tls. */
|
/* Grab 0x100 of tls. */
|
||||||
std::memcpy(ams_ctx.tls, armGetTls(), sizeof(ams_ctx.tls));
|
std::memcpy(ams_ctx.tls, svc::GetThreadLocalRegion(), sizeof(ams_ctx.tls));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Just call the user exception handler. */
|
/* Just call the user exception handler. */
|
||||||
|
|
|
@ -52,10 +52,10 @@ namespace ams::fssystem {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CreateExternalCode(Handle *out, ncm::ProgramId program_id) {
|
Result CreateExternalCode(os::NativeHandle *out, ncm::ProgramId program_id) {
|
||||||
/* Create a handle pair. */
|
/* Create a handle pair. */
|
||||||
Handle server, client;
|
os::NativeHandle server, client;
|
||||||
R_TRY(svcCreateSession(std::addressof(server), std::addressof(client), false, 0));
|
R_TRY(svc::CreateSession(std::addressof(server), std::addressof(client), false, 0));
|
||||||
|
|
||||||
/* Insert the handle into the map. */
|
/* Insert the handle into the map. */
|
||||||
g_hnd_map.Emplace(program_id, client);
|
g_hnd_map.Emplace(program_id, client);
|
||||||
|
|
|
@ -25,8 +25,8 @@ namespace ams::map {
|
||||||
|
|
||||||
/* Deprecated/Modern implementations. */
|
/* Deprecated/Modern implementations. */
|
||||||
Result LocateMappableSpaceDeprecated(uintptr_t *out_address, size_t size) {
|
Result LocateMappableSpaceDeprecated(uintptr_t *out_address, size_t size) {
|
||||||
MemoryInfo mem_info = {};
|
svc::MemoryInfo mem_info;
|
||||||
u32 page_info = 0;
|
svc::PageInfo page_info;
|
||||||
uintptr_t cur_base = 0;
|
uintptr_t cur_base = 0;
|
||||||
|
|
||||||
AddressSpaceInfo address_space;
|
AddressSpaceInfo address_space;
|
||||||
|
@ -34,15 +34,15 @@ namespace ams::map {
|
||||||
cur_base = address_space.aslr_base;
|
cur_base = address_space.aslr_base;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
R_TRY(svcQueryMemory(&mem_info, &page_info, cur_base));
|
R_TRY(svc::QueryMemory(&mem_info, &page_info, cur_base));
|
||||||
|
|
||||||
if (mem_info.type == MemType_Unmapped && mem_info.addr - cur_base + mem_info.size >= size) {
|
if (mem_info.state == svc::MemoryState_Free && mem_info.addr - cur_base + mem_info.size >= size) {
|
||||||
*out_address = cur_base;
|
*out_address = cur_base;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
const uintptr_t mem_end = mem_info.addr + mem_info.size;
|
const uintptr_t mem_end = mem_info.addr + mem_info.size;
|
||||||
R_UNLESS(mem_info.type != MemType_Reserved, svc::ResultOutOfMemory());
|
R_UNLESS(mem_info.state != svc::MemoryState_Inaccessible, svc::ResultOutOfMemory());
|
||||||
R_UNLESS(cur_base <= mem_end, svc::ResultOutOfMemory());
|
R_UNLESS(cur_base <= mem_end, svc::ResultOutOfMemory());
|
||||||
R_UNLESS(mem_end <= static_cast<uintptr_t>(std::numeric_limits<s32>::max()), svc::ResultOutOfMemory());
|
R_UNLESS(mem_end <= static_cast<uintptr_t>(std::numeric_limits<s32>::max()), svc::ResultOutOfMemory());
|
||||||
|
|
||||||
|
@ -51,8 +51,8 @@ namespace ams::map {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LocateMappableSpaceModern(uintptr_t *out_address, size_t size) {
|
Result LocateMappableSpaceModern(uintptr_t *out_address, size_t size) {
|
||||||
MemoryInfo mem_info = {};
|
svc::MemoryInfo mem_info;
|
||||||
u32 page_info = 0;
|
svc::PageInfo page_info;
|
||||||
uintptr_t cur_base = 0, cur_end = 0;
|
uintptr_t cur_base = 0, cur_end = 0;
|
||||||
|
|
||||||
AddressSpaceInfo address_space;
|
AddressSpaceInfo address_space;
|
||||||
|
@ -72,8 +72,8 @@ namespace ams::map {
|
||||||
R_UNLESS(cur_base != address_space.alias_end, svc::ResultOutOfMemory());
|
R_UNLESS(cur_base != address_space.alias_end, svc::ResultOutOfMemory());
|
||||||
cur_base = address_space.alias_end;
|
cur_base = address_space.alias_end;
|
||||||
} else {
|
} else {
|
||||||
R_ABORT_UNLESS(svcQueryMemory(&mem_info, &page_info, cur_base));
|
R_ABORT_UNLESS(svc::QueryMemory(&mem_info, &page_info, cur_base));
|
||||||
if (mem_info.type == 0 && mem_info.addr - cur_base + mem_info.size >= size) {
|
if (mem_info.state == svc::MemoryState_Free && mem_info.addr - cur_base + mem_info.size >= size) {
|
||||||
*out_address = cur_base;
|
*out_address = cur_base;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ namespace ams::map {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MapCodeMemoryInProcessDeprecated(MappedCodeMemory &out_mcm, Handle process_handle, uintptr_t base_address, size_t size) {
|
Result MapCodeMemoryInProcessDeprecated(MappedCodeMemory &out_mcm, os::NativeHandle process_handle, uintptr_t base_address, size_t size) {
|
||||||
AddressSpaceInfo address_space;
|
AddressSpaceInfo address_space;
|
||||||
R_TRY(GetProcessAddressSpaceInfo(&address_space, process_handle));
|
R_TRY(GetProcessAddressSpaceInfo(&address_space, process_handle));
|
||||||
|
|
||||||
|
@ -114,7 +114,7 @@ namespace ams::map {
|
||||||
return ro::ResultOutOfAddressSpace();
|
return ro::ResultOutOfAddressSpace();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MapCodeMemoryInProcessModern(MappedCodeMemory &out_mcm, Handle process_handle, uintptr_t base_address, size_t size) {
|
Result MapCodeMemoryInProcessModern(MappedCodeMemory &out_mcm, os::NativeHandle process_handle, uintptr_t base_address, size_t size) {
|
||||||
AddressSpaceInfo address_space;
|
AddressSpaceInfo address_space;
|
||||||
R_TRY(GetProcessAddressSpaceInfo(&address_space, process_handle));
|
R_TRY(GetProcessAddressSpaceInfo(&address_space, process_handle));
|
||||||
|
|
||||||
|
@ -153,28 +153,17 @@ namespace ams::map {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Public API. */
|
/* Public API. */
|
||||||
Result GetProcessAddressSpaceInfo(AddressSpaceInfo *out, Handle process_h) {
|
Result GetProcessAddressSpaceInfo(AddressSpaceInfo *out, os::NativeHandle process_h) {
|
||||||
/* Clear output. */
|
/* Clear output. */
|
||||||
std::memset(out, 0, sizeof(*out));
|
std::memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
/* Retrieve info from kernel. */
|
/* Retrieve info from kernel. */
|
||||||
R_TRY(svcGetInfo(&out->heap_base, InfoType_HeapRegionAddress, process_h, 0));
|
R_TRY(svc::GetInfo(&out->heap_base, svc::InfoType_HeapRegionAddress, process_h, 0));
|
||||||
R_TRY(svcGetInfo(&out->heap_size, InfoType_HeapRegionSize, process_h, 0));
|
R_TRY(svc::GetInfo(&out->heap_size, svc::InfoType_HeapRegionSize, process_h, 0));
|
||||||
R_TRY(svcGetInfo(&out->alias_base, InfoType_AliasRegionAddress, process_h, 0));
|
R_TRY(svc::GetInfo(&out->alias_base, svc::InfoType_AliasRegionAddress, process_h, 0));
|
||||||
R_TRY(svcGetInfo(&out->alias_size, InfoType_AliasRegionSize, process_h, 0));
|
R_TRY(svc::GetInfo(&out->alias_size, svc::InfoType_AliasRegionSize, process_h, 0));
|
||||||
if (hos::GetVersion() >= hos::Version_2_0_0) {
|
R_TRY(svc::GetInfo(&out->aslr_base, svc::InfoType_AslrRegionAddress, process_h, 0));
|
||||||
R_TRY(svcGetInfo(&out->aslr_base, InfoType_AslrRegionAddress, process_h, 0));
|
R_TRY(svc::GetInfo(&out->aslr_size, svc::InfoType_AslrRegionSize, process_h, 0));
|
||||||
R_TRY(svcGetInfo(&out->aslr_size, InfoType_AslrRegionSize, process_h, 0));
|
|
||||||
} else {
|
|
||||||
/* Auto-detect 32-bit vs 64-bit. */
|
|
||||||
if (out->heap_base < AslrBase64BitDeprecated || out->alias_base < AslrBase64BitDeprecated) {
|
|
||||||
out->aslr_base = AslrBase32Bit;
|
|
||||||
out->aslr_size = AslrSize32Bit;
|
|
||||||
} else {
|
|
||||||
out->aslr_base = AslrBase64BitDeprecated;
|
|
||||||
out->aslr_size = AslrSize64BitDeprecated;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
out->heap_end = out->heap_base + out->heap_size;
|
out->heap_end = out->heap_base + out->heap_size;
|
||||||
out->alias_end = out->alias_base + out->alias_size;
|
out->alias_end = out->alias_base + out->alias_size;
|
||||||
|
@ -190,7 +179,7 @@ namespace ams::map {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result MapCodeMemoryInProcess(MappedCodeMemory &out_mcm, Handle process_handle, uintptr_t base_address, size_t size) {
|
Result MapCodeMemoryInProcess(MappedCodeMemory &out_mcm, os::NativeHandle process_handle, uintptr_t base_address, size_t size) {
|
||||||
if (hos::GetVersion() >= hos::Version_2_0_0) {
|
if (hos::GetVersion() >= hos::Version_2_0_0) {
|
||||||
return MapCodeMemoryInProcessModern(out_mcm, process_handle, base_address, size);
|
return MapCodeMemoryInProcessModern(out_mcm, process_handle, base_address, size);
|
||||||
} else {
|
} else {
|
||||||
|
@ -198,16 +187,16 @@ namespace ams::map {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CanAddGuardRegionsInProcess(Handle process_handle, uintptr_t address, size_t size) {
|
bool CanAddGuardRegionsInProcess(os::NativeHandle process_handle, uintptr_t address, size_t size) {
|
||||||
MemoryInfo mem_info;
|
svc::MemoryInfo mem_info;
|
||||||
u32 page_info;
|
svc::PageInfo page_info;
|
||||||
|
|
||||||
/* Nintendo doesn't validate SVC return values at all. */
|
/* Nintendo doesn't validate SVC return values at all. */
|
||||||
/* TODO: Should we allow these to fail? */
|
/* TODO: Should we allow these to fail? */
|
||||||
R_ABORT_UNLESS(svcQueryProcessMemory(&mem_info, &page_info, process_handle, address - 1));
|
R_ABORT_UNLESS(svc::QueryProcessMemory(&mem_info, &page_info, process_handle, address - 1));
|
||||||
if (mem_info.type == MemType_Unmapped && address - GuardRegionSize >= mem_info.addr) {
|
if (mem_info.state == svc::MemoryState_Free && address - GuardRegionSize >= mem_info.addr) {
|
||||||
R_ABORT_UNLESS(svcQueryProcessMemory(&mem_info, &page_info, process_handle, address + size));
|
R_ABORT_UNLESS(svc::QueryProcessMemory(&mem_info, &page_info, process_handle, address + size));
|
||||||
return mem_info.type == MemType_Unmapped && address + size + GuardRegionSize <= mem_info.addr + mem_info.size;
|
return mem_info.state == svc::MemoryState_Free && address + size + GuardRegionSize <= mem_info.addr + mem_info.size;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -25,8 +25,8 @@ namespace ams::os::impl {
|
||||||
/* Nintendo does not check the result of these invocations, but we will for safety. */
|
/* Nintendo does not check the result of these invocations, but we will for safety. */
|
||||||
/* Nintendo uses entropy values 0, 1 to seed the public TinyMT random, and values */
|
/* Nintendo uses entropy values 0, 1 to seed the public TinyMT random, and values */
|
||||||
/* 2, 3 to seed os::detail::RngManager's private TinyMT random. */
|
/* 2, 3 to seed os::detail::RngManager's private TinyMT random. */
|
||||||
R_ABORT_UNLESS(svcGetInfo(reinterpret_cast<u64 *>(&seed[0]), InfoType_RandomEntropy, INVALID_HANDLE, 0));
|
R_ABORT_UNLESS(svc::GetInfo(reinterpret_cast<u64 *>(seed + 0), svc::InfoType_RandomEntropy, svc::InvalidHandle, 0));
|
||||||
R_ABORT_UNLESS(svcGetInfo(reinterpret_cast<u64 *>(&seed[2]), InfoType_RandomEntropy, INVALID_HANDLE, 1));
|
R_ABORT_UNLESS(svc::GetInfo(reinterpret_cast<u64 *>(seed + 2), svc::InfoType_RandomEntropy, svc::InvalidHandle, 1));
|
||||||
|
|
||||||
mt->Initialize(seed, util::size(seed));
|
mt->Initialize(seed, util::size(seed));
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,8 +26,8 @@ namespace ams::os::impl {
|
||||||
/* Nintendo does not check the result of these invocations, but we will for safety. */
|
/* Nintendo does not check the result of these invocations, but we will for safety. */
|
||||||
/* Nintendo uses entropy values 0, 1 to seed the public TinyMT random, and values */
|
/* Nintendo uses entropy values 0, 1 to seed the public TinyMT random, and values */
|
||||||
/* 2, 3 to seed os::detail::RngManager's private TinyMT random. */
|
/* 2, 3 to seed os::detail::RngManager's private TinyMT random. */
|
||||||
R_ABORT_UNLESS(svcGetInfo(reinterpret_cast<u64 *>(&seed[0]), InfoType_RandomEntropy, INVALID_HANDLE, 2));
|
R_ABORT_UNLESS(svc::GetInfo(reinterpret_cast<u64 *>(seed + 0), svc::InfoType_RandomEntropy, svc::InvalidHandle, 2));
|
||||||
R_ABORT_UNLESS(svcGetInfo(reinterpret_cast<u64 *>(&seed[2]), InfoType_RandomEntropy, INVALID_HANDLE, 3));
|
R_ABORT_UNLESS(svc::GetInfo(reinterpret_cast<u64 *>(seed + 2), svc::InfoType_RandomEntropy, svc::InvalidHandle, 3));
|
||||||
|
|
||||||
this->mt.Initialize(seed, util::size(seed));
|
this->mt.Initialize(seed, util::size(seed));
|
||||||
|
|
||||||
|
|
|
@ -19,10 +19,10 @@ namespace ams::os {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
/* TODO: Remove, add VammManager */
|
/* TODO: Remove, add VammManager/horizon-impl */
|
||||||
size_t GetSystemResourceSize() {
|
size_t GetSystemResourceSize() {
|
||||||
u64 v;
|
u64 v;
|
||||||
if (R_SUCCEEDED(svcGetInfo(std::addressof(v), InfoType_SystemResourceSizeTotal, CUR_PROCESS_HANDLE, 0))) {
|
if (R_SUCCEEDED(svc::GetInfo(std::addressof(v), svc::InfoType_SystemResourceSizeTotal, os::GetCurrentProcessHandle(), 0))) {
|
||||||
return v;
|
return v;
|
||||||
} else {
|
} else {
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -32,15 +32,15 @@ namespace ams::pm::dmnt {
|
||||||
return pmdmntGetApplicationProcessId(reinterpret_cast<u64 *>(out_process_id));
|
return pmdmntGetApplicationProcessId(reinterpret_cast<u64 *>(out_process_id));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HookToCreateApplicationProcess(Handle *out_handle) {
|
Result HookToCreateApplicationProcess(os::NativeHandle *out_handle) {
|
||||||
Event evt;
|
Event evt;
|
||||||
R_TRY(pmdmntHookToCreateApplicationProcess(&evt));
|
R_TRY(pmdmntHookToCreateApplicationProcess(&evt));
|
||||||
*out_handle = evt.revent;
|
*out_handle = evt.revent;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AtmosphereGetProcessInfo(Handle *out_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
|
Result AtmosphereGetProcessInfo(os::NativeHandle *out_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
|
||||||
*out_handle = INVALID_HANDLE;
|
*out_handle = os::InvalidNativeHandle;
|
||||||
*out_loc = {};
|
*out_loc = {};
|
||||||
*out_status = {};
|
*out_status = {};
|
||||||
static_assert(sizeof(*out_status) == sizeof(CfgOverrideStatus));
|
static_assert(sizeof(*out_status) == sizeof(CfgOverrideStatus));
|
||||||
|
|
|
@ -19,37 +19,37 @@ namespace ams::sf::hipc {
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
ALWAYS_INLINE Result ReceiveImpl(Handle session_handle, void *message_buf, size_t message_buf_size) {
|
ALWAYS_INLINE Result ReceiveImpl(os::NativeHandle session_handle, void *message_buf, size_t message_buf_size) {
|
||||||
s32 unused_index;
|
s32 unused_index;
|
||||||
if (message_buf == armGetTls()) {
|
if (message_buf == svc::GetThreadLocalRegion()->message_buffer) {
|
||||||
/* Consider: AMS_ABORT_UNLESS(message_buf_size == TlsMessageBufferSize); */
|
/* Consider: AMS_ABORT_UNLESS(message_buf_size == TlsMessageBufferSize); */
|
||||||
return svcReplyAndReceive(&unused_index, &session_handle, 1, INVALID_HANDLE, std::numeric_limits<u64>::max());
|
return svc::ReplyAndReceive(&unused_index, &session_handle, 1, svc::InvalidHandle, std::numeric_limits<u64>::max());
|
||||||
} else {
|
} else {
|
||||||
return svcReplyAndReceiveWithUserBuffer(&unused_index, message_buf, message_buf_size, &session_handle, 1, INVALID_HANDLE, std::numeric_limits<u64>::max());
|
return svc::ReplyAndReceiveWithUserBuffer(&unused_index, reinterpret_cast<uintptr_t>(message_buf), message_buf_size, &session_handle, 1, svc::InvalidHandle, std::numeric_limits<u64>::max());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ALWAYS_INLINE Result ReplyImpl(Handle session_handle, void *message_buf, size_t message_buf_size) {
|
ALWAYS_INLINE Result ReplyImpl(os::NativeHandle session_handle, void *message_buf, size_t message_buf_size) {
|
||||||
s32 unused_index;
|
s32 unused_index;
|
||||||
if (message_buf == armGetTls()) {
|
if (message_buf == svc::GetThreadLocalRegion()->message_buffer) {
|
||||||
/* Consider: AMS_ABORT_UNLESS(message_buf_size == TlsMessageBufferSize); */
|
/* Consider: AMS_ABORT_UNLESS(message_buf_size == TlsMessageBufferSize); */
|
||||||
return svcReplyAndReceive(&unused_index, &session_handle, 0, session_handle, 0);
|
return svc::ReplyAndReceive(&unused_index, &session_handle, 0, session_handle, 0);
|
||||||
} else {
|
} else {
|
||||||
return svcReplyAndReceiveWithUserBuffer(&unused_index, message_buf, message_buf_size, &session_handle, 0, session_handle, 0);
|
return svc::ReplyAndReceiveWithUserBuffer(&unused_index, reinterpret_cast<uintptr_t>(message_buf), message_buf_size, &session_handle, 0, session_handle, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, Handle port) {
|
void AttachMultiWaitHolderForAccept(os::MultiWaitHolderType *holder, os::NativeHandle port) {
|
||||||
return os::InitializeMultiWaitHolder(holder, port);
|
return os::InitializeMultiWaitHolder(holder, port);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, Handle request) {
|
void AttachMultiWaitHolderForReply(os::MultiWaitHolderType *holder, os::NativeHandle request) {
|
||||||
return os::InitializeMultiWaitHolder(holder, request);
|
return os::InitializeMultiWaitHolder(holder, request);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Receive(ReceiveResult *out_recv_result, Handle session_handle, const cmif::PointerAndSize &message_buffer) {
|
Result Receive(ReceiveResult *out_recv_result, os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer) {
|
||||||
R_TRY_CATCH(ReceiveImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
|
R_TRY_CATCH(ReceiveImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
|
||||||
R_CATCH(svc::ResultSessionClosed) {
|
R_CATCH(svc::ResultSessionClosed) {
|
||||||
*out_recv_result = ReceiveResult::Closed;
|
*out_recv_result = ReceiveResult::Closed;
|
||||||
|
@ -64,7 +64,7 @@ namespace ams::sf::hipc {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Receive(bool *out_closed, Handle session_handle, const cmif::PointerAndSize &message_buffer) {
|
Result Receive(bool *out_closed, os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer) {
|
||||||
R_TRY_CATCH(ReceiveImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
|
R_TRY_CATCH(ReceiveImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
|
||||||
R_CATCH(svc::ResultSessionClosed) {
|
R_CATCH(svc::ResultSessionClosed) {
|
||||||
*out_closed = true;
|
*out_closed = true;
|
||||||
|
@ -75,7 +75,7 @@ namespace ams::sf::hipc {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result Reply(Handle session_handle, const cmif::PointerAndSize &message_buffer) {
|
Result Reply(os::NativeHandle session_handle, const cmif::PointerAndSize &message_buffer) {
|
||||||
R_TRY_CATCH(ReplyImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
|
R_TRY_CATCH(ReplyImpl(session_handle, message_buffer.GetPointer(), message_buffer.GetSize())) {
|
||||||
R_CONVERT(svc::ResultTimedOut, ResultSuccess())
|
R_CONVERT(svc::ResultTimedOut, ResultSuccess())
|
||||||
R_CONVERT(svc::ResultSessionClosed, ResultSuccess())
|
R_CONVERT(svc::ResultSessionClosed, ResultSuccess())
|
||||||
|
@ -84,8 +84,8 @@ namespace ams::sf::hipc {
|
||||||
AMS_ABORT_UNLESS(false);
|
AMS_ABORT_UNLESS(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CreateSession(Handle *out_server_handle, Handle *out_client_handle) {
|
Result CreateSession(os::NativeHandle *out_server_handle, os::NativeHandle *out_client_handle) {
|
||||||
R_TRY_CATCH(svcCreateSession(out_server_handle, out_client_handle, 0, 0)) {
|
R_TRY_CATCH(svc::CreateSession(out_server_handle, out_client_handle, 0, 0)) {
|
||||||
R_CONVERT(svc::ResultOutOfResource, sf::hipc::ResultOutOfSessions());
|
R_CONVERT(svc::ResultOutOfResource, sf::hipc::ResultOutOfSessions());
|
||||||
} R_END_TRY_CATCH;
|
} R_END_TRY_CATCH;
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
|
|
@ -113,7 +113,7 @@ namespace ams::sf::hipc {
|
||||||
|
|
||||||
ServerSession *session = static_cast<ServerSession *>(holder);
|
ServerSession *session = static_cast<ServerSession *>(holder);
|
||||||
|
|
||||||
cmif::PointerAndSize tls_message(armGetTls(), hipc::TlsMessageBufferSize);
|
cmif::PointerAndSize tls_message(svc::GetThreadLocalRegion()->message_buffer, hipc::TlsMessageBufferSize);
|
||||||
const cmif::PointerAndSize &saved_message = session->saved_message;
|
const cmif::PointerAndSize &saved_message = session->saved_message;
|
||||||
AMS_ABORT_UNLESS(tls_message.GetSize() == saved_message.GetSize());
|
AMS_ABORT_UNLESS(tls_message.GetSize() == saved_message.GetSize());
|
||||||
if (!session->has_received) {
|
if (!session->has_received) {
|
||||||
|
|
|
@ -45,18 +45,21 @@ namespace ams::sf::hipc {
|
||||||
AMS_ABORT_UNLESS(this->saved_message.GetPointer() != nullptr);
|
AMS_ABORT_UNLESS(this->saved_message.GetPointer() != nullptr);
|
||||||
AMS_ABORT_UNLESS(this->saved_message.GetSize() == TlsMessageBufferSize);
|
AMS_ABORT_UNLESS(this->saved_message.GetSize() == TlsMessageBufferSize);
|
||||||
|
|
||||||
|
/* Get TLS message buffer. */
|
||||||
|
u32 * const message_buffer = svc::GetThreadLocalRegion()->message_buffer;
|
||||||
|
|
||||||
/* Copy saved TLS in. */
|
/* Copy saved TLS in. */
|
||||||
std::memcpy(armGetTls(), this->saved_message.GetPointer(), this->saved_message.GetSize());
|
std::memcpy(message_buffer, this->saved_message.GetPointer(), this->saved_message.GetSize());
|
||||||
|
|
||||||
/* Prepare buffer. */
|
/* Prepare buffer. */
|
||||||
PreProcessCommandBufferForMitm(ctx, this->pointer_buffer, reinterpret_cast<uintptr_t>(armGetTls()));
|
PreProcessCommandBufferForMitm(ctx, this->pointer_buffer, reinterpret_cast<uintptr_t>(message_buffer));
|
||||||
|
|
||||||
/* Dispatch forwards. */
|
/* Dispatch forwards. */
|
||||||
R_TRY(svcSendSyncRequest(this->forward_service->session));
|
R_TRY(svc::SendSyncRequest(this->forward_service->session));
|
||||||
|
|
||||||
/* Parse, to ensure we catch any copy handles and close them. */
|
/* Parse, to ensure we catch any copy handles and close them. */
|
||||||
{
|
{
|
||||||
const auto response = hipcParseResponse(armGetTls());
|
const auto response = hipcParseResponse(message_buffer);
|
||||||
if (response.num_copy_handles) {
|
if (response.num_copy_handles) {
|
||||||
ctx.handles_to_close->num_handles = response.num_copy_handles;
|
ctx.handles_to_close->num_handles = response.num_copy_handles;
|
||||||
for (size_t i = 0; i < response.num_copy_handles; i++) {
|
for (size_t i = 0; i < response.num_copy_handles; i++) {
|
||||||
|
@ -77,13 +80,13 @@ namespace ams::sf::hipc {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ServerSessionManager::CloseSessionImpl(ServerSession *session) {
|
void ServerSessionManager::CloseSessionImpl(ServerSession *session) {
|
||||||
const Handle session_handle = session->session_handle;
|
const auto session_handle = session->session_handle;
|
||||||
os::FinalizeMultiWaitHolder(session);
|
os::FinalizeMultiWaitHolder(session);
|
||||||
this->DestroySession(session);
|
this->DestroySession(session);
|
||||||
R_ABORT_UNLESS(svcCloseHandle(session_handle));
|
os::CloseNativeHandle(session_handle);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::RegisterSessionImpl(ServerSession *session_memory, Handle session_handle, cmif::ServiceObjectHolder &&obj) {
|
Result ServerSessionManager::RegisterSessionImpl(ServerSession *session_memory, os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj) {
|
||||||
/* Create session object. */
|
/* Create session object. */
|
||||||
std::construct_at(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
std::construct_at(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
||||||
|
|
||||||
|
@ -96,12 +99,12 @@ namespace ams::sf::hipc {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::AcceptSessionImpl(ServerSession *session_memory, Handle port_handle, cmif::ServiceObjectHolder &&obj) {
|
Result ServerSessionManager::AcceptSessionImpl(ServerSession *session_memory, os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj) {
|
||||||
/* Create session handle. */
|
/* Create session handle. */
|
||||||
Handle session_handle;
|
os::NativeHandle session_handle;
|
||||||
R_TRY(svcAcceptSession(&session_handle, port_handle));
|
R_TRY(svc::AcceptSession(&session_handle, port_handle));
|
||||||
|
|
||||||
auto session_guard = SCOPE_GUARD { R_ABORT_UNLESS(svc::CloseHandle(session_handle)); };
|
auto session_guard = SCOPE_GUARD { os::CloseNativeHandle(session_handle); };
|
||||||
|
|
||||||
/* Register session. */
|
/* Register session. */
|
||||||
R_TRY(this->RegisterSessionImpl(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj)));
|
R_TRY(this->RegisterSessionImpl(session_memory, session_handle, std::forward<cmif::ServiceObjectHolder>(obj)));
|
||||||
|
@ -110,7 +113,7 @@ namespace ams::sf::hipc {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::RegisterMitmSessionImpl(ServerSession *session_memory, Handle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
Result ServerSessionManager::RegisterMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||||
/* Create session object. */
|
/* Create session object. */
|
||||||
std::construct_at(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
std::construct_at(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||||
|
|
||||||
|
@ -127,12 +130,12 @@ namespace ams::sf::hipc {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::AcceptMitmSessionImpl(ServerSession *session_memory, Handle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
Result ServerSessionManager::AcceptMitmSessionImpl(ServerSession *session_memory, os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||||
/* Create session handle. */
|
/* Create session handle. */
|
||||||
Handle mitm_session_handle;
|
os::NativeHandle mitm_session_handle;
|
||||||
R_TRY(svcAcceptSession(&mitm_session_handle, mitm_port_handle));
|
R_TRY(svc::AcceptSession(&mitm_session_handle, mitm_port_handle));
|
||||||
|
|
||||||
auto session_guard = SCOPE_GUARD { R_ABORT_UNLESS(svc::CloseHandle(mitm_session_handle)); };
|
auto session_guard = SCOPE_GUARD { os::CloseNativeHandle(mitm_session_handle); };
|
||||||
|
|
||||||
/* Register session. */
|
/* Register session. */
|
||||||
R_TRY(this->RegisterMitmSessionImpl(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv)));
|
R_TRY(this->RegisterMitmSessionImpl(session_memory, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv)));
|
||||||
|
@ -141,25 +144,25 @@ namespace ams::sf::hipc {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::RegisterSession(Handle session_handle, cmif::ServiceObjectHolder &&obj) {
|
Result ServerSessionManager::RegisterSession(os::NativeHandle session_handle, cmif::ServiceObjectHolder &&obj) {
|
||||||
/* We don't actually care about what happens to the session. It'll get linked. */
|
/* We don't actually care about what happens to the session. It'll get linked. */
|
||||||
ServerSession *session_ptr = nullptr;
|
ServerSession *session_ptr = nullptr;
|
||||||
return this->RegisterSession(&session_ptr, session_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
return this->RegisterSession(&session_ptr, session_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::AcceptSession(Handle port_handle, cmif::ServiceObjectHolder &&obj) {
|
Result ServerSessionManager::AcceptSession(os::NativeHandle port_handle, cmif::ServiceObjectHolder &&obj) {
|
||||||
/* We don't actually care about what happens to the session. It'll get linked. */
|
/* We don't actually care about what happens to the session. It'll get linked. */
|
||||||
ServerSession *session_ptr = nullptr;
|
ServerSession *session_ptr = nullptr;
|
||||||
return this->AcceptSession(&session_ptr, port_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
return this->AcceptSession(&session_ptr, port_handle, std::forward<cmif::ServiceObjectHolder>(obj));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::RegisterMitmSession(Handle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
Result ServerSessionManager::RegisterMitmSession(os::NativeHandle mitm_session_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||||
/* We don't actually care about what happens to the session. It'll get linked. */
|
/* We don't actually care about what happens to the session. It'll get linked. */
|
||||||
ServerSession *session_ptr = nullptr;
|
ServerSession *session_ptr = nullptr;
|
||||||
return this->RegisterMitmSession(&session_ptr, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
return this->RegisterMitmSession(&session_ptr, mitm_session_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ServerSessionManager::AcceptMitmSession(Handle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
Result ServerSessionManager::AcceptMitmSession(os::NativeHandle mitm_port_handle, cmif::ServiceObjectHolder &&obj, std::shared_ptr<::Service> &&fsrv) {
|
||||||
/* We don't actually care about what happens to the session. It'll get linked. */
|
/* We don't actually care about what happens to the session. It'll get linked. */
|
||||||
ServerSession *session_ptr = nullptr;
|
ServerSession *session_ptr = nullptr;
|
||||||
return this->AcceptMitmSession(&session_ptr, mitm_port_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
return this->AcceptMitmSession(&session_ptr, mitm_port_handle, std::forward<cmif::ServiceObjectHolder>(obj), std::forward<std::shared_ptr<::Service>>(fsrv));
|
||||||
|
@ -313,7 +316,7 @@ namespace ams::sf::hipc {
|
||||||
{
|
{
|
||||||
ON_SCOPE_EXIT {
|
ON_SCOPE_EXIT {
|
||||||
for (size_t i = 0; i < handles_to_close.num_handles; i++) {
|
for (size_t i = 0; i < handles_to_close.num_handles; i++) {
|
||||||
R_ABORT_UNLESS(svcCloseHandle(handles_to_close.handles[i]));
|
os::CloseNativeHandle(handles_to_close.handles[i]);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
R_TRY(hipc::Reply(session->session_handle, out_message));
|
R_TRY(hipc::Reply(session->session_handle, out_message));
|
||||||
|
|
|
@ -18,292 +18,292 @@
|
||||||
namespace ams::spl::smc {
|
namespace ams::spl::smc {
|
||||||
|
|
||||||
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords) {
|
Result SetConfig(spl::ConfigItem which, const void *address, const u64 *value, size_t num_qwords) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::SetConfig);
|
args.r[0] = static_cast<u64>(FunctionId::SetConfig);
|
||||||
args.X[1] = static_cast<u64>(which);
|
args.r[1] = static_cast<u64>(which);
|
||||||
args.X[2] = reinterpret_cast<u64>(address);
|
args.r[2] = reinterpret_cast<u64>(address);
|
||||||
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
||||||
args.X[3 + i] = value[i];
|
args.r[3 + i] = value[i];
|
||||||
}
|
}
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetConfig(u64 *out, size_t num_qwords, spl::ConfigItem which) {
|
Result GetConfig(u64 *out, size_t num_qwords, spl::ConfigItem which) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::GetConfig);
|
args.r[0] = static_cast<u64>(FunctionId::GetConfig);
|
||||||
args.X[1] = static_cast<u64>(which);
|
args.r[1] = static_cast<u64>(which);
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
for (size_t i = 0; i < std::min(size_t(4), num_qwords); i++) {
|
||||||
out[i] = args.X[1 + i];
|
out[i] = args.r[1 + i];
|
||||||
}
|
}
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetResult(Result *out, AsyncOperationKey op) {
|
Result GetResult(Result *out, AsyncOperationKey op) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::GetResult);
|
args.r[0] = static_cast<u64>(FunctionId::GetResult);
|
||||||
args.X[1] = op.value;
|
args.r[1] = op.value;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
*out = static_cast<Result>(args.X[1]);
|
*out = static_cast<Result>(args.r[1]);
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetResultData(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op) {
|
Result GetResultData(Result *out, void *out_buf, size_t out_buf_size, AsyncOperationKey op) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::GetResultData);
|
args.r[0] = static_cast<u64>(FunctionId::GetResultData);
|
||||||
args.X[1] = op.value;
|
args.r[1] = op.value;
|
||||||
args.X[2] = reinterpret_cast<u64>(out_buf);
|
args.r[2] = reinterpret_cast<u64>(out_buf);
|
||||||
args.X[3] = out_buf_size;
|
args.r[3] = out_buf_size;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
*out = static_cast<Result>(args.X[1]);
|
*out = static_cast<Result>(args.r[1]);
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ModularExponentiate(AsyncOperationKey *out_op, const void *base, const void *exp, size_t exp_size, const void *mod) {
|
Result ModularExponentiate(AsyncOperationKey *out_op, const void *base, const void *exp, size_t exp_size, const void *mod) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::ModularExponentiate);
|
args.r[0] = static_cast<u64>(FunctionId::ModularExponentiate);
|
||||||
args.X[1] = reinterpret_cast<u64>(base);
|
args.r[1] = reinterpret_cast<u64>(base);
|
||||||
args.X[2] = reinterpret_cast<u64>(exp);
|
args.r[2] = reinterpret_cast<u64>(exp);
|
||||||
args.X[3] = reinterpret_cast<u64>(mod);
|
args.r[3] = reinterpret_cast<u64>(mod);
|
||||||
args.X[4] = exp_size;
|
args.r[4] = exp_size;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out_op->value = args.X[1];
|
out_op->value = args.r[1];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GenerateRandomBytes(void *out, size_t size) {
|
Result GenerateRandomBytes(void *out, size_t size) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::GenerateRandomBytes);
|
args.r[0] = static_cast<u64>(FunctionId::GenerateRandomBytes);
|
||||||
args.X[1] = size;
|
args.r[1] = size;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
if (args.X[0] == static_cast<u64>(Result::Success) && (size <= sizeof(args) - sizeof(args.X[0]))) {
|
if (args.r[0] == static_cast<u64>(Result::Success) && (size <= sizeof(args) - sizeof(args.r[0]))) {
|
||||||
std::memcpy(out, &args.X[1], size);
|
std::memcpy(out, &args.r[1], size);
|
||||||
}
|
}
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GenerateAesKek(AccessKey *out, const KeySource &source, u32 generation, u32 option) {
|
Result GenerateAesKek(AccessKey *out, const KeySource &source, u32 generation, u32 option) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::GenerateAesKek);
|
args.r[0] = static_cast<u64>(FunctionId::GenerateAesKek);
|
||||||
args.X[1] = source.data64[0];
|
args.r[1] = source.data64[0];
|
||||||
args.X[2] = source.data64[1];
|
args.r[2] = source.data64[1];
|
||||||
args.X[3] = generation;
|
args.r[3] = generation;
|
||||||
args.X[4] = option;
|
args.r[4] = option;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out->data64[0] = args.X[1];
|
out->data64[0] = args.r[1];
|
||||||
out->data64[1] = args.X[2];
|
out->data64[1] = args.r[2];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadAesKey(u32 keyslot, const AccessKey &access_key, const KeySource &source) {
|
Result LoadAesKey(u32 keyslot, const AccessKey &access_key, const KeySource &source) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::LoadAesKey);
|
args.r[0] = static_cast<u64>(FunctionId::LoadAesKey);
|
||||||
args.X[1] = keyslot;
|
args.r[1] = keyslot;
|
||||||
args.X[2] = access_key.data64[0];
|
args.r[2] = access_key.data64[0];
|
||||||
args.X[3] = access_key.data64[1];
|
args.r[3] = access_key.data64[1];
|
||||||
args.X[4] = source.data64[0];
|
args.r[4] = source.data64[0];
|
||||||
args.X[5] = source.data64[1];
|
args.r[5] = source.data64[1];
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ComputeAes(AsyncOperationKey *out_op, u32 mode, const IvCtr &iv_ctr, u32 dst_addr, u32 src_addr, size_t size) {
|
Result ComputeAes(AsyncOperationKey *out_op, u32 mode, const IvCtr &iv_ctr, u32 dst_addr, u32 src_addr, size_t size) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::ComputeAes);
|
args.r[0] = static_cast<u64>(FunctionId::ComputeAes);
|
||||||
args.X[1] = mode;
|
args.r[1] = mode;
|
||||||
args.X[2] = iv_ctr.data64[0];
|
args.r[2] = iv_ctr.data64[0];
|
||||||
args.X[3] = iv_ctr.data64[1];
|
args.r[3] = iv_ctr.data64[1];
|
||||||
args.X[4] = src_addr;
|
args.r[4] = src_addr;
|
||||||
args.X[5] = dst_addr;
|
args.r[5] = dst_addr;
|
||||||
args.X[6] = size;
|
args.r[6] = size;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out_op->value = args.X[1];
|
out_op->value = args.r[1];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &source, u32 generation, u32 which) {
|
Result GenerateSpecificAesKey(AesKey *out_key, const KeySource &source, u32 generation, u32 which) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::GenerateSpecificAesKey);
|
args.r[0] = static_cast<u64>(FunctionId::GenerateSpecificAesKey);
|
||||||
args.X[1] = source.data64[0];
|
args.r[1] = source.data64[0];
|
||||||
args.X[2] = source.data64[1];
|
args.r[2] = source.data64[1];
|
||||||
args.X[3] = generation;
|
args.r[3] = generation;
|
||||||
args.X[4] = which;
|
args.r[4] = which;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out_key->data64[0] = args.X[1];
|
out_key->data64[0] = args.r[1];
|
||||||
out_key->data64[1] = args.X[2];
|
out_key->data64[1] = args.r[2];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ComputeCmac(Cmac *out_mac, u32 keyslot, const void *data, size_t size) {
|
Result ComputeCmac(Cmac *out_mac, u32 keyslot, const void *data, size_t size) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::ComputeCmac);
|
args.r[0] = static_cast<u64>(FunctionId::ComputeCmac);
|
||||||
args.X[1] = keyslot;
|
args.r[1] = keyslot;
|
||||||
args.X[2] = reinterpret_cast<u64>(data);
|
args.r[2] = reinterpret_cast<u64>(data);
|
||||||
args.X[3] = size;
|
args.r[3] = size;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out_mac->data64[0] = args.X[1];
|
out_mac->data64[0] = args.r[1];
|
||||||
out_mac->data64[1] = args.X[2];
|
out_mac->data64[1] = args.r[2];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ReencryptDeviceUniqueData(void *data, size_t size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option) {
|
Result ReencryptDeviceUniqueData(void *data, size_t size, const AccessKey &access_key_dec, const KeySource &source_dec, const AccessKey &access_key_enc, const KeySource &source_enc, u32 option) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::ReencryptDeviceUniqueData);
|
args.r[0] = static_cast<u64>(FunctionId::ReencryptDeviceUniqueData);
|
||||||
args.X[1] = reinterpret_cast<u64>(&access_key_dec);
|
args.r[1] = reinterpret_cast<u64>(&access_key_dec);
|
||||||
args.X[2] = reinterpret_cast<u64>(&access_key_enc);
|
args.r[2] = reinterpret_cast<u64>(&access_key_enc);
|
||||||
args.X[3] = option;
|
args.r[3] = option;
|
||||||
args.X[4] = reinterpret_cast<u64>(data);
|
args.r[4] = reinterpret_cast<u64>(data);
|
||||||
args.X[5] = size;
|
args.r[5] = size;
|
||||||
args.X[6] = reinterpret_cast<u64>(&source_dec);
|
args.r[6] = reinterpret_cast<u64>(&source_dec);
|
||||||
args.X[7] = reinterpret_cast<u64>(&source_enc);
|
args.r[7] = reinterpret_cast<u64>(&source_enc);
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DecryptDeviceUniqueData(void *data, size_t size, const AccessKey &access_key, const KeySource &source, DeviceUniqueDataMode mode) {
|
Result DecryptDeviceUniqueData(void *data, size_t size, const AccessKey &access_key, const KeySource &source, DeviceUniqueDataMode mode) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::DecryptDeviceUniqueData);
|
args.r[0] = static_cast<u64>(FunctionId::DecryptDeviceUniqueData);
|
||||||
args.X[1] = access_key.data64[0];
|
args.r[1] = access_key.data64[0];
|
||||||
args.X[2] = access_key.data64[1];
|
args.r[2] = access_key.data64[1];
|
||||||
args.X[3] = static_cast<u32>(mode);
|
args.r[3] = static_cast<u32>(mode);
|
||||||
args.X[4] = reinterpret_cast<u64>(data);
|
args.r[4] = reinterpret_cast<u64>(data);
|
||||||
args.X[5] = size;
|
args.r[5] = size;
|
||||||
args.X[6] = source.data64[0];
|
args.r[6] = source.data64[0];
|
||||||
args.X[7] = source.data64[1];
|
args.r[7] = source.data64[1];
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ModularExponentiateWithStorageKey(AsyncOperationKey *out_op, const void *base, const void *mod, ModularExponentiateWithStorageKeyMode mode) {
|
Result ModularExponentiateWithStorageKey(AsyncOperationKey *out_op, const void *base, const void *mod, ModularExponentiateWithStorageKeyMode mode) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::ModularExponentiateWithStorageKey);
|
args.r[0] = static_cast<u64>(FunctionId::ModularExponentiateWithStorageKey);
|
||||||
args.X[1] = reinterpret_cast<u64>(base);
|
args.r[1] = reinterpret_cast<u64>(base);
|
||||||
args.X[2] = reinterpret_cast<u64>(mod);
|
args.r[2] = reinterpret_cast<u64>(mod);
|
||||||
args.X[3] = static_cast<u32>(mode);
|
args.r[3] = static_cast<u32>(mode);
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out_op->value = args.X[1];
|
out_op->value = args.r[1];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result PrepareEsDeviceUniqueKey(AsyncOperationKey *out_op, const void *base, const void *mod, const void *label_digest, size_t label_digest_size, u32 option) {
|
Result PrepareEsDeviceUniqueKey(AsyncOperationKey *out_op, const void *base, const void *mod, const void *label_digest, size_t label_digest_size, u32 option) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::PrepareEsDeviceUniqueKey);
|
args.r[0] = static_cast<u64>(FunctionId::PrepareEsDeviceUniqueKey);
|
||||||
args.X[1] = reinterpret_cast<u64>(base);
|
args.r[1] = reinterpret_cast<u64>(base);
|
||||||
args.X[2] = reinterpret_cast<u64>(mod);
|
args.r[2] = reinterpret_cast<u64>(mod);
|
||||||
std::memset(&args.X[3], 0, 4 * sizeof(args.X[3]));
|
std::memset(&args.r[3], 0, 4 * sizeof(args.r[3]));
|
||||||
std::memcpy(&args.X[3], label_digest, std::min(size_t(4 * sizeof(args.X[3])), label_digest_size));
|
std::memcpy(&args.r[3], label_digest, std::min(size_t(4 * sizeof(args.r[3])), label_digest_size));
|
||||||
args.X[7] = option;
|
args.r[7] = option;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out_op->value = args.X[1];
|
out_op->value = args.r[1];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadPreparedAesKey(u32 keyslot, const AccessKey &access_key) {
|
Result LoadPreparedAesKey(u32 keyslot, const AccessKey &access_key) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::LoadPreparedAesKey);
|
args.r[0] = static_cast<u64>(FunctionId::LoadPreparedAesKey);
|
||||||
args.X[1] = keyslot;
|
args.r[1] = keyslot;
|
||||||
args.X[2] = access_key.data64[0];
|
args.r[2] = access_key.data64[0];
|
||||||
args.X[3] = access_key.data64[1];
|
args.r[3] = access_key.data64[1];
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result PrepareCommonEsTitleKey(AccessKey *out, const KeySource &source, u32 generation) {
|
Result PrepareCommonEsTitleKey(AccessKey *out, const KeySource &source, u32 generation) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::PrepareCommonEsTitleKey);
|
args.r[0] = static_cast<u64>(FunctionId::PrepareCommonEsTitleKey);
|
||||||
args.X[1] = source.data64[0];
|
args.r[1] = source.data64[0];
|
||||||
args.X[2] = source.data64[1];
|
args.r[2] = source.data64[1];
|
||||||
args.X[3] = generation;
|
args.r[3] = generation;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
out->data64[0] = args.X[1];
|
out->data64[0] = args.r[1];
|
||||||
out->data64[1] = args.X[2];
|
out->data64[1] = args.r[2];
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Deprecated functions. */
|
/* Deprecated functions. */
|
||||||
Result LoadEsDeviceKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
Result LoadEsDeviceKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::LoadEsDeviceKey);
|
args.r[0] = static_cast<u64>(FunctionId::LoadEsDeviceKey);
|
||||||
args.X[1] = access_key.data64[0];
|
args.r[1] = access_key.data64[0];
|
||||||
args.X[2] = access_key.data64[1];
|
args.r[2] = access_key.data64[1];
|
||||||
args.X[3] = option;
|
args.r[3] = option;
|
||||||
args.X[4] = reinterpret_cast<u64>(data);
|
args.r[4] = reinterpret_cast<u64>(data);
|
||||||
args.X[5] = size;
|
args.r[5] = size;
|
||||||
args.X[6] = source.data64[0];
|
args.r[6] = source.data64[0];
|
||||||
args.X[7] = source.data64[1];
|
args.r[7] = source.data64[1];
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DecryptDeviceUniqueData(size_t *out_size, void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
Result DecryptDeviceUniqueData(size_t *out_size, void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::DecryptDeviceUniqueData);
|
args.r[0] = static_cast<u64>(FunctionId::DecryptDeviceUniqueData);
|
||||||
args.X[1] = access_key.data64[0];
|
args.r[1] = access_key.data64[0];
|
||||||
args.X[2] = access_key.data64[1];
|
args.r[2] = access_key.data64[1];
|
||||||
args.X[3] = option;
|
args.r[3] = option;
|
||||||
args.X[4] = reinterpret_cast<u64>(data);
|
args.r[4] = reinterpret_cast<u64>(data);
|
||||||
args.X[5] = size;
|
args.r[5] = size;
|
||||||
args.X[6] = source.data64[0];
|
args.r[6] = source.data64[0];
|
||||||
args.X[7] = source.data64[1];
|
args.r[7] = source.data64[1];
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
*out_size = static_cast<size_t>(args.X[1]);
|
*out_size = static_cast<size_t>(args.r[1]);
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result DecryptAndStoreGcKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
Result DecryptAndStoreGcKey(const void *data, size_t size, const AccessKey &access_key, const KeySource &source, u32 option) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
|
|
||||||
args.X[0] = static_cast<u64>(FunctionId::DecryptAndStoreGcKey);
|
args.r[0] = static_cast<u64>(FunctionId::DecryptAndStoreGcKey);
|
||||||
args.X[1] = access_key.data64[0];
|
args.r[1] = access_key.data64[0];
|
||||||
args.X[2] = access_key.data64[1];
|
args.r[2] = access_key.data64[1];
|
||||||
args.X[3] = option;
|
args.r[3] = option;
|
||||||
args.X[4] = reinterpret_cast<u64>(data);
|
args.r[4] = reinterpret_cast<u64>(data);
|
||||||
args.X[5] = size;
|
args.r[5] = size;
|
||||||
args.X[6] = source.data64[0];
|
args.r[6] = source.data64[0];
|
||||||
args.X[7] = source.data64[1];
|
args.r[7] = source.data64[1];
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Atmosphere functions. */
|
/* Atmosphere functions. */
|
||||||
|
@ -315,15 +315,15 @@ namespace ams::spl::smc {
|
||||||
};
|
};
|
||||||
|
|
||||||
inline Result AtmosphereIramCopy(uintptr_t dram_address, uintptr_t iram_address, size_t size, IramCopyDirection direction) {
|
inline Result AtmosphereIramCopy(uintptr_t dram_address, uintptr_t iram_address, size_t size, IramCopyDirection direction) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
args.X[0] = static_cast<u64>(FunctionId::AtmosphereIramCopy);
|
args.r[0] = static_cast<u64>(FunctionId::AtmosphereIramCopy);
|
||||||
args.X[1] = dram_address;
|
args.r[1] = dram_address;
|
||||||
args.X[2] = iram_address;
|
args.r[2] = iram_address;
|
||||||
args.X[3] = size;
|
args.r[3] = size;
|
||||||
args.X[4] = static_cast<u64>(direction);
|
args.r[4] = static_cast<u64>(direction);
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -337,29 +337,29 @@ namespace ams::spl::smc {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AtmosphereReadWriteRegister(uint64_t address, uint32_t mask, uint32_t value, uint32_t *out_value) {
|
Result AtmosphereReadWriteRegister(uint64_t address, uint32_t mask, uint32_t value, uint32_t *out_value) {
|
||||||
SecmonArgs args;
|
svc::SecureMonitorArguments args;
|
||||||
args.X[0] = static_cast<u64>(FunctionId::AtmosphereReadWriteRegister);
|
args.r[0] = static_cast<u64>(FunctionId::AtmosphereReadWriteRegister);
|
||||||
args.X[1] = address;
|
args.r[1] = address;
|
||||||
args.X[2] = mask;
|
args.r[2] = mask;
|
||||||
args.X[3] = value;
|
args.r[3] = value;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
*out_value = static_cast<uint32_t>(args.X[1]);
|
*out_value = static_cast<uint32_t>(args.r[1]);
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AtmosphereGetEmummcConfig(void *out_config, void *out_paths, u32 storage_id) {
|
Result AtmosphereGetEmummcConfig(void *out_config, void *out_paths, u32 storage_id) {
|
||||||
const u64 paths = reinterpret_cast<u64>(out_paths);
|
const u64 paths = reinterpret_cast<u64>(out_paths);
|
||||||
AMS_ABORT_UNLESS(util::IsAligned(paths, os::MemoryPageSize));
|
AMS_ABORT_UNLESS(util::IsAligned(paths, os::MemoryPageSize));
|
||||||
|
|
||||||
SecmonArgs args = {};
|
svc::SecureMonitorArguments args = {};
|
||||||
args.X[0] = static_cast<u64>(FunctionId::AtmosphereGetEmummcConfig);
|
args.r[0] = static_cast<u64>(FunctionId::AtmosphereGetEmummcConfig);
|
||||||
args.X[1] = storage_id;
|
args.r[1] = storage_id;
|
||||||
args.X[2] = paths;
|
args.r[2] = paths;
|
||||||
svcCallSecureMonitor(&args);
|
svc::CallSecureMonitor(std::addressof(args));
|
||||||
|
|
||||||
std::memcpy(out_config, &args.X[1], sizeof(args) - sizeof(args.X[0]));
|
std::memcpy(out_config, &args.r[1], sizeof(args) - sizeof(args.r[0]));
|
||||||
return static_cast<Result>(args.X[0]);
|
return static_cast<Result>(args.r[0]);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,7 +31,7 @@ namespace ams::svc::arch::arm64 {
|
||||||
|
|
||||||
ALWAYS_INLINE ThreadLocalRegion *GetThreadLocalRegion() {
|
ALWAYS_INLINE ThreadLocalRegion *GetThreadLocalRegion() {
|
||||||
ThreadLocalRegion *tlr;
|
ThreadLocalRegion *tlr;
|
||||||
__asm__ __volatile__("mrs %[tlr], tpidrro_el0" : [tlr]"=&r"(tlr) :: "memory");
|
__asm__ __volatile__("mrs %[tlr], tpidrro_el0" : [tlr]"=&r"(tlr));
|
||||||
return tlr;
|
return tlr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -37,8 +37,8 @@ namespace ams::mitm::bpc_ams {
|
||||||
void MitmModule::ThreadFunction(void *arg) {
|
void MitmModule::ThreadFunction(void *arg) {
|
||||||
/* Create bpc:ams. */
|
/* Create bpc:ams. */
|
||||||
{
|
{
|
||||||
Handle bpcams_h;
|
os::NativeHandle bpcams_h;
|
||||||
R_ABORT_UNLESS(svcManageNamedPort(&bpcams_h, AtmosphereServiceName.name, AtmosphereMaxSessions));
|
R_ABORT_UNLESS(svc::ManageNamedPort(&bpcams_h, AtmosphereServiceName.name, AtmosphereMaxSessions));
|
||||||
g_server_manager.RegisterObjectForServer(g_ams_service_object.GetShared(), bpcams_h);
|
g_server_manager.RegisterObjectForServer(g_ams_service_object.GetShared(), bpcams_h);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -165,7 +165,7 @@ namespace ams::creport {
|
||||||
void CrashReport::ProcessExceptions() {
|
void CrashReport::ProcessExceptions() {
|
||||||
/* Loop all debug events. */
|
/* Loop all debug events. */
|
||||||
svc::DebugEventInfo d;
|
svc::DebugEventInfo d;
|
||||||
while (R_SUCCEEDED(svcGetDebugEvent(reinterpret_cast<u8 *>(&d), this->debug_handle))) {
|
while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), this->debug_handle))) {
|
||||||
switch (d.type) {
|
switch (d.type) {
|
||||||
case svc::DebugEvent_CreateProcess:
|
case svc::DebugEvent_CreateProcess:
|
||||||
this->HandleDebugEventInfoCreateProcess(d);
|
this->HandleDebugEventInfoCreateProcess(d);
|
||||||
|
@ -200,7 +200,7 @@ namespace ams::creport {
|
||||||
u64 userdata_size = 0;
|
u64 userdata_size = 0;
|
||||||
|
|
||||||
/* Read userdata address. */
|
/* Read userdata address. */
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(&userdata_address, this->debug_handle, address, sizeof(userdata_address)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(userdata_address)), this->debug_handle, address, sizeof(userdata_address)))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -210,7 +210,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read userdata size. */
|
/* Read userdata size. */
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(&userdata_size, this->debug_handle, address + sizeof(userdata_address), sizeof(userdata_size)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(userdata_size)), this->debug_handle, address + sizeof(userdata_address), sizeof(userdata_size)))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ namespace ams::creport {
|
||||||
this->result = ResultUserBreak();
|
this->result = ResultUserBreak();
|
||||||
/* Try to parse out the user break result. */
|
/* Try to parse out the user break result. */
|
||||||
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
if (hos::GetVersion() >= hos::Version_5_0_0) {
|
||||||
svcReadDebugProcessMemory(&this->result, this->debug_handle, d.info.exception.specific.user_break.address, sizeof(this->result));
|
svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(this->result)), this->debug_handle, d.info.exception.specific.user_break.address, sizeof(this->result));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case svc::DebugException_UndefinedSystemCall:
|
case svc::DebugException_UndefinedSystemCall:
|
||||||
|
@ -289,7 +289,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the dying message. */
|
/* Read the dying message. */
|
||||||
svcReadDebugProcessMemory(this->dying_message, this->debug_handle, this->dying_message_address, this->dying_message_size);
|
svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(this->dying_message), this->debug_handle, this->dying_message_address, this->dying_message_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CrashReport::SaveReport(bool enable_screenshot) {
|
void CrashReport::SaveReport(bool enable_screenshot) {
|
||||||
|
@ -299,7 +299,7 @@ namespace ams::creport {
|
||||||
/* Get a timestamp. */
|
/* Get a timestamp. */
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
if (!TryGetCurrentTimestamp(×tamp)) {
|
if (!TryGetCurrentTimestamp(×tamp)) {
|
||||||
timestamp = svcGetSystemTick();
|
timestamp = os::GetSystemTick().GetInt64Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Save files. */
|
/* Save files. */
|
||||||
|
|
|
@ -25,7 +25,7 @@ namespace ams::creport {
|
||||||
static constexpr size_t MemoryHeapSize = 512_KB;
|
static constexpr size_t MemoryHeapSize = 512_KB;
|
||||||
static_assert(MemoryHeapSize >= DyingMessageSizeMax + sizeof(ModuleList) + sizeof(ThreadList) + os::MemoryPageSize);
|
static_assert(MemoryHeapSize >= DyingMessageSizeMax + sizeof(ModuleList) + sizeof(ThreadList) + os::MemoryPageSize);
|
||||||
private:
|
private:
|
||||||
Handle debug_handle = INVALID_HANDLE;
|
os::NativeHandle debug_handle = os::InvalidNativeHandle;
|
||||||
bool has_extra_info = true;
|
bool has_extra_info = true;
|
||||||
Result result = ResultIncompleteReport();
|
Result result = ResultIncompleteReport();
|
||||||
|
|
||||||
|
@ -63,7 +63,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsOpen() const {
|
bool IsOpen() const {
|
||||||
return this->debug_handle != INVALID_HANDLE;
|
return this->debug_handle != os::InvalidNativeHandle;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsApplication() const {
|
bool IsApplication() const {
|
||||||
|
@ -79,14 +79,12 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
|
|
||||||
bool OpenProcess(os::ProcessId process_id) {
|
bool OpenProcess(os::ProcessId process_id) {
|
||||||
return R_SUCCEEDED(svcDebugActiveProcess(&this->debug_handle, static_cast<u64>(process_id)));
|
return R_SUCCEEDED(svc::DebugActiveProcess(std::addressof(this->debug_handle), process_id.value));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Close() {
|
void Close() {
|
||||||
if (this->IsOpen()) {
|
os::CloseNativeHandle(this->debug_handle);
|
||||||
svcCloseHandle(this->debug_handle);
|
this->debug_handle = os::InvalidNativeHandle;
|
||||||
this->debug_handle = INVALID_HANDLE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Initialize();
|
void Initialize();
|
||||||
|
|
|
@ -58,7 +58,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ModuleList::FindModulesFromThreadInfo(Handle debug_handle, const ThreadInfo &thread) {
|
void ModuleList::FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread) {
|
||||||
/* Set the debug handle, for access in other member functions. */
|
/* Set the debug handle, for access in other member functions. */
|
||||||
this->debug_handle = debug_handle;
|
this->debug_handle = debug_handle;
|
||||||
|
|
||||||
|
@ -92,14 +92,14 @@ namespace ams::creport {
|
||||||
uintptr_t cur_address = base_address;
|
uintptr_t cur_address = base_address;
|
||||||
while (this->num_modules < ModuleCountMax) {
|
while (this->num_modules < ModuleCountMax) {
|
||||||
/* Get the region extents. */
|
/* Get the region extents. */
|
||||||
MemoryInfo mi;
|
svc::MemoryInfo mi;
|
||||||
u32 pi;
|
svc::PageInfo pi;
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, this->debug_handle, cur_address))) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, this->debug_handle, cur_address))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Parse module. */
|
/* Parse module. */
|
||||||
if (mi.perm == Perm_Rx) {
|
if (mi.perm == svc::MemoryPermission_ReadExecute) {
|
||||||
auto& module = this->modules[this->num_modules++];
|
auto& module = this->modules[this->num_modules++];
|
||||||
module.start_address = mi.addr;
|
module.start_address = mi.addr;
|
||||||
module.end_address = mi.addr + mi.size;
|
module.end_address = mi.addr + mi.size;
|
||||||
|
@ -112,7 +112,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we're out of readable memory, we're done reading code. */
|
/* If we're out of readable memory, we're done reading code. */
|
||||||
if (mi.type == MemType_Unmapped || mi.type == MemType_Reserved) {
|
if (mi.state == svc::MemoryState_Free || mi.state == svc::MemoryState_Inaccessible) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -127,39 +127,39 @@ namespace ams::creport {
|
||||||
|
|
||||||
bool ModuleList::TryFindModule(uintptr_t *out_address, uintptr_t guess) {
|
bool ModuleList::TryFindModule(uintptr_t *out_address, uintptr_t guess) {
|
||||||
/* Query the memory region our guess falls in. */
|
/* Query the memory region our guess falls in. */
|
||||||
MemoryInfo mi;
|
svc::MemoryInfo mi;
|
||||||
u32 pi;
|
svc::PageInfo pi;
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, this->debug_handle, guess))) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, this->debug_handle, guess))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we fall into a RW region, it may be rwdata. Query the region before it, which may be rodata or text. */
|
/* If we fall into a RW region, it may be rwdata. Query the region before it, which may be rodata or text. */
|
||||||
if (mi.perm == Perm_Rw) {
|
if (mi.perm == svc::MemoryPermission_ReadWrite) {
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr - 4))) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr - 4))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If we fall into an RO region, it may be rodata. Query the region before it, which should be text. */
|
/* If we fall into an RO region, it may be rodata. Query the region before it, which should be text. */
|
||||||
if (mi.perm == Perm_R) {
|
if (mi.perm == svc::MemoryPermission_Read) {
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr - 4))) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr - 4))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We should, at this point, be looking at an executable region (text). */
|
/* We should, at this point, be looking at an executable region (text). */
|
||||||
if (mi.perm != Perm_Rx) {
|
if (mi.perm != svc::MemoryPermission_ReadExecute) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Modules are a series of contiguous (text/rodata/rwdata) regions. */
|
/* Modules are a series of contiguous (text/rodata/rwdata) regions. */
|
||||||
/* Iterate backwards until we find unmapped memory, to find the start of the set of modules loaded here. */
|
/* Iterate backwards until we find unmapped memory, to find the start of the set of modules loaded here. */
|
||||||
while (mi.addr > 0) {
|
while (mi.addr > 0) {
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr - 4))) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr - 4))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mi.type == MemType_Unmapped) {
|
if (mi.state == svc::MemoryState_Free) {
|
||||||
/* We've found unmapped memory, so output the mapped memory afterwards. */
|
/* We've found unmapped memory, so output the mapped memory afterwards. */
|
||||||
*out_address = mi.addr + mi.size;
|
*out_address = mi.addr + mi.size;
|
||||||
return true;
|
return true;
|
||||||
|
@ -177,11 +177,11 @@ namespace ams::creport {
|
||||||
/* Read module path from process memory. */
|
/* Read module path from process memory. */
|
||||||
RoDataStart rodata_start;
|
RoDataStart rodata_start;
|
||||||
{
|
{
|
||||||
MemoryInfo mi;
|
svc::MemoryInfo mi;
|
||||||
u32 pi;
|
svc::PageInfo pi;
|
||||||
|
|
||||||
/* Verify .rodata is read-only. */
|
/* Verify .rodata is read-only. */
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, this->debug_handle, ro_start_address)) || mi.perm != Perm_R) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, this->debug_handle, ro_start_address)) || mi.perm != svc::MemoryPermission_Read) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -189,7 +189,7 @@ namespace ams::creport {
|
||||||
const u64 rw_start_address = mi.addr + mi.size;
|
const u64 rw_start_address = mi.addr + mi.size;
|
||||||
|
|
||||||
/* Read start of .rodata. */
|
/* Read start of .rodata. */
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(&rodata_start, this->debug_handle, ro_start_address, sizeof(rodata_start)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(rodata_start)), this->debug_handle, ro_start_address, sizeof(rodata_start)))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -226,15 +226,15 @@ namespace ams::creport {
|
||||||
std::memset(out_build_id, 0, ModuleBuildIdLength);
|
std::memset(out_build_id, 0, ModuleBuildIdLength);
|
||||||
|
|
||||||
/* Verify .rodata is read-only. */
|
/* Verify .rodata is read-only. */
|
||||||
MemoryInfo mi;
|
svc::MemoryInfo mi;
|
||||||
u32 pi;
|
svc::PageInfo pi;
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, this->debug_handle, ro_start_address)) || mi.perm != Perm_R) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, this->debug_handle, ro_start_address)) || mi.perm != svc::MemoryPermission_Read) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* We want to read the last two pages of .rodata. */
|
/* We want to read the last two pages of .rodata. */
|
||||||
const size_t read_size = mi.size >= sizeof(g_last_rodata_pages) ? sizeof(g_last_rodata_pages) : (sizeof(g_last_rodata_pages) / 2);
|
const size_t read_size = mi.size >= sizeof(g_last_rodata_pages) ? sizeof(g_last_rodata_pages) : (sizeof(g_last_rodata_pages) / 2);
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(g_last_rodata_pages, this->debug_handle, mi.addr + mi.size - read_size, read_size))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(g_last_rodata_pages), this->debug_handle, mi.addr + mi.size - read_size, read_size))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,14 +32,14 @@ namespace ams::creport {
|
||||||
u64 end_address;
|
u64 end_address;
|
||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
Handle debug_handle;
|
os::NativeHandle debug_handle;
|
||||||
size_t num_modules;
|
size_t num_modules;
|
||||||
ModuleInfo modules[ModuleCountMax];
|
ModuleInfo modules[ModuleCountMax];
|
||||||
|
|
||||||
/* For pretty-printing. */
|
/* For pretty-printing. */
|
||||||
char address_str_buf[0x280];
|
char address_str_buf[0x280];
|
||||||
public:
|
public:
|
||||||
ModuleList() : debug_handle(INVALID_HANDLE), num_modules(0) {
|
ModuleList() : debug_handle(os::InvalidNativeHandle), num_modules(0) {
|
||||||
std::memset(this->modules, 0, sizeof(this->modules));
|
std::memset(this->modules, 0, sizeof(this->modules));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +51,7 @@ namespace ams::creport {
|
||||||
return this->modules[i].start_address;
|
return this->modules[i].start_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
void FindModulesFromThreadInfo(Handle debug_handle, const ThreadInfo &thread);
|
void FindModulesFromThreadInfo(os::NativeHandle debug_handle, const ThreadInfo &thread);
|
||||||
const char *GetFormattedAddressString(uintptr_t address);
|
const char *GetFormattedAddressString(uintptr_t address);
|
||||||
void SaveToFile(ScopedFile &file);
|
void SaveToFile(ScopedFile &file);
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -34,7 +34,7 @@ namespace ams::creport {
|
||||||
|
|
||||||
/* Helpers. */
|
/* Helpers. */
|
||||||
template<typename T>
|
template<typename T>
|
||||||
void ReadStackTrace(size_t *out_trace_size, u64 *out_trace, size_t max_out_trace_size, Handle debug_handle, u64 fp) {
|
void ReadStackTrace(size_t *out_trace_size, u64 *out_trace, size_t max_out_trace_size, os::NativeHandle debug_handle, u64 fp) {
|
||||||
size_t trace_size = 0;
|
size_t trace_size = 0;
|
||||||
u64 cur_fp = fp;
|
u64 cur_fp = fp;
|
||||||
|
|
||||||
|
@ -46,7 +46,7 @@ namespace ams::creport {
|
||||||
|
|
||||||
/* Read a new frame. */
|
/* Read a new frame. */
|
||||||
StackFrame<T> cur_frame;
|
StackFrame<T> cur_frame;
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(cur_frame)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(cur_frame)), debug_handle, cur_fp, sizeof(cur_frame)))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,12 +79,12 @@ namespace ams::creport {
|
||||||
file.WriteFormat(" Registers:\n");
|
file.WriteFormat(" Registers:\n");
|
||||||
{
|
{
|
||||||
for (unsigned int i = 0; i <= 28; i++) {
|
for (unsigned int i = 0; i <= 28; i++) {
|
||||||
file.WriteFormat(" X[%02u]: %s\n", i, this->module_list->GetFormattedAddressString(this->context.cpu_gprs[i].x));
|
file.WriteFormat(" X[%02u]: %s\n", i, this->module_list->GetFormattedAddressString(this->context.r[i]));
|
||||||
}
|
}
|
||||||
file.WriteFormat(" FP: %s\n", this->module_list->GetFormattedAddressString(this->context.fp));
|
file.WriteFormat(" FP: %s\n", this->module_list->GetFormattedAddressString(this->context.fp));
|
||||||
file.WriteFormat(" LR: %s\n", this->module_list->GetFormattedAddressString(this->context.lr));
|
file.WriteFormat(" LR: %s\n", this->module_list->GetFormattedAddressString(this->context.lr));
|
||||||
file.WriteFormat(" SP: %s\n", this->module_list->GetFormattedAddressString(this->context.sp));
|
file.WriteFormat(" SP: %s\n", this->module_list->GetFormattedAddressString(this->context.sp));
|
||||||
file.WriteFormat(" PC: %s\n", this->module_list->GetFormattedAddressString(this->context.pc.x));
|
file.WriteFormat(" PC: %s\n", this->module_list->GetFormattedAddressString(this->context.pc));
|
||||||
}
|
}
|
||||||
if (this->stack_trace_size != 0) {
|
if (this->stack_trace_size != 0) {
|
||||||
file.WriteFormat(" Stack Trace:\n");
|
file.WriteFormat(" Stack Trace:\n");
|
||||||
|
@ -113,7 +113,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ThreadInfo::ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit) {
|
bool ThreadInfo::ReadFromProcess(os::NativeHandle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit) {
|
||||||
/* Set thread id. */
|
/* Set thread id. */
|
||||||
this->thread_id = thread_id;
|
this->thread_id = thread_id;
|
||||||
|
|
||||||
|
@ -121,7 +121,7 @@ namespace ams::creport {
|
||||||
{
|
{
|
||||||
u64 _;
|
u64 _;
|
||||||
u32 _thread_state;
|
u32 _thread_state;
|
||||||
if (R_FAILED(svcGetDebugThreadParam(&_, &_thread_state, debug_handle, this->thread_id, DebugThreadParam_State))) {
|
if (R_FAILED(svc::GetDebugThreadParam(&_, &_thread_state, debug_handle, this->thread_id, svc::DebugThreadParam_State))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -132,29 +132,29 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the thread context. */
|
/* Get the thread context. */
|
||||||
if (R_FAILED(svcGetDebugThreadContext(&this->context, debug_handle, this->thread_id, svc::ThreadContextFlag_All))) {
|
if (R_FAILED(svc::GetDebugThreadContext(&this->context, debug_handle, this->thread_id, svc::ThreadContextFlag_All))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* In aarch32 mode svcGetDebugThreadContext does not set the LR, FP, and SP registers correctly. */
|
/* In aarch32 mode svc::GetDebugThreadContext does not set the LR, FP, and SP registers correctly. */
|
||||||
if (!is_64_bit) {
|
if (!is_64_bit) {
|
||||||
this->context.fp = this->context.cpu_gprs[11].x;
|
this->context.fp = this->context.r[11];
|
||||||
this->context.sp = this->context.cpu_gprs[13].x;
|
this->context.sp = this->context.r[13];
|
||||||
this->context.lr = this->context.cpu_gprs[14].x;
|
this->context.lr = this->context.r[14];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read TLS, if present. */
|
/* Read TLS, if present. */
|
||||||
/* TODO: struct definitions for nnSdk's ThreadType/TLS Layout? */
|
/* TODO: struct definitions for nnSdk's ThreadType/TLS Layout? */
|
||||||
this->tls_address = 0;
|
this->tls_address = 0;
|
||||||
if (tls_map.GetThreadTls(std::addressof(this->tls_address), thread_id)) {
|
if (tls_map.GetThreadTls(std::addressof(this->tls_address), thread_id)) {
|
||||||
u8 thread_tls[0x200];
|
u8 thread_tls[sizeof(svc::ThreadLocalRegion)];
|
||||||
if (R_SUCCEEDED(svcReadDebugProcessMemory(thread_tls, debug_handle, this->tls_address, sizeof(thread_tls)))) {
|
if (R_SUCCEEDED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(thread_tls), debug_handle, this->tls_address, sizeof(thread_tls)))) {
|
||||||
std::memcpy(this->tls, thread_tls, sizeof(this->tls));
|
std::memcpy(this->tls, thread_tls, sizeof(this->tls));
|
||||||
/* Try to detect libnx threads, and skip name parsing then. */
|
/* Try to detect libnx threads, and skip name parsing then. */
|
||||||
if (*(reinterpret_cast<u32 *>(&thread_tls[0x1E0])) != LibnxThreadVarMagic) {
|
if (*(reinterpret_cast<u32 *>(&thread_tls[0x1E0])) != LibnxThreadVarMagic) {
|
||||||
u8 thread_type[0x1C0];
|
u8 thread_type[0x1C0];
|
||||||
const u64 thread_type_addr = *(reinterpret_cast<u64 *>(&thread_tls[0x1F8]));
|
const u64 thread_type_addr = *(reinterpret_cast<u64 *>(&thread_tls[0x1F8]));
|
||||||
if (R_SUCCEEDED(svcReadDebugProcessMemory(thread_type, debug_handle, thread_type_addr, sizeof(thread_type)))) {
|
if (R_SUCCEEDED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(thread_type), debug_handle, thread_type_addr, sizeof(thread_type)))) {
|
||||||
/* Get the thread version. */
|
/* Get the thread version. */
|
||||||
const u16 thread_version = *reinterpret_cast<u16 *>(&thread_type[0x46]);
|
const u16 thread_version = *reinterpret_cast<u16 *>(&thread_type[0x46]);
|
||||||
if (thread_version == 0 || thread_version == 0xFFFF) {
|
if (thread_version == 0 || thread_version == 0xFFFF) {
|
||||||
|
@ -187,18 +187,18 @@ namespace ams::creport {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadInfo::TryGetStackInfo(Handle debug_handle) {
|
void ThreadInfo::TryGetStackInfo(os::NativeHandle debug_handle) {
|
||||||
/* Query stack region. */
|
/* Query stack region. */
|
||||||
MemoryInfo mi;
|
svc::MemoryInfo mi;
|
||||||
u32 pi;
|
svc::PageInfo pi;
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, this->context.sp))) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, debug_handle, this->context.sp))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Check if sp points into the stack. */
|
/* Check if sp points into the stack. */
|
||||||
if (mi.type != MemType_MappedMemory) {
|
if (mi.state != svc::MemoryState_Stack) {
|
||||||
/* It's possible that sp is below the stack... */
|
/* It's possible that sp is below the stack... */
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr + mi.size)) || mi.type != MemType_MappedMemory) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, debug_handle, mi.addr + mi.size)) || mi.state != svc::MemoryState_Stack) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -212,7 +212,7 @@ namespace ams::creport {
|
||||||
this->stack_dump_base = std::min(std::max(this->context.sp & ~0xFul, this->stack_bottom), this->stack_top - sizeof(this->stack_dump));
|
this->stack_dump_base = std::min(std::max(this->context.sp & ~0xFul, this->stack_bottom), this->stack_top - sizeof(this->stack_dump));
|
||||||
|
|
||||||
/* Try to read stack. */
|
/* Try to read stack. */
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(this->stack_dump, debug_handle, this->stack_dump_base, sizeof(this->stack_dump)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(this->stack_dump), debug_handle, this->stack_dump_base, sizeof(this->stack_dump)))) {
|
||||||
this->stack_dump_base = 0;
|
this->stack_dump_base = 0;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -252,7 +252,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ThreadList::ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit) {
|
void ThreadList::ReadFromProcess(os::NativeHandle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit) {
|
||||||
this->thread_count = 0;
|
this->thread_count = 0;
|
||||||
|
|
||||||
/* Get thread list. */
|
/* Get thread list. */
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace ams::creport {
|
||||||
static constexpr size_t StackTraceSizeMax = 0x20;
|
static constexpr size_t StackTraceSizeMax = 0x20;
|
||||||
static constexpr size_t NameLengthMax = 0x20;
|
static constexpr size_t NameLengthMax = 0x20;
|
||||||
private:
|
private:
|
||||||
ThreadContext context = {};
|
svc::ThreadContext context = {};
|
||||||
u64 thread_id = 0;
|
u64 thread_id = 0;
|
||||||
u64 stack_top = 0;
|
u64 stack_top = 0;
|
||||||
u64 stack_bottom = 0;
|
u64 stack_bottom = 0;
|
||||||
|
@ -74,11 +74,11 @@ namespace ams::creport {
|
||||||
ModuleList *module_list = nullptr;
|
ModuleList *module_list = nullptr;
|
||||||
public:
|
public:
|
||||||
u64 GetGeneralPurposeRegister(size_t i) const {
|
u64 GetGeneralPurposeRegister(size_t i) const {
|
||||||
return this->context.cpu_gprs[i].x;
|
return this->context.r[i];
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetPC() const {
|
u64 GetPC() const {
|
||||||
return this->context.pc.x;
|
return this->context.pc;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetLR() const {
|
u64 GetLR() const {
|
||||||
|
@ -109,11 +109,11 @@ namespace ams::creport {
|
||||||
this->module_list = ml;
|
this->module_list = ml;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit);
|
bool ReadFromProcess(os::NativeHandle debug_handle, ThreadTlsMap &tls_map, u64 thread_id, bool is_64_bit);
|
||||||
void SaveToFile(ScopedFile &file);
|
void SaveToFile(ScopedFile &file);
|
||||||
void DumpBinary(ScopedFile &file);
|
void DumpBinary(ScopedFile &file);
|
||||||
private:
|
private:
|
||||||
void TryGetStackInfo(Handle debug_handle);
|
void TryGetStackInfo(os::NativeHandle debug_handle);
|
||||||
};
|
};
|
||||||
|
|
||||||
class ThreadList {
|
class ThreadList {
|
||||||
|
@ -135,7 +135,7 @@ namespace ams::creport {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void ReadFromProcess(Handle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit);
|
void ReadFromProcess(os::NativeHandle debug_handle, ThreadTlsMap &tls_map, bool is_64_bit);
|
||||||
void SaveToFile(ScopedFile &file);
|
void SaveToFile(ScopedFile &file);
|
||||||
void DumpBinary(ScopedFile &file, u64 crashed_thread_id);
|
void DumpBinary(ScopedFile &file, u64 crashed_thread_id);
|
||||||
};
|
};
|
||||||
|
|
|
@ -60,7 +60,7 @@ namespace ams::dmnt::cheat {
|
||||||
return dmnt::cheat::impl::GetCheatProcessMappingCount(out_count.GetPointer());
|
return dmnt::cheat::impl::GetCheatProcessMappingCount(out_count.GetPointer());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheatService::GetCheatProcessMappings(const sf::OutArray<MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset) {
|
Result CheatService::GetCheatProcessMappings(const sf::OutArray<svc::MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset) {
|
||||||
R_UNLESS(mappings.GetPointer() != nullptr, ResultCheatNullBuffer());
|
R_UNLESS(mappings.GetPointer() != nullptr, ResultCheatNullBuffer());
|
||||||
return dmnt::cheat::impl::GetCheatProcessMappings(mappings.GetPointer(), mappings.GetSize(), out_count.GetPointer(), offset);
|
return dmnt::cheat::impl::GetCheatProcessMappings(mappings.GetPointer(), mappings.GetSize(), out_count.GetPointer(), offset);
|
||||||
}
|
}
|
||||||
|
@ -75,7 +75,7 @@ namespace ams::dmnt::cheat {
|
||||||
return dmnt::cheat::impl::WriteCheatProcessMemory(address, buffer.GetPointer(), std::min(in_size, buffer.GetSize()));
|
return dmnt::cheat::impl::WriteCheatProcessMemory(address, buffer.GetPointer(), std::min(in_size, buffer.GetSize()));
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CheatService::QueryCheatProcessMemory(sf::Out<MemoryInfo> mapping, u64 address) {
|
Result CheatService::QueryCheatProcessMemory(sf::Out<svc::MemoryInfo> mapping, u64 address) {
|
||||||
return dmnt::cheat::impl::QueryCheatProcessMemory(mapping.GetPointer(), address);
|
return dmnt::cheat::impl::QueryCheatProcessMemory(mapping.GetPointer(), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -26,10 +26,10 @@
|
||||||
AMS_SF_METHOD_INFO(C, H, 65005, Result, ResumeCheatProcess, (), ()) \
|
AMS_SF_METHOD_INFO(C, H, 65005, Result, ResumeCheatProcess, (), ()) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65006, Result, ForceCloseCheatProcess, (), ()) \
|
AMS_SF_METHOD_INFO(C, H, 65006, Result, ForceCloseCheatProcess, (), ()) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65100, Result, GetCheatProcessMappingCount, (sf::Out<u64> out_count), (out_count)) \
|
AMS_SF_METHOD_INFO(C, H, 65100, Result, GetCheatProcessMappingCount, (sf::Out<u64> out_count), (out_count)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65101, Result, GetCheatProcessMappings, (const sf::OutArray<MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset), (mappings, out_count, offset)) \
|
AMS_SF_METHOD_INFO(C, H, 65101, Result, GetCheatProcessMappings, (const sf::OutArray<svc::MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset), (mappings, out_count, offset)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65102, Result, ReadCheatProcessMemory, (const sf::OutBuffer &buffer, u64 address, u64 out_size), (buffer, address, out_size)) \
|
AMS_SF_METHOD_INFO(C, H, 65102, Result, ReadCheatProcessMemory, (const sf::OutBuffer &buffer, u64 address, u64 out_size), (buffer, address, out_size)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65103, Result, WriteCheatProcessMemory, (const sf::InBuffer &buffer, u64 address, u64 in_size), (buffer, address, in_size)) \
|
AMS_SF_METHOD_INFO(C, H, 65103, Result, WriteCheatProcessMemory, (const sf::InBuffer &buffer, u64 address, u64 in_size), (buffer, address, in_size)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65104, Result, QueryCheatProcessMemory, (sf::Out<MemoryInfo> mapping, u64 address), (mapping, address)) \
|
AMS_SF_METHOD_INFO(C, H, 65104, Result, QueryCheatProcessMemory, (sf::Out<svc::MemoryInfo> mapping, u64 address), (mapping, address)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65200, Result, GetCheatCount, (sf::Out<u64> out_count), (out_count)) \
|
AMS_SF_METHOD_INFO(C, H, 65200, Result, GetCheatCount, (sf::Out<u64> out_count), (out_count)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65201, Result, GetCheats, (const sf::OutArray<dmnt::cheat::CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset), (cheats, out_count, offset)) \
|
AMS_SF_METHOD_INFO(C, H, 65201, Result, GetCheats, (const sf::OutArray<dmnt::cheat::CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset), (cheats, out_count, offset)) \
|
||||||
AMS_SF_METHOD_INFO(C, H, 65202, Result, GetCheatById, (sf::Out<dmnt::cheat::CheatEntry> cheat, u32 cheat_id), (cheat, cheat_id)) \
|
AMS_SF_METHOD_INFO(C, H, 65202, Result, GetCheatById, (sf::Out<dmnt::cheat::CheatEntry> cheat, u32 cheat_id), (cheat, cheat_id)) \
|
||||||
|
@ -61,10 +61,10 @@ namespace ams::dmnt::cheat {
|
||||||
Result ForceCloseCheatProcess();
|
Result ForceCloseCheatProcess();
|
||||||
|
|
||||||
Result GetCheatProcessMappingCount(sf::Out<u64> out_count);
|
Result GetCheatProcessMappingCount(sf::Out<u64> out_count);
|
||||||
Result GetCheatProcessMappings(const sf::OutArray<MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset);
|
Result GetCheatProcessMappings(const sf::OutArray<svc::MemoryInfo> &mappings, sf::Out<u64> out_count, u64 offset);
|
||||||
Result ReadCheatProcessMemory(const sf::OutBuffer &buffer, u64 address, u64 out_size);
|
Result ReadCheatProcessMemory(const sf::OutBuffer &buffer, u64 address, u64 out_size);
|
||||||
Result WriteCheatProcessMemory(const sf::InBuffer &buffer, u64 address, u64 in_size);
|
Result WriteCheatProcessMemory(const sf::InBuffer &buffer, u64 address, u64 in_size);
|
||||||
Result QueryCheatProcessMemory(sf::Out<MemoryInfo> mapping, u64 address);
|
Result QueryCheatProcessMemory(sf::Out<svc::MemoryInfo> mapping, u64 address);
|
||||||
|
|
||||||
Result GetCheatCount(sf::Out<u64> out_count);
|
Result GetCheatCount(sf::Out<u64> out_count);
|
||||||
Result GetCheats(const sf::OutArray<CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset);
|
Result GetCheats(const sf::OutArray<CheatEntry> &cheats, sf::Out<u64> out_count, u64 offset);
|
||||||
|
|
|
@ -307,11 +307,11 @@ namespace ams::dmnt::cheat::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ReadCheatProcessMemoryUnsafe(u64 proc_addr, void *out_data, size_t size) {
|
Result ReadCheatProcessMemoryUnsafe(u64 proc_addr, void *out_data, size_t size) {
|
||||||
return svcReadDebugProcessMemory(out_data, this->GetCheatProcessHandle(), proc_addr, size);
|
return svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(out_data), this->GetCheatProcessHandle(), proc_addr, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result WriteCheatProcessMemoryUnsafe(u64 proc_addr, const void *data, size_t size) {
|
Result WriteCheatProcessMemoryUnsafe(u64 proc_addr, const void *data, size_t size) {
|
||||||
R_TRY(svcWriteDebugProcessMemory(this->GetCheatProcessHandle(), data, proc_addr, size));
|
R_TRY(svc::WriteDebugProcessMemory(this->GetCheatProcessHandle(), reinterpret_cast<uintptr_t>(data), proc_addr, size));
|
||||||
|
|
||||||
for (auto &entry : this->frozen_addresses_map) {
|
for (auto &entry : this->frozen_addresses_map) {
|
||||||
/* Get address/value. */
|
/* Get address/value. */
|
||||||
|
@ -337,7 +337,7 @@ namespace ams::dmnt::cheat::impl {
|
||||||
Result PauseCheatProcessUnsafe() {
|
Result PauseCheatProcessUnsafe() {
|
||||||
this->broken_unsafe = true;
|
this->broken_unsafe = true;
|
||||||
this->unsafe_break_event.Clear();
|
this->unsafe_break_event.Clear();
|
||||||
return svcBreakDebugProcess(this->GetCheatProcessHandle());
|
return svc::BreakDebugProcess(this->GetCheatProcessHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ResumeCheatProcessUnsafe() {
|
Result ResumeCheatProcessUnsafe() {
|
||||||
|
@ -352,16 +352,15 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
MemoryInfo mem_info;
|
svc::MemoryInfo mem_info;
|
||||||
|
svc::PageInfo page_info;
|
||||||
u64 address = 0, count = 0;
|
u64 address = 0, count = 0;
|
||||||
do {
|
do {
|
||||||
mem_info.perm = Perm_None;
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mem_info, &page_info, this->GetCheatProcessHandle(), address))) {
|
||||||
u32 tmp;
|
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mem_info, &tmp, this->GetCheatProcessHandle(), address))) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_info.perm != Perm_None) {
|
if (mem_info.perm != svc::MemoryPermission_None) {
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -372,21 +371,20 @@ namespace ams::dmnt::cheat::impl {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetCheatProcessMappings(MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset) {
|
Result GetCheatProcessMappings(svc::MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset) {
|
||||||
std::scoped_lock lk(this->cheat_lock);
|
std::scoped_lock lk(this->cheat_lock);
|
||||||
|
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
MemoryInfo mem_info;
|
svc::MemoryInfo mem_info;
|
||||||
|
svc::PageInfo page_info;
|
||||||
u64 address = 0, total_count = 0, written_count = 0;
|
u64 address = 0, total_count = 0, written_count = 0;
|
||||||
do {
|
do {
|
||||||
mem_info.perm = Perm_None;
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mem_info, &page_info, this->GetCheatProcessHandle(), address))) {
|
||||||
u32 tmp;
|
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mem_info, &tmp, this->GetCheatProcessHandle(), address))) {
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mem_info.perm != Perm_None) {
|
if (mem_info.perm != svc::MemoryPermission_None) {
|
||||||
if (offset <= total_count && written_count < max_count) {
|
if (offset <= total_count && written_count < max_count) {
|
||||||
mappings[written_count++] = mem_info;
|
mappings[written_count++] = mem_info;
|
||||||
}
|
}
|
||||||
|
@ -416,13 +414,13 @@ namespace ams::dmnt::cheat::impl {
|
||||||
return this->WriteCheatProcessMemoryUnsafe(proc_addr, data, size);
|
return this->WriteCheatProcessMemoryUnsafe(proc_addr, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result QueryCheatProcessMemory(MemoryInfo *mapping, u64 address) {
|
Result QueryCheatProcessMemory(svc::MemoryInfo *mapping, u64 address) {
|
||||||
std::scoped_lock lk(this->cheat_lock);
|
std::scoped_lock lk(this->cheat_lock);
|
||||||
|
|
||||||
R_TRY(this->EnsureCheatProcess());
|
R_TRY(this->EnsureCheatProcess());
|
||||||
|
|
||||||
u32 tmp;
|
svc::PageInfo page_info;
|
||||||
return svcQueryDebugProcessMemory(mapping, &tmp, this->GetCheatProcessHandle(), address);
|
return svc::QueryDebugProcessMemory(mapping, &page_info, this->GetCheatProcessHandle(), address);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result PauseCheatProcess() {
|
Result PauseCheatProcess() {
|
||||||
|
@ -693,8 +691,9 @@ namespace ams::dmnt::cheat::impl {
|
||||||
/* Atomically wait (and clear) signal for new process. */
|
/* Atomically wait (and clear) signal for new process. */
|
||||||
this_ptr->debug_events_event.Wait();
|
this_ptr->debug_events_event.Wait();
|
||||||
while (true) {
|
while (true) {
|
||||||
Handle cheat_process_handle = this_ptr->GetCheatProcessHandle();
|
os::NativeHandle cheat_process_handle = this_ptr->GetCheatProcessHandle();
|
||||||
while (cheat_process_handle != svc::InvalidHandle && R_SUCCEEDED(svcWaitSynchronizationSingle(this_ptr->GetCheatProcessHandle(), std::numeric_limits<u64>::max()))) {
|
s32 dummy;
|
||||||
|
while (cheat_process_handle != os::InvalidNativeHandle && R_SUCCEEDED(svc::WaitSynchronization(std::addressof(dummy), std::addressof(cheat_process_handle), 1, std::numeric_limits<u64>::max()))) {
|
||||||
this_ptr->cheat_lock.Lock();
|
this_ptr->cheat_lock.Lock();
|
||||||
ON_SCOPE_EXIT { this_ptr->cheat_lock.Unlock(); };
|
ON_SCOPE_EXIT { this_ptr->cheat_lock.Unlock(); };
|
||||||
{
|
{
|
||||||
|
@ -758,16 +757,16 @@ namespace ams::dmnt::cheat::impl {
|
||||||
const auto &value = entry.GetValue();
|
const auto &value = entry.GetValue();
|
||||||
|
|
||||||
/* Use Write SVC directly, to avoid the usual frozen address update logic. */
|
/* Use Write SVC directly, to avoid the usual frozen address update logic. */
|
||||||
svcWriteDebugProcessMemory(this_ptr->GetCheatProcessHandle(), &value.value, address, value.width);
|
svc::WriteDebugProcessMemory(this_ptr->GetCheatProcessHandle(), reinterpret_cast<uintptr_t>(std::addressof(value.value)), address, value.width);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Sleep until next potential execution. */
|
/* Sleep until next potential execution. */
|
||||||
constexpr u64 ONE_SECOND = 1'000'000'000ul;
|
constexpr s64 TimesPerSecond = 12;
|
||||||
constexpr u64 TIMES_PER_SECOND = 12;
|
constexpr s64 DelayNanoSeconds = TimeSpan::FromSeconds(1).GetNanoSeconds() / TimesPerSecond;
|
||||||
constexpr u64 DELAY_TIME = ONE_SECOND / TIMES_PER_SECOND;
|
constexpr TimeSpan Delay = TimeSpan::FromNanoSeconds(DelayNanoSeconds);
|
||||||
svcSleepThread(DELAY_TIME);
|
os::SleepThread(Delay);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -803,10 +802,10 @@ namespace ams::dmnt::cheat::impl {
|
||||||
|
|
||||||
/* Get process handle, use it to learn memory extents. */
|
/* Get process handle, use it to learn memory extents. */
|
||||||
{
|
{
|
||||||
Handle proc_h = svc::InvalidHandle;
|
os::NativeHandle proc_h = os::InvalidNativeHandle;
|
||||||
ncm::ProgramLocation loc = {};
|
ncm::ProgramLocation loc = {};
|
||||||
cfg::OverrideStatus status = {};
|
cfg::OverrideStatus status = {};
|
||||||
ON_SCOPE_EXIT { if (proc_h != svc::InvalidHandle) { R_ABORT_UNLESS(svcCloseHandle(proc_h)); } };
|
ON_SCOPE_EXIT { os::CloseNativeHandle(proc_h); };
|
||||||
|
|
||||||
R_ABORT_UNLESS_IF_NEW_PROCESS(pm::dmnt::AtmosphereGetProcessInfo(&proc_h, &loc, &status, this->cheat_process_metadata.process_id));
|
R_ABORT_UNLESS_IF_NEW_PROCESS(pm::dmnt::AtmosphereGetProcessInfo(&proc_h, &loc, &status, this->cheat_process_metadata.process_id));
|
||||||
this->cheat_process_metadata.program_id = loc.program_id;
|
this->cheat_process_metadata.program_id = loc.program_id;
|
||||||
|
@ -1238,7 +1237,7 @@ namespace ams::dmnt::cheat::impl {
|
||||||
return GetReference(g_cheat_process_manager).GetCheatProcessMappingCount(out_count);
|
return GetReference(g_cheat_process_manager).GetCheatProcessMappingCount(out_count);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetCheatProcessMappings(MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset) {
|
Result GetCheatProcessMappings(svc::MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset) {
|
||||||
return GetReference(g_cheat_process_manager).GetCheatProcessMappings(mappings, max_count, out_count, offset);
|
return GetReference(g_cheat_process_manager).GetCheatProcessMappings(mappings, max_count, out_count, offset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1250,7 +1249,7 @@ namespace ams::dmnt::cheat::impl {
|
||||||
return GetReference(g_cheat_process_manager).WriteCheatProcessMemory(proc_addr, data, size);
|
return GetReference(g_cheat_process_manager).WriteCheatProcessMemory(proc_addr, data, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result QueryCheatProcessMemory(MemoryInfo *mapping, u64 address) {
|
Result QueryCheatProcessMemory(svc::MemoryInfo *mapping, u64 address) {
|
||||||
return GetReference(g_cheat_process_manager).QueryCheatProcessMemory(mapping, address);
|
return GetReference(g_cheat_process_manager).QueryCheatProcessMemory(mapping, address);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -35,10 +35,10 @@ namespace ams::dmnt::cheat::impl {
|
||||||
Result ResumeCheatProcessUnsafe();
|
Result ResumeCheatProcessUnsafe();
|
||||||
|
|
||||||
Result GetCheatProcessMappingCount(u64 *out_count);
|
Result GetCheatProcessMappingCount(u64 *out_count);
|
||||||
Result GetCheatProcessMappings(MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset);
|
Result GetCheatProcessMappings(svc::MemoryInfo *mappings, size_t max_count, u64 *out_count, u64 offset);
|
||||||
Result ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size);
|
Result ReadCheatProcessMemory(u64 proc_addr, void *out_data, size_t size);
|
||||||
Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size);
|
Result WriteCheatProcessMemory(u64 proc_addr, const void *data, size_t size);
|
||||||
Result QueryCheatProcessMemory(MemoryInfo *mapping, u64 address);
|
Result QueryCheatProcessMemory(svc::MemoryInfo *mapping, u64 address);
|
||||||
|
|
||||||
Result GetCheatCount(u64 *out_count);
|
Result GetCheatCount(u64 *out_count);
|
||||||
Result GetCheats(CheatEntry *cheats, size_t max_count, u64 *out_count, u64 offset);
|
Result GetCheats(CheatEntry *cheats, size_t max_count, u64 *out_count, u64 offset);
|
||||||
|
|
|
@ -38,10 +38,10 @@ namespace ams::dmnt::cheat::impl {
|
||||||
static void PerCoreThreadFunction(void *_this) {
|
static void PerCoreThreadFunction(void *_this) {
|
||||||
/* This thread will wait on the appropriate message queue. */
|
/* This thread will wait on the appropriate message queue. */
|
||||||
DebugEventsManager *this_ptr = reinterpret_cast<DebugEventsManager *>(_this);
|
DebugEventsManager *this_ptr = reinterpret_cast<DebugEventsManager *>(_this);
|
||||||
const size_t current_core = svcGetCurrentProcessorNumber();
|
const size_t current_core = svc::GetCurrentProcessorNumber();
|
||||||
while (true) {
|
while (true) {
|
||||||
/* Receive handle. */
|
/* Receive handle. */
|
||||||
Handle debug_handle = this_ptr->WaitReceiveHandle(current_core);
|
os::NativeHandle debug_handle = this_ptr->WaitReceiveHandle(current_core);
|
||||||
|
|
||||||
/* Continue events on the correct core. */
|
/* Continue events on the correct core. */
|
||||||
Result result = this_ptr->ContinueDebugEvent(debug_handle);
|
Result result = this_ptr->ContinueDebugEvent(debug_handle);
|
||||||
|
@ -51,7 +51,7 @@ namespace ams::dmnt::cheat::impl {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetTargetCore(size_t *out, const svc::DebugEventInfo &dbg_event, Handle debug_handle) {
|
Result GetTargetCore(size_t *out, const svc::DebugEventInfo &dbg_event, os::NativeHandle debug_handle) {
|
||||||
/* If we don't need to continue on a specific core, use the system core. */
|
/* If we don't need to continue on a specific core, use the system core. */
|
||||||
size_t target_core = NumCores - 1;
|
size_t target_core = NumCores - 1;
|
||||||
|
|
||||||
|
@ -60,7 +60,7 @@ namespace ams::dmnt::cheat::impl {
|
||||||
u64 out64 = 0;
|
u64 out64 = 0;
|
||||||
u32 out32 = 0;
|
u32 out32 = 0;
|
||||||
|
|
||||||
R_TRY_CATCH(svcGetDebugThreadParam(&out64, &out32, debug_handle, dbg_event.info.create_thread.thread_id, DebugThreadParam_CurrentCore)) {
|
R_TRY_CATCH(svc::GetDebugThreadParam(&out64, &out32, debug_handle, dbg_event.info.create_thread.thread_id, svc::DebugThreadParam_CurrentCore)) {
|
||||||
R_CATCH_RETHROW(svc::ResultProcessTerminated)
|
R_CATCH_RETHROW(svc::ResultProcessTerminated)
|
||||||
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
} R_END_TRY_CATCH_WITH_ABORT_UNLESS;
|
||||||
|
|
||||||
|
@ -72,21 +72,21 @@ namespace ams::dmnt::cheat::impl {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
void SendHandle(size_t target_core, Handle debug_handle) {
|
void SendHandle(size_t target_core, os::NativeHandle debug_handle) {
|
||||||
this->handle_message_queues[target_core].Send(static_cast<uintptr_t>(debug_handle));
|
this->handle_message_queues[target_core].Send(static_cast<uintptr_t>(debug_handle));
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle WaitReceiveHandle(size_t core_id) {
|
os::NativeHandle WaitReceiveHandle(size_t core_id) {
|
||||||
uintptr_t x = 0;
|
uintptr_t x = 0;
|
||||||
this->handle_message_queues[core_id].Receive(&x);
|
this->handle_message_queues[core_id].Receive(&x);
|
||||||
return static_cast<Handle>(x);
|
return static_cast<os::NativeHandle>(x);
|
||||||
}
|
}
|
||||||
|
|
||||||
Result ContinueDebugEvent(Handle debug_handle) {
|
Result ContinueDebugEvent(os::NativeHandle debug_handle) {
|
||||||
if (hos::GetVersion() >= hos::Version_3_0_0) {
|
if (hos::GetVersion() >= hos::Version_3_0_0) {
|
||||||
return svcContinueDebugEvent(debug_handle, 5, nullptr, 0);
|
return svc::ContinueDebugEvent(debug_handle, svc::ContinueFlag_ExceptionHandled | svc::ContinueFlag_ContinueAll, nullptr, 0);
|
||||||
} else {
|
} else {
|
||||||
return svcLegacyContinueDebugEvent(debug_handle, 5, 0);
|
return svc::LegacyContinueDebugEvent(debug_handle, svc::ContinueFlag_ExceptionHandled | svc::ContinueFlag_ContinueAll, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -63,40 +63,40 @@ namespace ams::fatal::srv {
|
||||||
|
|
||||||
constinit ThreadTlsMap g_thread_id_to_tls_map;
|
constinit ThreadTlsMap g_thread_id_to_tls_map;
|
||||||
|
|
||||||
bool IsThreadFatalCaller(Result result, u32 debug_handle, u64 thread_id, u64 thread_tls_addr, ThreadContext *thread_ctx) {
|
bool IsThreadFatalCaller(Result result, os::NativeHandle debug_handle, u64 thread_id, u64 thread_tls_addr, svc::ThreadContext *thread_ctx) {
|
||||||
/* Verify that the thread is running or waiting. */
|
/* Verify that the thread is running or waiting. */
|
||||||
{
|
{
|
||||||
u64 _;
|
u64 _;
|
||||||
u32 _thread_state;
|
u32 _thread_state;
|
||||||
if (R_FAILED(svcGetDebugThreadParam(&_, &_thread_state, debug_handle, thread_id, DebugThreadParam_State))) {
|
if (R_FAILED(svc::GetDebugThreadParam(&_, &_thread_state, debug_handle, thread_id, svc::DebugThreadParam_State))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
const svc::ThreadState thread_state = static_cast<svc::ThreadState>(_thread_state);
|
const auto thread_state = static_cast<svc::ThreadState>(_thread_state);
|
||||||
if (thread_state != svc::ThreadState_Waiting && thread_state != svc::ThreadState_Running) {
|
if (thread_state != svc::ThreadState_Waiting && thread_state != svc::ThreadState_Running) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Get the thread context. */
|
/* Get the thread context. */
|
||||||
if (R_FAILED(svcGetDebugThreadContext(thread_ctx, debug_handle, thread_id, svc::ThreadContextFlag_All))) {
|
if (R_FAILED(svc::GetDebugThreadContext(thread_ctx, debug_handle, thread_id, svc::ThreadContextFlag_All))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to read the current instruction. */
|
/* Try to read the current instruction. */
|
||||||
u32 insn;
|
u32 insn;
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(&insn, debug_handle, thread_ctx->pc.x, sizeof(insn)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(insn)), debug_handle, thread_ctx->pc, sizeof(insn)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If the instruction isn't svcSendSyncRequest, it's not the fatal caller. */
|
/* If the instruction isn't svc::SendSyncRequest, it's not the fatal caller. */
|
||||||
if (insn != SvcSendSyncRequestInstruction) {
|
if (insn != SvcSendSyncRequestInstruction) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read in the fatal caller's TLS. */
|
/* Read in the fatal caller's TLS. */
|
||||||
u8 thread_tls[0x100];
|
u8 thread_tls[sizeof(svc::ThreadLocalRegion::message_buffer)];
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(thread_tls, debug_handle, thread_tls_addr, sizeof(thread_tls)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(thread_tls), debug_handle, thread_tls_addr, sizeof(thread_tls)))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,20 +156,20 @@ namespace ams::fatal::srv {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool TryGuessBaseAddress(u64 *out_base_address, u32 debug_handle, u64 guess) {
|
bool TryGuessBaseAddress(u64 *out_base_address, os::NativeHandle debug_handle, u64 guess) {
|
||||||
MemoryInfo mi;
|
svc::MemoryInfo mi;
|
||||||
u32 pi;
|
svc::PageInfo pi;
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess)) || mi.perm != Perm_Rx) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, debug_handle, guess)) || mi.perm != svc::MemoryPermission_ReadExecute) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Iterate backwards until we find the memory before the code region. */
|
/* Iterate backwards until we find the memory before the code region. */
|
||||||
while (mi.addr > 0) {
|
while (mi.addr > 0) {
|
||||||
if (R_FAILED(svcQueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) {
|
if (R_FAILED(svc::QueryDebugProcessMemory(&mi, &pi, debug_handle, guess))) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (mi.type == MemType_Unmapped) {
|
if (mi.state == svc::MemoryState_Free) {
|
||||||
/* Code region will be at the end of the unmapped region preceding it. */
|
/* Code region will be at the end of the unmapped region preceding it. */
|
||||||
*out_base_address = mi.addr + mi.size;
|
*out_base_address = mi.addr + mi.size;
|
||||||
return true;
|
return true;
|
||||||
|
@ -181,10 +181,10 @@ namespace ams::fatal::srv {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetBaseAddress(const ThrowContext *throw_ctx, const ThreadContext *thread_ctx, u32 debug_handle) {
|
u64 GetBaseAddress(const ThrowContext *throw_ctx, const svc::ThreadContext *thread_ctx, os::NativeHandle debug_handle) {
|
||||||
u64 base_address = 0;
|
u64 base_address = 0;
|
||||||
|
|
||||||
if (TryGuessBaseAddress(&base_address, debug_handle, thread_ctx->pc.x)) {
|
if (TryGuessBaseAddress(&base_address, debug_handle, thread_ctx->pc)) {
|
||||||
return base_address;
|
return base_address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -205,18 +205,18 @@ namespace ams::fatal::srv {
|
||||||
|
|
||||||
void TryCollectDebugInformation(ThrowContext *ctx, os::ProcessId process_id) {
|
void TryCollectDebugInformation(ThrowContext *ctx, os::ProcessId process_id) {
|
||||||
/* Try to debug the process. This may fail, if we called into ourself. */
|
/* Try to debug the process. This may fail, if we called into ourself. */
|
||||||
Handle debug_handle;
|
os::NativeHandle debug_handle;
|
||||||
if (R_FAILED(svcDebugActiveProcess(std::addressof(debug_handle), static_cast<u64>(process_id)))) {
|
if (R_FAILED(svc::DebugActiveProcess(std::addressof(debug_handle), process_id.value))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
ON_SCOPE_EXIT { R_ABORT_UNLESS(svc::CloseHandle(debug_handle)); };
|
ON_SCOPE_EXIT { os::CloseNativeHandle(debug_handle); };
|
||||||
|
|
||||||
/* First things first, check if process is 64 bits, and get list of thread infos. */
|
/* First things first, check if process is 64 bits, and get list of thread infos. */
|
||||||
g_thread_id_to_tls_map.ResetThreadTlsMap();
|
g_thread_id_to_tls_map.ResetThreadTlsMap();
|
||||||
{
|
{
|
||||||
bool got_create_process = false;
|
bool got_create_process = false;
|
||||||
svc::DebugEventInfo d;
|
svc::DebugEventInfo d;
|
||||||
while (R_SUCCEEDED(svcGetDebugEvent(reinterpret_cast<u8 *>(&d), debug_handle))) {
|
while (R_SUCCEEDED(svc::GetDebugEvent(std::addressof(d), debug_handle))) {
|
||||||
switch (d.type) {
|
switch (d.type) {
|
||||||
case svc::DebugEvent_CreateProcess:
|
case svc::DebugEvent_CreateProcess:
|
||||||
ctx->cpu_ctx.architecture = (d.info.create_process.flags & 1) ? CpuContext::Architecture_Aarch64 : CpuContext::Architecture_Aarch32;
|
ctx->cpu_ctx.architecture = (d.info.create_process.flags & 1) ? CpuContext::Architecture_Aarch64 : CpuContext::Architecture_Aarch32;
|
||||||
|
@ -247,7 +247,7 @@ namespace ams::fatal::srv {
|
||||||
bool found_fatal_caller = false;
|
bool found_fatal_caller = false;
|
||||||
u64 thread_id = 0;
|
u64 thread_id = 0;
|
||||||
u64 thread_tls = 0;
|
u64 thread_tls = 0;
|
||||||
ThreadContext thread_ctx;
|
svc::ThreadContext thread_ctx;
|
||||||
{
|
{
|
||||||
/* We start by trying to get a list of threads. */
|
/* We start by trying to get a list of threads. */
|
||||||
s32 thread_count;
|
s32 thread_count;
|
||||||
|
@ -275,7 +275,7 @@ namespace ams::fatal::srv {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (R_FAILED(svcGetDebugThreadContext(&thread_ctx, debug_handle, thread_id, svc::ThreadContextFlag_All))) {
|
if (R_FAILED(svc::GetDebugThreadContext(&thread_ctx, debug_handle, thread_id, svc::ThreadContextFlag_All))) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,7 +283,7 @@ namespace ams::fatal::srv {
|
||||||
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_FP, thread_ctx.fp);
|
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_FP, thread_ctx.fp);
|
||||||
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_LR, thread_ctx.lr);
|
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_LR, thread_ctx.lr);
|
||||||
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_SP, thread_ctx.sp);
|
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_SP, thread_ctx.sp);
|
||||||
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_PC, thread_ctx.pc.x);
|
ctx->cpu_ctx.aarch64_ctx.SetRegisterValue(aarch64::RegisterName_PC, thread_ctx.pc);
|
||||||
|
|
||||||
/* Parse a stack trace. */
|
/* Parse a stack trace. */
|
||||||
u64 cur_fp = thread_ctx.fp;
|
u64 cur_fp = thread_ctx.fp;
|
||||||
|
@ -296,7 +296,7 @@ namespace ams::fatal::srv {
|
||||||
|
|
||||||
/* Read a new frame. */
|
/* Read a new frame. */
|
||||||
StackFrame cur_frame = {};
|
StackFrame cur_frame = {};
|
||||||
if (R_FAILED(svcReadDebugProcessMemory(&cur_frame, debug_handle, cur_fp, sizeof(StackFrame)))) {
|
if (R_FAILED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(std::addressof(cur_frame)), debug_handle, cur_fp, sizeof(StackFrame)))) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,7 +308,7 @@ namespace ams::fatal::srv {
|
||||||
/* Try to read up to 0x100 of stack. */
|
/* Try to read up to 0x100 of stack. */
|
||||||
ctx->stack_dump_base = 0;
|
ctx->stack_dump_base = 0;
|
||||||
for (size_t sz = 0x100; sz > 0; sz -= 0x10) {
|
for (size_t sz = 0x100; sz > 0; sz -= 0x10) {
|
||||||
if (R_SUCCEEDED(svcReadDebugProcessMemory(ctx->stack_dump, debug_handle, thread_ctx.sp, sz))) {
|
if (R_SUCCEEDED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(ctx->stack_dump), debug_handle, thread_ctx.sp, sz))) {
|
||||||
ctx->stack_dump_base = thread_ctx.sp;
|
ctx->stack_dump_base = thread_ctx.sp;
|
||||||
ctx->stack_dump_size = sz;
|
ctx->stack_dump_size = sz;
|
||||||
break;
|
break;
|
||||||
|
@ -316,7 +316,7 @@ namespace ams::fatal::srv {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to read the first 0x100 of TLS. */
|
/* Try to read the first 0x100 of TLS. */
|
||||||
if (R_SUCCEEDED(svcReadDebugProcessMemory(ctx->tls_dump, debug_handle, thread_tls, sizeof(ctx->tls_dump)))) {
|
if (R_SUCCEEDED(svc::ReadDebugProcessMemory(reinterpret_cast<uintptr_t>(ctx->tls_dump), debug_handle, thread_tls, sizeof(ctx->tls_dump)))) {
|
||||||
ctx->tls_address = thread_tls;
|
ctx->tls_address = thread_tls;
|
||||||
} else {
|
} else {
|
||||||
ctx->tls_address = 0;
|
ctx->tls_address = 0;
|
||||||
|
|
|
@ -74,7 +74,7 @@ namespace ams::fatal::srv {
|
||||||
/* Get a timestamp. */
|
/* Get a timestamp. */
|
||||||
u64 timestamp;
|
u64 timestamp;
|
||||||
if (!TryGetCurrentTimestamp(×tamp)) {
|
if (!TryGetCurrentTimestamp(×tamp)) {
|
||||||
timestamp = svcGetSystemTick();
|
timestamp = os::GetSystemTick().GetInt64Value();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Open report file. */
|
/* Open report file. */
|
||||||
|
|
|
@ -332,7 +332,7 @@ namespace ams::ldr {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetCreateProcessParameter(svc::CreateProcessParameter *out, const Meta *meta, u32 flags, Handle reslimit_h) {
|
Result GetCreateProcessParameter(svc::CreateProcessParameter *out, const Meta *meta, u32 flags, os::NativeHandle reslimit_h) {
|
||||||
/* Clear output. */
|
/* Clear output. */
|
||||||
std::memset(out, 0, sizeof(*out));
|
std::memset(out, 0, sizeof(*out));
|
||||||
|
|
||||||
|
@ -456,7 +456,7 @@ namespace ams::ldr {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result CreateProcessImpl(ProcessInfo *out, const Meta *meta, const NsoHeader *nso_headers, const bool *has_nso, const args::ArgumentInfo *arg_info, u32 flags, Handle reslimit_h) {
|
Result CreateProcessImpl(ProcessInfo *out, const Meta *meta, const NsoHeader *nso_headers, const bool *has_nso, const args::ArgumentInfo *arg_info, u32 flags, os::NativeHandle reslimit_h) {
|
||||||
/* Get CreateProcessParameter. */
|
/* Get CreateProcessParameter. */
|
||||||
svc::CreateProcessParameter param;
|
svc::CreateProcessParameter param;
|
||||||
R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, reslimit_h));
|
R_TRY(GetCreateProcessParameter(std::addressof(param), meta, flags, reslimit_h));
|
||||||
|
@ -507,7 +507,7 @@ namespace ams::ldr {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result LoadNsoIntoProcessMemory(Handle process_handle, fs::FileHandle file, uintptr_t map_address, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size) {
|
Result LoadNsoIntoProcessMemory(os::NativeHandle process_handle, fs::FileHandle file, uintptr_t map_address, const NsoHeader *nso_header, uintptr_t nso_address, size_t nso_size) {
|
||||||
/* Map and read data from file. */
|
/* Map and read data from file. */
|
||||||
{
|
{
|
||||||
map::AutoCloseMap mapper(map_address, process_handle, nso_address, nso_size);
|
map::AutoCloseMap mapper(map_address, process_handle, nso_address, nso_size);
|
||||||
|
@ -542,13 +542,13 @@ namespace ams::ldr {
|
||||||
const size_t ro_size = (static_cast<size_t>(nso_header->ro_size) + size_t(0xFFFul)) & ~size_t(0xFFFul);
|
const size_t ro_size = (static_cast<size_t>(nso_header->ro_size) + size_t(0xFFFul)) & ~size_t(0xFFFul);
|
||||||
const size_t rw_size = (static_cast<size_t>(nso_header->rw_size + nso_header->bss_size) + size_t(0xFFFul)) & ~size_t(0xFFFul);
|
const size_t rw_size = (static_cast<size_t>(nso_header->rw_size + nso_header->bss_size) + size_t(0xFFFul)) & ~size_t(0xFFFul);
|
||||||
if (text_size) {
|
if (text_size) {
|
||||||
R_TRY(svcSetProcessMemoryPermission(process_handle, nso_address + nso_header->text_dst_offset, text_size, Perm_Rx));
|
R_TRY(svc::SetProcessMemoryPermission(process_handle, nso_address + nso_header->text_dst_offset, text_size, svc::MemoryPermission_ReadExecute));
|
||||||
}
|
}
|
||||||
if (ro_size) {
|
if (ro_size) {
|
||||||
R_TRY(svcSetProcessMemoryPermission(process_handle, nso_address + nso_header->ro_dst_offset, ro_size, Perm_R));
|
R_TRY(svc::SetProcessMemoryPermission(process_handle, nso_address + nso_header->ro_dst_offset, ro_size, svc::MemoryPermission_Read));
|
||||||
}
|
}
|
||||||
if (rw_size) {
|
if (rw_size) {
|
||||||
R_TRY(svcSetProcessMemoryPermission(process_handle, nso_address + nso_header->rw_dst_offset, rw_size, Perm_Rw));
|
R_TRY(svc::SetProcessMemoryPermission(process_handle, nso_address + nso_header->rw_dst_offset, rw_size, svc::MemoryPermission_ReadWrite));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -587,7 +587,7 @@ namespace ams::ldr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Set argument region permissions. */
|
/* Set argument region permissions. */
|
||||||
R_TRY(svcSetProcessMemoryPermission(process_info->process_handle, process_info->args_address, process_info->args_size, Perm_Rw));
|
R_TRY(svc::SetProcessMemoryPermission(process_info->process_handle, process_info->args_address, process_info->args_size, svc::MemoryPermission_ReadWrite));
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
|
@ -596,7 +596,7 @@ namespace ams::ldr {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Process Creation API. */
|
/* Process Creation API. */
|
||||||
Result CreateProcess(Handle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, Handle reslimit_h) {
|
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, os::NativeHandle reslimit_h) {
|
||||||
/* Use global storage for NSOs. */
|
/* Use global storage for NSOs. */
|
||||||
NsoHeader *nso_headers = g_nso_headers;
|
NsoHeader *nso_headers = g_nso_headers;
|
||||||
bool *has_nso = g_has_nso;
|
bool *has_nso = g_has_nso;
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
namespace ams::ldr {
|
namespace ams::ldr {
|
||||||
|
|
||||||
/* Process Creation API. */
|
/* Process Creation API. */
|
||||||
Result CreateProcess(Handle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, Handle reslimit_h);
|
Result CreateProcess(os::NativeHandle *out, PinId pin_id, const ncm::ProgramLocation &loc, const cfg::OverrideStatus &override_status, const char *path, u32 flags, os::NativeHandle reslimit_h);
|
||||||
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc);
|
Result GetProgramInfo(ProgramInfo *out, cfg::OverrideStatus *out_status, const ncm::ProgramLocation &loc);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
|
|
||||||
namespace ams::pm::impl {
|
namespace ams::pm::impl {
|
||||||
|
|
||||||
ProcessInfo::ProcessInfo(Handle h, os::ProcessId pid, ldr::PinId pin, const ncm::ProgramLocation &l, const cfg::OverrideStatus &s) : process_id(pid), pin_id(pin), loc(l), status(s), handle(h), state(svc::ProcessState_Created), flags(0) {
|
ProcessInfo::ProcessInfo(os::NativeHandle h, os::ProcessId pid, ldr::PinId pin, const ncm::ProgramLocation &l, const cfg::OverrideStatus &s) : process_id(pid), pin_id(pin), loc(l), status(s), handle(h), state(svc::ProcessState_Created), flags(0) {
|
||||||
os::InitializeMultiWaitHolder(std::addressof(this->multi_wait_holder), this->handle);
|
os::InitializeMultiWaitHolder(std::addressof(this->multi_wait_holder), this->handle);
|
||||||
os::SetMultiWaitHolderUserData(std::addressof(this->multi_wait_holder), reinterpret_cast<uintptr_t>(this));
|
os::SetMultiWaitHolderUserData(std::addressof(this->multi_wait_holder), reinterpret_cast<uintptr_t>(this));
|
||||||
}
|
}
|
||||||
|
@ -28,15 +28,15 @@ namespace ams::pm::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
void ProcessInfo::Cleanup() {
|
void ProcessInfo::Cleanup() {
|
||||||
if (this->handle != INVALID_HANDLE) {
|
if (this->handle != os::InvalidNativeHandle) {
|
||||||
/* Unregister the process. */
|
/* Unregister the process. */
|
||||||
fsprUnregisterProgram(static_cast<u64>(this->process_id));
|
fsprUnregisterProgram(static_cast<u64>(this->process_id));
|
||||||
sm::manager::UnregisterProcess(this->process_id);
|
sm::manager::UnregisterProcess(this->process_id);
|
||||||
ldr::pm::UnpinProgram(this->pin_id);
|
ldr::pm::UnpinProgram(this->pin_id);
|
||||||
|
|
||||||
/* Close the process's handle. */
|
/* Close the process's handle. */
|
||||||
svcCloseHandle(this->handle);
|
os::CloseNativeHandle(this->handle);
|
||||||
this->handle = INVALID_HANDLE;
|
this->handle = os::InvalidNativeHandle;
|
||||||
|
|
||||||
/* Unlink the process from its multi wait. */
|
/* Unlink the process from its multi wait. */
|
||||||
os::UnlinkMultiWaitHolder(std::addressof(this->multi_wait_holder));
|
os::UnlinkMultiWaitHolder(std::addressof(this->multi_wait_holder));
|
||||||
|
|
|
@ -43,7 +43,7 @@ namespace ams::pm::impl {
|
||||||
const ldr::PinId pin_id;
|
const ldr::PinId pin_id;
|
||||||
const ncm::ProgramLocation loc;
|
const ncm::ProgramLocation loc;
|
||||||
const cfg::OverrideStatus status;
|
const cfg::OverrideStatus status;
|
||||||
Handle handle;
|
os::NativeHandle handle;
|
||||||
svc::ProcessState state;
|
svc::ProcessState state;
|
||||||
u32 flags;
|
u32 flags;
|
||||||
os::MultiWaitHolderType multi_wait_holder;
|
os::MultiWaitHolderType multi_wait_holder;
|
||||||
|
@ -60,7 +60,7 @@ namespace ams::pm::impl {
|
||||||
return (this->flags & flag);
|
return (this->flags & flag);
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
ProcessInfo(Handle h, os::ProcessId pid, ldr::PinId pin, const ncm::ProgramLocation &l, const cfg::OverrideStatus &s);
|
ProcessInfo(os::NativeHandle h, os::ProcessId pid, ldr::PinId pin, const ncm::ProgramLocation &l, const cfg::OverrideStatus &s);
|
||||||
~ProcessInfo();
|
~ProcessInfo();
|
||||||
void Cleanup();
|
void Cleanup();
|
||||||
|
|
||||||
|
@ -68,7 +68,7 @@ namespace ams::pm::impl {
|
||||||
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(this->multi_wait_holder));
|
os::LinkMultiWaitHolder(std::addressof(multi_wait), std::addressof(this->multi_wait_holder));
|
||||||
}
|
}
|
||||||
|
|
||||||
Handle GetHandle() const {
|
os::NativeHandle GetHandle() const {
|
||||||
return this->handle;
|
return this->handle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,7 +207,7 @@ namespace ams::pm::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result StartProcess(ProcessInfo *process_info, const ldr::ProgramInfo *program_info) {
|
Result StartProcess(ProcessInfo *process_info, const ldr::ProgramInfo *program_info) {
|
||||||
R_TRY(svcStartProcess(process_info->GetHandle(), program_info->main_thread_priority, program_info->default_cpu_id, program_info->main_thread_stack_size));
|
R_TRY(svc::StartProcess(process_info->GetHandle(), program_info->main_thread_priority, program_info->default_cpu_id, program_info->main_thread_stack_size));
|
||||||
process_info->SetState(svc::ProcessState_Running);
|
process_info->SetState(svc::ProcessState_Running);
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -242,7 +242,7 @@ namespace ams::pm::impl {
|
||||||
resource::WaitResourceAvailable(&program_info);
|
resource::WaitResourceAvailable(&program_info);
|
||||||
|
|
||||||
/* Actually create the process. */
|
/* Actually create the process. */
|
||||||
Handle process_handle;
|
os::NativeHandle process_handle;
|
||||||
{
|
{
|
||||||
auto pin_guard = SCOPE_GUARD { ldr::pm::UnpinProgram(pin_id); };
|
auto pin_guard = SCOPE_GUARD { ldr::pm::UnpinProgram(pin_id); };
|
||||||
R_TRY(ldr::pm::CreateProcess(&process_handle, pin_id, GetLoaderCreateProcessFlags(args.flags), resource::GetResourceLimitHandle(&program_info)));
|
R_TRY(ldr::pm::CreateProcess(&process_handle, pin_id, GetLoaderCreateProcessFlags(args.flags), resource::GetResourceLimitHandle(&program_info)));
|
||||||
|
@ -313,7 +313,7 @@ namespace ams::pm::impl {
|
||||||
|
|
||||||
void OnProcessSignaled(ProcessListAccessor &list, ProcessInfo *process_info) {
|
void OnProcessSignaled(ProcessListAccessor &list, ProcessInfo *process_info) {
|
||||||
/* Reset the process's signal. */
|
/* Reset the process's signal. */
|
||||||
svcResetSignal(process_info->GetHandle());
|
svc::ResetSignal(process_info->GetHandle());
|
||||||
|
|
||||||
/* Update the process's state. */
|
/* Update the process's state. */
|
||||||
const svc::ProcessState old_state = process_info->GetState();
|
const svc::ProcessState old_state = process_info->GetState();
|
||||||
|
@ -455,7 +455,7 @@ namespace ams::pm::impl {
|
||||||
auto process_info = list->Find(process_id);
|
auto process_info = list->Find(process_id);
|
||||||
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
|
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
|
||||||
|
|
||||||
return svcTerminateProcess(process_info->GetHandle());
|
return svc::TerminateProcess(process_info->GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result TerminateProgram(ncm::ProgramId program_id) {
|
Result TerminateProgram(ncm::ProgramId program_id) {
|
||||||
|
@ -464,10 +464,10 @@ namespace ams::pm::impl {
|
||||||
auto process_info = list->Find(program_id);
|
auto process_info = list->Find(program_id);
|
||||||
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
|
R_UNLESS(process_info != nullptr, pm::ResultProcessNotFound());
|
||||||
|
|
||||||
return svcTerminateProcess(process_info->GetHandle());
|
return svc::TerminateProcess(process_info->GetHandle());
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetProcessEventHandle(Handle *out) {
|
Result GetProcessEventHandle(os::NativeHandle *out) {
|
||||||
*out = os::GetReadableHandleOfSystemEvent(std::addressof(g_process_event));
|
*out = os::GetReadableHandleOfSystemEvent(std::addressof(g_process_event));
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -602,7 +602,7 @@ namespace ams::pm::impl {
|
||||||
return pm::ResultProcessNotFound();
|
return pm::ResultProcessNotFound();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result AtmosphereGetProcessInfo(Handle *out_process_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
|
Result AtmosphereGetProcessInfo(os::NativeHandle *out_process_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id) {
|
||||||
ProcessListAccessor list(g_process_list);
|
ProcessListAccessor list(g_process_list);
|
||||||
|
|
||||||
auto process_info = list->Find(process_id);
|
auto process_info = list->Find(process_id);
|
||||||
|
@ -615,8 +615,8 @@ namespace ams::pm::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Hook API. */
|
/* Hook API. */
|
||||||
Result HookToCreateProcess(Handle *out_hook, ncm::ProgramId program_id) {
|
Result HookToCreateProcess(os::NativeHandle *out_hook, ncm::ProgramId program_id) {
|
||||||
*out_hook = INVALID_HANDLE;
|
*out_hook = os::InvalidNativeHandle;
|
||||||
|
|
||||||
{
|
{
|
||||||
ncm::ProgramId old_value = ncm::InvalidProgramId;
|
ncm::ProgramId old_value = ncm::InvalidProgramId;
|
||||||
|
@ -627,8 +627,8 @@ namespace ams::pm::impl {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result HookToCreateApplicationProcess(Handle *out_hook) {
|
Result HookToCreateApplicationProcess(os::NativeHandle *out_hook) {
|
||||||
*out_hook = INVALID_HANDLE;
|
*out_hook = os::InvalidNativeHandle;
|
||||||
|
|
||||||
{
|
{
|
||||||
bool old_value = false;
|
bool old_value = false;
|
||||||
|
@ -670,7 +670,7 @@ namespace ams::pm::impl {
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
Result GetBootFinishedEventHandle(Handle *out) {
|
Result GetBootFinishedEventHandle(os::NativeHandle *out) {
|
||||||
/* In 8.0.0, Nintendo added this command, which signals that the boot sysmodule has finished. */
|
/* In 8.0.0, Nintendo added this command, which signals that the boot sysmodule has finished. */
|
||||||
/* Nintendo only signals it in safe mode FIRM, and this function aborts on normal FIRM. */
|
/* Nintendo only signals it in safe mode FIRM, and this function aborts on normal FIRM. */
|
||||||
/* We will signal it always, but only allow this function to succeed on safe mode. */
|
/* We will signal it always, but only allow this function to succeed on safe mode. */
|
||||||
|
|
|
@ -26,7 +26,7 @@ namespace ams::pm::impl {
|
||||||
Result StartProcess(os::ProcessId process_id);
|
Result StartProcess(os::ProcessId process_id);
|
||||||
Result TerminateProcess(os::ProcessId process_id);
|
Result TerminateProcess(os::ProcessId process_id);
|
||||||
Result TerminateProgram(ncm::ProgramId program_id);
|
Result TerminateProgram(ncm::ProgramId program_id);
|
||||||
Result GetProcessEventHandle(Handle *out);
|
Result GetProcessEventHandle(os::NativeHandle *out);
|
||||||
Result GetProcessEventInfo(ProcessEventInfo *out);
|
Result GetProcessEventInfo(ProcessEventInfo *out);
|
||||||
Result CleanupProcess(os::ProcessId process_id);
|
Result CleanupProcess(os::ProcessId process_id);
|
||||||
Result ClearExceptionOccurred(os::ProcessId process_id);
|
Result ClearExceptionOccurred(os::ProcessId process_id);
|
||||||
|
@ -37,16 +37,16 @@ namespace ams::pm::impl {
|
||||||
Result GetProcessId(os::ProcessId *out, ncm::ProgramId program_id);
|
Result GetProcessId(os::ProcessId *out, ncm::ProgramId program_id);
|
||||||
Result GetProgramId(ncm::ProgramId *out, os::ProcessId process_id);
|
Result GetProgramId(ncm::ProgramId *out, os::ProcessId process_id);
|
||||||
Result GetApplicationProcessId(os::ProcessId *out_process_id);
|
Result GetApplicationProcessId(os::ProcessId *out_process_id);
|
||||||
Result AtmosphereGetProcessInfo(Handle *out_process_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id);
|
Result AtmosphereGetProcessInfo(os::NativeHandle *out_process_handle, ncm::ProgramLocation *out_loc, cfg::OverrideStatus *out_status, os::ProcessId process_id);
|
||||||
|
|
||||||
/* Hook API. */
|
/* Hook API. */
|
||||||
Result HookToCreateProcess(Handle *out_hook, ncm::ProgramId program_id);
|
Result HookToCreateProcess(os::NativeHandle *out_hook, ncm::ProgramId program_id);
|
||||||
Result HookToCreateApplicationProcess(Handle *out_hook);
|
Result HookToCreateApplicationProcess(os::NativeHandle *out_hook);
|
||||||
Result ClearHook(u32 which);
|
Result ClearHook(u32 which);
|
||||||
|
|
||||||
/* Boot API. */
|
/* Boot API. */
|
||||||
Result NotifyBootFinished();
|
Result NotifyBootFinished();
|
||||||
Result GetBootFinishedEventHandle(Handle *out);
|
Result GetBootFinishedEventHandle(os::NativeHandle *out);
|
||||||
|
|
||||||
/* Resource Limit API. */
|
/* Resource Limit API. */
|
||||||
Result BoostSystemMemoryResourceLimit(u64 boost_size);
|
Result BoostSystemMemoryResourceLimit(u64 boost_size);
|
||||||
|
|
|
@ -72,9 +72,9 @@ namespace ams::ro::impl {
|
||||||
const u64 ro_offset = rx_offset + rx_size;
|
const u64 ro_offset = rx_offset + rx_size;
|
||||||
const u64 rw_offset = ro_offset + ro_size;
|
const u64 rw_offset = ro_offset + ro_size;
|
||||||
|
|
||||||
R_TRY(svcSetProcessMemoryPermission(process_handle, base_address + rx_offset, rx_size, Perm_Rx));
|
R_TRY(svc::SetProcessMemoryPermission(process_handle, base_address + rx_offset, rx_size, svc::MemoryPermission_ReadExecute));
|
||||||
R_TRY(svcSetProcessMemoryPermission(process_handle, base_address + ro_offset, ro_size, Perm_R ));
|
R_TRY(svc::SetProcessMemoryPermission(process_handle, base_address + ro_offset, ro_size, svc::MemoryPermission_Read));
|
||||||
R_TRY(svcSetProcessMemoryPermission(process_handle, base_address + rw_offset, rw_size, Perm_Rw));
|
R_TRY(svc::SetProcessMemoryPermission(process_handle, base_address + rw_offset, rw_size, svc::MemoryPermission_ReadWrite));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
@ -82,16 +82,16 @@ namespace ams::ro::impl {
|
||||||
Result UnmapNro(os::NativeHandle process_handle, u64 base_address, u64 nro_heap_address, u64 bss_heap_address, u64 bss_heap_size, u64 code_size, u64 rw_size) {
|
Result UnmapNro(os::NativeHandle process_handle, u64 base_address, u64 nro_heap_address, u64 bss_heap_address, u64 bss_heap_size, u64 code_size, u64 rw_size) {
|
||||||
/* First, unmap bss. */
|
/* First, unmap bss. */
|
||||||
if (bss_heap_size > 0) {
|
if (bss_heap_size > 0) {
|
||||||
R_TRY(svcUnmapProcessCodeMemory(process_handle, base_address + code_size + rw_size, bss_heap_address, bss_heap_size));
|
R_TRY(svc::UnmapProcessCodeMemory(process_handle, base_address + code_size + rw_size, bss_heap_address, bss_heap_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Next, unmap .rwdata */
|
/* Next, unmap .rwdata */
|
||||||
if (rw_size > 0) {
|
if (rw_size > 0) {
|
||||||
R_TRY(svcUnmapProcessCodeMemory(process_handle, base_address + code_size, nro_heap_address + code_size, rw_size));
|
R_TRY(svc::UnmapProcessCodeMemory(process_handle, base_address + code_size, nro_heap_address + code_size, rw_size));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Finally, unmap .text + .rodata. */
|
/* Finally, unmap .text + .rodata. */
|
||||||
R_TRY(svcUnmapProcessCodeMemory(process_handle, base_address, nro_heap_address, code_size));
|
R_TRY(svc::UnmapProcessCodeMemory(process_handle, base_address, nro_heap_address, code_size));
|
||||||
|
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
|
@ -224,8 +224,8 @@ namespace ams::ro::impl {
|
||||||
}
|
}
|
||||||
|
|
||||||
Result UnmapNrr(os::NativeHandle process_handle, const NrrHeader *header, u64 nrr_heap_address, u64 nrr_heap_size, u64 mapped_code_address) {
|
Result UnmapNrr(os::NativeHandle process_handle, const NrrHeader *header, u64 nrr_heap_address, u64 nrr_heap_size, u64 mapped_code_address) {
|
||||||
R_TRY(svcUnmapProcessMemory(reinterpret_cast<void *>(const_cast<NrrHeader *>(header)), process_handle, mapped_code_address, nrr_heap_size));
|
R_TRY(svc::UnmapProcessMemory(reinterpret_cast<uintptr_t>(header), process_handle, mapped_code_address, nrr_heap_size));
|
||||||
R_TRY(svcUnmapProcessCodeMemory(process_handle, mapped_code_address, nrr_heap_address, nrr_heap_size));
|
R_TRY(svc::UnmapProcessCodeMemory(process_handle, mapped_code_address, nrr_heap_address, nrr_heap_size));
|
||||||
return ResultSuccess();
|
return ResultSuccess();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -319,7 +319,7 @@ namespace ams::ro::impl {
|
||||||
UnmapNrr(context->process_handle, context->nrr_infos[i].mapped_header, context->nrr_infos[i].nrr_heap_address, context->nrr_infos[i].nrr_heap_size, context->nrr_infos[i].mapped_code_address);
|
UnmapNrr(context->process_handle, context->nrr_infos[i].mapped_header, context->nrr_infos[i].nrr_heap_address, context->nrr_infos[i].nrr_heap_size, context->nrr_infos[i].mapped_code_address);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
svcCloseHandle(context->process_handle);
|
os::CloseNativeHandle(context->process_handle);
|
||||||
}
|
}
|
||||||
std::memset(context, 0, sizeof(*context));
|
std::memset(context, 0, sizeof(*context));
|
||||||
context->in_use = false;
|
context->in_use = false;
|
||||||
|
|
|
@ -226,13 +226,13 @@ namespace ams::spl::impl {
|
||||||
u64 dst_addr;
|
u64 dst_addr;
|
||||||
u64 src_addr;
|
u64 src_addr;
|
||||||
size_t size;
|
size_t size;
|
||||||
u32 perm;
|
svc::MemoryPermission perm;
|
||||||
public:
|
public:
|
||||||
DeviceAddressSpaceMapHelper(Handle h, u64 dst, u64 src, size_t sz, u32 p) : das_hnd(h), dst_addr(dst), src_addr(src), size(sz), perm(p) {
|
DeviceAddressSpaceMapHelper(Handle h, u64 dst, u64 src, size_t sz, svc::MemoryPermission p) : das_hnd(h), dst_addr(dst), src_addr(src), size(sz), perm(p) {
|
||||||
R_ABORT_UNLESS(svcMapDeviceAddressSpaceAligned(this->das_hnd, dd::GetCurrentProcessHandle(), this->src_addr, this->size, this->dst_addr, this->perm));
|
R_ABORT_UNLESS(svc::MapDeviceAddressSpaceAligned(this->das_hnd, dd::GetCurrentProcessHandle(), this->src_addr, this->size, this->dst_addr, this->perm));
|
||||||
}
|
}
|
||||||
~DeviceAddressSpaceMapHelper() {
|
~DeviceAddressSpaceMapHelper() {
|
||||||
R_ABORT_UNLESS(svcUnmapDeviceAddressSpace(this->das_hnd, dd::GetCurrentProcessHandle(), this->src_addr, this->size, this->dst_addr));
|
R_ABORT_UNLESS(svc::UnmapDeviceAddressSpace(this->das_hnd, dd::GetCurrentProcessHandle(), this->src_addr, this->size, this->dst_addr));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -279,16 +279,16 @@ namespace ams::spl::impl {
|
||||||
void InitializeDeviceAddressSpace() {
|
void InitializeDeviceAddressSpace() {
|
||||||
|
|
||||||
/* Create Address Space. */
|
/* Create Address Space. */
|
||||||
R_ABORT_UNLESS(svcCreateDeviceAddressSpace(&g_se_das_hnd, 0, (1ul << 32)));
|
R_ABORT_UNLESS(svc::CreateDeviceAddressSpace(&g_se_das_hnd, 0, (1ul << 32)));
|
||||||
|
|
||||||
/* Attach it to the SE. */
|
/* Attach it to the SE. */
|
||||||
R_ABORT_UNLESS(svcAttachDeviceAddressSpace(svc::DeviceName_Se, g_se_das_hnd));
|
R_ABORT_UNLESS(svc::AttachDeviceAddressSpace(svc::DeviceName_Se, g_se_das_hnd));
|
||||||
|
|
||||||
const u64 work_buffer_addr = reinterpret_cast<u64>(g_work_buffer);
|
const u64 work_buffer_addr = reinterpret_cast<u64>(g_work_buffer);
|
||||||
g_se_mapped_work_buffer_addr = WorkBufferMapBase + (work_buffer_addr % DeviceAddressSpaceAlign);
|
g_se_mapped_work_buffer_addr = WorkBufferMapBase + (work_buffer_addr % DeviceAddressSpaceAlign);
|
||||||
|
|
||||||
/* Map the work buffer for the SE. */
|
/* Map the work buffer for the SE. */
|
||||||
R_ABORT_UNLESS(svcMapDeviceAddressSpaceAligned(g_se_das_hnd, dd::GetCurrentProcessHandle(), work_buffer_addr, sizeof(g_work_buffer), g_se_mapped_work_buffer_addr, 3));
|
R_ABORT_UNLESS(svc::MapDeviceAddressSpaceAligned(g_se_das_hnd, dd::GetCurrentProcessHandle(), work_buffer_addr, sizeof(g_work_buffer), g_se_mapped_work_buffer_addr, svc::MemoryPermission_ReadWrite));
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Internal RNG functionality. */
|
/* Internal RNG functionality. */
|
||||||
|
@ -689,8 +689,8 @@ namespace ams::spl::impl {
|
||||||
R_UNLESS(dst_size_page_aligned <= ComputeAesSizeMax, spl::ResultInvalidSize());
|
R_UNLESS(dst_size_page_aligned <= ComputeAesSizeMax, spl::ResultInvalidSize());
|
||||||
|
|
||||||
/* Helpers for mapping/unmapping. */
|
/* Helpers for mapping/unmapping. */
|
||||||
DeviceAddressSpaceMapHelper in_mapper(g_se_das_hnd, src_se_map_addr, src_addr_page_aligned, src_size_page_aligned, 1);
|
DeviceAddressSpaceMapHelper in_mapper(g_se_das_hnd, src_se_map_addr, src_addr_page_aligned, src_size_page_aligned, svc::MemoryPermission_Read);
|
||||||
DeviceAddressSpaceMapHelper out_mapper(g_se_das_hnd, dst_se_map_addr, dst_addr_page_aligned, dst_size_page_aligned, 2);
|
DeviceAddressSpaceMapHelper out_mapper(g_se_das_hnd, dst_se_map_addr, dst_addr_page_aligned, dst_size_page_aligned, svc::MemoryPermission_Write);
|
||||||
|
|
||||||
/* Setup SE linked list entries. */
|
/* Setup SE linked list entries. */
|
||||||
SeCryptContext *crypt_ctx = reinterpret_cast<SeCryptContext *>(g_work_buffer);
|
SeCryptContext *crypt_ctx = reinterpret_cast<SeCryptContext *>(g_work_buffer);
|
||||||
|
|
Loading…
Reference in a new issue