From 8ab68bc69cf19da6352a2943cc7201819901d7a4 Mon Sep 17 00:00:00 2001 From: Gleb Balykov Date: Fri, 21 Jun 2019 03:55:10 +0300 Subject: [PATCH] Add custom default base address option to crossgen (dotnet/coreclr#25227) * Add crossgen option to setup default base address for native image This is enabled only with -DFEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION. * Mmap native images at default base address if env variable COMPlus_UseDefaultBaseAddr=0x1 is setup. This is enabled only with -DFEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION. Commit migrated from https://github.com/dotnet/coreclr/commit/86e600cef40a650a8ffb294dd195186b1679609b --- src/coreclr/clrdefinitions.cmake | 3 +++ src/coreclr/src/inc/zapper.h | 5 +++++ src/coreclr/src/pal/src/CMakeLists.txt | 3 +++ src/coreclr/src/pal/src/include/pal/init.h | 2 ++ src/coreclr/src/pal/src/init/pal.cpp | 19 +++++++++++++++++++ src/coreclr/src/pal/src/map/map.cpp | 9 ++++++++- src/coreclr/src/tools/crossgen/crossgen.cpp | 20 +++++++++++++++++++- src/coreclr/src/zap/zapimage.cpp | 6 ++++++ src/coreclr/src/zap/zapper.cpp | 17 ++++++++++++++++- 9 files changed, 81 insertions(+), 3 deletions(-) diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index aacc2f0..19eab4d 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -196,6 +196,9 @@ endif () if (FEATURE_NGEN_RELOCS_OPTIMIZATIONS) add_definitions(-DFEATURE_NGEN_RELOCS_OPTIMIZATIONS) endif(FEATURE_NGEN_RELOCS_OPTIMIZATIONS) +if (FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) + add_definitions(-DFEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) +endif(FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) add_definitions(-DFEATURE_SVR_GC) add_definitions(-DFEATURE_SYMDIFF) add_definitions(-DFEATURE_TIERED_COMPILATION) diff --git a/src/coreclr/src/inc/zapper.h b/src/coreclr/src/inc/zapper.h index 33bad04..29fc4fb 100644 --- a/src/coreclr/src/inc/zapper.h +++ b/src/coreclr/src/inc/zapper.h @@ -129,6 +129,8 @@ class Zapper SString m_outputFilename; + SIZE_T m_customBaseAddress; + public: struct assemblyDependencies @@ -362,6 +364,9 @@ class Zapper void SetOutputFilename(LPCWSTR pwszOutputFilename); SString GetOutputFileName(); + void SetCustomBaseAddress(SIZE_T baseAddress); + SIZE_T GetCustomBaseAddress(); + private: void DestroyDomain(); diff --git a/src/coreclr/src/pal/src/CMakeLists.txt b/src/coreclr/src/pal/src/CMakeLists.txt index 6d8d92f..3e2cee8 100644 --- a/src/coreclr/src/pal/src/CMakeLists.txt +++ b/src/coreclr/src/pal/src/CMakeLists.txt @@ -123,6 +123,9 @@ if(CMAKE_SYSTEM_NAME STREQUAL Darwin) ) endif(CMAKE_SYSTEM_NAME STREQUAL Darwin) +if (FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) + add_definitions(-DFEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) +endif(FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION) add_definitions(-DPLATFORM_UNIX) add_definitions(-DLP64COMPATIBLE) add_definitions(-DFEATURE_PAL) diff --git a/src/coreclr/src/pal/src/include/pal/init.h b/src/coreclr/src/pal/src/include/pal/init.h index 0f4c672..7001fc8 100644 --- a/src/coreclr/src/pal/src/include/pal/init.h +++ b/src/coreclr/src/pal/src/include/pal/init.h @@ -41,6 +41,8 @@ extern Volatile init_count; extern SIZE_T g_defaultStackSize; +extern BOOL g_useDefaultBaseAddr; + /*++ MACRO: PALIsInitialized diff --git a/src/coreclr/src/pal/src/init/pal.cpp b/src/coreclr/src/pal/src/init/pal.cpp index 8150406..ab926a1 100644 --- a/src/coreclr/src/pal/src/init/pal.cpp +++ b/src/coreclr/src/pal/src/init/pal.cpp @@ -104,6 +104,9 @@ static pthread_mutex_t init_critsec_mutex = PTHREAD_MUTEX_INITIALIZER; // The default minimum stack size SIZE_T g_defaultStackSize = 0; +// The default value of parameter, whether to mmap images at default base address or not +BOOL g_useDefaultBaseAddr = FALSE; + /* critical section to protect access to init_count. This is allocated on the very first PAL_Initialize call, and is freed afterward. */ static PCRITICAL_SECTION init_critsec = NULL; @@ -382,6 +385,22 @@ Initialize( } #endif // ENSURE_PRIMARY_STACK_SIZE +#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + char* useDefaultBaseAddr = getenv("COMPlus_UseDefaultBaseAddr"); + if (useDefaultBaseAddr != NULL) + { + errno = 0; + // Like all numeric values specific by the COMPlus_xxx variables, it is a + // hexadecimal string without any prefix. + long int flag = strtol(useDefaultBaseAddr, NULL, 16); + + if (errno == 0) + { + g_useDefaultBaseAddr = (BOOL) flag; + } + } +#endif // FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + // Initialize the TLS lookaside cache if (FALSE == TLSInitialize()) { diff --git a/src/coreclr/src/pal/src/map/map.cpp b/src/coreclr/src/pal/src/map/map.cpp index ba764c0..f6a15f2 100644 --- a/src/coreclr/src/pal/src/map/map.cpp +++ b/src/coreclr/src/pal/src/map/map.cpp @@ -2350,9 +2350,16 @@ void * MAPMapPEFile(HANDLE hFile) if (loadedBase == NULL) { + void *usedBaseAddr = NULL; +#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + if (g_useDefaultBaseAddr) + { + usedBaseAddr = (void*) preferredBase; + } +#endif // FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION // MAC64 requires we pass MAP_SHARED (or MAP_PRIVATE) flags - otherwise, the call is failed. // Refer to mmap documentation at http://www.manpagez.com/man/2/mmap/ for details. - loadedBase = mmap(NULL, virtualSize, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); + loadedBase = mmap(usedBaseAddr, virtualSize, PROT_NONE, MAP_ANON|MAP_PRIVATE, -1, 0); } if (MAP_FAILED == loadedBase) diff --git a/src/coreclr/src/tools/crossgen/crossgen.cpp b/src/coreclr/src/tools/crossgen/crossgen.cpp index 39d91a1..1d8e76f 100644 --- a/src/coreclr/src/tools/crossgen/crossgen.cpp +++ b/src/coreclr/src/tools/crossgen/crossgen.cpp @@ -34,7 +34,7 @@ enum ReturnValues #define NumItems(s) (sizeof(s) / sizeof(s[0])) STDAPI CreatePDBWorker(LPCWSTR pwzAssemblyPath, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzAppNiPaths, LPCWSTR pwzPdbPath, BOOL fGeneratePDBLinesInfo, LPCWSTR pwzManagedPdbSearchPath, LPCWSTR pwzPlatformWinmdPaths, LPCWSTR pwzDiasymreaderPath); -STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, LPCWSTR pwzPlatformWinmdPaths=NULL, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr); +STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, SIZE_T customBaseAddress=0, LPCWSTR pwzPlatformWinmdPaths=NULL, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr); void SetSvcLogger(ICorSvcLogger *pCorSvcLogger); void SetMscorlibPath(LPCWSTR wzSystemDirectory); @@ -155,6 +155,9 @@ void PrintUsageHelper() W(" input assemblies\n") #endif +#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + W(" /BaseAddress - Specifies base address to use for compilation.\n") +#endif #ifdef FEATURE_WINMD_RESILIENT W(" WinMD Parameters\n") W(" /WinMDResilient - Generate images resilient to WinMD dependency changes.\n") @@ -436,6 +439,7 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) LPCWSTR pwzOutputFilename = NULL; LPCWSTR pwzPublicKeys = nullptr; bool fLargeVersionBubbleSwitch = false; + SIZE_T baseAddress = 0; #if !defined(FEATURE_MERGE_JIT_AND_ENGINE) LPCWSTR pwszCLRJITPath = nullptr; @@ -544,6 +548,19 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) fLargeVersionBubbleSwitch = true; } #endif +#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION + else if (MatchParameter(*argv, W("BaseAddress"))) + { + if (baseAddress != 0) + { + OutputErr(W("Cannot specify multiple base addresses.\n")); + exit(INVALID_ARGUMENTS); + } + baseAddress = (SIZE_T) _wcstoui64(argv[1], NULL, 0); + argv++; + argc--; + } +#endif else if (MatchParameter(*argv, W("NoMetaData"))) { dwFlags |= NGENWORKER_FLAGS_NO_METADATA; @@ -942,6 +959,7 @@ int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) pwzPlatformResourceRoots, pwzAppPaths, pwzOutputFilename, + baseAddress, pwzPlatformWinmdPaths #if !defined(FEATURE_MERGE_JIT_AND_ENGINE) , diff --git a/src/coreclr/src/zap/zapimage.cpp b/src/coreclr/src/zap/zapimage.cpp index c498719..4a11405 100644 --- a/src/coreclr/src/zap/zapimage.cpp +++ b/src/coreclr/src/zap/zapimage.cpp @@ -1282,6 +1282,12 @@ void ZapImage::CalculateZapBaseAddress() } } + if (m_zapper->GetCustomBaseAddress() != 0) + { + //set baseAddress here from crossgen options + baseAddress = m_zapper->GetCustomBaseAddress(); + } + // Round to a multiple of 64K // 64K is the allocation granularity of VirtualAlloc. (Officially this number is not a constant - // we should be querying the system for its allocation granularity, but we do this all over the place diff --git a/src/coreclr/src/zap/zapper.cpp b/src/coreclr/src/zap/zapper.cpp index e511b57..66346d7 100644 --- a/src/coreclr/src/zap/zapper.cpp +++ b/src/coreclr/src/zap/zapper.cpp @@ -33,7 +33,7 @@ static bool s_fNGenNoMetaData; // Zapper Object instead of creating one on your own. -STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, LPCWSTR pwzPlatformWinmdPaths=NULL, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr) +STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, SIZE_T customBaseAddress=0, LPCWSTR pwzPlatformWinmdPaths=NULL, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr) { HRESULT hr = S_OK; @@ -83,6 +83,8 @@ STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembl if (pwzOutputFilename) zap->SetOutputFilename(pwzOutputFilename); + zap->SetCustomBaseAddress(customBaseAddress); + if (pwzPlatformAssembliesPaths != nullptr) zap->SetPlatformAssembliesPaths(pwzPlatformAssembliesPaths); @@ -408,6 +410,8 @@ void Zapper::Init(ZapperOptions *pOptions, bool fFreeZapperOptions) m_pAssemblyEmit = NULL; m_fFreeZapperOptions = fFreeZapperOptions; + m_customBaseAddress = 0; + #ifdef LOGGING InitializeLogging(); #endif @@ -1688,3 +1692,14 @@ SString Zapper::GetOutputFileName() { return m_outputFilename; } + + +void Zapper::SetCustomBaseAddress(SIZE_T baseAddress) +{ + m_customBaseAddress = baseAddress; +} + +SIZE_T Zapper::GetCustomBaseAddress() +{ + return m_customBaseAddress; +} \ No newline at end of file -- 2.7.4