summaryrefslogtreecommitdiff
path: root/platform
diff options
context:
space:
mode:
authorRĂ©mi Verschelde <rverschelde@gmail.com>2019-07-05 10:28:29 +0200
committerGitHub <noreply@github.com>2019-07-05 10:28:29 +0200
commita149e412f75e9eef87e8ff54e21402f90161f65b (patch)
tree22b36e565fe883fdf51a9c83a0b57e985d27179b /platform
parenta9ad1e6692af85fbe8aab36361c304b81ed376f4 (diff)
parent40f4d3cf0fea814e23de33db1f1f02ebe05292ab (diff)
Merge pull request #24086 from RandomShaper/bundle-pck-to-executable
Enhance game export
Diffstat (limited to 'platform')
-rw-r--r--platform/windows/export/export.cpp76
-rw-r--r--platform/windows/godot_windows.cpp11
-rw-r--r--platform/x11/detect.py3
-rw-r--r--platform/x11/export/export.cpp112
-rw-r--r--platform/x11/pck_embed.ld10
5 files changed, 212 insertions, 0 deletions
diff --git a/platform/windows/export/export.cpp b/platform/windows/export/export.cpp
index 4a72d07adc..827daa2d58 100644
--- a/platform/windows/export/export.cpp
+++ b/platform/windows/export/export.cpp
@@ -34,6 +34,8 @@
#include "editor/editor_settings.h"
#include "platform/windows/logo.gen.h"
+static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
+
class EditorExportPlatformWindows : public EditorExportPlatformPC {
public:
@@ -172,6 +174,80 @@ void register_windows_exporter() {
platform->set_release_64("windows_64_release.exe");
platform->set_debug_64("windows_64_debug.exe");
platform->set_os_name("Windows");
+ platform->set_fixup_embedded_pck_func(&fixup_embedded_pck);
EditorExport::get_singleton()->add_export_platform(platform);
}
+
+static Error 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
+
+ FileAccess *f = FileAccess::open(p_path, FileAccess::READ_WRITE);
+ if (!f) {
+ return ERR_CANT_OPEN;
+ }
+
+ // Jump to the PE header and check the magic number
+ {
+ f->seek(0x3c);
+ uint32_t pe_pos = f->get_32();
+
+ f->seek(pe_pos);
+ uint32_t magic = f->get_32();
+ if (magic != 0x00004550) {
+ f->close();
+ return ERR_FILE_CORRUPT;
+ }
+ }
+
+ // Process header
+
+ int num_sections;
+ {
+ int64_t header_pos = f->get_position();
+
+ f->seek(header_pos + 2);
+ num_sections = f->get_16();
+ f->seek(header_pos + 16);
+ uint16_t opt_header_size = f->get_16();
+
+ // Skip rest of header + optional header to go to the section headers
+ f->seek(f->get_position() + 2 + opt_header_size);
+ }
+
+ // Search for the "pck" section
+
+ int64_t section_table_pos = f->get_position();
+
+ bool found = false;
+ for (int i = 0; i < num_sections; ++i) {
+
+ int64_t section_header_pos = section_table_pos + i * 40;
+ f->seek(section_header_pos);
+
+ uint8_t section_name[9];
+ f->get_buffer(section_name, 8);
+ section_name[8] = '\0';
+
+ if (strcmp((char *)section_name, "pck") == 0) {
+ // "pck" section found, let's patch!
+
+ // 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;
+ break;
+ }
+ }
+
+ f->close();
+
+ return found ? OK : ERR_FILE_CORRUPT;
+}
diff --git a/platform/windows/godot_windows.cpp b/platform/windows/godot_windows.cpp
index 0b52682c7c..11bfea6922 100644
--- a/platform/windows/godot_windows.cpp
+++ b/platform/windows/godot_windows.cpp
@@ -34,6 +34,17 @@
#include <locale.h>
#include <stdio.h>
+// For export templates, add a section; the exporter will patch it to enclose
+// the data appended to the executable (bundled PCK)
+#ifndef TOOLS_ENABLED
+#if defined _MSC_VER
+#pragma section("pck", read)
+__declspec(allocate("pck")) static char dummy[8] = { 0 };
+#elif defined __GNUC__
+static const char dummy[8] __attribute__((section("pck"), used)) = { 0 };
+#endif
+#endif
+
PCHAR *
CommandLineToArgvA(
PCHAR CmdLine,
diff --git a/platform/x11/detect.py b/platform/x11/detect.py
index 58dea615cb..f3a486df02 100644
--- a/platform/x11/detect.py
+++ b/platform/x11/detect.py
@@ -324,6 +324,9 @@ def configure(env):
if env["execinfo"]:
env.Append(LIBS=['execinfo'])
+
+ if not env['tools']:
+ env.Append(LINKFLAGS=['-T', 'platform/x11/pck_embed.ld'])
## Cross-compilation
diff --git a/platform/x11/export/export.cpp b/platform/x11/export/export.cpp
index f7d98c1d68..8767aac517 100644
--- a/platform/x11/export/export.cpp
+++ b/platform/x11/export/export.cpp
@@ -30,10 +30,13 @@
#include "export.h"
+#include "core/os/file_access.h"
#include "editor/editor_export.h"
#include "platform/x11/logo.gen.h"
#include "scene/resources/texture.h"
+static Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size);
+
void register_x11_exporter() {
Ref<EditorExportPlatformPC> platform;
@@ -53,6 +56,115 @@ void register_x11_exporter() {
platform->set_debug_64("linux_x11_64_debug");
platform->set_os_name("X11");
platform->set_chmod_flags(0755);
+ platform->set_fixup_embedded_pck_func(&fixup_embedded_pck);
EditorExport::get_singleton()->add_export_platform(platform);
}
+
+static Error 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 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_EXPLAIN("32-bit executables cannot have embedded data >= 4 GiB");
+ ERR_FAIL_V(ERR_INVALID_DATA);
+ }
+
+ // 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;
+}
diff --git a/platform/x11/pck_embed.ld b/platform/x11/pck_embed.ld
new file mode 100644
index 0000000000..fe09144d88
--- /dev/null
+++ b/platform/x11/pck_embed.ld
@@ -0,0 +1,10 @@
+SECTIONS
+{
+ /* Add a zero-sized section; the exporter will patch it to enclose the data appended to the executable (embedded PCK) */
+ pck 0 (NOLOAD) :
+ {
+ /* Just some content to avoid the linker discarding the section */
+ . = ALIGN(8);
+ }
+}
+INSERT AFTER .rodata;