From e957f4dcebfac954f9d481050a491c278888c68d Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Thu, 21 Mar 2024 12:28:17 -0400 Subject: [PATCH 01/11] Messing around with extending host_runtime_contract --- src/coreclr/hosts/corerun/corerun.cpp | 1 + src/coreclr/inc/hostinformation.h | 1 + src/coreclr/vm/hostinformation.cpp | 8 +++++ src/native/corehost/host_runtime_contract.h | 29 +++++++++++++++++++ .../hostpolicy/hostpolicy_context.cpp | 14 +++++++++ .../corehost/hostpolicy/hostpolicy_context.h | 1 + 6 files changed, 54 insertions(+) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 4e506b95c9746b..ed585648d4cae8 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -374,6 +374,7 @@ static int run(const configuration& config) (void*)&config, &get_runtime_property, nullptr, + nullptr, nullptr }; propertyKeys.push_back(HOST_PROPERTY_RUNTIME_CONTRACT); std::stringstream ss; diff --git a/src/coreclr/inc/hostinformation.h b/src/coreclr/inc/hostinformation.h index d57b4729d30e68..ae95ba308be443 100644 --- a/src/coreclr/inc/hostinformation.h +++ b/src/coreclr/inc/hostinformation.h @@ -11,6 +11,7 @@ class HostInformation public: static void SetContract(_In_ host_runtime_contract* hostContract); static bool GetProperty(_In_z_ const char* name, SString& value); + static bool GetProbingProperties(probing_path_properties* props); }; #endif // _HOSTINFORMATION_H_ diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index b440f6f2168ab7..a790a6827ad5ed 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -40,3 +40,11 @@ bool HostInformation::GetProperty(_In_z_ const char* name, SString& value) return lenActual > 0 && lenActual <= len; } + +bool HostInformation::GetProbingProperties(probing_path_properties* props) +{ + if (s_hostContract == nullptr || s_hostContract->get_runtime_property == nullptr) + return false; + + return s_hostContract->get_probing_path_properties(props, s_hostContract->context); +} diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 7806e5ae345969..33bdfd7099eb9f 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -23,6 +23,29 @@ #define HOST_PROPERTY_PLATFORM_RESOURCE_ROOTS "PLATFORM_RESOURCE_ROOTS" #define HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES "TRUSTED_PLATFORM_ASSEMBLIES" +struct trusted_platform_assemblies +{ + uint32_t assembly_count; + char** basenames; /* Foo.dll */ + uint32_t* basename_length; + char** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ +}; + +struct probing_lookup_paths +{ + uint32_t dir_count; + char** dirs; +}; + +struct probing_path_properties +{ + size_t size; + + trusted_platform_assemblies trusted_platform_assemblies; + probing_lookup_paths native_dll_search_directories; + probing_lookup_paths platform_resource_roots; +}; + struct host_runtime_contract { size_t size; @@ -51,6 +74,12 @@ struct host_runtime_contract const void* (HOST_CONTRACT_CALLTYPE* pinvoke_override)( const char* library_name, const char* entry_point_name); + + // Populates the structure containing the list of values for each probing path property + // Returns true if found, false otherwise + bool(HOST_CONTRACT_CALLTYPE* get_probing_path_properties)( + /*out*/ probing_path_properties* props, + void* contract_context); }; #endif // __HOST_RUNTIME_CONTRACT_H__ diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index 1a1f63dae073c4..3c385d1d76a1fa 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -133,6 +133,17 @@ namespace return -1; } + + bool HOST_CONTRACT_CALLTYPE get_probing_path_properties( + probing_path_properties* props, + void* contract_context) + { + hostpolicy_context_t* context = static_cast(contract_context); + + // do we need to copy this instead of referring? + props = &context->probing_path_properties; + return true; + } } bool hostpolicy_context_t::should_read_rid_fallback_graph(const hostpolicy_init_t &init) @@ -273,6 +284,8 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c // Build properties for CoreCLR instantiation pal::string_t app_base; resolver.get_app_dir(&app_base); + + // populate probing path properties struct here.... coreclr_properties.add(common_property::TrustedPlatformAssemblies, probe_paths.tpa.c_str()); coreclr_properties.add(common_property::NativeDllSearchDirectories, probe_paths.native.c_str()); coreclr_properties.add(common_property::PlatformResourceRoots, probe_paths.resources.c_str()); @@ -340,6 +353,7 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c } host_contract.get_runtime_property = &get_runtime_property; + host_contract.get_probing_path_properties = &get_probing_path_properties; pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), buffer)) diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.h b/src/native/corehost/hostpolicy/hostpolicy_context.h index a7d8faf6f7a6f3..8979ba228da781 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.h +++ b/src/native/corehost/hostpolicy/hostpolicy_context.h @@ -25,6 +25,7 @@ struct hostpolicy_context_t mutable std::unordered_set breadcrumbs; coreclr_property_bag_t coreclr_properties; + probing_path_properties probing_path_properties; std::unique_ptr coreclr; From bb99691e96f306d698876cc526c2c9182ebd9d04 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Thu, 28 Mar 2024 10:05:32 -0700 Subject: [PATCH 02/11] Update the host_runtime_contract to contain entry assembly and probing path fields. Modified the host to read the values into these structures --- src/coreclr/hosts/corerun/corerun.cpp | 67 +++++++++++++++---- src/coreclr/inc/hostinformation.h | 1 - src/coreclr/vm/hostinformation.cpp | 8 --- src/native/corehost/host_runtime_contract.h | 19 ++---- .../corehost/hostpolicy/deps_resolver.cpp | 59 +++++++++++++--- .../corehost/hostpolicy/deps_resolver.h | 4 ++ src/native/corehost/hostpolicy/hostpolicy.cpp | 9 ++- .../hostpolicy/hostpolicy_context.cpp | 60 +++++++---------- 8 files changed, 148 insertions(+), 79 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index ed585648d4cae8..5332d85115d1a5 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -9,6 +9,8 @@ #include "dotenv.hpp" #include +#include +#include using char_t = pal::char_t; using string_t = pal::string_t; @@ -101,7 +103,7 @@ static void wait_for_debugger() // (for example, ni's may be preferred over il, even if they appear later). Therefore, when building // the TPA only include the first instance of a simple assembly name to allow users the opportunity to // override Framework assemblies by placing dlls in %CORE_LIBRARIES%. -static string_t build_tpa(const string_t& core_root, const string_t& core_libraries) +static string_t build_tpa(const string_t& core_root, const string_t& core_libraries, trusted_platform_assemblies* tpa_items) { static const char_t* const tpa_extensions[] = { @@ -112,7 +114,7 @@ static string_t build_tpa(const string_t& core_root, const string_t& core_librar nullptr }; - std::set name_set; + std::unordered_map name_path_map; pal::stringstream_t tpa_list; // Iterate over all extensions. @@ -131,13 +133,14 @@ static string_t build_tpa(const string_t& core_root, const string_t& core_librar string_t tmp = pal::build_file_list(dir, ext, [&](const char_t* file) { string_t file_local{ file }; + string_t file_name { file }; // Strip the extension. if (pal::string_ends_with(file_local, ext_len, ext)) - file_local = file_local.substr(0, file_local.length() - ext_len); + file_name = file_local.substr(0, file_local.length() - ext_len); // Return true if the file is new. - return name_set.insert(file_local).second; + return name_path_map.insert({file_name, file_local}).second; }); // Add to the TPA. @@ -145,6 +148,26 @@ static string_t build_tpa(const string_t& core_root, const string_t& core_librar } } + tpa_items->assembly_count = static_cast(name_path_map.size()); + tpa_items->assembly_filepaths = new char_t*[tpa_items->assembly_count]; + tpa_items->basenames = new char_t*[tpa_items->assembly_count]; + + // Convert the paths into a string and return it + int32_t item_count = 0; + for (auto item = name_path_map.begin(); item != name_path_map.end(); ++item) + { + string_t base_name = item->first; + size_t base_length = base_name.size() + 1; + size_t assembly_name_length = item->second.size() + 1; + + tpa_items->basenames[item_count] = new char_t[base_length]; + tpa_items->assembly_filepaths[item_count] = new char_t[assembly_name_length]; + wcscpy_s(tpa_items->basenames[item_count], base_length, base_name.c_str()); + wcscpy_s(tpa_items->assembly_filepaths[item_count], assembly_name_length, item->second.c_str()); + + item_count++; + } + return tpa_list.str(); } @@ -247,6 +270,16 @@ static int run(const configuration& config) // Check if debugger attach scenario was requested. if (config.wait_to_debug) wait_for_debugger(); + + host_runtime_contract host_contract; + host_contract.size = sizeof(host_runtime_contract); + host_contract.context = (void*)&config; + host_contract.get_runtime_property = &get_runtime_property; + host_contract.bundle_probe = nullptr; + host_contract.pinvoke_override = nullptr; + + host_contract.entry_assembly = new char_t[config.entry_assembly_fullpath.size() + 1]; + wcscpy_s(host_contract.entry_assembly, config.entry_assembly_fullpath.size() + 1, config.entry_assembly_fullpath.c_str()); config.dotenv_configuration.load_into_current_process(); @@ -262,6 +295,9 @@ static int run(const configuration& config) // Accumulate path for native search path. pal::stringstream_t native_search_dirs; + std::set native_search_dirs_set; + + native_search_dirs_set.insert(app_path); native_search_dirs << app_path << pal::env_path_delim; // CORE_LIBRARIES @@ -269,6 +305,7 @@ static int run(const configuration& config) if (!core_libs.empty() && core_libs != app_path) { pal::ensure_trailing_delimiter(core_libs); + native_search_dirs_set.insert(core_libs); native_search_dirs << core_libs << pal::env_path_delim; } @@ -290,10 +327,23 @@ static int run(const configuration& config) else { pal::ensure_trailing_delimiter(core_root); + native_search_dirs_set.insert(core_root); native_search_dirs << core_root << pal::env_path_delim; } - string_t tpa_list = build_tpa(core_root, core_libs); + string_t tpa_list = build_tpa(core_root, core_libs, &host_contract.probing_paths.trusted_platform_assemblies); + probing_lookup_paths* native_paths = &host_contract.probing_paths.native_dll_search_directories; + + native_paths->dir_count = static_cast(native_search_dirs_set.size()); + native_paths->dirs = new char_t*[native_paths->dir_count]; + + int dir_count = 0; + for (const auto& native_dir : native_search_dirs_set) + { + native_paths->dirs[dir_count] = new char_t[native_dir.size() + 1]; + wcscpy_s(native_paths->dirs[dir_count], native_dir.size() + 1, native_dir.c_str()); + } + { // Load hostpolicy if requested. @@ -369,13 +419,6 @@ static int run(const configuration& config) for (const pal::string_utf8_t& str : user_defined_values_utf8) propertyValues.push_back(str.c_str()); - host_runtime_contract host_contract = { - sizeof(host_runtime_contract), - (void*)&config, - &get_runtime_property, - nullptr, - nullptr, - nullptr }; propertyKeys.push_back(HOST_PROPERTY_RUNTIME_CONTRACT); std::stringstream ss; ss << "0x" << std::hex << (size_t)(&host_contract); diff --git a/src/coreclr/inc/hostinformation.h b/src/coreclr/inc/hostinformation.h index ae95ba308be443..d57b4729d30e68 100644 --- a/src/coreclr/inc/hostinformation.h +++ b/src/coreclr/inc/hostinformation.h @@ -11,7 +11,6 @@ class HostInformation public: static void SetContract(_In_ host_runtime_contract* hostContract); static bool GetProperty(_In_z_ const char* name, SString& value); - static bool GetProbingProperties(probing_path_properties* props); }; #endif // _HOSTINFORMATION_H_ diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index a790a6827ad5ed..b440f6f2168ab7 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -40,11 +40,3 @@ bool HostInformation::GetProperty(_In_z_ const char* name, SString& value) return lenActual > 0 && lenActual <= len; } - -bool HostInformation::GetProbingProperties(probing_path_properties* props) -{ - if (s_hostContract == nullptr || s_hostContract->get_runtime_property == nullptr) - return false; - - return s_hostContract->get_probing_path_properties(props, s_hostContract->context); -} diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 33bdfd7099eb9f..9a60ab17531936 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -26,21 +26,18 @@ struct trusted_platform_assemblies { uint32_t assembly_count; - char** basenames; /* Foo.dll */ - uint32_t* basename_length; - char** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ + wchar_t** basenames; /* Foo.dll */ + wchar_t** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ }; struct probing_lookup_paths { uint32_t dir_count; - char** dirs; + wchar_t** dirs; }; struct probing_path_properties { - size_t size; - trusted_platform_assemblies trusted_platform_assemblies; probing_lookup_paths native_dll_search_directories; probing_lookup_paths platform_resource_roots; @@ -53,6 +50,10 @@ struct host_runtime_contract // Context for the contract. Pass to functions taking a contract context. void* context; + wchar_t* entry_assembly; + + probing_path_properties probing_paths; + // Get the value of a runtime property. // Returns the length of the property including a terminating null or -1 if not found. size_t(HOST_CONTRACT_CALLTYPE* get_runtime_property)( @@ -74,12 +75,6 @@ struct host_runtime_contract const void* (HOST_CONTRACT_CALLTYPE* pinvoke_override)( const char* library_name, const char* entry_point_name); - - // Populates the structure containing the list of values for each probing path property - // Returns true if found, false otherwise - bool(HOST_CONTRACT_CALLTYPE* get_probing_path_properties)( - /*out*/ probing_path_properties* props, - void* contract_context); }; #endif // __HOST_RUNTIME_CONTRACT_H__ diff --git a/src/native/corehost/hostpolicy/deps_resolver.cpp b/src/native/corehost/hostpolicy/deps_resolver.cpp index 8bab2fa1d79f90..15c7dacde1bebc 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.cpp +++ b/src/native/corehost/hostpolicy/deps_resolver.cpp @@ -2,16 +2,20 @@ // The .NET Foundation licenses this file to you under the MIT license. #include +#include #include #include #include +#include #include "deps_entry.h" #include "deps_format.h" #include "deps_resolver.h" + #include "shared_store.h" #include #include +#include namespace { @@ -42,6 +46,7 @@ namespace deps_entry_t::asset_types asset_type, const pal::string_t& path, std::unordered_set* existing, + std::deque* items, pal::string_t* serviced, pal::string_t* non_serviced, const pal::string_t& svc_dir) @@ -56,13 +61,16 @@ namespace trace::verbose(_X("Adding to %s path: %s"), deps_entry_t::s_known_asset_types[asset_type], path.c_str()); + // serviced paths come before non-serviced paths. if (utils::starts_with(path, svc_dir.c_str(), svc_dir.length(), false)) { + items->push_front(path); serviced->append(path); serviced->push_back(PATH_SEPARATOR); } else { + items->push_back(path); non_serviced->append(path); non_serviced->push_back(PATH_SEPARATOR); } @@ -412,6 +420,7 @@ bool report_missing_assembly_in_manifest(const deps_entry_t& entry, bool continu */ bool deps_resolver_t::resolve_tpa_list( pal::string_t* output, + trusted_platform_assemblies* tpa_list, std::unordered_set* breadcrumb, bool ignore_missing_assemblies) { @@ -581,11 +590,26 @@ bool deps_resolver_t::resolve_tpa_list( } } + tpa_list->assembly_count = static_cast(items.size()); + tpa_list->assembly_filepaths = new pal::char_t*[tpa_list->assembly_count]; + tpa_list->basenames = new pal::char_t*[tpa_list->assembly_count]; + // Convert the paths into a string and return it - for (const auto& item : items) + int32_t item_count = 0; + for (auto item = items.begin(); item != items.end(); ++item) { - output->append(item.second.resolved_path); + pal::string_t base_name = get_filename(item->second.resolved_path); + size_t base_length = base_name.size() + 1; + size_t assembly_name_length = item->second.resolved_path.size() + 1; + + tpa_list->basenames[item_count] = new pal::char_t[base_length]; + tpa_list->assembly_filepaths[item_count] = new pal::char_t[assembly_name_length]; + wcscpy_s(tpa_list->basenames[item_count], base_length, base_name.c_str()); + wcscpy_s(tpa_list->assembly_filepaths[item_count], assembly_name_length, item->second.resolved_path.c_str()); + + output->append(item->second.resolved_path); output->push_back(PATH_SEPARATOR); + item_count++; } return true; @@ -746,6 +770,7 @@ void deps_resolver_t::enum_app_context_deps_files(std::function* breadcrumb) { bool is_resources = asset_type == deps_entry_t::asset_types::resources; @@ -763,6 +788,9 @@ bool deps_resolver_t::resolve_probe_dirs( // Action for post processing the resolved path std::function& action = is_resources ? resources : native; + // Set to track the entries in probing_lookup_paths + std::deque probing_items; + // Set for de-duplication std::unordered_set items; @@ -802,7 +830,7 @@ bool deps_resolver_t::resolve_probe_dirs( if (!found_in_bundle) { init_known_entry_path(entry, candidate); - add_unique_path(asset_type, action(candidate), &items, output, &non_serviced, core_servicing); + add_unique_path(asset_type, action(candidate), &items, &probing_items, output, &non_serviced, core_servicing); } } else @@ -834,7 +862,7 @@ bool deps_resolver_t::resolve_probe_dirs( if (!get_app_deps().exists()) { // App local path - add_unique_path(asset_type, m_app_dir, &items, output, &non_serviced, core_servicing); + add_unique_path(asset_type, m_app_dir, &items, &probing_items, output, &non_serviced, core_servicing); // deps_resolver treats being able to get the coreclr path as optional, so we ignore the return value here. // The caller is responsible for checking whether coreclr path is set and handling as appropriate. @@ -872,15 +900,26 @@ bool deps_resolver_t::resolve_probe_dirs( if (bundle::info_t::is_single_file_bundle() && !is_resources) { auto bundle = bundle::runner_t::app(); - add_unique_path(asset_type, bundle->base_path(), &items, output, &non_serviced, core_servicing); + add_unique_path(asset_type, bundle->base_path(), &items, &probing_items, output, &non_serviced, core_servicing); // Add the extraction path if it exists. if (pal::directory_exists(bundle->extraction_path())) { - add_unique_path(asset_type, bundle->extraction_path(), &items, output, &non_serviced, core_servicing); + add_unique_path(asset_type, bundle->extraction_path(), &items, &probing_items, output, &non_serviced, core_servicing); } } + // Add the probing paths to piece of the host_runtime_contract + probing_paths->dir_count = static_cast(probing_items.size()); + probing_paths->dirs = new pal::char_t*[probing_paths->dir_count]; + + int dir_count = 0; + for (const auto& probing_item : probing_items) + { + probing_paths->dirs[dir_count] = new pal::char_t[probing_item.size() + 1]; + wcscpy_s(probing_paths->dirs[dir_count], probing_item.size() + 1, probing_item.c_str()); + } + output->append(non_serviced); return true; @@ -898,19 +937,19 @@ bool deps_resolver_t::resolve_probe_dirs( // instead such entry will simply be ignored. // // -bool deps_resolver_t::resolve_probe_paths(probe_paths_t* probe_paths, std::unordered_set* breadcrumb, bool ignore_missing_assemblies) +bool deps_resolver_t::resolve_probe_paths(probe_paths_t* probe_paths, host_runtime_contract* host_contract, std::unordered_set* breadcrumb, bool ignore_missing_assemblies) { - if (!resolve_tpa_list(&probe_paths->tpa, breadcrumb, ignore_missing_assemblies)) + if (!resolve_tpa_list(&probe_paths->tpa, &host_contract->probing_paths.trusted_platform_assemblies, breadcrumb, ignore_missing_assemblies)) { return false; } - if (!resolve_probe_dirs(deps_entry_t::asset_types::native, &probe_paths->native, breadcrumb)) + if (!resolve_probe_dirs(deps_entry_t::asset_types::native, &probe_paths->native, &host_contract->probing_paths.native_dll_search_directories, breadcrumb)) { return false; } - if (!resolve_probe_dirs(deps_entry_t::asset_types::resources, &probe_paths->resources, breadcrumb)) + if (!resolve_probe_dirs(deps_entry_t::asset_types::resources, &probe_paths->resources, &host_contract->probing_paths.platform_resource_roots, breadcrumb)) { return false; } diff --git a/src/native/corehost/hostpolicy/deps_resolver.h b/src/native/corehost/hostpolicy/deps_resolver.h index 2a971ef0cfc33f..60d131c4479fdd 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.h +++ b/src/native/corehost/hostpolicy/deps_resolver.h @@ -14,6 +14,7 @@ #include "deps_entry.h" #include "runtime_config.h" #include "bundle/runner.h" +#include // Probe paths to be resolved for ordering struct probe_paths_t @@ -129,6 +130,7 @@ class deps_resolver_t bool resolve_probe_paths( probe_paths_t* probe_paths, + host_runtime_contract* host_contract, std::unordered_set* breadcrumb, bool ignore_missing_assemblies = false); @@ -208,6 +210,7 @@ class deps_resolver_t // Resolve order for TPA lookup. bool resolve_tpa_list( pal::string_t* output, + trusted_platform_assemblies* tpa_list, std::unordered_set* breadcrumb, bool ignore_missing_assemblies); @@ -215,6 +218,7 @@ class deps_resolver_t bool resolve_probe_dirs( deps_entry_t::asset_types asset_type, pal::string_t* output, + probing_lookup_paths* probing_paths, std::unordered_set* breadcrumb); // Probe entry in probe configurations and deps dir. diff --git a/src/native/corehost/hostpolicy/hostpolicy.cpp b/src/native/corehost/hostpolicy/hostpolicy.cpp index a50069fbb3782e..abf4ca9ed7a41d 100644 --- a/src/native/corehost/hostpolicy/hostpolicy.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy.cpp @@ -971,8 +971,15 @@ SHARED_API int HOSTPOLICY_CALLTYPE corehost_resolve_component_dependencies( // Don't write breadcrumbs since we're not executing the app, just resolving dependencies // doesn't guarantee that they will actually execute. + const std::shared_ptr context = get_hostpolicy_context(/*require_runtime*/ true); + if (context == nullptr) + { + trace::error(_X("Trying to get host_runtime_contract, but hostpolicy has not been initialized")); + return StatusCode::HostInvalidState; + } + probe_paths_t probe_paths; - if (!resolver.resolve_probe_paths(&probe_paths, nullptr, /* ignore_missing_assemblies */ true)) + if (!resolver.resolve_probe_paths(&probe_paths, &context->host_contract, nullptr, /* ignore_missing_assemblies */ true)) { return StatusCode::ResolverResolveFailure; } diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index 3c385d1d76a1fa..ff2f69471872ec 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -133,17 +133,6 @@ namespace return -1; } - - bool HOST_CONTRACT_CALLTYPE get_probing_path_properties( - probing_path_properties* props, - void* contract_context) - { - hostpolicy_context_t* context = static_cast(contract_context); - - // do we need to copy this instead of referring? - props = &context->probing_path_properties; - return true; - } } bool hostpolicy_context_t::should_read_rid_fallback_graph(const hostpolicy_init_t &init) @@ -189,6 +178,29 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c return StatusCode::ResolverInitFailure; } + { + host_contract = { sizeof(host_runtime_contract), this }; + if (bundle::info_t::is_single_file_bundle()) + { + host_contract.bundle_probe = &bundle_probe; +#if defined(NATIVE_LIBS_EMBEDDED) + host_contract.pinvoke_override = &pinvoke_override; +#endif + } + + host_contract.entry_assembly = new pal::char_t[application.size() + 1]; + wcscpy_s(host_contract.entry_assembly, application.size() + 1, application.c_str()); + + host_contract.get_runtime_property = &get_runtime_property; + pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; + pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); + if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), buffer)) + { + log_duplicate_property_error(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT)); + return StatusCode::LibHostDuplicateProperty; + } + } + probe_paths_t probe_paths; // Setup breadcrumbs. @@ -201,14 +213,14 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c breadcrumbs.insert(policy_name); breadcrumbs.insert(policy_name + _X(",") + policy_version); - if (!resolver.resolve_probe_paths(&probe_paths, &breadcrumbs)) + if (!resolver.resolve_probe_paths(&probe_paths, &host_contract, &breadcrumbs)) { return StatusCode::ResolverResolveFailure; } } else { - if (!resolver.resolve_probe_paths(&probe_paths, nullptr)) + if (!resolver.resolve_probe_paths(&probe_paths, &host_contract, nullptr)) { return StatusCode::ResolverResolveFailure; } @@ -285,7 +297,6 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c pal::string_t app_base; resolver.get_app_dir(&app_base); - // populate probing path properties struct here.... coreclr_properties.add(common_property::TrustedPlatformAssemblies, probe_paths.tpa.c_str()); coreclr_properties.add(common_property::NativeDllSearchDirectories, probe_paths.native.c_str()); coreclr_properties.add(common_property::PlatformResourceRoots, probe_paths.resources.c_str()); @@ -342,26 +353,5 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c coreclr_properties.add(common_property::StartUpHooks, startup_hooks.c_str()); } - { - host_contract = { sizeof(host_runtime_contract), this }; - if (bundle::info_t::is_single_file_bundle()) - { - host_contract.bundle_probe = &bundle_probe; -#if defined(NATIVE_LIBS_EMBEDDED) - host_contract.pinvoke_override = &pinvoke_override; -#endif - } - - host_contract.get_runtime_property = &get_runtime_property; - host_contract.get_probing_path_properties = &get_probing_path_properties; - pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; - pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); - if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), buffer)) - { - log_duplicate_property_error(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT)); - return StatusCode::LibHostDuplicateProperty; - } - } - return StatusCode::Success; } From 8dd3eac4d97f9e6172b9aa5f094f2eac2e5e13d5 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Fri, 29 Mar 2024 13:56:06 -0700 Subject: [PATCH 03/11] Make sure to use char_t in the contract --- src/coreclr/hosts/corerun/corerun.cpp | 1 - src/coreclr/hosts/corerun/corerun.hpp | 2 ++ src/coreclr/inc/hostinformation.h | 2 ++ src/coreclr/vm/corhost.cpp | 6 ++++-- src/coreclr/vm/hostinformation.cpp | 16 ++++++++++++++++ src/native/corehost/host_runtime_contract.h | 14 ++++++++++---- src/native/corehost/hostmisc/pal.h | 2 ++ src/native/corehost/hostpolicy/deps_resolver.cpp | 4 ++-- 8 files changed, 38 insertions(+), 9 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 5332d85115d1a5..8b6d78866122c0 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -9,7 +9,6 @@ #include "dotenv.hpp" #include -#include #include using char_t = pal::char_t; diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 38ced1eb87bbad..05685836224a59 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -69,6 +69,7 @@ namespace pal inline int strcmp(const char_t* str1, const char_t* str2) { return wcscmp(str1, str2); } inline size_t strlen(const char_t* str) { return wcslen(str); } inline char_t* strdup(const char_t* str) { return ::_wcsdup(str); } + inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::wcscpy_s(dest, destsz, src); } inline int fprintf(FILE* fd, const char_t* const fmt, ...) { va_list args; @@ -357,6 +358,7 @@ namespace pal inline int strcmp(const char_t* str1, const char_t* str2) { return ::strcmp(str1, str2); } inline size_t strlen(const char_t* str) { return ::strlen(str); } inline char_t* strdup(const char_t* str) { return ::strdup(str); } + inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::strcpy_s(dest, destsz, src); } inline int fprintf(FILE* fd, const char_t* const fmt, ...) { va_list args; diff --git a/src/coreclr/inc/hostinformation.h b/src/coreclr/inc/hostinformation.h index d57b4729d30e68..badfdb148e8fde 100644 --- a/src/coreclr/inc/hostinformation.h +++ b/src/coreclr/inc/hostinformation.h @@ -11,6 +11,8 @@ class HostInformation public: static void SetContract(_In_ host_runtime_contract* hostContract); static bool GetProperty(_In_z_ const char* name, SString& value); + static LPCWSTR GetEntryAssembly(); + trusted_platform_assemblies* GetTrustedPlatformAssemblies(); }; #endif // _HOSTINFORMATION_H_ diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index b85331e00ce8d2..5263b02ffa819b 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -40,6 +40,7 @@ #ifndef DACCESS_COMPILE +#include "hostinformation.h" #include extern void STDMETHODCALLTYPE EEShutDown(BOOL fIsDllUnloading); @@ -313,9 +314,10 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, if (g_EntryAssemblyPath == NULL) { // Store the entry assembly path for diagnostic purposes (for example, dumps) - size_t len = u16_strlen(pwzAssemblyPath) + 1; + LPCWSTR pEntryAssembly = HostInformation::GetEntryAssembly(); + size_t len = u16_strlen(pEntryAssembly) + 1; NewArrayHolder path { new WCHAR[len] }; - wcscpy_s(path, len, pwzAssemblyPath); + wcscpy_s(path, len, pEntryAssembly); g_EntryAssemblyPath = path.Extract(); } diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index b440f6f2168ab7..3f2d9993b9615c 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -40,3 +40,19 @@ bool HostInformation::GetProperty(_In_z_ const char* name, SString& value) return lenActual > 0 && lenActual <= len; } + +LPCWSTR HostInformation::GetEntryAssembly() +{ + if (s_hostContract == nullptr) + return nullptr; + + return s_hostContract->entry_assembly; +} + +trusted_platform_assemblies* HostInformation::GetTrustedPlatformAssemblies() +{ + if (s_hostContract == nullptr) + return nullptr; + + return &s_hostContract->probing_paths.trusted_platform_assemblies; +} diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 9a60ab17531936..94f03d84bfe594 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -9,8 +9,14 @@ #if defined(_WIN32) #define HOST_CONTRACT_CALLTYPE __stdcall + #ifdef _WCHAR_T_DEFINED + typedef wchar_t char_t; + #else + typedef unsigned char char_t; + #endif #else #define HOST_CONTRACT_CALLTYPE + typedef unsigned char char_t; #endif // Known host property names @@ -26,14 +32,14 @@ struct trusted_platform_assemblies { uint32_t assembly_count; - wchar_t** basenames; /* Foo.dll */ - wchar_t** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ + char_t** basenames; /* Foo.dll */ + char_t** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ }; struct probing_lookup_paths { uint32_t dir_count; - wchar_t** dirs; + char_t** dirs; }; struct probing_path_properties @@ -50,7 +56,7 @@ struct host_runtime_contract // Context for the contract. Pass to functions taking a contract context. void* context; - wchar_t* entry_assembly; + char_t* entry_assembly; probing_path_properties probing_paths; diff --git a/src/native/corehost/hostmisc/pal.h b/src/native/corehost/hostmisc/pal.h index f482b6df63456b..7ad31a23246874 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -152,6 +152,7 @@ namespace pal inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::_wcsicmp(str1, str2); } inline int strncmp(const char_t* str1, const char_t* str2, size_t len) { return ::wcsncmp(str1, str2, len); } inline int strncasecmp(const char_t* str1, const char_t* str2, size_t len) { return ::_wcsnicmp(str1, str2, len); } + inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::wcscpy_s(dest, destsz, src); } inline int pathcmp(const pal::string_t& path1, const pal::string_t& path2) { return strcasecmp(path1.c_str(), path2.c_str()); } inline string_t to_string(int value) { return std::to_wstring(value); } @@ -220,6 +221,7 @@ namespace pal inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::strcasecmp(str1, str2); } inline int strncmp(const char_t* str1, const char_t* str2, int len) { return ::strncmp(str1, str2, len); } inline int strncasecmp(const char_t* str1, const char_t* str2, int len) { return ::strncasecmp(str1, str2, len); } + inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::strcpy_s(dest, destsz, src); } inline int pathcmp(const pal::string_t& path1, const pal::string_t& path2) { return strcmp(path1.c_str(), path2.c_str()); } inline string_t to_string(int value) { return std::to_string(value); } diff --git a/src/native/corehost/hostpolicy/deps_resolver.cpp b/src/native/corehost/hostpolicy/deps_resolver.cpp index 15c7dacde1bebc..de071666d9d0cf 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.cpp +++ b/src/native/corehost/hostpolicy/deps_resolver.cpp @@ -604,8 +604,8 @@ bool deps_resolver_t::resolve_tpa_list( tpa_list->basenames[item_count] = new pal::char_t[base_length]; tpa_list->assembly_filepaths[item_count] = new pal::char_t[assembly_name_length]; - wcscpy_s(tpa_list->basenames[item_count], base_length, base_name.c_str()); - wcscpy_s(tpa_list->assembly_filepaths[item_count], assembly_name_length, item->second.resolved_path.c_str()); + pal::strcpy_s(tpa_list->basenames[item_count], base_length, base_name.c_str()); + pal::strcpy_s(tpa_list->assembly_filepaths[item_count], assembly_name_length, item->second.resolved_path.c_str()); output->append(item->second.resolved_path); output->push_back(PATH_SEPARATOR); From 580dcb829ed26167f85f648f4aa50115c8517d4b Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Fri, 29 Mar 2024 21:03:13 -0700 Subject: [PATCH 04/11] Switch host_runtime_contract strings back to char* --- src/coreclr/hosts/corerun/corerun.cpp | 25 +++---- src/coreclr/hosts/corerun/corerun.hpp | 2 - src/coreclr/inc/hostinformation.h | 2 - src/coreclr/vm/corhost.cpp | 5 +- src/coreclr/vm/hostinformation.cpp | 16 ---- src/native/corehost/host_runtime_contract.h | 14 +--- src/native/corehost/hostmisc/pal.h | 2 - src/native/corehost/hostmisc/utils.cpp | 33 +++++++++ src/native/corehost/hostmisc/utils.h | 4 + .../corehost/hostpolicy/deps_resolver.cpp | 74 +++++++++++-------- .../corehost/hostpolicy/deps_resolver.h | 6 ++ .../hostpolicy/hostpolicy_context.cpp | 6 +- 12 files changed, 106 insertions(+), 83 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 8b6d78866122c0..da003c270e146a 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -148,21 +148,16 @@ static string_t build_tpa(const string_t& core_root, const string_t& core_librar } tpa_items->assembly_count = static_cast(name_path_map.size()); - tpa_items->assembly_filepaths = new char_t*[tpa_items->assembly_count]; - tpa_items->basenames = new char_t*[tpa_items->assembly_count]; + tpa_items->assembly_filepaths = new char*[tpa_items->assembly_count]; + tpa_items->basenames = new char*[tpa_items->assembly_count]; // Convert the paths into a string and return it int32_t item_count = 0; for (auto item = name_path_map.begin(); item != name_path_map.end(); ++item) { string_t base_name = item->first; - size_t base_length = base_name.size() + 1; - size_t assembly_name_length = item->second.size() + 1; - - tpa_items->basenames[item_count] = new char_t[base_length]; - tpa_items->assembly_filepaths[item_count] = new char_t[assembly_name_length]; - wcscpy_s(tpa_items->basenames[item_count], base_length, base_name.c_str()); - wcscpy_s(tpa_items->assembly_filepaths[item_count], assembly_name_length, item->second.c_str()); + tpa_items->basenames[item_count] = (char*)pal::convert_to_utf8(base_name.c_str()).c_str(); + tpa_items->assembly_filepaths[item_count] = (char*)pal::convert_to_utf8(item->second.c_str()).c_str(); item_count++; } @@ -277,9 +272,8 @@ static int run(const configuration& config) host_contract.bundle_probe = nullptr; host_contract.pinvoke_override = nullptr; - host_contract.entry_assembly = new char_t[config.entry_assembly_fullpath.size() + 1]; - wcscpy_s(host_contract.entry_assembly, config.entry_assembly_fullpath.size() + 1, config.entry_assembly_fullpath.c_str()); - + host_contract.entry_assembly = (char*)pal::convert_to_utf8(config.entry_assembly_fullpath.c_str()).c_str(); + config.dotenv_configuration.load_into_current_process(); string_t exe_path = pal::get_exe_path(); @@ -334,16 +328,15 @@ static int run(const configuration& config) probing_lookup_paths* native_paths = &host_contract.probing_paths.native_dll_search_directories; native_paths->dir_count = static_cast(native_search_dirs_set.size()); - native_paths->dirs = new char_t*[native_paths->dir_count]; + native_paths->dirs = new char*[native_paths->dir_count]; int dir_count = 0; for (const auto& native_dir : native_search_dirs_set) { - native_paths->dirs[dir_count] = new char_t[native_dir.size() + 1]; - wcscpy_s(native_paths->dirs[dir_count], native_dir.size() + 1, native_dir.c_str()); + native_paths->dirs[dir_count] = (char*)pal::convert_to_utf8(native_dir.c_str()).c_str(); + dir_count++; } - { // Load hostpolicy if requested. string_t mock_hostpolicy = pal::getenv(envvar::mockHostPolicy); diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 05685836224a59..38ced1eb87bbad 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -69,7 +69,6 @@ namespace pal inline int strcmp(const char_t* str1, const char_t* str2) { return wcscmp(str1, str2); } inline size_t strlen(const char_t* str) { return wcslen(str); } inline char_t* strdup(const char_t* str) { return ::_wcsdup(str); } - inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::wcscpy_s(dest, destsz, src); } inline int fprintf(FILE* fd, const char_t* const fmt, ...) { va_list args; @@ -358,7 +357,6 @@ namespace pal inline int strcmp(const char_t* str1, const char_t* str2) { return ::strcmp(str1, str2); } inline size_t strlen(const char_t* str) { return ::strlen(str); } inline char_t* strdup(const char_t* str) { return ::strdup(str); } - inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::strcpy_s(dest, destsz, src); } inline int fprintf(FILE* fd, const char_t* const fmt, ...) { va_list args; diff --git a/src/coreclr/inc/hostinformation.h b/src/coreclr/inc/hostinformation.h index badfdb148e8fde..d57b4729d30e68 100644 --- a/src/coreclr/inc/hostinformation.h +++ b/src/coreclr/inc/hostinformation.h @@ -11,8 +11,6 @@ class HostInformation public: static void SetContract(_In_ host_runtime_contract* hostContract); static bool GetProperty(_In_z_ const char* name, SString& value); - static LPCWSTR GetEntryAssembly(); - trusted_platform_assemblies* GetTrustedPlatformAssemblies(); }; #endif // _HOSTINFORMATION_H_ diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index 5263b02ffa819b..e4ac7c34285889 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -314,10 +314,9 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, if (g_EntryAssemblyPath == NULL) { // Store the entry assembly path for diagnostic purposes (for example, dumps) - LPCWSTR pEntryAssembly = HostInformation::GetEntryAssembly(); - size_t len = u16_strlen(pEntryAssembly) + 1; + size_t len = u16_strlen(pwzAssemblyPath) + 1; NewArrayHolder path { new WCHAR[len] }; - wcscpy_s(path, len, pEntryAssembly); + wcscpy_s(path, len, pwzAssemblyPath); g_EntryAssemblyPath = path.Extract(); } diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index 3f2d9993b9615c..b440f6f2168ab7 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -40,19 +40,3 @@ bool HostInformation::GetProperty(_In_z_ const char* name, SString& value) return lenActual > 0 && lenActual <= len; } - -LPCWSTR HostInformation::GetEntryAssembly() -{ - if (s_hostContract == nullptr) - return nullptr; - - return s_hostContract->entry_assembly; -} - -trusted_platform_assemblies* HostInformation::GetTrustedPlatformAssemblies() -{ - if (s_hostContract == nullptr) - return nullptr; - - return &s_hostContract->probing_paths.trusted_platform_assemblies; -} diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 94f03d84bfe594..840212abb0251e 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -9,14 +9,8 @@ #if defined(_WIN32) #define HOST_CONTRACT_CALLTYPE __stdcall - #ifdef _WCHAR_T_DEFINED - typedef wchar_t char_t; - #else - typedef unsigned char char_t; - #endif #else #define HOST_CONTRACT_CALLTYPE - typedef unsigned char char_t; #endif // Known host property names @@ -32,14 +26,14 @@ struct trusted_platform_assemblies { uint32_t assembly_count; - char_t** basenames; /* Foo.dll */ - char_t** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ + char** basenames; /* Foo.dll */ + char** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ }; struct probing_lookup_paths { uint32_t dir_count; - char_t** dirs; + char** dirs; }; struct probing_path_properties @@ -56,7 +50,7 @@ struct host_runtime_contract // Context for the contract. Pass to functions taking a contract context. void* context; - char_t* entry_assembly; + char* entry_assembly; probing_path_properties probing_paths; diff --git a/src/native/corehost/hostmisc/pal.h b/src/native/corehost/hostmisc/pal.h index 7ad31a23246874..f482b6df63456b 100644 --- a/src/native/corehost/hostmisc/pal.h +++ b/src/native/corehost/hostmisc/pal.h @@ -152,7 +152,6 @@ namespace pal inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::_wcsicmp(str1, str2); } inline int strncmp(const char_t* str1, const char_t* str2, size_t len) { return ::wcsncmp(str1, str2, len); } inline int strncasecmp(const char_t* str1, const char_t* str2, size_t len) { return ::_wcsnicmp(str1, str2, len); } - inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::wcscpy_s(dest, destsz, src); } inline int pathcmp(const pal::string_t& path1, const pal::string_t& path2) { return strcasecmp(path1.c_str(), path2.c_str()); } inline string_t to_string(int value) { return std::to_wstring(value); } @@ -221,7 +220,6 @@ namespace pal inline int strcasecmp(const char_t* str1, const char_t* str2) { return ::strcasecmp(str1, str2); } inline int strncmp(const char_t* str1, const char_t* str2, int len) { return ::strncmp(str1, str2, len); } inline int strncasecmp(const char_t* str1, const char_t* str2, int len) { return ::strncasecmp(str1, str2, len); } - inline errno_t strcpy_s(char_t* dest, rsize_t destsz, const char_t* src) { return ::strcpy_s(dest, destsz, src); } inline int pathcmp(const pal::string_t& path1, const pal::string_t& path2) { return strcmp(path1.c_str(), path2.c_str()); } inline string_t to_string(int value) { return std::to_string(value); } diff --git a/src/native/corehost/hostmisc/utils.cpp b/src/native/corehost/hostmisc/utils.cpp index 521574fe2a5fd4..482a0c8dced1c1 100644 --- a/src/native/corehost/hostmisc/utils.cpp +++ b/src/native/corehost/hostmisc/utils.cpp @@ -4,6 +4,7 @@ #include "utils.h" #include "trace.h" #include "bundle/info.h" +#include "host_runtime_contract.h" #if defined(TARGET_WINDOWS) #include <_version.h> #else @@ -500,6 +501,38 @@ pal::string_t to_upper(const pal::char_t* in) { return ret; } +void destroy_tpa_list(trusted_platform_assemblies* tpa_list) +{ + if (tpa_list == nullptr) + { + return; + } + + for (uint32_t i = 0; i < tpa_list->assembly_count; ++i) + { + delete tpa_list->basenames[i]; + delete tpa_list->assembly_filepaths[i]; + } + + delete[] tpa_list->basenames; + delete[] tpa_list->assembly_filepaths; +} + +void destroy_probing_path_list(probing_lookup_paths* probing_paths) +{ + if (probing_paths == nullptr) + { + return; + } + + for (uint32_t i = 0; i < probing_paths->dir_count; ++i) + { + delete probing_paths->dirs[i]; + } + + delete[] probing_paths->dirs; +} + #define TEST_ONLY_MARKER "d38cc827-e34f-4453-9df4-1e796e9f1d07" // Retrieves environment variable which is only used for testing. diff --git a/src/native/corehost/hostmisc/utils.h b/src/native/corehost/hostmisc/utils.h index 5d782a070f8b8e..34b655c8f67c9a 100644 --- a/src/native/corehost/hostmisc/utils.h +++ b/src/native/corehost/hostmisc/utils.h @@ -6,6 +6,7 @@ #include "pal.h" #include "trace.h" +#include "host_runtime_contract.h" #include #include #include @@ -121,6 +122,9 @@ pal::string_t get_host_version_description(); pal::string_t to_lower(const pal::char_t* in); pal::string_t to_upper(const pal::char_t* in); +void destroy_tpa_list(trusted_platform_assemblies* tpa_list); +void destroy_probing_path_list(probing_lookup_paths* probing_paths); + // Retrieves environment variable which is only used for testing. // This will return the value of the variable only if the product binary is stamped // with test-only marker. diff --git a/src/native/corehost/hostpolicy/deps_resolver.cpp b/src/native/corehost/hostpolicy/deps_resolver.cpp index de071666d9d0cf..b5bafb536cd560 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.cpp +++ b/src/native/corehost/hostpolicy/deps_resolver.cpp @@ -214,6 +214,47 @@ pal::string_t deps_resolver_t::get_lookup_probe_directories() return directories; } +void deps_resolver_t::create_probing_paths(const std::deque& probing_items, probing_lookup_paths& probing_paths) +{ + // Add the probing paths to piece of the host_runtime_contract + probing_paths.dir_count = static_cast(probing_items.size()); + probing_paths.dirs = new char*[probing_paths.dir_count]; + + int dir_count = 0; + for (const auto& probing_item : probing_items) + { + probing_paths.dirs[dir_count] = new char[probing_item.size() + 1]; + pal::pal_utf8string(probing_item, probing_paths.dirs[dir_count], probing_item.size() + 1); + dir_count++; + } +} + +void deps_resolver_t::create_tpa_list(const name_to_resolved_asset_map_t& items, trusted_platform_assemblies& tpa_list, pal::string_t& output) +{ + tpa_list.assembly_count = static_cast(items.size()); + tpa_list.assembly_filepaths = new char*[tpa_list.assembly_count]; + tpa_list.basenames = new char*[tpa_list.assembly_count]; + + // Convert the paths into a string and return it + int32_t item_count = 0; + for (auto item = items.begin(); item != items.end(); ++item) + { + pal::string_t base_name = get_filename(item->second.resolved_path); + size_t base_length = base_name.size() + 1; + size_t assembly_name_length = item->second.resolved_path.size() + 1; + + tpa_list.basenames[item_count] = new char[base_length]; + tpa_list.assembly_filepaths[item_count] = new char[assembly_name_length]; + + pal::pal_utf8string(base_name, tpa_list.basenames[item_count], base_length); + pal::pal_utf8string(item->second.resolved_path, tpa_list.assembly_filepaths[item_count], assembly_name_length); + + output.append(item->second.resolved_path); + output.push_back(PATH_SEPARATOR); + item_count++; + } +} + void deps_resolver_t::setup_probe_config( const std::vector& shared_stores, const std::vector& additional_probe_paths) @@ -590,27 +631,8 @@ bool deps_resolver_t::resolve_tpa_list( } } - tpa_list->assembly_count = static_cast(items.size()); - tpa_list->assembly_filepaths = new pal::char_t*[tpa_list->assembly_count]; - tpa_list->basenames = new pal::char_t*[tpa_list->assembly_count]; - - // Convert the paths into a string and return it - int32_t item_count = 0; - for (auto item = items.begin(); item != items.end(); ++item) - { - pal::string_t base_name = get_filename(item->second.resolved_path); - size_t base_length = base_name.size() + 1; - size_t assembly_name_length = item->second.resolved_path.size() + 1; - - tpa_list->basenames[item_count] = new pal::char_t[base_length]; - tpa_list->assembly_filepaths[item_count] = new pal::char_t[assembly_name_length]; - pal::strcpy_s(tpa_list->basenames[item_count], base_length, base_name.c_str()); - pal::strcpy_s(tpa_list->assembly_filepaths[item_count], assembly_name_length, item->second.resolved_path.c_str()); - - output->append(item->second.resolved_path); - output->push_back(PATH_SEPARATOR); - item_count++; - } + // Now that we have the complete list, store it in the host_runtime_contract and as a ; delimted string. + create_tpa_list(items, *tpa_list, *output); return true; } @@ -910,15 +932,7 @@ bool deps_resolver_t::resolve_probe_dirs( } // Add the probing paths to piece of the host_runtime_contract - probing_paths->dir_count = static_cast(probing_items.size()); - probing_paths->dirs = new pal::char_t*[probing_paths->dir_count]; - - int dir_count = 0; - for (const auto& probing_item : probing_items) - { - probing_paths->dirs[dir_count] = new pal::char_t[probing_item.size() + 1]; - wcscpy_s(probing_paths->dirs[dir_count], probing_item.size() + 1, probing_item.c_str()); - } + create_probing_paths(probing_items, *probing_paths); output->append(non_serviced); diff --git a/src/native/corehost/hostpolicy/deps_resolver.h b/src/native/corehost/hostpolicy/deps_resolver.h index 60d131c4479fdd..065872faca5cb8 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.h +++ b/src/native/corehost/hostpolicy/deps_resolver.h @@ -5,6 +5,7 @@ #define DEPS_RESOLVER_H #include +#include #include "pal.h" #include "args.h" @@ -193,6 +194,11 @@ class deps_resolver_t const std::vector& shared_stores, const std::vector& additional_probe_paths); + void create_probing_paths(const std::deque& probing_items, + probing_lookup_paths& probing_paths); + + void create_tpa_list(const name_to_resolved_asset_map_t& items, trusted_platform_assemblies& tpa_list, pal::string_t& output); + void init_known_entry_path( const deps_entry_t& entry, const pal::string_t& path); diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index ff2f69471872ec..eeae5702e11384 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -188,8 +188,10 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c #endif } - host_contract.entry_assembly = new pal::char_t[application.size() + 1]; - wcscpy_s(host_contract.entry_assembly, application.size() + 1, application.c_str()); + size_t entry_assembly_length = application.size() + 1; + + host_contract.entry_assembly = new char[entry_assembly_length]; + pal::pal_utf8string(application, host_contract.entry_assembly, entry_assembly_length); host_contract.get_runtime_property = &get_runtime_property; pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; From 4879bf5ecce20dbf1b349762f665e5c9cefcae3e Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Thu, 11 Apr 2024 14:34:36 -0700 Subject: [PATCH 05/11] Provide a way for the runtime to ask the host for the list of platform assembly names and the ability to resolve their paths --- src/coreclr/binder/applicationcontext.cpp | 137 +++++++++++----- src/coreclr/binder/assemblybindercommon.cpp | 31 ++-- src/coreclr/binder/defaultassemblybinder.cpp | 13 ++ src/coreclr/binder/inc/applicationcontext.hpp | 66 +------- .../binder/inc/defaultassemblybinder.h | 3 + src/coreclr/binder/inc/utils.hpp | 2 +- src/coreclr/binder/utils.cpp | 17 +- src/coreclr/dlls/mscoree/exports.cpp | 2 +- src/coreclr/hosts/corerun/corerun.cpp | 138 ++++++++++------ src/coreclr/hosts/corerun/corerun.hpp | 152 ++++++++++++++++++ src/coreclr/inc/hostinformation.h | 29 +++- src/coreclr/inc/simplefilenamemap.h | 64 ++++++++ src/coreclr/vm/corhost.cpp | 19 ++- .../vm/eventing/eventpipe/ep-rt-coreclr.h | 2 +- src/coreclr/vm/hostinformation.cpp | 133 +++++++++++++++ src/native/corehost/host_runtime_contract.h | 34 ++-- src/native/corehost/hostmisc/utils.cpp | 31 ---- src/native/corehost/hostmisc/utils.h | 3 - .../corehost/hostpolicy/deps_resolver.cpp | 97 +++-------- .../corehost/hostpolicy/deps_resolver.h | 12 +- src/native/corehost/hostpolicy/hostpolicy.cpp | 4 +- .../hostpolicy/hostpolicy_context.cpp | 71 +++++++- .../corehost/hostpolicy/hostpolicy_context.h | 4 +- 23 files changed, 735 insertions(+), 329 deletions(-) create mode 100644 src/coreclr/inc/simplefilenamemap.h diff --git a/src/coreclr/binder/applicationcontext.cpp b/src/coreclr/binder/applicationcontext.cpp index e41b504c8feb61..7e0480c8b231e2 100644 --- a/src/coreclr/binder/applicationcontext.cpp +++ b/src/coreclr/binder/applicationcontext.cpp @@ -18,6 +18,7 @@ #include "utils.hpp" #include "ex.h" #include "clr/fs/path.h" +#include "hostinformation.h" using namespace clr::fs; namespace BINDER_SPACE @@ -102,69 +103,80 @@ namespace BINDER_SPACE { SString fileName; SString simpleName; - bool isNativeImage = false; HRESULT pathResult = S_OK; - IF_FAIL_GO(pathResult = GetNextTPAPath(sTrustedPlatformAssemblies, i, /*dllOnly*/ false, fileName, simpleName, isNativeImage)); + IF_FAIL_GO(pathResult = GetNextTPAPath(sTrustedPlatformAssemblies, i, /*dllOnly*/ false, fileName, simpleName)); if (pathResult == S_FALSE) { break; } - const SimpleNameToFileNameMapEntry *pExistingEntry = m_pTrustedPlatformAssemblyMap->LookupPtr(simpleName.GetUnicode()); + IF_FAIL_GO(hr = AddAssemblyMapEntry(simpleName, fileName)); + } - if (pExistingEntry != nullptr) - { - // - // We want to store only the first entry matching a simple name we encounter. - // The exception is if we first store an IL reference and later in the string - // we encounter a native image. Since we don't touch IL in the presence of - // native images, we replace the IL entry with the NI. - // - if ((pExistingEntry->m_wszILFileName != nullptr && !isNativeImage) || - (pExistingEntry->m_wszNIFileName != nullptr && isNativeImage)) - { - continue; - } - } + // + // Parse PlatformResourceRoots + // + sPlatformResourceRoots.Normalize(); + for (SString::Iterator i = sPlatformResourceRoots.Begin(); i != sPlatformResourceRoots.End(); ) + { + SString pathName; + HRESULT pathResult = S_OK; - LPWSTR wszSimpleName = nullptr; - if (pExistingEntry == nullptr) - { - wszSimpleName = new WCHAR[simpleName.GetCount() + 1]; - if (wszSimpleName == nullptr) - { - GO_WITH_HRESULT(E_OUTOFMEMORY); - } - wcscpy_s(wszSimpleName, simpleName.GetCount() + 1, simpleName.GetUnicode()); - } - else + IF_FAIL_GO(pathResult = GetNextPath(sPlatformResourceRoots, i, pathName)); + if (pathResult == S_FALSE) { - wszSimpleName = pExistingEntry->m_wszSimpleName; + break; } - LPWSTR wszFileName = new WCHAR[fileName.GetCount() + 1]; - if (wszFileName == nullptr) + if (Path::IsRelative(pathName)) { - GO_WITH_HRESULT(E_OUTOFMEMORY); + GO_WITH_HRESULT(E_INVALIDARG); } - wcscpy_s(wszFileName, fileName.GetCount() + 1, fileName.GetUnicode()); - SimpleNameToFileNameMapEntry mapEntry; - mapEntry.m_wszSimpleName = wszSimpleName; - if (isNativeImage) + m_platformResourceRoots.Append(pathName); + } + + // + // Parse AppPaths + // + sAppPaths.Normalize(); + for (SString::Iterator i = sAppPaths.Begin(); i != sAppPaths.End(); ) + { + SString pathName; + HRESULT pathResult = S_OK; + + IF_FAIL_GO(pathResult = GetNextPath(sAppPaths, i, pathName)); + if (pathResult == S_FALSE) { - mapEntry.m_wszNIFileName = wszFileName; - mapEntry.m_wszILFileName = pExistingEntry == nullptr ? nullptr : pExistingEntry->m_wszILFileName; + break; } - else + + if (Path::IsRelative(pathName)) { - mapEntry.m_wszILFileName = wszFileName; - mapEntry.m_wszNIFileName = pExistingEntry == nullptr ? nullptr : pExistingEntry->m_wszNIFileName; + GO_WITH_HRESULT(E_INVALIDARG); } - m_pTrustedPlatformAssemblyMap->AddOrReplace(mapEntry); + m_appPaths.Append(pathName); } + Exit: + return hr; + } + + HRESULT ApplicationContext::SetupBindingPaths(SString &sPlatformResourceRoots, + SString &sAppPaths, + BOOL fAcquireLock) + { + HRESULT hr = S_OK; + + CRITSEC_Holder contextLock(fAcquireLock ? GetCriticalSectionCookie() : NULL); + if (m_pTrustedPlatformAssemblyMap != nullptr) + { + GO_WITH_HRESULT(S_OK); + } + + m_pTrustedPlatformAssemblyMap = HostInformation::Instance().GetHostAssemblyNames(); + // // Parse PlatformResourceRoots // @@ -219,4 +231,45 @@ namespace BINDER_SPACE { return m_pTrustedPlatformAssemblyMap != nullptr; } + + HRESULT ApplicationContext::AddAssemblyMapEntry(SString& simpleName, SString& fileName) + { + HRESULT hr = S_OK; + const SimpleNameToFileNameMapEntry *pExistingEntry = m_pTrustedPlatformAssemblyMap->LookupPtr(simpleName.GetUnicode()); + + LPWSTR wszSimpleName = nullptr; + if (pExistingEntry == nullptr) + { + wszSimpleName = new WCHAR[simpleName.GetCount() + 1]; + if (wszSimpleName == nullptr) + { + return E_OUTOFMEMORY; + } + wcscpy_s(wszSimpleName, simpleName.GetCount() + 1, simpleName.GetUnicode()); + } + else + { + wszSimpleName = pExistingEntry->m_wszSimpleName; + } + + LPWSTR wszFileName = nullptr; + + if (fileName.GetCount() > 0) + { + wszFileName = new WCHAR[fileName.GetCount() + 1]; + if (wszFileName == nullptr) + { + return E_OUTOFMEMORY; + } + wcscpy_s(wszFileName, fileName.GetCount() + 1, fileName.GetUnicode()); + } + + SimpleNameToFileNameMapEntry mapEntry; + mapEntry.m_wszSimpleName = wszSimpleName; + mapEntry.m_wszILFileName = wszFileName; + + m_pTrustedPlatformAssemblyMap->AddOrReplace(mapEntry); + + return hr; + } }; diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 55f9a0ae533614..08b8f6d1766aea 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -20,6 +20,7 @@ #include "bindertracing.h" #include "bindresult.inl" #include "failurecache.hpp" +#include "hostinformation.h" #include "utils.hpp" #include "stringarraylist.h" #include "configuration.h" @@ -298,9 +299,8 @@ namespace BINDER_SPACE { SString fileName; SString simpleName; - bool isNativeImage = false; HRESULT pathResult = S_OK; - IF_FAIL_GO(pathResult = GetNextTPAPath(sTrustedPlatformAssemblies, i, /*dllOnly*/ true, fileName, simpleName, isNativeImage)); + IF_FAIL_GO(pathResult = GetNextTPAPath(sTrustedPlatformAssemblies, i, /*dllOnly*/ true, fileName, simpleName)); if (pathResult == S_FALSE) { break; @@ -893,25 +893,24 @@ namespace BINDER_SPACE const SimpleNameToFileNameMapEntry *pTpaEntry = tpaMap->LookupPtr(simpleName.GetUnicode()); if (pTpaEntry != nullptr) { - if (pTpaEntry->m_wszNIFileName != nullptr) - { - SString fileName(pTpaEntry->m_wszNIFileName); + SString fileName; - hr = GetAssembly(fileName, - TRUE, // fIsInTPA - &pTPAAssembly); - BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); + // If supported, go ask the host to resolve the path to the assembly + if (pTpaEntry->m_wszILFileName == nullptr) + { + _ASSERTE(pTpaEntry->m_wszSimpleName != nullptr); + LPCWSTR lpFileName = HostInformation::Instance().ResolveHostAssemblyPath(pTpaEntry->m_wszSimpleName); + fileName.Set(lpFileName); } else { - _ASSERTE(pTpaEntry->m_wszILFileName != nullptr); - SString fileName(pTpaEntry->m_wszILFileName); - - hr = GetAssembly(fileName, - TRUE, // fIsInTPA - &pTPAAssembly); - BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); + fileName.Set(pTpaEntry->m_wszILFileName); } + + hr = GetAssembly(fileName, + TRUE, // fIsInTPA + &pTPAAssembly); + BinderTracing::PathProbed(fileName, BinderTracing::PathSource::ApplicationAssemblies, hr); pBindResult->SetAttemptResult(hr, pTPAAssembly); diff --git a/src/coreclr/binder/defaultassemblybinder.cpp b/src/coreclr/binder/defaultassemblybinder.cpp index d4ad4f3265ce8b..5a2f748f8b3699 100644 --- a/src/coreclr/binder/defaultassemblybinder.cpp +++ b/src/coreclr/binder/defaultassemblybinder.cpp @@ -187,6 +187,19 @@ HRESULT DefaultAssemblyBinder::SetupBindingPaths(SString &sTrustedPlatformAssem return hr; } +HRESULT DefaultAssemblyBinder::SetupBindingPaths(SString &sPlatformResourceRoots, + SString &sAppPaths) +{ + HRESULT hr = S_OK; + + EX_TRY + { + hr = GetAppContext()->SetupBindingPaths(sPlatformResourceRoots, sAppPaths, TRUE /* fAcquireLock */); + } + EX_CATCH_HRESULT(hr); + return hr; +} + HRESULT DefaultAssemblyBinder::BindToSystem(BINDER_SPACE::Assembly** ppSystemAssembly) { HRESULT hr = S_OK; diff --git a/src/coreclr/binder/inc/applicationcontext.hpp b/src/coreclr/binder/inc/applicationcontext.hpp index 721f571af1e5d6..810dea25e8abc8 100644 --- a/src/coreclr/binder/inc/applicationcontext.hpp +++ b/src/coreclr/binder/inc/applicationcontext.hpp @@ -17,67 +17,10 @@ #include "bindertypes.hpp" #include "failurecache.hpp" #include "stringarraylist.h" +#include "simplefilenamemap.h" namespace BINDER_SPACE { - //============================================================================================= - // Data structures for Simple Name -> File Name hash - - // Entry in SHash table that maps namespace to list of files - struct SimpleNameToFileNameMapEntry - { - LPWSTR m_wszSimpleName; - LPWSTR m_wszILFileName; - LPWSTR m_wszNIFileName; - }; - - // SHash traits for Namespace -> FileNameList hash - class SimpleNameToFileNameMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits< SimpleNameToFileNameMapEntry > > - { - public: - typedef PCWSTR key_t; - static const SimpleNameToFileNameMapEntry Null() { SimpleNameToFileNameMapEntry e; e.m_wszSimpleName = nullptr; return e; } - static bool IsNull(const SimpleNameToFileNameMapEntry & e) { return e.m_wszSimpleName == nullptr; } - static key_t GetKey(const SimpleNameToFileNameMapEntry & e) - { - key_t key; - key = e.m_wszSimpleName; - return key; - } - static count_t Hash(const key_t &str) - { - SString ssKey(SString::Literal, str); - return ssKey.HashCaseInsensitive(); - } - static BOOL Equals(const key_t &lhs, const key_t &rhs) { LIMITED_METHOD_CONTRACT; return (SString::_wcsicmp(lhs, rhs) == 0); } - - void OnDestructPerEntryCleanupAction(const SimpleNameToFileNameMapEntry & e) - { - if (e.m_wszILFileName == nullptr && e.m_wszNIFileName == nullptr) - { - // Don't delete simple name here since it's a filename only entry and will be cleaned up - // by the SimpleName -> FileName entry which reuses the same filename pointer. - return; - } - - if (e.m_wszSimpleName != nullptr) - { - delete [] e.m_wszSimpleName; - } - if (e.m_wszILFileName != nullptr) - { - delete [] e.m_wszILFileName; - } - if (e.m_wszNIFileName != nullptr) - { - delete [] e.m_wszNIFileName; - } - } - static const bool s_DestructPerEntryCleanupAction = true; - }; - - typedef SHash SimpleNameToFileNameMap; - class AssemblyHashTraits; typedef SHash ExecutionContext; @@ -95,6 +38,10 @@ namespace BINDER_SPACE /* in */ SString &sPlatformResourceRoots, /* in */ SString &sAppPaths, /* in */ BOOL fAcquireLock); + + HRESULT SetupBindingPaths(/* in */ SString &sPlatformResourceRoots, + /* in */ SString &sAppPaths, + /* in */ BOOL fAcquireLock); // Getters/Setter inline ExecutionContext *GetExecutionContext(); @@ -111,6 +58,9 @@ namespace BINDER_SPACE inline LONG GetVersion(); inline void IncrementVersion(); + private: + HRESULT AddAssemblyMapEntry(SString& simpleName, SString& fileName); + private: Volatile m_cVersion; SString m_applicationName; diff --git a/src/coreclr/binder/inc/defaultassemblybinder.h b/src/coreclr/binder/inc/defaultassemblybinder.h index 3d35854e09f3ff..72f95fe620fdd1 100644 --- a/src/coreclr/binder/inc/defaultassemblybinder.h +++ b/src/coreclr/binder/inc/defaultassemblybinder.h @@ -38,6 +38,9 @@ class DefaultAssemblyBinder final : public AssemblyBinder HRESULT SetupBindingPaths(SString &sTrustedPlatformAssemblies, SString &sPlatformResourceRoots, SString &sAppPaths); + + HRESULT SetupBindingPaths(SString &PlatformResourceRoots, + SString &AppPaths); HRESULT BindToSystem(BINDER_SPACE::Assembly **ppSystemAssembly); diff --git a/src/coreclr/binder/inc/utils.hpp b/src/coreclr/binder/inc/utils.hpp index 54a6c79d853bdb..75af40f400ebd7 100644 --- a/src/coreclr/binder/inc/utils.hpp +++ b/src/coreclr/binder/inc/utils.hpp @@ -29,7 +29,7 @@ namespace BINDER_SPACE BOOL IsFileNotFound(HRESULT hr); HRESULT GetNextPath(const SString& paths, SString::CIterator& startPos, SString& outPath); - HRESULT GetNextTPAPath(const SString& paths, SString::CIterator& startPos, bool dllOnly, SString& outPath, SString& simpleName, bool& isNativeImage); + HRESULT GetNextTPAPath(const SString& paths, SString::CIterator& startPos, bool dllOnly, SString& outPath, SString& simpleName); }; #endif diff --git a/src/coreclr/binder/utils.cpp b/src/coreclr/binder/utils.cpp index f1b916ec9dc1ab..86334a6e524521 100644 --- a/src/coreclr/binder/utils.cpp +++ b/src/coreclr/binder/utils.cpp @@ -140,11 +140,9 @@ namespace BINDER_SPACE return hr; } - HRESULT GetNextTPAPath(const SString& paths, SString::CIterator& startPos, bool dllOnly, SString& outPath, SString& simpleName, bool& isNativeImage) + HRESULT GetNextTPAPath(const SString& paths, SString::CIterator& startPos, bool dllOnly, SString& outPath, SString& simpleName) { HRESULT hr = S_OK; - isNativeImage = false; - HRESULT pathResult = S_OK; while(true) { @@ -178,25 +176,16 @@ namespace BINDER_SPACE GO_WITH_HRESULT(E_INVALIDARG); } - const SString sNiDll(SString::Literal, W(".ni.dll")); - const SString sNiExe(SString::Literal, W(".ni.exe")); const SString sDll(SString::Literal, W(".dll")); const SString sExe(SString::Literal, W(".exe")); - if (dllOnly && (outPath.EndsWithCaseInsensitive(sExe) || - outPath.EndsWithCaseInsensitive(sNiExe))) + if (dllOnly && (outPath.EndsWithCaseInsensitive(sExe))) { // Skip exe files when the caller requested only dlls continue; } - if (outPath.EndsWithCaseInsensitive(sNiDll) || - outPath.EndsWithCaseInsensitive(sNiExe)) - { - simpleName.Set(outPath, iSimpleNameStart, outPath.End() - 7); - isNativeImage = true; - } - else if (outPath.EndsWithCaseInsensitive(sDll) || + if (outPath.EndsWithCaseInsensitive(sDll) || outPath.EndsWithCaseInsensitive(sExe)) { simpleName.Set(outPath, iSimpleNameStart, outPath.End() - 4); diff --git a/src/coreclr/dlls/mscoree/exports.cpp b/src/coreclr/dlls/mscoree/exports.cpp index f1cfb2faf5c88d..e62caa8746f1a0 100644 --- a/src/coreclr/dlls/mscoree/exports.cpp +++ b/src/coreclr/dlls/mscoree/exports.cpp @@ -277,7 +277,7 @@ int coreclr_initialize( if (hostContract != nullptr) { - HostInformation::SetContract(hostContract); + HostInformation::Instance().SetContract(hostContract); } if (pinvokeOverride != nullptr) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index da003c270e146a..44b1d5d3d047ad 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -29,6 +29,12 @@ struct configuration ::free((void*)entry_assembly_argv[i]); } ::free(entry_assembly_argv); + + for (uint32_t i = 0; i < host_assemblies.assembly_count; ++i) + { + ::free(host_assemblies.assembly_names[i]); + } + ::free(host_assemblies.assembly_names); } // @@ -38,6 +44,10 @@ struct configuration // CLR path - user supplied location of coreclr binary and managed assemblies. string_t clr_path; + pal::string_utf8_t core_root; + + pal::string_utf8_t core_libraries; + // The full path to the Supplied managed entry assembly. string_t entry_assembly_fullpath; @@ -58,6 +68,12 @@ struct configuration // configured .env file to load dotenv dotenv_configuration; + + // the list of assembly names that the runtime knows about + host_runtime_assemblies host_assemblies; + + // contains the name minus extension as the key and the name+extension plus a reference to where it's at on disk as the value + std::unordered_map host_file_map; }; namespace envvar @@ -98,71 +114,57 @@ static void wait_for_debugger() } } -// N.B. It seems that CoreCLR doesn't always use the first instance of an assembly on the TPA list +// N.B. It seems that CoreCLR doesn't always use the first instance of an assembly // (for example, ni's may be preferred over il, even if they appear later). Therefore, when building -// the TPA only include the first instance of a simple assembly name to allow users the opportunity to +// the list of assemblies to be used by the runtime, only include the first instance of a simple assembly name to allow users the opportunity to // override Framework assemblies by placing dlls in %CORE_LIBRARIES%. -static string_t build_tpa(const string_t& core_root, const string_t& core_libraries, trusted_platform_assemblies* tpa_items) +// +// build the unordered_map -> store in config -> construct the host_runtime_assemblies for the contract -> store in config -> pass to runtime +static void build_host_assembly_list(const string_t& core_root, const string_t& core_libraries, std::unordered_map& name_file_map) { static const char_t* const tpa_extensions[] = { - W(".ni.dll"), // Probe for .ni.dll first so that it's preferred if ni and il coexist in the same dir W(".dll"), - W(".ni.exe"), W(".exe"), nullptr }; - std::unordered_map name_path_map; - pal::stringstream_t tpa_list; - // Iterate over all extensions. for (const char_t* const* curr_ext = tpa_extensions; *curr_ext != nullptr; ++curr_ext) { const char_t* ext = *curr_ext; - const size_t ext_len = pal::strlen(ext); // Iterate over all supplied directories. + int dir_type = 0; for (const string_t& dir : { core_libraries, core_root }) { if (dir.empty()) continue; assert(dir.back() == pal::dir_delim); - string_t tmp = pal::build_file_list(dir, ext, [&](const char_t* file) - { - string_t file_local{ file }; - string_t file_name { file }; - - // Strip the extension. - if (pal::string_ends_with(file_local, ext_len, ext)) - file_name = file_local.substr(0, file_local.length() - ext_len); - - // Return true if the file is new. - return name_path_map.insert({file_name, file_local}).second; - }); - - // Add to the TPA. - tpa_list << tmp; + pal::add_files_from_directory(dir, ext, dir_type, name_file_map); + dir_type++; } } +} - tpa_items->assembly_count = static_cast(name_path_map.size()); - tpa_items->assembly_filepaths = new char*[tpa_items->assembly_count]; - tpa_items->basenames = new char*[tpa_items->assembly_count]; +static void build_contract_assembly_list(std::unordered_map& name_file_map, host_runtime_assemblies& assemblies) +{ + assemblies.assembly_count = static_cast(name_file_map.size()); + assemblies.assembly_names = new char*[assemblies.assembly_count]; - // Convert the paths into a string and return it int32_t item_count = 0; - for (auto item = name_path_map.begin(); item != name_path_map.end(); ++item) + for (auto item = name_file_map.begin(); item != name_file_map.end(); ++item) { - string_t base_name = item->first; - tpa_items->basenames[item_count] = (char*)pal::convert_to_utf8(base_name.c_str()).c_str(); - tpa_items->assembly_filepaths[item_count] = (char*)pal::convert_to_utf8(item->second.c_str()).c_str(); + pal::string_utf8_t file_name = item->first; + size_t len = file_name.size() + 1; + assemblies.assembly_names[item_count] = new char[len]; + + ::strncpy(assemblies.assembly_names[item_count], file_name.c_str(), len - 1); + assemblies.assembly_names[item_count][len - 1] = '\0'; item_count++; } - - return tpa_list.str(); } static bool try_get_export(pal::mod_t mod, const char* symbol, void** fptr) @@ -228,6 +230,50 @@ static void log_error_info(const char* line) std::fprintf(stderr, "%s\n", line); } +const host_runtime_assemblies* HOST_CONTRACT_CALLTYPE get_assemblies( + void* contract_context) +{ + configuration* config = static_cast(contract_context); + return &config->host_assemblies; +} + +const char* HOST_CONTRACT_CALLTYPE resolve_assembly_to_path( + const char* assembly_name, + void* contract_context) +{ + configuration* config = static_cast(contract_context); + + auto assembly = config->host_file_map.find(assembly_name); + + pal::string_utf8_t full_file; + if (assembly != config->host_file_map.end()) + { + host_file_t file = assembly->second; + pal::string_utf8_t file_name = file.name; + + if (file.dtype == host_file_t::core_root) + { + full_file = config->core_root + file_name; + } + else if (file.dtype == host_file_t::core_libraries) + { + full_file = config->core_libraries + file_name; + } + else + { + full_file = file_name; + } + } + + size_t len = full_file.size() + 1; + char* ret = new char[len]; + + ::strncpy(ret, full_file.c_str(), len - 1); + ret[len - 1] = '\0'; + + return ret; +} + size_t HOST_CONTRACT_CALLTYPE get_runtime_property( const char* key, char* value_buffer, @@ -257,7 +303,7 @@ size_t HOST_CONTRACT_CALLTYPE get_runtime_property( return -1; } -static int run(const configuration& config) +static int run(configuration& config) { platform_specific_actions actions; @@ -269,6 +315,8 @@ static int run(const configuration& config) host_contract.size = sizeof(host_runtime_contract); host_contract.context = (void*)&config; host_contract.get_runtime_property = &get_runtime_property; + host_contract.get_assemblies = &get_assemblies; + host_contract.resolve_assembly_to_path = &resolve_assembly_to_path; host_contract.bundle_probe = nullptr; host_contract.pinvoke_override = nullptr; @@ -324,18 +372,12 @@ static int run(const configuration& config) native_search_dirs << core_root << pal::env_path_delim; } - string_t tpa_list = build_tpa(core_root, core_libs, &host_contract.probing_paths.trusted_platform_assemblies); - probing_lookup_paths* native_paths = &host_contract.probing_paths.native_dll_search_directories; + config.core_root = pal::convert_to_utf8(core_root.c_str()); + config.core_libraries = pal::convert_to_utf8(core_libs.c_str()); - native_paths->dir_count = static_cast(native_search_dirs_set.size()); - native_paths->dirs = new char*[native_paths->dir_count]; + build_host_assembly_list(core_root, core_libs, config.host_file_map); + build_contract_assembly_list(config.host_file_map, config.host_assemblies); - int dir_count = 0; - for (const auto& native_dir : native_search_dirs_set) - { - native_paths->dirs[dir_count] = (char*)pal::convert_to_utf8(native_dir.c_str()).c_str(); - dir_count++; - } { // Load hostpolicy if requested. @@ -372,7 +414,6 @@ static int run(const configuration& config) (void)try_get_export(coreclr_mod, "coreclr_set_error_writer", (void**)&coreclr_set_error_writer_func); // Construct CoreCLR properties. - pal::string_utf8_t tpa_list_utf8 = pal::convert_to_utf8(tpa_list.c_str()); pal::string_utf8_t app_path_utf8 = pal::convert_to_utf8(app_path.c_str()); pal::string_utf8_t native_search_dirs_utf8 = pal::convert_to_utf8(native_search_dirs.str().c_str()); @@ -387,11 +428,6 @@ static int run(const configuration& config) std::vector propertyKeys; std::vector propertyValues; - // TRUSTED_PLATFORM_ASSEMBLIES - // - The list of complete paths to each of the fully trusted assemblies - propertyKeys.push_back("TRUSTED_PLATFORM_ASSEMBLIES"); - propertyValues.push_back(tpa_list_utf8.c_str()); - // APP_PATHS // - The list of paths which will be probed by the assembly loader propertyKeys.push_back("APP_PATHS"); diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 38ced1eb87bbad..5a0a07a4ff143d 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -14,6 +14,7 @@ #include #include #include +#include #include #include #include @@ -65,6 +66,22 @@ namespace pal const char_t env_path_delim = W(';'); const char_t nativelib_ext[] = W(".dll"); const char_t coreclr_lib[] = W("coreclr"); +} + +struct host_file_t +{ + enum host_dir_type + { + core_libraries, + core_root + }; + + pal::string_utf8_t name; // file name + extension + host_dir_type dtype; +}; + +namespace pal +{ inline int strcmp(const char_t* str1, const char_t* str2) { return wcscmp(str1, str2); } inline size_t strlen(const char_t* str) { return wcslen(str); } @@ -148,6 +165,57 @@ namespace pal // Forward declaration void ensure_trailing_delimiter(pal::string_t& dir); + inline bool string_ends_with(const string_t& str, size_t suffix_len, const char_t* suffix); + inline string_utf8_t convert_to_utf8(const char_t* str); + + inline void add_files_from_directory( + const string_t& dir, + const char_t* ext, + const int dir_type, + std::unordered_map& files) + { + assert(ext != nullptr); + + string_t dir_local = dir; + dir_local.append(W("*")); + dir_local.append(ext); + + const size_t ext_len = pal::strlen(ext); + + WIN32_FIND_DATA data; + HANDLE findHandle = ::FindFirstFileW(dir_local.data(), &data); + if (findHandle == INVALID_HANDLE_VALUE) + return; + + do + { + if (!(data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) + { + // ToLower for case-insensitive comparisons + char_t* fileNameChar = data.cFileName; + while (*fileNameChar) + { + *fileNameChar = towlower(*fileNameChar); + fileNameChar++; + } + + string_t file_local{ data.cFileName }; + string_t file_name { data.cFileName }; + + // Strip the extension. + if (pal::string_ends_with(file_local, ext_len, ext)) + file_name = file_local.substr(0, file_local.length() - ext_len); + + host_file_t f; + f.name = convert_to_utf8(file_local.c_str()); + f.dtype = static_cast(dir_type); + + files.insert({convert_to_utf8(file_name.c_str()), f}); + } + } while (FALSE != ::FindNextFileW(findHandle, &data)); + + ::FindClose(findHandle); + } inline string_t build_file_list( const string_t& dir, @@ -353,6 +421,22 @@ namespace pal const char_t nativelib_ext[] = W(".so"); #endif const char_t coreclr_lib[] = W("libcoreclr"); +} + +struct host_file_t +{ + enum host_dir_type + { + core_libraries, + core_root + }; + + string_t name; // file name + extension + host_dir_type dtype; +}; + +namespace pal +{ inline int strcmp(const char_t* str1, const char_t* str2) { return ::strcmp(str1, str2); } inline size_t strlen(const char_t* str) { return ::strlen(str); } @@ -516,8 +600,76 @@ namespace pal template bool string_ends_with(const string_t& str, const char_t(&suffix)[LEN]); bool string_ends_with(const string_t& str, size_t suffix_len, const char_t* suffix); + inline string_utf8_t convert_to_utf8(const char_t* str); void ensure_trailing_delimiter(pal::string_t& dir); + inline void add_files_from_directory( + const string_t& dir, + const char_t* ext, + const int dir_type, + std::unordered_map& files) + { + assert(ext != nullptr); + const size_t ext_len = pal::strlen(ext); + + DIR* dir = opendir(directory.c_str()); + if (dir == nullptr) + return; + + // For all entries in the directory + struct dirent* entry; + while ((entry = readdir(dir)) != nullptr) + { +#if HAVE_DIRENT_D_TYPE + int dirEntryType = entry->d_type; +#else + int dirEntryType = DT_UNKNOWN; +#endif + + // We are interested in files only + switch (dirEntryType) + { + case DT_REG: + break; + + // Handle symlinks and file systems that do not support d_type + case DT_LNK: + case DT_UNKNOWN: + { + string_t full_filename{directory}; + full_filename.append(entry->d_name); + if (!does_file_exist(full_filename.c_str())) + continue; + } + break; + + default: + continue; + } + + // Check if the extension matches the one we are looking for + if (!pal::string_ends_with(entry->d_name, ext_len, ext)) + continue; + + // Make sure if we have an assembly with multiple extensions present, + // we insert only one version of it. + string_t file_local{ entry->d_name }; + string_t file_name { entry->d_name }; + + // Strip the extension. + if (pal::string_ends_with(file_local, ext_len, ext)) + file_name = file_local.substr(0, file_local.length() - ext_len); + + host_file_t file; + f.name = convert_to_utf8(file_local.c_str()); + f.dtype = static_cast(dir_type); + + files.insert({convert_to_utf8(file_name.c_str()), file}); + } + + closedir(dir); + } + inline string_t build_file_list( const string_t& directory, const char_t* ext, diff --git a/src/coreclr/inc/hostinformation.h b/src/coreclr/inc/hostinformation.h index d57b4729d30e68..17e17adeab41c5 100644 --- a/src/coreclr/inc/hostinformation.h +++ b/src/coreclr/inc/hostinformation.h @@ -5,12 +5,37 @@ #define _HOSTINFORMATION_H_ #include +#include "simplefilenamemap.h" class HostInformation { public: - static void SetContract(_In_ host_runtime_contract* hostContract); - static bool GetProperty(_In_z_ const char* name, SString& value); + static HostInformation& Instance() + { + static HostInformation instance; + return instance; + } + + ~HostInformation(); + + void SetContract(_In_ host_runtime_contract* hostContract); + bool GetProperty(_In_z_ const char* name, SString& value); + LPCWSTR GetEntryAssembly(); + + // flip this back to const SimpleNameToFileNameMap& + SimpleNameToFileNameMap* GetHostAssemblyNames(); + LPCWSTR ResolveHostAssemblyPath(LPCWSTR simpleName); + +private: + HostInformation() {} // Private constructor to prevent instantiation + HostInformation(const HostInformation&) = delete; // Delete copy constructor + HostInformation& operator=(const HostInformation&) = delete; // Delete assignment operator + + LPCSTR ConvertToUTF8(LPCWSTR utf16String); + LPCWSTR ConvertToUnicode(const char* utf8String); + +private: + SimpleNameToFileNameMap* m_simpleFileNameMap; }; #endif // _HOSTINFORMATION_H_ diff --git a/src/coreclr/inc/simplefilenamemap.h b/src/coreclr/inc/simplefilenamemap.h new file mode 100644 index 00000000000000..574e7308452617 --- /dev/null +++ b/src/coreclr/inc/simplefilenamemap.h @@ -0,0 +1,64 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. +// + +//============================================================================================= +// Data structures for Simple Name -> File Name hash + +#ifndef __SIMPLEFILENAMEMAP_H_ +#define __SIMPLEFILENAMEMAP_H_ + +#include "clrtypes.h" +#include "shash.h" + +// Entry in SHash table that maps namespace to list of files +struct SimpleNameToFileNameMapEntry +{ + LPWSTR m_wszSimpleName; + LPWSTR m_wszILFileName; +}; + +// SHash traits for Namespace -> FileNameList hash +class SimpleNameToFileNameMapTraits : public NoRemoveSHashTraits< DefaultSHashTraits< SimpleNameToFileNameMapEntry > > +{ + public: + typedef PCWSTR key_t; + static const SimpleNameToFileNameMapEntry Null() { SimpleNameToFileNameMapEntry e; e.m_wszSimpleName = nullptr; return e; } + static bool IsNull(const SimpleNameToFileNameMapEntry & e) { return e.m_wszSimpleName == nullptr; } + static key_t GetKey(const SimpleNameToFileNameMapEntry & e) + { + key_t key; + key = e.m_wszSimpleName; + return key; + } + static count_t Hash(const key_t &str) + { + SString ssKey(SString::Literal, str); + return ssKey.HashCaseInsensitive(); + } + static BOOL Equals(const key_t &lhs, const key_t &rhs) { LIMITED_METHOD_CONTRACT; return (SString::_wcsicmp(lhs, rhs) == 0); } + + void OnDestructPerEntryCleanupAction(const SimpleNameToFileNameMapEntry & e) + { + if (e.m_wszILFileName == nullptr) + { + // Don't delete simple name here since it's a filename only entry and will be cleaned up + // by the SimpleName -> FileName entry which reuses the same filename pointer. + return; + } + + if (e.m_wszSimpleName != nullptr) + { + delete [] e.m_wszSimpleName; + } + if (e.m_wszILFileName != nullptr) + { + delete [] e.m_wszILFileName; + } + } + static const bool s_DestructPerEntryCleanupAction = true; +}; + +typedef SHash SimpleNameToFileNameMap; + +#endif // __SIMPLEFILENAMEMAP_H_ diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index e4ac7c34285889..be624350b02bf6 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -314,9 +314,10 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, if (g_EntryAssemblyPath == NULL) { // Store the entry assembly path for diagnostic purposes (for example, dumps) - size_t len = u16_strlen(pwzAssemblyPath) + 1; + LPCWSTR pEntryAssembly = HostInformation::Instance().GetEntryAssembly(); + size_t len = u16_strlen(pEntryAssembly) + 1; NewArrayHolder path { new WCHAR[len] }; - wcscpy_s(path, len, pwzAssemblyPath); + wcscpy_s(path, len, pEntryAssembly); g_EntryAssemblyPath = path.Extract(); } @@ -627,6 +628,20 @@ HRESULT CorHost2::CreateAppDomainWithManager( pDomain->SetNativeDllSearchDirectories(pwzNativeDllSearchDirectories); + // If the tpa list has not been provided, use the host contract to get the list of assemblies being used. + // Otherwise, use the TPA list provided by the host. + if (pwzTrustedPlatformAssemblies == nullptr) + { + SString sPlatformResourceRoots(pwzPlatformResourceRoots); + SString sAppPaths(pwzAppPaths); + + DefaultAssemblyBinder *pBinder = pDomain->GetDefaultBinder(); + _ASSERTE(pBinder != NULL); + IfFailThrow(pBinder->SetupBindingPaths( + sPlatformResourceRoots, + sAppPaths)); + } + else { SString sTrustedPlatformAssemblies(pwzTrustedPlatformAssemblies); SString sPlatformResourceRoots(pwzPlatformResourceRoots); diff --git a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h index 95c568f50acbfe..38a9922875640f 100644 --- a/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h +++ b/src/coreclr/vm/eventing/eventpipe/ep-rt-coreclr.h @@ -76,7 +76,7 @@ ep_rt_entrypoint_assembly_name_get_utf8 (void) { const ep_char8_t* entrypoint_assembly_name_local; SString assembly_name; - if (HostInformation::GetProperty (HOST_PROPERTY_ENTRY_ASSEMBLY_NAME, assembly_name)) + if (HostInformation::Instance().GetProperty (HOST_PROPERTY_ENTRY_ASSEMBLY_NAME, assembly_name)) { entrypoint_assembly_name_local = reinterpret_cast(assembly_name.GetCopyOfUTF8String ()); } diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index b440f6f2168ab7..d3f77e64172e1b 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -9,6 +9,14 @@ namespace host_runtime_contract* s_hostContract = nullptr; } +HostInformation::~HostInformation() +{ + if (m_simpleFileNameMap != nullptr) + { + delete m_simpleFileNameMap; + } +} + void HostInformation::SetContract(_In_ host_runtime_contract* hostContract) { _ASSERTE(s_hostContract == nullptr); @@ -40,3 +48,128 @@ bool HostInformation::GetProperty(_In_z_ const char* name, SString& value) return lenActual > 0 && lenActual <= len; } + +LPCWSTR HostInformation::GetEntryAssembly() +{ + if ((s_hostContract == nullptr) || (s_hostContract->entry_assembly == nullptr)) + return L""; + + LPCWSTR entryAssembly = ConvertToUnicode(s_hostContract->entry_assembly); + + size_t len = wcslen(entryAssembly) + 1; + LPWSTR ret = new WCHAR[len]; + + if (ret == nullptr) + { + return L""; + } + + wcscpy_s(ret, len, entryAssembly); + return ret; +} + +SimpleNameToFileNameMap* HostInformation::GetHostAssemblyNames() +{ + if (m_simpleFileNameMap != nullptr) + return m_simpleFileNameMap; + + m_simpleFileNameMap = new SimpleNameToFileNameMap(); + + if (s_hostContract == nullptr || s_hostContract->get_assemblies == nullptr) + return m_simpleFileNameMap; + + const host_runtime_assemblies* assemblies; + assemblies = s_hostContract->get_assemblies(s_hostContract->context); + + if (assemblies == nullptr) + return m_simpleFileNameMap; + + for (uint32_t i = 0; i < assemblies->assembly_count; i++) + { + LPCWSTR assemblyName = ConvertToUnicode(assemblies->assembly_names[i]); + if (assemblyName != nullptr) + { + size_t len = wcslen(assemblyName) + 1; + LPWSTR wszSimpleName = new WCHAR[len]; + + if (wszSimpleName != nullptr) + { + wcscpy_s(wszSimpleName, len, assemblyName); + + SimpleNameToFileNameMapEntry mapEntry; + mapEntry.m_wszSimpleName = wszSimpleName; + mapEntry.m_wszILFileName = nullptr; + + m_simpleFileNameMap->AddOrReplace(mapEntry); + } + } + } + + return m_simpleFileNameMap; +} + +LPCWSTR HostInformation::ResolveHostAssemblyPath(LPCWSTR simpleName) +{ + LPCWSTR ret; + + if (s_hostContract == nullptr || s_hostContract->resolve_assembly_to_path == nullptr) + return simpleName; + + LPCSTR utf8SimpleName = ConvertToUTF8(simpleName); + + if (utf8SimpleName == nullptr) + return simpleName; + + LPCSTR assemblyPath = s_hostContract->resolve_assembly_to_path(utf8SimpleName, s_hostContract->context); + + if (assemblyPath == nullptr) + { + ret = simpleName; + } + else + { + ret = ConvertToUnicode(assemblyPath); + } + + delete utf8SimpleName; + + return ret; +} + +LPCSTR HostInformation::ConvertToUTF8(LPCWSTR utf16String) +{ + int length = WideCharToMultiByte(CP_ACP, 0, utf16String, -1, NULL, 0, NULL, NULL); + + if (length <= 0) + return ""; + + char* ret = new char[length]; + + if (ret == nullptr) + { + return ""; + } + + length = WideCharToMultiByte(CP_ACP, 0, utf16String, -1, ret, length, NULL, NULL); + + return (length > 0) ? ret : ""; +} + +LPCWSTR HostInformation::ConvertToUnicode(const char* utf8String) +{ + int length = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, NULL, 0); + + if (length <= 0) + return L""; + + LPWSTR ret = new WCHAR[length]; + + if (ret == nullptr) + { + return L""; + } + + length = MultiByteToWideChar(CP_UTF8, 0, utf8String, -1, ret, length); + + return (length > 0) ? ret : L""; +} diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 840212abb0251e..43432fa4ebf332 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -23,24 +23,10 @@ #define HOST_PROPERTY_PLATFORM_RESOURCE_ROOTS "PLATFORM_RESOURCE_ROOTS" #define HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES "TRUSTED_PLATFORM_ASSEMBLIES" -struct trusted_platform_assemblies +struct host_runtime_assemblies { - uint32_t assembly_count; - char** basenames; /* Foo.dll */ - char** assembly_filepaths; /* /blah/blah/blah/Foo.dll */ -}; - -struct probing_lookup_paths -{ - uint32_t dir_count; - char** dirs; -}; - -struct probing_path_properties -{ - trusted_platform_assemblies trusted_platform_assemblies; - probing_lookup_paths native_dll_search_directories; - probing_lookup_paths platform_resource_roots; + uint32_t assembly_count; + char** assembly_names; }; struct host_runtime_contract @@ -50,10 +36,6 @@ struct host_runtime_contract // Context for the contract. Pass to functions taking a contract context. void* context; - char* entry_assembly; - - probing_path_properties probing_paths; - // Get the value of a runtime property. // Returns the length of the property including a terminating null or -1 if not found. size_t(HOST_CONTRACT_CALLTYPE* get_runtime_property)( @@ -75,6 +57,16 @@ struct host_runtime_contract const void* (HOST_CONTRACT_CALLTYPE* pinvoke_override)( const char* library_name, const char* entry_point_name); + + // Gets the list of assemblies (name plus extension) identified by the host. + const host_runtime_assemblies* (HOST_CONTRACT_CALLTYPE* get_assemblies)( + void* contract_context); + + const char* (HOST_CONTRACT_CALLTYPE* resolve_assembly_to_path)( + const char* assembly_name, + void* contract_context); + + char* entry_assembly; }; #endif // __HOST_RUNTIME_CONTRACT_H__ diff --git a/src/native/corehost/hostmisc/utils.cpp b/src/native/corehost/hostmisc/utils.cpp index 482a0c8dced1c1..42d692b2aef984 100644 --- a/src/native/corehost/hostmisc/utils.cpp +++ b/src/native/corehost/hostmisc/utils.cpp @@ -501,37 +501,6 @@ pal::string_t to_upper(const pal::char_t* in) { return ret; } -void destroy_tpa_list(trusted_platform_assemblies* tpa_list) -{ - if (tpa_list == nullptr) - { - return; - } - - for (uint32_t i = 0; i < tpa_list->assembly_count; ++i) - { - delete tpa_list->basenames[i]; - delete tpa_list->assembly_filepaths[i]; - } - - delete[] tpa_list->basenames; - delete[] tpa_list->assembly_filepaths; -} - -void destroy_probing_path_list(probing_lookup_paths* probing_paths) -{ - if (probing_paths == nullptr) - { - return; - } - - for (uint32_t i = 0; i < probing_paths->dir_count; ++i) - { - delete probing_paths->dirs[i]; - } - - delete[] probing_paths->dirs; -} #define TEST_ONLY_MARKER "d38cc827-e34f-4453-9df4-1e796e9f1d07" diff --git a/src/native/corehost/hostmisc/utils.h b/src/native/corehost/hostmisc/utils.h index 34b655c8f67c9a..c8811b248875b3 100644 --- a/src/native/corehost/hostmisc/utils.h +++ b/src/native/corehost/hostmisc/utils.h @@ -122,9 +122,6 @@ pal::string_t get_host_version_description(); pal::string_t to_lower(const pal::char_t* in); pal::string_t to_upper(const pal::char_t* in); -void destroy_tpa_list(trusted_platform_assemblies* tpa_list); -void destroy_probing_path_list(probing_lookup_paths* probing_paths); - // Retrieves environment variable which is only used for testing. // This will return the value of the variable only if the product binary is stamped // with test-only marker. diff --git a/src/native/corehost/hostpolicy/deps_resolver.cpp b/src/native/corehost/hostpolicy/deps_resolver.cpp index b5bafb536cd560..06409cd7db4e38 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.cpp +++ b/src/native/corehost/hostpolicy/deps_resolver.cpp @@ -5,6 +5,7 @@ #include #include #include +#include #include #include @@ -100,10 +101,10 @@ namespace void add_tpa_asset( const deps_asset_t& asset, const pal::string_t& resolved_path, - name_to_resolved_asset_map_t* items) + std::unique_ptr& host_assemblies) { - name_to_resolved_asset_map_t::iterator existing = items->find(asset.name); - if (existing == items->end()) + name_to_resolved_asset_map_t::iterator existing = host_assemblies->find(asset.name); + if (existing == host_assemblies->end()) { if (trace::is_enabled()) { @@ -113,7 +114,7 @@ namespace asset.file_version.as_str().c_str()); } - items->emplace(asset.name, deps_resolved_asset_t(asset, resolved_path)); + host_assemblies->emplace(asset.name, deps_resolved_asset_t(asset, resolved_path)); } } @@ -124,13 +125,13 @@ namespace void get_dir_assemblies( const pal::string_t& dir, const pal::string_t& dir_name, - name_to_resolved_asset_map_t* items) + std::unique_ptr& host_assemblies) { version_t empty; trace::verbose(_X("Adding files from %s dir %s"), dir_name.c_str(), dir.c_str()); // Managed extensions in priority order, pick DLL over EXE and NI over IL. - const pal::string_t managed_ext[] = { _X(".ni.dll"), _X(".dll"), _X(".ni.exe"), _X(".exe") }; + const pal::string_t managed_ext[] = { _X(".dll"), _X(".exe") }; // List of files in the dir std::vector files; @@ -156,11 +157,11 @@ namespace } // Already added entry for this asset, by priority order skip this ext - if (items->count(file_name)) + if (host_assemblies->count(file_name)) { trace::verbose(_X("Skipping %s because the %s already exists in %s assemblies"), file.c_str(), - items->find(file_name)->second.asset.relative_path.c_str(), + host_assemblies->find(file_name)->second.asset.relative_path.c_str(), dir_name.c_str()); continue; @@ -180,7 +181,7 @@ namespace file_path.c_str()); deps_asset_t asset(file_name, file, empty, empty); - add_tpa_asset(asset, file_path, items); + add_tpa_asset(asset, file_path, host_assemblies); } } } @@ -214,47 +215,6 @@ pal::string_t deps_resolver_t::get_lookup_probe_directories() return directories; } -void deps_resolver_t::create_probing_paths(const std::deque& probing_items, probing_lookup_paths& probing_paths) -{ - // Add the probing paths to piece of the host_runtime_contract - probing_paths.dir_count = static_cast(probing_items.size()); - probing_paths.dirs = new char*[probing_paths.dir_count]; - - int dir_count = 0; - for (const auto& probing_item : probing_items) - { - probing_paths.dirs[dir_count] = new char[probing_item.size() + 1]; - pal::pal_utf8string(probing_item, probing_paths.dirs[dir_count], probing_item.size() + 1); - dir_count++; - } -} - -void deps_resolver_t::create_tpa_list(const name_to_resolved_asset_map_t& items, trusted_platform_assemblies& tpa_list, pal::string_t& output) -{ - tpa_list.assembly_count = static_cast(items.size()); - tpa_list.assembly_filepaths = new char*[tpa_list.assembly_count]; - tpa_list.basenames = new char*[tpa_list.assembly_count]; - - // Convert the paths into a string and return it - int32_t item_count = 0; - for (auto item = items.begin(); item != items.end(); ++item) - { - pal::string_t base_name = get_filename(item->second.resolved_path); - size_t base_length = base_name.size() + 1; - size_t assembly_name_length = item->second.resolved_path.size() + 1; - - tpa_list.basenames[item_count] = new char[base_length]; - tpa_list.assembly_filepaths[item_count] = new char[assembly_name_length]; - - pal::pal_utf8string(base_name, tpa_list.basenames[item_count], base_length); - pal::pal_utf8string(item->second.resolved_path, tpa_list.assembly_filepaths[item_count], assembly_name_length); - - output.append(item->second.resolved_path); - output.push_back(PATH_SEPARATOR); - item_count++; - } -} - void deps_resolver_t::setup_probe_config( const std::vector& shared_stores, const std::vector& additional_probe_paths) @@ -460,12 +420,11 @@ bool report_missing_assembly_in_manifest(const deps_entry_t& entry, bool continu * Resolve the TPA assembly locations */ bool deps_resolver_t::resolve_tpa_list( - pal::string_t* output, - trusted_platform_assemblies* tpa_list, + std::unique_ptr& host_assemblies, std::unordered_set* breadcrumb, bool ignore_missing_assemblies) -{ - name_to_resolved_asset_map_t items; +{ + host_assemblies = std::make_unique(); auto process_entry = [&](const pal::string_t& deps_dir, const deps_entry_t& entry, int fx_level) -> bool { @@ -486,8 +445,8 @@ bool deps_resolver_t::resolve_tpa_list( pal::string_t resolved_path; - name_to_resolved_asset_map_t::iterator existing = items.find(entry.asset.name); - if (existing == items.end()) + name_to_resolved_asset_map_t::iterator existing = host_assemblies->find(entry.asset.name); + if (existing == host_assemblies->end()) { bool found_in_bundle = false; if (probe_deps_entry(entry, deps_dir, fx_level, &resolved_path, found_in_bundle)) @@ -496,7 +455,7 @@ bool deps_resolver_t::resolve_tpa_list( // The runtime directly probes the bundle-manifest using a host-callback. if (!found_in_bundle) { - add_tpa_asset(entry.asset, resolved_path, &items); + add_tpa_asset(entry.asset, resolved_path, host_assemblies); } return true; @@ -537,12 +496,12 @@ bool deps_resolver_t::resolve_tpa_list( resolved_path.c_str(), entry.asset.assembly_version.as_str().c_str(), entry.asset.file_version.as_str().c_str()); existing_entry = nullptr; - items.erase(existing); + host_assemblies->erase(existing); if (!found_in_bundle) { deps_asset_t asset(entry.asset.name, entry.asset.relative_path, entry.asset.assembly_version, entry.asset.file_version); - add_tpa_asset(asset, resolved_path, &items); + add_tpa_asset(asset, resolved_path, host_assemblies); } } } @@ -574,7 +533,7 @@ bool deps_resolver_t::resolve_tpa_list( bundle::runner_t::app()->probe(managed_app_name) == nullptr) { deps_asset_t asset(get_filename_without_ext(m_managed_app), managed_app_name, version_t(), version_t()); - add_tpa_asset(asset, m_managed_app, &items); + add_tpa_asset(asset, m_managed_app, host_assemblies); } // Add the app's entries @@ -593,7 +552,7 @@ bool deps_resolver_t::resolve_tpa_list( if (!get_app_deps().exists()) { // Obtain the local assemblies in the app dir. - get_dir_assemblies(m_app_dir, _X("local"), &items); + get_dir_assemblies(m_app_dir, _X("local"), host_assemblies); } } @@ -631,9 +590,6 @@ bool deps_resolver_t::resolve_tpa_list( } } - // Now that we have the complete list, store it in the host_runtime_contract and as a ; delimted string. - create_tpa_list(items, *tpa_list, *output); - return true; } @@ -792,7 +748,6 @@ void deps_resolver_t::enum_app_context_deps_files(std::function* breadcrumb) { bool is_resources = asset_type == deps_entry_t::asset_types::resources; @@ -931,9 +886,6 @@ bool deps_resolver_t::resolve_probe_dirs( } } - // Add the probing paths to piece of the host_runtime_contract - create_probing_paths(probing_items, *probing_paths); - output->append(non_serviced); return true; @@ -946,24 +898,25 @@ bool deps_resolver_t::resolve_probe_dirs( // Parameters: // probe_paths - Pointer to struct containing fields that will contain // resolved path ordering. +// host_assemblies - The name + path of the assemblies that made up the TPA list // breadcrumb - set of breadcrumb paths - or null if no breadcrumbs should be collected. // ignore_missing_assemblies - if set to true, resolving TPA assemblies will not fail if an assembly can't be found on disk // instead such entry will simply be ignored. // // -bool deps_resolver_t::resolve_probe_paths(probe_paths_t* probe_paths, host_runtime_contract* host_contract, std::unordered_set* breadcrumb, bool ignore_missing_assemblies) +bool deps_resolver_t::resolve_probe_paths(probe_paths_t* probe_paths, std::unique_ptr& host_assemblies, std::unordered_set* breadcrumb, bool ignore_missing_assemblies) { - if (!resolve_tpa_list(&probe_paths->tpa, &host_contract->probing_paths.trusted_platform_assemblies, breadcrumb, ignore_missing_assemblies)) + if (!resolve_tpa_list(host_assemblies, breadcrumb, ignore_missing_assemblies)) { return false; } - if (!resolve_probe_dirs(deps_entry_t::asset_types::native, &probe_paths->native, &host_contract->probing_paths.native_dll_search_directories, breadcrumb)) + if (!resolve_probe_dirs(deps_entry_t::asset_types::native, &probe_paths->native, breadcrumb)) { return false; } - if (!resolve_probe_dirs(deps_entry_t::asset_types::resources, &probe_paths->resources, &host_contract->probing_paths.platform_resource_roots, breadcrumb)) + if (!resolve_probe_dirs(deps_entry_t::asset_types::resources, &probe_paths->resources, breadcrumb)) { return false; } diff --git a/src/native/corehost/hostpolicy/deps_resolver.h b/src/native/corehost/hostpolicy/deps_resolver.h index 065872faca5cb8..b5e45993bca664 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.h +++ b/src/native/corehost/hostpolicy/deps_resolver.h @@ -6,6 +6,7 @@ #include #include +#include #include "pal.h" #include "args.h" @@ -131,7 +132,7 @@ class deps_resolver_t bool resolve_probe_paths( probe_paths_t* probe_paths, - host_runtime_contract* host_contract, + std::unique_ptr& host_assemblies, std::unordered_set* breadcrumb, bool ignore_missing_assemblies = false); @@ -194,11 +195,6 @@ class deps_resolver_t const std::vector& shared_stores, const std::vector& additional_probe_paths); - void create_probing_paths(const std::deque& probing_items, - probing_lookup_paths& probing_paths); - - void create_tpa_list(const name_to_resolved_asset_map_t& items, trusted_platform_assemblies& tpa_list, pal::string_t& output); - void init_known_entry_path( const deps_entry_t& entry, const pal::string_t& path); @@ -215,8 +211,7 @@ class deps_resolver_t private: // Resolve order for TPA lookup. bool resolve_tpa_list( - pal::string_t* output, - trusted_platform_assemblies* tpa_list, + std::unique_ptr& host_assemblies, std::unordered_set* breadcrumb, bool ignore_missing_assemblies); @@ -224,7 +219,6 @@ class deps_resolver_t bool resolve_probe_dirs( deps_entry_t::asset_types asset_type, pal::string_t* output, - probing_lookup_paths* probing_paths, std::unordered_set* breadcrumb); // Probe entry in probe configurations and deps dir. diff --git a/src/native/corehost/hostpolicy/hostpolicy.cpp b/src/native/corehost/hostpolicy/hostpolicy.cpp index abf4ca9ed7a41d..3e4fd929811215 100644 --- a/src/native/corehost/hostpolicy/hostpolicy.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy.cpp @@ -978,8 +978,10 @@ SHARED_API int HOSTPOLICY_CALLTYPE corehost_resolve_component_dependencies( return StatusCode::HostInvalidState; } + // TO DO: Think of how resolve_probe_paths changes as a result of looking up paths on the host. probe_paths_t probe_paths; - if (!resolver.resolve_probe_paths(&probe_paths, &context->host_contract, nullptr, /* ignore_missing_assemblies */ true)) + std::unique_ptr host_assemblies = std::make_unique(); + if (!resolver.resolve_probe_paths(&probe_paths, host_assemblies, nullptr, /* ignore_missing_assemblies */ true)) { return StatusCode::ResolverResolveFailure; } diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index eeae5702e11384..3af3750e4e6571 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -133,6 +133,63 @@ namespace return -1; } + + const host_runtime_assemblies* HOST_CONTRACT_CALLTYPE get_runtime_framework_assemblies( + void* contract_context) + { + hostpolicy_context_t* context = static_cast(contract_context); + host_runtime_assemblies* assemblies = new host_runtime_assemblies(); + + assemblies->assembly_count = static_cast(context->host_assemblies->size()); + assemblies->assembly_names = new char*[assemblies->assembly_count]; + + int32_t item_count = 0; + for (auto item = context->host_assemblies->begin(); item != context->host_assemblies->end(); ++item) + { + pal::string_t file_name = item->second.asset.name; + + size_t len = file_name.size() + 1; + assemblies->assembly_names[item_count] = new char[len]; + + pal::pal_utf8string(file_name, assemblies->assembly_names[item_count], len); + item_count++; + } + + return assemblies; + } + + const char* HOST_CONTRACT_CALLTYPE resolve_assembly_to_path( + const char* assembly_name, + void* contract_context) + { + hostpolicy_context_t* context = static_cast(contract_context); + + if (context->host_assemblies == nullptr) + return assembly_name; + + pal::string_t host_assembly_name; + if (!pal::clr_palstring(assembly_name, &host_assembly_name)) + { + trace::warning(_X("Failed to convert assembly_name [%hs] to UTF8"), assembly_name); + return assembly_name; + } + + char* ret; + name_to_resolved_asset_map_t::iterator host_assembly = context->host_assemblies->find(host_assembly_name); + if (host_assembly != context->host_assemblies->end()) + { + size_t len = host_assembly->second.resolved_path.size() + 1; + ret = new char[len]; + + pal::pal_utf8string(host_assembly->second.resolved_path, ret, len); + } + else + { + ret = const_cast(assembly_name); + } + + return ret; + } } bool hostpolicy_context_t::should_read_rid_fallback_graph(const hostpolicy_init_t &init) @@ -194,6 +251,8 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c pal::pal_utf8string(application, host_contract.entry_assembly, entry_assembly_length); host_contract.get_runtime_property = &get_runtime_property; + host_contract.get_assemblies = &get_runtime_framework_assemblies; + host_contract.resolve_assembly_to_path = &resolve_assembly_to_path; pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); if (!coreclr_properties.add(_STRINGIFY(HOST_PROPERTY_RUNTIME_CONTRACT), buffer)) @@ -203,6 +262,8 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c } } + host_assemblies = std::make_unique(); + probe_paths_t probe_paths; // Setup breadcrumbs. @@ -215,14 +276,14 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c breadcrumbs.insert(policy_name); breadcrumbs.insert(policy_name + _X(",") + policy_version); - if (!resolver.resolve_probe_paths(&probe_paths, &host_contract, &breadcrumbs)) + if (!resolver.resolve_probe_paths(&probe_paths, host_assemblies, &breadcrumbs)) { return StatusCode::ResolverResolveFailure; } } else { - if (!resolver.resolve_probe_paths(&probe_paths, &host_contract, nullptr)) + if (!resolver.resolve_probe_paths(&probe_paths, host_assemblies, nullptr)) { return StatusCode::ResolverResolveFailure; } @@ -248,6 +309,10 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c clr_dir = get_directory(clr_path); } +/* + TO DO: Figure out if single file is impacted by taking this code out and + not providing a TPA list. + // If this is a self-contained single-file bundle, // System.Private.CoreLib.dll is expected to be within the bundle, unless it is explicitly excluded from the bundle. // In all other cases, @@ -266,6 +331,7 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c probe_paths.tpa.append(corelib_path); } +*/ pal::string_t fx_deps_str; if (resolver.is_framework_dependent()) @@ -299,7 +365,6 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c pal::string_t app_base; resolver.get_app_dir(&app_base); - coreclr_properties.add(common_property::TrustedPlatformAssemblies, probe_paths.tpa.c_str()); coreclr_properties.add(common_property::NativeDllSearchDirectories, probe_paths.native.c_str()); coreclr_properties.add(common_property::PlatformResourceRoots, probe_paths.resources.c_str()); coreclr_properties.add(common_property::AppContextBaseDirectory, app_base.c_str()); diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.h b/src/native/corehost/hostpolicy/hostpolicy_context.h index 8979ba228da781..9a1fe5ac343db3 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.h +++ b/src/native/corehost/hostpolicy/hostpolicy_context.h @@ -9,6 +9,7 @@ #include "args.h" #include "coreclr.h" #include +#include "deps_resolver.h" #include #include "hostpolicy_init.h" @@ -25,12 +26,13 @@ struct hostpolicy_context_t mutable std::unordered_set breadcrumbs; coreclr_property_bag_t coreclr_properties; - probing_path_properties probing_path_properties; std::unique_ptr coreclr; host_runtime_contract host_contract; + std::unique_ptr host_assemblies; + int initialize(const hostpolicy_init_t &hostpolicy_init, const arguments_t &args, bool enable_breadcrumbs); public: // static From 93ab723a8c8ddaecce3c2eff128216394edf882d Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Fri, 12 Apr 2024 14:30:27 -0700 Subject: [PATCH 06/11] Clean ups --- src/coreclr/binder/assemblybindercommon.cpp | 3 +- src/coreclr/hosts/corerun/corerun.cpp | 30 +++---- src/coreclr/inc/hostinformation.h | 6 +- src/coreclr/vm/corhost.cpp | 9 ++- src/coreclr/vm/hostinformation.cpp | 80 ++++++++----------- src/native/corehost/host_runtime_contract.h | 9 +-- .../hostpolicy/hostpolicy_context.cpp | 13 +-- 7 files changed, 70 insertions(+), 80 deletions(-) diff --git a/src/coreclr/binder/assemblybindercommon.cpp b/src/coreclr/binder/assemblybindercommon.cpp index 08b8f6d1766aea..c15be517597974 100644 --- a/src/coreclr/binder/assemblybindercommon.cpp +++ b/src/coreclr/binder/assemblybindercommon.cpp @@ -899,8 +899,7 @@ namespace BINDER_SPACE if (pTpaEntry->m_wszILFileName == nullptr) { _ASSERTE(pTpaEntry->m_wszSimpleName != nullptr); - LPCWSTR lpFileName = HostInformation::Instance().ResolveHostAssemblyPath(pTpaEntry->m_wszSimpleName); - fileName.Set(lpFileName); + HostInformation::Instance().ResolveHostAssemblyPath(simpleName, fileName); } else { diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 44b1d5d3d047ad..127baeede0203f 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -30,11 +30,11 @@ struct configuration } ::free(entry_assembly_argv); - for (uint32_t i = 0; i < host_assemblies.assembly_count; ++i) + for (uint32_t i = 0; i < host_assembly_count; ++i) { - ::free(host_assemblies.assembly_names[i]); + ::free(host_assemblies[i]); } - ::free(host_assemblies.assembly_names); + ::free(host_assemblies); } // @@ -70,7 +70,8 @@ struct configuration dotenv dotenv_configuration; // the list of assembly names that the runtime knows about - host_runtime_assemblies host_assemblies; + uint32_t host_assembly_count; + char** host_assemblies; // contains the name minus extension as the key and the name+extension plus a reference to where it's at on disk as the value std::unordered_map host_file_map; @@ -148,10 +149,10 @@ static void build_host_assembly_list(const string_t& core_root, const string_t& } } -static void build_contract_assembly_list(std::unordered_map& name_file_map, host_runtime_assemblies& assemblies) +static void build_contract_assembly_list(std::unordered_map& name_file_map, char** assemblies, uint32_t& assemblyCount) { - assemblies.assembly_count = static_cast(name_file_map.size()); - assemblies.assembly_names = new char*[assemblies.assembly_count]; + assemblyCount = static_cast(name_file_map.size()); + assemblies = new char*[assemblyCount]; int32_t item_count = 0; for (auto item = name_file_map.begin(); item != name_file_map.end(); ++item) @@ -159,10 +160,10 @@ static void build_contract_assembly_list(std::unordered_mapfirst; size_t len = file_name.size() + 1; - assemblies.assembly_names[item_count] = new char[len]; + assemblies[item_count] = new char[len]; - ::strncpy(assemblies.assembly_names[item_count], file_name.c_str(), len - 1); - assemblies.assembly_names[item_count][len - 1] = '\0'; + ::strncpy(assemblies[item_count], file_name.c_str(), len - 1); + assemblies[item_count][len - 1] = '\0'; item_count++; } } @@ -230,11 +231,13 @@ static void log_error_info(const char* line) std::fprintf(stderr, "%s\n", line); } -const host_runtime_assemblies* HOST_CONTRACT_CALLTYPE get_assemblies( +char** HOST_CONTRACT_CALLTYPE get_assemblies( + uint32_t& assembly_count, void* contract_context) { configuration* config = static_cast(contract_context); - return &config->host_assemblies; + assembly_count = config->host_assembly_count; + return config->host_assemblies; } const char* HOST_CONTRACT_CALLTYPE resolve_assembly_to_path( @@ -376,8 +379,7 @@ static int run(configuration& config) config.core_libraries = pal::convert_to_utf8(core_libs.c_str()); build_host_assembly_list(core_root, core_libs, config.host_file_map); - build_contract_assembly_list(config.host_file_map, config.host_assemblies); - + build_contract_assembly_list(config.host_file_map, config.host_assemblies, config.host_assembly_count); { // Load hostpolicy if requested. diff --git a/src/coreclr/inc/hostinformation.h b/src/coreclr/inc/hostinformation.h index 17e17adeab41c5..92d8e06ab4d70e 100644 --- a/src/coreclr/inc/hostinformation.h +++ b/src/coreclr/inc/hostinformation.h @@ -6,6 +6,7 @@ #include #include "simplefilenamemap.h" +#include "sstring.h" class HostInformation { @@ -20,11 +21,10 @@ class HostInformation void SetContract(_In_ host_runtime_contract* hostContract); bool GetProperty(_In_z_ const char* name, SString& value); - LPCWSTR GetEntryAssembly(); + void GetEntryAssemblyName(/*Out*/ SString& entryAssemblyName); - // flip this back to const SimpleNameToFileNameMap& SimpleNameToFileNameMap* GetHostAssemblyNames(); - LPCWSTR ResolveHostAssemblyPath(LPCWSTR simpleName); + void ResolveHostAssemblyPath(const SString& simpleName, /*Out*/ SString& resolvedPath); private: HostInformation() {} // Private constructor to prevent instantiation diff --git a/src/coreclr/vm/corhost.cpp b/src/coreclr/vm/corhost.cpp index be624350b02bf6..bec72efc962997 100644 --- a/src/coreclr/vm/corhost.cpp +++ b/src/coreclr/vm/corhost.cpp @@ -314,10 +314,13 @@ HRESULT CorHost2::ExecuteAssembly(DWORD dwAppDomainId, if (g_EntryAssemblyPath == NULL) { // Store the entry assembly path for diagnostic purposes (for example, dumps) - LPCWSTR pEntryAssembly = HostInformation::Instance().GetEntryAssembly(); - size_t len = u16_strlen(pEntryAssembly) + 1; + SString ssEntryAssemblyName; + HostInformation::Instance().GetEntryAssemblyName(ssEntryAssemblyName); + + const WCHAR* pEntryAssemblyName = ssEntryAssemblyName.GetUnicode(); + size_t len = u16_strlen(pEntryAssemblyName) + 1; NewArrayHolder path { new WCHAR[len] }; - wcscpy_s(path, len, pEntryAssembly); + wcscpy_s(path, len, pEntryAssemblyName); g_EntryAssemblyPath = path.Extract(); } diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index d3f77e64172e1b..a5b59f82ad0a2d 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -49,23 +49,16 @@ bool HostInformation::GetProperty(_In_z_ const char* name, SString& value) return lenActual > 0 && lenActual <= len; } -LPCWSTR HostInformation::GetEntryAssembly() +void HostInformation::GetEntryAssemblyName(SString& entryAssemblyName) { if ((s_hostContract == nullptr) || (s_hostContract->entry_assembly == nullptr)) - return L""; - - LPCWSTR entryAssembly = ConvertToUnicode(s_hostContract->entry_assembly); - - size_t len = wcslen(entryAssembly) + 1; - LPWSTR ret = new WCHAR[len]; - - if (ret == nullptr) { - return L""; - } + entryAssemblyName.Set(W("")); + return; + } - wcscpy_s(ret, len, entryAssembly); - return ret; + entryAssemblyName.SetUTF8(s_hostContract->entry_assembly); + entryAssemblyName.Normalize(); } SimpleNameToFileNameMap* HostInformation::GetHostAssemblyNames() @@ -78,62 +71,59 @@ SimpleNameToFileNameMap* HostInformation::GetHostAssemblyNames() if (s_hostContract == nullptr || s_hostContract->get_assemblies == nullptr) return m_simpleFileNameMap; - const host_runtime_assemblies* assemblies; - assemblies = s_hostContract->get_assemblies(s_hostContract->context); + char** assemblies; + uint32_t assemblyCount = 0; + assemblies = s_hostContract->get_assemblies(assemblyCount, s_hostContract->context); if (assemblies == nullptr) return m_simpleFileNameMap; - for (uint32_t i = 0; i < assemblies->assembly_count; i++) + for (uint32_t i = 0; i < assemblyCount; i++) { - LPCWSTR assemblyName = ConvertToUnicode(assemblies->assembly_names[i]); - if (assemblyName != nullptr) - { - size_t len = wcslen(assemblyName) + 1; - LPWSTR wszSimpleName = new WCHAR[len]; - - if (wszSimpleName != nullptr) - { - wcscpy_s(wszSimpleName, len, assemblyName); + SimpleNameToFileNameMapEntry mapEntry; + SString assemblyName; - SimpleNameToFileNameMapEntry mapEntry; - mapEntry.m_wszSimpleName = wszSimpleName; - mapEntry.m_wszILFileName = nullptr; + assemblyName.SetUTF8(assemblies[i]); + assemblyName.Normalize(); - m_simpleFileNameMap->AddOrReplace(mapEntry); - } + LPWSTR wszSimpleName = new WCHAR[assemblyName.GetCount() + 1]; + if (wszSimpleName == nullptr) + { + return m_simpleFileNameMap; } + wcscpy_s(wszSimpleName, assemblyName.GetCount() + 1, assemblyName.GetUnicode()); + + mapEntry.m_wszSimpleName = wszSimpleName; + mapEntry.m_wszILFileName = nullptr; + + m_simpleFileNameMap->AddOrReplace(mapEntry); } return m_simpleFileNameMap; } -LPCWSTR HostInformation::ResolveHostAssemblyPath(LPCWSTR simpleName) +void HostInformation::ResolveHostAssemblyPath(const SString& simpleName, SString& resolvedPath) { - LPCWSTR ret; - if (s_hostContract == nullptr || s_hostContract->resolve_assembly_to_path == nullptr) - return simpleName; - - LPCSTR utf8SimpleName = ConvertToUTF8(simpleName); + { + resolvedPath.Set(simpleName); + return; + } - if (utf8SimpleName == nullptr) - return simpleName; + SString ssUtf8SimpleName(simpleName); + simpleName.ConvertToUTF8(ssUtf8SimpleName); - LPCSTR assemblyPath = s_hostContract->resolve_assembly_to_path(utf8SimpleName, s_hostContract->context); + LPCSTR assemblyPath = s_hostContract->resolve_assembly_to_path(ssUtf8SimpleName.GetUTF8(), s_hostContract->context); if (assemblyPath == nullptr) { - ret = simpleName; + resolvedPath.Set(simpleName); } else { - ret = ConvertToUnicode(assemblyPath); + resolvedPath.SetUTF8(assemblyPath); + resolvedPath.Normalize(); } - - delete utf8SimpleName; - - return ret; } LPCSTR HostInformation::ConvertToUTF8(LPCWSTR utf16String) diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 43432fa4ebf332..3f97a24998e11a 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -23,12 +23,6 @@ #define HOST_PROPERTY_PLATFORM_RESOURCE_ROOTS "PLATFORM_RESOURCE_ROOTS" #define HOST_PROPERTY_TRUSTED_PLATFORM_ASSEMBLIES "TRUSTED_PLATFORM_ASSEMBLIES" -struct host_runtime_assemblies -{ - uint32_t assembly_count; - char** assembly_names; -}; - struct host_runtime_contract { size_t size; @@ -59,7 +53,8 @@ struct host_runtime_contract const char* entry_point_name); // Gets the list of assemblies (name plus extension) identified by the host. - const host_runtime_assemblies* (HOST_CONTRACT_CALLTYPE* get_assemblies)( + char** (HOST_CONTRACT_CALLTYPE* get_assemblies)( + /*out*/ uint32_t& assembly_count, void* contract_context); const char* (HOST_CONTRACT_CALLTYPE* resolve_assembly_to_path)( diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index 3af3750e4e6571..b32b1931893c62 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -134,14 +134,15 @@ namespace return -1; } - const host_runtime_assemblies* HOST_CONTRACT_CALLTYPE get_runtime_framework_assemblies( + char** HOST_CONTRACT_CALLTYPE get_runtime_framework_assemblies( + uint32_t& assembly_count, void* contract_context) { hostpolicy_context_t* context = static_cast(contract_context); - host_runtime_assemblies* assemblies = new host_runtime_assemblies(); - assemblies->assembly_count = static_cast(context->host_assemblies->size()); - assemblies->assembly_names = new char*[assemblies->assembly_count]; + char** assemblies; + assembly_count = static_cast(context->host_assemblies->size()); + assemblies = new char*[assembly_count]; int32_t item_count = 0; for (auto item = context->host_assemblies->begin(); item != context->host_assemblies->end(); ++item) @@ -149,9 +150,9 @@ namespace pal::string_t file_name = item->second.asset.name; size_t len = file_name.size() + 1; - assemblies->assembly_names[item_count] = new char[len]; + assemblies[item_count] = new char[len]; - pal::pal_utf8string(file_name, assemblies->assembly_names[item_count], len); + pal::pal_utf8string(file_name, assemblies[item_count], len); item_count++; } From 18d2488f2d0909e646a1554c311ca5e7cba7764f Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Tue, 16 Apr 2024 14:23:17 -0700 Subject: [PATCH 07/11] Add a destory callback on the host side to clean up the host assembly list --- src/coreclr/hosts/corerun/corerun.cpp | 11 +++++++++++ src/coreclr/vm/hostinformation.cpp | 4 +++- src/native/corehost/host_runtime_contract.h | 4 ++++ .../corehost/hostpolicy/hostpolicy_context.cpp | 13 +++++++++++++ 4 files changed, 31 insertions(+), 1 deletion(-) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 127baeede0203f..9a6e062b6b399a 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -240,6 +240,17 @@ char** HOST_CONTRACT_CALLTYPE get_assemblies( return config->host_assemblies; } +void HOST_CONTRACT_CALLTYPE destroy_assemblies( + char** assemblies, + uint32_t assembly_count) +{ + for (uint32_t i = 0; i < assembly_count; ++i) + { + delete[] assemblies[i]; + } + delete[] assemblies; +} + const char* HOST_CONTRACT_CALLTYPE resolve_assembly_to_path( const char* assembly_name, void* contract_context) diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index a5b59f82ad0a2d..b8cda59b932517 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -89,7 +89,7 @@ SimpleNameToFileNameMap* HostInformation::GetHostAssemblyNames() LPWSTR wszSimpleName = new WCHAR[assemblyName.GetCount() + 1]; if (wszSimpleName == nullptr) { - return m_simpleFileNameMap; + continue; } wcscpy_s(wszSimpleName, assemblyName.GetCount() + 1, assemblyName.GetUnicode()); @@ -99,6 +99,8 @@ SimpleNameToFileNameMap* HostInformation::GetHostAssemblyNames() m_simpleFileNameMap->AddOrReplace(mapEntry); } + s_hostContract->destroy_assemblies(assemblies, assemblyCount); + return m_simpleFileNameMap; } diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 3f97a24998e11a..586bd46574953d 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -56,6 +56,10 @@ struct host_runtime_contract char** (HOST_CONTRACT_CALLTYPE* get_assemblies)( /*out*/ uint32_t& assembly_count, void* contract_context); + + void (HOST_CONTRACT_CALLTYPE* destroy_assemblies)( + char** assemblies, + uint32_t assembly_count); const char* (HOST_CONTRACT_CALLTYPE* resolve_assembly_to_path)( const char* assembly_name, diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index b32b1931893c62..3a4ec9a2b4a2fe 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -159,6 +159,18 @@ namespace return assemblies; } + void HOST_CONTRACT_CALLTYPE destroy_assemblies( + char** assemblies, + uint32_t assembly_count) + { + for (uint32_t i = 0; i < assembly_count; ++i) + { + delete[] assemblies[i]; + } + + delete[] assemblies; + } + const char* HOST_CONTRACT_CALLTYPE resolve_assembly_to_path( const char* assembly_name, void* contract_context) @@ -253,6 +265,7 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c host_contract.get_runtime_property = &get_runtime_property; host_contract.get_assemblies = &get_runtime_framework_assemblies; + host_contract.destroy_assemblies = &destroy_assemblies; host_contract.resolve_assembly_to_path = &resolve_assembly_to_path; pal::char_t buffer[STRING_LENGTH("0xffffffffffffffff")]; pal::snwprintf(buffer, ARRAY_SIZE(buffer), _X("0x%zx"), (size_t)(&host_contract)); From 0a0b40d959239eb46754f989e5fe7aef650611a2 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Wed, 22 May 2024 11:28:10 -0400 Subject: [PATCH 08/11] Fixed some usage shennanigans for the osx / linux coreclr build --- src/coreclr/hosts/corerun/corerun.hpp | 12 ++++++------ src/coreclr/inc/hostinformation.h | 2 ++ src/coreclr/vm/hostinformation.cpp | 2 ++ src/native/corehost/hostpolicy/deps_resolver.cpp | 2 +- src/native/corehost/hostpolicy/hostpolicy.cpp | 2 +- .../corehost/hostpolicy/hostpolicy_context.cpp | 2 +- 6 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.hpp b/src/coreclr/hosts/corerun/corerun.hpp index 5a0a07a4ff143d..4757db4a131d1b 100644 --- a/src/coreclr/hosts/corerun/corerun.hpp +++ b/src/coreclr/hosts/corerun/corerun.hpp @@ -169,14 +169,14 @@ namespace pal inline string_utf8_t convert_to_utf8(const char_t* str); inline void add_files_from_directory( - const string_t& dir, + const string_t& directory, const char_t* ext, const int dir_type, std::unordered_map& files) { assert(ext != nullptr); - string_t dir_local = dir; + string_t dir_local = directory; dir_local.append(W("*")); dir_local.append(ext); @@ -431,7 +431,7 @@ struct host_file_t core_root }; - string_t name; // file name + extension + pal::string_t name; // file name + extension host_dir_type dtype; }; @@ -604,7 +604,7 @@ namespace pal void ensure_trailing_delimiter(pal::string_t& dir); inline void add_files_from_directory( - const string_t& dir, + const string_t& directory, const char_t* ext, const int dir_type, std::unordered_map& files) @@ -661,8 +661,8 @@ namespace pal file_name = file_local.substr(0, file_local.length() - ext_len); host_file_t file; - f.name = convert_to_utf8(file_local.c_str()); - f.dtype = static_cast(dir_type); + file.name = convert_to_utf8(file_local.c_str()); + file.dtype = static_cast(dir_type); files.insert({convert_to_utf8(file_name.c_str()), file}); } diff --git a/src/coreclr/inc/hostinformation.h b/src/coreclr/inc/hostinformation.h index 92d8e06ab4d70e..d5cade43fc49bb 100644 --- a/src/coreclr/inc/hostinformation.h +++ b/src/coreclr/inc/hostinformation.h @@ -31,8 +31,10 @@ class HostInformation HostInformation(const HostInformation&) = delete; // Delete copy constructor HostInformation& operator=(const HostInformation&) = delete; // Delete assignment operator +/* LPCSTR ConvertToUTF8(LPCWSTR utf16String); LPCWSTR ConvertToUnicode(const char* utf8String); +*/ private: SimpleNameToFileNameMap* m_simpleFileNameMap; diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index b8cda59b932517..d51f0bbccb9e6a 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -128,6 +128,7 @@ void HostInformation::ResolveHostAssemblyPath(const SString& simpleName, SString } } +/* LPCSTR HostInformation::ConvertToUTF8(LPCWSTR utf16String) { int length = WideCharToMultiByte(CP_ACP, 0, utf16String, -1, NULL, 0, NULL, NULL); @@ -165,3 +166,4 @@ LPCWSTR HostInformation::ConvertToUnicode(const char* utf8String) return (length > 0) ? ret : L""; } +*/ diff --git a/src/native/corehost/hostpolicy/deps_resolver.cpp b/src/native/corehost/hostpolicy/deps_resolver.cpp index 06409cd7db4e38..428183dc4c9d5c 100644 --- a/src/native/corehost/hostpolicy/deps_resolver.cpp +++ b/src/native/corehost/hostpolicy/deps_resolver.cpp @@ -424,7 +424,7 @@ bool deps_resolver_t::resolve_tpa_list( std::unordered_set* breadcrumb, bool ignore_missing_assemblies) { - host_assemblies = std::make_unique(); + host_assemblies = std::unique_ptr(new name_to_resolved_asset_map_t()); auto process_entry = [&](const pal::string_t& deps_dir, const deps_entry_t& entry, int fx_level) -> bool { diff --git a/src/native/corehost/hostpolicy/hostpolicy.cpp b/src/native/corehost/hostpolicy/hostpolicy.cpp index 3e4fd929811215..3c190b93350de5 100644 --- a/src/native/corehost/hostpolicy/hostpolicy.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy.cpp @@ -980,7 +980,7 @@ SHARED_API int HOSTPOLICY_CALLTYPE corehost_resolve_component_dependencies( // TO DO: Think of how resolve_probe_paths changes as a result of looking up paths on the host. probe_paths_t probe_paths; - std::unique_ptr host_assemblies = std::make_unique(); + std::unique_ptr host_assemblies = std::unique_ptr(new name_to_resolved_asset_map_t()); if (!resolver.resolve_probe_paths(&probe_paths, host_assemblies, nullptr, /* ignore_missing_assemblies */ true)) { return StatusCode::ResolverResolveFailure; diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index 3a4ec9a2b4a2fe..518fae08fd99b6 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -276,7 +276,7 @@ int hostpolicy_context_t::initialize(const hostpolicy_init_t &hostpolicy_init, c } } - host_assemblies = std::make_unique(); + host_assemblies = std::unique_ptr(new name_to_resolved_asset_map_t()); probe_paths_t probe_paths; From 7d8b6713bb48e80c4e31e1c28fd59562b8492fc8 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Wed, 22 May 2024 19:29:11 -0400 Subject: [PATCH 09/11] Adjust to get mono to build --- src/coreclr/hosts/corerun/corerun.cpp | 4 ++-- src/coreclr/vm/hostinformation.cpp | 2 +- src/native/corehost/host_runtime_contract.h | 2 +- src/native/corehost/hostpolicy/hostpolicy_context.cpp | 6 +++--- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/coreclr/hosts/corerun/corerun.cpp b/src/coreclr/hosts/corerun/corerun.cpp index 9a6e062b6b399a..413ca8730b8bbc 100644 --- a/src/coreclr/hosts/corerun/corerun.cpp +++ b/src/coreclr/hosts/corerun/corerun.cpp @@ -232,11 +232,11 @@ static void log_error_info(const char* line) } char** HOST_CONTRACT_CALLTYPE get_assemblies( - uint32_t& assembly_count, + uint32_t* assembly_count, void* contract_context) { configuration* config = static_cast(contract_context); - assembly_count = config->host_assembly_count; + *assembly_count = config->host_assembly_count; return config->host_assemblies; } diff --git a/src/coreclr/vm/hostinformation.cpp b/src/coreclr/vm/hostinformation.cpp index d51f0bbccb9e6a..9f6850e5c9e38e 100644 --- a/src/coreclr/vm/hostinformation.cpp +++ b/src/coreclr/vm/hostinformation.cpp @@ -73,7 +73,7 @@ SimpleNameToFileNameMap* HostInformation::GetHostAssemblyNames() char** assemblies; uint32_t assemblyCount = 0; - assemblies = s_hostContract->get_assemblies(assemblyCount, s_hostContract->context); + assemblies = s_hostContract->get_assemblies(&assemblyCount, s_hostContract->context); if (assemblies == nullptr) return m_simpleFileNameMap; diff --git a/src/native/corehost/host_runtime_contract.h b/src/native/corehost/host_runtime_contract.h index 586bd46574953d..cf8ea9aaf8b2fb 100644 --- a/src/native/corehost/host_runtime_contract.h +++ b/src/native/corehost/host_runtime_contract.h @@ -54,7 +54,7 @@ struct host_runtime_contract // Gets the list of assemblies (name plus extension) identified by the host. char** (HOST_CONTRACT_CALLTYPE* get_assemblies)( - /*out*/ uint32_t& assembly_count, + /*out*/ uint32_t* assembly_count, void* contract_context); void (HOST_CONTRACT_CALLTYPE* destroy_assemblies)( diff --git a/src/native/corehost/hostpolicy/hostpolicy_context.cpp b/src/native/corehost/hostpolicy/hostpolicy_context.cpp index 518fae08fd99b6..2258f90293c740 100644 --- a/src/native/corehost/hostpolicy/hostpolicy_context.cpp +++ b/src/native/corehost/hostpolicy/hostpolicy_context.cpp @@ -135,14 +135,14 @@ namespace } char** HOST_CONTRACT_CALLTYPE get_runtime_framework_assemblies( - uint32_t& assembly_count, + uint32_t* assembly_count, void* contract_context) { hostpolicy_context_t* context = static_cast(contract_context); char** assemblies; - assembly_count = static_cast(context->host_assemblies->size()); - assemblies = new char*[assembly_count]; + *assembly_count = static_cast(context->host_assemblies->size()); + assemblies = new char*[*assembly_count]; int32_t item_count = 0; for (auto item = context->host_assemblies->begin(); item != context->host_assemblies->end(); ++item) From 5ae1b0142dbd382289c05bba90aae1eef4936288 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Wed, 22 May 2024 21:10:44 -0400 Subject: [PATCH 10/11] Update GetProperty usage --- src/coreclr/vm/gcheaputilities.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/vm/gcheaputilities.cpp b/src/coreclr/vm/gcheaputilities.cpp index 2f588ae6bdaec1..b8871abacb11dc 100644 --- a/src/coreclr/vm/gcheaputilities.cpp +++ b/src/coreclr/vm/gcheaputilities.cpp @@ -187,7 +187,7 @@ HMODULE LoadStandaloneGc(LPCWSTR libFileName, LPCWSTR libFilePath) } SString appBase; - if (HostInformation::GetProperty("APP_CONTEXT_BASE_DIRECTORY", appBase)) + if (HostInformation::Instance().GetProperty("APP_CONTEXT_BASE_DIRECTORY", appBase)) { PathString libPath = appBase.GetUnicode(); libPath.Append(libFileName); From 9fd6e6c53887bd183988ab09dd1e556fd8c2a7a6 Mon Sep 17 00:00:00 2001 From: Steve Pfister Date: Mon, 17 Jun 2024 10:34:58 -0400 Subject: [PATCH 11/11] Start to modify tests around modified contract --- .../HostApiInvokerApp/HostRuntimeContract.cs | 4 +++ src/libraries/externals.csproj | 5 +++ src/native/corehost/hostpolicy/hostpolicy.cpp | 1 - .../corehost/test/mockcoreclr/mockcoreclr.cpp | 35 ++++++++++++++++++- 4 files changed, 43 insertions(+), 2 deletions(-) diff --git a/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostRuntimeContract.cs b/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostRuntimeContract.cs index 4ecf59b2761ace..a260db758f11ca 100644 --- a/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostRuntimeContract.cs +++ b/src/installer/tests/Assets/Projects/HostApiInvokerApp/HostRuntimeContract.cs @@ -18,6 +18,10 @@ internal struct host_runtime_contract public delegate* unmanaged[Stdcall] get_runtime_property; public delegate* unmanaged[Stdcall] bundle_probe; public IntPtr pinvoke_override; + public delegate* unmanaged[Stdcall] get_assemblies; + public delegate* unmanaged[Stdcall] destroy_assemblies; + public delegate* unmanaged[Stdcall] resolve_assembly_to_path; + public byte* entry_assembly; } #pragma warning restore CS0649 diff --git a/src/libraries/externals.csproj b/src/libraries/externals.csproj index 6aa753ec79b239..3425274d30475e 100644 --- a/src/libraries/externals.csproj +++ b/src/libraries/externals.csproj @@ -27,6 +27,8 @@ + <_HostSymbols Include="$(DotNetHostBinDir)$(LibPrefix)hostfxr$(LibSuffix)$(SymbolsSuffix)" /> + <_HostSymbols Include="$(DotNetHostBinDir)$(LibPrefix)hostpolicy$(LibSuffix)$(SymbolsSuffix)" /> @@ -82,6 +84,8 @@ + + @@ -120,6 +124,7 @@ + host_assemblies = std::unique_ptr(new name_to_resolved_asset_map_t()); if (!resolver.resolve_probe_paths(&probe_paths, host_assemblies, nullptr, /* ignore_missing_assemblies */ true)) diff --git a/src/native/corehost/test/mockcoreclr/mockcoreclr.cpp b/src/native/corehost/test/mockcoreclr/mockcoreclr.cpp index 3ea15bbf813495..4f0e1ba2cd8493 100644 --- a/src/native/corehost/test/mockcoreclr/mockcoreclr.cpp +++ b/src/native/corehost/test/mockcoreclr/mockcoreclr.cpp @@ -2,6 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. #include "mockcoreclr.h" +#include "host_runtime_contract.h" #include #include #include @@ -44,9 +45,20 @@ SHARED_API pal::hresult_t STDMETHODCALLTYPE coreclr_initialize( MockLogArg(hostHandle); MockLogArg(domainId); + host_runtime_contract* host_contract; + for (int i = 0; i < propertyCount; ++i) { - MockLogEntry("property", propertyKeys[i], propertyValues[i]); + if (strcmp(propertyKeys[i], "HOST_RUNTIME_CONTRACT") == 0) + { + char* endPtr; + uint64_t contractValue = strtoul(propertyValues[i], nullptr, 0); + host_contract = (host_runtime_contract*)contractValue; + } + else + { + MockLogEntry("property", propertyKeys[i], propertyValues[i]); + } } if (hostHandle != nullptr) @@ -54,6 +66,27 @@ SHARED_API pal::hresult_t STDMETHODCALLTYPE coreclr_initialize( *hostHandle = reinterpret_cast(static_cast(0xdeadbeef)); } + if (host_contract != nullptr) + { + // construct the formerly known as TPA list + char** assemblies; + uint32_t assemblyCount = 0; + std::stringstream asmss; + + assemblies = host_contract->get_assemblies(&assemblyCount, host_contract->context); + + for (int ac = 0; ac < assemblyCount; ac++) + { + const char* assemblyPath = host_contract->resolve_assembly_to_path(assemblies[ac], host_contract->context); + asmss << assemblyPath << ":"; + } + + delete assemblies; + + // for now - name this something else when tests start passing + MockLogEntry("property", "TRUSTED_PLATFORM_ASSEMBLIES", asmss.str()); + } + return StatusCode::Success; }