fix: reslice entry functions without container (#70)

This commit is contained in:
Antonio Guastella
2026-02-20 14:07:31 +01:00
committed by GitHub
parent ea8283d034
commit d7701f9ea7
3 changed files with 324 additions and 0 deletions
+142
View File
@@ -120,6 +120,148 @@ void register_ps2_recompiler_tests()
}
});
tc.Run("entry reslice trims earlier entries after late discovery", [](TestCase &t) {
std::vector<Function> functions = {
makeFunction("container", 0x1000u, 0x1018u),
makeFunction("entry_1008", 0x1008u, 0x1018u),
makeFunction("entry_100c", 0x100Cu, 0x1018u)
};
std::unordered_map<uint32_t, std::vector<Instruction>> decodedFunctions;
decodedFunctions[0x1000u] = {
makeNopLike(0x1000u),
makeNopLike(0x1004u),
makeNopLike(0x1008u),
makeNopLike(0x100Cu),
makeNopLike(0x1010u),
makeNopLike(0x1014u)
};
decodedFunctions[0x1008u] = {
makeNopLike(0x1008u),
makeNopLike(0x100Cu),
makeNopLike(0x1010u),
makeNopLike(0x1014u)
};
decodedFunctions[0x100Cu] = {
makeNopLike(0x100Cu),
makeNopLike(0x1010u),
makeNopLike(0x1014u)
};
size_t resliced = PS2Recompiler::ResliceEntryFunctions(functions, decodedFunctions);
t.Equals(resliced, static_cast<size_t>(1),
"expected only the earlier entry to be resliced");
auto findByStart = [&](uint32_t start) -> const Function* {
auto it = std::find_if(functions.begin(), functions.end(),
[&](const Function &fn) { return fn.start == start; });
if (it == functions.end())
{
return nullptr;
}
return &(*it);
};
const Function *entry1008 = findByStart(0x1008u);
const Function *entry100C = findByStart(0x100Cu);
t.IsNotNull(entry1008, "entry at 0x1008 should exist");
t.IsNotNull(entry100C, "entry at 0x100C should exist");
if (entry1008)
{
t.Equals(entry1008->end, 0x100Cu,
"entry 0x1008 should be trimmed to next entry start");
}
if (entry100C)
{
t.Equals(entry100C->end, 0x1018u,
"entry 0x100C should still end at containing end");
}
auto decoded1008It = decodedFunctions.find(0x1008u);
auto decoded100CIt = decodedFunctions.find(0x100Cu);
t.IsTrue(decoded1008It != decodedFunctions.end(), "decoded slice for 0x1008 should exist");
t.IsTrue(decoded100CIt != decodedFunctions.end(), "decoded slice for 0x100C should exist");
if (decoded1008It != decodedFunctions.end())
{
t.Equals(decoded1008It->second.size(), static_cast<size_t>(1),
"entry 0x1008 slice should stop before 0x100C");
if (!decoded1008It->second.empty())
{
t.Equals(decoded1008It->second.front().address, 0x1008u,
"entry 0x1008 slice should begin at 0x1008");
}
}
if (decoded100CIt != decodedFunctions.end())
{
t.Equals(decoded100CIt->second.size(), static_cast<size_t>(3),
"entry 0x100C slice should keep remaining instructions");
}
});
tc.Run("entry reslice handles entries without containing function", [](TestCase &t) {
std::vector<Function> functions = {
makeFunction("entry_1008", 0x1008u, 0x1018u),
makeFunction("entry_100c", 0x100Cu, 0x1018u)
};
std::unordered_map<uint32_t, std::vector<Instruction>> decodedFunctions;
decodedFunctions[0x1008u] = {
makeNopLike(0x1008u),
makeNopLike(0x100Cu),
makeNopLike(0x1010u),
makeNopLike(0x1014u)
};
decodedFunctions[0x100Cu] = {
makeNopLike(0x100Cu),
makeNopLike(0x1010u),
makeNopLike(0x1014u)
};
size_t resliced = PS2Recompiler::ResliceEntryFunctions(functions, decodedFunctions);
t.Equals(resliced, static_cast<size_t>(1),
"expected only the earlier entry to be resliced");
auto findByStart = [&](uint32_t start) -> const Function* {
auto it = std::find_if(functions.begin(), functions.end(),
[&](const Function &fn) { return fn.start == start; });
if (it == functions.end())
{
return nullptr;
}
return &(*it);
};
const Function *entry1008 = findByStart(0x1008u);
const Function *entry100C = findByStart(0x100Cu);
t.IsNotNull(entry1008, "entry at 0x1008 should exist");
t.IsNotNull(entry100C, "entry at 0x100C should exist");
if (entry1008)
{
t.Equals(entry1008->end, 0x100Cu,
"entry 0x1008 should be trimmed to next entry start");
}
if (entry100C)
{
t.Equals(entry100C->end, 0x1018u,
"entry 0x100C should keep original end");
}
auto decoded1008It = decodedFunctions.find(0x1008u);
auto decoded100CIt = decodedFunctions.find(0x100Cu);
t.IsTrue(decoded1008It != decodedFunctions.end(), "decoded slice for 0x1008 should exist");
t.IsTrue(decoded100CIt != decodedFunctions.end(), "decoded slice for 0x100C should exist");
if (decoded1008It != decodedFunctions.end())
{
t.Equals(decoded1008It->second.size(), static_cast<size_t>(1),
"entry 0x1008 slice should stop before 0x100C");
}
if (decoded100CIt != decodedFunctions.end())
{
t.Equals(decoded100CIt->second.size(), static_cast<size_t>(3),
"entry 0x100C slice should keep remaining instructions");
}
});
tc.Run("non-executable section targets are ignored", [](TestCase &t) {
std::vector<Section> sections = {
{".text", 0x1000u, 0x2000u, 0u, true, false, false, true, nullptr},