From 207589e5a1e481ea14bf2951bb22c8316193dac7 Mon Sep 17 00:00:00 2001 From: gibbed Date: Sat, 24 Nov 2018 04:05:41 -0600 Subject: [PATCH] [CPU/Kernel] Correct parsing of XEX_HEADER_IMPORT_LIBRARIES. --- src/xenia/cpu/xex_module.cc | 46 +++++++++++++++++-------------- src/xenia/kernel/user_module.cc | 34 +++++++++++++---------- src/xenia/kernel/util/xex2_info.h | 10 ++++--- 3 files changed, 51 insertions(+), 39 deletions(-) diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 8b6b5e173..6f8537970 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -1119,23 +1119,23 @@ bool XexModule::LoadContinue() { processor_->backend()->CommitExecutableRange(low_address_, high_address_); // Add all imports (variables/functions). - xex2_opt_import_libraries* opt_import_header = nullptr; - GetOptHeader(XEX_HEADER_IMPORT_LIBRARIES, &opt_import_header); + xex2_opt_import_libraries* opt_import_libraries = nullptr; + GetOptHeader(XEX_HEADER_IMPORT_LIBRARIES, &opt_import_libraries); - if (opt_import_header) { + if (opt_import_libraries) { // FIXME: Don't know if 32 is the actual limit, but haven't seen more than // 2. const char* string_table[32]; std::memset(string_table, 0, sizeof(string_table)); - size_t max_string_table_index = 0; // Parse the string table - for (size_t i = 0; i < opt_import_header->string_table_size; - ++max_string_table_index) { - assert_true(max_string_table_index < xe::countof(string_table)); - const char* str = opt_import_header->string_table + i; + for (size_t i = 0, o = 0; i < opt_import_libraries->string_table.size && + o < opt_import_libraries->string_table.count; + ++o) { + assert_true(o < xe::countof(string_table)); + const char* str = &opt_import_libraries->string_table.data[i]; - string_table[max_string_table_index] = str; + string_table[o] = str; i += std::strlen(str) + 1; // Padding @@ -1144,15 +1144,19 @@ bool XexModule::LoadContinue() { } } - auto libraries_ptr = reinterpret_cast(opt_import_header) + - opt_import_header->string_table_size + 12; + auto library_data = reinterpret_cast(opt_import_libraries) + + opt_import_libraries->string_table.size + 12; uint32_t library_offset = 0; - uint32_t library_count = opt_import_header->library_count; - for (uint32_t i = 0; i < library_count; i++) { - auto library = reinterpret_cast(libraries_ptr + - library_offset); + while (library_offset < opt_import_libraries->size) { + auto library = + reinterpret_cast(library_data + library_offset); + if (!library->size) { + break; + } size_t library_name_index = library->name_index & 0xFF; - assert_true(library_name_index < max_string_table_index); + assert_true(library_name_index < + opt_import_libraries->string_table.count); + assert_not_null(string_table[library_name_index]); SetupLibraryImports(string_table[library_name_index], library); library_offset += library->size; } @@ -1312,10 +1316,12 @@ bool XexModule::SetupLibraryImports(const char* name, var_info->set_status(Symbol::Status::kDefined); } else if (record_type == 1) { // Thunk. - assert_true(library_info.imports.size() > 0); - auto& prev_import = library_info.imports[library_info.imports.size() - 1]; - assert_true(prev_import.ordinal == ordinal); - prev_import.thunk_address = record_addr; + if (library_info.imports.size() > 0) { + auto& prev_import = + library_info.imports[library_info.imports.size() - 1]; + assert_true(prev_import.ordinal == ordinal); + prev_import.thunk_address = record_addr; + } if (kernel_export) { import_name.AppendFormat("%s", kernel_export->name); diff --git a/src/xenia/kernel/user_module.cc b/src/xenia/kernel/user_module.cc index a79091d3c..df65650f2 100644 --- a/src/xenia/kernel/user_module.cc +++ b/src/xenia/kernel/user_module.cc @@ -486,29 +486,33 @@ void UserModule::Dump() { std::memset(string_table, 0, sizeof(string_table)); // Parse the string table - for (size_t l = 0, j = 0; l < opt_import_libraries->string_table_size; - j++) { - assert_true(j < xe::countof(string_table)); - const char* str = opt_import_libraries->string_table + l; + for (size_t j = 0, o = 0; j < opt_import_libraries->string_table.size && + o < opt_import_libraries->string_table.count; + o++) { + assert_true(o < xe::countof(string_table)); + const char* str = &opt_import_libraries->string_table.data[o]; - string_table[j] = str; - l += std::strlen(str) + 1; + string_table[o] = str; + j += std::strlen(str) + 1; // Padding - if ((l % 4) != 0) { - l += 4 - (l % 4); + if ((j % 4) != 0) { + j += 4 - (j % 4); } } - auto libraries = + auto library_data = reinterpret_cast(opt_import_libraries) + - opt_import_libraries->string_table_size + 12; + opt_import_libraries->string_table.size + 12; uint32_t library_offset = 0; - uint32_t library_count = opt_import_libraries->library_count; - for (uint32_t l = 0; l < library_count; l++) { + while (library_offset < opt_import_libraries->size) { auto library = reinterpret_cast( - libraries + library_offset); + library_data + library_offset); + if (!library->size) { + break; + } auto name = string_table[library->name_index & 0xFF]; + assert_not_null(name); sb.AppendFormat(" %s - %d imports\n", name, (uint16_t)library->count); @@ -786,11 +790,11 @@ void UserModule::Dump() { } if (kernel_export && kernel_export->type == cpu::Export::Type::kVariable) { - sb.AppendFormat(" V %.8X %.3X (%3d) %s %s\n", + sb.AppendFormat(" V %.8X %.3X (%4d) %s %s\n", info->value_address, info->ordinal, info->ordinal, implemented ? " " : "!!", name); } else if (info->thunk_address) { - sb.AppendFormat(" F %.8X %.8X %.3X (%3d) %s %s\n", + sb.AppendFormat(" F %.8X %.8X %.3X (%4d) %s %s\n", info->value_address, info->thunk_address, info->ordinal, info->ordinal, implemented ? " " : "!!", name); diff --git a/src/xenia/kernel/util/xex2_info.h b/src/xenia/kernel/util/xex2_info.h index 23aa62524..f91b7c30f 100644 --- a/src/xenia/kernel/util/xex2_info.h +++ b/src/xenia/kernel/util/xex2_info.h @@ -474,10 +474,12 @@ struct xex2_opt_execution_info { static_assert_size(xex2_opt_execution_info, 0x18); struct xex2_opt_import_libraries { - xe::be section_size; // 0x0 - xe::be string_table_size; // 0x4 - xe::be library_count; // 0x8 - char string_table[1]; // 0xC string_table_size bytes + xe::be size; // 0x0 + struct { + xe::be size; // 0x4 + xe::be count; // 0x8 + char data[1]; // 0xC string_table_size bytes + } string_table; }; struct xex2_import_library {