diff --git a/src/xenia/kernel/objects/xuser_module.cc b/src/xenia/kernel/objects/xuser_module.cc index 71eae83a3..58f4dd185 100644 --- a/src/xenia/kernel/objects/xuser_module.cc +++ b/src/xenia/kernel/objects/xuser_module.cc @@ -143,9 +143,12 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) { } void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) { - // TODO(benvanik): check export tables. - XELOGE("GetProcAddressByOrdinal not implemented"); - return NULL; + PEExport export; + int ret = xe_xex2_lookup_export(xex_, ordinal, export); + + if (ret) return nullptr; + + return (void*)export.addr; } void* XUserModule::GetProcAddressByName(const char* name) { @@ -153,7 +156,7 @@ void* XUserModule::GetProcAddressByName(const char* name) { int ret = xe_xex2_lookup_export(xex_, name, export); // Failure. - if (ret) return NULL; + if (ret) return nullptr; return (void*)export.addr; } diff --git a/src/xenia/kernel/util/xex2.cc b/src/xenia/kernel/util/xex2.cc index 87b023bba..9ccf2d2c5 100644 --- a/src/xenia/kernel/util/xex2.cc +++ b/src/xenia/kernel/util/xex2.cc @@ -1004,14 +1004,15 @@ int xe_xex2_lookup_export(xe_xex2_ref xex, const char *name, // 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 *)((uint64_t)e + e->AddressOfFunctions); + + // Names relative to directory uint32_t *name_table = - (uint32_t *)((uint64_t)e + - e->AddressOfNames); // Names relative to directory + (uint32_t *)((uint64_t)e + e->AddressOfNames); + + // Table of ordinals (by name) uint16_t *ordinal_table = - (uint16_t *)((uint64_t)e + - e->AddressOfNameOrdinals); // Table of ordinals + (uint16_t *)((uint64_t)e + e->AddressOfNameOrdinals); const char *mod_name = (const char *)((uint64_t)e + e->Name); @@ -1030,6 +1031,47 @@ int xe_xex2_lookup_export(xe_xex2_ref xex, const char *name, } } + // No match + return 1; +} + +int xe_xex2_lookup_export(xe_xex2_ref xex, int ordinal, + 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! + // Functions relative to base + uint32_t *function_table = + (uint32_t *)((uint64_t)e + e->AddressOfFunctions); + + // Names relative to directory + uint32_t *name_table = + (uint32_t *)((uint64_t)e + e->AddressOfNames); + + // Table of ordinals (by name) + uint16_t *ordinal_table = + (uint16_t *)((uint64_t)e + e->AddressOfNameOrdinals); + + const char *mod_name = (const char *)((uint64_t)e + e->Name); + + if (ordinal < e->NumberOfFunctions) { + peexport.name = nullptr; // TODO: Backwards conversion to get this + peexport.ordinal = ordinal; + peexport.addr = (uint64_t)(baseaddr + function_table[ordinal]); + + return 0; + } + // No match return 1; } \ No newline at end of file diff --git a/src/xenia/kernel/util/xex2.h b/src/xenia/kernel/util/xex2.h index 1d86f6dac..a48ea6100 100644 --- a/src/xenia/kernel/util/xex2.h +++ b/src/xenia/kernel/util/xex2.h @@ -64,5 +64,7 @@ int xe_xex2_get_import_infos(xe_xex2_ref xex, int xe_xex2_lookup_export(xe_xex2_ref xex, const char* name, PEExport& peexport); +int xe_xex2_lookup_export(xe_xex2_ref xex, int ordinal, + PEExport& peexport); #endif // XENIA_KERNEL_UTIL_XEX2_H_