Basic function analysis.

Finds basic blocks and estimates proper function bounds.
Seems legit for compiled code.
This commit is contained in:
Ben Vanik
2013-01-20 16:46:08 -08:00
parent d4b0bf73c1
commit 852536ae0a
7 changed files with 400 additions and 25 deletions

View File

@@ -23,6 +23,7 @@
#define XE_OPTION_LOG_INFO 1
#define XE_OPTION_LOG_DEBUG 1
#define XE_OPTION_LOG_CPU 1
#define XE_OPTION_LOG_SDB 0
#define XE_OPTION_LOG_GPU 1
#define XE_OPTION_LOG_KERNEL 1

View File

@@ -56,6 +56,14 @@ typedef enum {
class InstrType;
static inline int32_t XEEXTS16(uint32_t v) {
return (int32_t)((int16_t)v);
}
static inline int32_t XEEXTS26(uint32_t v) {
return v & 0x02000000 ? (int32_t)v | 0xFC000000 : (int32_t)(v);
}
typedef struct {
InstrType* type;
uint32_t address;
@@ -97,6 +105,14 @@ typedef struct {
} DS;
// kXEPPCInstrFormatX
// kXEPPCInstrFormatXL
struct {
uint32_t LK : 1;
uint32_t : 10;
uint32_t BB : 5;
uint32_t BI : 5;
uint32_t BO : 5;
uint32_t OPCD : 6;
} XL;
struct {
uint32_t : 1;
uint32_t : 10;
@@ -114,7 +130,7 @@ typedef struct {
// kXEPPCInstrFormatVA
// kXEPPCInstrFormatVX
// kXEPPCInstrFormatVXR
} data;
};
} InstrData;
class Instr {

View File

@@ -45,8 +45,9 @@ public:
class Symbol {
public:
enum SymbolType {
Function = 0,
Variable = 1,
Function = 0,
Variable = 1,
ExceptionEntry = 2,
};
virtual ~Symbol() {}
@@ -57,6 +58,18 @@ protected:
Symbol(SymbolType type) : symbol_type(type) {}
};
class ExceptionEntrySymbol;
class FunctionBlock {
public:
uint32_t start_address;
uint32_t end_address;
vector<FunctionBlock*> incoming_blocks;
FunctionBlock* outgoing_block;
uint32_t outgoing_address;
};
class FunctionSymbol : public Symbol {
public:
enum FunctionType {
@@ -64,6 +77,10 @@ public:
Kernel = 1,
User = 2,
};
enum Flags {
kFlagSaveGprLr = 1 << 1,
kFlagRestGprLr = 1 << 2,
};
FunctionSymbol() : Symbol(Function) {}
virtual ~FunctionSymbol() {}
@@ -74,9 +91,13 @@ public:
FunctionType type;
uint32_t flags;
ExceptionEntrySymbol* ee;
vector<FunctionCall*> incoming_calls;
vector<FunctionCall*> outgoing_calls;
vector<VariableAccess*> variable_accesses;
map<uint32_t, FunctionBlock*> blocks;
};
class VariableSymbol : public Symbol {
@@ -88,6 +109,15 @@ public:
char *name;
};
class ExceptionEntrySymbol : public Symbol {
public:
ExceptionEntrySymbol() : Symbol(ExceptionEntry) {}
virtual ~ExceptionEntrySymbol() {}
uint32_t address;
FunctionSymbol* function;
};
class SymbolDatabase {
public:
@@ -96,6 +126,7 @@ public:
int Analyze();
ExceptionEntrySymbol* GetOrInsertExceptionEntry(uint32_t address);
FunctionSymbol* GetOrInsertFunction(uint32_t address);
VariableSymbol* GetOrInsertVariable(uint32_t address);
FunctionSymbol* GetFunction(uint32_t address);
@@ -105,6 +136,7 @@ public:
int GetAllFunctions(vector<FunctionSymbol*>& functions);
void Dump();
void DumpFunctionBlocks(FunctionSymbol* fn);
private:
typedef std::map<uint32_t, Symbol*> SymbolMap;
@@ -114,9 +146,12 @@ private:
int AddImports(const xe_xex2_import_library_t *library);
int AddMethodHints();
int AnalyzeFunction(FunctionSymbol* fn);
int FillHoles();
bool FillHoles();
int FlushQueue();
bool IsValueInTextRange(uint32_t value);
bool IsRestGprLr(uint32_t addr);
xe_memory_ref memory_;
kernel::UserModule* module_;
size_t function_count_;

View File

@@ -57,6 +57,11 @@ void xe_log_line(const xechar_t* file_path, const uint32_t line_number,
#else
#define XELOGCPU(fmt, ...) XE_EMPTY_MACRO
#endif
#if XE_OPTION(LOG_SDB)
#define XELOGSDB(fmt, ...) XELOGCORE('S', fmt, ##__VA_ARGS__)
#else
#define XELOGSDB(fmt, ...) XE_EMPTY_MACRO
#endif
#if XE_OPTION(LOG_GPU)
#define XELOGGPU(fmt, ...) XELOGCORE('G', fmt, ##__VA_ARGS__)
#else