#error "CROSSGEN_PATH is missed"
#endif
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+#define SYSTEM_BASE_FILE "/usr/share/dotnet.tizen/system.base.addr.txt"
+#define DEFAULT_BASE_ADDR_START 0x1000000
+#endif
+
#define __XSTR(x) #x
#define __STR(x) __XSTR(x)
static const char* __CROSSGEN_PATH = __STR(CROSSGEN_PATH);
return false;
}
-static ni_error_e crossgen(const std::string& dllPath, const std::string& appPath, bool enableR2R, bool isAppNI = 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 " SYSTEM_BASE_FILE "\n");
+ 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 &dllPath, uintptr_t baseAddr)
+{
+ std::string absNiPath = getNiFilePath(dllPath);
+ if (absNiPath.empty()) {
+ fprintf(stderr, "Failed to get ni file path for %s\n", dllPath.c_str());
+ return;
+ }
+
+ 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 " SYSTEM_BASE_FILE "\n");
+ 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, uintptr_t baseAddr = 0, bool isAppNI = false)
{
if (!isFileExist(dllPath)) {
fprintf(stderr, "dll file is not exist : %s\n", dllPath.c_str());
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()) {
return 0;
}
-static void createCoreLibNI(bool enableR2R)
+static void createCoreLibNI(bool enableR2R, bool doGenUniqueBaseSystem)
{
std::string coreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll");
std::string niCoreLib = concatPath(getRuntimeDir(), "System.Private.CoreLib.ni.dll");
std::string coreLibBackup = concatPath(getRuntimeDir(), "System.Private.CoreLib.dll.Backup");
if (!isFileExist(coreLibBackup)) {
- if (!crossgen(coreLib, std::string(), enableR2R)) {
+ uintptr_t baseAddr = 0;
+
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ if (doGenUniqueBaseSystem) {
+ baseAddr = getNextBaseAddr();
+ }
+#endif
+
+ if (!crossgen(coreLib, std::string(), enableR2R, baseAddr)) {
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ if (doGenUniqueBaseSystem && baseAddr != 0) {
+ updateBaseAddrFile(coreLib, baseAddr);
+ }
+#endif
+
if (rename(coreLib.c_str(), coreLibBackup.c_str())) {
fprintf(stderr, "Failed to rename System.Private.CoreLib.dll\n");
}
}
-void createNiPlatform(bool enableR2R)
+void createNiPlatform(bool enableR2R, bool doGenUniqueBaseSystem)
{
const std::string platformDirs[] = {getRuntimeDir(), getTizenFXDir()};
- createNiUnderDirs(platformDirs, 2, enableR2R);
+ createNiUnderDirs(platformDirs, 2, enableR2R, doGenUniqueBaseSystem);
}
-ni_error_e createNiDll(const std::string& dllPath, bool enableR2R)
+ni_error_e createNiDll(const std::string& dllPath, bool enableR2R, bool doGenUniqueBaseSystem)
{
- createCoreLibNI(enableR2R);
+ createCoreLibNI(enableR2R, doGenUniqueBaseSystem);
// System.Private.CoreLib.dll is generated in the createCoreLibNI function.
// Skip if input dll is System.Private.CoreLib.dll
if (dllPath.find("System.Private.CoreLib.dll") != std::string::npos) {
return NI_ERROR_NONE;
}
- return crossgen(dllPath, std::string(), enableR2R);
+ uintptr_t baseAddr = 0;
+
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ if (doGenUniqueBaseSystem && isTPADll(dllPath)) {
+ baseAddr = getNextBaseAddr();
+ }
+#endif
+
+ ni_error_e status = crossgen(dllPath, std::string(), enableR2R, baseAddr);
+
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ if (doGenUniqueBaseSystem && baseAddr != 0) {
+ updateBaseAddrFile(dllPath, baseAddr);
+ }
+#endif
+
+ return status;
}
-void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R, bool isAppNI)
+void createNiUnderDirs(const std::string rootPaths[], int count, bool enableR2R, bool doGenUniqueBaseSystem, bool isAppNI)
{
- createCoreLibNI(enableR2R);
+ createCoreLibNI(enableR2R, doGenUniqueBaseSystem);
std::string appPaths;
for (int i = 0; i < count; i++) {
if (appPaths.back() == ':')
appPaths.pop_back();
- auto convert = [&appPaths, enableR2R, isAppNI](const std::string& path, const char* name) {
- if (!crossgen(path, appPaths.c_str(), enableR2R, isAppNI)) {
+ auto convert = [&appPaths, enableR2R, doGenUniqueBaseSystem, isAppNI](const std::string& path, const char* name) {
+ uintptr_t baseAddr = 0;
+
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ if (doGenUniqueBaseSystem && !isAppNI && isTPADll(path)) {
+ baseAddr = getNextBaseAddr();
+ }
+#endif
+
+ if (!crossgen(path, appPaths.c_str(), enableR2R, baseAddr, isAppNI)) {
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ if (doGenUniqueBaseSystem && !isAppNI && baseAddr != 0) {
+ updateBaseAddrFile(path, baseAddr);
+ }
+#endif
+
waitInterval();
}
};
std::string tacDir = concatPath(binDir, TAC_SYMLINK_SUB_DIR);
std::string paths[] = {binDir, libDir, tacDir};
- createNiUnderDirs(paths, 3, enableR2R, true);
+ createNiUnderDirs(paths, 3, enableR2R, false, true);
return NI_ERROR_NONE;
}
std::string appTAC = concatPath(binDir, ".TAC.Release");
std::string paths = binDir + ":" + libDir + ":" + appTAC;
- return crossgen(dllPath, paths, enableR2R, true);
+ return crossgen(dllPath, paths, enableR2R, 0, true);
}
void removeNiPlatform()
return;
}
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ if (isFileExist(SYSTEM_BASE_FILE)) {
+ if (remove(SYSTEM_BASE_FILE)) {
+ fprintf(stderr, "Failed to remove " SYSTEM_BASE_FILE " file\n");
+ }
+ }
+#endif
+
if (remove(coreLib.c_str())) {
fprintf(stderr, "Failed to remove System.Private.CoreLib native image file\n");
}
" --reset-system - Remove System NI files\n"
" --reset-pkg - Remove App NI files\n"
" --regen-all-app - Re-generate All App NI files\n"
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ " --gen-unique-baddr-system - Generate unique base addr for dll\n"
+#endif
"\n"
"Example:\n"
"1. Create native image for dlls and exes under platform directories\n"
"3. Create native image under the package's bin and lib directory\n"
" # %s --pkg org.tizen.FormsGallery\n"
"4. Regenerate native images for all installed .net packages with ready-to-run option\n"
- " # %s --r2r --regen-all-app\n\n";
- printf(helpDesc, argv0, argv0, argv0, argv0, argv0);
+ " # %s --r2r --regen-all-app\n\n"
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ "5. Generate unique base addr for system dll\n"
+ " # %s --gen-unique-baddr-system --dll /usr/bin/Tizen.Runtime.dll\n\n"
+#endif
+ ;
+ printf(helpDesc, argv0, argv0, argv0, argv0, argv0, argv0);
}
int main(int argc, char* argv[])
bool enableR2R = false;
bool pkgDllMode = false;
+ bool doGenUniqueBaseSystem = false;
+
NiCommonOption option = {std::string(), std::string(), std::string()};
if (initNICommon(&option) != NI_ERROR_NONE) {
fprintf(stderr, "Fail to initialize NI Common\n");
enableR2R = true;
}
+ if (cmdOptionExists(argv, argv+argc, "--gen-unique-baddr-system")) {
+#ifdef UNIQUE_DEFAULT_BASE_ADDR_SUPPORT
+ doGenUniqueBaseSystem = true;
+#else
+ fprintf(stderr, "--gen-unique-baddr-system is not supported\n");
+#endif
+ }
+
if (cmdOptionExists(argv, argv+argc, "--help")) {
help(argv[0]);
return 0;
} else if (cmdOptionExists(argv, argv+argc, "--system")) {
- createNiPlatform(enableR2R);
+ createNiPlatform(enableR2R, doGenUniqueBaseSystem);
return 0;
} else if (cmdOptionExists(argv, argv+argc, "--dll")) {
dllMode = true;
// donot return error code for generation failure.
// we have to run crossgen for all input dlls.
for (const std::string dll : args) {
- int ret = createNiDll(dll, enableR2R);
+ int ret = createNiDll(dll, enableR2R, doGenUniqueBaseSystem);
if (ret == NI_ERROR_ALREADY_EXIST) {
// skip for already exist case
} else if (ret != NI_ERROR_NONE) {
}
}
} else if (dirMode) {
- createNiUnderDirs(args.data(), args.size(), enableR2R);
+ createNiUnderDirs(args.data(), args.size(), enableR2R, doGenUniqueBaseSystem);
}
return 0;