ce880a90528d18e7dbbab33cef6ca356f1122e3a
[platform/core/dotnet/launcher.git] / NativeLauncher / src / dotnet / dotnet_launcher.cc
1
2 #include <dlfcn.h>
3
4 #include <string>
5 #include <fstream>
6 #include <vector>
7
8 #include "utils.h"
9 #include "log.h"
10 #include "launcher.h"
11 #include "dotnet_launcher.h"
12
13 namespace tizen {
14 namespace runtime {
15 namespace dotnetcore {
16
17 CoreRuntime::CoreRuntime() :
18   coreclrLib(nullptr),
19   hostHandle(nullptr),
20   domainId(-1),
21   PreparedFunction(nullptr),
22   LaunchFunction(nullptr),
23   InitializeClr(nullptr),
24   ExecuteAssembly(nullptr),
25   Shutdown(nullptr),
26   CreateDelegate(nullptr)
27 {
28 #define __XSTR(x) #x
29 #define __STR(x) __XSTR(x)
30
31 #ifdef DEVICE_API_DIR
32   DeviceAPIDirectory = __STR(DEVICE_API_DIR);
33 #endif
34 #ifdef RUNTIME_DIR
35   RuntimeDirectory = __STR(RUNTIME_DIR);
36 #endif
37 #ifdef CORECLR_LAUNCHER_ASSEMBLY_PATH
38   LauncherAssembly = __STR(CORECLR_LAUNCHER_ASSEMBLY_PATH);
39 #endif
40
41 #undef __STR
42 #undef __XSTR
43
44   _DBG("Constructor called!!");
45 }
46
47 CoreRuntime::~CoreRuntime()
48 {
49   Dispose();
50 }
51
52 int CoreRuntime::Initialize(bool standalone)
53 {
54
55   if (standalone)
56   {
57     const char *_deviceapi_directory = getenv("DeviceAPIDirectory");
58     const char *_runtime_directory = getenv("RuntimeDirectory");
59     const char *_launcher_assembly = getenv("LauncherAssembly");
60     if (_deviceapi_directory != nullptr)
61       DeviceAPIDirectory = _deviceapi_directory;
62     if (_runtime_directory != nullptr)
63       RuntimeDirectory = _runtime_directory;
64     if (_launcher_assembly != nullptr)
65       LauncherAssembly = _launcher_assembly;
66   }
67
68   if (DeviceAPIDirectory.empty())
69   {
70     _ERR("Empty Device API Directory");
71     return 1;
72   }
73   else
74   {
75     DeviceAPIDirectory = AbsolutePath(DeviceAPIDirectory);
76   }
77   if (RuntimeDirectory.empty())
78   {
79     _ERR("Empty Runtime Directory");
80     return 1;
81   }
82   else
83   {
84     RuntimeDirectory = AbsolutePath(RuntimeDirectory);
85   }
86   if (LauncherAssembly.empty())
87   {
88     _ERR("Empty Launcher Assembly");
89     return 1;
90   }
91   else
92   {
93     LauncherAssembly = AbsolutePath(LauncherAssembly);
94   }
95
96   std::string libcoreclr(ConcatPath(RuntimeDirectory, "libcoreclr.so"));
97
98   _DBG("libcoreclr : %s", libcoreclr.c_str());
99
100   coreclrLib = dlopen(libcoreclr.c_str(), RTLD_NOW | RTLD_LOCAL);
101   if (coreclrLib == nullptr)
102   {
103     char *err = dlerror();
104     _ERR("dlopen failed to open libcoreclr.so with error %s", err);
105     return 1;
106   }
107
108 #define CORELIB_RETURN_IF_NOSYM(type, variable, name) \
109   do { variable = (type)dlsym(coreclrLib, name); \
110     if (variable == nullptr) { \
111       _ERR(name " is not found in the libcoreclr.so"); \
112       return 1; \
113     }} while(0)
114
115   CORELIB_RETURN_IF_NOSYM(coreclr_initialize_ptr, InitializeClr, "coreclr_initialize");
116   CORELIB_RETURN_IF_NOSYM(coreclr_execute_assembly_ptr, ExecuteAssembly, "coreclr_execute_assembly");
117   CORELIB_RETURN_IF_NOSYM(coreclr_shutdown_ptr, Shutdown, "coreclr_shutdown");
118   CORELIB_RETURN_IF_NOSYM(coreclr_create_delegate_ptr, CreateDelegate, "coreclr_create_delegate");
119
120 #undef CORELIB_RETURN_IF_NOSYM
121
122   _DBG("libcoreclr dlopen and dlsym success");
123
124   _DBG("this addr : %x", this);
125   _DBG("coreclr_initialize : %x", InitializeClr);
126
127   return 0;
128 }
129
130 bool CoreRuntime::InitializeCoreClr(const char* assembly_probe_paths, const char* pinvoke_probe_paths)
131 {
132   std::vector<std::string> platformDirectories = {
133     RuntimeDirectory, DeviceAPIDirectory
134   };
135
136   std::string trusted_assemblies;
137   AssembliesInDirectory(platformDirectories, trusted_assemblies);
138
139   const char *propertyKeys[] =
140   {
141     "TRUSTED_PLATFORM_ASSEMBLIES",
142     "APP_PATHS",
143     "APP_NI_PATHS",
144     "NATIVE_DLL_SEARCH_DIRECTORIES",
145     "AppDomainCompatSwitch"
146   };
147
148   const char *propertyValues[] =
149   {
150     trusted_assemblies.c_str(),
151     assembly_probe_paths,
152     assembly_probe_paths,
153     pinvoke_probe_paths,
154     "UseLatestBehaviorWhenTFMNotSpecified"
155   };
156
157   std::string selfPath = ReadSelfPath();
158
159   int st = InitializeClr(
160       selfPath.c_str(),
161       "dotnet-launcher",
162       sizeof(propertyKeys) / sizeof(propertyKeys[0]),
163       propertyKeys,
164       propertyValues,
165       &hostHandle,
166       &domainId);
167
168   if (st < 0)
169   {
170     _ERR("initialize core clr fail! (0x%08x)", st);
171     return false;
172   }
173
174   _DBG("Initialize core clr success");
175   return true;
176 }
177
178 int CoreRuntime::RunManagedLauncher()
179 {
180   if (FileNotExist(LauncherAssembly))
181   {
182     _ERR("Launcher assembly is not exist in %s", LauncherAssembly.c_str());
183     return 1;
184   }
185
186   std::string launcherDir = Basename(LauncherAssembly);
187   std::vector<std::string> searchDirectories = {
188     RuntimeDirectory, DeviceAPIDirectory
189   };
190
191   std::string trusted_directories = JoinStrings(searchDirectories, ":");
192
193   _DBG("coreclr_dir : %s", RuntimeDirectory.c_str());
194   _DBG("native_so_search_dir : %s", trusted_directories.c_str());
195   _DBG("launcher_assembly : %s", LauncherAssembly.c_str());
196   _DBG("launcher_dir : %s", launcherDir.c_str());
197
198   if (!InitializeCoreClr(launcherDir.c_str(), launcherDir.c_str()))
199   {
200     _ERR("Failed to initialize coreclr");
201     return 1;
202   }
203
204   void *preparedFunctionDelegate;
205   int st = CreateDelegate(hostHandle, domainId,
206       "Tizen.Runtime.Coreclr",
207       "Tizen.Runtime.Coreclr.AssemblyManager",
208       "Prepared", &preparedFunctionDelegate);
209   if (st < 0)
210   {
211     _ERR("Create delegate for Launch prepared function is fail (0x%08x)", st);
212     return 1;
213   }
214   PreparedFunction = reinterpret_cast<PreparedFunctionPtr>(preparedFunctionDelegate);
215
216   if(PreparedFunction != nullptr)
217   {
218     PreparedFunction();
219   }
220
221   void *launchFunctionDelegate;
222   st = CreateDelegate(hostHandle, domainId,
223       "Tizen.Runtime.Coreclr",
224       "Tizen.Runtime.Coreclr.AssemblyManager",
225       "Launch", &launchFunctionDelegate);
226   if (st < 0)
227   {
228     _ERR("Create delegate for Launch managed function is fail! (0x%08x)", st);
229     return 1;
230   }
231   LaunchFunction = reinterpret_cast<LaunchFunctionPtr>(launchFunctionDelegate);
232
233   return 0;
234 }
235
236 void CoreRuntime::Dispose()
237 {
238   if (hostHandle != nullptr)
239   {
240     int st = Shutdown(hostHandle, domainId);
241     if (st < 0)
242     {
243       _ERR("shutdown core clr fail! (0x%08x)", st);
244     }
245   }
246
247   if (dlclose(coreclrLib) != 0)
248   {
249     _ERR("libcoreclr.so close failed");
250   }
251   coreclrLib = nullptr;
252
253   _DBG("Dotnet runtime disposed");
254 }
255
256 int CoreRuntime::Launch(const char* root, const char* path, int argc, char* argv[])
257 {
258   if (path == nullptr)
259   {
260     _ERR("executable path is null");
261     return 1;
262   }
263
264   if (FileNotExist(path))
265   {
266     _ERR("File not exist : %s", path);
267     return 1;
268   }
269
270   bool success = false;
271   if (LaunchFunction != nullptr)
272   {
273     success = LaunchFunction(root, path, argc, argv);
274     if (!success)
275     {
276       _ERR("Failed to launch Application %s", path);
277     }
278     return success ? 0 : 1;
279   }
280   else
281   {
282     std::string appRoot = root;
283     std::string appBin = ConcatPath(appRoot, "bin");
284     std::string appLib = ConcatPath(appRoot, "lib");
285     std::string probePath = appBin + ":" + appLib;
286
287     int st = InitializeCoreClr(probePath.c_str(), probePath.c_str());
288     unsigned int ret = 0;
289     st = ExecuteAssembly(hostHandle, domainId, argc, (const char**)argv, path, &ret);
290     if (st < 0)
291     {
292       _ERR("Failed to Execute Assembly %s (0x%08x)", path, st);
293     }
294     return ret;
295   }
296 }
297
298 }  // namespace dotnetcore
299 }  // namespace runtime
300 }  // namespace tizen