Merge pull request #187 from DrChat/upstream

XexGetProcedureAddress by proc name
This commit is contained in:
Ben Vanik 2015-05-04 18:59:37 -07:00
commit c4784e6dcd
9 changed files with 114 additions and 6 deletions

View File

@ -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

View File

@ -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_;

View File

@ -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);

View File

@ -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_);

View File

@ -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);

View File

@ -237,6 +237,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);
@ -982,3 +987,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 baseaddr = (uint64_t)xex->memory->TranslateVirtual(header->exe_address);
IMAGE_EXPORT_DIRECTORY *e = (PIMAGE_EXPORT_DIRECTORY)(baseaddr + 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)(baseaddr + 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;
}

View File

@ -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_

View File

@ -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;

View File

@ -246,10 +246,16 @@ SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state,
KernelState* state) {
uint32_t module_handle = SHIM_GET_ARG_32(0);
uint32_t ordinal = SHIM_GET_ARG_32(1);
const char *name = (const char *)SHIM_MEM_ADDR(ordinal);
uint32_t out_function_ptr = SHIM_GET_ARG_32(2);
XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", module_handle, ordinal,
out_function_ptr);
if (ordinal < 0x10000) {
XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", module_handle, ordinal,
out_function_ptr);
} else {
XELOGD("XexGetProcedureAddress(%.8X, %.8X(%s), %.8X)", module_handle, ordinal,
name, out_function_ptr);
}
X_STATUS result = X_STATUS_INVALID_HANDLE;
SHIM_SET_MEM_32(out_function_ptr, 0xDEADF00D);
@ -263,11 +269,29 @@ SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state,
state->object_table()->GetObject(module_handle, (XObject**)&module);
}
result = X_STATUS_UNSUCCESSFUL;
if (XSUCCEEDED(result)) {
// TODO(benvanik): implement. May need to create stub functions on the fly.
// module->GetProcAddressByOrdinal(ordinal);
result = X_STATUS_NOT_IMPLEMENTED;
if (ordinal < 0x10000) {
// Ordinal.
uint64_t ptr = (uint64_t)module->GetProcAddressByOrdinal(ordinal);
if (ptr) {
SHIM_SET_MEM_32(out_function_ptr, ptr);
result = X_STATUS_SUCCESS;
}
} else {
// It's a name pointer instead.
uint64_t ptr = (uint64_t)module->GetProcAddressByName(name);
// FYI: We don't need to generate this function now. It'll
// be done automatically by xenia when it gets called.
if (ptr) {
SHIM_SET_MEM_32(out_function_ptr, ptr);
result = X_STATUS_SUCCESS;
}
}
}
if (module) {
module->Release();
}