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;
|
||||
}
|
||||
|
||||
void* XKernelModule::GetProcAddressByName(const char* name) {
|
||||
XELOGE("GetProcAddressByName not implemented");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -24,6 +24,7 @@ class XKernelModule : public XModule {
|
|||
virtual ~XKernelModule();
|
||||
|
||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
||||
virtual void* GetProcAddressByName(const char* name);
|
||||
|
||||
protected:
|
||||
Emulator* emulator_;
|
||||
|
|
|
@ -27,6 +27,7 @@ class XModule : public XObject {
|
|||
const std::string& name() const { return name_; }
|
||||
|
||||
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,
|
||||
uint32_t* out_section_size);
|
||||
|
||||
|
|
|
@ -148,6 +148,17 @@ void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) {
|
|||
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,
|
||||
uint32_t* out_section_size) {
|
||||
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);
|
||||
|
||||
virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
|
||||
virtual void* GetProcAddressByName(const char* name);
|
||||
virtual X_STATUS GetSection(const char* name, uint32_t* out_section_data,
|
||||
uint32_t* out_section_size);
|
||||
|
||||
|
|
|
@ -49,6 +49,8 @@ typedef struct xe_xex2 {
|
|||
size_t count;
|
||||
xe_xex2_import_info_t *infos;
|
||||
} library_imports[16];
|
||||
|
||||
xe_xex2_export_table *export_table;
|
||||
} xe_xex2_t;
|
||||
|
||||
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:
|
||||
header->exe_heap_size = opt_header->value;
|
||||
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: {
|
||||
const size_t max_count = xe::countof(header->import_libraries);
|
||||
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);
|
||||
}
|
||||
|
||||
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);
|
||||
// DumpExportsSection(pImageBase, pNTHeader);
|
||||
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;
|
||||
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*
|
||||
};
|
||||
|
||||
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,
|
||||
const size_t length, xe_xex2_options_t options);
|
||||
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,
|
||||
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_
|
||||
|
|
|
@ -295,6 +295,17 @@ typedef struct {
|
|||
xe_xex2_approval_type approval;
|
||||
} 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 {
|
||||
XEX_ENCRYPTION_NONE = 0,
|
||||
XEX_ENCRYPTION_NORMAL = 1,
|
||||
|
@ -397,7 +408,7 @@ typedef struct {
|
|||
uint8_t import_table_digest[20];
|
||||
uint8_t media_id[16];
|
||||
uint8_t file_key[16];
|
||||
uint32_t export_table;
|
||||
uint32_t export_table; // address of the export table
|
||||
uint8_t header_digest[20];
|
||||
xe_xex2_region_flags game_regions;
|
||||
xe_xex2_media_flags media_flags;
|
||||
|
@ -434,6 +445,7 @@ typedef struct {
|
|||
xe_xex2_tls_info_t tls_info;
|
||||
size_t import_library_count;
|
||||
xe_xex2_import_library_t import_libraries[32];
|
||||
size_t export_table_offset; // PE Export Directory
|
||||
size_t static_library_count;
|
||||
xe_xex2_static_library_t static_libraries[32];
|
||||
xe_xex2_file_format_info_t file_format_info;
|
||||
|
|
Loading…
Reference in New Issue