mirror of
https://github.com/zeldaret/oot.git
synced 2025-08-10 17:00:19 +00:00
Update ZAPD (#1001)
* remove fake match * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "3e9ed72e2" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "3e9ed72e2" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * new extraction script and a hack to make clear tag work * fix clear tag again * remove static from clear tag DLists * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "e7a8a48cf" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "e7a8a48cf" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "e243634e5" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "e243634e5" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * git subrepo pull --force tools/ZAPD subrepo: subdir: "tools/ZAPD" merged: "d0cd6b397" upstream: origin: "https://github.com/zeldaret/ZAPD.git" branch: "master" commit: "d0cd6b397" git-subrepo: version: "0.4.3" origin: "https://github.com/ingydotnet/git-subrepo.git" commit: "2f68596" * Update ovl_En_Clear_Tag.xml
This commit is contained in:
parent
ed487b4bb8
commit
750c0cab35
272 changed files with 7790 additions and 58414 deletions
|
@ -1,18 +1,57 @@
|
|||
#include "ZOverlay.h"
|
||||
#include "../Directory.h"
|
||||
#include "../File.h"
|
||||
#include "../Path.h"
|
||||
#include "../StringHelper.h"
|
||||
|
||||
#include <assert.h>
|
||||
#include <unordered_set>
|
||||
|
||||
#include <Utils/Directory.h>
|
||||
#include <Utils/File.h>
|
||||
#include <Utils/Path.h>
|
||||
#include <Utils/StringHelper.h>
|
||||
#include "Globals.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<RelocationEntry*>();
|
||||
}
|
||||
|
||||
ZOverlay::ZOverlay(std::string nName) : ZOverlay()
|
||||
ZOverlay::ZOverlay(const std::string& nName) : ZOverlay()
|
||||
{
|
||||
name = nName;
|
||||
}
|
||||
|
@ -25,15 +64,22 @@ ZOverlay::~ZOverlay()
|
|||
entries.clear();
|
||||
}
|
||||
|
||||
ZOverlay* ZOverlay::FromBuild(std::string buildPath, std::string cfgFolderPath)
|
||||
static const std::unordered_set<std::string> sRelSections = {
|
||||
".rel.text",
|
||||
".rel.data",
|
||||
".rel.rodata",
|
||||
};
|
||||
static const std::unordered_set<std::string> sSections = {
|
||||
".text", ".data", ".symtab", ".rodata", ".rodata.str1.4", ".rodata.cst4", ".rodata.cst8",
|
||||
};
|
||||
|
||||
ZOverlay* ZOverlay::FromBuild(fs::path buildPath, fs::path cfgFolderPath)
|
||||
{
|
||||
std::string cfgText = File::ReadAllText(cfgFolderPath + "/overlay.cfg");
|
||||
std::string cfgText = File::ReadAllText(cfgFolderPath / "overlay.cfg");
|
||||
std::vector<std::string> cfgLines = StringHelper::Split(cfgText, "\n");
|
||||
|
||||
ZOverlay* ovl = new ZOverlay(StringHelper::Strip(cfgLines[0], "\r"));
|
||||
|
||||
std::vector<std::string> relSections = {".rel.text", ".rel.data", ".rel.rodata"};
|
||||
std::vector<std::string> sections = {".text", ".data", ".rodata"};
|
||||
ovl->cfgLines = cfgLines;
|
||||
|
||||
int32_t sectionOffs[5] = {0};
|
||||
std::vector<RelocationEntry*> textRelocs;
|
||||
|
@ -44,8 +90,7 @@ ZOverlay* ZOverlay::FromBuild(std::string buildPath, std::string cfgFolderPath)
|
|||
std::vector<elfio*> readers;
|
||||
for (size_t i = 1; i < cfgLines.size(); i++)
|
||||
{
|
||||
std::string elfPath =
|
||||
buildPath + "/" + cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o";
|
||||
std::string elfPath = buildPath / (cfgLines[i].substr(0, cfgLines[i].size() - 2) + ".o");
|
||||
elfio* reader = new elfio();
|
||||
|
||||
if (!reader->load(elfPath))
|
||||
|
@ -62,102 +107,119 @@ ZOverlay* ZOverlay::FromBuild(std::string buildPath, std::string cfgFolderPath)
|
|||
readers.push_back(reader);
|
||||
}
|
||||
|
||||
for (auto curReader : readers)
|
||||
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 && std::find(relSections.begin(), relSections.end(),
|
||||
pSec->get_name()) != relSections.end())
|
||||
if (pSec->get_type() != SHT_REL ||
|
||||
sRelSections.find(pSec->get_name()) == sRelSections.end())
|
||||
{
|
||||
SectionType sectionType = GetSectionTypeFromStr(pSec->get_name());
|
||||
continue;
|
||||
}
|
||||
|
||||
if (sectionType == SectionType::ERROR)
|
||||
fprintf(stderr, "WARNING: One of the section types returned ERROR\n");
|
||||
symbol_section_accessor currentSymbols(*curReader,
|
||||
curReader->sections[(Elf_Half)pSec->get_link()]);
|
||||
|
||||
relocation_section_accessor relocs(*curReader, pSec);
|
||||
for (Elf_Xword j = 0; j < relocs.get_entries_num(); j++)
|
||||
SectionType sectionType = GetSectionTypeFromStr(pSec->get_name());
|
||||
|
||||
if (sectionType == SectionType::ERROR)
|
||||
fprintf(stderr, "WARNING: One of the section types returned ERROR\n");
|
||||
|
||||
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;
|
||||
{
|
||||
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)
|
||||
{
|
||||
Elf_Sxword addend = 0;
|
||||
relocs.get_entry(j, offset, symbol, type, addend);
|
||||
printf("Symbol '%s' doesn't exist in current .o file (%s). Searching...\n",
|
||||
curSymName.c_str(), cfgLines[curReaderId + 1].c_str());
|
||||
}
|
||||
|
||||
std::string curSymName;
|
||||
Elf_Half curSymShndx = SHN_UNDEF;
|
||||
for (size_t readerId = 0; readerId < readers.size(); readerId++)
|
||||
{
|
||||
symbol_section_accessor symbols(
|
||||
*curReader, curReader->sections[(Elf_Half)pSec->get_link()]);
|
||||
Elf64_Addr value;
|
||||
Elf_Xword size;
|
||||
unsigned char bind;
|
||||
unsigned char type;
|
||||
unsigned char other;
|
||||
symbols.get_symbol(symbol, curSymName, value, size, bind, type, curSymShndx,
|
||||
other);
|
||||
}
|
||||
auto& reader = readers[readerId];
|
||||
|
||||
// check symbols outside the elf but within the overlay
|
||||
if (curSymShndx == SHN_UNDEF)
|
||||
{
|
||||
for (auto reader : readers)
|
||||
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)
|
||||
{
|
||||
if (curSymShndx != SHN_UNDEF)
|
||||
break;
|
||||
|
||||
if (reader == curReader)
|
||||
continue;
|
||||
|
||||
auto sectionData = reader->sections[(Elf_Half)pSec->get_link()];
|
||||
|
||||
if (sectionData == nullptr)
|
||||
continue;
|
||||
|
||||
symbol_section_accessor symbols(*reader, sectionData);
|
||||
|
||||
for (Elf_Xword symIdx = 0; symIdx < symbols.get_symbols_num(); symIdx++)
|
||||
// Symbol wasn't found, try checking every section
|
||||
Elf_Half sec_num = reader->sections.size();
|
||||
for (int32_t otherSectionIdx = 0; otherSectionIdx < sec_num;
|
||||
otherSectionIdx++)
|
||||
{
|
||||
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 (curSymShndx != SHN_UNDEF)
|
||||
{
|
||||
curSymShndx = shndx;
|
||||
break;
|
||||
}
|
||||
|
||||
auto sectionDataIter = reader->sections[otherSectionIdx];
|
||||
|
||||
curSymShndx = ovl->FindSymbolInSection(curSymName, sectionDataIter,
|
||||
*reader, readerId);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (curSymShndx != SHN_UNDEF)
|
||||
if (curSymShndx != SHN_UNDEF)
|
||||
{
|
||||
RelocationType typeConverted = (RelocationType)type;
|
||||
offset += sectionOffs[static_cast<size_t>(sectionType)];
|
||||
|
||||
RelocationEntry* reloc =
|
||||
new RelocationEntry(sectionType, typeConverted, offset);
|
||||
|
||||
if (Globals::Instance->verbosity >= VerbosityLevel::VERBOSITY_DEBUG)
|
||||
{
|
||||
RelocationType typeConverted = (RelocationType)type;
|
||||
offset += sectionOffs[sectionType];
|
||||
|
||||
RelocationEntry* reloc =
|
||||
new RelocationEntry(sectionType, typeConverted, 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -167,20 +229,18 @@ ZOverlay* ZOverlay::FromBuild(std::string buildPath, std::string cfgFolderPath)
|
|||
{
|
||||
section* pSec = curReader->sections[i];
|
||||
if (pSec->get_type() == SHT_PROGBITS &&
|
||||
std::find(sections.begin(), sections.end(), pSec->get_name()) != sections.end())
|
||||
sSections.find(pSec->get_name()) != sSections.end())
|
||||
{
|
||||
SectionType sectionType = GetSectionTypeFromStr(pSec->get_name());
|
||||
sectionOffs[sectionType] += pSec->get_size();
|
||||
sectionOffs[static_cast<size_t>(sectionType)] += pSec->get_size();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto reloc : textRelocs)
|
||||
ovl->entries.push_back(reloc);
|
||||
for (auto reloc : dataRelocs)
|
||||
ovl->entries.push_back(reloc);
|
||||
for (auto reloc : rodataRelocs)
|
||||
ovl->entries.push_back(reloc);
|
||||
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;
|
||||
|
@ -189,23 +249,27 @@ ZOverlay* ZOverlay::FromBuild(std::string buildPath, std::string cfgFolderPath)
|
|||
return ovl;
|
||||
}
|
||||
|
||||
std::string ZOverlay::GetSourceOutputCode(const std::string& prefix)
|
||||
std::string ZOverlay::GetSourceOutputCode([[maybe_unused]] const std::string& prefix)
|
||||
{
|
||||
std::string output = "";
|
||||
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\n", entries.size());
|
||||
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\n", reloc->CalcRelocationWord());
|
||||
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;
|
||||
|
@ -216,11 +280,13 @@ std::string ZOverlay::GetSourceOutputCode(const std::string& prefix)
|
|||
offset += 4;
|
||||
}
|
||||
|
||||
output += StringHelper::Sprintf(".word 0x%08X\n", offset + 4);
|
||||
output += "\n";
|
||||
output +=
|
||||
StringHelper::Sprintf(".word 0x%08X # %sOverlayInfoOffset\n", offset + 4, name.c_str());
|
||||
return output;
|
||||
}
|
||||
|
||||
SectionType ZOverlay::GetSectionTypeFromStr(std::string sectionName)
|
||||
SectionType ZOverlay::GetSectionTypeFromStr(const std::string& sectionName)
|
||||
{
|
||||
if (sectionName == ".rel.text" || sectionName == ".text")
|
||||
return SectionType::Text;
|
||||
|
@ -234,3 +300,50 @@ SectionType ZOverlay::GetSectionTypeFromStr(std::string sectionName)
|
|||
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue