diff options
| author | Rémi Verschelde <remi@verschelde.fr> | 2022-03-21 17:41:23 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2022-03-21 17:41:23 +0100 |
| commit | 5a28b1ae5118d05b5d22fe2f6f1109f839058c9d (patch) | |
| tree | 7d403df065a91d1272688f0f81ff43b8c9a7b3c5 /platform/linuxbsd/export/export_plugin.cpp | |
| parent | 16e96e52d3e27f0ea66b16ff29d8579751d5dfed (diff) | |
| parent | e5e697564d61f889bd0345d6507e8eea123a37cd (diff) | |
| download | redot-engine-5a28b1ae5118d05b5d22fe2f6f1109f839058c9d.tar.gz | |
Merge pull request #59369 from aaronfranke/fixup-embedded-pck
Diffstat (limited to 'platform/linuxbsd/export/export_plugin.cpp')
| -rw-r--r-- | platform/linuxbsd/export/export_plugin.cpp | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/platform/linuxbsd/export/export_plugin.cpp b/platform/linuxbsd/export/export_plugin.cpp index 99f5b82b34..6300a37854 100644 --- a/platform/linuxbsd/export/export_plugin.cpp +++ b/platform/linuxbsd/export/export_plugin.cpp @@ -72,3 +72,108 @@ Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> return err; } + +Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) const { + // Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data + + FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE); + if (!f) { + return ERR_CANT_OPEN; + } + + // Read and check ELF magic number + { + uint32_t magic = f->get_32(); + if (magic != 0x464c457f) { // 0x7F + "ELF" + f->close(); + return ERR_FILE_CORRUPT; + } + } + + // Read program architecture bits from class field + + int bits = f->get_8() * 32; + + if (bits == 32 && p_embedded_size >= 0x100000000) { + f->close(); + ERR_FAIL_V_MSG(ERR_INVALID_DATA, "32-bit executables cannot have embedded data >= 4 GiB."); + } + + // Get info about the section header table + + int64_t section_table_pos; + int64_t section_header_size; + if (bits == 32) { + section_header_size = 40; + f->seek(0x20); + section_table_pos = f->get_32(); + f->seek(0x30); + } else { // 64 + section_header_size = 64; + f->seek(0x28); + section_table_pos = f->get_64(); + f->seek(0x3c); + } + int num_sections = f->get_16(); + int string_section_idx = f->get_16(); + + // Load the strings table + uint8_t *strings; + { + // Jump to the strings section header + f->seek(section_table_pos + string_section_idx * section_header_size); + + // Read strings data size and offset + int64_t string_data_pos; + int64_t string_data_size; + if (bits == 32) { + f->seek(f->get_position() + 0x10); + string_data_pos = f->get_32(); + string_data_size = f->get_32(); + } else { // 64 + f->seek(f->get_position() + 0x18); + string_data_pos = f->get_64(); + string_data_size = f->get_64(); + } + + // Read strings data + f->seek(string_data_pos); + strings = (uint8_t *)memalloc(string_data_size); + if (!strings) { + f->close(); + return ERR_OUT_OF_MEMORY; + } + f->get_buffer(strings, string_data_size); + } + + // Search for the "pck" section + + bool found = false; + for (int i = 0; i < num_sections; ++i) { + int64_t section_header_pos = section_table_pos + i * section_header_size; + f->seek(section_header_pos); + + uint32_t name_offset = f->get_32(); + if (strcmp((char *)strings + name_offset, "pck") == 0) { + // "pck" section found, let's patch! + + if (bits == 32) { + f->seek(section_header_pos + 0x10); + f->store_32(p_embedded_start); + f->store_32(p_embedded_size); + } else { // 64 + f->seek(section_header_pos + 0x18); + f->store_64(p_embedded_start); + f->store_64(p_embedded_size); + } + + found = true; + break; + } + } + + memfree(strings); + f->close(); + + return found ? OK : ERR_FILE_CORRUPT; +} |
