XexGetProcedureAddress by name implemented.
This commit is contained in:
parent
78921c1a7e
commit
49c8efdc6d
|
@ -34,5 +34,10 @@ void* XKernelModule::GetProcAddressByOrdinal(uint16_t ordinal) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* XKernelModule::GetProcAddressByName(const char* name) {
|
||||||
|
XELOGE("GetProcAddressByName not implemented");
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -24,6 +24,7 @@ class XKernelModule : public XModule {
|
||||||
virtual ~XKernelModule();
|
virtual ~XKernelModule();
|
||||||
|
|
||||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
||||||
|
virtual void* GetProcAddressByName(const char* name);
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
Emulator* emulator_;
|
Emulator* emulator_;
|
||||||
|
|
|
@ -27,6 +27,7 @@ class XModule : public XObject {
|
||||||
const std::string& name() const { return name_; }
|
const std::string& name() const { return name_; }
|
||||||
|
|
||||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0;
|
virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0;
|
||||||
|
virtual void* GetProcAddressByName(const char *name) = 0;
|
||||||
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
|
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
|
||||||
uint32_t* out_section_size);
|
uint32_t* out_section_size);
|
||||||
|
|
||||||
|
|
|
@ -148,6 +148,17 @@ void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void* XUserModule::GetProcAddressByName(const char* name) {
|
||||||
|
PEExport export;
|
||||||
|
int ret = xe_xex2_lookup_export(xex_, name, export);
|
||||||
|
|
||||||
|
// Failure.
|
||||||
|
if (ret)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return (void *)export.addr;
|
||||||
|
}
|
||||||
|
|
||||||
X_STATUS XUserModule::GetSection(const char* name, uint32_t* out_section_data,
|
X_STATUS XUserModule::GetSection(const char* name, uint32_t* out_section_data,
|
||||||
uint32_t* out_section_size) {
|
uint32_t* out_section_size) {
|
||||||
auto header = xe_xex2_get_header(xex_);
|
auto header = xe_xex2_get_header(xex_);
|
||||||
|
|
|
@ -33,6 +33,7 @@ class XUserModule : public XModule {
|
||||||
X_STATUS LoadFromMemory(const void* addr, const size_t length);
|
X_STATUS LoadFromMemory(const void* addr, const size_t length);
|
||||||
|
|
||||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
||||||
|
virtual void* GetProcAddressByName(const char* name);
|
||||||
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
|
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
|
||||||
uint32_t* out_section_size);
|
uint32_t* out_section_size);
|
||||||
|
|
||||||
|
|
|
@ -49,6 +49,8 @@ typedef struct xe_xex2 {
|
||||||
size_t count;
|
size_t count;
|
||||||
xe_xex2_import_info_t *infos;
|
xe_xex2_import_info_t *infos;
|
||||||
} library_imports[16];
|
} library_imports[16];
|
||||||
|
|
||||||
|
xe_xex2_export_table *export_table;
|
||||||
} xe_xex2_t;
|
} xe_xex2_t;
|
||||||
|
|
||||||
int xe_xex2_read_header(const uint8_t *addr, const size_t length,
|
int xe_xex2_read_header(const uint8_t *addr, const size_t length,
|
||||||
|
@ -237,6 +239,11 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length,
|
||||||
case XEX_HEADER_DEFAULT_HEAP_SIZE:
|
case XEX_HEADER_DEFAULT_HEAP_SIZE:
|
||||||
header->exe_heap_size = opt_header->value;
|
header->exe_heap_size = opt_header->value;
|
||||||
break;
|
break;
|
||||||
|
case XEX_HEADER_EXPORTS_BY_NAME: {
|
||||||
|
// IMAGE_DATA_DIRECTORY (w/ offset from PE file base)
|
||||||
|
header->export_table_offset = xe::load_and_swap<uint32_t>(pp);
|
||||||
|
// size = xe::load_and_swap<uint32_t>(pp + 0x04);
|
||||||
|
} break;
|
||||||
case XEX_HEADER_IMPORT_LIBRARIES: {
|
case XEX_HEADER_IMPORT_LIBRARIES: {
|
||||||
const size_t max_count = xe::countof(header->import_libraries);
|
const size_t max_count = xe::countof(header->import_libraries);
|
||||||
size_t count = xe::load_and_swap<uint32_t>(pp + 0x08);
|
size_t count = xe::load_and_swap<uint32_t>(pp + 0x08);
|
||||||
|
@ -869,6 +876,20 @@ int xe_xex2_load_pe(xe_xex2_ref xex) {
|
||||||
xex->sections->push_back(section);
|
xex->sections->push_back(section);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (header->export_table_offset) {
|
||||||
|
// This table is located inside of the PE (for some reason)
|
||||||
|
xe_xex2_export_table *table = (xe_xex2_export_table *)xex->memory->TranslateVirtual(xex->header.loader_info.export_table);
|
||||||
|
xex->export_table = table;
|
||||||
|
// cmp magic...
|
||||||
|
|
||||||
|
table->base = xe::load_and_swap<uint32_t>(&table->base);
|
||||||
|
table->imagebaseaddr = xe::load_and_swap<uint32_t>(&table->imagebaseaddr);
|
||||||
|
table->count = xe::load_and_swap<uint32_t>(&table->count);
|
||||||
|
for (int i = 0; i < table->count; i++) {
|
||||||
|
table->ordOffset[i] = xe::load_and_swap<uint32_t>(&table->ordOffset[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// DumpTLSDirectory(pImageBase, pNTHeader, (PIMAGE_TLS_DIRECTORY32)0);
|
// DumpTLSDirectory(pImageBase, pNTHeader, (PIMAGE_TLS_DIRECTORY32)0);
|
||||||
// DumpExportsSection(pImageBase, pNTHeader);
|
// DumpExportsSection(pImageBase, pNTHeader);
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -982,3 +1003,41 @@ int xe_xex2_get_import_infos(xe_xex2_ref xex,
|
||||||
*out_import_infos = xex->library_imports[library_index].infos;
|
*out_import_infos = xex->library_imports[library_index].infos;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int xe_xex2_lookup_export(xe_xex2_ref xex, const char *name,
|
||||||
|
PEExport &peexport) {
|
||||||
|
auto header = xe_xex2_get_header(xex);
|
||||||
|
|
||||||
|
// no exports :(
|
||||||
|
if (!header->export_table_offset) {
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint64_t loadaddr = (uint64_t)xex->memory->TranslateVirtual(header->loader_info.load_address);
|
||||||
|
IMAGE_EXPORT_DIRECTORY *e = (PIMAGE_EXPORT_DIRECTORY)(loadaddr + header->export_table_offset);
|
||||||
|
|
||||||
|
// e->AddressOfX RVAs are relative to the IMAGE_EXPORT_DIRECTORY!
|
||||||
|
uint32_t* function_table = (uint32_t*)((uint64_t)e + e->AddressOfFunctions); // Functions relative to base
|
||||||
|
uint32_t* name_table = (uint32_t*)((uint64_t)e + e->AddressOfNames); // Names relative to directory
|
||||||
|
uint16_t* ordinal_table = (uint16_t*)((uint64_t)e + e->AddressOfNameOrdinals); // Table of ordinals
|
||||||
|
|
||||||
|
const char* mod_name = (const char*)((uint64_t)e + e->Name);
|
||||||
|
|
||||||
|
for (int i = 0; i < e->NumberOfNames; i++) {
|
||||||
|
const char *fn_name = (const char *)((uint64_t)e + name_table[i]);
|
||||||
|
uint16_t ordinal = ordinal_table[i];
|
||||||
|
uint64_t addr = (uint64_t)(loadaddr + function_table[ordinal]);
|
||||||
|
|
||||||
|
if (!strcmp(name, fn_name)) {
|
||||||
|
// We have a match!
|
||||||
|
peexport.name = fn_name;
|
||||||
|
peexport.addr = addr;
|
||||||
|
peexport.ordinal = ordinal;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// No match
|
||||||
|
return 1;
|
||||||
|
}
|
|
@ -43,6 +43,13 @@ class PESection {
|
||||||
uint32_t flags; // kXEPESection*
|
uint32_t flags; // kXEPESection*
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct PEExport {
|
||||||
|
const char *name;
|
||||||
|
uint32_t ordinal;
|
||||||
|
|
||||||
|
uint64_t addr; // Function address
|
||||||
|
};
|
||||||
|
|
||||||
xe_xex2_ref xe_xex2_load(xe::Memory* memory, const void* addr,
|
xe_xex2_ref xe_xex2_load(xe::Memory* memory, const void* addr,
|
||||||
const size_t length, xe_xex2_options_t options);
|
const size_t length, xe_xex2_options_t options);
|
||||||
void xe_xex2_dealloc(xe_xex2_ref xex);
|
void xe_xex2_dealloc(xe_xex2_ref xex);
|
||||||
|
@ -55,4 +62,7 @@ int xe_xex2_get_import_infos(xe_xex2_ref xex,
|
||||||
xe_xex2_import_info_t** out_import_infos,
|
xe_xex2_import_info_t** out_import_infos,
|
||||||
size_t* out_import_info_count);
|
size_t* out_import_info_count);
|
||||||
|
|
||||||
|
int xe_xex2_lookup_export(xe_xex2_ref xex, const char *name,
|
||||||
|
PEExport &peexport);
|
||||||
|
|
||||||
#endif // XENIA_KERNEL_UTIL_XEX2_H_
|
#endif // XENIA_KERNEL_UTIL_XEX2_H_
|
||||||
|
|
|
@ -295,6 +295,17 @@ typedef struct {
|
||||||
xe_xex2_approval_type approval;
|
xe_xex2_approval_type approval;
|
||||||
} xe_xex2_static_library_t;
|
} xe_xex2_static_library_t;
|
||||||
|
|
||||||
|
// credits: some obscure pastebin (http://pastebin.com/ZRvr3Sgj)
|
||||||
|
typedef struct {
|
||||||
|
uint32_t magic[3];
|
||||||
|
uint32_t modulenumber[2];
|
||||||
|
uint32_t version[3];
|
||||||
|
uint32_t imagebaseaddr; // must be <<16 to be accurate
|
||||||
|
uint32_t count;
|
||||||
|
uint32_t base;
|
||||||
|
uint32_t ordOffset[1]; // ordOffset[0] + (imagebaseaddr << 16) = function offset of ordinal 1
|
||||||
|
} xe_xex2_export_table;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
XEX_ENCRYPTION_NONE = 0,
|
XEX_ENCRYPTION_NONE = 0,
|
||||||
XEX_ENCRYPTION_NORMAL = 1,
|
XEX_ENCRYPTION_NORMAL = 1,
|
||||||
|
@ -397,7 +408,7 @@ typedef struct {
|
||||||
uint8_t import_table_digest[20];
|
uint8_t import_table_digest[20];
|
||||||
uint8_t media_id[16];
|
uint8_t media_id[16];
|
||||||
uint8_t file_key[16];
|
uint8_t file_key[16];
|
||||||
uint32_t export_table;
|
uint32_t export_table; // address of the export table
|
||||||
uint8_t header_digest[20];
|
uint8_t header_digest[20];
|
||||||
xe_xex2_region_flags game_regions;
|
xe_xex2_region_flags game_regions;
|
||||||
xe_xex2_media_flags media_flags;
|
xe_xex2_media_flags media_flags;
|
||||||
|
@ -434,6 +445,7 @@ typedef struct {
|
||||||
xe_xex2_tls_info_t tls_info;
|
xe_xex2_tls_info_t tls_info;
|
||||||
size_t import_library_count;
|
size_t import_library_count;
|
||||||
xe_xex2_import_library_t import_libraries[32];
|
xe_xex2_import_library_t import_libraries[32];
|
||||||
|
size_t export_table_offset; // PE Export Directory
|
||||||
size_t static_library_count;
|
size_t static_library_count;
|
||||||
xe_xex2_static_library_t static_libraries[32];
|
xe_xex2_static_library_t static_libraries[32];
|
||||||
xe_xex2_file_format_info_t file_format_info;
|
xe_xex2_file_format_info_t file_format_info;
|
||||||
|
|
Loading…
Reference in New Issue