Closed
Description
According to the MIPS System V ABI (https://refspecs.linuxfoundation.org/elf/mipsabi.pdf, pages 4-17 and 4-18), HI16 and LO16 relocations must be paired to determine the full addend for a given relocation of either type. This is important to show the correct addend on a HI16 reloc, and is also needed to show the correct addend on the LO16 when the HI16's addend is nonzero. It's also necessary for correctly identifying symbols for compilers that emit section-relative relocations instead of references to symbols. Here's an excerpt of a relocation pairing algorithm, where relocations
is a list of relocations in the exact original order they show up in the elf's reloc section:
bool prev_hi = false;
int32_t hi_immediate = 0;
for (size_t i = 0; i < relocations.size(); i++) {
Relocation& reloc = relocations[i];
// Calculate addends for LO16 relocs.
if (reloc.type == R_MIPS_LO16) {
int32_t cur_immediate = (int16_t)(reloc.word & 0xFFFF);
int32_t full_addend = hi_immediate + cur_immediate;
if (prev_hi) {
// Paired LO16 relocs (use the paired HI16's immediate and update the HI16's addend)
reloc.addend = full_addend;
relocations[i - 1].addend = full_addend;
} else {
// Orphaned LO16 relocs (use the most recent HI16's immediate)
reloc.addend = full_addend;
}
} else {
if (prev_hi) {
// Invalid elf, HI16 followed by a relocation that isn't a LO16
}
}
// Track HI16 relocs.
if (reloc.type == R_MIPS_HI16) {
prev_hi = true;
hi_immediate = (reloc.word & 0xFFFF) << 16;
} else {
prev_hi = false;
}
}
Metadata
Metadata
Assignees
Labels
No labels