diff --git a/src/xenia/cpu/sdb/symbol_database.cc b/src/xenia/cpu/sdb/symbol_database.cc index 04b8217e8..827a53c7a 100644 --- a/src/xenia/cpu/sdb/symbol_database.cc +++ b/src/xenia/cpu/sdb/symbol_database.cc @@ -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);