From 5f90ffa88771c3c42139948c6093d49838600e4a Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 11 Feb 2025 14:59:03 -0800 Subject: [PATCH 1/9] Set AppContext.BaseDirectory and the lookup path for AssemblyDirectory to the directory containing the NativeAOT module --- .../src/System/AppContext.NativeAot.cs | 13 +++++++++++++ .../src/System/AppContext.AnyOS.cs | 2 +- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs index 535eb123ddf0f3..1e2e96b840e5b1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs @@ -36,5 +36,18 @@ internal static void OnUnhandledException(object e) { UnhandledException?.Invoke(/* AppDomain */ null, new UnhandledExceptionEventArgs(e, true)); } + + private static unsafe string GetRuntimeModulePath() + { + delegate* unmanaged ip = &GetRuntimeModulePath; + if (RuntimeAugments.TryGetFullPathToApplicationModule((nint)(void*)ip, out _) is string modulePath) + { + return modulePath; + } + + // If this method isn't in a dynamically loaded module, + // then it's in the executable. In that case, we can use the process path. + return Environment.ProcessPath; + } } } diff --git a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs index b2c83e67dd4538..ed002f35600ccb 100644 --- a/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs +++ b/src/libraries/System.Private.CoreLib/src/System/AppContext.AnyOS.cs @@ -19,7 +19,7 @@ private static string GetBaseDirectoryCore() { // Fallback path for hosts that do not set APP_CONTEXT_BASE_DIRECTORY explicitly #if NATIVEAOT - string? path = Environment.ProcessPath; + string? path = GetRuntimeModulePath(); #else string? path = Assembly.GetEntryAssembly()?.Location; #endif From 5ad0b1ba453457b0dd30ecf3a630c03d96a7c8ed Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Fri, 14 Feb 2025 18:40:18 -0800 Subject: [PATCH 2/9] Fix calling convention --- .../System.Private.CoreLib/src/System/AppContext.NativeAot.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs index 1e2e96b840e5b1..78b3cf2230120c 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs @@ -39,7 +39,7 @@ internal static void OnUnhandledException(object e) private static unsafe string GetRuntimeModulePath() { - delegate* unmanaged ip = &GetRuntimeModulePath; + delegate* ip = &GetRuntimeModulePath; if (RuntimeAugments.TryGetFullPathToApplicationModule((nint)(void*)ip, out _) is string modulePath) { return modulePath; From 0bb7c80f91242cfe493146b1ac79267341c085bd Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 17 Feb 2025 15:48:50 -0800 Subject: [PATCH 3/9] Fix missing using --- .../System.Private.CoreLib/src/System/AppContext.NativeAot.cs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs index 78b3cf2230120c..040cdb7e4ea343 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using Internal.Runtime.Augments; using System.Collections.Generic; using System.Runtime; using System.Runtime.ExceptionServices; From bba4f9e220a9982429cdbfae373b7307077cec17 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Thu, 20 Feb 2025 10:54:23 -0800 Subject: [PATCH 4/9] Rewrite an add comment --- .../src/System/AppContext.NativeAot.cs | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs index 040cdb7e4ea343..e4b354899dd8aa 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/System/AppContext.NativeAot.cs @@ -40,8 +40,11 @@ internal static void OnUnhandledException(object e) private static unsafe string GetRuntimeModulePath() { - delegate* ip = &GetRuntimeModulePath; - if (RuntimeAugments.TryGetFullPathToApplicationModule((nint)(void*)ip, out _) is string modulePath) + // We aren't going to call this method, we just need an address that we know is in this module. + // As this code is NativeAOT only, we know that this method will be AOT compiled into the executable, + // so the entry point address will be in the module. + void* ip = (void*)(delegate*)&GetRuntimeModulePath; + if (RuntimeAugments.TryGetFullPathToApplicationModule((nint)ip, out _) is string modulePath) { return modulePath; } From aaf93c70bda98636469680037860135b5c00e09e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 24 Feb 2025 11:56:02 -0800 Subject: [PATCH 5/9] Add test --- .../CMakeLists.txt | 14 ++++++ .../SharedLibraryDependency.cpp | 10 ++++ .../SharedLibraryDependencyLoading.cs | 23 +++++++++ .../SharedLibraryDependencyLoading.csproj | 43 ++++++++++++++++ .../SharedLibraryHost.cpp | 50 +++++++++++++++++++ 5 files changed, 140 insertions(+) create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/CMakeLists.txt create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.csproj create mode 100644 src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/CMakeLists.txt b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/CMakeLists.txt new file mode 100644 index 00000000000000..311de58864d465 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/CMakeLists.txt @@ -0,0 +1,14 @@ +project (SharedLibrary) +include_directories(${INC_PLATFORM_DIR}) + +add_executable(SharedLibraryHost SharedLibraryHost.cpp) +add_library(SharedLibraryDependency SHARED SharedLibraryDependency.cpp) + +if (CLR_CMAKE_TARGET_UNIX) + target_link_libraries (SharedLibraryHost PRIVATE ${CMAKE_DL_LIBS}) +endif() + +# If there's a dynamic ASAN runtime, then copy it to project output. +if (NOT "${ASAN_RUNTIME}" STREQUAL "") + file(COPY "${ASAN_RUNTIME}" DESTINATION "${CMAKE_CURRENT_BINARY_DIR}") +endif() diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp new file mode 100644 index 00000000000000..4618a530069780 --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp @@ -0,0 +1,10 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#include + + +extern "C" DLL_EXPORT int32_t STDMETHODCALLTYPE MultiplyIntegers(int32_t a, int32_t b) +{ + return a * b; +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs new file mode 100644 index 00000000000000..80c2069eb58e4f --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs @@ -0,0 +1,23 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace SharedLibrary +{ + public class ClassLibrary + { + [UnmanagedCallersOnly(EntryPoint = "MultiplyIntegers", CallConvs = [typeof(CallConvStdcall)])] + public static int MultiplyIntegersExport(int x, int y) + { + return MultiplyIntegers(x, y); + } + + [DllImport("SharedLibraryDependency")] + [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] + [UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])] + public static extern int MultiplyIntegers(int x, int y); + } +} diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.csproj b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.csproj new file mode 100644 index 00000000000000..6d4d2b52a8c28a --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.csproj @@ -0,0 +1,43 @@ + + + Library + BuildAndRun + 0 + true + Shared + false + + true + true + true + + + + nul +mkdir subdir 2>nul +copy /y clang_rt.* native\ +copy /y SharedLibraryDependency.dll subdir\ +copy /y native\SharedLibraryDependencyLoading* subdir\ +copy /y SharedLibraryHost.exe native\SharedLibraryDependencyLoading.exe +]]> + + + + + + + + + + + diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp new file mode 100644 index 00000000000000..fe48c846f810cd --- /dev/null +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp @@ -0,0 +1,50 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +#ifdef TARGET_WINDOWS +#include "windows.h" +#else +#include "dlfcn.h" +#endif +#include + +#ifndef TARGET_WINDOWS +#define __stdcall +#endif + +// typedef for shared lib exported methods +using f_MultiplyIntegers = int32_t(__stdcall *)(int32_t, int32_t); + +#ifdef TARGET_WINDOWS +int __cdecl main() +#else +int main(int argc, char* argv[]) +#endif +{ +#ifdef TARGET_WINDOWS + // We need to include System32 to find system dependencies of SharedLibraryDependencyLoading.dll + HINSTANCE handle = LoadLibraryEx("..\\subdir\\SharedLibraryDependencyLoading.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); +#elif __APPLE__ + void *handle = dlopen("../subdir/SharedLibraryDependencyLoading.dylib", RTLD_LAZY); +#else + void *handle = dlopen("../subdir/SharedLibraryDependencyLoading.so", RTLD_LAZY); +#endif + + if (!handle) + return 1; + +#ifdef TARGET_WINDOWS + f_MultiplyIntegers multiplyIntegers = (f_MultiplyIntegers)GetProcAddress(handle, "MultiplyIntegers"); +#else + f_MultiplyIntegers multiplyIntegers = (f_MultiplyIntegers)dlsym(handle, "MultiplyIntegers"); +#endif + + return multiplyIntegers(10, 7) == 70 ? 100 : 2; +} + +extern "C" const char* __stdcall __asan_default_options() +{ + // NativeAOT is not designed to be unloadable, so we'll leak a few allocations from the shared library. + // Disable leak detection as we don't care about these leaks as of now. + return "detect_leaks=0 use_sigaltstack=0"; +} From 6f871ebb021f1bbd592c8d3246e8cf49a8bd0b9e Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Mon, 24 Feb 2025 13:09:10 -0800 Subject: [PATCH 6/9] Make TryGetFullPathToApplicationModule nullable --- .../src/Internal/DeveloperExperience/DeveloperExperience.cs | 2 +- .../src/Internal/Runtime/Augments/RuntimeAugments.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs index c7253c85b1e1b9..1afcfd799e631b 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/DeveloperExperience/DeveloperExperience.cs @@ -25,7 +25,7 @@ public virtual string CreateStackTraceString(IntPtr ip, bool includeFileInfo, ou } // If we don't have precise information, try to map it at least back to the right module. - string moduleFullFileName = RuntimeAugments.TryGetFullPathToApplicationModule(ip, out IntPtr moduleBase); + string? moduleFullFileName = RuntimeAugments.TryGetFullPathToApplicationModule(ip, out IntPtr moduleBase); // Without any callbacks or the ability to map ip correctly we better admit that we don't know if (string.IsNullOrEmpty(moduleFullFileName)) diff --git a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs index 6fb23a261f3337..00fe842cf9f3d1 100644 --- a/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs +++ b/src/coreclr/nativeaot/System.Private.CoreLib/src/Internal/Runtime/Augments/RuntimeAugments.cs @@ -621,7 +621,7 @@ public static RuntimeTypeHandle GetNullableType(RuntimeTypeHandle nullableType) /// /// Address inside the module /// Module base address - public static unsafe string TryGetFullPathToApplicationModule(IntPtr ip, out IntPtr moduleBase) + public static unsafe string? TryGetFullPathToApplicationModule(IntPtr ip, out IntPtr moduleBase) { moduleBase = RuntimeImports.RhGetOSModuleFromPointer(ip); if (moduleBase == IntPtr.Zero) From 85ebfee21853042c02b21c34c3c5221ba66a7544 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 25 Feb 2025 11:11:12 -0800 Subject: [PATCH 7/9] Don't use relative paths to load dependencies on Linux/macos. Those are relative to the current working directory. --- .../SharedLibraryHost.cpp | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp index fe48c846f810cd..88ed26ed56f3a4 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp @@ -7,6 +7,7 @@ #include "dlfcn.h" #endif #include +#include #ifndef TARGET_WINDOWS #define __stdcall @@ -24,10 +25,20 @@ int main(int argc, char* argv[]) #ifdef TARGET_WINDOWS // We need to include System32 to find system dependencies of SharedLibraryDependencyLoading.dll HINSTANCE handle = LoadLibraryEx("..\\subdir\\SharedLibraryDependencyLoading.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); -#elif __APPLE__ - void *handle = dlopen("../subdir/SharedLibraryDependencyLoading.dylib", RTLD_LAZY); #else - void *handle = dlopen("../subdir/SharedLibraryDependencyLoading.so", RTLD_LAZY); +#if TARGET_APPLE + constexpr char const* ext = ".dylib"; +#else + constexpr char const* ext = ".so"; +#endif + + std::string path = argv[0]; + // Step out of the current directory and the parent directory. + path = path.substr(0, path.find_last_of("/\\")); + path = path.substr(0, path.find_last_of("/\\")); + path += "/subdir/SharedLibraryDependencyLoading"; + path += ext; + void* handle = dlopen(path.c_str(), RTLD_LAZY); #endif if (!handle) From 43e78ade5c8d64a5c336cc7e196f478a1a76cc92 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 25 Feb 2025 11:28:14 -0800 Subject: [PATCH 8/9] Add test for AppContext.BaseDirectory --- .../SharedLibraryDependency.cpp | 1 - .../SharedLibraryDependencyLoading.cs | 6 +++ .../SharedLibraryHost.cpp | 53 ++++++++++++++++--- 3 files changed, 53 insertions(+), 7 deletions(-) diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp index 4618a530069780..d9f36cbd88fa9b 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependency.cpp @@ -3,7 +3,6 @@ #include - extern "C" DLL_EXPORT int32_t STDMETHODCALLTYPE MultiplyIntegers(int32_t a, int32_t b) { return a * b; diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs index 80c2069eb58e4f..ea84bcb3b3c04f 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryDependencyLoading.cs @@ -15,6 +15,12 @@ public static int MultiplyIntegersExport(int x, int y) return MultiplyIntegers(x, y); } + [UnmanagedCallersOnly(EntryPoint = "GetBaseDirectory", CallConvs = [typeof(CallConvStdcall)])] + public static IntPtr GetBaseDirectory() + { + return Marshal.StringToCoTaskMemAnsi(AppContext.BaseDirectory); + } + [DllImport("SharedLibraryDependency")] [DefaultDllImportSearchPaths(DllImportSearchPath.AssemblyDirectory)] [UnmanagedCallConv(CallConvs = [typeof(CallConvStdcall)])] diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp index 88ed26ed56f3a4..bab6a5665ba7a9 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp @@ -8,6 +8,8 @@ #endif #include #include +#include +#include #ifndef TARGET_WINDOWS #define __stdcall @@ -15,6 +17,22 @@ // typedef for shared lib exported methods using f_MultiplyIntegers = int32_t(__stdcall *)(int32_t, int32_t); +using f_getBaseDirectory = const char*(__stdcall *)(); + +#ifdef TARGET_WINDOWS +struct CoTaskMemDeleter +{ + void operator()(void* p) const + { + CoTaskMemFree(p); + } +}; +template +using CoTaskMemPtr = std::unique_ptr; +#else +template +using CoTaskMemPtr = std::unique_ptr; +#endif #ifdef TARGET_WINDOWS int __cdecl main() @@ -22,7 +40,12 @@ int __cdecl main() int main(int argc, char* argv[]) #endif { + std::string pathToSubdir = argv[0]; + // Step out of the current directory and the parent directory. + pathToSubdir = pathToSubdir.substr(0, pathToSubdir.find_last_of("/\\")); + pathToSubdir = pathToSubdir.substr(0, pathToSubdir.find_last_of("/\\")); #ifdef TARGET_WINDOWS + pathToSubdir += "subdir"; // We need to include System32 to find system dependencies of SharedLibraryDependencyLoading.dll HINSTANCE handle = LoadLibraryEx("..\\subdir\\SharedLibraryDependencyLoading.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); #else @@ -32,11 +55,8 @@ int main(int argc, char* argv[]) constexpr char const* ext = ".so"; #endif - std::string path = argv[0]; - // Step out of the current directory and the parent directory. - path = path.substr(0, path.find_last_of("/\\")); - path = path.substr(0, path.find_last_of("/\\")); - path += "/subdir/SharedLibraryDependencyLoading"; + pathToSubdir += "subdir/"; + std::string path = pathToSubdir + "SharedLibraryDependencyLoading"; path += ext; void* handle = dlopen(path.c_str(), RTLD_LAZY); #endif @@ -50,7 +70,28 @@ int main(int argc, char* argv[]) f_MultiplyIntegers multiplyIntegers = (f_MultiplyIntegers)dlsym(handle, "MultiplyIntegers"); #endif - return multiplyIntegers(10, 7) == 70 ? 100 : 2; + if (multiplyIntegers(10, 7) != 70) + return 2; + + CoTaskMemPtr baseDirectory; +#ifdef TARGET_WINDOWS + f_getBaseDirectory getBaseDirectory = (f_getBaseDirectory)GetProcAddress(handle, "GetBaseDirectory"); +#else + f_getBaseDirectory getBaseDirectory = (f_getBaseDirectory)dlsym(handle, "GetBaseDirectory"); +#endif + + baseDirectory.reset(getBaseDirectory()); + if (baseDirectory == nullptr) + return 3; + + if (pathToSubdir != baseDirectory.get()) + { + std::cout << "Expected base directory: " << pathToSubdir << std::endl; + std::cout << "Actual base directory: " << baseDirectory.get() << std::endl; + return 4; + } + + return 100; } extern "C" const char* __stdcall __asan_default_options() From e874ec0d6658de317888110efb7be45a31276828 Mon Sep 17 00:00:00 2001 From: Jeremy Koritzinsky Date: Tue, 25 Feb 2025 11:34:02 -0800 Subject: [PATCH 9/9] Fix test on Windows --- .../SharedLibraryHost.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp index bab6a5665ba7a9..f7fa40c5947331 100644 --- a/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp +++ b/src/tests/nativeaot/SmokeTests/SharedLibraryDependencyLoading/SharedLibraryHost.cpp @@ -20,22 +20,23 @@ using f_MultiplyIntegers = int32_t(__stdcall *)(int32_t, int32_t); using f_getBaseDirectory = const char*(__stdcall *)(); #ifdef TARGET_WINDOWS +template struct CoTaskMemDeleter { - void operator()(void* p) const + void operator()(T* p) const { - CoTaskMemFree(p); + CoTaskMemFree((void*)p); } }; template -using CoTaskMemPtr = std::unique_ptr; +using CoTaskMemPtr = std::unique_ptr>; #else template using CoTaskMemPtr = std::unique_ptr; #endif #ifdef TARGET_WINDOWS -int __cdecl main() +int __cdecl main(int argc, char* argv[]) #else int main(int argc, char* argv[]) #endif @@ -45,7 +46,7 @@ int main(int argc, char* argv[]) pathToSubdir = pathToSubdir.substr(0, pathToSubdir.find_last_of("/\\")); pathToSubdir = pathToSubdir.substr(0, pathToSubdir.find_last_of("/\\")); #ifdef TARGET_WINDOWS - pathToSubdir += "subdir"; + pathToSubdir += "subdir\\"; // We need to include System32 to find system dependencies of SharedLibraryDependencyLoading.dll HINSTANCE handle = LoadLibraryEx("..\\subdir\\SharedLibraryDependencyLoading.dll", nullptr, LOAD_LIBRARY_SEARCH_APPLICATION_DIR | LOAD_LIBRARY_SEARCH_SYSTEM32); #else @@ -83,7 +84,7 @@ int main(int argc, char* argv[]) baseDirectory.reset(getBaseDirectory()); if (baseDirectory == nullptr) return 3; - + if (pathToSubdir != baseDirectory.get()) { std::cout << "Expected base directory: " << pathToSubdir << std::endl;