Skip to content

Commit

Permalink
Merge pull request #1298 from nicolasnoble/load-symbols
Browse files Browse the repository at this point in the history
Loading symbols off binaries.
  • Loading branch information
nicolasnoble committed Apr 27, 2023
2 parents 32a0ada + 63ba55a commit 1b89c00
Show file tree
Hide file tree
Showing 7 changed files with 67 additions and 22 deletions.
7 changes: 6 additions & 1 deletion src/core/psxmem.cc
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
#include "core/r3000a.h"
#include "mips/common/util/encoder.hh"
#include "support/file.h"
#include "supportpsx/binloader.h"

static const std::map<uint32_t, std::string_view> s_knownBioses = {
#ifdef USE_ADLER
Expand Down Expand Up @@ -208,7 +209,11 @@ The distributed OpenBIOS.bin file can be an appropriate BIOS replacement.
}

if (!f->failed()) {
f->read(m_bios, bios_size);
BinaryLoader::Info i;
if (!BinaryLoader::load(f, getMemoryAsFile(), i, g_emulator->m_cpu->m_symbols)) {
f->rSeek(0);
f->read(m_bios, bios_size);
}
f->close();
PCSX::g_system->printf(_("Loaded BIOS: %s\n"), biosPath.string());
}
Expand Down
5 changes: 3 additions & 2 deletions src/gui/gui.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2102,7 +2102,7 @@ void PCSX::GUI::shellReached() {
if (in->failed()) {
throw std::runtime_error("Failed to open file.");
}
success = BinaryLoader::load(in, g_emulator->m_mem->getMemoryAsFile(), info);
success = BinaryLoader::load(in, g_emulator->m_mem->getMemoryAsFile(), info, g_emulator->m_cpu->m_symbols);
if (!info.pc.has_value()) {
throw std::runtime_error("Binary loaded without any PC to jump to.");
}
Expand Down Expand Up @@ -2145,7 +2145,8 @@ void PCSX::GUI::magicOpen(const char* pathStr) {
bool success = false;
try {
BinaryLoader::Info info;
success = BinaryLoader::load(new PosixFile(path), new Mem4G(), info);
std::map<uint32_t, std::string> symbols;
success = BinaryLoader::load(new PosixFile(path), new Mem4G(), info, symbols);
if (success) success = info.pc.has_value();
} catch (...) {
success = false;
Expand Down
64 changes: 49 additions & 15 deletions src/supportpsx/binloader.cc
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,17 @@ namespace PCSX {

namespace {

bool loadCPE(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
void eraseSymbolsInSpan(uint32_t low, uint32_t high, std::map<uint32_t, std::string>& symbols) {
for (auto s = symbols.begin(); s != symbols.end();) {
if (s->first >= low && s->first < high) {
s = symbols.erase(s);
} else {
s++;
}
}
}

bool loadCPE(IO<File> file, IO<File> dest, BinaryLoader::Info& info, std::map<uint32_t, std::string>& symbols) {
uint32_t magic = file->read<uint32_t>();
if (magic != 0x1455043) return false;
file->skip<uint16_t>();
Expand All @@ -50,6 +60,7 @@ bool loadCPE(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
uint32_t addr = file->read<uint32_t>();
uint32_t size = file->read<uint32_t>();
dest->writeAt(file->read(size), addr);
eraseSymbolsInSpan(addr, addr + size, symbols);
} break;
case 2: {
file->read<uint32_t>();
Expand Down Expand Up @@ -96,7 +107,7 @@ bool loadCPE(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
return true;
}

bool loadPSEXE(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
bool loadPSEXE(IO<File> file, IO<File> dest, BinaryLoader::Info& info, std::map<uint32_t, std::string>& symbols) {
uint64_t magic = file->read<uint64_t>();
if (magic != 0x45584520582d5350) return false;

Expand All @@ -117,6 +128,7 @@ bool loadPSEXE(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
uint8_t regionByte = file->byte();
file->rSeek(2048, SEEK_SET);
dest->writeAt(file->read(size), addr);
eraseSymbolsInSpan(addr, addr + size, symbols);
switch (regionByte) {
case 'A':
case 'J':
Expand All @@ -129,7 +141,8 @@ bool loadPSEXE(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
return true;
}

bool loadPSF(IO<File> file, IO<File> dest, BinaryLoader::Info& info, bool seenRefresh = false, unsigned depth = 0) {
bool loadPSF(IO<File> file, IO<File> dest, BinaryLoader::Info& info, std::map<uint32_t, std::string>& symbols,
bool seenRefresh = false, unsigned depth = 0) {
if (depth >= 10) return false;
uint32_t magic = file->read<uint32_t>();
if (magic != 0x1465350) return false;
Expand Down Expand Up @@ -173,11 +186,11 @@ bool loadPSF(IO<File> file, IO<File> dest, BinaryLoader::Info& info, bool seenRe
if (pairs.find("_lib") != pairs.end()) {
std::filesystem::path subFilePath(file->filename());
IO<File> subFile(new PosixFile(subFilePath.parent_path() / pairs["_lib"]));
if (!subFile->failed()) loadPSF(subFile, dest, info, seenRefresh, depth++);
if (!subFile->failed()) loadPSF(subFile, dest, info, symbols, seenRefresh, depth++);
}

IO<File> psexe(new ZReader(zpsexe));
loadPSEXE(psexe, dest, info);
loadPSEXE(psexe, dest, info, symbols);

unsigned libNum = 2;

Expand All @@ -186,13 +199,13 @@ bool loadPSF(IO<File> file, IO<File> dest, BinaryLoader::Info& info, bool seenRe
if (pairs.find(libName) == pairs.end()) break;
std::filesystem::path subFilePath(file->filename());
IO<File> subFile(new PosixFile(subFilePath.parent_path() / pairs[libName]));
if (!subFile->failed()) loadPSF(subFile, dest, info, seenRefresh, depth++);
if (!subFile->failed()) loadPSF(subFile, dest, info, symbols, seenRefresh, depth++);
}

return true;
}

bool loadELF(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
bool loadELF(IO<File> file, IO<File> dest, BinaryLoader::Info& info, std::map<uint32_t, std::string>& symbols) {
using namespace ELFIO;
elfio reader;
FileIStream stream(file);
Expand All @@ -203,8 +216,8 @@ bool loadELF(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
info.pc = reader.get_entry();

Elf_Half sec_num = reader.sections.size();
for (int i = 0; i < sec_num; i++) {
const section* psec = reader.sections[i];
for (unsigned i = 0; i < sec_num; i++) {
section* psec = reader.sections[i];
auto name = psec->get_name();

if (StringsHelpers::endsWith(name, "_Header")) continue;
Expand All @@ -217,6 +230,27 @@ bool loadELF(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {
auto data = psec->get_data();
auto addr = psec->get_address();
dest->writeAt(data, size, addr);
eraseSymbolsInSpan(addr, addr + size, symbols);
}

for (unsigned i = 0; i < sec_num; i++) {
section* psec = reader.sections[i];
auto name = psec->get_name();

auto type = psec->get_type();
if (type != SHT_SYMTAB) continue;
const ELFIO::symbol_section_accessor symbolstab(reader, psec);
for (unsigned s = 0; s < symbolstab.get_symbols_num(); s++) {
std::string name;
Elf64_Addr value;
Elf_Xword size;
unsigned char bind;
unsigned char type;
Elf_Half section_index;
unsigned char other;
symbolstab.get_symbol(s, name, value, size, bind, type, section_index, other);
symbols[value] = name;
}
}

return true;
Expand All @@ -226,19 +260,19 @@ bool loadELF(IO<File> file, IO<File> dest, BinaryLoader::Info& info) {

} // namespace PCSX

bool PCSX::BinaryLoader::load(IO<File> in, IO<File> dest, Info& info) {
bool PCSX::BinaryLoader::load(IO<File> in, IO<File> dest, Info& info, std::map<uint32_t, std::string>& symbols) {
{
IO<File> ny(new PosixFile(in->filename().parent_path() / "libps.exe"));
if (!ny->failed()) loadPSEXE(ny, dest, info);
if (!ny->failed()) loadPSEXE(ny, dest, info, symbols);
}

if (in->failed()) return false;
if (loadCPE(in, dest, info)) return true;
if (loadCPE(in, dest, info, symbols)) return true;
in->rSeek(0, SEEK_SET);
if (loadPSEXE(in, dest, info)) return true;
if (loadPSEXE(in, dest, info, symbols)) return true;
in->rSeek(0, SEEK_SET);
if (loadPSF(in, dest, info)) return true;
if (loadPSF(in, dest, info, symbols)) return true;
in->rSeek(0, SEEK_SET);
if (loadELF(in, dest, info)) return true;
if (loadELF(in, dest, info, symbols)) return true;
return false;
}
4 changes: 3 additions & 1 deletion src/supportpsx/binloader.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@
#include <stdint.h>

#include <filesystem>
#include <map>
#include <optional>
#include <string>

#include "support/file.h"

Expand All @@ -38,7 +40,7 @@ struct Info {
std::optional<uint32_t> gp;
};

bool load(IO<File> in, IO<File> dest, Info& info);
bool load(IO<File> in, IO<File> dest, Info& info, std::map<uint32_t, std::string>& symbols);

} // namespace BinaryLoader

Expand Down
3 changes: 2 additions & 1 deletion src/supportpsx/binlua.cc
Original file line number Diff line number Diff line change
Expand Up @@ -41,11 +41,12 @@ struct BinaryLoaderInfo {

bool binaryLoaderLoad(PCSX::LuaFFI::LuaFile* src, PCSX::LuaFFI::LuaFile* dest, BinaryLoaderInfo* info) {
PCSX::BinaryLoader::Info i;
std::map<uint32_t, std::string> symbols;
info->region = PCSX::BinaryLoader::Region::UNKNOWN;
info->pc = 0;
info->sp = 0;
info->gp = 0;
bool ret = PCSX::BinaryLoader::load(src->file, dest->file, i);
bool ret = PCSX::BinaryLoader::load(src->file, dest->file, i, symbols);
if (ret) {
info->region = i.region.value_or(PCSX::BinaryLoader::Region::UNKNOWN);
info->pc = i.pc.value_or(0);
Expand Down
3 changes: 2 additions & 1 deletion tools/exe2elf/exe2elf.cc
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ Usage: {} input.ps-exe [-h] -o output.elf

PCSX::BinaryLoader::Info info;
PCSX::IO<PCSX::Mem4G> memory(new PCSX::Mem4G());
bool success = PCSX::BinaryLoader::load(file, memory, info);
std::map<uint32_t, std::string> symbols;
bool success = PCSX::BinaryLoader::load(file, memory, info, symbols);
if (!success) {
fmt::print("Unable to load file: {}\n", input);
return -1;
Expand Down
3 changes: 2 additions & 1 deletion tools/ps1-packer/ps1-packer.cc
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,8 @@ Valid input binary files can be in the following formats:

PCSX::BinaryLoader::Info info;
PCSX::IO<PCSX::Mem4G> memory(new PCSX::Mem4G());
bool success = PCSX::BinaryLoader::load(file, memory, info);
std::map<uint32_t, std::string> symbols;
bool success = PCSX::BinaryLoader::load(file, memory, info, symbols);
if (!success) {
fmt::print("Unable to load file: {}\n", input);
return -1;
Expand Down

0 comments on commit 1b89c00

Please sign in to comment.