Set base address at native image (#400) accepted/tizen/unified/20220501.223640 submit/tizen/20220429.002649
author조웅석/Common Platform Lab(SR)/삼성전자 <ws77.cho@samsung.com>
Fri, 29 Apr 2022 00:37:07 +0000 (09:37 +0900)
committerGitHub Enterprise <noreply-CODE@samsung.com>
Fri, 29 Apr 2022 00:37:07 +0000 (09:37 +0900)
--imagebase option is added to set base address at native imaage to avoid relocatoin.

Note! this feature is enabled --no-pipeline mode only

NativeLauncher/tool/ni_common.cc

index 199426f..80f1f6c 100644 (file)
@@ -111,6 +111,94 @@ static void waitInterval()
        }
 }
 
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+static uintptr_t getFileSize(const std::string& path)
+{
+       struct stat sb;
+
+       if (stat(path.c_str(), &sb) == 0) {
+               return sb.st_size;
+       }
+
+       return 0;
+}
+
+// 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) {
+               _SERR("Failed to open %s", __SYSTEM_BASE_FILE);
+               return 0;
+       }
+
+       uintptr_t addr = 0;
+       uintptr_t size = 0;
+
+       while (fscanf(pFile, "%" SCNxPTR " %" SCNuPTR "", &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 (!isFile(__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) {
+               _SERR("File %s doesn't exist", absNIPath.c_str());
+               return;
+       }
+
+       // Write new entry to the file
+       FILE *pFile = fopen(__SYSTEM_BASE_FILE, "a");
+       if (pFile == NULL) {
+               _SERR("Failed to open %s", __SYSTEM_BASE_FILE);
+               return;
+       }
+
+       fprintf(pFile, "%" PRIxPTR " %" PRIuPTR "\n", baseAddr, niSize);
+       fclose(pFile);
+}
+
+// check if dll is listed in TPA
+static bool isTPADll(const std::string& dllPath)
+{
+       std::string absPath = getBaseName(getAbsolutePath(dllPath));
+
+       std::vector<std::string> paths = __pm->getPlatformAssembliesPaths();
+       for (unsigned int i = 0; i < paths.size(); i++) {
+               if (paths[i].find(getBaseName(absPath)) != std::string::npos) {
+                       return true;
+               }
+       }
+
+       return false;
+}
+#endif
+
 /**
  * @brief create the directory including parents directory, and
  *        copy ownership and smack labels to the created directory.
@@ -483,6 +571,13 @@ static ni_error_e crossgen2NoPipeLine(const std::vector<std::string>& dllList, c
                        niPath = getNIFilePath(dllPath);
                }
 
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+               uintptr_t baseAddr = 0;
+               if (isTPADll(dllPath)) {
+                       baseAddr = getNextBaseAddr();
+               }
+#endif
+
                // fork crossgen2
                pid_t pid = fork();
                if (pid == -1)
@@ -496,6 +591,11 @@ static ni_error_e crossgen2NoPipeLine(const std::vector<std::string>& dllList, c
                                if (ret != NI_ERROR_NONE) {
                                        return ret;
                                }
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+                               if (baseAddr != 0) {
+                                       updateBaseAddrFile(niPath, baseAddr);
+                               }
+#endif
                        } else {
                                _SERR("Failed. Forked process terminated abnormally");
                                _SERR("Crossgen2 was terminated by the OOM killer. Please check the system.");
@@ -506,6 +606,16 @@ static ni_error_e crossgen2NoPipeLine(const std::vector<std::string>& dllList, c
                        std::vector<const char*> argv;
                        makeArgs(argv, refPaths, opt);
 
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+                       std::string baseAddrString;
+                       if (baseAddr != 0) {
+                               argv.push_back("--imagebase");
+                               std::stringstream ss;
+                               ss << "0x" << std::hex << baseAddr;
+                               baseAddrString = ss.str();
+                               argv.push_back(baseAddrString.c_str());
+                       }
+#endif
                        argv.push_back("-o");
                        argv.push_back(niPath.c_str());