From e2e2a392ee2c6da7ec8af57c286ba07b013c247e Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 8 Dec 2013 11:26:43 -0800 Subject: [PATCH] Scanner now picks up restgprlr calls. --- src/alloy/frontend/ppc/ppc_scanner.cc | 24 +++++++++++++----------- src/alloy/runtime/symbol_info.cc | 2 +- src/alloy/runtime/symbol_info.h | 12 ++++++++++++ src/xenia/cpu/xex_module.cc | 8 ++++++++ 4 files changed, 34 insertions(+), 12 deletions(-) diff --git a/src/alloy/frontend/ppc/ppc_scanner.cc b/src/alloy/frontend/ppc/ppc_scanner.cc index 0d2af4c3a..22be03733 100644 --- a/src/alloy/frontend/ppc/ppc_scanner.cc +++ b/src/alloy/frontend/ppc/ppc_scanner.cc @@ -12,6 +12,7 @@ #include #include #include +#include using namespace alloy; using namespace alloy::frontend; @@ -27,10 +28,11 @@ PPCScanner::~PPCScanner() { } bool PPCScanner::IsRestGprLr(uint64_t address) { - // TODO(benvanik): detect type. - /*FunctionSymbol* fn = GetFunction(addr); - return fn && (fn->flags & FunctionSymbol::kFlagRestGprLr);*/ - return false; + FunctionInfo* symbol_info; + if (frontend_->runtime()->LookupFunctionInfo(address, &symbol_info)) { + return false; + } + return symbol_info->behavior() == FunctionInfo::BEHAVIOR_EPILOG_RETURN; } int PPCScanner::FindExtents(FunctionInfo* symbol_info) { @@ -136,7 +138,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) { // (Indirect branches may still go beyond, but no way of knowing). if (target >= start_address && target < address && furthest_target <= address) { - XELOGSDB("function end %.8X (back b)", addr); + XELOGSDB("function end %.8X (back b)", address); ends_fn = true; } @@ -144,7 +146,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) { // address it's definitely a tail call. if (!ends_fn && target < start_address && furthest_target <= address) { - XELOGSDB("function end %.8X (back b before addr)", addr); + XELOGSDB("function end %.8X (back b before addr)", address); ends_fn = true; } @@ -155,7 +157,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) { if (!ends_fn && furthest_target <= address && IsRestGprLr(target)) { - XELOGSDB("function end %.8X (__restgprlr_*)", addr); + XELOGSDB("function end %.8X (__restgprlr_*)", address); ends_fn = true; } @@ -224,17 +226,17 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) { } else if (i.type->opcode == 0x4C000020) { // bclr/bclrl if (i.XL.LK) { - XELOGSDB("bclrl %.8X", addr); + XELOGSDB("bclrl %.8X", address); } else { - XELOGSDB("bclr %.8X", addr); + XELOGSDB("bclr %.8X", address); } ends_block = true; } else if (i.type->opcode == 0x4C000420) { // bcctr/bcctrl if (i.XL.LK) { - XELOGSDB("bcctrl %.8X", addr); + XELOGSDB("bcctrl %.8X", address); } else { - XELOGSDB("bcctr %.8X", addr); + XELOGSDB("bcctr %.8X", address); } ends_block = true; } diff --git a/src/alloy/runtime/symbol_info.cc b/src/alloy/runtime/symbol_info.cc index 4475d5bcd..407dc69a0 100644 --- a/src/alloy/runtime/symbol_info.cc +++ b/src/alloy/runtime/symbol_info.cc @@ -22,7 +22,7 @@ SymbolInfo::~SymbolInfo() { } FunctionInfo::FunctionInfo(Module* module, uint64_t address) : - end_address_(0), function_(0), + end_address_(0), behavior_(BEHAVIOR_DEFAULT), function_(0), SymbolInfo(SymbolInfo::TYPE_FUNCTION, module, address) { } diff --git a/src/alloy/runtime/symbol_info.h b/src/alloy/runtime/symbol_info.h index b0a5ffbda..a108adc7e 100644 --- a/src/alloy/runtime/symbol_info.h +++ b/src/alloy/runtime/symbol_info.h @@ -52,6 +52,14 @@ protected: }; class FunctionInfo : public SymbolInfo { +public: + enum Behavior { + BEHAVIOR_DEFAULT = 0, + BEHAVIOR_PROLOG, + BEHAVIOR_EPILOG, + BEHAVIOR_EPILOG_RETURN, + }; + public: FunctionInfo(Module* module, uint64_t address); virtual ~FunctionInfo(); @@ -60,11 +68,15 @@ public: uint64_t end_address() const { return end_address_; } void set_end_address(uint64_t value) { end_address_ = value; } + Behavior behavior() const { return behavior_; } + void set_behavior(Behavior value) { behavior_ = value; } + Function* function() const { return function_; } void set_function(Function* value) { function_ = value; } private: uint64_t end_address_; + Behavior behavior_; Function* function_; }; diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 716c78179..f0e74f1a5 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -390,6 +390,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveGprLr; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 4; } @@ -402,6 +403,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestGprLr; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG_RETURN); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 4; } @@ -416,6 +418,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveFpr; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 4; } @@ -428,6 +431,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestFpr; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 4; } @@ -446,6 +450,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 2 * 4; } @@ -457,6 +462,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 2 * 4; } @@ -468,6 +474,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 2 * 4; } @@ -479,6 +486,7 @@ int XexModule::FindSaveRest() { // TODO(benvanik): set name // TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx; + symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG); symbol_info->set_status(SymbolInfo::STATUS_DECLARED); address += 2 * 4; }