From 21aa53f7183541b4cc74b8b93fe51da7bedfb7f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pa=CC=84vels=20Nadtoc=CC=8Cajevs?= <7645683+bruvzg@users.noreply.github.com> Date: Wed, 15 Oct 2025 12:31:18 +0300 Subject: [PATCH] Update embedded PCK virtual address. --- core/config/project_settings.cpp | 12 ++-- platform/windows/export/export_plugin.cpp | 82 ++++++++++++++++------- 2 files changed, 65 insertions(+), 29 deletions(-) diff --git a/core/config/project_settings.cpp b/core/config/project_settings.cpp index c5c7a0a6460..de83621df45 100644 --- a/core/config/project_settings.cpp +++ b/core/config/project_settings.cpp @@ -783,12 +783,14 @@ Error ProjectSettings::_setup(const String &p_path, const String &p_main_pack, b resource_path = current_dir; resource_path = resource_path.replace_char('\\', '/'); // Windows path to Unix path just in case. err = _load_settings_text_or_binary(current_dir.path_join("project.godot"), current_dir.path_join("project.binary")); - if (err == OK && !p_ignore_override) { - // Optional, we don't mind if it fails. + if (err == OK) { #ifdef OVERRIDE_ENABLED - bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override"); - if (!disable_override) { - _load_settings_text(current_dir.path_join("override.cfg")); + if (!p_ignore_override) { + // Optional, we don't mind if it fails. + bool disable_override = GLOBAL_GET("application/config/disable_project_settings_override"); + if (!disable_override) { + _load_settings_text(current_dir.path_join("override.cfg")); + } } #endif // OVERRIDE_ENABLED found = true; diff --git a/platform/windows/export/export_plugin.cpp b/platform/windows/export/export_plugin.cpp index 0d2cf66dc5a..dad6f9e1623 100644 --- a/platform/windows/export/export_plugin.cpp +++ b/platform/windows/export/export_plugin.cpp @@ -802,9 +802,9 @@ String EditorExportPlatformWindows::_get_exe_arch(const String &p_path) const { } Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) { - // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data + // Patch the header of the "pck" section in the PE file so that it corresponds to the embedded data. - if (p_embedded_size + p_embedded_start >= 0x100000000) { // Check for total executable size + if (p_embedded_size + p_embedded_start >= 0x100000000) { // Check for total executable size. add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("Windows executables cannot be >= 4 GiB.")); return ERR_INVALID_DATA; } @@ -815,7 +815,7 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6 return ERR_CANT_OPEN; } - // Jump to the PE header and check the magic number + // Jump to the PE header and check the magic number. { f->seek(0x3c); uint32_t pe_pos = f->get_32(); @@ -828,27 +828,36 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6 } } - // Process header - + // Process header. + uint32_t sect_alignment = 0x1000; + uint32_t image_size = 0; int num_sections; - { - int64_t header_pos = f->get_position(); + int64_t header_pos = f->get_position(); + int64_t opt_header_pos = 0; + { f->seek(header_pos + 2); num_sections = f->get_16(); f->seek(header_pos + 16); uint16_t opt_header_size = f->get_16(); + opt_header_pos = f->get_position() + 2; - // Skip rest of header + optional header to go to the section headers - f->seek(f->get_position() + 2 + opt_header_size); + f->seek(opt_header_pos + 32); + sect_alignment = f->get_32(); + + f->seek(opt_header_pos + 56); + image_size = f->get_32(); + + // Skip rest of header + optional header to go to the section headers. + f->seek(opt_header_pos + opt_header_size); } - // Search for the "pck" section + // Search for the "pck" section. int64_t section_table_pos = f->get_position(); - bool found = false; - for (int i = 0; i < num_sections; ++i) { + int pck_old_pos = -1; + for (int i = 0; i < num_sections; i++) { int64_t section_header_pos = section_table_pos + i * 40; f->seek(section_header_pos); @@ -857,23 +866,48 @@ Error EditorExportPlatformWindows::fixup_embedded_pck(const String &p_path, int6 section_name[8] = '\0'; if (strcmp((char *)section_name, "pck") == 0) { - // "pck" section found, let's patch! + pck_old_pos = i; - // Set virtual size to a little to avoid it taking memory (zero would give issues) - f->seek(section_header_pos + 8); - f->store_32(8); - - f->seek(section_header_pos + 16); - f->store_32(p_embedded_size); - f->seek(section_header_pos + 20); - f->store_32(p_embedded_start); - - found = true; + // Update virtual size of previous section to avoid gaps in the virtual addresses. + f->seek(section_table_pos + (i - 1) * 40 + 8); + uint32_t virt_size = f->get_32(); + f->seek(section_table_pos + (i - 1) * 40 + 8); + f->store_32(virt_size + sect_alignment); break; } } + if (pck_old_pos >= 0) { + // Move section data. + uint8_t section_data[40]; + for (int i = pck_old_pos; i < num_sections - 1; i++) { + f->seek(section_table_pos + (i + 1) * 40); + f->get_buffer(section_data, 40); + f->seek(section_table_pos + i * 40); + f->store_buffer(section_data, 40); + } - if (!found) { + // Add "pck" at the end. + f->seek(section_table_pos + (num_sections - 1) * 40); + uint8_t section_name[8] = { 'p', 'c', 'k', '\0', '\0', '\0', '\0', '\0' }; + f->store_buffer(section_name, 8); // Name. + f->store_32(8); // VirtualSize, set to a little to avoid it taking memory (zero would give issues). + f->store_32(image_size); // VirtualAddress. + f->store_32(p_embedded_size); // SizeOfRawData. + f->store_32(p_embedded_start); // PointerToRawData. + f->store_32(0); // PointerToRelocations, not used. + f->store_32(0); // PointerToLinenumbers, not used. + f->store_16(0); // NumberOfRelocations. + f->store_16(0); // NumberOfLinenumbers. + f->store_32(0x40000000); // Characteristics: Read. + + // Update image virtual size. + f->seek(opt_header_pos + 56); + f->store_32(image_size + sect_alignment); + } + + f->close(); + + if (pck_old_pos == -1) { add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("Executable \"pck\" section not found.")); return ERR_FILE_CORRUPT; }