From e9f4fc638ed904cc0dcdac24ea7708c9a220a702 Mon Sep 17 00:00:00 2001 From: briaguya <70942617+briaguya-ai@users.noreply.github.com> Date: Tue, 17 Oct 2023 22:04:12 -0400 Subject: update to latest version used by SoH --- ZAPD/Overlays/ZOverlay.cpp | 354 +++++++++++++++++++++++++++++++++++++++++++++ ZAPD/Overlays/ZOverlay.h | 78 ++++++++++ 2 files changed, 432 insertions(+) create mode 100644 ZAPD/Overlays/ZOverlay.cpp create mode 100644 ZAPD/Overlays/ZOverlay.h (limited to 'ZAPD/Overlays') diff --git a/ZAPD/Overlays/ZOverlay.cpp b/ZAPD/Overlays/ZOverlay.cpp new file mode 100644 index 0000000..168ed23 --- /dev/null +++ b/ZAPD/Overlays/ZOverlay.cpp @@ -0,0 +1,354 @@ +#if 0 +#include "ZOverlay.h" + +#include +#include +#include "Globals.h" +#include "Utils/Directory.h" +#include +#include "Utils/Path.h" +#include "Utils/StringHelper.h" +#include "WarningHandler.h" + +using namespace ELFIO; + +const char* RelocationEntry::GetSectionName() const +{ + switch (sectionType) + { + case SectionType::Text: + return ".text"; + case SectionType::Data: + return ".data"; + case SectionType::RoData: + return ".rodata"; + case SectionType::Bss: + return ".bss"; + case SectionType::ERROR: + return ".ERROR"; + } + assert(!"Oh no :c"); +} + +const char* RelocationEntry::GetRelocTypeName() const +{ + switch (relocationType) + { + case RelocationType::R_MIPS_32: + return "R_MIPS_32"; + case RelocationType::R_MIPS_26: + return "R_MIPS_26"; + case RelocationType::R_MIPS_HI16: + return "R_MIPS_HI16"; + case RelocationType::R_MIPS_LO16: + return "R_MIPS_LO16"; + } + assert(!"Oh no :c"); +} + +ZOverlay::ZOverlay() +{ + name = ""; + entries = std::vector(); +} + +ZOverlay::ZOverlay(const std::string& nName) : ZOverlay() +{ + name = nName; +} + +ZOverlay::~ZOverlay() +{ + for (auto entry : entries) + if (entry) + delete entry; + entries.clear(); +} + +static const std::unordered_set sRelSections = { + ".rel.text", + ".rel.data", + ".rel.rodata", +}; +static const std::unordered_set sSections = { + ".text", ".data", ".symtab", ".rodata", ".rodata.str1.4", ".rodata.cst4", ".rodata.cst8", +}; + +ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath) +{ + std::string cfgText = DiskFile::ReadAllText(cfgFolderPath / "overlay.cfg"); + std::vector cfgLines = StringHelper::Split(cfgText, "\n"); + + ZOverlay* ovl = new ZOverlay(StringHelper::Strip(cfgLines[0], "\r")); + ovl->cfgLines = cfgLines; + + int32_t sectionOffs[5] = {0}; + std::vector textRelocs; + std::vector dataRelocs; + std::vector rodataRelocs; + + // get the elf files + std::vector readers; + for (size_t i = 1; i < cfgLines.size(); i++) + { + std::string elfPath = + (buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o")).string(); + elfio* reader = new elfio(); + + if (!reader->load(elfPath)) + { + // not all files were compiled + for (auto r : readers) + delete r; + readers.clear(); + + delete ovl; + return nullptr; + } + + readers.push_back(reader); + } + + for (size_t curReaderId = 0; curReaderId < readers.size(); curReaderId++) + { + auto& curReader = readers[curReaderId]; + + Elf_Half sec_num = curReader->sections.size(); + for (int32_t i = 0; i < sec_num; i++) + { + section* pSec = curReader->sections[i]; + + if (pSec->get_type() != SHT_REL || + sRelSections.find(pSec->get_name()) == sRelSections.end()) + { + continue; + } + + symbol_section_accessor currentSymbols(*curReader, + curReader->sections[(Elf_Half)pSec->get_link()]); + + SectionType sectionType = GetSectionTypeFromStr(pSec->get_name()); + + if (sectionType == SectionType::ERROR) + { + HANDLE_WARNING(WarningType::Always, "one of the section types returned ERROR", ""); + } + + relocation_section_accessor relocs(*curReader, pSec); + for (Elf_Xword j = 0; j < relocs.get_entries_num(); j++) + { + Elf64_Addr offset = 0; + Elf_Word symbol = 0; + Elf_Word type = 0; + { + Elf_Sxword addend = 0; + relocs.get_entry(j, offset, symbol, type, addend); + } + + std::string curSymName; + Elf_Half curSymShndx = SHN_UNDEF; + { + Elf64_Addr value; + Elf_Xword size; + unsigned char bind; + unsigned char type; + unsigned char other; + currentSymbols.get_symbol(symbol, curSymName, value, size, bind, type, + curSymShndx, other); + } + + // check symbols outside the elf but within the overlay + if (curSymShndx == SHN_UNDEF) + { + if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) + { + printf("Symbol '%s' doesn't exist in current .o file (%s). Searching...\n", + curSymName.c_str(), cfgLines[curReaderId + 1].c_str()); + } + + for (size_t readerId = 0; readerId < readers.size(); readerId++) + { + auto& reader = readers[readerId]; + + if (curSymShndx != SHN_UNDEF) + break; + + if (reader == curReader) + continue; + + auto sectionData = reader->sections[(Elf_Half)pSec->get_link()]; + curSymShndx = + ovl->FindSymbolInSection(curSymName, sectionData, *reader, readerId); + if (curSymShndx != SHN_UNDEF) + break; + + if (Globals::Instance->gccCompat) + { + // Symbol wasn't found, try checking every section + Elf_Half sec_num = reader->sections.size(); + for (int32_t otherSectionIdx = 0; otherSectionIdx < sec_num; + otherSectionIdx++) + { + if (curSymShndx != SHN_UNDEF) + { + break; + } + + auto sectionDataIter = reader->sections[otherSectionIdx]; + + curSymShndx = ovl->FindSymbolInSection(curSymName, sectionDataIter, + *reader, readerId); + } + } + } + } + + if (curSymShndx != SHN_UNDEF) + { + RelocationType typeConverted = (RelocationType)type; + offset += sectionOffs[static_cast(sectionType)]; + + RelocationEntry* reloc = + new RelocationEntry(sectionType, typeConverted, offset); + + if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) + { + printf(".word 0x%08X # %s %s 0x%04X\n", reloc->CalcRelocationWord(), + reloc->GetSectionName(), reloc->GetRelocTypeName(), reloc->offset); + } + + // this is to keep the correct reloc entry order + if (sectionType == SectionType::Text) + textRelocs.push_back(reloc); + if (sectionType == SectionType::Data) + dataRelocs.push_back(reloc); + if (sectionType == SectionType::RoData) + rodataRelocs.push_back(reloc); + } + } + } + + // increase section offsets + for (int32_t i = 0; i < sec_num; i++) + { + section* pSec = curReader->sections[i]; + if (pSec->get_type() == SHT_PROGBITS && + sSections.find(pSec->get_name()) != sSections.end()) + { + SectionType sectionType = GetSectionTypeFromStr(pSec->get_name()); + sectionOffs[static_cast(sectionType)] += pSec->get_size(); + } + } + } + + ovl->entries.reserve(textRelocs.size() + dataRelocs.size() + rodataRelocs.size()); + ovl->entries.insert(ovl->entries.end(), textRelocs.begin(), textRelocs.end()); + ovl->entries.insert(ovl->entries.end(), dataRelocs.begin(), dataRelocs.end()); + ovl->entries.insert(ovl->entries.end(), rodataRelocs.begin(), rodataRelocs.end()); + + for (auto r : readers) + delete r; + readers.clear(); + + return ovl; +} + +std::string ZOverlay::GetSourceOutputCode([[maybe_unused]] const std::string& prefix) +{ + std::string output; + + output += ".section .ovl\n"; + + output += StringHelper::Sprintf("# %sOverlayInfo\n", name.c_str()); + output += StringHelper::Sprintf(".word _%sSegmentTextSize\n", name.c_str()); + output += StringHelper::Sprintf(".word _%sSegmentDataSize\n", name.c_str()); + output += StringHelper::Sprintf(".word _%sSegmentRoDataSize\n", name.c_str()); + output += StringHelper::Sprintf(".word _%sSegmentBssSize\n", name.c_str()); + output += "\n"; + + output += StringHelper::Sprintf(".word %i # reloc_count\n", entries.size()); + + for (size_t i = 0; i < entries.size(); i++) + { + RelocationEntry* reloc = entries[i]; + output += StringHelper::Sprintf(".word 0x%08X # %s %s 0x%04X\n", + reloc->CalcRelocationWord(), reloc->GetSectionName(), + reloc->GetRelocTypeName(), reloc->offset); + } + + size_t offset = (entries.size() * 4) + 20; + + while (offset % 16 != 12) + { + output += ".word 0\n"; + offset += 4; + } + + output += "\n"; + output += + StringHelper::Sprintf(".word 0x%08X # %sOverlayInfoOffset\n", offset + 4, name.c_str()); + return output; +} + +SectionType ZOverlay::GetSectionTypeFromStr(const std::string& sectionName) +{ + if (sectionName == ".rel.text" || sectionName == ".text") + return SectionType::Text; + else if (sectionName == ".rel.data" || sectionName == ".data") + return SectionType::Data; + else if (sectionName == ".rel.rodata" || sectionName == ".rodata" || + sectionName == ".rodata.str1.4" || sectionName == ".rodata.cst4") + return SectionType::RoData; + else if (sectionName == ".rel.bss" || sectionName == ".bss") + return SectionType::Bss; + + return SectionType::ERROR; +} + +ELFIO::Elf_Half ZOverlay::FindSymbolInSection(const std::string& curSymName, + ELFIO::section* sectionData, ELFIO::elfio& reader, + size_t readerId) +{ + if (sectionData == nullptr) + return SHN_UNDEF; + + auto sectionDataName = sectionData->get_name(); + if (sSections.find(sectionDataName) == sSections.end()) + return SHN_UNDEF; + +#ifdef DEVELOPMENT + if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) + { + printf("\t File '%s' section: %s \n", cfgLines[readerId + 1].c_str(), + sectionDataName.c_str()); + } +#endif + + symbol_section_accessor symbols(reader, sectionData); + + Elf_Xword symbolNum = symbols.get_symbols_num(); + for (Elf_Xword symIdx = 0; symIdx < symbolNum; symIdx++) + { + Elf_Half shndx = SHN_UNDEF; + Elf64_Addr value; + std::string name; + Elf_Xword size; + unsigned char bind; + unsigned char type; + unsigned char other; + + symbols.get_symbol(symIdx, name, value, size, bind, type, shndx, other); + + if (name == curSymName) + { + if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG) + { + printf("\t Symbol '%s' found in '%s' '%s' \n", curSymName.c_str(), + cfgLines[readerId + 1].c_str(), sectionDataName.c_str()); + } + return shndx; + } + } + return SHN_UNDEF; +} +#endif \ No newline at end of file diff --git a/ZAPD/Overlays/ZOverlay.h b/ZAPD/Overlays/ZOverlay.h new file mode 100644 index 0000000..c1faddd --- /dev/null +++ b/ZAPD/Overlays/ZOverlay.h @@ -0,0 +1,78 @@ +#pragma once + +#if 0 + +#include "Utils/Directory.h" +#include "ZResource.h" +#include "elfio/elfio.hpp" +#include "tinyxml2.h" + +enum class SectionType +{ + Text = 1, + Data = 2, + RoData = 3, + Bss = 4, + ERROR = 255 +}; + +enum class RelocationType +{ + R_MIPS_32 = 2, + R_MIPS_26 = 4, + R_MIPS_HI16 = 5, + R_MIPS_LO16 = 6, +}; + +class RelocationEntry +{ +public: + SectionType sectionType; + RelocationType relocationType; + int32_t offset; + + RelocationEntry(SectionType nSecType, RelocationType nRelType, int32_t nOffset) + { + sectionType = nSecType; + relocationType = nRelType; + offset = nOffset; + } + + uint32_t CalcRelocationWord() + { + uint32_t relocationWord = 0; + + relocationWord |= static_cast(sectionType) << 30; + relocationWord |= static_cast(relocationType) << 24; + relocationWord |= offset; + + return relocationWord; + } + + const char* GetSectionName() const; + const char* GetRelocTypeName() const; +}; + +class ZOverlay +{ +public: + std::string name; + + ZOverlay(const std::string& nName); + ~ZOverlay(); + static ZOverlay* FromBuild(fs::path buildPath, fs::path cfgFolderPath); + std::string GetSourceOutputCode(const std::string& prefix); + +private: + std::vector entries; + std::vector cfgLines; + + ZOverlay(); + + static SectionType GetSectionTypeFromStr(const std::string& sectionName); + // static std::string GetOverlayNameFromElf(ELFIO::elfio& reader); + + ELFIO::Elf_Half FindSymbolInSection(const std::string& curSymName, ELFIO::section* sectionData, + ELFIO::elfio& reader, size_t readerId); +}; +#endif \ No newline at end of file -- cgit v1.2.3