Scanner now picks up restgprlr calls.

This commit is contained in:
Ben Vanik 2013-12-08 11:26:43 -08:00
parent 1dc356cb4d
commit e2e2a392ee
4 changed files with 34 additions and 12 deletions

View File

@ -12,6 +12,7 @@
#include <alloy/frontend/tracing.h> #include <alloy/frontend/tracing.h>
#include <alloy/frontend/ppc/ppc_frontend.h> #include <alloy/frontend/ppc/ppc_frontend.h>
#include <alloy/frontend/ppc/ppc_instr.h> #include <alloy/frontend/ppc/ppc_instr.h>
#include <alloy/runtime/runtime.h>
using namespace alloy; using namespace alloy;
using namespace alloy::frontend; using namespace alloy::frontend;
@ -27,10 +28,11 @@ PPCScanner::~PPCScanner() {
} }
bool PPCScanner::IsRestGprLr(uint64_t address) { bool PPCScanner::IsRestGprLr(uint64_t address) {
// TODO(benvanik): detect type. FunctionInfo* symbol_info;
/*FunctionSymbol* fn = GetFunction(addr); if (frontend_->runtime()->LookupFunctionInfo(address, &symbol_info)) {
return fn && (fn->flags & FunctionSymbol::kFlagRestGprLr);*/ return false;
return false; }
return symbol_info->behavior() == FunctionInfo::BEHAVIOR_EPILOG_RETURN;
} }
int PPCScanner::FindExtents(FunctionInfo* symbol_info) { 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). // (Indirect branches may still go beyond, but no way of knowing).
if (target >= start_address && if (target >= start_address &&
target < address && furthest_target <= address) { target < address && furthest_target <= address) {
XELOGSDB("function end %.8X (back b)", addr); XELOGSDB("function end %.8X (back b)", address);
ends_fn = true; ends_fn = true;
} }
@ -144,7 +146,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
// address it's definitely a tail call. // address it's definitely a tail call.
if (!ends_fn && if (!ends_fn &&
target < start_address && furthest_target <= address) { 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; ends_fn = true;
} }
@ -155,7 +157,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
if (!ends_fn && if (!ends_fn &&
furthest_target <= address && furthest_target <= address &&
IsRestGprLr(target)) { IsRestGprLr(target)) {
XELOGSDB("function end %.8X (__restgprlr_*)", addr); XELOGSDB("function end %.8X (__restgprlr_*)", address);
ends_fn = true; ends_fn = true;
} }
@ -224,17 +226,17 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
} else if (i.type->opcode == 0x4C000020) { } else if (i.type->opcode == 0x4C000020) {
// bclr/bclrl // bclr/bclrl
if (i.XL.LK) { if (i.XL.LK) {
XELOGSDB("bclrl %.8X", addr); XELOGSDB("bclrl %.8X", address);
} else { } else {
XELOGSDB("bclr %.8X", addr); XELOGSDB("bclr %.8X", address);
} }
ends_block = true; ends_block = true;
} else if (i.type->opcode == 0x4C000420) { } else if (i.type->opcode == 0x4C000420) {
// bcctr/bcctrl // bcctr/bcctrl
if (i.XL.LK) { if (i.XL.LK) {
XELOGSDB("bcctrl %.8X", addr); XELOGSDB("bcctrl %.8X", address);
} else { } else {
XELOGSDB("bcctr %.8X", addr); XELOGSDB("bcctr %.8X", address);
} }
ends_block = true; ends_block = true;
} }

View File

@ -22,7 +22,7 @@ SymbolInfo::~SymbolInfo() {
} }
FunctionInfo::FunctionInfo(Module* module, uint64_t address) : 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) { SymbolInfo(SymbolInfo::TYPE_FUNCTION, module, address) {
} }

View File

@ -52,6 +52,14 @@ protected:
}; };
class FunctionInfo : public SymbolInfo { class FunctionInfo : public SymbolInfo {
public:
enum Behavior {
BEHAVIOR_DEFAULT = 0,
BEHAVIOR_PROLOG,
BEHAVIOR_EPILOG,
BEHAVIOR_EPILOG_RETURN,
};
public: public:
FunctionInfo(Module* module, uint64_t address); FunctionInfo(Module* module, uint64_t address);
virtual ~FunctionInfo(); virtual ~FunctionInfo();
@ -60,11 +68,15 @@ public:
uint64_t end_address() const { return end_address_; } uint64_t end_address() const { return end_address_; }
void set_end_address(uint64_t value) { end_address_ = value; } 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_; } Function* function() const { return function_; }
void set_function(Function* value) { function_ = value; } void set_function(Function* value) { function_ = value; }
private: private:
uint64_t end_address_; uint64_t end_address_;
Behavior behavior_;
Function* function_; Function* function_;
}; };

View File

@ -390,6 +390,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveGprLr; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveGprLr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 4; address += 4;
} }
@ -402,6 +403,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestGprLr; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestGprLr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG_RETURN);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 4; address += 4;
} }
@ -416,6 +418,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveFpr; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveFpr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 4; address += 4;
} }
@ -428,6 +431,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestFpr; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestFpr;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 4; address += 4;
} }
@ -446,6 +450,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 2 * 4; address += 2 * 4;
} }
@ -457,6 +462,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagSaveVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_PROLOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 2 * 4; address += 2 * 4;
} }
@ -468,6 +474,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 2 * 4; address += 2 * 4;
} }
@ -479,6 +486,7 @@ int XexModule::FindSaveRest() {
// TODO(benvanik): set name // TODO(benvanik): set name
// TODO(benvanik): set type fn->type = FunctionSymbol::User; // TODO(benvanik): set type fn->type = FunctionSymbol::User;
// TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx; // TODO(benvanik): set flags fn->flags |= FunctionSymbol::kFlagRestVmx;
symbol_info->set_behavior(FunctionInfo::BEHAVIOR_EPILOG);
symbol_info->set_status(SymbolInfo::STATUS_DECLARED); symbol_info->set_status(SymbolInfo::STATUS_DECLARED);
address += 2 * 4; address += 2 * 4;
} }