[Refactoring] Improve SAM score through DC and GV improvement
[platform/core/dotnet/launcher.git] / NativeLauncher / hydra / hydra_main.cc
index 2ba1a26..7ced0a3 100644 (file)
 #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
@@ -61,17 +113,74 @@ static void preloadAssemblies()
                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();
        }
 }
 
@@ -90,7 +199,7 @@ int main(int argc, char** argv)
 
        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;
@@ -99,10 +208,11 @@ int main(int argc, char** argv)
                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 {