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 "svc.h"
|
||||
|
||||
Result MapProcessMemoryEx(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size);
|
||||
Result MapProcessMemoryExWrapper(Handle dstProcessHandle, u32 vaDst, Handle srcProcessHandle, u32 vaSrc, u32 size);
|
||||
/// Flags for svcMapProcessMemoryEx
|
||||
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"
|
||||
|
||||
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;
|
||||
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
|
||||
res = KProcessHwInfo__CheckVaState(hwInfoOfProcess(dstProcess), vaDst, size, 0, 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);
|
||||
|
||||
@ -118,8 +118,12 @@ ControlMemoryUnsafeWrapper:
|
||||
.global MapProcessMemoryExWrapper
|
||||
.type MapProcessMemoryExWrapper, %function
|
||||
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]!
|
||||
bl MapProcessMemoryEx
|
||||
add sp, #4
|
||||
pop {pc}
|
||||
add sp, #8
|
||||
pop {r5, pc}
|
||||
@ -73,6 +73,13 @@ void svcInvalidateEntireInstructionCache(void);
|
||||
|
||||
///@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.
|
||||
* @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 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 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.
|
||||
|
||||
@ -23,7 +23,8 @@ typedef struct CTR_PACKED
|
||||
u32 compatibility : 2;
|
||||
u32 eventsSelfManaged : 1;
|
||||
u32 swapNotNeeded : 1;
|
||||
u32 unused : 24;
|
||||
u32 usePrivateMemory : 1;
|
||||
u32 unused : 23;
|
||||
};
|
||||
};
|
||||
u32 exeLoadChecksum;
|
||||
|
||||
@ -93,6 +93,7 @@ typedef struct
|
||||
u32 swapLoadChecksum;
|
||||
|
||||
bool eventsSelfManaged;
|
||||
bool isMemPrivate;
|
||||
} PluginLoaderContext;
|
||||
|
||||
extern PluginLoaderContext PluginLoaderCtx;
|
||||
|
||||
@ -59,10 +59,13 @@ SVC_BEGIN svcInvalidateEntireInstructionCache
|
||||
SVC_END
|
||||
|
||||
SVC_BEGIN svcMapProcessMemoryEx
|
||||
str r4, [sp, #-4]!
|
||||
ldr r4, [sp, #4]
|
||||
push {r4, r5, r6}
|
||||
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
|
||||
ldr r4, [sp], #4
|
||||
pop {r4, r5, r6}
|
||||
bx lr
|
||||
SVC_END
|
||||
|
||||
|
||||
@ -223,7 +223,7 @@ static Result InputRedirection_DoUndoIrPatches(Handle processHandle, bool doPatc
|
||||
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
||||
|
||||
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)
|
||||
{
|
||||
@ -356,7 +356,7 @@ static Result InputRedirection_DoUndoHidPatches(Handle processHandle, bool doPat
|
||||
totalSize = (u32)(textTotalRoundedSize + rodataTotalRoundedSize + dataTotalRoundedSize);
|
||||
|
||||
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)
|
||||
{
|
||||
|
||||
@ -245,8 +245,8 @@ static void ProcessListMenu_MemoryViewer(const ProcessInfo *info)
|
||||
svcQueryProcessMemory(&mem, &out, processHandle, heapStartAddress);
|
||||
heapTotalSize = mem.size;
|
||||
|
||||
Result codeRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, codeDestAddress, processHandle, codeStartAddress, codeTotalSize);
|
||||
Result heapRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, heapDestAddress, processHandle, heapStartAddress, heapTotalSize);
|
||||
Result codeRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, codeDestAddress, processHandle, codeStartAddress, codeTotalSize, 0);
|
||||
Result heapRes = svcMapProcessMemoryEx(CUR_PROCESS_HANDLE, heapDestAddress, processHandle, heapStartAddress, heapTotalSize, 0);
|
||||
|
||||
bool codeAvailable = R_SUCCEEDED(codeRes);
|
||||
bool heapAvailable = R_SUCCEEDED(heapRes);
|
||||
|
||||
@ -214,6 +214,7 @@ bool TryToLoadPlugin(Handle process)
|
||||
// Flags
|
||||
if (!res) {
|
||||
ctx->eventsSelfManaged = fileHeader.infos.eventsSelfManaged;
|
||||
ctx->isMemPrivate = fileHeader.infos.usePrivateMemory;
|
||||
if (ctx->pluginMemoryStrategy == PLG_STRATEGY_SWAP && fileHeader.infos.swapNotNeeded)
|
||||
ctx->pluginMemoryStrategy = PLG_STRATEGY_NONE;
|
||||
}
|
||||
@ -292,7 +293,7 @@ bool TryToLoadPlugin(Handle process)
|
||||
|
||||
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.code = res;
|
||||
|
||||
@ -205,11 +205,12 @@ Result MemoryBlock__MountInProcess(void)
|
||||
Error *error = &PluginLoaderCtx.error;
|
||||
PluginHeader *header = &PluginLoaderCtx.header;
|
||||
MemoryBlock *memblock = &PluginLoaderCtx.memblock;
|
||||
bool isPrivate = PluginLoaderCtx.isMemPrivate;
|
||||
|
||||
Result res = 0;
|
||||
|
||||
// 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->code = res;
|
||||
@ -217,7 +218,7 @@ Result MemoryBlock__MountInProcess(void)
|
||||
}
|
||||
|
||||
// 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->code = res;
|
||||
@ -233,7 +234,7 @@ Result MemoryBlock__UnmountFromProcess(void)
|
||||
|
||||
Result res = 0;
|
||||
|
||||
res = svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize);
|
||||
res |= svcUnmapProcessMemoryEx(target, 0x07000000, header->exeSize);
|
||||
res |= svcUnmapProcessMemoryEx(target, header->heapVA, header->heapSize);
|
||||
|
||||
return res;
|
||||
|
||||
@ -558,6 +558,7 @@ static void WaitForProcessTerminated(void *arg)
|
||||
ctx->isSwapFunctionset = false;
|
||||
ctx->pluginMemoryStrategy = PLG_STRATEGY_SWAP;
|
||||
ctx->eventsSelfManaged = false;
|
||||
ctx->isMemPrivate = false;
|
||||
g_blockMenuOpen = 0;
|
||||
MemoryBlock__ResetSwapSettings();
|
||||
//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
|
||||
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);
|
||||
return res;
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user