Merge pull request #187 from DrChat/upstream
XexGetProcedureAddress by proc name
This commit is contained in:
commit
c4784e6dcd
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -237,6 +237,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);
|
||||||
|
@ -982,3 +987,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 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;
|
||||||
|
}
|
|
@ -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;
|
||||||
|
|
|
@ -246,10 +246,16 @@ SHIM_CALL XexGetProcedureAddress_shim(PPCContext* ppc_state,
|
||||||
KernelState* state) {
|
KernelState* state) {
|
||||||
uint32_t module_handle = SHIM_GET_ARG_32(0);
|
uint32_t module_handle = SHIM_GET_ARG_32(0);
|
||||||
uint32_t ordinal = SHIM_GET_ARG_32(1);
|
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);
|
uint32_t out_function_ptr = SHIM_GET_ARG_32(2);
|
||||||
|
|
||||||
|
if (ordinal < 0x10000) {
|
||||||
XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", module_handle, ordinal,
|
XELOGD("XexGetProcedureAddress(%.8X, %.8X, %.8X)", module_handle, ordinal,
|
||||||
out_function_ptr);
|
out_function_ptr);
|
||||||
|
} else {
|
||||||
|
XELOGD("XexGetProcedureAddress(%.8X, %.8X(%s), %.8X)", module_handle, ordinal,
|
||||||
|
name, out_function_ptr);
|
||||||
|
}
|
||||||
|
|
||||||
X_STATUS result = X_STATUS_INVALID_HANDLE;
|
X_STATUS result = X_STATUS_INVALID_HANDLE;
|
||||||
SHIM_SET_MEM_32(out_function_ptr, 0xDEADF00D);
|
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);
|
state->object_table()->GetObject(module_handle, (XObject**)&module);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
result = X_STATUS_UNSUCCESSFUL;
|
||||||
|
|
||||||
if (XSUCCEEDED(result)) {
|
if (XSUCCEEDED(result)) {
|
||||||
// TODO(benvanik): implement. May need to create stub functions on the fly.
|
if (ordinal < 0x10000) {
|
||||||
// module->GetProcAddressByOrdinal(ordinal);
|
// Ordinal.
|
||||||
result = X_STATUS_NOT_IMPLEMENTED;
|
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) {
|
if (module) {
|
||||||
module->Release();
|
module->Release();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue