Loader: Implement most of LoadNsosIntoProcessMemory

This commit is contained in:
Michael Scire 2018-04-24 06:01:32 -06:00
parent d09c48c6c7
commit a96f862f11
3 changed files with 78 additions and 1 deletions

View file

@ -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};
@ -168,4 +169,71 @@ 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;
}

View file

@ -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);
};

View file

@ -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. */