diff options
author | Ignacio Roldán Etcheverry <neikeq@users.noreply.github.com> | 2020-05-10 13:33:03 +0200 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-05-10 13:33:03 +0200 |
commit | 54b20a25b90c8c8d8dfd7f68d66d0ec57c71435f (patch) | |
tree | ed0fd3e030e6f65568f664bc9f5d2bb028f37618 /modules/mono/mono_gd | |
parent | da898c116c0b45ff0dc16e80800f8694339cd4f1 (diff) | |
parent | 3ce09246d10a267bf00ae8bf37068ec458c69287 (diff) |
Merge pull request #38600 from neikeq/no
Switch to nuget Microsoft.Build and rewrite GodotTools messasing protocol
Diffstat (limited to 'modules/mono/mono_gd')
-rw-r--r-- | modules/mono/mono_gd/gd_mono.cpp | 35 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono.h | 1 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.cpp | 71 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_assembly.h | 6 | ||||
-rw-r--r-- | modules/mono/mono_gd/gd_mono_log.cpp | 2 |
5 files changed, 84 insertions, 31 deletions
diff --git a/modules/mono/mono_gd/gd_mono.cpp b/modules/mono/mono_gd/gd_mono.cpp index 3298c5da4c..fbaa81e83f 100644 --- a/modules/mono/mono_gd/gd_mono.cpp +++ b/modules/mono/mono_gd/gd_mono.cpp @@ -133,6 +133,10 @@ void gd_mono_debug_init() { CharString da_args = OS::get_singleton()->get_environment("GODOT_MONO_DEBUGGER_AGENT").utf8(); + if (da_args.length()) { + OS::get_singleton()->set_environment("GODOT_MONO_DEBUGGER_AGENT", String()); + } + #ifdef TOOLS_ENABLED int da_port = GLOBAL_DEF("mono/debugger_agent/port", 23685); bool da_suspend = GLOBAL_DEF("mono/debugger_agent/wait_for_debugger", false); @@ -515,8 +519,8 @@ void GDMono::add_assembly(uint32_t p_domain_id, GDMonoAssembly *p_assembly) { GDMonoAssembly *GDMono::get_loaded_assembly(const String &p_name) { - if (p_name == "mscorlib") - return get_corlib_assembly(); + if (p_name == "mscorlib" && corlib_assembly) + return corlib_assembly; MonoDomain *domain = mono_domain_get(); uint32_t domain_id = domain ? mono_domain_get_id(domain) : 0; @@ -526,7 +530,9 @@ GDMonoAssembly *GDMono::get_loaded_assembly(const String &p_name) { bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly) { +#ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); +#endif MonoAssemblyName *aname = mono_assembly_name_new(p_name.utf8()); bool result = load_assembly(p_name, aname, r_assembly, p_refonly); @@ -538,26 +544,27 @@ bool GDMono::load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bo bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly) { +#ifdef DEBUG_ENABLED CRASH_COND(!r_assembly); +#endif - print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); + return load_assembly(p_name, p_aname, r_assembly, p_refonly, GDMonoAssembly::get_default_search_dirs()); +} - MonoImageOpenStatus status = MONO_IMAGE_OK; - MonoAssembly *assembly = mono_assembly_load_full(p_aname, nullptr, &status, p_refonly); +bool GDMono::load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly, const Vector<String> &p_search_dirs) { - if (!assembly) - return false; - - ERR_FAIL_COND_V(status != MONO_IMAGE_OK, false); +#ifdef DEBUG_ENABLED + CRASH_COND(!r_assembly); +#endif - uint32_t domain_id = mono_domain_get_id(mono_domain_get()); + print_verbose("Mono: Loading assembly " + p_name + (p_refonly ? " (refonly)" : "") + "..."); - GDMonoAssembly **stored_assembly = assemblies[domain_id].getptr(p_name); + GDMonoAssembly *assembly = GDMonoAssembly::load(p_name, p_aname, p_refonly, p_search_dirs); - ERR_FAIL_COND_V(stored_assembly == nullptr, false); - ERR_FAIL_COND_V((*stored_assembly)->get_assembly() != assembly, false); + if (!assembly) + return false; - *r_assembly = *stored_assembly; + *r_assembly = assembly; print_verbose("Mono: Assembly " + p_name + (p_refonly ? " (refonly)" : "") + " loaded from path: " + (*r_assembly)->get_path()); diff --git a/modules/mono/mono_gd/gd_mono.h b/modules/mono/mono_gd/gd_mono.h index 4898833e8e..153ae891f7 100644 --- a/modules/mono/mono_gd/gd_mono.h +++ b/modules/mono/mono_gd/gd_mono.h @@ -241,6 +241,7 @@ public: bool load_assembly(const String &p_name, GDMonoAssembly **r_assembly, bool p_refonly = false); bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly = false); + bool load_assembly(const String &p_name, MonoAssemblyName *p_aname, GDMonoAssembly **r_assembly, bool p_refonly, const Vector<String> &p_search_dirs); bool load_assembly_from(const String &p_name, const String &p_path, GDMonoAssembly **r_assembly, bool p_refonly = false); Error finalize_and_unload_domain(MonoDomain *p_domain); diff --git a/modules/mono/mono_gd/gd_mono_assembly.cpp b/modules/mono/mono_gd/gd_mono_assembly.cpp index 0f211eebc6..da2ed2a7fc 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.cpp +++ b/modules/mono/mono_gd/gd_mono_assembly.cpp @@ -33,6 +33,7 @@ #include <mono/metadata/mono-debug.h> #include <mono/metadata/tokentype.h> +#include "core/io/file_access_pack.h" #include "core/list.h" #include "core/os/file_access.h" #include "core/os/os.h" @@ -99,7 +100,7 @@ void GDMonoAssembly::fill_search_dirs(Vector<String> &r_search_dirs, const Strin // - The 'load' hook is called after the assembly has been loaded. Its job is to add the // assembly to the list of loaded assemblies so that the 'search' hook can look it up. -void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, void *user_data) { +void GDMonoAssembly::assembly_load_hook(MonoAssembly *assembly, [[maybe_unused]] void *user_data) { String name = String::utf8(mono_assembly_name_get_name(mono_assembly_get_name(assembly))); @@ -133,9 +134,7 @@ MonoAssembly *GDMonoAssembly::assembly_refonly_preload_hook(MonoAssemblyName *an return GDMonoAssembly::_preload_hook(aname, assemblies_path, user_data, true); } -MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly) { - - (void)user_data; // UNUSED +MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, [[maybe_unused]] void *user_data, bool refonly) { String name = String::utf8(mono_assembly_name_get_name(aname)); bool has_extension = name.ends_with(".dll") || name.ends_with(".exe"); @@ -147,15 +146,13 @@ MonoAssembly *GDMonoAssembly::_search_hook(MonoAssemblyName *aname, void *user_d return nullptr; } -MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, void *user_data, bool refonly) { - - (void)user_data; // UNUSED +MonoAssembly *GDMonoAssembly::_preload_hook(MonoAssemblyName *aname, char **, [[maybe_unused]] void *user_data, bool refonly) { String name = String::utf8(mono_assembly_name_get_name(aname)); - return _load_assembly_search(name, search_dirs, refonly); + return _load_assembly_search(name, aname, refonly, search_dirs); } -MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly) { +MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) { MonoAssembly *res = nullptr; String path; @@ -168,21 +165,21 @@ MonoAssembly *GDMonoAssembly::_load_assembly_search(const String &p_name, const if (has_extension) { path = search_dir.plus_file(p_name); if (FileAccess::exists(path)) { - res = _real_load_assembly_from(path, p_refonly); + res = _real_load_assembly_from(path, p_refonly, p_aname); if (res != nullptr) return res; } } else { path = search_dir.plus_file(p_name + ".dll"); if (FileAccess::exists(path)) { - res = _real_load_assembly_from(path, p_refonly); + res = _real_load_assembly_from(path, p_refonly, p_aname); if (res != nullptr) return res; } path = search_dir.plus_file(p_name + ".exe"); if (FileAccess::exists(path)) { - res = _real_load_assembly_from(path, p_refonly); + res = _real_load_assembly_from(path, p_refonly, p_aname); if (res != nullptr) return res; } @@ -230,7 +227,7 @@ void GDMonoAssembly::initialize() { mono_install_assembly_load_hook(&assembly_load_hook, nullptr); } -MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, bool p_refonly) { +MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, bool p_refonly, MonoAssemblyName *p_aname) { Vector<uint8_t> data = FileAccess::get_file_as_array(p_path); ERR_FAIL_COND_V_MSG(data.empty(), nullptr, "Could read the assembly in the specified location"); @@ -255,7 +252,33 @@ MonoAssembly *GDMonoAssembly::_real_load_assembly_from(const String &p_path, boo true, &status, p_refonly, image_filename.utf8()); - ERR_FAIL_COND_V_MSG(status != MONO_IMAGE_OK || !image, nullptr, "Failed to open assembly image from the loaded data"); + ERR_FAIL_COND_V_MSG(status != MONO_IMAGE_OK || !image, nullptr, "Failed to open assembly image from memory: '" + p_path + "'."); + + if (p_aname != nullptr) { + // Check assembly version + const MonoTableInfo *table = mono_image_get_table_info(image, MONO_TABLE_ASSEMBLY); + + ERR_FAIL_NULL_V(table, nullptr); + + if (mono_table_info_get_rows(table)) { + uint32_t cols[MONO_ASSEMBLY_SIZE]; + mono_metadata_decode_row(table, 0, cols, MONO_ASSEMBLY_SIZE); + + // Not sure about .NET's policy. We will only ensure major and minor are equal, and ignore build and revision. + uint16_t major = cols[MONO_ASSEMBLY_MAJOR_VERSION]; + uint16_t minor = cols[MONO_ASSEMBLY_MINOR_VERSION]; + + uint16_t required_minor; + uint16_t required_major = mono_assembly_name_get_version(p_aname, &required_minor, nullptr, nullptr); + + if (required_major != 0) { + if (major != required_major && minor != required_minor) { + mono_image_close(image); + return nullptr; + } + } + } + } #ifdef DEBUG_ENABLED Vector<uint8_t> pdb_data; @@ -425,6 +448,26 @@ GDMonoClass *GDMonoAssembly::get_object_derived_class(const StringName &p_class) return match; } +GDMonoAssembly *GDMonoAssembly::load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs) { + + if (GDMono::get_singleton()->get_corlib_assembly() && (p_name == "mscorlib" || p_name == "mscorlib.dll")) + return GDMono::get_singleton()->get_corlib_assembly(); + + // We need to manually call the search hook in this case, as it won't be called in the next step + MonoAssembly *assembly = mono_assembly_invoke_search_hook(p_aname); + + if (!assembly) { + assembly = _load_assembly_search(p_name, p_aname, p_refonly, p_search_dirs); + ERR_FAIL_NULL_V(assembly, nullptr); + } + + GDMonoAssembly *loaded_asm = GDMono::get_singleton()->get_loaded_assembly(p_name); + ERR_FAIL_NULL_V_MSG(loaded_asm, nullptr, "Loaded assembly missing from table. Did we not receive the load hook?"); + ERR_FAIL_COND_V(loaded_asm->get_assembly() != assembly, nullptr); + + return loaded_asm; +} + GDMonoAssembly *GDMonoAssembly::load_from(const String &p_name, const String &p_path, bool p_refonly) { if (p_name == "mscorlib" || p_name == "mscorlib.dll") diff --git a/modules/mono/mono_gd/gd_mono_assembly.h b/modules/mono/mono_gd/gd_mono_assembly.h index 43c8225b74..7fc1817993 100644 --- a/modules/mono/mono_gd/gd_mono_assembly.h +++ b/modules/mono/mono_gd/gd_mono_assembly.h @@ -93,8 +93,8 @@ class GDMonoAssembly { static MonoAssembly *_search_hook(MonoAssemblyName *aname, void *user_data, bool refonly); static MonoAssembly *_preload_hook(MonoAssemblyName *aname, char **assemblies_path, void *user_data, bool refonly); - static MonoAssembly *_real_load_assembly_from(const String &p_path, bool p_refonly); - static MonoAssembly *_load_assembly_search(const String &p_name, const Vector<String> &p_search_dirs, bool p_refonly); + static MonoAssembly *_real_load_assembly_from(const String &p_path, bool p_refonly, MonoAssemblyName *p_aname = nullptr); + static MonoAssembly *_load_assembly_search(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs); friend class GDMono; static void initialize(); @@ -120,7 +120,9 @@ public: static String find_assembly(const String &p_name); static void fill_search_dirs(Vector<String> &r_search_dirs, const String &p_custom_config = String(), const String &p_custom_bcl_dir = String()); + static const Vector<String> &get_default_search_dirs() { return search_dirs; } + static GDMonoAssembly *load(const String &p_name, MonoAssemblyName *p_aname, bool p_refonly, const Vector<String> &p_search_dirs); static GDMonoAssembly *load_from(const String &p_name, const String &p_path, bool p_refonly); GDMonoAssembly(const String &p_name, MonoImage *p_image, MonoAssembly *p_assembly); diff --git a/modules/mono/mono_gd/gd_mono_log.cpp b/modules/mono/mono_gd/gd_mono_log.cpp index ca16c2b76a..b56350ae1b 100644 --- a/modules/mono/mono_gd/gd_mono_log.cpp +++ b/modules/mono/mono_gd/gd_mono_log.cpp @@ -175,7 +175,7 @@ void GDMonoLog::initialize() { log_level_id = get_log_level_id(log_level.get_data()); if (log_file) { - OS::get_singleton()->print("Mono: Logfile is: %s\n", log_file_path.utf8().get_data()); + OS::get_singleton()->print("Mono: Log file is: '%s'\n", log_file_path.utf8().get_data()); mono_trace_set_log_handler(mono_log_callback, this); } else { OS::get_singleton()->printerr("Mono: No log file, using default log handler\n"); |