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 static const char* CLR_PATH = "/usr/share/dotnet.tizen/netcoreapp";
23 static const char* TOOL_PATH = "/home/owner/share/.dotnet/tools";
27 "Execute a .NET application or command.\n\n"
28 "Usage: dotnet [options] [path-to-executable] [arguments]\n"
29 "Usage: dotnet [command] [arguments]\n\n"
31 "-h, --help show this help message\n"
32 "--clr-path <path> path to libcoreclr.so and runtime assemblies\n"
33 "--tool-path <path> path to the tool installation directory\n"
34 "--additionalprobingpath <path> path containing assemblies to probe for\n"
35 "--globalizationinvariant run in globalization invariant mode\n\n"
37 "counters monitor or collect performance counters\n"
38 "dump capture or analyze a coredump\n"
39 "gcdump capture a heapdump\n"
40 "trace collect or convert a diagnostic event trace\n");
43 int main(int argc, const char* argv[]) {
45 // libunwind library is used to unwind stack frame, but libunwind for ARM
46 // does not support ARM vfpv3/NEON registers in DWARF format correctly.
47 // Therefore let's disable stack unwinding using DWARF information
48 // See https://github.com/dotnet/runtime/issues/6479
50 // libunwind use following methods to unwind stack frame.
51 // UNW_ARM_METHOD_ALL 0xFF
52 // UNW_ARM_METHOD_DWARF 0x01
53 // UNW_ARM_METHOD_FRAME 0x02
54 // UNW_ARM_METHOD_EXIDX 0x04
55 putenv(const_cast<char*>("UNW_ARM_UNWIND_METHOD=6"));
66 std::string clrFilesPath(CLR_PATH);
67 std::string toolDllsPath(TOOL_PATH);
69 std::string managedAssemblyPath;
70 std::string additionalProbingPath;
71 bool globalizationInvariant = false;
74 std::string arg(argv[0]);
76 if (arg == "-?" || arg == "-h" || arg == "--help") {
79 } else if (arg == "--clr-path" && argc > 1) {
80 clrFilesPath = argv[1];
83 } else if (arg == "--tool-path" && argc > 1) {
84 toolDllsPath = argv[1];
87 } else if (arg == "--additionalprobingpath" && argc > 1) {
88 additionalProbingPath = absolutePath(argv[1]);
91 } else if (arg == "--globalizationinvariant") {
92 globalizationInvariant = true;
93 } else if ((arg == "--runtimeconfig" || arg == "--depsfile") && argc > 1) {
94 // Just for compatibility with corefx tests.
95 // See ParseArguments() in coreclr/hosts/unixcorerun/corerun.cpp.
98 } else if (arg.at(0) == '-') {
99 fprintf(stderr, "Unknown option %s.\n", argv[0]);
102 } else if (isManagedAssembly(arg) || isNativeImage(arg)) {
103 if (!isFileExist(arg)) {
104 fprintf(stderr, "The specified file does not exist.\n");
107 managedAssemblyPath = arg;
111 } else if (arg == "exec") {
112 // 'dotnet' and 'dotnet exec' can be alternatively used.
113 } else if (arg == "tool") {
114 fprintf(stderr, "This command is not currently supported.\n");
117 managedAssemblyPath = toolDllsPath + "/dotnet-" + arg;
119 if (isFileExist(managedAssemblyPath + ".ni.dll")) {
120 managedAssemblyPath += ".ni.dll";
121 } else if (isFileExist(managedAssemblyPath + ".dll")) {
122 managedAssemblyPath += ".dll";
125 "Could not execute because dotnet-%s does not exist.\n"
126 "Follow the instructions for tool installation: https://github.com/Samsung/diagnostic-tools\n", argv[0]);
130 // Implicit compatibility mode for System.CommandLine.
131 std::string termValue(getenv("TERM"));
132 if (termValue == "linux") {
133 setenv("TERM", "xterm", 1);
145 std::string currentExeAbsolutePath = absolutePath("/proc/self/exe");
146 if (currentExeAbsolutePath.empty()) {
147 fprintf(stderr, "Failed to get the current executable's absolute path.\n");
151 std::string clrFilesAbsolutePath = absolutePath(clrFilesPath);
152 if (clrFilesAbsolutePath.empty()) {
153 fprintf(stderr, "Failed to resolve the full path to the CLR files.\n");
157 std::string managedAssemblyAbsolutePath = absolutePath(managedAssemblyPath);
158 if (managedAssemblyAbsolutePath.empty()) {
159 fprintf(stderr, "Failed to get the managed assembly's absolute path.\n");
163 std::string coreclrLibPath(clrFilesAbsolutePath + "/libcoreclr.so");
164 std::string appPath = baseName(managedAssemblyAbsolutePath);
165 std::string nativeDllSearchDirs(appPath);
166 nativeDllSearchDirs += ":" + additionalProbingPath;
167 nativeDllSearchDirs += ":" + clrFilesAbsolutePath;
169 std::string tpaList(managedAssemblyAbsolutePath);
170 // For now we don't parse .deps.json file but let application DLLs can override runtime DLLs.
171 std::vector<std::string> tpaDirs = { appPath, additionalProbingPath, clrFilesAbsolutePath };
172 addAssembliesFromDirectories(tpaDirs, tpaList);
174 void* coreclrLib = dlopen(coreclrLibPath.c_str(), RTLD_NOW | RTLD_LOCAL);
175 if (coreclrLib == nullptr) {
176 const char* error = dlerror();
177 fprintf(stderr, "dlopen failed to open the libcoreclr.so with error %s\n", error);
181 coreclr_initialize_ptr initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
182 coreclr_execute_assembly_ptr executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
183 coreclr_shutdown_ptr shutdownCoreCLR = (coreclr_shutdown_ptr)dlsym(coreclrLib, "coreclr_shutdown");
185 if (initializeCoreCLR == nullptr) {
186 fprintf(stderr, "Function coreclr_initialize not found in the libcoreclr.so\n");
188 } else if (executeAssembly == nullptr) {
189 fprintf(stderr, "Function coreclr_execute_assembly not found in the libcoreclr.so\n");
191 } else if (shutdownCoreCLR == nullptr) {
192 fprintf(stderr, "Function coreclr_shutdown not found in the libcoreclr.so\n");
196 const char* propertyKeys[] = {
197 "TRUSTED_PLATFORM_ASSEMBLIES",
200 "NATIVE_DLL_SEARCH_DIRECTORIES",
201 "System.Globalization.Invariant",
203 const char* propertyValues[] = {
207 nativeDllSearchDirs.c_str(),
208 globalizationInvariant ? "true" : "false",
212 unsigned int domainId;
214 int st = initializeCoreCLR(
215 currentExeAbsolutePath.c_str(),
217 sizeof(propertyKeys) / sizeof(propertyKeys[0]),
224 fprintf(stderr, "coreclr_initialize failed - status: 0x%08x\n", st);
228 // Set the current process's command name.
229 std::string managedAssemblyName = getFileName(managedAssemblyAbsolutePath);
230 setCmdName(managedAssemblyName);
234 st = executeAssembly(
239 managedAssemblyAbsolutePath.c_str(),
240 (unsigned int*)&exitCode);
243 fprintf(stderr, "coreclr_execute_assembly failed - status: 0x%08x\n", st);
247 st = shutdownCoreCLR(hostHandle, domainId);
249 fprintf(stderr, "coreclr_shutdown failed - status: 0x%08x\n", st);