Adding a simple heuristic to find leaf thunk functions.

This commit is contained in:
Ben Vanik 2013-05-26 01:43:44 -07:00
parent 1640acaf8a
commit f94256aaaf
1 changed files with 24 additions and 0 deletions

View File

@ -272,6 +272,7 @@ int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) {
FunctionBlock* block = NULL;
uint32_t furthest_target = fn->start_address;
uint32_t addr = fn->start_address;
bool starts_with_mfspr_lr = false;
while (true) {
i.code = XEGETUINT32BE(p + addr);
i.type = ppc::GetInstrType(i.code);
@ -284,6 +285,16 @@ int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) {
break;
}
// Check if the function starts with a mfspr lr, as that's a good indication
// of whether or not this is a normal function with a prolog/epilog.
// Some valid leaf functions won't have this, but most will.
if (addr == fn->start_address &&
i.type &&
i.type->opcode == 0x7C0002A6 &&
(((i.XFX.spr & 0x1F) << 5) | ((i.XFX.spr >> 5) & 0x1F)) == 8) {
starts_with_mfspr_lr = true;
}
// Create a new basic block, if needed.
if (!block) {
block = new FunctionBlock();
@ -357,6 +368,19 @@ int SymbolDatabase::AnalyzeFunction(FunctionSymbol* fn) {
ends_fn = true;
}
// Heuristic: if there's an unconditional branch in the first block of
// the function it's likely a thunk.
// Ex:
// li r3, 0
// b KeBugCheck
// This check may hit on functions that jump over data code, so only
// trigger this check in leaf functions (no mfspr lr/prolog).
if (!starts_with_mfspr_lr &&
fn->blocks.size() == 1) {
XELOGSDB("simple leaf thunk detected, ending");
ends_fn = true;
}
if (!ends_fn) {
furthest_target = MAX(furthest_target, target);