2 * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
4 * Licensed under the Apache License, Version 2.0 (the License);
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an AS IS BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
19 #include "coreclr_host.h"
22 #include "r2r_checker.h"
24 static const char* CLR_PATH = "/usr/share/dotnet.tizen/netcoreapp";
25 static const char* TOOL_PATH = "/home/owner/share/.dotnet/tools";
26 static const char* DIAGNOSTICS_TOOL_PATH = "/home/owner/share/tmp/sdk_tools/coreclr-diagnostics";
30 "Execute a .NET application or command.\n\n"
31 "Usage: dotnet [options] [path-to-executable] [arguments]\n"
32 "Usage: dotnet [command] [arguments]\n\n"
34 "-h, --help show this help message\n"
35 "--clr-path <path> path to libcoreclr.so and runtime assemblies\n"
36 "--tool-path <path> path to the tool installation directory\n"
37 "--additionalprobingpath <path> path containing assemblies to probe for\n"
38 "--globalizationinvariant run in globalization invariant mode\n\n"
40 "counters monitor or collect performance counters\n"
41 "dump capture or analyze a coredump\n"
42 "gcdump capture a heapdump\n"
43 "trace collect or convert a diagnostic event trace\n"
44 "stack reports the managed stacks\n");
47 int main(int argc, const char* argv[]) {
49 // libunwind library is used to unwind stack frame, but libunwind for ARM
50 // does not support ARM vfpv3/NEON registers in DWARF format correctly.
51 // Therefore let's disable stack unwinding using DWARF information
52 // See https://github.com/dotnet/runtime/issues/6479
54 // libunwind use following methods to unwind stack frame.
55 // UNW_ARM_METHOD_ALL 0xFF
56 // UNW_ARM_METHOD_DWARF 0x01
57 // UNW_ARM_METHOD_FRAME 0x02
58 // UNW_ARM_METHOD_EXIDX 0x04
59 putenv(const_cast<char*>("UNW_ARM_UNWIND_METHOD=6"));
70 std::string clrFilesPath(CLR_PATH);
71 std::string toolDllsPath(clrFilesPath + "/SOS");
73 std::string managedAssemblyPath;
74 std::string additionalProbingPath;
75 bool globalizationInvariant = false;
78 std::string arg(argv[0]);
80 if (arg == "-?" || arg == "-h" || arg == "--help") {
83 } else if (arg == "--clr-path" && argc > 1) {
84 clrFilesPath = argv[1];
87 } else if (arg == "--tool-path" && argc > 1) {
88 toolDllsPath = argv[1];
91 } else if (arg == "--additionalprobingpath" && argc > 1) {
92 additionalProbingPath = getAbsolutePath(argv[1]);
95 } else if (arg == "--globalizationinvariant") {
96 globalizationInvariant = true;
97 } else if ((arg == "--runtimeconfig" || arg == "--depsfile") && argc > 1) {
98 // Just for compatibility with corefx tests.
99 // See ParseArguments() in coreclr/hosts/unixcorerun/corerun.cpp.
102 } else if (arg.at(0) == '-') {
103 _SERR("Unknown option %s.", argv[0]);
106 } else if (isManagedAssembly(arg) || isR2RImage(arg)) {
108 _SERR("The specified file does not exist.");
111 managedAssemblyPath = arg;
115 } else if (arg == "exec") {
116 // 'dotnet' and 'dotnet exec' can be alternatively used.
117 } else if (arg == "tool") {
118 _SERR("This command is not currently supported.");
121 std::string toolDll = "/dotnet-" + arg + ".dll";
122 std::string searchToolPath1 = toolDllsPath + toolDll;
123 std::string searchToolPath2 = std::string(TOOL_PATH) + toolDll;
124 std::string searchToolPath3 = std::string(DIAGNOSTICS_TOOL_PATH) + toolDll;
125 if (isFile(searchToolPath1)) {
126 managedAssemblyPath = searchToolPath1;
127 } else if (isFile(searchToolPath2)) {
128 managedAssemblyPath = searchToolPath2;
129 } else if (isFile(searchToolPath3)) {
130 managedAssemblyPath = searchToolPath3;
133 "Could not execute because dotnet-%s does not exist.\n"
134 "Go to https://developer.samsung.com/tizen to learn how to install tools.\n", argv[0]);
138 // Implicit compatibility mode for System.CommandLine.
139 std::string termValue(getenv("TERM"));
140 if (termValue == "linux") {
141 setenv("TERM", "xterm", 1);
153 std::string currentExeAbsolutePath = getAbsolutePath("/proc/self/exe");
154 if (currentExeAbsolutePath.empty()) {
155 _SERR("Failed to get the current executable's absolute path.");
159 std::string clrFilesAbsolutePath = getAbsolutePath(clrFilesPath);
160 if (clrFilesAbsolutePath.empty()) {
161 _SERR("Failed to resolve the full path to the CLR files.");
165 std::string managedAssemblyAbsolutePath = getAbsolutePath(managedAssemblyPath);
166 if (managedAssemblyAbsolutePath.empty()) {
167 _SERR("Failed to get the managed assembly's absolute path.");
171 std::string coreclrLibPath(clrFilesAbsolutePath + "/libcoreclr.so");
172 std::string appPath = getBaseName(managedAssemblyAbsolutePath);
173 std::string nativeDllSearchDirs(appPath);
174 nativeDllSearchDirs += ":" + additionalProbingPath;
175 nativeDllSearchDirs += ":" + clrFilesAbsolutePath;
177 std::string tpaList(managedAssemblyAbsolutePath);
178 // For now we don't parse .deps.json file but let application DLLs can override runtime DLLs.
179 std::vector<std::string> tpaDirs = { appPath, additionalProbingPath, clrFilesAbsolutePath };
180 addAssembliesFromDirectories(tpaDirs, tpaList);
182 void* coreclrLib = dlopen(coreclrLibPath.c_str(), RTLD_NOW | RTLD_LOCAL);
183 if (coreclrLib == nullptr) {
184 const char* error = dlerror();
185 _SERR("dlopen failed to open the libcoreclr.so with error %s", error);
189 coreclr_initialize_ptr initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
190 coreclr_execute_assembly_ptr executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
191 coreclr_shutdown_ptr shutdownCoreCLR = (coreclr_shutdown_ptr)dlsym(coreclrLib, "coreclr_shutdown");
193 if (initializeCoreCLR == nullptr) {
194 _SERR("Function coreclr_initialize not found in the libcoreclr.so");
196 } else if (executeAssembly == nullptr) {
197 _SERR("Function coreclr_execute_assembly not found in the libcoreclr.so");
199 } else if (shutdownCoreCLR == nullptr) {
200 _SERR("Function coreclr_shutdown not found in the libcoreclr.so");
204 bool ncdbStartupHook = isNCDBStartupHookProvided();
206 const char* propertyKeys[] = {
207 "TRUSTED_PLATFORM_ASSEMBLIES",
210 "NATIVE_DLL_SEARCH_DIRECTORIES",
211 "System.Globalization.Invariant",
212 ncdbStartupHook ? "STARTUP_HOOKS" : "" // must be the last one
214 const char* propertyValues[] = {
218 nativeDllSearchDirs.c_str(),
219 globalizationInvariant ? "true" : "false",
220 ncdbStartupHook ? getNCDBStartupHook() : "" // must be the last one
224 unsigned int domainId;
226 int st = initializeCoreCLR(
227 currentExeAbsolutePath.c_str(),
229 sizeof(propertyKeys) / sizeof(propertyKeys[0]) - (ncdbStartupHook ? 0 : 1),
236 _SERR("coreclr_initialize failed - status: 0x%08x", st);
240 // Set the current process's command name.
241 std::string managedAssemblyName = getFileName(managedAssemblyAbsolutePath);
242 setCmdName(managedAssemblyName);
246 st = executeAssembly(
251 managedAssemblyAbsolutePath.c_str(),
252 (unsigned int*)&exitCode);
255 _SERR("coreclr_execute_assembly failed - status: 0x%08x", st);
259 st = shutdownCoreCLR(hostHandle, domainId);
261 _SERR("coreclr_shutdown failed - status: 0x%08x", st);