X-Git-Url: http://review.tizen.org/git/?a=blobdiff_plain;f=NativeLauncher%2Ftool%2Fni_common.cc;h=f1127e4933b8a2f74255b606bb9dd6f6b450a941;hb=42e47e57b40b9e5365a97b9eea194ab63bb7a031;hp=666f7520a2fd163409d1183029c8188cfcc5f695;hpb=97cf43315c40b144b96c618ea9482fea89408234;p=platform%2Fcore%2Fdotnet%2Flauncher.git diff --git a/NativeLauncher/tool/ni_common.cc b/NativeLauncher/tool/ni_common.cc index 666f752..f1127e4 100644 --- a/NativeLauncher/tool/ni_common.cc +++ b/NativeLauncher/tool/ni_common.cc @@ -28,24 +28,22 @@ #include #include +#include #include #include -#include #include #include -#include -#include - #include "ni_common.h" +#include "tac_common.h" #include "path_manager.h" #include "plugin_manager.h" #ifdef LOG_TAG #undef LOG_TAG #endif -#define LOG_TAG "NETCORE_INSTALLER_PLUGIN" +#define LOG_TAG "DOTNET_INSTALLER_PLUGIN" #ifndef CROSSGEN_PATH #error "CROSSGEN_PATH is missed" @@ -54,6 +52,12 @@ #define __XSTR(x) #x #define __STR(x) __XSTR(x) static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH); +static const char* __TAC_DIR = __STR(TAC_DIR); + +#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT +static const char* __SYSTEM_BASE_FILE = __STR(SYSTEM_BASE_FILE); +#endif + #undef __STR #undef __XSTR @@ -69,26 +73,6 @@ static void waitInterval() } } -static void updateNiFileInfo(const std::string& dllPath, const std::string& niPath) -{ - char* label = NULL; - - // change smack label - if (smack_getlabel(dllPath.c_str(), &label, SMACK_LABEL_ACCESS) == 0) { - if (smack_setlabel(niPath.c_str(), label, SMACK_LABEL_ACCESS) < 0) { - fprintf(stderr, "Fail to set smack label\n"); - } - free(label); - } - - // change owner and groups for generated ni file. - struct stat info; - if (!stat(dllPath.c_str(), &info)) { - if (chown(niPath.c_str(), info.st_uid, info.st_gid) == -1) - fprintf(stderr, "Failed to change owner and group name\n"); - } -} - static std::string getNiFilePath(const std::string& dllPath) { size_t index = dllPath.find_last_of("."); @@ -125,7 +109,7 @@ static std::string getAppNIPath(const std::string& niPath) if (!isFileExist(niDirPath)) { if (mkdir(niDirPath.c_str(), 0755) == 0) { - updateNiFileInfo(prevPath, niDirPath); + updateAssemblyInfo(prevPath, niDirPath); } else { fprintf(stderr, "Fail to create app ni directory (%s)\n", niDirPath.c_str()); } @@ -157,6 +141,81 @@ static bool niExist(const std::string& path) return false; } +#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT +// Get next base address to be used for system ni image from file +// __SYSTEM_BASE_FILE should be checked for existance before calling this function +static uintptr_t getNextBaseAddrFromFile() +{ + FILE *pFile = fopen(__SYSTEM_BASE_FILE, "r"); + if (pFile == NULL) { + fprintf(stderr, "Failed to open %s\n", __SYSTEM_BASE_FILE); + return 0; + } + + uintptr_t addr = 0; + uintptr_t size = 0; + + while (fscanf(pFile, "%u %u", &addr, &size) != EOF) { + } + + fclose(pFile); + + return addr + size; +} + +// Get next base address to be used for system ni image +static uintptr_t getNextBaseAddr() +{ + uintptr_t baseAddr = 0; + + if (!isFileExist(__SYSTEM_BASE_FILE)) { + // This is the starting address for all default base addresses + baseAddr = DEFAULT_BASE_ADDR_START; + } else { + baseAddr = getNextBaseAddrFromFile(); + + // Round to a multple of 64K (see ZapImage::CalculateZapBaseAddress in CoreCLR) + uintptr_t BASE_ADDRESS_ALIGNMENT = 0xffff; + baseAddr = (baseAddr + BASE_ADDRESS_ALIGNMENT) & ~BASE_ADDRESS_ALIGNMENT; + } + + return baseAddr; +} + +// Save base address of system ni image to file +static void updateBaseAddrFile(const std::string &absNiPath, uintptr_t baseAddr) +{ + uintptr_t niSize = getFileSize(absNiPath); + if (niSize == 0) { + fprintf(stderr, "File %s doesn't exist\n", absNiPath.c_str()); + return; + } + + // Write new entry to the file + FILE *pFile = fopen(__SYSTEM_BASE_FILE, "a"); + if (pFile == NULL) { + fprintf(stderr, "Failed to open %s\n", __SYSTEM_BASE_FILE); + return; + } + + fprintf(pFile, "%u %u\n", baseAddr, niSize); + fclose(pFile); +} + +// check if dll is listed in TPA +static bool isTPADll(const std::string &dllPath) +{ + std::string absDllPath = absolutePath(dllPath); + + if (__tpa.find(absDllPath) != std::string::npos) { + return true; + } + + return false; +} +#endif + +// baseAddr should be checked in file before getting here static ni_error_e crossgen(const std::string& dllPath, const std::string& appPath, bool enableR2R, bool isAppNI = false) { if (!isFileExist(dllPath)) { @@ -181,10 +240,18 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat return NI_ERROR_UNKNOWN; } - if (isAppNI) { + if (isAppNI && strstr(absNiPath.c_str(), __TAC_DIR) == NULL) { absNiPath = getAppNIPath(absNiPath); } +#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT + uintptr_t baseAddr = 0; + + if (isTPADll(dllPath)) { + baseAddr = getNextBaseAddr(); + } +#endif + pid_t pid = fork(); if (pid == -1) return NI_ERROR_UNKNOWN; @@ -196,7 +263,12 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat // Do not use niExist() function to check whether ni file created or not. // niEixst() return false for System.Private.Corelib.dll if (isFileExist(absNiPath)) { - updateNiFileInfo(absDllPath, absNiPath); + updateAssemblyInfo(absDllPath, absNiPath); +#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT + if (baseAddr != 0) { + updateBaseAddrFile(absNiPath, baseAddr); + } +#endif return NI_ERROR_NONE; } else { fprintf(stderr, "Fail to create native image for %s\n", dllPath.c_str()); @@ -216,6 +288,13 @@ static ni_error_e crossgen(const std::string& dllPath, const std::string& appPat argv.push_back("/FragileNonVersionable"); } +#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT + if (baseAddr != 0) { + argv.push_back("/BaseAddress"); + argv.push_back(std::to_string(baseAddr).c_str()); + } +#endif + argv.push_back("/App_Paths"); std::string absAppPath; if (!appPath.empty()) { @@ -253,19 +332,31 @@ static int appAotCb(pkgmgrinfo_appinfo_h handle, void *userData) return -1; } - if (removeNiUnderPkgRoot(pkgId) != 0) { + if (removeNiUnderPkgRoot(pkgId) != NI_ERROR_NONE) { fprintf(stderr, "Failed to remove previous dlls from [%s]\n", pkgId); return -1; } + if (resetTACPackage(pkgId) != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to remove symlink for given package [%s]\n", pkgId); + return -1; + } + // Regenerate ni files with R2R mode forcibiliy. (there is no way to now which option is used) - if (createNiUnderPkgRoot(pkgId, *enableR2R) != 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId); + if (createNiUnderPkgRoot(pkgId, *enableR2R) != NI_ERROR_NONE) { + fprintf(stderr, "Failed to generate NI file [%s]\n", pkgId); return -1; } else { fprintf(stderr, "Complete make application to native image\n"); } + if (createTACPackage(pkgId) != TAC_ERROR_NONE) { + fprintf(stderr, "Failed to generate symbolic link file [%s]\n", pkgId); + return -1; + }else { + fprintf(stderr, "Complete make symbolic link file to tac\n"); + } + return 0; } @@ -276,6 +367,7 @@ static void createCoreLibNI(bool enableR2R) std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup"); if (!isFileExist(coreLibBackup)) { + if (!crossgen(coreLib, std::string(), enableR2R)) { if (rename(coreLib.c_str(), coreLibBackup.c_str())) { fprintf(stderr, "Failed to rename System.Private.CoreLib.dll\n"); @@ -301,11 +393,11 @@ ni_error_e initNICommon(NiCommonOption* option) } if (initializePluginManager("normal")) { - fprintf(stderr, "Fail to initialize plugin manager\n"); + fprintf(stderr, "Fail to initialize PluginManager\n"); return NI_ERROR_UNKNOWN; } if (initializePathManager(option->runtimeDir, option->tizenFXDir, option->extraDirs)) { - fprintf(stderr, "Fail to initialize path manager\n"); + fprintf(stderr, "Fail to initialize PathManager\n"); return NI_ERROR_UNKNOWN; } @@ -344,7 +436,43 @@ ni_error_e createNiDll(const std::string& dllPath, bool enableR2R) return NI_ERROR_NONE; } - return crossgen(dllPath, std::string(), enableR2R); + ni_error_e status = crossgen(dllPath, std::string(), enableR2R); + + return status; +} + +void createNiUnderTAC(const std::string rootPaths[], int count) +{ + std::string appPaths; + try { + for (auto& nuget : bf::recursive_directory_iterator(__TAC_DIR)) { + std::string nugetPath = nuget.path().string(); + if (bf::is_directory(nugetPath)) { + appPaths += nugetPath; + appPaths += ':'; + } + } + if (appPaths.back() == ':') { + appPaths.pop_back(); + } + + auto convert = [&appPaths](const std::string& path, const char* name) { + if (strstr(path.c_str(), TAC_APP_LIST_DB) != NULL || + strstr(path.c_str(), TAC_APP_LIST_RESTORE_DB) != NULL || + strstr(path.c_str(), TAC_SHA_256_INFO) != NULL) + return; + if (!crossgen(path, appPaths.c_str(), false)) { + waitInterval(); + } + }; + + for (int i = 0; i < count; i++) { + scanFilesInDir(rootPaths[i], convert, -1); + } + } catch (const bf::filesystem_error& error) { + fprintf(stderr, "Failed to recursive directory: %s", error.what()); + return; + } } void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R, bool isAppNI) @@ -360,7 +488,24 @@ void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R, if (appPaths.back() == ':') appPaths.pop_back(); - auto convert = [&appPaths, enableR2R, isAppNI](const std::string& path, const char* name) { + std::vector tpaAssemblies; + splitPath(__tpa, tpaAssemblies); + + auto convert = [&appPaths, enableR2R, isAppNI, tpaAssemblies](const std::string& path, const char* name) { + if (isAppNI) { + std::string assembly = path.substr(path.rfind('/') + 1); + bool isExist = false; + for (auto& tpa : tpaAssemblies) { + if (!strcmp(replaceAll(tpa, ".ni.dll", ".dll").c_str(), assembly.c_str())) { + isExist = true; + break; + } + } + if (isExist) { + fprintf(stderr, "%s present in the TPA list skips generation of NI file.\n", path.c_str()); + return; + } + } if (!crossgen(path, appPaths.c_str(), enableR2R, isAppNI)) { waitInterval(); } @@ -369,20 +514,21 @@ void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R, for (int i = 0; i < count; i++) { scanFilesInDir(rootPaths[i], convert, 1); } + + tpaAssemblies.clear(); } ni_error_e createNiUnderPkgRoot(const std::string& pkgId, bool enableR2R) { std::string pkgRoot; - if (getRootPath(pkgId, pkgRoot) != NI_ERROR_NONE) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str()); + if (getRootPath(pkgId, pkgRoot) < 0) { return NI_ERROR_INVALID_PACKAGE; } std::string binDir = concatPath(pkgRoot, "bin"); std::string libDir = concatPath(pkgRoot, "lib"); - std::string appTAC = concatPath(binDir, ".TAC.Release"); - std::string paths[] = {binDir, libDir, appTAC}; + std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR); + std::string paths[] = {binDir, libDir, tacDir}; createNiUnderDirs(paths, 3, enableR2R, true); @@ -393,16 +539,53 @@ ni_error_e createNiDllUnderPkgRoot(const std::string& pkgId, const std::string& { std::string pkgRoot; if (getRootPath(pkgId, pkgRoot) < 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str()); return NI_ERROR_INVALID_PACKAGE; } std::string binDir = concatPath(pkgRoot, "bin"); std::string libDir = concatPath(pkgRoot, "lib"); - std::string appTAC = concatPath(binDir, ".TAC.Release"); - std::string paths = binDir + ":" + libDir + ":" + appTAC; - - return crossgen(dllPath, paths, enableR2R, true); + std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR); + std::string paths = binDir + ":" + libDir + ":" + tacDir; + + if (bf::is_symlink(dllPath)) { + if (bf::exists(tacDir)) { + if (!isNativeImage(dllPath)) { + std::string originPath = bf::read_symlink(dllPath).string(); + std::string originNiPath = originPath.substr(0, originPath.rfind(".dll")) + ".ni.dll"; + if (!bf::exists(originNiPath)) { + if(createNiDll(originPath, false) != NI_ERROR_NONE) { + fprintf(stderr, "Failed to create NI file [%s]\n", originPath.c_str()); + return NI_ERROR_UNKNOWN; + } + } + std::string setNiPath = dllPath.substr(0, dllPath.rfind(".dll")) + ".ni.dll"; + if (!bf::exists(setNiPath)) { + bf::create_symlink(originNiPath, setNiPath); + fprintf(stderr, "%s symbolic link file generated successfully.\n", setNiPath.c_str()); + updateAssemblyInfo(tacDir.c_str(), setNiPath.c_str(), true); + } + } + } + return NI_ERROR_NONE; + } else { + std::string assembly = dllPath.substr(dllPath.rfind('/') + 1); + std::vector tpaAssemblies; + splitPath(__tpa, tpaAssemblies); + bool isExist = false; + for (auto& tpa : tpaAssemblies) { + if (!strcmp(replaceAll(tpa, ".ni.dll", ".dll").c_str(), assembly.c_str())) { + isExist = true; + break; + } + } + tpaAssemblies.clear(); + if (isExist) { + fprintf(stderr, "%s present in the TPA list skips generation of NI file.\n", dllPath.c_str()); + return NI_ERROR_NONE; + } else { + return crossgen(dllPath, paths, enableR2R, true); + } + } } void removeNiPlatform() @@ -414,6 +597,14 @@ void removeNiPlatform() return; } +#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT + if (isFileExist(__SYSTEM_BASE_FILE)) { + if (remove(__SYSTEM_BASE_FILE)) { + fprintf(stderr, "Failed to remove %s\n", __SYSTEM_BASE_FILE); + } + } +#endif + if (remove(coreLib.c_str())) { fprintf(stderr, "Failed to remove System.Private.CoreLib native image file\n"); } @@ -445,7 +636,6 @@ ni_error_e removeNiUnderPkgRoot(const std::string& pkgId) { std::string pkgRoot; if (getRootPath(pkgId, pkgRoot) < 0) { - fprintf(stderr, "Failed to get root path from [%s]\n", pkgId.c_str()); return NI_ERROR_INVALID_PACKAGE; } @@ -481,7 +671,7 @@ ni_error_e regenerateAppNI(bool enableR2R) if (ret != PMINFO_R_OK) return NI_ERROR_UNKNOWN; - ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, AOT_METADATA_KEY, AOT_METADATA_VALUE); + ret = pkgmgrinfo_appinfo_metadata_filter_add(handle, AOT_METADATA_KEY, METADATA_VALUE); if (ret != PMINFO_R_OK) { pkgmgrinfo_appinfo_metadata_filter_destroy(handle); return NI_ERROR_UNKNOWN;