mirror of
https://github.com/ran-j/PS2Recomp.git
synced 2026-09-29 01:47:44 -04:00
Feature/runtime review codegen fixes (#87)
* feat: small fixes on code gen * feat: added code gen test * feat: rename IOP * fix: fix special case on JR feat: added code generator test * feat: ps2 logs now need special macros * feat: a lot of regressions test feat: use test to fix bugs on runtime fix: fix incorrect instructions on code generator feat: added missing decode on r5900 decoder feat: added scissor on rasterizer * feat: better ghidra plugin analyzer fix: fix real bug on function finding on elf analyzer * feat: some logs on GS feat: added more syscalls stubs feat: added more ps2 stubs * feat: added missing stub
This commit is contained in:
@@ -143,6 +143,69 @@ namespace
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
bool HasAnyExecutableSection(const std::vector<ps2recomp::Section> §ions)
|
||||
{
|
||||
for (const auto §ion : sections)
|
||||
{
|
||||
if (section.isCode)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const ps2recomp::Section *FindFunctionSectionByAddress(const std::vector<ps2recomp::Section> §ions, uint32_t address)
|
||||
{
|
||||
const ps2recomp::Section *codeSection = FindCodeSectionByAddress(sections, address);
|
||||
if (codeSection)
|
||||
{
|
||||
return codeSection;
|
||||
}
|
||||
|
||||
// Some malformed/stripped ELFs may not carry executable section flags.
|
||||
if (!HasAnyExecutableSection(sections))
|
||||
{
|
||||
return FindSectionByAddress(sections, address);
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t ClampFunctionEndToSection(const ps2recomp::Section *section, uint32_t start, uint32_t requestedEnd)
|
||||
{
|
||||
if (!section)
|
||||
{
|
||||
return requestedEnd;
|
||||
}
|
||||
|
||||
const uint64_t sectionEnd64 = static_cast<uint64_t>(section->address) + static_cast<uint64_t>(section->size);
|
||||
const uint32_t sectionEnd = (sectionEnd64 > 0xFFFFFFFFull)
|
||||
? 0xFFFFFFFFu
|
||||
: static_cast<uint32_t>(sectionEnd64);
|
||||
|
||||
uint32_t end = requestedEnd;
|
||||
if (end == 0 || end > sectionEnd)
|
||||
{
|
||||
end = sectionEnd;
|
||||
}
|
||||
|
||||
if (end <= start)
|
||||
{
|
||||
const uint64_t minimumEnd64 = static_cast<uint64_t>(start) + 4ull;
|
||||
if (minimumEnd64 <= sectionEnd64)
|
||||
{
|
||||
end = static_cast<uint32_t>(minimumEnd64);
|
||||
}
|
||||
else
|
||||
{
|
||||
end = sectionEnd;
|
||||
}
|
||||
}
|
||||
|
||||
return end;
|
||||
}
|
||||
|
||||
std::string MakeAutoFunctionName(uint32_t address)
|
||||
{
|
||||
char buffer[32]{};
|
||||
@@ -503,7 +566,22 @@ namespace ps2recomp
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t symbolEnd = symbol.address + symbol.size;
|
||||
const Section *functionSection = FindFunctionSectionByAddress(m_sections, symbol.address);
|
||||
if (!functionSection)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint64_t symbolEnd64 = static_cast<uint64_t>(symbol.address) + static_cast<uint64_t>(symbol.size);
|
||||
uint32_t symbolEnd = (symbolEnd64 > 0xFFFFFFFFull)
|
||||
? 0xFFFFFFFFu
|
||||
: static_cast<uint32_t>(symbolEnd64);
|
||||
symbolEnd = ClampFunctionEndToSection(functionSection, symbol.address, symbolEnd);
|
||||
if (symbolEnd <= symbol.address)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto inserted = authoritativeEndByStart.emplace(symbol.address, symbolEnd);
|
||||
if (!inserted.second && symbolEnd > inserted.first->second)
|
||||
{
|
||||
@@ -519,10 +597,22 @@ namespace ps2recomp
|
||||
continue;
|
||||
}
|
||||
|
||||
auto inserted = authoritativeEndByStart.emplace(extra.start, extra.end);
|
||||
if (!inserted.second && extra.end > inserted.first->second)
|
||||
const Section *functionSection = FindFunctionSectionByAddress(m_sections, extra.start);
|
||||
if (!functionSection)
|
||||
{
|
||||
inserted.first->second = extra.end;
|
||||
continue;
|
||||
}
|
||||
|
||||
const uint32_t clampedEnd = ClampFunctionEndToSection(functionSection, extra.start, extra.end);
|
||||
if (clampedEnd <= extra.start)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
auto inserted = authoritativeEndByStart.emplace(extra.start, clampedEnd);
|
||||
if (!inserted.second && clampedEnd > inserted.first->second)
|
||||
{
|
||||
inserted.first->second = clampedEnd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -566,6 +656,11 @@ namespace ps2recomp
|
||||
return;
|
||||
}
|
||||
|
||||
if (!FindFunctionSectionByAddress(m_sections, newFunction.start))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
const bool insideAuthoritativeRange = isInsideAuthoritativeRange(newFunction.start);
|
||||
const bool hasOwnAuthoritativeRange = authoritativeEndByStart.contains(newFunction.start);
|
||||
const bool hasAutoName = newFunction.name.empty() || IsAutoGeneratedName(newFunction.name);
|
||||
@@ -585,7 +680,10 @@ namespace ps2recomp
|
||||
auto authoritativeIt = authoritativeEndByStart.find(insertedFunction.start);
|
||||
if (authoritativeIt != authoritativeEndByStart.end())
|
||||
{
|
||||
insertedFunction.end = authoritativeIt->second;
|
||||
insertedFunction.end = ClampFunctionEndToSection(
|
||||
FindFunctionSectionByAddress(m_sections, insertedFunction.start),
|
||||
insertedFunction.start,
|
||||
authoritativeIt->second);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -603,7 +701,10 @@ namespace ps2recomp
|
||||
auto authoritativeIt = authoritativeEndByStart.find(existing.start);
|
||||
if (authoritativeIt != authoritativeEndByStart.end())
|
||||
{
|
||||
existing.end = authoritativeIt->second;
|
||||
existing.end = ClampFunctionEndToSection(
|
||||
FindFunctionSectionByAddress(m_sections, existing.start),
|
||||
existing.start,
|
||||
authoritativeIt->second);
|
||||
}
|
||||
else if (newFunction.end > existing.end)
|
||||
{
|
||||
@@ -620,10 +721,24 @@ namespace ps2recomp
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!FindFunctionSectionByAddress(m_sections, symbol.address))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
Function func;
|
||||
func.name = symbol.name;
|
||||
func.start = symbol.address;
|
||||
func.end = (symbol.size > 0) ? (symbol.address + symbol.size) : 0;
|
||||
if (symbol.size > 0)
|
||||
{
|
||||
const uint64_t end64 = static_cast<uint64_t>(symbol.address) + static_cast<uint64_t>(symbol.size);
|
||||
func.end = (end64 > 0xFFFFFFFFull) ? 0xFFFFFFFFu : static_cast<uint32_t>(end64);
|
||||
}
|
||||
else
|
||||
{
|
||||
func.end = 0;
|
||||
}
|
||||
func.isRecompiled = false;
|
||||
func.isStub = false;
|
||||
func.isSkipped = false;
|
||||
@@ -656,7 +771,7 @@ namespace ps2recomp
|
||||
continue;
|
||||
}
|
||||
|
||||
const Section *section = FindSectionByAddress(m_sections, func.start);
|
||||
const Section *section = FindFunctionSectionByAddress(m_sections, func.start);
|
||||
uint32_t sectionEnd = section ? (section->address + section->size) : (func.start + 4);
|
||||
|
||||
uint32_t nextStart = sectionEnd;
|
||||
@@ -846,6 +961,8 @@ namespace ps2recomp
|
||||
}
|
||||
|
||||
int count = 0;
|
||||
int skippedNonExecutable = 0;
|
||||
int skippedInvalidRange = 0;
|
||||
while (std::getline(file, line))
|
||||
{
|
||||
if (line.empty())
|
||||
@@ -867,6 +984,20 @@ namespace ps2recomp
|
||||
uint32_t start = std::stoul(startStr, nullptr, 0);
|
||||
uint32_t end = std::stoul(endStr, nullptr, 0);
|
||||
|
||||
const Section *section = FindFunctionSectionByAddress(m_sections, start);
|
||||
if (!section)
|
||||
{
|
||||
++skippedNonExecutable;
|
||||
continue;
|
||||
}
|
||||
|
||||
end = ClampFunctionEndToSection(section, start, end);
|
||||
if (end <= start)
|
||||
{
|
||||
++skippedInvalidRange;
|
||||
continue;
|
||||
}
|
||||
|
||||
Function func{};
|
||||
func.name = name;
|
||||
func.start = start;
|
||||
@@ -887,6 +1018,16 @@ namespace ps2recomp
|
||||
if (count > 0)
|
||||
{
|
||||
std::cout << "Loaded " << count << " functions from Ghidra map" << std::endl;
|
||||
if (skippedNonExecutable > 0)
|
||||
{
|
||||
std::cout << "Ignored " << skippedNonExecutable
|
||||
<< " Ghidra function(s) outside executable sections." << std::endl;
|
||||
}
|
||||
if (skippedInvalidRange > 0)
|
||||
{
|
||||
std::cout << "Ignored " << skippedInvalidRange
|
||||
<< " Ghidra function(s) with invalid ranges after section clamping." << std::endl;
|
||||
}
|
||||
|
||||
std::sort(m_extraFunctions.begin(), m_extraFunctions.end(),
|
||||
[](const Function &a, const Function &b)
|
||||
@@ -908,6 +1049,13 @@ namespace ps2recomp
|
||||
return true;
|
||||
}
|
||||
|
||||
if (skippedNonExecutable > 0 || skippedInvalidRange > 0)
|
||||
{
|
||||
std::cout << "Loaded 0 functions from Ghidra map after filtering ("
|
||||
<< skippedNonExecutable << " non-executable, "
|
||||
<< skippedInvalidRange << " invalid range)." << std::endl;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user