1 // Licensed to the .NET Foundation under one or more agreements.
2 // The .NET Foundation licenses this file to you under the MIT license.
3 // See the LICENSE file in the project root for more information.
6 //*****************************************************************************
9 // Implementation for the interface exposed by libcoreclr.so
12 //*****************************************************************************
17 #include <configuration.h>
19 #include "../../vm/gdbjithelpers.h"
20 #endif // FEATURE_GDBJIT
22 typedef int (STDMETHODCALLTYPE *HostMain)(
27 #define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr))
29 // Holder for const wide strings
30 typedef NewArrayHolder<const WCHAR> ConstWStringHolder;
32 // Holder for array of wide strings
33 class ConstWStringArrayHolder : public NewArrayHolder<LPCWSTR>
38 ConstWStringArrayHolder() :
39 NewArrayHolder<LPCWSTR>(),
44 void Set(LPCWSTR* value, int cElements)
46 NewArrayHolder<LPCWSTR>::operator=(value);
47 m_cElements = cElements;
50 ~ConstWStringArrayHolder()
52 for (int i = 0; i < m_cElements; i++)
54 delete [] this->m_value[i];
59 // Convert 8 bit string to unicode
60 static LPCWSTR StringToUnicode(LPCSTR str)
62 int length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
63 ASSERTE_ALL_BUILDS(length != 0);
65 LPWSTR result = new (nothrow) WCHAR[length];
66 ASSERTE_ALL_BUILDS(result != NULL);
68 length = MultiByteToWideChar(CP_UTF8, 0, str, -1, result, length);
69 ASSERTE_ALL_BUILDS(length != 0);
74 // Convert 8 bit string array to unicode string array
75 static LPCWSTR* StringArrayToUnicode(int argc, LPCSTR* argv)
77 LPCWSTR* argvW = nullptr;
81 argvW = new (nothrow) LPCWSTR[argc];
82 ASSERTE_ALL_BUILDS(argvW != 0);
84 for (int i = 0; i < argc; i++)
86 argvW[i] = StringToUnicode(argv[i]);
93 static void InitializeStartupFlags(STARTUP_FLAGS* startupFlagsRef)
95 STARTUP_FLAGS startupFlags = static_cast<STARTUP_FLAGS>(
96 STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN |
97 STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN);
99 if (Configuration::GetKnobBooleanValue(W("System.GC.Concurrent"), CLRConfig::UNSUPPORTED_gcConcurrent))
101 startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_CONCURRENT_GC);
103 if (Configuration::GetKnobBooleanValue(W("System.GC.Server"), CLRConfig::UNSUPPORTED_gcServer))
105 startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_SERVER_GC);
107 if (Configuration::GetKnobBooleanValue(W("System.GC.RetainVM"), CLRConfig::UNSUPPORTED_GCRetainVM))
109 startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_HOARD_GC_VM);
112 *startupFlagsRef = startupFlags;
115 static void ConvertConfigPropertiesToUnicode(
116 const char** propertyKeys,
117 const char** propertyValues,
119 LPCWSTR** propertyKeysWRef,
120 LPCWSTR** propertyValuesWRef)
122 LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount];
123 ASSERTE_ALL_BUILDS(propertyKeysW != nullptr);
125 LPCWSTR* propertyValuesW = new (nothrow) LPCWSTR[propertyCount];
126 ASSERTE_ALL_BUILDS(propertyValuesW != nullptr);
128 for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
130 propertyKeysW[propertyIndex] = StringToUnicode(propertyKeys[propertyIndex]);
131 propertyValuesW[propertyIndex] = StringToUnicode(propertyValues[propertyIndex]);
134 *propertyKeysWRef = propertyKeysW;
135 *propertyValuesWRef = propertyValuesW;
138 #if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
139 // Reference to the global holding the path to the JIT
140 extern "C" LPCWSTR g_CLRJITPath;
141 #endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)
143 #ifdef FEATURE_GDBJIT
144 GetInfoForMethodDelegate getInfoForMethodDelegate = NULL;
145 extern "C" int coreclr_create_delegate(void*, unsigned int, const char*, const char*, const char*, void**);
146 #endif //FEATURE_GDBJIT
149 // Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
152 // exePath - Absolute path of the executable that invoked the ExecuteAssembly
153 // appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
154 // propertyCount - Number of properties (elements of the following two arguments)
155 // propertyKeys - Keys of properties of the app domain
156 // propertyValues - Values of properties of the app domain
157 // hostHandle - Output parameter, handle of the created host
158 // domainId - Output parameter, id of the created app domain
161 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
164 int coreclr_initialize(
166 const char* appDomainFriendlyName,
168 const char** propertyKeys,
169 const char** propertyValues,
171 unsigned int* domainId)
175 DWORD error = PAL_InitializeCoreCLR(exePath);
176 hr = HRESULT_FROM_WIN32(error);
178 // If PAL initialization failed, then we should return right away and avoid
179 // calling any other APIs because they can end up calling into the PAL layer again.
186 ReleaseHolder<ICLRRuntimeHost4> host;
188 hr = CorHost2::CreateObject(IID_ICLRRuntimeHost4, (void**)&host);
191 ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName);
193 LPCWSTR* propertyKeysW;
194 LPCWSTR* propertyValuesW;
195 ConvertConfigPropertiesToUnicode(
202 // This will take ownership of propertyKeysWTemp and propertyValuesWTemp
203 Configuration::InitializeConfigurationKnobs(propertyCount, propertyKeysW, propertyValuesW);
205 #if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
206 // Fetch the path to JIT binary, if specified
207 g_CLRJITPath = Configuration::GetKnobStringValue(W("JIT_PATH"));
208 #endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)
210 STARTUP_FLAGS startupFlags;
211 InitializeStartupFlags(&startupFlags);
213 hr = host->SetStartupFlags(startupFlags);
219 hr = host->CreateAppDomainWithManager(
220 appDomainFriendlyNameW,
222 // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS
223 // - By default CoreCLR only allows platform neutral assembly to be run. To allow
224 // assemblies marked as platform specific, include this flag
226 // APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP
227 // - Allows sandboxed applications to make P/Invoke calls and use COM interop
229 // APPDOMAIN_SECURITY_SANDBOXED
230 // - Enables sandboxing. If not set, the app is considered full trust
232 // APPDOMAIN_IGNORE_UNHANDLED_EXCEPTION
233 // - Prevents the application from being torn down if a managed exception is unhandled
235 APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS |
236 APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP |
237 APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT,
238 NULL, // Name of the assembly that contains the AppDomainManager implementation
239 NULL, // The AppDomainManager implementation type name
247 host.SuppressRelease();
249 #ifdef FEATURE_GDBJIT
250 HRESULT createDelegateResult;
251 createDelegateResult = coreclr_create_delegate(*hostHandle,
256 (void**)&getInfoForMethodDelegate);
259 if (!SUCCEEDED(createDelegateResult))
262 "Can't create delegate for 'SOS.SymbolReader.GetInfoForMethod' "
263 "method - status: 0x%08x\n", createDelegateResult);
273 // Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
276 // hostHandle - Handle of the host
277 // domainId - Id of the domain
280 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
283 int coreclr_shutdown(
285 unsigned int domainId)
287 ReleaseHolder<ICLRRuntimeHost4> host(reinterpret_cast<ICLRRuntimeHost4*>(hostHandle));
289 HRESULT hr = host->UnloadAppDomain(domainId, true); // Wait until done
302 // Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
305 // hostHandle - Handle of the host
306 // domainId - Id of the domain
307 // latchedExitCode - Latched exit code after domain unloaded
310 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
313 int coreclr_shutdown_2(
315 unsigned int domainId,
316 int* latchedExitCode)
318 ReleaseHolder<ICLRRuntimeHost4> host(reinterpret_cast<ICLRRuntimeHost4*>(hostHandle));
320 HRESULT hr = host->UnloadAppDomain2(domainId, true, latchedExitCode); // Wait until done
333 // Create a native callable delegate for a managed method.
336 // hostHandle - Handle of the host
337 // domainId - Id of the domain
338 // entryPointAssemblyName - Name of the assembly which holds the custom entry point
339 // entryPointTypeName - Name of the type which holds the custom entry point
340 // entryPointMethodName - Name of the method which is the custom entry point
341 // delegate - Output parameter, the function stores a pointer to the delegate at the specified address
344 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
347 int coreclr_create_delegate(
349 unsigned int domainId,
350 const char* entryPointAssemblyName,
351 const char* entryPointTypeName,
352 const char* entryPointMethodName,
355 ICLRRuntimeHost4* host = reinterpret_cast<ICLRRuntimeHost4*>(hostHandle);
357 ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName);
358 ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName);
359 ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName);
361 HRESULT hr = host->CreateDelegate(
363 entryPointAssemblyNameW,
365 entryPointMethodNameW,
372 // Execute a managed assembly with given arguments
375 // hostHandle - Handle of the host
376 // domainId - Id of the domain
377 // argc - Number of arguments passed to the executed assembly
378 // argv - Array of arguments passed to the executed assembly
379 // managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
380 // exitCode - Exit code returned by the executed assembly
383 // HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
386 int coreclr_execute_assembly(
388 unsigned int domainId,
391 const char* managedAssemblyPath,
392 unsigned int* exitCode)
394 if (exitCode == NULL)
396 return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
400 ICLRRuntimeHost4* host = reinterpret_cast<ICLRRuntimeHost4*>(hostHandle);
402 ConstWStringArrayHolder argvW;
403 argvW.Set(StringArrayToUnicode(argc, argv), argc);
405 ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath);
407 HRESULT hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, (DWORD *)exitCode);