diff --git a/ps2xRecomp/src/lib/elf_parser.cpp b/ps2xRecomp/src/lib/elf_parser.cpp index 91e43ee32..865dd6aad 100644 --- a/ps2xRecomp/src/lib/elf_parser.cpp +++ b/ps2xRecomp/src/lib/elf_parser.cpp @@ -986,6 +986,7 @@ namespace ps2recomp int skippedNonExecutable = 0; int skippedInvalidRange = 0; std::unordered_set mapStarts; + std::vector mapFunctions; while (std::getline(file, line)) { if (line.empty()) @@ -1029,7 +1030,7 @@ namespace ps2recomp func.isStub = false; func.isSkipped = false; - m_extraFunctions.push_back(std::move(func)); + mapFunctions.push_back(std::move(func)); mapStarts.insert(start); count++; } @@ -1062,14 +1063,27 @@ namespace ps2recomp } } + // An explicit function map is authoritative over the internal JAL-target + // scan. Those carvings end at the next JAL target or, for the last one in + // a region, at the end of the code section - which on single-PROGBITS + // executables runs straight through interleaved rodata. Because both the + // carvings ("sub_") and typical map names ("FUN_") count as + // auto-generated, a carving sharing a start with a map row used to + // survive this purge and then win the "larger end" tie-break below, + // replacing precise bounds with runaway ones. Drop every auto-named + // carving instead, then append the map rows. m_extraFunctions.erase( std::remove_if(m_extraFunctions.begin(), m_extraFunctions.end(), [&](const Function &func) { - return IsAutoGeneratedName(func.name) && !mapStarts.contains(func.start); + return IsAutoGeneratedName(func.name); }), m_extraFunctions.end()); + m_extraFunctions.insert(m_extraFunctions.end(), + std::make_move_iterator(mapFunctions.begin()), + std::make_move_iterator(mapFunctions.end())); + std::sort(m_extraFunctions.begin(), m_extraFunctions.end(), [](const Function &a, const Function &b) {