Przeglądaj źródła

[Windows/Linux] Check custom export templates architecture.

bruvzg 1 rok temu
rodzic
commit
f72e74f395

+ 91 - 9
platform/linuxbsd/export/export_plugin.cpp

@@ -61,6 +61,20 @@ Error EditorExportPlatformLinuxBSD::_export_debug_script(const Ref<EditorExportP
 }
 
 Error EditorExportPlatformLinuxBSD::export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) {
+	String custom_debug = p_preset->get("custom_template/debug");
+	String custom_release = p_preset->get("custom_template/release");
+	String arch = p_preset->get("binary_format/architecture");
+
+	String template_path = p_debug ? custom_debug : custom_release;
+	template_path = template_path.strip_edges();
+	if (!template_path.is_empty()) {
+		String exe_arch = _get_exe_arch(template_path);
+		if (arch != exe_arch) {
+			add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture, found \"%s\", expected \"%s\"."), exe_arch, arch));
+			return ERR_CANT_CREATE;
+		}
+	}
+
 	bool export_as_zip = p_path.ends_with("zip");
 
 	String pkg_name;
@@ -205,8 +219,76 @@ bool EditorExportPlatformLinuxBSD::is_executable(const String &p_path) const {
 	return is_elf(p_path) || is_shebang(p_path);
 }
 
+bool EditorExportPlatformLinuxBSD::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
+	String err;
+	bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug);
+
+	String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges();
+	String custom_release = p_preset->get("custom_template/release").operator String().strip_edges();
+	String arch = p_preset->get("binary_format/architecture");
+
+	if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) {
+		String exe_arch = _get_exe_arch(custom_debug);
+		if (arch != exe_arch) {
+			err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
+		}
+	}
+	if (!custom_release.is_empty() && FileAccess::exists(custom_release)) {
+		String exe_arch = _get_exe_arch(custom_release);
+		if (arch != exe_arch) {
+			err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
+		}
+	}
+
+	if (!err.is_empty()) {
+		r_error = err;
+	}
+
+	return valid;
+}
+
+String EditorExportPlatformLinuxBSD::_get_exe_arch(const String &p_path) const {
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	if (f.is_null()) {
+		return "invalid";
+	}
+
+	// Read and check ELF magic number.
+	{
+		uint32_t magic = f->get_32();
+		if (magic != 0x464c457f) { // 0x7F + "ELF"
+			return "invalid";
+		}
+	}
+
+	// Process header.
+	int64_t header_pos = f->get_position();
+	f->seek(header_pos + 14);
+	uint16_t machine = f->get_16();
+	f->close();
+
+	switch (machine) {
+		case 0x0003:
+			return "x86_32";
+		case 0x003e:
+			return "x86_64";
+		case 0x0014:
+			return "ppc32";
+		case 0x0015:
+			return "ppc64";
+		case 0x0028:
+			return "arm32";
+		case 0x00b7:
+			return "arm64";
+		case 0x00f3:
+			return "rv64";
+		default:
+			return "unknown";
+	}
+}
+
 Error EditorExportPlatformLinuxBSD::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
+	// Patch the header of the "pck" section in the ELF file so that it corresponds to the embedded data.
 
 	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ_WRITE);
 	if (f.is_null()) {
@@ -214,7 +296,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
 		return ERR_CANT_OPEN;
 	}
 
-	// Read and check ELF magic number
+	// Read and check ELF magic number.
 	{
 		uint32_t magic = f->get_32();
 		if (magic != 0x464c457f) { // 0x7F + "ELF"
@@ -223,7 +305,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
 		}
 	}
 
-	// Read program architecture bits from class field
+	// Read program architecture bits from class field.
 
 	int bits = f->get_8() * 32;
 
@@ -231,7 +313,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
 		add_message(EXPORT_MESSAGE_ERROR, TTR("PCK Embedding"), TTR("32-bit executables cannot have embedded data >= 4 GiB."));
 	}
 
-	// Get info about the section header table
+	// Get info about the section header table.
 
 	int64_t section_table_pos;
 	int64_t section_header_size;
@@ -249,13 +331,13 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
 	int num_sections = f->get_16();
 	int string_section_idx = f->get_16();
 
-	// Load the strings table
+	// Load the strings table.
 	uint8_t *strings;
 	{
-		// Jump to the strings section header
+		// Jump to the strings section header.
 		f->seek(section_table_pos + string_section_idx * section_header_size);
 
-		// Read strings data size and offset
+		// Read strings data size and offset.
 		int64_t string_data_pos;
 		int64_t string_data_size;
 		if (bits == 32) {
@@ -268,7 +350,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
 			string_data_size = f->get_64();
 		}
 
-		// Read strings data
+		// Read strings data.
 		f->seek(string_data_pos);
 		strings = (uint8_t *)memalloc(string_data_size);
 		if (!strings) {
@@ -277,7 +359,7 @@ Error EditorExportPlatformLinuxBSD::fixup_embedded_pck(const String &p_path, int
 		f->get_buffer(strings, string_data_size);
 	}
 
-	// Search for the "pck" section
+	// Search for the "pck" section.
 
 	bool found = false;
 	for (int i = 0; i < num_sections; ++i) {

+ 2 - 0
platform/linuxbsd/export/export_plugin.h

@@ -69,11 +69,13 @@ class EditorExportPlatformLinuxBSD : public EditorExportPlatformPC {
 	bool is_shebang(const String &p_path) const;
 
 	Error _export_debug_script(const Ref<EditorExportPreset> &p_preset, const String &p_app_name, const String &p_pkg_name, const String &p_path);
+	String _get_exe_arch(const String &p_path) const;
 
 public:
 	virtual void get_export_options(List<ExportOption> *r_options) const override;
 	virtual List<String> get_binary_extensions(const Ref<EditorExportPreset> &p_preset) const override;
 	virtual bool get_export_option_visibility(const EditorExportPreset *p_preset, const String &p_option) const override;
+	virtual bool has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug = false) const override;
 	virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
 	virtual String get_template_file_name(const String &p_target, const String &p_arch) const override;
 	virtual Error fixup_embedded_pck(const String &p_path, int64_t p_embedded_start, int64_t p_embedded_size) override;

+ 62 - 2
platform/windows/export/export_plugin.cpp

@@ -187,6 +187,12 @@ Error EditorExportPlatformWindows::export_project(const Ref<EditorExportPreset>
 	template_path = template_path.strip_edges();
 	if (template_path.is_empty()) {
 		template_path = find_export_template(get_template_file_name(p_debug ? "debug" : "release", arch));
+	} else {
+		String exe_arch = _get_exe_arch(template_path);
+		if (arch != exe_arch) {
+			add_message(EXPORT_MESSAGE_ERROR, TTR("Prepare Templates"), vformat(TTR("Mismatching custom export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch));
+			return ERR_CANT_CREATE;
+		}
 	}
 
 	int export_angle = p_preset->get("application/export_angle");
@@ -753,9 +759,26 @@ Error EditorExportPlatformWindows::_code_sign(const Ref<EditorExportPreset> &p_p
 }
 
 bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error, bool &r_missing_templates, bool p_debug) const {
-	String err = "";
+	String err;
 	bool valid = EditorExportPlatformPC::has_valid_export_configuration(p_preset, err, r_missing_templates, p_debug);
 
+	String custom_debug = p_preset->get("custom_template/debug").operator String().strip_edges();
+	String custom_release = p_preset->get("custom_template/release").operator String().strip_edges();
+	String arch = p_preset->get("binary_format/architecture");
+
+	if (!custom_debug.is_empty() && FileAccess::exists(custom_debug)) {
+		String exe_arch = _get_exe_arch(custom_debug);
+		if (arch != exe_arch) {
+			err += vformat(TTR("Mismatching custom debug export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
+		}
+	}
+	if (!custom_release.is_empty() && FileAccess::exists(custom_release)) {
+		String exe_arch = _get_exe_arch(custom_release);
+		if (arch != exe_arch) {
+			err += vformat(TTR("Mismatching custom release export template executable architecture: found \"%s\", expected \"%s\"."), exe_arch, arch) + "\n";
+		}
+	}
+
 	String rcedit_path = EDITOR_GET("export/windows/rcedit");
 	if (p_preset->get("application/modify_resources") && rcedit_path.is_empty()) {
 		err += TTR("The rcedit tool must be configured in the Editor Settings (Export > Windows > rcedit) to change the icon or app information data.") + "\n";
@@ -769,7 +792,7 @@ bool EditorExportPlatformWindows::has_valid_export_configuration(const Ref<Edito
 }
 
 bool EditorExportPlatformWindows::has_valid_project_configuration(const Ref<EditorExportPreset> &p_preset, String &r_error) const {
-	String err = "";
+	String err;
 	bool valid = true;
 
 	List<ExportOption> options;
@@ -793,6 +816,43 @@ bool EditorExportPlatformWindows::has_valid_project_configuration(const Ref<Edit
 	return valid;
 }
 
+String EditorExportPlatformWindows::_get_exe_arch(const String &p_path) const {
+	Ref<FileAccess> f = FileAccess::open(p_path, FileAccess::READ);
+	if (f.is_null()) {
+		return "invalid";
+	}
+
+	// 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) {
+			return "invalid";
+		}
+	}
+
+	// Process header.
+	uint16_t machine = f->get_16();
+	f->close();
+
+	switch (machine) {
+		case 0x014c:
+			return "x86_32";
+		case 0x8664:
+			return "x86_64";
+		case 0x01c0:
+		case 0x01c4:
+			return "arm32";
+		case 0xaa64:
+			return "arm64";
+		default:
+			return "unknown";
+	}
+}
+
 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
 

+ 2 - 0
platform/windows/export/export_plugin.h

@@ -73,6 +73,8 @@ class EditorExportPlatformWindows : public EditorExportPlatformPC {
 	Error _rcedit_add_data(const Ref<EditorExportPreset> &p_preset, const String &p_path, bool p_console_icon);
 	Error _code_sign(const Ref<EditorExportPreset> &p_preset, const String &p_path);
 
+	String _get_exe_arch(const String &p_path) const;
+
 public:
 	virtual Error export_project(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags = 0) override;
 	virtual Error modify_template(const Ref<EditorExportPreset> &p_preset, bool p_debug, const String &p_path, int p_flags) override;