From 30b2d05bac8b16a39c3ddd058243f730f929fa5a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Jan 2018 21:53:13 -0800 Subject: [PATCH 1/3] Module: Correct detection of executable sections. --- Core/ELF/ElfReader.cpp | 11 ++++++++++ Core/ELF/ElfReader.h | 6 ++++-- Core/HLE/sceKernelModule.cpp | 41 ++++++++++++++++++------------------ Core/MIPS/MIPSAnalyst.cpp | 6 ++++-- 4 files changed, 39 insertions(+), 25 deletions(-) diff --git a/Core/ELF/ElfReader.cpp b/Core/ELF/ElfReader.cpp index 9494604bd6..b68e7775b8 100644 --- a/Core/ELF/ElfReader.cpp +++ b/Core/ELF/ElfReader.cpp @@ -633,6 +633,17 @@ u32 ElfReader::GetTotalSectionSizeByPrefix(const std::string &prefix) const { return total; } +std::vector ElfReader::GetCodeSections() const { + std::vector ids; + for (int i = 0; i < GetNumSections(); ++i) { + u32 flags = sections[i].sh_flags; + if ((flags & (SHF_ALLOC | SHF_EXECINSTR)) == (SHF_ALLOC | SHF_EXECINSTR)) { + ids.push_back(i); + } + } + return ids; +} + bool ElfReader::LoadSymbols() { bool hasSymbols = false; diff --git a/Core/ELF/ElfReader.h b/Core/ELF/ElfReader.h index 78680c0f42..44d33a8e8e 100644 --- a/Core/ELF/ElfReader.h +++ b/Core/ELF/ElfReader.h @@ -17,9 +17,9 @@ #pragma once +#include #include "Common/CommonTypes.h" - -#include "ElfTypes.h" +#include "Core/ELF/ElfTypes.h" enum { R_MIPS_NONE, @@ -130,6 +130,8 @@ public: u32 GetTotalDataSize() const; u32 GetTotalSectionSizeByPrefix(const std::string &prefix) const; + std::vector GetCodeSections() const; + int LoadInto(u32 vaddr, bool fromTop); bool LoadSymbols(); bool LoadRelocations(const Elf32_Rel *rels, int numRelocs); diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index d26eabf4f4..3448e5f6a9 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1238,18 +1238,6 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd module->nm.text_addr = module->textStart; module->nm.text_size = reader.GetTotalTextSize(); - - if (!module->isFake) { -#if !defined(MOBILE_DEVICE) - bool gotSymbols = reader.LoadSymbols(); - MIPSAnalyst::ScanForFunctions(module->textStart, module->textEnd, !gotSymbols); -#else - if (g_Config.bFuncReplacements) { - bool gotSymbols = reader.LoadSymbols(); - MIPSAnalyst::ScanForFunctions(module->textStart, module->textEnd, !gotSymbols); - } -#endif - } } else { module->nm.text_addr = 0; module->nm.text_size = 0; @@ -1269,17 +1257,28 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd if (textSection == -1) { module->textStart = reader.GetVaddr(); module->textEnd = firstImportStubAddr - 4; + } - if (!module->isFake) { -#if !defined(MOBILE_DEVICE) - bool gotSymbols = reader.LoadSymbols(); - MIPSAnalyst::ScanForFunctions(module->textStart, module->textEnd, !gotSymbols); -#else - if (g_Config.bFuncReplacements) { - bool gotSymbols = reader.LoadSymbols(); - MIPSAnalyst::ScanForFunctions(module->textStart, module->textEnd, !gotSymbols); - } + if (!module->isFake) { + bool scan = true; +#if defined(MOBILE_DEVICE) + scan = g_Config.bFuncReplacements; #endif + + bool gotSymbols = scan && reader.LoadSymbols(); + std::vector codeSections = reader.GetCodeSections(); + for (SectionID id : codeSections) { + u32 start = reader.GetSectionAddr(id); + u32 end = start + reader.GetSectionSize(id); + + if (start < module->textStart) + module->textStart = start; + if (end > module->textEnd) + module->textEnd = end; + + // Note: scan end is inclusive. + if (scan) + MIPSAnalyst::ScanForFunctions(start, end - 4, !gotSymbols); } } diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 3070c864b3..99afd042d3 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -1124,8 +1124,10 @@ skip: } } - currentFunction.end = addr + 4; - functions.push_back(currentFunction); + if (addr <= endAddr) { + currentFunction.end = addr + 4; + functions.push_back(currentFunction); + } for (auto iter = functions.begin(); iter != functions.end(); iter++) { iter->size = iter->end - iter->start + 4; From 00a05e97acacc51fe4b60e1d0896a4041380c364 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Jan 2018 22:20:09 -0800 Subject: [PATCH 2/3] Module: Scan modules with no sections at all. Also, fix some off-by-one issues with end addresses. --- Core/HLE/sceKernelModule.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index 3448e5f6a9..b65394ddb0 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1234,7 +1234,7 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd if (textSection != -1) { module->textStart = reader.GetSectionAddr(textSection); u32 textSize = reader.GetSectionSize(textSection); - module->textEnd = module->textStart + textSize; + module->textEnd = module->textStart + textSize - 4; module->nm.text_addr = module->textStart; module->nm.text_size = reader.GetTotalTextSize(); @@ -1269,16 +1269,21 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd std::vector codeSections = reader.GetCodeSections(); for (SectionID id : codeSections) { u32 start = reader.GetSectionAddr(id); - u32 end = start + reader.GetSectionSize(id); + // Note: scan end is inclusive. + u32 end = start + reader.GetSectionSize(id) - 4; if (start < module->textStart) module->textStart = start; if (end > module->textEnd) module->textEnd = end; - // Note: scan end is inclusive. if (scan) - MIPSAnalyst::ScanForFunctions(start, end - 4, !gotSymbols); + MIPSAnalyst::ScanForFunctions(start, end, !gotSymbols); + } + + // Some games don't have any sections at all. + if (scan && codeSections.empty()) { + MIPSAnalyst::ScanForFunctions(module->textStart, module->textEnd, !gotSymbols); } } From 29ed48c32aabe03cb086634b6dd0a26c6a57d7f1 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Tue, 2 Jan 2018 22:21:08 -0800 Subject: [PATCH 3/3] Module: Avoid scanning stubs if possible. In this case, we often scan some garbage, but let's reduce it at least. --- Core/HLE/sceKernelModule.cpp | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/Core/HLE/sceKernelModule.cpp b/Core/HLE/sceKernelModule.cpp index b65394ddb0..26d54d8794 100644 --- a/Core/HLE/sceKernelModule.cpp +++ b/Core/HLE/sceKernelModule.cpp @@ -1283,7 +1283,18 @@ static Module *__KernelLoadELFFromPtr(const u8 *ptr, size_t elfSize, u32 loadAdd // Some games don't have any sections at all. if (scan && codeSections.empty()) { - MIPSAnalyst::ScanForFunctions(module->textStart, module->textEnd, !gotSymbols); + u32 scanStart = module->textStart; + u32 scanEnd = module->textEnd; + // Skip the exports and imports sections, they're not code. + if (scanEnd >= std::min(modinfo->libent, modinfo->libstub)) { + MIPSAnalyst::ScanForFunctions(scanStart, std::min(modinfo->libent, modinfo->libstub) - 4, !gotSymbols); + scanStart = std::min(modinfo->libentend, modinfo->libstubend); + } + if (scanEnd >= std::max(modinfo->libent, modinfo->libstub)) { + MIPSAnalyst::ScanForFunctions(scanStart, std::max(modinfo->libent, modinfo->libstub) - 4, !gotSymbols); + scanStart = std::max(modinfo->libentend, modinfo->libstubend); + } + MIPSAnalyst::ScanForFunctions(scanStart, scanEnd, !gotSymbols); } }