Add custom default base address option to crossgen (dotnet/coreclr#25227)
authorGleb Balykov <g.balykov@samsung.com>
Fri, 21 Jun 2019 00:55:10 +0000 (03:55 +0300)
committerJan Kotas <jkotas@microsoft.com>
Fri, 21 Jun 2019 00:55:09 +0000 (17:55 -0700)
* 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
src/coreclr/src/inc/zapper.h
src/coreclr/src/pal/src/CMakeLists.txt
src/coreclr/src/pal/src/include/pal/init.h
src/coreclr/src/pal/src/init/pal.cpp
src/coreclr/src/pal/src/map/map.cpp
src/coreclr/src/tools/crossgen/crossgen.cpp
src/coreclr/src/zap/zapimage.cpp
src/coreclr/src/zap/zapper.cpp

index aacc2f0..19eab4d 100644 (file)
@@ -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)
index 33bad04..29fc4fb 100644 (file)
@@ -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();
index 6d8d92f..3e2cee8 100644 (file)
@@ -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)
index 0f4c672..7001fc8 100644 (file)
@@ -41,6 +41,8 @@ extern Volatile<INT> init_count;
 
 extern SIZE_T g_defaultStackSize;
 
+extern BOOL g_useDefaultBaseAddr;
+
 /*++
 MACRO:
   PALIsInitialized
index 8150406..ab926a1 100644 (file)
@@ -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())
         {
index ba764c0..f6a15f2 100644 (file)
@@ -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)
index 39d91a1..1d8e76f 100644 (file)
@@ -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 <value> - 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)
         ,
index c498719..4a11405 100644 (file)
@@ -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
index e511b57..66346d7 100644 (file)
@@ -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