mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-12-18 08:22:04 +00:00
Loader: Implement most of LoadNsosIntoProcessMemory
This commit is contained in:
parent
d09c48c6c7
commit
a96f862f11
3 changed files with 78 additions and 1 deletions
|
@ -2,6 +2,7 @@
|
|||
#include <algorithm>
|
||||
#include <cstdio>
|
||||
#include "ldr_nso.hpp"
|
||||
#include "ldr_map.hpp"
|
||||
#include "ldr_random.hpp"
|
||||
|
||||
static NsoUtils::NsoHeader g_nso_headers[NSO_NUM_MAX] = {0};
|
||||
|
@ -169,3 +170,70 @@ Result NsoUtils::CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLo
|
|||
|
||||
return 0x0;
|
||||
}
|
||||
|
||||
|
||||
Result NsoUtils::LoadNsoSegment(unsigned int index, unsigned int segment, FILE *f_nso, u8 *map_base) {
|
||||
/* TODO */
|
||||
return 0xA09;
|
||||
}
|
||||
|
||||
Result NsoUtils::LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, u8 *args, u32 args_size) {
|
||||
Result rc = 0xA09;
|
||||
for (unsigned int i = 0; i < NSO_NUM_MAX; i++) {
|
||||
if (g_nso_present[i]) {
|
||||
u64 map_addr = 0;
|
||||
if (R_FAILED((rc = MapUtils::LocateSpaceForMap(&map_addr, extents->nso_sizes[i])))) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
u8 *map_base = (u8 *)map_addr;
|
||||
|
||||
if (R_FAILED((rc = svcMapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
FILE *f_nso = OpenNso(i, title_id);
|
||||
if (f_nso == NULL) {
|
||||
/* Is there a better error to return here? */
|
||||
return 0xA09;
|
||||
}
|
||||
for (unsigned int seg = 0; seg < 3; seg++) {
|
||||
if (R_FAILED((rc = LoadNsoSegment(i, seg, f_nso, map_base)))) {
|
||||
fclose(f_nso);
|
||||
svcUnmapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i]);
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
fclose(f_nso);
|
||||
/* Zero out memory before .text. */
|
||||
u64 text_base = 0, text_start = g_nso_headers[i].segments[0].dst_offset;
|
||||
std::fill(map_base + text_base, map_base + text_start, 0);
|
||||
/* Zero out memory before .rodata. */
|
||||
u64 ro_base = text_start + g_nso_headers[i].segments[0].decomp_size, ro_start = g_nso_headers[i].segments[1].dst_offset;
|
||||
std::fill(map_base + ro_base, map_base + ro_start, 0);
|
||||
/* Zero out memory before .rwdata. */
|
||||
u64 rw_base = ro_start + g_nso_headers[i].segments[1].decomp_size, rw_start = g_nso_headers[i].segments[2].dst_offset;
|
||||
std::fill(map_base + rw_base, map_base + rw_start, 0);
|
||||
/* Zero out .bss. */
|
||||
u64 bss_base = rw_base + g_nso_headers[i].segments[2].decomp_size, bss_size = g_nso_headers[i].segments[2].align_or_total_size;
|
||||
std::fill(map_base + bss_base, map_base + bss_base + bss_size, 0);
|
||||
|
||||
if (R_FAILED((rc = svcUnmapProcessMemory(map_base, process_h, extents->nso_addresses[i], extents->nso_sizes[i])))) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
for (unsigned int seg = 0; seg < 3; seg++) {
|
||||
u64 size = g_nso_headers[i].segments[seg].decomp_size;
|
||||
size += 0xFFF;
|
||||
size &= ~0xFFFULL;
|
||||
const static unsigned int segment_perms[3] = {5, 1, 3};
|
||||
if (R_FAILED((rc = svcSetProcessMemoryPermission(process_h, extents->nso_addresses[i] + g_nso_headers[i].segments[seg].dst_offset, size, segment_perms[seg])))) {
|
||||
return rc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* TODO: Map in arguments, here. */
|
||||
return rc;
|
||||
}
|
||||
|
|
|
@ -82,4 +82,7 @@ class NsoUtils {
|
|||
static Result LoadNsoHeaders(u64 title_id);
|
||||
static Result ValidateNsoLoadSet();
|
||||
static Result CalculateNsoLoadExtents(u32 addspace_type, u32 args_size, NsoLoadExtents *extents);
|
||||
|
||||
static Result LoadNsoSegment(unsigned int index, unsigned int segment, FILE *f_nso, u8 *map_base);
|
||||
static Result LoadNsosIntoProcessMemory(Handle process_h, u64 title_id, NsoLoadExtents *extents, u8 *args, u32 args_size);
|
||||
};
|
|
@ -159,6 +159,12 @@ Result ProcessCreation::CreateProcess(Handle *out_process_h, u64 index, char *nc
|
|||
goto CREATE_PROCESS_END;
|
||||
}
|
||||
|
||||
/* Load all NSOs into Process memory, and set permissions accordingly. */
|
||||
if (launch_item == NULL) {
|
||||
NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, (u8 *)launch_item->args, launch_item->arg_size);
|
||||
} else {
|
||||
NsoUtils::LoadNsosIntoProcessMemory(process_h, npdm_info.aci0->title_id, &nso_extents, NULL, 0);
|
||||
}
|
||||
/* TODO: For each NSO, call svcMapProcessMemory, load the NSO into memory there (validating it), and then svcUnmapProcessMemory. */
|
||||
|
||||
/* TODO: svcSetProcessMemoryPermission for each memory segment in the new process. */
|
||||
|
|
Loading…
Reference in a new issue