fxos: fix basic block duplication bug

This commit is contained in:
Lephenixnoir 2024-01-15 18:55:55 +01:00
parent 51ee6fd6ff
commit 593d486185
Signed by: Lephenixnoir
GPG Key ID: 1BBA026E13FC0495
1 changed files with 16 additions and 3 deletions

View File

@ -172,7 +172,8 @@ struct Superblock
};
// TODO: Unclear what the exit status of the superblock is in case of error
static Superblock exploreSuperblock(Function &function, u32 entry, bool *error)
static Superblock exploreSuperblock(Function &function,
std::vector<Superblock> const &blocks, u32 entry, bool *error)
{
Superblock sb;
sb.addresses.reserve(32);
@ -182,6 +183,7 @@ static Superblock exploreSuperblock(Function &function, u32 entry, bool *error)
VirtualSpace &vspace = function.parentBinary().vspace();
bool inDelaySlot = false;
bool terminatorFound = false;
bool ranIntoAnotherBlock = false;
u32 pc = entry;
/* Determine how much space the vspace covers at this address to know if we
@ -195,7 +197,11 @@ static Superblock exploreSuperblock(Function &function, u32 entry, bool *error)
return sb;
}
while(!terminatorFound || inDelaySlot) {
/* Break after either finding a terminator or finding an instruction
already explored as part of another superblock, unless we are in a delay
slot, because (1) delay slots go with terminators, (2) if another block
starts at the delay slot there will be trouble, so duplicate it. */
while((!terminatorFound && !ranIntoAnotherBlock) || inDelaySlot) {
sb.addresses.push_back(pc);
/* Read the next instruction from memory */
@ -238,6 +244,13 @@ static Superblock exploreSuperblock(Function &function, u32 entry, bool *error)
terminatorFound = terminatorFound || opcode.isBlockTerminator();
inDelaySlot = !inDelaySlot && opcode.hasDelaySlot();
pc += 2;
for(auto const &other: blocks) {
if(other.addresses[0] == pc) {
ranIntoAnotherBlock = true;
break;
}
}
}
if(*error)
@ -289,7 +302,7 @@ bool Function::exploreFunctionAt(u32 functionAddress)
continue;
bool error = false;
Superblock sb = exploreSuperblock(*this, entry, &error);
Superblock sb = exploreSuperblock(*this, blocks, entry, &error);
if(error)
return false;