#include <fstream>
#include <limits.h>
#include <stdlib.h>
+#include <set>
+
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <dirent.h>
#include "log.h"
#include "launcher_env.h"
-const char* __coreclr_lib = "/usr/share/dotnet.tizen/netcoreapp/libcoreclr.so";
-const char* __dotnet_launcher = "/usr/bin/dotnet-launcher";
+static const char* __coreclr_lib = "/usr/share/dotnet.tizen/netcoreapp/libcoreclr.so";
+static const char* __dotnet_loader = "/usr/bin/dotnet-loader";
typedef int (*coreclr_preload_assembly_ptr)(const char* assemblyPath);
-typedef int (*launcher_real_main_ptr)(int argc, char *argv[], const char* mode);
+typedef int (*launcher_real_main_ptr)(int argc, char *argv[]);
-static std::string absolutePath(const std::string& path)
+static std::string getAbsolutePath(const std::string& path)
{
std::string absPath;
- char realPath[PATH_MAX];
- if (realpath(path.c_str(), realPath) != nullptr && realPath[0] != '\0')
+ char *realPath = realpath(path.c_str(), NULL);
+ if (realPath) {
absPath.assign(realPath);
+ free(realPath);
+ }
return absPath;
}
+static bool isFile(const std::string& path)
+{
+ struct stat sb;
+ return lstat(path.c_str(), &sb) == 0;
+}
+
+static std::string replaceAll(const std::string& str, const std::string& pattern, const std::string& replace)
+{
+ std::string result = str;
+ std::string::size_type pos = 0;
+ std::string::size_type offset = 0;
+
+ while ((pos = result.find(pattern, offset)) != std::string::npos) {
+ result.replace(result.begin() + pos, result.begin() + pos + pattern.size(), replace);
+ offset = pos + replace.size();
+ }
+
+ return result;
+}
+
+static std::string findDllPath(const std::string& filename)
+{
+ const std::string netcoreappDir = "/usr/share/dotnet.tizen/netcoreapp/";
+ const std::string frameworkDir = "/usr/share/dotnet.tizen/framework/";
+
+ std::string result;
+
+ // check whether the target file exist under netcoreapp directory
+ result = netcoreappDir + filename;
+ if (isFile(result)) {
+ return result;
+ }
+
+ // check whether the target file exist under framework directory
+ result = frameworkDir + filename;
+ if (isFile(result)) {
+ return result;
+ }
+
+ // dll file is not found. return empty string
+ result.clear();
+
+ return result;
+}
+
static void preloadAssemblies()
{
#ifdef USE_DEFAULT_BASE_ADDR
return;
}
- std::ifstream preloadList(AOT_PRELOAD_PATH);
- if (preloadList) {
- std::string path;
- while (getline(preloadList, path)) {
- int st = preloadAssembly(absolutePath(path).c_str());
- if (st != 0) {
- _DBG("preload of %s failed! (0x%08x)", path.c_str(), st);
- } else {
- _DBG("preload of %s succeded", path.c_str());
- }
+ const std::string preloadDir = "/usr/share/dotnet.tizen/preload/";
+
+ // get file list from preload directory
+ // file is sorted by std::set
+ std::set<std::string> preloadFiles;
+ DIR* dirp = opendir(preloadDir.c_str());
+ struct dirent * dp;
+ while ((dp = readdir(dirp)) != NULL) {
+ if (dp->d_type != DT_DIR) {
+ // Make sure that the file name follows naming conventions.
+ if (dp->d_name &&
+ isdigit(dp->d_name[0]) &&
+ isdigit(dp->d_name[1]) &&
+ (dp->d_name[2] == '.')) {
+ preloadFiles.insert(preloadDir + dp->d_name);
+ }
}
}
+ closedir(dirp);
+
+ // get dll list from each preload file, and preload dll.
+ std::set<std::string> dllList;
+ std::ifstream ifs;
+ std::string in_line;
+ for (const auto& pf: preloadFiles) {
+ ifs.open(pf);
+ if (!ifs.is_open()) {
+ _ERR("failed to open preload file (%s)", pf.c_str());
+ continue;
+ }
+
+ while (std::getline(ifs, in_line)) {
+ in_line = in_line.substr(0, in_line.find_first_of(" ", 0));
+
+ // select dll file case
+ if (in_line[0] == '#' ||
+ in_line[0] == ' ' ||
+ in_line.empty() ||
+ (in_line.find(".dll") == std::string::npos)) {
+ continue;
+ }
+
+ // only native image should be passed as a parameter of coreclr_preload_assembly.
+ if (in_line.find(".ni.dll") == std::string::npos &&
+ in_line.compare("System.Private.CoreLib.dll")) {
+ in_line = replaceAll(in_line, ".dll", ".ni.dll");
+ }
+
+ // coreclr_preload_assembly cannot ignore duplicate loading.
+ // Therefore, only one dll should be preloaded.
+ // dllList is used to ignore duplicated loading request
+ if (dllList.insert(in_line).second) {
+ // check whether the target file exist under netcoreapp directory
+ std::string path = findDllPath(in_line);
+ if (!path.empty()) {
+ int st = preloadAssembly(getAbsolutePath(path).c_str());
+ if (st != 0) {
+ _ERR("preload of %s failed! (0x%08x)", path.c_str(), st);
+ } else {
+ _INFO("preload of %s succeeded", path.c_str());
+ }
+ } else {
+ _ERR("preload failed : file (%s) does not eixst", in_line.c_str());
+ }
+ }
+ }
+
+ ifs.close();
+ }
}
-int main(int argc, char** argv)
+int main(int argc, char** argv)
{
hydra_lifecycle_callback_s hydra_callback;
hydra_callback.create = [](void* user_data) {
_INFO("hydra : create");
};
-
+
hydra_callback.fork = [](int argc, char **argv, void* user_data) -> int {
_INFO("hydra : fork");
- void* launcher_h = dlopen(__dotnet_launcher, RTLD_NOW | RTLD_GLOBAL);
+ void* launcher_h = dlopen(__dotnet_loader, RTLD_NOW | RTLD_GLOBAL);
if (launcher_h == nullptr) {
_DBG("dlopen failed to open dotnet-launcher");
return -1;
launcher_real_main_ptr realMain = (launcher_real_main_ptr)dlsym(launcher_h, "realMain");
if (realMain == nullptr) {
_DBG("realMain is not found in the dotnet-launcher");
+ dlclose(launcher_h);
return -1;
}
- return realMain(argc, argv, "default");
+ return realMain(argc, argv);
};
hydra_callback.terminate = [](void* user_data)-> int {
return launchpad_hydra_main(argc, argv, &hydra_callback, nullptr);
}
-