Properly parsing resource infos and implementing XexGetModuleSection.

This commit is contained in:
Ben Vanik 2014-01-19 00:46:46 -08:00
parent d22b59555e
commit 0bc49621d4
8 changed files with 100 additions and 36 deletions

View File

@ -526,13 +526,19 @@ json_t* Processor::DumpModule(XexModule* module, bool& succeeded) {
} }
json_object_set_new(module_json, "headers", headers_json); json_object_set_new(module_json, "headers", headers_json);
// TODO(benvanik): resources. json_t* resource_infos_json = json_array();
json_t* resource_info_json = json_object(); for (size_t n = 0; n < header->resource_info_count; n++) {
json_object_set_integer_new( auto& res = header->resource_infos[n];
resource_info_json, "address", header->resource_info.address); json_t* resource_info_json = json_object();
json_object_set_integer_new( json_object_set_string_new(
resource_info_json, "size", header->resource_info.size); resource_info_json, "name", res.name);
json_object_set_new(module_json, "resourceInfo", resource_info_json); json_object_set_integer_new(
resource_info_json, "address", res.address);
json_object_set_integer_new(
resource_info_json, "size", res.size);
json_array_append_new(resource_infos_json, resource_info_json);
}
json_object_set_new(module_json, "resourceInfos", resource_infos_json);
json_t* sections_json = json_array(); json_t* sections_json = json_array();
for (size_t n = 0, i = 0; n < header->section_count; n++) { for (size_t n = 0, i = 0; n < header->section_count; n++) {

View File

@ -33,3 +33,9 @@ XModule::XModule(KernelState* kernel_state, const char* path) :
XModule::~XModule() { XModule::~XModule() {
} }
X_STATUS XModule::GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size) {
return X_STATUS_UNSUCCESSFUL;
}

View File

@ -28,6 +28,9 @@ public:
const char* name() const { return name_; } const char* name() const { return name_; }
virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0; virtual void* GetProcAddressByOrdinal(uint16_t ordinal) = 0;
virtual X_STATUS GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size);
protected: protected:
char name_[256]; char name_[256];

View File

@ -124,23 +124,28 @@ XECLEANUP:
return X_STATUS_UNSUCCESSFUL; return X_STATUS_UNSUCCESSFUL;
} }
X_STATUS XUserModule::GetSection(const char* name,
uint32_t* out_data, uint32_t* out_size) {
const PESection* section = xe_xex2_get_pe_section(xex_, name);
if (!section) {
return X_STATUS_UNSUCCESSFUL;
}
*out_data = section->address;
*out_size = section->size;
return X_STATUS_SUCCESS;
}
void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) { void* XUserModule::GetProcAddressByOrdinal(uint16_t ordinal) {
// TODO(benvanik): check export tables. // TODO(benvanik): check export tables.
XELOGE("GetProcAddressByOrdinal not implemented"); XELOGE("GetProcAddressByOrdinal not implemented");
return NULL; return NULL;
} }
X_STATUS XUserModule::GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size) {
auto header = xe_xex2_get_header(xex_);
for (size_t n = 0; n < header->resource_info_count; n++) {
auto& res = header->resource_infos[n];
if (xestrcmpa(name, res.name) == 0) {
// Found!
*out_section_data = res.address;
*out_section_size = res.size;
return X_STATUS_SUCCESS;
}
}
return X_STATUS_UNSUCCESSFUL;
}
X_STATUS XUserModule::Launch(uint32_t flags) { X_STATUS XUserModule::Launch(uint32_t flags) {
const xe_xex2_header_t* header = xex_header(); const xe_xex2_header_t* header = xex_header();
@ -226,9 +231,11 @@ void XUserModule::Dump() {
// Resources. // Resources.
printf("Resources:\n"); printf("Resources:\n");
printf(" %.8X, %db\n", header->resource_info.address, for (size_t n = 0; n < header->resource_info_count; n++) {
header->resource_info.size); auto& res = header->resource_infos[n];
printf(" TODO\n"); printf(" %-8s %.8X-%.8X, %db\n",
res.name, res.address, res.address + res.size, res.size);
}
printf("\n"); printf("\n");
// Section info. // Section info.

View File

@ -32,8 +32,10 @@ public:
X_STATUS LoadFromFile(const char* path); X_STATUS LoadFromFile(const char* path);
X_STATUS LoadFromMemory(const void* addr, const size_t length); X_STATUS LoadFromMemory(const void* addr, const size_t length);
X_STATUS GetSection(const char* name, uint32_t* out_data, uint32_t* out_size);
virtual void* GetProcAddressByOrdinal(uint16_t ordinal); virtual void* GetProcAddressByOrdinal(uint16_t ordinal);
virtual X_STATUS GetSection(
const char* name,
uint32_t* out_section_data, uint32_t* out_section_size);
X_STATUS Launch(uint32_t flags); X_STATUS Launch(uint32_t flags);

View File

@ -73,6 +73,7 @@ void xe_xex2_dealloc(xe_xex2_ref xex) {
xe_xex2_header_t *header = &xex->header; xe_xex2_header_t *header = &xex->header;
xe_free(header->sections); xe_free(header->sections);
xe_free(header->resource_infos);
if (header->file_format_info.compression_type == XEX_COMPRESSION_BASIC) { if (header->file_format_info.compression_type == XEX_COMPRESSION_BASIC) {
xe_free(header->file_format_info.compression_info.basic.blocks); xe_free(header->file_format_info.compression_info.basic.blocks);
} }
@ -147,19 +148,31 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length,
const uint8_t *pp = p + opt_header->offset; const uint8_t *pp = p + opt_header->offset;
switch (opt_header->key) { switch (opt_header->key) {
default:
XELOGW("Unknown XEX header key %.8X", opt_header->key);
break;
case XEX_HEADER_CHECKSUM_TIMESTAMP:
case XEX_HEADER_ORIGINAL_PE_NAME:
case XEX_HEADER_LAN_KEY:
case XEX_HEADER_XBOX360_LOGO:
// Ignored.
break;
case XEX_HEADER_SYSTEM_FLAGS: case XEX_HEADER_SYSTEM_FLAGS:
header->system_flags = (xe_xex2_system_flags)data_offset; header->system_flags = (xe_xex2_system_flags)data_offset;
break; break;
case XEX_HEADER_RESOURCE_INFO: case XEX_HEADER_RESOURCE_INFO:
{ {
xe_xex2_resource_info_t *res = &header->resource_info; header->resource_info_count = (opt_header->length - 4) / 16;
XEEXPECTZERO(xe_copy_memory(res->title_id, header->resource_infos = (xe_xex2_resource_info_t*)xe_calloc(
sizeof(res->title_id), pp + 0x04, 8)); sizeof(xe_xex2_resource_info_t) * header->resource_info_count);
res->address = XEGETUINT32BE(pp + 0x0C); const uint8_t* ph = pp + 0x04;
res->size = XEGETUINT32BE(pp + 0x10); for (size_t n = 0; n < header->resource_info_count; n++) {
if ((opt_header->length - 4) / 16 > 1) { auto& res = header->resource_infos[n];
// Ignoring extra resources (not yet seen) XEEXPECTZERO(xe_copy_memory(res.name,
XELOGW("ignoring extra XEX_HEADER_RESOURCE_INFO resources"); sizeof(res.name), ph + 0x00, 8));
res.address = XEGETUINT32BE(ph + 0x08);
res.size = XEGETUINT32BE(ph + 0x0C);
ph += 16;
} }
} }
break; break;

View File

@ -246,7 +246,7 @@ typedef struct {
} xe_xex2_opt_header_t; } xe_xex2_opt_header_t;
typedef struct { typedef struct {
char title_id[8]; char name[9];
uint32_t address; uint32_t address;
uint32_t size; uint32_t size;
} xe_xex2_resource_info_t; } xe_xex2_resource_info_t;
@ -431,7 +431,6 @@ typedef struct {
uint32_t certificate_offset; uint32_t certificate_offset;
xe_xex2_system_flags system_flags; xe_xex2_system_flags system_flags;
xe_xex2_resource_info_t resource_info;
xe_xex2_execution_info_t execution_info; xe_xex2_execution_info_t execution_info;
xe_xex2_game_ratings_t game_ratings; xe_xex2_game_ratings_t game_ratings;
xe_xex2_tls_info_t tls_info; xe_xex2_tls_info_t tls_info;
@ -451,6 +450,8 @@ typedef struct {
size_t header_count; size_t header_count;
xe_xex2_opt_header_t headers[64]; xe_xex2_opt_header_t headers[64];
size_t resource_info_count;
xe_xex2_resource_info_t* resource_infos;
size_t section_count; size_t section_count;
xe_xex2_section_t* sections; xe_xex2_section_t* sections;
} xe_xex2_header_t; } xe_xex2_header_t;

View File

@ -204,9 +204,35 @@ SHIM_CALL XexGetModuleHandle_shim(
} }
// SHIM_CALL XexGetModuleSection_shim( SHIM_CALL XexGetModuleSection_shim(
// PPCContext* ppc_state, KernelState* state) { PPCContext* ppc_state, KernelState* state) {
// } uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t name_ptr = SHIM_GET_ARG_32(1);
const char* name = (const char*)SHIM_MEM_ADDR(name_ptr);
uint32_t data_ptr = SHIM_GET_ARG_32(2);
uint32_t size_ptr = SHIM_GET_ARG_32(3);
XELOGD(
"XexGetModuleSection(%.8X, %s, %.8X, %.8X)",
handle, name, data_ptr, size_ptr);
XModule* module = NULL;
X_STATUS result =
state->object_table()->GetObject(handle, (XObject**)&module);
if (XSUCCEEDED(result)) {
uint32_t section_data = 0;
uint32_t section_size = 0;
result = module->GetSection(name, &section_data, &section_size);
if (XSUCCEEDED(result)) {
SHIM_SET_MEM_32(data_ptr, section_data);
SHIM_SET_MEM_32(size_ptr, section_size);
}
module->Release();
}
SHIM_SET_RETURN(result);
}
SHIM_CALL XexLoadImage_shim( SHIM_CALL XexLoadImage_shim(
@ -323,7 +349,7 @@ void xe::kernel::xboxkrnl::RegisterModuleExports(
SHIM_SET_MAPPING("xboxkrnl.exe", XexCheckExecutablePrivilege, state); SHIM_SET_MAPPING("xboxkrnl.exe", XexCheckExecutablePrivilege, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleHandle, state); SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleHandle, state);
// SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleSection, state); SHIM_SET_MAPPING("xboxkrnl.exe", XexGetModuleSection, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XexLoadImage, state); SHIM_SET_MAPPING("xboxkrnl.exe", XexLoadImage, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XexUnloadImage, state); SHIM_SET_MAPPING("xboxkrnl.exe", XexUnloadImage, state);
SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state); SHIM_SET_MAPPING("xboxkrnl.exe", XexGetProcedureAddress, state);