Loader: Automatically unload NRRs on service close.

This commit is contained in:
Michael Scire 2018-04-26 20:50:27 -06:00
parent e7aa5c246b
commit 2e7b6de195
3 changed files with 38 additions and 14 deletions

View file

@ -7,8 +7,7 @@ static Registration::List g_registration_list = {0};
static u64 g_num_registered = 1;
Registration::Process *Registration::GetFreeProcess() {
unsigned int i;
for (i = 0; i < REGISTRATION_LIST_MAX; i++) {
for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) {
if (!g_registration_list.processes[i].in_use) {
return &g_registration_list.processes[i];
}
@ -17,24 +16,30 @@ Registration::Process *Registration::GetFreeProcess() {
}
Registration::Process *Registration::GetProcess(u64 index) {
unsigned int i;
for (i = 0; i < REGISTRATION_LIST_MAX && (!g_registration_list.processes[i].in_use || g_registration_list.processes[i].index != index); i++) {
for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) {
if (g_registration_list.processes[i].in_use && g_registration_list.processes[i].index == index) {
return &g_registration_list.processes[i];
}
}
if (i >= REGISTRATION_LIST_MAX) {
return NULL;
}
return &g_registration_list.processes[i];
return NULL;
}
Registration::Process *Registration::GetProcessByProcessId(u64 pid) {
unsigned int i;
for (i = 0; i < REGISTRATION_LIST_MAX && (!g_registration_list.processes[i].in_use || g_registration_list.processes[i].process_id != pid); i++) {
for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) {
if (g_registration_list.processes[i].in_use && g_registration_list.processes[i].process_id == pid) {
return &g_registration_list.processes[i];
}
}
if (i >= REGISTRATION_LIST_MAX) {
return NULL;
return NULL;
}
Registration::Process *Registration::GetProcessByRoService(void *service) {
for (unsigned int i = 0; i < REGISTRATION_LIST_MAX; i++) {
if (g_registration_list.processes[i].in_use && g_registration_list.processes[i].owner_ro_service == service) {
return &g_registration_list.processes[i];
}
}
return &g_registration_list.processes[i];
return NULL;
}
bool Registration::RegisterTidSid(const TidSid *tid_sid, u64 *out_index) {
@ -103,6 +108,17 @@ void Registration::AddNsoInfo(u64 index, u64 base_address, u64 size, const unsig
}
}
void Registration::CloseRoService(void *service, Handle process_h) {
Registration::Process *target_process = GetProcessByRoService(service);
if (target_process == NULL) {
return;
}
for (unsigned int i = 0; i < NRR_INFO_MAX; i++) {
if (target_process->nrr_infos[i].IsActive() && target_process->nrr_infos[i].process_handle == process_h) {
target_process->nrr_infos[i].Close();
}
}
}
Result Registration::AddNrrInfo(u64 index, MappedCodeMemory *nrr_info) {
Registration::Process *target_process = GetProcess(index);

View file

@ -46,11 +46,13 @@ class Registration {
static Registration::Process *GetFreeProcess();
static Registration::Process *GetProcess(u64 index);
static Registration::Process *GetProcessByProcessId(u64 pid);
static Registration::Process *GetProcessByRoService(void *service);
static Result GetRegisteredTidSid(u64 index, Registration::TidSid *out);
static bool RegisterTidSid(const TidSid *tid_sid, u64 *out_index);
static bool UnregisterIndex(u64 index);
static void SetProcessIdTidMinAndIs64BitAddressSpace(u64 index, u64 process_id, u64 tid_min, bool is_64_bit_addspace);
static void AddNsoInfo(u64 index, u64 base_address, u64 size, const unsigned char *build_id);
static void CloseRoService(void *service, Handle process_h);
static Result AddNrrInfo(u64 index, MappedCodeMemory *nrr_info);
static Result RemoveNrrInfo(u64 index, u64 base_address);
static Result GetNsoInfosForProcessId(NsoInfo *out, u32 max_out, u64 process_id, u32 *num_written);

View file

@ -18,6 +18,12 @@ class RelocatableObjectsService : IServiceObject {
bool has_initialized;
public:
RelocatableObjectsService() : process_handle(0), process_id(U64_MAX), has_initialized(false) { }
~RelocatableObjectsService() {
Registration::CloseRoService(this, this->process_handle);
if (this->has_initialized) {
svcCloseHandle(this->process_handle);
}
}
virtual Result dispatch(IpcParsedCommand &r, IpcCommand &out_c, u64 cmd_id, u8 *pointer_buffer, size_t pointer_buffer_size);
virtual Result handle_deferred() {
/* This service will never defer. */