mirror of
https://github.com/LumaTeam/Luma3DS.git
synced 2026-02-22 01:44:38 +00:00
Allow plugins to use PRIVATE memory instead of SHARED on requests (#2086)
- Modify the svcMapProcessMemoryEx svc so that it takes an extra flags argument. This change was made in a way that shouldn't break existing plugins or applications. - Add MAPEXFLAGS_PRIVATE flag, which maps the specified memory as PRIVATE instead of SHARED. - Allow plugins to be mapped with PRIVATE memory instead of SHARED with a flag in the .3gx header. This allows plugins to use socket and http services without additional hacks. --------- Co-authored-by: LittleCube <littlecubehax@gmail.com>
This commit is contained in:
parent
e0e86c46a7
commit
3253fdb255
@ -30,5 +30,11 @@
|
|||||||
#include "kernel.h"
|
#include "kernel.h"
|
||||||
#include "svc.h"
|
#include "svc.h"
|
||||||
|
|
||||||
Result MapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size);
|
/// Flags for svcMapProcessMemoryEx
|
||||||
Result MapProcessMemoryExWrapper(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size);
|
typedef enum MapExFlags
|
||||||
|
{
|
||||||
|
MAPEXFLAGS_PRIVATE = BIT(0), ///< Maps the memory as PRIVATE (0xBB05) instead of SHARED (0x5806)
|
||||||
|
} MapExFlags;
|
||||||
|
|
||||||
|
Result MapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size, MapExFlags flags);
|
||||||
|
Result MapProcessMemoryExWrapper(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size, MapExFlags flags);
|
||||||
|
|||||||
@ -26,7 +26,7 @@
|
|||||||
|
|
||||||
#include "svc/MapProcessMemoryEx.h"
|
#include "svc/MapProcessMemoryEx.h"
|
||||||
|
|
||||||
Result MapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size)
|
Result MapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size, MapExFlags flags)
|
||||||
{
|
{
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
u32 sizeInPage = size >> 12;
|
u32 sizeInPage = size >> 12;
|
||||||
@ -69,7 +69,7 @@ Result MapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcess
|
|||||||
// Check if the destination address is free and large enough
|
// Check if the destination address is free and large enough
|
||||||
res = KProcessHwInfo__CheckVaState(hwInfoOfProcess(dstProcess), vaDst, size, 0, 0);
|
res = KProcessHwInfo__CheckVaState(hwInfoOfProcess(dstProcess), vaDst, size, 0, 0);
|
||||||
if (res == 0)
|
if (res == 0)
|
||||||
res = KProcessHwInfo__MapListOfKBlockInfo(hwInfoOfProcess(dstProcess), vaDst, &list, 0x5806, MEMPERM_RW | 0x18, 0);
|
res = KProcessHwInfo__MapListOfKBlockInfo(hwInfoOfProcess(dstProcess), vaDst, &list, (flags & MAPEXFLAGS_PRIVATE) ? 0xBB05 : 0x5806, MEMPERM_RW | 0x18, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
KLinkedList_KBlockInfo__Clear(&list);
|
KLinkedList_KBlockInfo__Clear(&list);
|
||||||
|
|||||||
@ -118,8 +118,12 @@ ControlMemoryUnsafeWrapper:
|
|||||||
.global MapProcessMemoryExWrapper
|
.global MapProcessMemoryExWrapper
|
||||||
.type MapProcessMemoryExWrapper, %function
|
.type MapProcessMemoryExWrapper, %function
|
||||||
MapProcessMemoryExWrapper:
|
MapProcessMemoryExWrapper:
|
||||||
push {lr}
|
push {r5, lr} @ We need to save r5 because the old implementation doesn't save it
|
||||||
|
cmp r0, #0xFFFFFFF2 @ Check magic value, for backwards compatibility
|
||||||
|
moveq r0, r6 @ If value present, flags present in r5 and dst process in r6, so move dst process back to r0
|
||||||
|
movne r5, #0 @ If value not present, clear the flags as its the old version
|
||||||
|
str r5, [sp, #-4]!
|
||||||
str r4, [sp, #-4]!
|
str r4, [sp, #-4]!
|
||||||
bl MapProcessMemoryEx
|
bl MapProcessMemoryEx
|
||||||
add sp, #4
|
add sp, #8
|
||||||
pop {pc}
|
pop {r5, pc}
|
||||||
@ -73,6 +73,13 @@ void svcInvalidateEntireInstructionCache(void);
|
|||||||
|
|
||||||
///@name Memory management
|
///@name Memory management
|
||||||
///@{
|
///@{
|
||||||
|
|
||||||
|
/// Flags for svcMapProcessMemoryEx
|
||||||
|
typedef enum MapExFlags
|
||||||
|
{
|
||||||
|
MAPEXFLAGS_PRIVATE = BIT(0), ///< Maps the memory as PRIVATE (0xBB05) instead of SHARED (0x5806)
|
||||||
|
} MapExFlags;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Maps a block of process memory.
|
* @brief Maps a block of process memory.
|
||||||
* @param dstProcessHandle Handle of the process to map the memory in (destination)
|
* @param dstProcessHandle Handle of the process to map the memory in (destination)
|
||||||
@ -80,8 +87,9 @@ void svcInvalidateEntireInstructionCache(void);
|
|||||||
* @param srcProcessHandle Handle of the process to map the memory from (source)
|
* @param srcProcessHandle Handle of the process to map the memory from (source)
|
||||||
* @param srcAddress Start address of the memory block in the source process
|
* @param srcAddress Start address of the memory block in the source process
|
||||||
* @param size Size of the block of the memory to map (truncated to a multiple of 0x1000 bytes)
|
* @param size Size of the block of the memory to map (truncated to a multiple of 0x1000 bytes)
|
||||||
|
* @param flags Extended flags for mapping the memory (see MapExFlags)
|
||||||
*/
|
*/
|
||||||
Result svcMapProcessMemoryEx(Handle dstProcessHandle, u32 destAddress, Handle srcProcessHandle, u32 srcAddress, u32 size);
|
Result svcMapProcessMemoryEx(Handle dstProcessHandle, u32 destAddress, Handle srcProcessHandle, u32 srcAddress, u32 size, MapExFlags flags);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Unmaps a block of process memory.
|
* @brief Unmaps a block of process memory.
|
||||||
|
|||||||
@ -23,7 +23,8 @@ typedef struct CTR_PACKED
|
|||||||
u32 compatibility : 2;
|
u32 compatibility : 2;
|
||||||
u32 eventsSelfManaged : 1;
|
u32 eventsSelfManaged : 1;
|
||||||
u32 swapNotNeeded : 1;
|
u32 swapNotNeeded : 1;
|
||||||
u32 unused : 24;
|
u32 usePrivateMemory : 1;
|
||||||
|
u32 unused : 23;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
u32 exeLoadChecksum;
|
u32 exeLoadChecksum;
|
||||||
|
|||||||
@ -93,6 +93,7 @@ typedef struct
|
|||||||
u32 swapLoadChecksum;
|
u32 swapLoadChecksum;
|
||||||
|
|
||||||
bool eventsSelfManaged;
|
bool eventsSelfManaged;
|
||||||
|
bool isMemPrivate;
|
||||||
} PluginLoaderContext;
|
} PluginLoaderContext;
|
||||||
|
|
||||||
extern PluginLoaderContext PluginLoaderCtx;
|
extern PluginLoaderContext PluginLoaderCtx;
|
||||||
|
|||||||
@ -59,10 +59,13 @@ SVC_BEGIN svcInvalidateEntireInstructionCache
|
|||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
SVC_BEGIN svcMapProcessMemoryEx
|
SVC_BEGIN svcMapProcessMemoryEx
|
||||||
str r4, [sp, #-4]!
|
push {r4, r5, r6}
|
||||||
ldr r4, [sp, #4]
|
ldr r4, [sp, #12]
|
||||||
|
ldr r5, [sp, #16]
|
||||||
|
mov r6, r0 @ Move the dst handle to r6 to make room for magic value
|
||||||
|
mov r0, #0xFFFFFFF2 @ Set r0 to magic value, which allows for backwards compatibility
|
||||||
svc 0xA0
|
svc 0xA0
|
||||||
ldr r4, [sp], #4
|
pop {r4, r5, r6}
|
||||||
bx lr
|
bx lr
|
||||||
SVC_END
|
SVC_END
|
||||||
|
|
||||||
|
|||||||
@ -223,7 +223,7 @@ static Result InputRedirection_DoUndoIrPatches(Handle processHandle, bool doPatc
|
|||||||
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
||||||
|
|
||||||
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
||||||
res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize);
|
res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize, 0);
|
||||||
|
|
||||||
if(R_SUCCEEDED(res) && !patchPrepared)
|
if(R_SUCCEEDED(res) && !patchPrepared)
|
||||||
{
|
{
|
||||||
@ -356,7 +356,7 @@ static Result InputRedirection_DoUndoHidPatches(Handle processHandle, bool doPat
|
|||||||
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
||||||
|
|
||||||
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
svcGetProcessInfo(&startAddress, processHandle, 0x10005);
|
||||||
res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize);
|
res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize, 0);
|
||||||
|
|
||||||
if (R_SUCCEEDED(res) && !patchPrepared)
|
if (R_SUCCEEDED(res) && !patchPrepared)
|
||||||
{
|
{
|
||||||
|
|||||||
@ -245,8 +245,8 @@ static void ProcessListMenu_MemoryViewer(const ProcessInfo *info)
|
|||||||
svcQueryProcessMemory(&mem, &out, processHandle, heapStartAddress);
|
svcQueryProcessMemory(&mem, &out, processHandle, heapStartAddress);
|
||||||
heapTotalSize = mem.size;
|
heapTotalSize = mem.size;
|
||||||
|
|
||||||
Result codeRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, codeDestAddress, processHandle, codeStartAddress, codeTotalSize);
|
Result codeRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, codeDestAddress, processHandle, codeStartAddress, codeTotalSize, 0);
|
||||||
Result heapRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, heapDestAddress, processHandle, heapStartAddress, heapTotalSize);
|
Result heapRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, heapDestAddress, processHandle, heapStartAddress, heapTotalSize, 0);
|
||||||
|
|
||||||
bool codeAvailable = R_SUCCEEDED(codeRes);
|
bool codeAvailable = R_SUCCEEDED(codeRes);
|
||||||
bool heapAvailable = R_SUCCEEDED(heapRes);
|
bool heapAvailable = R_SUCCEEDED(heapRes);
|
||||||
|
|||||||
@ -214,6 +214,7 @@ bool TryToLoadPlugin(Handle process)
|
|||||||
// Flags
|
// Flags
|
||||||
if (!res) {
|
if (!res) {
|
||||||
ctx->eventsSelfManaged = fileHeader.infos.eventsSelfManaged;
|
ctx->eventsSelfManaged = fileHeader.infos.eventsSelfManaged;
|
||||||
|
ctx->isMemPrivate = fileHeader.infos.usePrivateMemory;
|
||||||
if (ctx->pluginMemoryStrategy == PLG_STRATEGY_SWAP && fileHeader.infos.swapNotNeeded)
|
if (ctx->pluginMemoryStrategy == PLG_STRATEGY_SWAP && fileHeader.infos.swapNotNeeded)
|
||||||
ctx->pluginMemoryStrategy = PLG_STRATEGY_NONE;
|
ctx->pluginMemoryStrategy = PLG_STRATEGY_NONE;
|
||||||
}
|
}
|
||||||
@ -292,7 +293,7 @@ bool TryToLoadPlugin(Handle process)
|
|||||||
|
|
||||||
extern u32 g_savedGameInstr[2];
|
extern u32 g_savedGameInstr[2];
|
||||||
|
|
||||||
if (R_FAILED((res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, procStart, process, procStart, 0x1000))))
|
if (R_FAILED((res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, procStart, process, procStart, 0x1000, 0))))
|
||||||
{
|
{
|
||||||
ctx->error.message = "Couldn't map process";
|
ctx->error.message = "Couldn't map process";
|
||||||
ctx->error.code = res;
|
ctx->error.code = res;
|
||||||
|
|||||||
@ -205,11 +205,12 @@ Result MemoryBlock__MountInProcess(void)
|
|||||||
Error *error = &PluginLoaderCtx.error;
|
Error *error = &PluginLoaderCtx.error;
|
||||||
PluginHeader *header = &PluginLoaderCtx.header;
|
PluginHeader *header = &PluginLoaderCtx.header;
|
||||||
MemoryBlock *memblock = &PluginLoaderCtx.memblock;
|
MemoryBlock *memblock = &PluginLoaderCtx.memblock;
|
||||||
|
bool isPrivate = PluginLoaderCtx.isMemPrivate;
|
||||||
|
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
|
|
||||||
// Executable
|
// Executable
|
||||||
if (R_FAILED((res = svcMapProcessMemoryEx(target, 0x07000000, CUR_PROCESS_HANDLE, (u32)memblock->memblock, header->exeSize))))
|
if (R_FAILED((res = svcMapProcessMemoryEx(target, 0x07000000, CUR_PROCESS_HANDLE, (u32) memblock->memblock, header->exeSize, isPrivate ? MAPEXFLAGS_PRIVATE : 0))))
|
||||||
{
|
{
|
||||||
error->message = "Couldn't map exe memory block";
|
error->message = "Couldn't map exe memory block";
|
||||||
error->code = res;
|
error->code = res;
|
||||||
@ -217,7 +218,7 @@ Result MemoryBlock__MountInProcess(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Heap (to be used by the plugin)
|
// Heap (to be used by the plugin)
|
||||||
if (R_FAILED((res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32)memblock->memblock + header->exeSize, header->heapSize))))
|
if (R_FAILED((res = svcMapProcessMemoryEx(target, header->heapVA, CUR_PROCESS_HANDLE, (u32) memblock->memblock + header->exeSize, header->heapSize, isPrivate ? MAPEXFLAGS_PRIVATE : 0))))
|
||||||
{
|
{
|
||||||
error->message = "Couldn't map heap memory block";
|
error->message = "Couldn't map heap memory block";
|
||||||
error->code = res;
|
error->code = res;
|
||||||
@ -233,7 +234,7 @@ Result MemoryBlock__UnmountFromProcess(void)
|
|||||||
|
|
||||||
Result res = 0;
|
Result res = 0;
|
||||||
|
|
||||||
res = svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize);
|
res |= svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize);
|
||||||
res |= svcUnmapProcessMemoryEx(target, header->heapVA, header->heapSize);
|
res |= svcUnmapProcessMemoryEx(target, header->heapVA, header->heapSize);
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
@ -558,6 +558,7 @@ static void WaitForProcessTerminated(void *arg)
|
|||||||
ctx->isSwapFunctionset = false;
|
ctx->isSwapFunctionset = false;
|
||||||
ctx->pluginMemoryStrategy = PLG_STRATEGY_SWAP;
|
ctx->pluginMemoryStrategy = PLG_STRATEGY_SWAP;
|
||||||
ctx->eventsSelfManaged = false;
|
ctx->eventsSelfManaged = false;
|
||||||
|
ctx->isMemPrivate = false;
|
||||||
g_blockMenuOpen = 0;
|
g_blockMenuOpen = 0;
|
||||||
MemoryBlock__ResetSwapSettings();
|
MemoryBlock__ResetSwapSettings();
|
||||||
//if (!ctx->userLoadParameters.noIRPatch)
|
//if (!ctx->userLoadParameters.noIRPatch)
|
||||||
|
|||||||
@ -77,7 +77,7 @@ Result OperateOnProcessByName(const char *name, OperateOnProcessCb func)
|
|||||||
|
|
||||||
// NOTE: we suppose .text, .rodata, .data+.bss are contiguous & in that order
|
// NOTE: we suppose .text, .rodata, .data+.bss are contiguous & in that order
|
||||||
u32 totalSize = (u32)(textSize + roSize + rwSize);
|
u32 totalSize = (u32)(textSize + roSize + rwSize);
|
||||||
if (R_FAILED(res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize)))
|
if (R_FAILED(res = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, 0x00100000, processHandle, (u32) startAddress, totalSize, 0)))
|
||||||
{
|
{
|
||||||
svcCloseHandle(processHandle);
|
svcCloseHandle(processHandle);
|
||||||
return res;
|
return res;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user