Upgrade the nuget(Newtonsoft.Json) version of TC (#422)
[platform/core/dotnet/launcher.git] / NativeLauncher / launcher / exec / corerun.cc
1 /*
2  * Copyright (c) 2020 Samsung Electronics Co., Ltd All Rights Reserved
3  *
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
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
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.
15  */
16
17 #include <dlfcn.h>
18 #include <string>
19 #include "coreclr_host.h"
20 #include "log.h"
21 #include "utils.h"
22
23 static const char* CLR_PATH = "/usr/share/dotnet.tizen/netcoreapp";
24 static const char* TOOL_PATH = "/home/owner/share/.dotnet/tools";
25
26 void DisplayUsage() {
27         _SOUT(
28                 "Execute a .NET application or command.\n\n"
29                 "Usage: dotnet [options] [path-to-executable] [arguments]\n"
30                 "Usage: dotnet [command] [arguments]\n\n"
31                 "Options:\n"
32                 "-h, --help                         show this help message\n"
33                 "--clr-path <path>                  path to libcoreclr.so and runtime assemblies\n"
34                 "--tool-path <path>                 path to the tool installation directory\n"
35                 "--additionalprobingpath <path>     path containing assemblies to probe for\n"
36                 "--globalizationinvariant           run in globalization invariant mode\n\n"
37                 "Commands:\n"
38                 "counters       monitor or collect performance counters\n"
39                 "dump           capture or analyze a coredump\n"
40                 "gcdump         capture a heapdump\n"
41                 "trace          collect or convert a diagnostic event trace\n"
42                 "stack          reports the managed stacks\n");
43 }
44
45 int main(int argc, const char* argv[]) {
46 #ifdef __arm__
47         // libunwind library is used to unwind stack frame, but libunwind for ARM
48         // does not support ARM vfpv3/NEON registers in DWARF format correctly.
49         // Therefore let's disable stack unwinding using DWARF information
50         // See https://github.com/dotnet/runtime/issues/6479
51         //
52         // libunwind use following methods to unwind stack frame.
53         // UNW_ARM_METHOD_ALL          0xFF
54         // UNW_ARM_METHOD_DWARF        0x01
55         // UNW_ARM_METHOD_FRAME        0x02
56         // UNW_ARM_METHOD_EXIDX        0x04
57         putenv(const_cast<char*>("UNW_ARM_UNWIND_METHOD=6"));
58 #endif // __arm__
59
60         argv++;
61         argc--;
62
63         if (argc <= 0) {
64                 DisplayUsage();
65                 return -1;
66         }
67
68         std::string clrFilesPath(CLR_PATH);
69         std::string toolDllsPath(TOOL_PATH);
70
71         std::string managedAssemblyPath;
72         std::string additionalProbingPath;
73         bool globalizationInvariant = false;
74
75         while (argc > 0) {
76                 std::string arg(argv[0]);
77
78                 if (arg == "-?" || arg == "-h" || arg == "--help") {
79                         DisplayUsage();
80                         return 0;
81                 } else if (arg == "--clr-path" && argc > 1) {
82                         clrFilesPath = argv[1];
83                         argc--;
84                         argv++;
85                 } else if (arg == "--tool-path" && argc > 1) {
86                         toolDllsPath = argv[1];
87                         argc--;
88                         argv++;
89                 } else if (arg == "--additionalprobingpath" && argc > 1) {
90                         additionalProbingPath = getAbsolutePath(argv[1]);
91                         argc--;
92                         argv++;
93                 } else if (arg == "--globalizationinvariant") {
94                         globalizationInvariant = true;
95                 } else if ((arg == "--runtimeconfig" || arg == "--depsfile") && argc > 1) {
96                         // Just for compatibility with corefx tests.
97                         // See ParseArguments() in coreclr/hosts/unixcorerun/corerun.cpp.
98                         argc--;
99                         argv++;
100                 } else if (arg.at(0) == '-') {
101                         _SERR("Unknown option %s.", argv[0]);
102                         DisplayUsage();
103                         return -1;
104                 } else if (isManagedAssembly(arg) || isNativeImage(arg)) {
105                         if (!isFile(arg)) {
106                                 _SERR("The specified file does not exist.");
107                                 return -1;
108                         }
109                         managedAssemblyPath = arg;
110                         argc--;
111                         argv++;
112                         break;
113                 } else if (arg == "exec") {
114                         // 'dotnet' and 'dotnet exec' can be alternatively used.
115                 } else if (arg == "tool") {
116                         _SERR("This command is not currently supported.");
117                         return -1;
118                 } else {
119                         managedAssemblyPath = toolDllsPath + "/dotnet-" + arg + ".dll";
120
121                         if (!isFile(managedAssemblyPath)) {
122                                 _SERR(
123                                         "Could not execute because dotnet-%s does not exist.\n"
124                                         "Go to https://developer.samsung.com/tizen to learn how to install tools.\n", argv[0]);
125                                 return -1;
126                         }
127
128                         // Implicit compatibility mode for System.CommandLine.
129                         std::string termValue(getenv("TERM"));
130                         if (termValue == "linux") {
131                                 setenv("TERM", "xterm", 1);
132                         }
133
134                         argc--;
135                         argv++;
136                         break;
137                 }
138
139                 argc--;
140                 argv++;
141         }
142
143         std::string currentExeAbsolutePath = getAbsolutePath("/proc/self/exe");
144         if (currentExeAbsolutePath.empty()) {
145                 _SERR("Failed to get the current executable's absolute path.");
146                 return -1;
147         }
148
149         std::string clrFilesAbsolutePath = getAbsolutePath(clrFilesPath);
150         if (clrFilesAbsolutePath.empty()) {
151                 _SERR("Failed to resolve the full path to the CLR files.");
152                 return -1;
153         }
154
155         std::string managedAssemblyAbsolutePath = getAbsolutePath(managedAssemblyPath);
156         if (managedAssemblyAbsolutePath.empty()) {
157                 _SERR("Failed to get the managed assembly's absolute path.");
158                 return -1;
159         }
160
161         std::string coreclrLibPath(clrFilesAbsolutePath + "/libcoreclr.so");
162         std::string appPath = getBaseName(managedAssemblyAbsolutePath);
163         std::string nativeDllSearchDirs(appPath);
164         nativeDllSearchDirs += ":" + additionalProbingPath;
165         nativeDllSearchDirs += ":" + clrFilesAbsolutePath;
166
167         std::string tpaList(managedAssemblyAbsolutePath);
168         // For now we don't parse .deps.json file but let application DLLs can override runtime DLLs.
169         std::vector<std::string> tpaDirs = { appPath, additionalProbingPath, clrFilesAbsolutePath };
170         addAssembliesFromDirectories(tpaDirs, tpaList);
171
172         void* coreclrLib = dlopen(coreclrLibPath.c_str(), RTLD_NOW | RTLD_LOCAL);
173         if (coreclrLib == nullptr) {
174                 const char* error = dlerror();
175                 _SERR("dlopen failed to open the libcoreclr.so with error %s", error);
176                 return -1;
177         }
178
179         coreclr_initialize_ptr initializeCoreCLR = (coreclr_initialize_ptr)dlsym(coreclrLib, "coreclr_initialize");
180         coreclr_execute_assembly_ptr executeAssembly = (coreclr_execute_assembly_ptr)dlsym(coreclrLib, "coreclr_execute_assembly");
181         coreclr_shutdown_ptr shutdownCoreCLR = (coreclr_shutdown_ptr)dlsym(coreclrLib, "coreclr_shutdown");
182
183         if (initializeCoreCLR == nullptr) {
184                 _SERR("Function coreclr_initialize not found in the libcoreclr.so");
185                 return -1;
186         } else if (executeAssembly == nullptr) {
187                 _SERR("Function coreclr_execute_assembly not found in the libcoreclr.so");
188                 return -1;
189         } else if (shutdownCoreCLR == nullptr) {
190                 _SERR("Function coreclr_shutdown not found in the libcoreclr.so");
191                 return -1;
192         }
193
194         const char* propertyKeys[] = {
195                 "TRUSTED_PLATFORM_ASSEMBLIES",
196                 "APP_PATHS",
197                 "APP_NI_PATHS",
198                 "NATIVE_DLL_SEARCH_DIRECTORIES",
199                 "System.Globalization.Invariant",
200         };
201         const char* propertyValues[] = {
202                 tpaList.c_str(),
203                 appPath.c_str(),
204                 appPath.c_str(),
205                 nativeDllSearchDirs.c_str(),
206                 globalizationInvariant ? "true" : "false",
207         };
208
209         void* hostHandle;
210         unsigned int domainId;
211
212         int st = initializeCoreCLR(
213                 currentExeAbsolutePath.c_str(),
214                 "dotnet",
215                 sizeof(propertyKeys) / sizeof(propertyKeys[0]),
216                 propertyKeys,
217                 propertyValues,
218                 &hostHandle,
219                 &domainId);
220
221         if (st < 0) {
222                 _SERR("coreclr_initialize failed - status: 0x%08x", st);
223                 return -1;
224         }
225
226         // Set the current process's command name.
227         std::string managedAssemblyName = getFileName(managedAssemblyAbsolutePath);
228         setCmdName(managedAssemblyName);
229
230         int exitCode = -1;
231
232         st = executeAssembly(
233                 hostHandle,
234                 domainId,
235                 argc,
236                 argv,
237                 managedAssemblyAbsolutePath.c_str(),
238                 (unsigned int*)&exitCode);
239
240         if (st < 0) {
241                 _SERR("coreclr_execute_assembly failed - status: 0x%08x", st);
242                 exitCode = -1;
243         }
244
245         st = shutdownCoreCLR(hostHandle, domainId);
246         if (st < 0) {
247                 _SERR("coreclr_shutdown failed - status: 0x%08x", st);
248                 return -1;
249         }
250
251         return exitCode;
252 }