summaryrefslogtreecommitdiff
path: root/src/dlls/mscoree/unixinterface.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dlls/mscoree/unixinterface.cpp')
-rw-r--r--src/dlls/mscoree/unixinterface.cpp378
1 files changed, 378 insertions, 0 deletions
diff --git a/src/dlls/mscoree/unixinterface.cpp b/src/dlls/mscoree/unixinterface.cpp
new file mode 100644
index 0000000000..8d75ff2721
--- /dev/null
+++ b/src/dlls/mscoree/unixinterface.cpp
@@ -0,0 +1,378 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+
+//*****************************************************************************
+// unixinterface.cpp
+//
+// Implementation for the interface exposed by libcoreclr.so
+//
+
+//*****************************************************************************
+
+#include "stdafx.h"
+#include <utilcode.h>
+#include <corhost.h>
+#include <configuration.h>
+#ifdef FEATURE_GDBJIT
+#include "../../vm/gdbjithelpers.h"
+#endif // FEATURE_GDBJIT
+
+typedef int (STDMETHODCALLTYPE *HostMain)(
+ const int argc,
+ const wchar_t** argv
+ );
+
+#define ASSERTE_ALL_BUILDS(expr) _ASSERTE_ALL_BUILDS(__FILE__, (expr))
+
+// Holder for const wide strings
+typedef NewArrayHolder<const WCHAR> ConstWStringHolder;
+
+// Holder for array of wide strings
+class ConstWStringArrayHolder : public NewArrayHolder<LPCWSTR>
+{
+ int m_cElements;
+
+public:
+ ConstWStringArrayHolder() :
+ NewArrayHolder<LPCWSTR>(),
+ m_cElements(0)
+ {
+ }
+
+ void Set(LPCWSTR* value, int cElements)
+ {
+ NewArrayHolder<LPCWSTR>::operator=(value);
+ m_cElements = cElements;
+ }
+
+ ~ConstWStringArrayHolder()
+ {
+ for (int i = 0; i < m_cElements; i++)
+ {
+ delete [] this->m_value[i];
+ }
+ }
+};
+
+// Convert 8 bit string to unicode
+static LPCWSTR StringToUnicode(LPCSTR str)
+{
+ int length = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0);
+ ASSERTE_ALL_BUILDS(length != 0);
+
+ LPWSTR result = new (nothrow) WCHAR[length];
+ ASSERTE_ALL_BUILDS(result != NULL);
+
+ length = MultiByteToWideChar(CP_UTF8, 0, str, -1, result, length);
+ ASSERTE_ALL_BUILDS(length != 0);
+
+ return result;
+}
+
+// Convert 8 bit string array to unicode string array
+static LPCWSTR* StringArrayToUnicode(int argc, LPCSTR* argv)
+{
+ LPCWSTR* argvW = nullptr;
+
+ if (argc > 0)
+ {
+ argvW = new (nothrow) LPCWSTR[argc];
+ ASSERTE_ALL_BUILDS(argvW != 0);
+
+ for (int i = 0; i < argc; i++)
+ {
+ argvW[i] = StringToUnicode(argv[i]);
+ }
+ }
+
+ return argvW;
+}
+
+static void InitializeStartupFlags(STARTUP_FLAGS* startupFlagsRef)
+{
+ STARTUP_FLAGS startupFlags = static_cast<STARTUP_FLAGS>(
+ STARTUP_FLAGS::STARTUP_LOADER_OPTIMIZATION_SINGLE_DOMAIN |
+ STARTUP_FLAGS::STARTUP_SINGLE_APPDOMAIN);
+
+ if (Configuration::GetKnobBooleanValue(W("System.GC.Concurrent"), CLRConfig::UNSUPPORTED_gcConcurrent))
+ {
+ startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_CONCURRENT_GC);
+ }
+ if (Configuration::GetKnobBooleanValue(W("System.GC.Server"), CLRConfig::UNSUPPORTED_gcServer))
+ {
+ startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_SERVER_GC);
+ }
+ if (Configuration::GetKnobBooleanValue(W("System.GC.RetainVM"), CLRConfig::UNSUPPORTED_GCRetainVM))
+ {
+ startupFlags = static_cast<STARTUP_FLAGS>(startupFlags | STARTUP_HOARD_GC_VM);
+ }
+
+ *startupFlagsRef = startupFlags;
+}
+
+static void ConvertConfigPropertiesToUnicode(
+ const char** propertyKeys,
+ const char** propertyValues,
+ int propertyCount,
+ LPCWSTR** propertyKeysWRef,
+ LPCWSTR** propertyValuesWRef)
+{
+ LPCWSTR* propertyKeysW = new (nothrow) LPCWSTR[propertyCount];
+ ASSERTE_ALL_BUILDS(propertyKeysW != nullptr);
+
+ LPCWSTR* propertyValuesW = new (nothrow) LPCWSTR[propertyCount];
+ ASSERTE_ALL_BUILDS(propertyValuesW != nullptr);
+
+ for (int propertyIndex = 0; propertyIndex < propertyCount; ++propertyIndex)
+ {
+ propertyKeysW[propertyIndex] = StringToUnicode(propertyKeys[propertyIndex]);
+ propertyValuesW[propertyIndex] = StringToUnicode(propertyValues[propertyIndex]);
+ }
+
+ *propertyKeysWRef = propertyKeysW;
+ *propertyValuesWRef = propertyValuesW;
+}
+
+#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
+// Reference to the global holding the path to the JIT
+extern "C" LPCWSTR g_CLRJITPath;
+#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)
+
+#ifdef FEATURE_GDBJIT
+GetInfoForMethodDelegate getInfoForMethodDelegate = NULL;
+extern "C" int coreclr_create_delegate(void*, unsigned int, const char*, const char*, const char*, void**);
+#endif //FEATURE_GDBJIT
+
+//
+// Initialize the CoreCLR. Creates and starts CoreCLR host and creates an app domain
+//
+// Parameters:
+// exePath - Absolute path of the executable that invoked the ExecuteAssembly
+// appDomainFriendlyName - Friendly name of the app domain that will be created to execute the assembly
+// propertyCount - Number of properties (elements of the following two arguments)
+// propertyKeys - Keys of properties of the app domain
+// propertyValues - Values of properties of the app domain
+// hostHandle - Output parameter, handle of the created host
+// domainId - Output parameter, id of the created app domain
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+int coreclr_initialize(
+ const char* exePath,
+ const char* appDomainFriendlyName,
+ int propertyCount,
+ const char** propertyKeys,
+ const char** propertyValues,
+ void** hostHandle,
+ unsigned int* domainId)
+{
+ HRESULT hr;
+#ifdef FEATURE_PAL
+ DWORD error = PAL_InitializeCoreCLR(exePath);
+ hr = HRESULT_FROM_WIN32(error);
+
+ // If PAL initialization failed, then we should return right away and avoid
+ // calling any other APIs because they can end up calling into the PAL layer again.
+ if (FAILED(hr))
+ {
+ return hr;
+ }
+#endif
+
+ ReleaseHolder<ICLRRuntimeHost2> host;
+
+ hr = CorHost2::CreateObject(IID_ICLRRuntimeHost2, (void**)&host);
+ IfFailRet(hr);
+
+ ConstWStringHolder appDomainFriendlyNameW = StringToUnicode(appDomainFriendlyName);
+
+ LPCWSTR* propertyKeysW;
+ LPCWSTR* propertyValuesW;
+ ConvertConfigPropertiesToUnicode(
+ propertyKeys,
+ propertyValues,
+ propertyCount,
+ &propertyKeysW,
+ &propertyValuesW);
+
+ // This will take ownership of propertyKeysWTemp and propertyValuesWTemp
+ Configuration::InitializeConfigurationKnobs(propertyCount, propertyKeysW, propertyValuesW);
+
+#if !defined(FEATURE_MERGE_JIT_AND_ENGINE)
+ // Fetch the path to JIT binary, if specified
+ g_CLRJITPath = Configuration::GetKnobStringValue(W("JIT_PATH"));
+#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE)
+
+ STARTUP_FLAGS startupFlags;
+ InitializeStartupFlags(&startupFlags);
+
+ hr = host->SetStartupFlags(startupFlags);
+ IfFailRet(hr);
+
+ hr = host->Start();
+ IfFailRet(hr);
+
+ hr = host->CreateAppDomainWithManager(
+ appDomainFriendlyNameW,
+ // Flags:
+ // APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS
+ // - By default CoreCLR only allows platform neutral assembly to be run. To allow
+ // assemblies marked as platform specific, include this flag
+ //
+ // APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP
+ // - Allows sandboxed applications to make P/Invoke calls and use COM interop
+ //
+ // APPDOMAIN_SECURITY_SANDBOXED
+ // - Enables sandboxing. If not set, the app is considered full trust
+ //
+ // APPDOMAIN_IGNORE_UNHANDLED_EXCEPTION
+ // - Prevents the application from being torn down if a managed exception is unhandled
+ //
+ APPDOMAIN_ENABLE_PLATFORM_SPECIFIC_APPS |
+ APPDOMAIN_ENABLE_PINVOKE_AND_CLASSIC_COMINTEROP |
+ APPDOMAIN_DISABLE_TRANSPARENCY_ENFORCEMENT,
+ NULL, // Name of the assembly that contains the AppDomainManager implementation
+ NULL, // The AppDomainManager implementation type name
+ propertyCount,
+ propertyKeysW,
+ propertyValuesW,
+ (DWORD *)domainId);
+
+ if (SUCCEEDED(hr))
+ {
+ host.SuppressRelease();
+ *hostHandle = host;
+#ifdef FEATURE_GDBJIT
+
+ hr = coreclr_create_delegate(*hostHandle,
+ *domainId,
+ "SOS.NETCore",
+ "SOS.SymbolReader",
+ "GetInfoForMethod",
+ (void**)&getInfoForMethodDelegate);
+
+ if (!SUCCEEDED(hr))
+ {
+ fprintf(stderr,
+ "Can't create delegate for 'System.Diagnostics.Debug.SymbolReader.SymbolReader.GetInfoForMethod' "
+ "method - status: 0x%08x\n", hr);
+ }
+ hr = S_OK; // We don't need to fail if we can't create delegate
+#endif
+ }
+ return hr;
+}
+
+//
+// Shutdown CoreCLR. It unloads the app domain and stops the CoreCLR host.
+//
+// Parameters:
+// hostHandle - Handle of the host
+// domainId - Id of the domain
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+int coreclr_shutdown(
+ void* hostHandle,
+ unsigned int domainId)
+{
+ ReleaseHolder<ICLRRuntimeHost2> host(reinterpret_cast<ICLRRuntimeHost2*>(hostHandle));
+
+ HRESULT hr = host->UnloadAppDomain(domainId, true); // Wait until done
+ IfFailRet(hr);
+
+ hr = host->Stop();
+
+#ifdef FEATURE_PAL
+ PAL_Shutdown();
+#endif
+
+ return hr;
+}
+
+//
+// Create a native callable delegate for a managed method.
+//
+// Parameters:
+// hostHandle - Handle of the host
+// domainId - Id of the domain
+// entryPointAssemblyName - Name of the assembly which holds the custom entry point
+// entryPointTypeName - Name of the type which holds the custom entry point
+// entryPointMethodName - Name of the method which is the custom entry point
+// delegate - Output parameter, the function stores a pointer to the delegate at the specified address
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+int coreclr_create_delegate(
+ void* hostHandle,
+ unsigned int domainId,
+ const char* entryPointAssemblyName,
+ const char* entryPointTypeName,
+ const char* entryPointMethodName,
+ void** delegate)
+{
+ ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);
+
+ ConstWStringHolder entryPointAssemblyNameW = StringToUnicode(entryPointAssemblyName);
+ ConstWStringHolder entryPointTypeNameW = StringToUnicode(entryPointTypeName);
+ ConstWStringHolder entryPointMethodNameW = StringToUnicode(entryPointMethodName);
+
+ HRESULT hr = host->CreateDelegate(
+ domainId,
+ entryPointAssemblyNameW,
+ entryPointTypeNameW,
+ entryPointMethodNameW,
+ (INT_PTR*)delegate);
+
+ return hr;
+}
+
+//
+// Execute a managed assembly with given arguments
+//
+// Parameters:
+// hostHandle - Handle of the host
+// domainId - Id of the domain
+// argc - Number of arguments passed to the executed assembly
+// argv - Array of arguments passed to the executed assembly
+// managedAssemblyPath - Path of the managed assembly to execute (or NULL if using a custom entrypoint).
+// exitCode - Exit code returned by the executed assembly
+//
+// Returns:
+// HRESULT indicating status of the operation. S_OK if the assembly was successfully executed
+//
+extern "C"
+int coreclr_execute_assembly(
+ void* hostHandle,
+ unsigned int domainId,
+ int argc,
+ const char** argv,
+ const char* managedAssemblyPath,
+ unsigned int* exitCode)
+{
+ if (exitCode == NULL)
+ {
+ return HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
+ }
+ *exitCode = -1;
+
+ ICLRRuntimeHost2* host = reinterpret_cast<ICLRRuntimeHost2*>(hostHandle);
+
+ ConstWStringArrayHolder argvW;
+ argvW.Set(StringArrayToUnicode(argc, argv), argc);
+
+ ConstWStringHolder managedAssemblyPathW = StringToUnicode(managedAssemblyPath);
+
+ HRESULT hr = host->ExecuteAssembly(domainId, managedAssemblyPathW, argc, argvW, (DWORD *)exitCode);
+ IfFailRet(hr);
+
+ return hr;
+}