Loader: Support HI16/16 pairs, not just LO16.

Motorstorm: Arctic Edge US uses these pairs for some VFPU loads.
Without relocating these, strange shadows show underneath vehicles.

It appears as if actual firmware pairs with any non-HI16 relocation.
This commit is contained in:
Unknown W. Brackets 2023-06-18 19:04:59 -07:00
parent a9668bdb60
commit b2b61d58d4

View File

@ -154,26 +154,41 @@ bool ElfReader::LoadRelocations(const Elf32_Rel *rels, int numRelocs) {
u16 hi = 0;
bool found = false;
for (int t = r + 1; t < numRelocs; t++) {
if ((rels[t].r_info & 0xF) == R_MIPS_LO16) {
u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite];
// Should have matching index and segment info, according to llvm, which makes sense.
if ((rels[t].r_info >> 8) != (rels[r].r_info >> 8)) {
WARN_LOG_REPORT(LOADER, "ELF relocation HI16/LO16 with mismatching r_info lo=%08x, hi=%08x", rels[t].r_info, rels[r].r_info);
}
if (log) {
DEBUG_LOG(LOADER, "Corresponding lo found at %08x", corrLoAddr);
}
if (Memory::IsValidAddress(corrLoAddr)) {
s16 lo = (s16)relocOps[t];
cur += lo;
cur += relocateTo;
addrToHiLo(cur, hi, lo);
found = true;
break;
int t_type = rels[t].r_info & 0xF;
if (t_type == R_MIPS_HI16)
continue;
u32 corrLoAddr = rels[t].r_offset + segmentVAddr[readwrite];
// In MotorStorm: Arctic Edge (US), these are sometimes R_MIPS_16 (instead of LO16.)
// It appears the PSP takes any relocation that is not a HI16.
if (t_type != R_MIPS_LO16) {
if (t_type != R_MIPS_16) {
// Let's play it safe for now and skip. We've only seen this type.
ERROR_LOG_REPORT(LOADER, "ELF relocation HI16/%d pair (instead of LO16) at %08x / %08x", t_type, addr, corrLoAddr);
continue;
} else {
ERROR_LOG(LOADER, "Bad corrLoAddr %08x", corrLoAddr);
WARN_LOG_REPORT(LOADER, "ELF relocation HI16/%d(16) pair (instead of LO16) at %08x / %08x", t_type, addr, corrLoAddr);
}
}
// Should have matching index and segment info, according to llvm, which makes sense.
if ((rels[t].r_info >> 8) != (rels[r].r_info >> 8)) {
WARN_LOG_REPORT(LOADER, "ELF relocation HI16/LO16 with mismatching r_info lo=%08x, hi=%08x", rels[t].r_info, rels[r].r_info);
}
if (log) {
DEBUG_LOG(LOADER, "Corresponding lo found at %08x", corrLoAddr);
}
if (Memory::IsValidAddress(corrLoAddr)) {
s16 lo = (s16)relocOps[t];
cur += lo;
cur += relocateTo;
addrToHiLo(cur, hi, lo);
found = true;
break;
} else {
ERROR_LOG(LOADER, "Bad corrLoAddr %08x", corrLoAddr);
}
}
if (!found) {
ERROR_LOG_REPORT(LOADER, "R_MIPS_HI16: could not find R_MIPS_LO16 (r=%d of %d, addr=%08x)", r, numRelocs, addr);