Adding support for detecting the save/rest fpr and vmx blocks.

This commit is contained in:
Ben Vanik 2013-05-31 01:53:30 -07:00
parent e6195c4086
commit 38efd3837d
3 changed files with 498 additions and 31 deletions

View File

@ -108,6 +108,10 @@ public:
enum Flags { enum Flags {
kFlagSaveGprLr = 1 << 1, kFlagSaveGprLr = 1 << 1,
kFlagRestGprLr = 1 << 2, kFlagRestGprLr = 1 << 2,
kFlagSaveFpr = 1 << 3,
kFlagRestFpr = 1 << 4,
kFlagSaveVmx = 1 << 5,
kFlagRestVmx = 1 << 6,
}; };
FunctionSymbol(); FunctionSymbol();

View File

@ -64,8 +64,8 @@ XexSymbolDatabase::~XexSymbolDatabase() {
int XexSymbolDatabase::Analyze() { int XexSymbolDatabase::Analyze() {
const xe_xex2_header_t* header = xe_xex2_get_header(xex_); const xe_xex2_header_t* header = xe_xex2_get_header(xex_);
// Find __savegprlr_* and __restgprlr_*. // Find __savegprlr_* and __restgprlr_* and the others.
FindGplr(); FindSaveRest();
// Add each import thunk. // Add each import thunk.
for (size_t n = 0; n < header->import_library_count; n++) { for (size_t n = 0; n < header->import_library_count; n++) {
@ -84,14 +84,14 @@ int XexSymbolDatabase::Analyze() {
return SymbolDatabase::Analyze(); return SymbolDatabase::Analyze();
} }
int XexSymbolDatabase::FindGplr() { int XexSymbolDatabase::FindSaveRest() {
// Special stack save/restore functions. // Special stack save/restore functions.
// __savegprlr_14 to __savegprlr_31
// __restgprlr_14 to __restgprlr_31
// http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/ppc/xxx.s.htm // http://research.microsoft.com/en-us/um/redmond/projects/invisible/src/crt/md/ppc/xxx.s.htm
// It'd be nice to stash these away and mark them as such to allow for // It'd be nice to stash these away and mark them as such to allow for
// special codegen. // special codegen.
static const uint32_t code_values[] = { // __savegprlr_14 to __savegprlr_31
// __restgprlr_14 to __restgprlr_31
static const uint32_t gprlr_code_values[] = {
0x68FFC1F9, // __savegprlr_14 0x68FFC1F9, // __savegprlr_14
0x70FFE1F9, // __savegprlr_15 0x70FFE1F9, // __savegprlr_15
0x78FF01FA, // __savegprlr_16 0x78FF01FA, // __savegprlr_16
@ -134,8 +134,395 @@ int XexSymbolDatabase::FindGplr() {
0xA603887D, 0xA603887D,
0x2000804E, 0x2000804E,
}; };
// __savefpr_14 to __savefpr_31
// __restfpr_14 to __restfpr_31
static const uint32_t fpr_code_values[] = {
0x70FFCCD9, // __savefpr_14
0x78FFECD9, // __savefpr_15
0x80FF0CDA, // __savefpr_16
0x88FF2CDA, // __savefpr_17
0x90FF4CDA, // __savefpr_18
0x98FF6CDA, // __savefpr_19
0xA0FF8CDA, // __savefpr_20
0xA8FFACDA, // __savefpr_21
0xB0FFCCDA, // __savefpr_22
0xB8FFECDA, // __savefpr_23
0xC0FF0CDB, // __savefpr_24
0xC8FF2CDB, // __savefpr_25
0xD0FF4CDB, // __savefpr_26
0xD8FF6CDB, // __savefpr_27
0xE0FF8CDB, // __savefpr_28
0xE8FFACDB, // __savefpr_29
0xF0FFCCDB, // __savefpr_30
0xF8FFECDB, // __savefpr_31
0x2000804E,
0x70FFCCC9, // __restfpr_14
0x78FFECC9, // __restfpr_15
0x80FF0CCA, // __restfpr_16
0x88FF2CCA, // __restfpr_17
0x90FF4CCA, // __restfpr_18
0x98FF6CCA, // __restfpr_19
0xA0FF8CCA, // __restfpr_20
0xA8FFACCA, // __restfpr_21
0xB0FFCCCA, // __restfpr_22
0xB8FFECCA, // __restfpr_23
0xC0FF0CCB, // __restfpr_24
0xC8FF2CCB, // __restfpr_25
0xD0FF4CCB, // __restfpr_26
0xD8FF6CCB, // __restfpr_27
0xE0FF8CCB, // __restfpr_28
0xE8FFACCB, // __restfpr_29
0xF0FFCCCB, // __restfpr_30
0xF8FFECCB, // __restfpr_31
0x2000804E,
};
// __savevmx_14 to __savevmx_31
// __savevmx_64 to __savevmx_127
// __restvmx_14 to __restvmx_31
// __restvmx_64 to __restvmx_127
static const uint32_t vmx_code_values[] = {
0xE0FE6039, // __savevmx_14
0xCE61CB7D,
0xF0FE6039,
0xCE61EB7D,
0x00FF6039,
0xCE610B7E,
0x10FF6039,
0xCE612B7E,
0x20FF6039,
0xCE614B7E,
0x30FF6039,
0xCE616B7E,
0x40FF6039,
0xCE618B7E,
0x50FF6039,
0xCE61AB7E,
0x60FF6039,
0xCE61CB7E,
0x70FF6039,
0xCE61EB7E,
0x80FF6039,
0xCE610B7F,
0x90FF6039,
0xCE612B7F,
0xA0FF6039,
0xCE614B7F,
0xB0FF6039,
0xCE616B7F,
0xC0FF6039,
0xCE618B7F,
0xD0FF6039,
0xCE61AB7F,
0xE0FF6039,
0xCE61CB7F,
0xF0FF6039, // __savevmx_31
0xCE61EB7F,
0x2000804E,
0x00FC6039, // __savevmx_64
0xCB610B10,
0x10FC6039,
0xCB612B10,
0x20FC6039,
0xCB614B10,
0x30FC6039,
0xCB616B10,
0x40FC6039,
0xCB618B10,
0x50FC6039,
0xCB61AB10,
0x60FC6039,
0xCB61CB10,
0x70FC6039,
0xCB61EB10,
0x80FC6039,
0xCB610B11,
0x90FC6039,
0xCB612B11,
0xA0FC6039,
0xCB614B11,
0xB0FC6039,
0xCB616B11,
0xC0FC6039,
0xCB618B11,
0xD0FC6039,
0xCB61AB11,
0xE0FC6039,
0xCB61CB11,
0xF0FC6039,
0xCB61EB11,
0x00FD6039,
0xCB610B12,
0x10FD6039,
0xCB612B12,
0x20FD6039,
0xCB614B12,
0x30FD6039,
0xCB616B12,
0x40FD6039,
0xCB618B12,
0x50FD6039,
0xCB61AB12,
0x60FD6039,
0xCB61CB12,
0x70FD6039,
0xCB61EB12,
0x80FD6039,
0xCB610B13,
0x90FD6039,
0xCB612B13,
0xA0FD6039,
0xCB614B13,
0xB0FD6039,
0xCB616B13,
0xC0FD6039,
0xCB618B13,
0xD0FD6039,
0xCB61AB13,
0xE0FD6039,
0xCB61CB13,
0xF0FD6039,
0xCB61EB13,
0x00FE6039,
0xCF610B10,
0x10FE6039,
0xCF612B10,
0x20FE6039,
0xCF614B10,
0x30FE6039,
0xCF616B10,
0x40FE6039,
0xCF618B10,
0x50FE6039,
0xCF61AB10,
0x60FE6039,
0xCF61CB10,
0x70FE6039,
0xCF61EB10,
0x80FE6039,
0xCF610B11,
0x90FE6039,
0xCF612B11,
0xA0FE6039,
0xCF614B11,
0xB0FE6039,
0xCF616B11,
0xC0FE6039,
0xCF618B11,
0xD0FE6039,
0xCF61AB11,
0xE0FE6039,
0xCF61CB11,
0xF0FE6039,
0xCF61EB11,
0x00FF6039,
0xCF610B12,
0x10FF6039,
0xCF612B12,
0x20FF6039,
0xCF614B12,
0x30FF6039,
0xCF616B12,
0x40FF6039,
0xCF618B12,
0x50FF6039,
0xCF61AB12,
0x60FF6039,
0xCF61CB12,
0x70FF6039,
0xCF61EB12,
0x80FF6039,
0xCF610B13,
0x90FF6039,
0xCF612B13,
0xA0FF6039,
0xCF614B13,
0xB0FF6039,
0xCF616B13,
0xC0FF6039,
0xCF618B13,
0xD0FF6039,
0xCF61AB13,
0xE0FF6039,
0xCF61CB13,
0xF0FF6039, // __savevmx_127
0xCF61EB13,
0x2000804E,
0xE0FE6039, // __restvmx_14
0xCE60CB7D,
0xF0FE6039,
0xCE60EB7D,
0x00FF6039,
0xCE600B7E,
0x10FF6039,
0xCE602B7E,
0x20FF6039,
0xCE604B7E,
0x30FF6039,
0xCE606B7E,
0x40FF6039,
0xCE608B7E,
0x50FF6039,
0xCE60AB7E,
0x60FF6039,
0xCE60CB7E,
0x70FF6039,
0xCE60EB7E,
0x80FF6039,
0xCE600B7F,
0x90FF6039,
0xCE602B7F,
0xA0FF6039,
0xCE604B7F,
0xB0FF6039,
0xCE606B7F,
0xC0FF6039,
0xCE608B7F,
0xD0FF6039,
0xCE60AB7F,
0xE0FF6039,
0xCE60CB7F,
0xF0FF6039, // __restvmx_31
0xCE60EB7F,
0x2000804E,
0x00FC6039, // __restvmx_64
0xCB600B10,
0x10FC6039,
0xCB602B10,
0x20FC6039,
0xCB604B10,
0x30FC6039,
0xCB606B10,
0x40FC6039,
0xCB608B10,
0x50FC6039,
0xCB60AB10,
0x60FC6039,
0xCB60CB10,
0x70FC6039,
0xCB60EB10,
0x80FC6039,
0xCB600B11,
0x90FC6039,
0xCB602B11,
0xA0FC6039,
0xCB604B11,
0xB0FC6039,
0xCB606B11,
0xC0FC6039,
0xCB608B11,
0xD0FC6039,
0xCB60AB11,
0xE0FC6039,
0xCB60CB11,
0xF0FC6039,
0xCB60EB11,
0x00FD6039,
0xCB600B12,
0x10FD6039,
0xCB602B12,
0x20FD6039,
0xCB604B12,
0x30FD6039,
0xCB606B12,
0x40FD6039,
0xCB608B12,
0x50FD6039,
0xCB60AB12,
0x60FD6039,
0xCB60CB12,
0x70FD6039,
0xCB60EB12,
0x80FD6039,
0xCB600B13,
0x90FD6039,
0xCB602B13,
0xA0FD6039,
0xCB604B13,
0xB0FD6039,
0xCB606B13,
0xC0FD6039,
0xCB608B13,
0xD0FD6039,
0xCB60AB13,
0xE0FD6039,
0xCB60CB13,
0xF0FD6039,
0xCB60EB13,
0x00FE6039,
0xCF600B10,
0x10FE6039,
0xCF602B10,
0x20FE6039,
0xCF604B10,
0x30FE6039,
0xCF606B10,
0x40FE6039,
0xCF608B10,
0x50FE6039,
0xCF60AB10,
0x60FE6039,
0xCF60CB10,
0x70FE6039,
0xCF60EB10,
0x80FE6039,
0xCF600B11,
0x90FE6039,
0xCF602B11,
0xA0FE6039,
0xCF604B11,
0xB0FE6039,
0xCF606B11,
0xC0FE6039,
0xCF608B11,
0xD0FE6039,
0xCF60AB11,
0xE0FE6039,
0xCF60CB11,
0xF0FE6039,
0xCF60EB11,
0x00FF6039,
0xCF600B12,
0x10FF6039,
0xCF602B12,
0x20FF6039,
0xCF604B12,
0x30FF6039,
0xCF606B12,
0x40FF6039,
0xCF608B12,
0x50FF6039,
0xCF60AB12,
0x60FF6039,
0xCF60CB12,
0x70FF6039,
0xCF60EB12,
0x80FF6039,
0xCF600B13,
0x90FF6039,
0xCF602B13,
0xA0FF6039,
0xCF604B13,
0xB0FF6039,
0xCF606B13,
0xC0FF6039,
0xCF608B13,
0xD0FF6039,
0xCF60AB13,
0xE0FF6039,
0xCF60CB13,
0xF0FF6039, // __restvmx_127
0xCF60EB13,
0x2000804E,
};
uint32_t gplr_start = 0; uint32_t gplr_start = 0;
uint32_t fpr_start = 0;
uint32_t vmx_start = 0;
const xe_xex2_header_t* header = xe_xex2_get_header(xex_); const xe_xex2_header_t* header = xe_xex2_get_header(xex_);
for (size_t n = 0, i = 0; n < header->section_count; n++) { for (size_t n = 0, i = 0; n < header->section_count; n++) {
const xe_xex2_section_t* section = &header->sections[n]; const xe_xex2_section_t* section = &header->sections[n];
@ -144,40 +531,116 @@ int XexSymbolDatabase::FindGplr() {
const size_t end_address = const size_t end_address =
start_address + (section->info.page_count * xe_xex2_section_length); start_address + (section->info.page_count * xe_xex2_section_length);
if (section->info.type == XEX_SECTION_CODE) { if (section->info.type == XEX_SECTION_CODE) {
gplr_start = xe_memory_search_aligned( if (!gplr_start) {
memory_, start_address, end_address, gplr_start = xe_memory_search_aligned(
code_values, XECOUNT(code_values)); memory_, start_address, end_address,
if (gplr_start) { gprlr_code_values, XECOUNT(gprlr_code_values));
}
if (!fpr_start) {
fpr_start = xe_memory_search_aligned(
memory_, start_address, end_address,
fpr_code_values, XECOUNT(fpr_code_values));
}
if (!vmx_start) {
vmx_start = xe_memory_search_aligned(
memory_, start_address, end_address,
vmx_code_values, XECOUNT(vmx_code_values));
}
if (gplr_start && fpr_start && vmx_start) {
break; break;
} }
} }
i += section->info.page_count; i += section->info.page_count;
} }
if (!gplr_start) {
return 0;
}
// Add function stubs. // Add function stubs.
char name[32]; char name[32];
uint32_t address = gplr_start; if (gplr_start) {
for (int n = 14; n <= 31; n++) { uint32_t address = gplr_start;
xesnprintfa(name, XECOUNT(name), "__savegprlr_%d", n); for (int n = 14; n <= 31; n++) {
FunctionSymbol* fn = GetOrInsertFunction(address); xesnprintfa(name, XECOUNT(name), "__savegprlr_%d", n);
fn->end_address = fn->start_address + (31 - n) * 4 + 2 * 4; FunctionSymbol* fn = GetOrInsertFunction(address);
fn->set_name(name); fn->end_address = fn->start_address + (31 - n) * 4 + 2 * 4;
fn->type = FunctionSymbol::User; fn->set_name(name);
fn->flags |= FunctionSymbol::kFlagSaveGprLr; fn->type = FunctionSymbol::User;
address += 4; fn->flags |= FunctionSymbol::kFlagSaveGprLr;
address += 4;
}
address = gplr_start + 20 * 4;
for (int n = 14; n <= 31; n++) {
xesnprintfa(name, XECOUNT(name), "__restgprlr_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->end_address = fn->start_address + (31 - n) * 4 + 3 * 4;
fn->set_name(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagRestGprLr;
address += 4;
}
} }
address = gplr_start + 20 * 4; if (fpr_start) {
for (int n = 14; n <= 31; n++) { uint32_t address = fpr_start;
xesnprintfa(name, XECOUNT(name), "__restgprlr_%d", n); for (int n = 14; n <= 31; n++) {
FunctionSymbol* fn = GetOrInsertFunction(address); xesnprintfa(name, XECOUNT(name), "__savefpr_%d", n);
fn->end_address = fn->start_address + (31 - n) * 4 + 3 * 4; FunctionSymbol* fn = GetOrInsertFunction(address);
fn->set_name(name); fn->end_address = fn->start_address + (31 - n) * 4 + 1 * 4;
fn->type = FunctionSymbol::User; fn->set_name(name);
fn->flags |= FunctionSymbol::kFlagRestGprLr; fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagSaveFpr;
address += 4;
}
address = fpr_start + (18 * 4) + (1 * 4);
for (int n = 14; n <= 31; n++) {
xesnprintfa(name, XECOUNT(name), "__restfpr_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->end_address = fn->start_address + (31 - n) * 4 + 1 * 4;
fn->set_name(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagRestFpr;
address += 4;
}
}
if (vmx_start) {
// vmx is:
// 14-31 save
// 64-127 save
// 14-31 rest
// 64-127 rest
uint32_t address = vmx_start;
for (int n = 14; n <= 31; n++) {
xesnprintfa(name, XECOUNT(name), "__savevmx_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->set_name(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagSaveVmx;
address += 2 * 4;
}
address += 4; address += 4;
for (int n = 64; n <= 127; n++) {
xesnprintfa(name, XECOUNT(name), "__savevmx_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->set_name(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagSaveVmx;
address += 2 * 4;
}
address = vmx_start + (18 * 2 * 4) + (1 * 4) + (64 * 2 * 4) + (1 * 4);
for (int n = 14; n <= 31; n++) {
xesnprintfa(name, XECOUNT(name), "__restvmx_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->set_name(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagRestVmx;
address += 2 * 4;
}
address += 4;
for (int n = 64; n <= 127; n++) {
xesnprintfa(name, XECOUNT(name), "__restvmx_%d", n);
FunctionSymbol* fn = GetOrInsertFunction(address);
fn->set_name(name);
fn->type = FunctionSymbol::User;
fn->flags |= FunctionSymbol::kFlagSaveVmx;
address += 2 * 4;
}
} }
return 0; return 0;

View File

@ -30,7 +30,7 @@ public:
virtual int Analyze(); virtual int Analyze();
private: private:
int FindGplr(); int FindSaveRest();
int AddImports(const xe_xex2_import_library_t *library); int AddImports(const xe_xex2_import_library_t *library);
int AddMethodHints(); int AddMethodHints();