diff --git a/src/coreclr/binder/CMakeLists.txt b/src/coreclr/binder/CMakeLists.txt index f04c647f88f4b6..537791412fd84a 100644 --- a/src/coreclr/binder/CMakeLists.txt +++ b/src/coreclr/binder/CMakeLists.txt @@ -61,21 +61,11 @@ set(BINDER_HEADERS inc/contextentry.hpp ) -set(BINDER_CROSSGEN_SOURCES - ${BINDER_COMMON_SOURCES} -) - -set(BINDER_CROSSGEN_HEADERS - ${BINDER_COMMON_HEADERS} -) - if (CLR_CMAKE_TARGET_WIN32) list(APPEND BINDER_SOURCES ${BINDER_HEADERS}) - list(APPEND BINDER_CROSSGEN_SOURCES ${BINDER_CROSSGEN_HEADERS}) endif(CLR_CMAKE_TARGET_WIN32) convert_to_absolute_path(BINDER_SOURCES ${BINDER_SOURCES}) -convert_to_absolute_path(BINDER_CROSSGEN_SOURCES ${BINDER_CROSSGEN_SOURCES}) add_library_clr(v3binder_obj OBJECT @@ -84,11 +74,3 @@ add_library_clr(v3binder_obj add_dependencies(v3binder_obj eventing_headers) add_library(v3binder INTERFACE) target_sources(v3binder INTERFACE $) - -add_library_clr(v3binder_crossgen - STATIC - ${BINDER_CROSSGEN_SOURCES} -) -add_dependencies(v3binder_crossgen eventing_headers) -set_target_properties(v3binder_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) - diff --git a/src/coreclr/clrdefinitions.cmake b/src/coreclr/clrdefinitions.cmake index 257a9c377e3bac..be2335b5910d57 100644 --- a/src/coreclr/clrdefinitions.cmake +++ b/src/coreclr/clrdefinitions.cmake @@ -1,10 +1,6 @@ include(${CMAKE_CURRENT_LIST_DIR}/clrfeatures.cmake) add_compile_definitions($<$>:DACCESS_COMPILE>) -add_compile_definitions($<$>:CROSSGEN_COMPILE>) -add_compile_definitions($<$>:CROSS_COMPILE>) -add_compile_definitions($<$>:FEATURE_NATIVE_IMAGE_GENERATION>) -add_compile_definitions($<$>:SELF_NO_HOST>) if (CLR_CMAKE_TARGET_ARCH_ARM64) if (CLR_CMAKE_TARGET_UNIX) @@ -58,11 +54,11 @@ if(CLR_CMAKE_HOST_WIN32) endif(CLR_CMAKE_HOST_WIN32) if (NOT (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_UNIX)) - add_compile_definitions($<$>>:EnC_SUPPORTED>) + add_compile_definitions(EnC_SUPPORTED) endif() if(CLR_CMAKE_TARGET_ARCH_AMD64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32)) if(CLR_CMAKE_TARGET_WIN32) - add_compile_definitions($<$>>:FEATURE_ENC_SUPPORTED>) + add_compile_definitions(FEATURE_ENC_SUPPORTED) endif(CLR_CMAKE_TARGET_WIN32) endif(CLR_CMAKE_TARGET_ARCH_AMD64 OR (CLR_CMAKE_TARGET_ARCH_I386 AND CLR_CMAKE_TARGET_WIN32)) @@ -85,7 +81,7 @@ if(CLR_CMAKE_TARGET_UNIX OR NOT CLR_CMAKE_TARGET_ARCH_I386) add_definitions(-DFEATURE_INSTANTIATINGSTUB_AS_IL) endif() -add_compile_definitions($<$>>:FEATURE_CODE_VERSIONING>) +add_compile_definitions(FEATURE_CODE_VERSIONING) add_definitions(-DFEATURE_COLLECTIBLE_TYPES) if(CLR_CMAKE_TARGET_WIN32) @@ -103,7 +99,7 @@ if(FEATURE_DBGIPC) endif(FEATURE_DBGIPC) add_definitions(-DFEATURE_DEFAULT_INTERFACES) if(FEATURE_EVENT_TRACE) - add_compile_definitions($<$>>:FEATURE_EVENT_TRACE>) + add_compile_definitions(FEATURE_EVENT_TRACE) add_definitions(-DFEATURE_PERFTRACING) else(FEATURE_EVENT_TRACE) add_custom_target(eventing_headers) # add a dummy target to avoid checking for FEATURE_EVENT_TRACE in multiple places @@ -132,7 +128,7 @@ if (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ add_definitions(-DFEATURE_INTEROP_DEBUGGING) endif (CLR_CMAKE_TARGET_WIN32 AND (CLR_CMAKE_TARGET_ARCH_AMD64 OR CLR_CMAKE_TARGET_ARCH_I386 OR CLR_CMAKE_TARGET_ARCH_ARM64)) if(FEATURE_INTERPRETER) - add_compile_definitions($<$>>:FEATURE_INTERPRETER>) + add_compile_definitions(FEATURE_INTERPRETER) endif(FEATURE_INTERPRETER) add_definitions(-DFEATURE_ISYM_READER) if (CLR_CMAKE_TARGET_LINUX OR CLR_CMAKE_TARGET_WIN32) @@ -143,7 +139,7 @@ add_definitions(-DFEATURE_MANAGED_ETW_CHANNELS) if(FEATURE_MERGE_JIT_AND_ENGINE) add_compile_definitions($<$>>:FEATURE_MERGE_JIT_AND_ENGINE>) endif(FEATURE_MERGE_JIT_AND_ENGINE) -add_compile_definitions($<$>>:FEATURE_MULTICOREJIT>) +add_compile_definitions(FEATURE_MULTICOREJIT) if(CLR_CMAKE_TARGET_UNIX) add_definitions(-DFEATURE_PAL_ANSI) endif(CLR_CMAKE_TARGET_UNIX) @@ -151,13 +147,8 @@ if(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX) add_definitions(-DFEATURE_PERFMAP) endif(CLR_CMAKE_TARGET_LINUX AND CLR_CMAKE_HOST_LINUX) if(CLR_CMAKE_TARGET_FREEBSD) - add_compile_definitions($<$>>:FEATURE_PERFMAP>) + add_compile_definitions(FEATURE_PERFMAP) endif(CLR_CMAKE_TARGET_FREEBSD) -if(FEATURE_PREJIT) - add_definitions(-DFEATURE_PREJIT) -else() - add_compile_definitions($<$>:FEATURE_PREJIT>) -endif(FEATURE_PREJIT) if(FEATURE_COMWRAPPERS) add_compile_definitions(FEATURE_COMWRAPPERS) @@ -167,14 +158,13 @@ if(FEATURE_OBJCMARSHAL) add_compile_definitions(FEATURE_OBJCMARSHAL) endif() -add_compile_definitions($<$>>,$>>>:FEATURE_PROFAPI_ATTACH_DETACH>) +add_compile_definitions($<$>>:FEATURE_PROFAPI_ATTACH_DETACH>) add_definitions(-DFEATURE_READYTORUN) -add_compile_definitions($<$>:FEATURE_READYTORUN_COMPILER>) set(FEATURE_READYTORUN 1) -add_compile_definitions($<$>>:FEATURE_REJIT>) +add_compile_definitions(FEATURE_REJIT) if (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_TARGET_UNIX) add_definitions(-DFEATURE_REMOTE_PROC_MEM) @@ -183,19 +173,16 @@ endif (CLR_CMAKE_HOST_UNIX AND CLR_CMAKE_TARGET_UNIX) if (CLR_CMAKE_TARGET_UNIX OR CLR_CMAKE_TARGET_ARCH_ARM64) add_definitions(-DFEATURE_STUBS_AS_IL) 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_compile_definitions($<$>>:FEATURE_TIERED_COMPILATION>) +add_compile_definitions(FEATURE_TIERED_COMPILATION) if (CLR_CMAKE_TARGET_ARCH_AMD64) - add_compile_definitions($<$>>:FEATURE_ON_STACK_REPLACEMENT>) + add_compile_definitions(FEATURE_ON_STACK_REPLACEMENT) endif (CLR_CMAKE_TARGET_ARCH_AMD64) -add_compile_definitions($<$>>:FEATURE_PGO>) +add_compile_definitions(FEATURE_PGO) if (CLR_CMAKE_TARGET_WIN32) add_definitions(-DFEATURE_TYPEEQUIVALENCE) endif(CLR_CMAKE_TARGET_WIN32) diff --git a/src/coreclr/gcinfo/CMakeLists.txt b/src/coreclr/gcinfo/CMakeLists.txt index bfddaee4b700af..96319fd98b4252 100644 --- a/src/coreclr/gcinfo/CMakeLists.txt +++ b/src/coreclr/gcinfo/CMakeLists.txt @@ -32,13 +32,6 @@ add_library_clr(gcinfo_obj add_library(gcinfo INTERFACE) target_sources(gcinfo INTERFACE $) -add_library_clr(gcinfo_crossgen - STATIC - ${GCINFO_SOURCES} -) - -set_target_properties(gcinfo_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) - install (FILES gcinfoencoder.cpp DESTINATION gcinfo) diff --git a/src/coreclr/jit/CMakeLists.txt b/src/coreclr/jit/CMakeLists.txt index 629ea1ae4bc9d7..ae033295cee5fa 100644 --- a/src/coreclr/jit/CMakeLists.txt +++ b/src/coreclr/jit/CMakeLists.txt @@ -482,10 +482,6 @@ endfunction() set(JIT_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}) -if (FEATURE_MERGE_JIT_AND_ENGINE) - add_subdirectory(crossgen) -endif (FEATURE_MERGE_JIT_AND_ENGINE) - # Creates a static library "clrjit_static" to link into the VM. add_subdirectory(static) diff --git a/src/coreclr/jit/crossgen/CMakeLists.txt b/src/coreclr/jit/crossgen/CMakeLists.txt deleted file mode 100644 index 30d35e8cde59ed..00000000000000 --- a/src/coreclr/jit/crossgen/CMakeLists.txt +++ /dev/null @@ -1,6 +0,0 @@ -add_library_clr(clrjit_crossgen ${SOURCES} ${JIT_ARCH_SOURCES}) -if(FEATURE_MERGE_JIT_AND_ENGINE) - target_link_libraries(clrjit_crossgen ${JIT_LINK_LIBRARIES} ${JIT_ARCH_LINK_LIBRARIES}) -endif(FEATURE_MERGE_JIT_AND_ENGINE) -set_target_properties(clrjit_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(clrjit_static PRIVATE [["jitpch.h"]]) diff --git a/src/coreclr/md/compiler/CMakeLists.txt b/src/coreclr/md/compiler/CMakeLists.txt index a2d3a5776c0b49..3ef387534a476d 100644 --- a/src/coreclr/md/compiler/CMakeLists.txt +++ b/src/coreclr/md/compiler/CMakeLists.txt @@ -76,10 +76,6 @@ add_library_clr(mdcompiler-dbi ${MDCOMPILER_SOURCES}) set_target_properties(mdcompiler-dbi PROPERTIES DBI_COMPONENT TRUE) target_precompile_headers(mdcompiler-dbi PRIVATE stdafx.h) -add_library_clr(mdcompiler_crossgen ${MDCOMPILER_SOURCES}) -set_target_properties(mdcompiler_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(mdcompiler_crossgen PRIVATE stdafx.h) - add_library_clr(mdcompiler_ppdb ${MDCOMPILER_SOURCES}) target_compile_definitions(mdcompiler_ppdb PRIVATE FEATURE_METADATA_EMIT_ALL FEATURE_METADATA_EMIT_PORTABLE_PDB) target_precompile_headers(mdcompiler_ppdb PRIVATE stdafx.h) diff --git a/src/coreclr/md/hotdata/CMakeLists.txt b/src/coreclr/md/hotdata/CMakeLists.txt index 7f8ba752c4bf5e..37bdc0bc58807a 100644 --- a/src/coreclr/md/hotdata/CMakeLists.txt +++ b/src/coreclr/md/hotdata/CMakeLists.txt @@ -38,10 +38,6 @@ target_precompile_headers(mdhotdata_full_obj PRIVATE external.h) add_library(mdhotdata_full INTERFACE) target_sources(mdhotdata_full INTERFACE $) -add_library_clr(mdhotdata_crossgen ${MDHOTDATA_SOURCES}) -set_target_properties(mdhotdata_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(mdhotdata_crossgen PRIVATE external.h) - if(CLR_CMAKE_HOST_WIN32) add_library_clr(mdhotdata-staticcrt ${MDHOTDATA_SOURCES}) target_precompile_headers(mdhotdata-staticcrt PRIVATE external.h) diff --git a/src/coreclr/tools/crossgen/CMakeLists.txt b/src/coreclr/tools/crossgen/CMakeLists.txt deleted file mode 100644 index 6b998ebb9e1ad1..00000000000000 --- a/src/coreclr/tools/crossgen/CMakeLists.txt +++ /dev/null @@ -1,83 +0,0 @@ -project(crossgen) - -set(CMAKE_INCLUDE_CURRENT_DIR ON) -include_directories(../util) -include_directories(../../pal/prebuilt/corerror) - -set(crossgen_SOURCES crossgen.cpp ../util/consoleargs.cpp) -if(CLR_CMAKE_TARGET_WIN32) - list(APPEND crossgen_SOURCES ../util/consoleargs.h) - set(crossgen_RESOURCES Native.rc) -endif() - -if(CLR_CMAKE_HOST_WIN32) - add_definitions(-D_CRT_NON_CONFORMING_WCSTOK) -endif() - -if(CLR_CMAKE_HOST_UNIX) - add_definitions(-DNO_NGENPDB) -endif(CLR_CMAKE_HOST_UNIX) - -add_definitions(-DFX_VER_INTERNALNAME_STR=crossgen.exe) - -add_executable_clr(crossgen - ${crossgen_SOURCES} - ${crossgen_RESOURCES} -) -set_target_properties(crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) - -if(FEATURE_MERGE_JIT_AND_ENGINE) - set(CLRJIT_CROSSGEN clrjit_crossgen) -endif(FEATURE_MERGE_JIT_AND_ENGINE) - -if(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) - # The following linked options can be inserted into the linker libraries list to - # ensure proper resolving of circular references between a subset of the libraries. - set(START_LIBRARY_GROUP -Wl,--start-group) - set(END_LIBRARY_GROUP -Wl,--end-group) -endif(CLR_CMAKE_HOST_LINUX OR CLR_CMAKE_HOST_FREEBSD OR CLR_CMAKE_HOST_NETBSD OR CLR_CMAKE_HOST_SUNOS) - -target_link_libraries(crossgen - ${START_LIBRARY_GROUP} # Start group of libraries that have circular references - cee_crossgen - v3binder_crossgen - mdcompiler_crossgen - mdruntime_crossgen - mdruntimerw_crossgen - mdhotdata_crossgen - ${END_LIBRARY_GROUP} # End group of libraries that have circular references - corguids - ${CLRJIT_CROSSGEN} - gcinfo_crossgen - corzap_crossgen - corelib_crossgen - utilcode_crossgen -) - -if(CLR_CMAKE_HOST_UNIX) - target_link_libraries(crossgen - mscorrc - palrt - coreclrpal - ) -else() - target_link_libraries(crossgen - advapi32 - ole32 - oleaut32 - uuid - user32 - version - shlwapi - bcrypt - ${STATIC_MT_CRT_LIB} - ${STATIC_MT_VCRT_LIB} - ) - -endif(CLR_CMAKE_HOST_UNIX) - -add_subdirectory(../../zap ../../zap) -add_subdirectory(../../vm/crossgen ../../vm/crossgen) - -# add the install targets -install_clr(TARGETS crossgen DESTINATIONS . sharedFramework COMPONENT runtime) diff --git a/src/coreclr/tools/crossgen/Native.rc b/src/coreclr/tools/crossgen/Native.rc deleted file mode 100644 index c90ad0d19ccf89..00000000000000 --- a/src/coreclr/tools/crossgen/Native.rc +++ /dev/null @@ -1,6 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -#define FX_VER_FILEDESCRIPTION_STR "Microsoft Common Language Runtime native cross compiler\0" - -#include "..\..\dlls\mscorrc\mscorrc.rc" diff --git a/src/coreclr/tools/crossgen/compare.bat b/src/coreclr/tools/crossgen/compare.bat deleted file mode 100644 index 436876a02a76c1..00000000000000 --- a/src/coreclr/tools/crossgen/compare.bat +++ /dev/null @@ -1,168 +0,0 @@ -::mscorlib -::System -::System.Core -::System.Xml -::System.Configuration -::System.Drawing -::System.Data -::System.Windows.Forms -::System.Runtime.Remoting -::System.Serviceprocess -::System.Management -::Accessibility -::Microsoft.VisualBasic -::System.DirectoryServices -::System.Transactions -::System.Web.Services -::CustomMarshalers -::System.Configuration.Install -::System.Xaml -::WindowsBase -::System.Net.Http -::System.Xml.Linq -::System.Runtime.WindowsRuntime -::System.Runtime.WindowsRuntime.UI.Xaml -::System.Runtime.Serialization -::System.ServiceModel -::PresentationCore -::PresentationFramework -::System.EnterpriseServices -::System.Collections.Concurrent -::System.Collections -::System.ComponentModel.Annotations -::System.ComponentModel -::System.ComponentModel.EventBasedAsync -::System.Diagnostics.Contracts -::System.Diagnostics.Debug -::System.Diagnostics.Tools -::System.Diagnostics.Tracing -::System.Dynamic.Runtime -::System.Globalization -::System.IO -::System.Linq -::System.Linq.Expressions -::System.Linq.Parallel -::System.Linq.Queryable -::System.Net.Http.Rtc -::System.Net.NetworkInformation -::System.Net.Primitives -::System.Net.Requests -::System.ObjectModel -::System.Reflection -::System.Reflection.Emit -::System.Reflection.Emit.ILGeneration -::System.Reflection.Emit.Lightweight -::System.Reflection.Extensions -::System.Reflection.Primitives -::System.Resources.ResourceManager -::System.Runtime -::System.Runtime.Extensions -::System.Runtime.InteropServices -::System.Runtime.InteropServices.WindowsRuntime -::System.Runtime.Numerics -::System.Runtime.Serialization.Json -::System.Runtime.Serialization.Primitives -::System.Runtime.Serialization.Xml -::System.Security.Principal -::System.ServiceModel.Duplex -::System.ServiceModel.Http -::System.ServiceModel.NetTcp -::System.ServiceModel.Primitives -::System.ServiceModel.Security -::System.Text.Encoding -::System.Text.Encoding.Extensions -::System.Text.RegularExpressions -::System.Threading -::System.Threading.Tasks -::System.Threading.Tasks.Parallel -::System.Windows -::System.Xml.ReaderWriter -::System.Xml.XDocument -::System.Xml.XmlSerializer -::END_OF_LIST - -@echo off - -rem -rem This script compares ngen and crossgen output for framework assemblies -rem - -SETLOCAL ENABLEDELAYEDEXPANSION - -set BITNESS= -IF /I "%_BuildArch%" == "amd64" set BITNESS=64 -set FRAMEWORKDIR=%SYSTEMROOT%\Microsoft.NET\Framework%BITNESS%\%COMPlus_Version% -IF "%BITNESS%" == "" set BITNESS=32 - -set NATIVEIMAGEPATH=%FRAMEWORKDIR%\assembly\NativeImages_%COMPlus_Version%_%BITNESS% - -rem rmdir /S /Q %NATIVEIMAGEPATH% -rem %FRAMEWORKDIR%\ngen install mscorlib -rem %FRAMEWORKDIR%\ngen update - -%FRAMEWORKDIR%\gacutil /if %_NTTREE%\System.Runtime.WindowsRuntime.dll -%FRAMEWORKDIR%\gacutil /if %_NTTREE%\System.Runtime.WindowsRuntime.UI.Xaml.dll - -set ILIMAGEPATH=%_NTTREE%\il -rmdir /S /Q %ILIMAGEPATH% -if not exist %ILIMAGEPATH% mkdir %ILIMAGEPATH% - -rem Collect all files from the GAC into ILIMAGEPATH directory to guaranteed that we get the exact same IL images -rem between ngen and crossgen. It is important on non-x86 builds because of non-x86 layouts pull files from x86 build. -forfiles /P %FRAMEWORKDIR%\assembly\GAC_%BITNESS% /M *.dll /S /C "cmd /c copy @path %ILIMAGEPATH%\@file > nul" -forfiles /P %FRAMEWORKDIR%\assembly\GAC_MSIL /M *.dll /S /C "cmd /c copy @path %ILIMAGEPATH%\@file > nul" -rem clr.dll and clrjit.dll are required for timestamps -copy %FRAMEWORKDIR%\clr.dll %ILIMAGEPATH%\clr.dll >nul -copy %FRAMEWORKDIR%\clrjit.dll %ILIMAGEPATH%\clrjit.dll >nul - -set CROSSGENIMAGEPATH=%_NTTREE%\ni -rmdir /S /Q %CROSSGENIMAGEPATH% -if not exist %CROSSGENIMAGEPATH% mkdir %CROSSGENIMAGEPATH% - -set SELF=%~fd0 -set FAILED= - -for /f "eol=; usebackq tokens=1,2,3* delims=,:" %%I in ("%SELF%") DO ( - if "%%I"=="END_OF_LIST" goto LDone - call :ProcessFile %%I - if "!FAILED!"=="1" goto LFailed -) - -:LDone -echo DONE -exit /B 0 - -:LFailed -echo FAILED -exit /B 1 - -:ProcessFile - -set FILEPATH= -call :ProbeFile %ILIMAGEPATH%\%1.dll - -if "%FILEPATH%" == "" ( echo File not found: %1 & goto LError ) - -echo. -echo ========= COMPILE and COMPARE %1 ========== -echo ngen install /nodependencies %FILEPATH% -ngen install /nodependencies %FILEPATH% -echo. -echo %_NTTREE%\crossgen /platform_assemblies_paths %ILIMAGEPATH%;%CROSSGENIMAGEPATH% /in %FILEPATH% /out %CROSSGENIMAGEPATH%\%1.ni.dll -%_NTTREE%\crossgen /platform_assemblies_paths %ILIMAGEPATH%;%CROSSGENIMAGEPATH% /in %FILEPATH% /out %CROSSGENIMAGEPATH%\%1.ni.dll -IF NOT "%ERRORLEVEL%"=="0" set FAILED=1 -echo. -forfiles /P %NATIVEIMAGEPATH% /M %1.ni.dll /S /C "cmd /c echo Compare: @path & fc /B @path %CROSSGENIMAGEPATH%\%1.ni.dll > %CROSSGENIMAGEPATH%\diff.txt & IF NOT ERRORLEVEL 1 del %CROSSGENIMAGEPATH%\diff.txt" -IF not exist %CROSSGENIMAGEPATH%\diff.txt goto LExit -echo ----- DIFFERENT ----- -:LError -set FAILED=1 -goto LExit - -:ProbeFile -if NOT "%FILEPATH%" == "" goto LExit -if NOT exist "%1" goto LExit -set FILEPATH=%1 -goto LExit - -:LExit diff --git a/src/coreclr/tools/crossgen/crossgen.cpp b/src/coreclr/tools/crossgen/crossgen.cpp deleted file mode 100644 index 61faeb761a6bb6..00000000000000 --- a/src/coreclr/tools/crossgen/crossgen.cpp +++ /dev/null @@ -1,949 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// -// TO DO: we currently use raw printf() for output. Maybe we need to pick up something like ngen's Output() handling -// to handle multiple code pages, etc, better. - -#include -#include -#include - -#include -#include -#include - -#include "palclr.h" - -#include -#include "ex.h" - -#include "coregen.h" -#include "consoleargs.h" - -// Return values from wmain() in case of error -enum ReturnValues -{ - FAILURE_RESULT = 1, - CLR_INIT_ERROR = -2, - ASSEMBLY_NOT_FOUND = -3, - INVALID_ARGUMENTS = -4 -}; - -#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 pwzDiasymreaderPath); -STDAPI NGenWorker(LPCWSTR pwzFilename, DWORD dwFlags, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzOutputFilename=NULL, SIZE_T customBaseAddress=0, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr); -void SetSvcLogger(ICorSvcLogger *pCorSvcLogger); -void SetCoreLibPath(LPCWSTR wzSystemDirectory); - -/* --------------------------------------------------------------------------- * - * Console stuff - * --------------------------------------------------------------------------- */ - -void Output(LPCWSTR str) -{ - wprintf(W("%s"), str); -} - -void Outputf(LPCWSTR szFormat, ...) -{ - va_list args; - va_start(args, szFormat); - vfwprintf(stdout, szFormat, args); - va_end(args); -} - -void OutputErr(LPCWSTR str) -{ - fwprintf(stderr, W("%s"), str); -} - -void OutputErrf(LPCWSTR szFormat, ...) -{ - va_list args; - va_start(args, szFormat); - vfwprintf(stderr, szFormat, args); - va_end(args); -} - -void ErrorHR(HRESULT hr) -{ - OutputErrf(W("Error: failed to initialize CoreCLR: 0x%08x\n"), hr); -} - -void ErrorWin32(DWORD err) -{ - ErrorHR(HRESULT_FROM_WIN32(err)); -} - -// Some error messages are useless to callers, so make them generic, except in debug builds, where we want as much -// information as possible. - -#ifdef _DEBUG -#define ERROR_HR(msg,hr) Outputf(msg, hr) -#define ERROR_WIN32(msg,err) Outputf(msg, err) -#else // _DEBUG -#define ERROR_HR(msg,hr) ErrorHR(hr) -#define ERROR_WIN32(msg,err) ErrorWin32(err) -#endif // _DEBUG - - -void PrintLogoHelper() -{ - Output(W("Microsoft (R) CoreCLR Native Image ")); - Outputf(W("Generator - Version %S\n"), CLR_PRODUCT_VERSION); - Outputf(W("%S\n"), VER_LEGALCOPYRIGHT_LOGO_STR); - Output(W("\n")); -} - -void PrintUsageHelper() -{ - // Always print the logo when we print the usage, even if they've specified /nologo and we've parsed that already. - PrintLogoHelper(); - - Output( - W("Usage: crossgen [args] \n") - W("\n") - W(" /? or /help - Display this screen\n") - W(" /nologo - Prevents displaying the logo\n") - W(" /nowarnings - Prevents displaying warning messages\n") - W(" /silent - Do not display completion message\n") - W(" /verbose - Display verbose information\n") - W(" @response.rsp - Process command line arguments from specified\n") - W(" response file\n") - W(" /in - Specifies input filename (optional)\n") - W(" /out - Specifies output filename (optional)\n") - W(" /r - Specifies a trusted platform assembly reference\n") - W(" - Cannot be used with /p\n") - W(" /p - List of paths containing target platform assemblies\n") - // If /p, we will use it to build the TPA list and thus, - // TPA list cannot be explicitly specified. - W(" - Cannot be used with /r\n") - - W(" /Platform_Resource_Roots \n") - W(" - List of paths containing localized assembly directories\n") - W(" /App_Paths \n") - W(" - List of paths containing user-application assemblies and resources\n") -#ifndef NO_NGENPDB - W(" /App_Ni_Paths \n") - W(" - List of paths containing user-application native images\n") - W(" - Must be used with /CreatePDB switch\n") -#endif // NO_NGENPDB - W(" /MissingDependenciesOK\n") - W(" - Specifies that crossgen should attempt not to fail\n") - W(" if a dependency is missing.\n") -#if 0 - W(" /Tuning - Generate an instrumented image to collect\n") - W(" scenario traces, which can be used with ibcmerge.exe\n") -#endif -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - W(" /JITPath \n") - W(" - Specifies the absolute file path to JIT compiler to be used.\n") -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) -#ifdef FEATURE_READYTORUN_COMPILER - W(" /ReadyToRun - Generate images resilient to the runtime and\n") - W(" dependency versions\n") - W(" /LargeVersionBubble - Generate image with a version bubble including all\n") - W(" input assemblies\n") - -#endif -#ifdef FEATURE_ENABLE_NO_ADDRESS_SPACE_RANDOMIZATION - W(" /BaseAddress - Specifies base address to use for compilation.\n") -#endif -#ifndef NO_NGENPDB - W(" Debugging Parameters\n") - W(" /CreatePDB [/lines [] ]\n") - W(" When specifying /CreatePDB, the native image should be created\n") - W(" first, and should be the path to the NI.\n") - W(" /DiasymreaderPath \n") - W(" - Specifies the absolute file path to diasymreader.dll to be used.\n") -#elif defined(FEATURE_PERFMAP) - W(" Debugging Parameters\n") - W(" /CreatePerfMap \n") - W(" When specifying /CreatePerfMap, the native image should be created\n") - W(" first, and should be the path to the NI.\n") -#endif - ); -} - -class CrossgenLogger : public ICorSvcLogger -{ -public: - STDMETHODIMP_(ULONG) AddRef() {return E_NOTIMPL;} - STDMETHODIMP_(ULONG) Release() {return E_NOTIMPL;} - STDMETHODIMP QueryInterface(REFIID riid,void ** ppv) - { - if (ppv==0) - return E_POINTER; - - *ppv = NULL; - - if (IsEqualIID(riid, IID_ICorSvcLogger) || IsEqualIID(riid, IID_IUnknown)) - { - *ppv = this; - return S_OK; - } - else - { - return E_NOINTERFACE; - } - } - - HRESULT STDMETHODCALLTYPE Log( - /*[in] */CorSvcLogLevel logLevel, - /*[in] */BSTR message - ) - { - if (logLevel == LogLevel_Error) - OutputErr(message); - else if(logLevel != LogLevel_Warning || m_bEnableWarningLogging) - Output(message); - return S_OK; - } - - void SetWarningLogging(bool value) - { - m_bEnableWarningLogging = value; - } - - CrossgenLogger() : m_bEnableWarningLogging(true) { } - -private: - bool m_bEnableWarningLogging; -}; - -CrossgenLogger g_CrossgenLogger; - -// -// Tests whether szArg, the currently indexed argv matches the specified parameter name, szTestParamName. -// Specify szTestParamName without a switch. This method handles testing for - and / switches. -// -bool MatchParameter(LPCWSTR szArg, LPCWSTR szTestParamName) -{ - if (wcslen(szArg) == 0) - { - return false; - } - - if (szArg[0] != W('/') && szArg[0] != W('-')) - { - return false; - } - - return !_wcsicmp(szArg + 1, szTestParamName) || !_wcsicmp(szArg + 1, szTestParamName); -} - -// -// Returns true if pwzString ends with the string in pwzCandidate -// Ignores case -// -bool StringEndsWith(LPCWSTR pwzString, LPCWSTR pwzCandidate) -{ - size_t stringLength = wcslen(pwzString); - size_t candidateLength = wcslen(pwzCandidate); - - if (candidateLength > stringLength || stringLength == 0 || candidateLength == 0) - { - return false; - } - - LPCWSTR pwzStringEnd = pwzString + stringLength - candidateLength; - - return !_wcsicmp(pwzStringEnd, pwzCandidate); -} - -// -// When using the Phone binding model (TrustedPlatformAssemblies), automatically -// detect which path CoreLib.[ni.]dll lies in. -// -bool ComputeCoreLibPathFromTrustedPlatformAssemblies(SString& pwzCoreLibPath, LPCWSTR pwzTrustedPlatformAssemblies) -{ - LPWSTR wszTrustedPathCopy = new WCHAR[wcslen(pwzTrustedPlatformAssemblies) + 1]; - wcscpy_s(wszTrustedPathCopy, wcslen(pwzTrustedPlatformAssemblies) + 1, pwzTrustedPlatformAssemblies); - WCHAR *context; - LPWSTR wszSingleTrustedPath = wcstok_s(wszTrustedPathCopy, PATH_SEPARATOR_STR_W, &context); - - while (wszSingleTrustedPath != NULL) - { - size_t pathLength = wcslen(wszSingleTrustedPath); - // Strip off enclosing quotes, if present - if (wszSingleTrustedPath[0] == W('\"') && wszSingleTrustedPath[pathLength-1] == W('\"')) - { - wszSingleTrustedPath[pathLength-1] = '\0'; - wszSingleTrustedPath++; - } - - if (StringEndsWith(wszSingleTrustedPath, DIRECTORY_SEPARATOR_STR_W CoreLibName_IL_W) || - StringEndsWith(wszSingleTrustedPath, DIRECTORY_SEPARATOR_STR_W CoreLibName_NI_W)) - { - pwzCoreLibPath.Set(wszSingleTrustedPath); - SString::Iterator pwzSeparator = pwzCoreLibPath.End(); - bool retval = true; - - if (!SUCCEEDED(CopySystemDirectory(pwzCoreLibPath, pwzCoreLibPath))) - { - retval = false; - } - - delete [] wszTrustedPathCopy; - return retval; - } - - wszSingleTrustedPath = wcstok_s(NULL, PATH_SEPARATOR_STR_W, &context); - } - delete [] wszTrustedPathCopy; - - return false; -} - -// Given a path terminated with "\\" and a search mask, this function will add -// the enumerated files, corresponding to the search mask, from the path into -// the refTPAList. -void PopulateTPAList(SString path, LPCWSTR pwszMask, SString &refTPAList, bool fCreatePDB) -{ - _ASSERTE(path.GetCount() > 0); - ClrDirectoryEnumerator folderEnumerator(path.GetUnicode(), pwszMask); - - while (folderEnumerator.Next()) - { - // Got a valid enumeration handle and the data about the first file. - DWORD dwAttributes = folderEnumerator.GetFileAttributes(); - if ((!(dwAttributes & FILE_ATTRIBUTE_DIRECTORY)) && (!(dwAttributes & FILE_ATTRIBUTE_DEVICE))) - { - bool fAddDelimiter = (refTPAList.GetCount() > 0)?true:false; - bool fAddFileToTPAList = true; - LPCWSTR pwszFilename = folderEnumerator.GetFileName(); - - // No NIs are supported when creating NI images (other than NI of System.Private.CoreLib.dll). - if (!fCreatePDB) - { - // Only CoreLib's ni.dll should be in the TPAList for the compilation of non-CoreLib assemblies. - if (StringEndsWith((LPWSTR)pwszFilename, W(".ni.dll"))) - { - fAddFileToTPAList = false; - } - } - - if (fAddFileToTPAList) - { - if (fAddDelimiter) - { - // Add the path delimiter if we already have entries in the TPAList - refTPAList.Append(PATH_SEPARATOR_CHAR_W); - } - // Add the path to the TPAList - refTPAList.Append(path); - refTPAList.Append(pwszFilename); - } - } - } - } - -// Given a semi-colon delimited set of absolute folder paths (pwzPlatformAssembliesPaths), this function -// will enumerate all EXE/DLL modules in those folders and add them to the TPAList buffer (refTPAList). -void ComputeTPAListFromPlatformAssembliesPath(LPCWSTR pwzPlatformAssembliesPaths, SString &refTPAList, bool fCreatePDB) -{ - // We should have a valid pointer to the paths - _ASSERTE(pwzPlatformAssembliesPaths != NULL); - - SString ssPlatformAssembliesPath(pwzPlatformAssembliesPaths); - - // Platform Assemblies Path List is semi-colon delimited - if(ssPlatformAssembliesPath.GetCount() > 0) - { - SString::CIterator start = ssPlatformAssembliesPath.Begin(); - SString::CIterator itr = ssPlatformAssembliesPath.Begin(); - SString::CIterator end = ssPlatformAssembliesPath.End(); - SString qualifiedPath; - - while (itr != end) - { - start = itr; - BOOL found = ssPlatformAssembliesPath.Find(itr, PATH_SEPARATOR_CHAR_W); - if (!found) - { - itr = end; - } - - SString qualifiedPath(ssPlatformAssembliesPath,start,itr); - - if (found) - { - itr++; - } - - unsigned len = qualifiedPath.GetCount(); - - if (len > 0) - { - if (qualifiedPath[len-1]!=DIRECTORY_SEPARATOR_CHAR_W) - { - qualifiedPath.Append(DIRECTORY_SEPARATOR_CHAR_W); - } - - // Enumerate the EXE/DLL modules within this path and add them to the TPAList - EX_TRY - { - PopulateTPAList(qualifiedPath, W("*.exe"), refTPAList, fCreatePDB); - PopulateTPAList(qualifiedPath, W("*.dll"), refTPAList, fCreatePDB); - } - EX_CATCH - { - Outputf(W("Warning: Error enumerating files under %s.\n"), qualifiedPath.GetUnicode()); - } - EX_END_CATCH(SwallowAllExceptions); - } - } - } -} - -int _cdecl wmain(int argc, __in_ecount(argc) WCHAR **argv) -{ - ///////////////////////////////////////////////////////////////////////// - // - // Parse the arguments - // - bool fDisplayLogo = true; - DWORD dwFlags = 0; - LPCWSTR pwzFilename = NULL; - LPCWSTR pwzPlatformResourceRoots = nullptr; - LPCWSTR pwzTrustedPlatformAssemblies = nullptr; - LPCWSTR pwzAppPaths = nullptr; - LPCWSTR pwzAppNiPaths = nullptr; - LPCWSTR pwzPlatformAssembliesPaths = nullptr; - StackSString wzDirectoryToStorePDB; - bool fCreatePDB = false; - bool fGeneratePDBLinesInfo = false; - LPWSTR pwzSearchPathForManagedPDB = NULL; - LPCWSTR pwzOutputFilename = NULL; - LPCWSTR pwzPublicKeys = nullptr; - bool fLargeVersionBubbleSwitch = false; - SIZE_T baseAddress = 0; - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - LPCWSTR pwszCLRJITPath = nullptr; -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - - LPCWSTR pwzDiasymreaderPath = nullptr; - - HRESULT hr; - -#ifndef TARGET_UNIX - // This is required to properly display Unicode characters - _setmode(_fileno(stdout), _O_U8TEXT); -#endif - - // Skip this executable path - argv++; - argc--; - - ConsoleArgs consoleArgs; - int argc2; - LPWSTR *argv2; - - SString ssTrustedPlatformAssemblies; - - if (argc == 0) - { - PrintUsageHelper(); - exit(INVALID_ARGUMENTS); - } - - if (!consoleArgs.ExpandResponseFiles(argc, argv, &argc2, &argv2)) - { - if (consoleArgs.ErrorMessage() != nullptr) - { - wprintf(consoleArgs.ErrorMessage()); - exit(FAILURE_RESULT); - } - } - - argc = argc2; - argv = argv2; - - // By default, Crossgen will generate readytorun images unless /FragileNonVersionable switch is specified - dwFlags |= NGENWORKER_FLAGS_READYTORUN; - - while (argc > 0) - { - if (MatchParameter(*argv, W("?")) - || MatchParameter(*argv, W("help"))) - { - PrintUsageHelper(); - exit(INVALID_ARGUMENTS); - } - else if (MatchParameter(*argv, W("nologo"))) - { - fDisplayLogo = false; - } - else if (MatchParameter(*argv, W("silent"))) - { - dwFlags |= NGENWORKER_FLAGS_SILENT; - } - else if (MatchParameter(*argv, W("verbose"))) - { - dwFlags |= NGENWORKER_FLAGS_VERBOSE; - } - else if (MatchParameter(*argv, W("nowarnings"))) - { - dwFlags |= NGENWORKER_FLAGS_SUPPRESS_WARNINGS; - } - else if (MatchParameter(*argv, W("Tuning"))) - { - dwFlags |= NGENWORKER_FLAGS_TUNING; - } - else if (MatchParameter(*argv, W("MissingDependenciesOK"))) - { - dwFlags |= NGENWORKER_FLAGS_MISSINGDEPENDENCIESOK; - } -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - else if (MatchParameter(*argv, W("JITPath")) && (argc > 1)) - { - pwszCLRJITPath = argv[1]; - - // skip JIT Path - argv++; - argc--; - } -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) -#ifdef FEATURE_READYTORUN_COMPILER - else if (MatchParameter(*argv, W("ReadyToRun"))) - { - dwFlags |= NGENWORKER_FLAGS_READYTORUN; - } - else if (MatchParameter(*argv, W("FragileNonVersionable"))) - { - dwFlags &= ~NGENWORKER_FLAGS_READYTORUN; - } - else if (MatchParameter(*argv, W("LargeVersionBubble"))) - { - dwFlags |= NGENWORKER_FLAGS_LARGEVERSIONBUBBLE; - 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("out"))) - { - if (pwzOutputFilename != NULL) - { - OutputErr(W("Cannot specify multiple output files.\n")); - exit(INVALID_ARGUMENTS); - } - pwzOutputFilename = argv[1]; - argv++; - argc--; - } - else if (MatchParameter(*argv, W("in"))) - { - if (pwzFilename != NULL) - { - OutputErr(W("Cannot specify multiple input files.\n")); - exit(INVALID_ARGUMENTS); - } - pwzFilename = argv[1]; - argv++; - argc--; - } - else if (MatchParameter(*argv, W("r")) && (argc > 1)) - { - if (!ssTrustedPlatformAssemblies.IsEmpty()) - { - // Add the path delimiter if we already have entries in the TPAList - ssTrustedPlatformAssemblies.Append(PATH_SEPARATOR_CHAR_W); - } - ssTrustedPlatformAssemblies.Append(argv[1]); - - // skip path list - argv++; - argc--; - } - else if (MatchParameter(*argv, W("Platform_Resource_Roots")) && (argc > 1)) - { - pwzPlatformResourceRoots = argv[1]; - - // skip path list - argv++; - argc--; - } - else if (MatchParameter(*argv, W("App_Paths")) && (argc > 1)) - { - pwzAppPaths = argv[1]; - - // skip User app path - argv++; - argc--; - } -#ifndef NO_NGENPDB - else if (MatchParameter(*argv, W("App_Ni_Paths")) && (argc > 1)) - { - pwzAppNiPaths = argv[1]; - - // skip User app path - argv++; - argc--; - } -#endif // NO_NGENPDB - // Note: Leaving "Platform_Assemblies_Paths" for backwards compatibility reasons. - else if ((MatchParameter(*argv, W("Platform_Assemblies_Paths")) || MatchParameter(*argv, W("p"))) && (argc > 1)) - { - pwzPlatformAssembliesPaths = argv[1]; - - // skip path list - argv++; - argc--; - } -#ifndef NO_NGENPDB - else if (MatchParameter(*argv, W("CreatePDB")) && (argc > 1)) - { - // syntax: /CreatePDB [/lines [] ] - - // Parse: /CreatePDB - fCreatePDB = true; - argv++; - argc--; - - // Clear any extra flags - using /CreatePDB fails if any of these are set. - dwFlags = dwFlags & ~NGENWORKER_FLAGS_READYTORUN; - - // Parse: - wzDirectoryToStorePDB.Set(argv[0]); - argv++; - argc--; - - // Ensure output dir ends in a backslash, or else diasymreader has issues - if (wzDirectoryToStorePDB[wzDirectoryToStorePDB.GetCount()-1] != DIRECTORY_SEPARATOR_CHAR_W) - { - wzDirectoryToStorePDB.Append(DIRECTORY_SEPARATOR_STR_W); - } - - if (argc == 0) - { - OutputErr(W("The /CreatePDB switch requires and .\n")); - exit(FAILURE_RESULT); - } - - // [/lines [] ] - if (MatchParameter(*argv, W("lines")) && (argc > 1)) - { - // Parse: /lines - fGeneratePDBLinesInfo = true; - argv++; - argc--; - - if (argc == 0) - { - OutputErr(W("The /CreatePDB switch requires and .\n")); - exit(FAILURE_RESULT); - } - - if (argc > 1) - { - // Parse: - pwzSearchPathForManagedPDB = argv[0]; - argv++; - argc--; - } - } - - // Undo last arg iteration, since we do it for all cases at the bottom of - // the loop - argv--; - argc++; - } - else if (MatchParameter(*argv, W("DiasymreaderPath")) && (argc > 1)) - { - pwzDiasymreaderPath = argv[1]; - - // skip diasymreader Path - argv++; - argc--; - } -#endif // NO_NGENPDB -#ifdef FEATURE_PERFMAP - else if (MatchParameter(*argv, W("CreatePerfMap")) && (argc > 1)) - { - // syntax: /CreatePerfMap - - // Parse: /CreatePerfMap - // NOTE: We use the same underlying PDB logic. - fCreatePDB = true; - argv++; - argc--; - - // Clear the /ready to run flag - /CreatePerfmap does not work with any other flags. - dwFlags = dwFlags & ~NGENWORKER_FLAGS_READYTORUN; - - // Parse: - wzDirectoryToStorePDB.Set(argv[0]); - argv++; - argc--; - - // Ensure output dir ends in a backslash - if (wzDirectoryToStorePDB[wcslen(wzDirectoryToStorePDB)-1] != DIRECTORY_SEPARATOR_CHAR_W) - { - wzDirectoryToStorePDB.Append(DIRECTORY_SEPARATOR_STR_W); - } - - if (argc == 0) - { - OutputErr(W("The /CreatePerfMap switch requires and .\n")); - exit(FAILURE_RESULT); - } - - // Undo last arg iteration, since we do it for all cases at the bottom of - // the loop - argv--; - argc++; - } -#endif // FEATURE_PERFMAP - else - { - if (argc == 1) - { -#if !defined(TARGET_UNIX) - // When not running on Mac or Linux, which can have forward-slash pathnames, we know - // a command switch here means an invalid argument. - if (*argv[0] == W('-') || *argv[0] == W('/')) - { - OutputErrf(W("Invalid parameter: %s\n"), *argv); - exit(INVALID_ARGUMENTS); - } -#endif //!TARGET_UNIX - // The last thing on the command line is an assembly name or path, and - // because we got this far is not an argument like /nologo. Because this - // code works on Mac, with forward-slash pathnames, we can't assume - // anything with a forward slash is an argument. So we just always - // assume the last thing on the command line must be an assembly name. - - if (pwzFilename != NULL) - { - OutputErr(W("Cannot use /In and specify an input file as the last argument.\n")); - exit(INVALID_ARGUMENTS); - } - - pwzFilename = *argv; - break; - } - else - { - OutputErrf(W("Invalid parameter: %s\n"), *argv); - exit(INVALID_ARGUMENTS); - } - } - - argv++; - argc--; - } - - if (pwzFilename == NULL) - { - OutputErr(W("You must specify an assembly to compile\n")); - exit(INVALID_ARGUMENTS); - } - - if (fCreatePDB && (dwFlags != 0)) - { - OutputErr(W("The /CreatePDB switch cannot be used with other switches, except /lines and the various path switches.\n")); - exit(FAILURE_RESULT); - } - - if (pwzAppNiPaths != nullptr && !fCreatePDB) - { - OutputErr(W("The /App_Ni_Paths switch can only be used with the /CreatePDB switch.\n")); - exit(FAILURE_RESULT); - } - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - if (pwszCLRJITPath != nullptr && fCreatePDB) - { - OutputErr(W("The /JITPath switch can not be used with the /CreatePDB switch.\n")); - exit(FAILURE_RESULT); - } -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - -#if !defined(NO_NGENPDB) - if (pwzDiasymreaderPath != nullptr && !fCreatePDB) - { - OutputErr(W("The /DiasymreaderPath switch can only be used with the /CreatePDB switch.\n")); - exit(FAILURE_RESULT); - } -#endif // !defined(NO_NGENPDB) - - if (!ssTrustedPlatformAssemblies.IsEmpty()) - { - pwzTrustedPlatformAssemblies = (WCHAR *)ssTrustedPlatformAssemblies.GetUnicode(); - } - - if ((pwzTrustedPlatformAssemblies != nullptr) && (pwzPlatformAssembliesPaths != nullptr)) - { - OutputErr(W("The /r and /p switches cannot be both specified.\n")); - exit(FAILURE_RESULT); - } - - // All argument processing has happened by now. The only messages that should appear before here are errors - // related to argument parsing, such as the Usage message. Afterwards, other messages can appear. - - ///////////////////////////////////////////////////////////////////////// - // - // Start processing - // - - if (fDisplayLogo) - { - PrintLogoHelper(); - } - - PathString wzTrustedPathRoot; - - SString ssTPAList; - - if (fCreatePDB) - { - // While creating PDB, assembly binder gives preference to files in TPA. - // This can create difficulties if the input file is not in TPA. - // To avoid this issue, put the input file as the first item in TPA. - ssTPAList.Append(pwzFilename); - } - - if(pwzPlatformAssembliesPaths != nullptr) - { - // /p command line switch has been specified. - _ASSERTE(pwzTrustedPlatformAssemblies == nullptr); - - // Formulate the TPAList from /p - ComputeTPAListFromPlatformAssembliesPath(pwzPlatformAssembliesPaths, ssTPAList, fCreatePDB); - pwzTrustedPlatformAssemblies = (WCHAR *)ssTPAList.GetUnicode(); - pwzPlatformAssembliesPaths = NULL; - } - - if (pwzTrustedPlatformAssemblies != nullptr) - { - if (ComputeCoreLibPathFromTrustedPlatformAssemblies(wzTrustedPathRoot, pwzTrustedPlatformAssemblies)) - { - pwzPlatformAssembliesPaths = wzTrustedPathRoot.GetUnicode(); - SetCoreLibPath(pwzPlatformAssembliesPaths); - } - } - - if (pwzPlatformAssembliesPaths == NULL) - { - if (!WszGetModuleFileName(NULL, wzTrustedPathRoot)) - { - ERROR_WIN32(W("Error: GetModuleFileName failed (%d)\n"), GetLastError()); - exit(CLR_INIT_ERROR); - } - - if (SUCCEEDED(CopySystemDirectory(wzTrustedPathRoot, wzTrustedPathRoot))) - { - pwzPlatformAssembliesPaths = wzTrustedPathRoot.GetUnicode(); - } - else - { - ERROR_HR(W("Error: wcsrchr returned NULL; GetModuleFileName must have given us something bad\n"), E_UNEXPECTED); - exit(CLR_INIT_ERROR); - } - - - } - - // Verbose mode will always print warnings - if ((dwFlags & NGENWORKER_FLAGS_VERBOSE) != 0) - dwFlags &= ~NGENWORKER_FLAGS_SUPPRESS_WARNINGS; - - g_CrossgenLogger.SetWarningLogging((dwFlags & NGENWORKER_FLAGS_SUPPRESS_WARNINGS) == 0); - - // Initialize the logger - SetSvcLogger(&g_CrossgenLogger); - - //Step - Compile the assembly - - if (fCreatePDB) - { - hr = CreatePDBWorker( - pwzFilename, - pwzPlatformAssembliesPaths, - pwzTrustedPlatformAssemblies, - pwzPlatformResourceRoots, - pwzAppPaths, - pwzAppNiPaths, - wzDirectoryToStorePDB, - fGeneratePDBLinesInfo, - pwzSearchPathForManagedPDB, - pwzDiasymreaderPath); - - } - else - { - hr = NGenWorker(pwzFilename, dwFlags, - pwzPlatformAssembliesPaths, - pwzTrustedPlatformAssemblies, - pwzPlatformResourceRoots, - pwzAppPaths, - pwzOutputFilename, - baseAddress -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - , - NULL, // ICorSvcLogger - pwszCLRJITPath -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - ); - } - - - if (FAILED(hr)) - { - if (hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND)) - { - OutputErrf(W("Error: file \"%s\" or one of its dependencies was not found\n"), pwzFilename); - exit(ASSEMBLY_NOT_FOUND); - } - else - { - OutputErrf(W("Error: compilation failed for \"%s\" (0x%08x)\n"), pwzFilename, hr); - exit(hr); - } - } - - return 0; -} - -#ifdef TARGET_UNIX -int main(int argc, char *argv[]) -{ - if (0 != PAL_Initialize(argc, argv)) - { - return FAILURE_RESULT; - } - - WCHAR **wargv = new WCHAR*[argc]; - for (int i = 0; i < argc; i++) - { - size_t len = strlen(argv[i]) + 1; - wargv[i] = new WCHAR[len]; - WszMultiByteToWideChar(CP_ACP, 0, argv[i], -1, wargv[i], len); - } - - int ret = wmain(argc, wargv); - - for (int i = 0; i < argc; i++) - { - delete[] wargv[i]; - } - delete[] wargv; - - return ret; -} -#endif // TARGET_UNIX diff --git a/src/coreclr/zap/CMakeLists.txt b/src/coreclr/zap/CMakeLists.txt deleted file mode 100644 index 12bcebbcbf3897..00000000000000 --- a/src/coreclr/zap/CMakeLists.txt +++ /dev/null @@ -1,56 +0,0 @@ -set(ZAP_SOURCES - svcworker.cpp - zapper.cpp - zaprelocs.cpp - zapcode.cpp - zapheaders.cpp - zapimage.cpp - zapinfo.cpp - zapimport.cpp - zapinnerptr.cpp - zapmetadata.cpp - zapwriter.cpp - zapwrapper.cpp - zapperstats.cpp - nativeformatwriter.cpp -) - -set(ZAP_HEADERS - zaprelocs.h - zapcode.h - zapheaders.h - zapimage.h - zapinfo.h - zapimport.h - zapinnerptr.h - zaplog.h - zapmetadata.h - zapnodetype.h - zapwriter.h - zapwrapper.h - zapperstats.h - nativeformatwriter.h -) - -if (FEATURE_READYTORUN) - list(APPEND ZAP_SOURCES - zapreadytorun.cpp - nativeformatwriter.cpp - ) - list(APPEND ZAP_HEADERS - zapreadytorun.h - nativeformatwriter.h - ) -endif (FEATURE_READYTORUN) - -if (CLR_CMAKE_TARGET_WIN32) - list(APPEND ZAP_SOURCES ${ZAP_HEADERS}) -endif(CLR_CMAKE_TARGET_WIN32) - -add_library_clr(corzap_crossgen STATIC ${ZAP_SOURCES}) -set_target_properties(corzap_crossgen PROPERTIES CROSSGEN_COMPONENT TRUE) -target_precompile_headers(corzap_crossgen PRIVATE [["common.h"]]) - -if(FEATURE_MERGE_JIT_AND_ENGINE) - target_link_libraries(corzap_crossgen clrjit_crossgen) -endif(FEATURE_MERGE_JIT_AND_ENGINE) diff --git a/src/coreclr/zap/common.h b/src/coreclr/zap/common.h deleted file mode 100644 index beb744e3f9156d..00000000000000 --- a/src/coreclr/zap/common.h +++ /dev/null @@ -1,64 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -//***************************************************************************** -// common.h -// - -// -// Precompiled headers. -// -//***************************************************************************** -#ifndef __COMMON_H__ -#define __COMMON_H__ - -#include -#include -#include -#include -#include -#include -#include -#include - -#if !defined(TARGET_X86) || defined(TARGET_UNIX) -#ifndef FEATURE_EH_FUNCLETS -#define FEATURE_EH_FUNCLETS -#endif -#endif // !TARGET_X86 || TARGET_UNIX - -#ifdef TARGET_64BIT -typedef unsigned __int64 TARGET_POINTER_TYPE; -#else -typedef unsigned int TARGET_POINTER_TYPE; -#endif - -#include "utilcode.h" -#include "corjit.h" -#include "corcompile.h" -#include "iceefilegen.h" -#include "corpriv.h" -#include "gcinfotypes.h" - -#include "holder.h" -#include "ex.h" -#include "corbbtprof.h" -#include "clrnt.h" -#include "contract.h" -#include "psapi.h" -#include "log.h" -#include "ngen.h" -#include "pedecoder.h" -#include "guidfromname.h" -#include "../dlls/mscorrc/resource.h" -#include "zaplog.h" -#include "clrversion.h" - -#include "loaderheap.h" - -#include "zapper.h" -#include "zapwriter.h" -#include "zapimage.h" - -#include "zapperstats.h" - -#endif // __COMMON_H__ diff --git a/src/coreclr/zap/nativeformatwriter.cpp b/src/coreclr/zap/nativeformatwriter.cpp deleted file mode 100644 index 91de6573857130..00000000000000 --- a/src/coreclr/zap/nativeformatwriter.cpp +++ /dev/null @@ -1,575 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// --------------------------------------------------------------------------- -// NativeFormatWriter -// -// Utilities to write native data to images, that can be read by the NativeFormat.Reader class -// --------------------------------------------------------------------------- - -#include "common.h" - -#include "nativeformatwriter.h" - -#include - -namespace NativeFormat -{ - // - // Same encoding as what's used by CTL - // - void NativeWriter::WriteUnsigned(unsigned d) - { - if (d < 128) - { - WriteByte((byte)(d*2 + 0)); - } - else if (d < 128*128) - { - WriteByte((byte)(d*4 + 1)); - WriteByte((byte)(d >> 6)); - } - else if (d < 128*128*128) - { - WriteByte((byte)(d*8 + 3)); - WriteByte((byte)(d >> 5)); - WriteByte((byte)(d >> 13)); - } - else if (d < 128*128*128*128) - { - WriteByte((byte)(d*16 + 7)); - WriteByte((byte)(d >> 4)); - WriteByte((byte)(d >> 12)); - WriteByte((byte)(d >> 20)); - } - else - { - WriteByte((byte)15); - WriteUInt32(d); - } - } - - unsigned NativeWriter::GetUnsignedEncodingSize(unsigned d) - { - if (d < 128) return 1; - if (d < 128*128) return 2; - if (d < 128*128*128) return 3; - if (d < 128*128*128*128) return 4; - return 5; - } - - void NativeWriter::WriteSigned(int i) - { - unsigned d = (unsigned)i; - if (d + 64 < 128) - { - WriteByte((byte)(d*2 + 0)); - } - else if (d + 64*128 < 128*128) - { - WriteByte((byte)(d*4 + 1)); - WriteByte((byte)(d >> 6)); - } - else if (d + 64*128*128 < 128*128*128) - { - WriteByte((byte)(d*8 + 3)); - WriteByte((byte)(d >> 5)); - WriteByte((byte)(d >> 13)); - } - else if (d + 64*128*128*128 < 128*128*128*128) - { - WriteByte((byte)(d*16 + 7)); - WriteByte((byte)(d >> 4)); - WriteByte((byte)(d >> 12)); - WriteByte((byte)(d >> 20)); - } - else - { - WriteByte((byte)15); - WriteUInt32(d); - } - } - - void NativeWriter::WriteRelativeOffset(Vertex * pVal) - { - WriteSigned(GetExpectedOffset(pVal) - GetCurrentOffset()); - } - - int NativeWriter::GetExpectedOffset(Vertex * pVal) - { - assert(pVal->m_offset != Vertex::NotPlaced); - - if (pVal->m_iteration == -1) - { - // If the offsets are not determined yet, use the maximum possible encoding - return 0x7FFFFFFF; - } - - int offset = pVal->m_offset; - - // If the offset was not update in this iteration yet, adjust it by delta we have accumulated in this iteration so far. - // This adjustment allows the offsets to converge faster. - if (pVal->m_iteration < m_iteration) - offset += m_offsetAdjustment; - - return offset; - } - - vector& NativeWriter::Save() - { - assert(m_phase == Initial); - - for (auto pSection : m_Sections) for (auto pVertex : *pSection) - { - pVertex->m_offset = GetCurrentOffset(); - pVertex->m_iteration = m_iteration; - pVertex->Save(this); - } - - // Aggresive phase that only allows offsets to shrink. - m_phase = Shrinking; - for (;;) - { - m_iteration++; - m_Buffer.clear(); - - m_offsetAdjustment = 0; - - for (auto pSection : m_Sections) for (auto pVertex : *pSection) - { - int currentOffset = GetCurrentOffset(); - - // Only allow the offsets to shrink. - m_offsetAdjustment = min(m_offsetAdjustment, currentOffset - pVertex->m_offset); - - pVertex->m_offset += m_offsetAdjustment; - - if (pVertex->m_offset < currentOffset) - { - // It is possible for the encoding of relative offsets to grow during some iterations. - // Ignore this growth because of it should disappear during next iteration. - RollbackTo(pVertex->m_offset); - } - assert(pVertex->m_offset == GetCurrentOffset()); - - pVertex->m_iteration = m_iteration; - - pVertex->Save(this); - } - - // We are not able to shrink anymore. We cannot just return here. It is possible that we have rolledback - // above because of we shrinked too much. - if (m_offsetAdjustment == 0) - break; - - // Limit number of shrinking interations. This limit is meant to be hit in corner cases only. - if (m_iteration > 10) - break; - } - - // Conservative phase that only allows the offsets to grow. It is guaranteed to converge. - m_phase = Growing; - for (;;) - { - m_iteration++; - m_Buffer.clear(); - - m_offsetAdjustment = 0; - m_paddingSize = 0; - - for (auto pSection : m_Sections) for (auto pVertex : *pSection) - { - int currentOffset = GetCurrentOffset(); - - // Only allow the offsets to grow. - m_offsetAdjustment = max(m_offsetAdjustment, currentOffset - pVertex->m_offset); - - pVertex->m_offset += m_offsetAdjustment; - - if (pVertex->m_offset > currentOffset) - { - // Padding - int padding = pVertex->m_offset - currentOffset; - m_paddingSize += padding; - WritePad(padding); - } - assert(pVertex->m_offset == GetCurrentOffset()); - - pVertex->m_iteration = m_iteration; - - pVertex->Save(this); - } - - if (m_offsetAdjustment == 0) - return m_Buffer; - } - - m_phase = Done; - } - - Vertex * NativeSection::Place(Vertex * pVertex) - { - assert(pVertex->m_offset == Vertex::NotPlaced); - pVertex->m_offset = Vertex::Placed; - push_back(pVertex); - - return pVertex; - } - - Vertex * VertexArray::ExpandBlock(size_t index, int depth, bool place, bool * pIsLeaf) - { - if (depth == 1) - { - Vertex * pFirst = (index < m_Entries.size()) ? m_Entries[index] : nullptr; - Vertex * pSecond = ((index + 1) < m_Entries.size()) ? m_Entries[index + 1] : nullptr; - - if (pFirst == nullptr && pSecond == nullptr) - return nullptr; - - if (pFirst == nullptr || pSecond == nullptr) - { - VertexLeaf * pLeaf = new VertexLeaf(); - if (place) - m_pSection->Place(pLeaf); - - pLeaf->m_pVertex = (pFirst == nullptr) ? pSecond : pFirst; - pLeaf->m_leafIndex = ((pFirst == nullptr) ? (index + 1) : index) & (_blockSize - 1); - - *pIsLeaf = true; - return pLeaf; - } - - VertexTree * pTree = new VertexTree(); - if (place) - m_pSection->Place(pTree); - - pTree->m_pFirst = pFirst; - pTree->m_pSecond = pSecond; - - m_pSection->Place(pSecond); - - return pTree; - } - else - { - VertexTree * pTree = new VertexTree(); - if (place) - m_pSection->Place(pTree); - - bool fFirstIsLeaf = false, fSecondIsLeaf = false; - Vertex * pFirst = ExpandBlock(index, depth - 1, false, &fFirstIsLeaf); - Vertex * pSecond = ExpandBlock(index + (size_t{ 1 } << (depth - 1)), depth - 1, true, &fSecondIsLeaf); - - Vertex * pPop; - - if ((pFirst == nullptr && pSecond == nullptr)) - { - if (place) - { - pPop = m_pSection->Pop(); - assert(pPop == pTree); - } - - delete pTree; - return nullptr; - } - - if ((pFirst == nullptr) && fSecondIsLeaf) - { - pPop = m_pSection->Pop(); - assert(pPop == pSecond); - - if (place) - { - pPop = m_pSection->Pop(); - assert(pPop == pTree); - } - - delete pTree; - - if (place) - m_pSection->Place(pSecond); - - *pIsLeaf = true; - return pSecond; - } - - if ((pSecond == nullptr) && fFirstIsLeaf) - { - if (place) - { - pPop = m_pSection->Pop(); - assert(pPop == pTree); - } - - delete pTree; - - if (place) - m_pSection->Place(pFirst); - - *pIsLeaf = true; - return pFirst; - } - - pTree->m_pFirst = pFirst; - pTree->m_pSecond = pSecond; - - return pTree; - } - } - - void VertexArray::ExpandLayout() - { - VertexLeaf * pNullBlock = nullptr; - for (size_t i = 0; i < m_Entries.size(); i += _blockSize) - { - bool fIsLeaf; - Vertex * pBlock = ExpandBlock(i, 4, true, &fIsLeaf); - - if (pBlock == nullptr) - { - if (pNullBlock == nullptr) - { - pNullBlock = new VertexLeaf(); - pNullBlock->m_leafIndex = _blockSize; - pNullBlock->m_pVertex = nullptr; - m_pSection->Place(pNullBlock); - } - pBlock = pNullBlock; - } - - m_Blocks.push_back(pBlock); - } - - // Start with maximum size entries - m_entryIndexSize = 2; - } - - void VertexArray::VertexLeaf::Save(NativeWriter * pWriter) - { - pWriter->WriteUnsigned(m_leafIndex << 2); - - if (m_pVertex != nullptr) - m_pVertex->Save(pWriter); - } - - void VertexArray::VertexTree::Save(NativeWriter * pWriter) - { - unsigned value = (m_pFirst != nullptr) ? 1 : 0; - - if (m_pSecond != nullptr) - { - value |= 2; - - int delta = pWriter->GetExpectedOffset(m_pSecond) - pWriter->GetCurrentOffset(); - assert(delta >= 0); - value |= (delta << 2); - } - - pWriter->WriteUnsigned(value); - - if (m_pFirst != nullptr) - m_pFirst->Save(pWriter); - } - - void VertexArray::Save(NativeWriter * pWriter) - { - // Lowest two bits are entry index size, the rest is number of elements - pWriter->WriteUnsigned((m_Entries.size() << 2) | m_entryIndexSize); - - int blocksOffset = pWriter->GetCurrentOffset(); - int maxOffset = 0; - - for (auto pBlock : m_Blocks) - { - int offset = pWriter->GetExpectedOffset(pBlock) - blocksOffset; - assert(offset >= 0); - - maxOffset = max(offset, maxOffset); - - if (m_entryIndexSize == 0) - { - pWriter->WriteByte((byte)offset); - } - else - if (m_entryIndexSize == 1) - { - pWriter->WriteUInt16((UInt16)offset); - } - else - { - pWriter->WriteUInt32((UInt32)offset); - } - } - - int newEntryIndexSize = 0; - if (maxOffset > 0xFF) - { - newEntryIndexSize++; - if (maxOffset > 0xFFFF) - newEntryIndexSize++; - } - - if (pWriter->IsGrowing()) - { - if (newEntryIndexSize > m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(1); - - m_entryIndexSize = newEntryIndexSize; - } - } - else - { - if (newEntryIndexSize < m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(-1); - - m_entryIndexSize = newEntryIndexSize; - } - } - } - - // - // VertexHashtable - // - - // Returns 1 + log2(x) rounded up, 0 iff x == 0 - static unsigned HighestBit(unsigned x) - { - unsigned ret = 0; - while (x != 0) - { - x >>= 1; - ret++; - } - return ret; - } - - // Helper method to back patch entry index in the bucket table - static void PatchEntryIndex(NativeWriter * pWriter, int patchOffset, int entryIndexSize, int entryIndex) - { - if (entryIndexSize == 0) - { - pWriter->PatchByteAt(patchOffset, (byte)entryIndex); - } - else - if (entryIndexSize == 1) - { - pWriter->PatchByteAt(patchOffset, (byte)entryIndex); - pWriter->PatchByteAt(patchOffset + 1, (byte)(entryIndex >> 8)); - } - else - { - pWriter->PatchByteAt(patchOffset, (byte)entryIndex); - pWriter->PatchByteAt(patchOffset + 1, (byte)(entryIndex >> 8)); - pWriter->PatchByteAt(patchOffset + 2, (byte)(entryIndex >> 16)); - pWriter->PatchByteAt(patchOffset + 3, (byte)(entryIndex >> 24)); - } - } - - void VertexHashtable::Save(NativeWriter * pWriter) - { - // Compute the layout of the table if we have not done it yet - if (m_nBuckets == 0) - ComputeLayout(); - - int nEntries = (int)m_Entries.size(); - int startOffset = pWriter->GetCurrentOffset(); - int bucketMask = (m_nBuckets - 1); - - // Lowest two bits are entry index size, the rest is log2 number of buckets - int numberOfBucketsShift = HighestBit(m_nBuckets) - 1; - pWriter->WriteByte(static_cast((numberOfBucketsShift << 2) | m_entryIndexSize)); - - int bucketsOffset = pWriter->GetCurrentOffset(); - - pWriter->WritePad((m_nBuckets + 1) << m_entryIndexSize); - - // For faster lookup at runtime, we store the first entry index even though it is redundant (the value can be - // inferred from number of buckets) - PatchEntryIndex(pWriter, bucketsOffset, m_entryIndexSize, pWriter->GetCurrentOffset() - bucketsOffset); - - int iEntry = 0; - - for (int iBucket = 0; iBucket < m_nBuckets; iBucket++) - { - while (iEntry < nEntries) - { - Entry &e = m_Entries[iEntry]; - - if (((e.hashcode >> 8) & bucketMask) != (unsigned)iBucket) - break; - - int currentOffset = pWriter->GetCurrentOffset(); - pWriter->UpdateOffsetAdjustment(currentOffset - e.offset); - e.offset = currentOffset; - - pWriter->WriteByte((byte)e.hashcode); - pWriter->WriteRelativeOffset(e.pVertex); - - iEntry++; - } - - int patchOffset = bucketsOffset + ((iBucket + 1) << m_entryIndexSize); - - PatchEntryIndex(pWriter, patchOffset, m_entryIndexSize, pWriter->GetCurrentOffset() - bucketsOffset); - } - assert(iEntry == nEntries); - - int maxIndexEntry = (pWriter->GetCurrentOffset() - bucketsOffset); - int newEntryIndexSize = 0; - if (maxIndexEntry > 0xFF) - { - newEntryIndexSize++; - if (maxIndexEntry > 0xFFFF) - newEntryIndexSize++; - } - - if (pWriter->IsGrowing()) - { - if (newEntryIndexSize > m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(1); - - m_entryIndexSize = newEntryIndexSize; - } - } - else - { - if (newEntryIndexSize < m_entryIndexSize) - { - // Ensure that the table will be redone with new entry index size - pWriter->UpdateOffsetAdjustment(-1); - - m_entryIndexSize = newEntryIndexSize; - } - } - } - - void VertexHashtable::ComputeLayout() - { - unsigned bucketsEstimate = (unsigned)(m_Entries.size() / m_nFillFactor); - - // Round number of buckets up to the power of two - m_nBuckets = 1 << HighestBit(bucketsEstimate); - - // Lowest byte of the hashcode is used for lookup within the bucket. Keep it sorted too so that - // we can use the ordering to terminate the lookup prematurely. - unsigned mask = ((m_nBuckets - 1) << 8) | 0xFF; - - // sort it by hashcode - std::sort(m_Entries.begin(), m_Entries.end(), - [=](Entry const& a, Entry const& b) - { - return (a.hashcode & mask) < (b.hashcode & mask); - } - ); - - // Start with maximum size entries - m_entryIndexSize = 2; - } -} diff --git a/src/coreclr/zap/nativeformatwriter.h b/src/coreclr/zap/nativeformatwriter.h deleted file mode 100644 index 3d8752f0be053b..00000000000000 --- a/src/coreclr/zap/nativeformatwriter.h +++ /dev/null @@ -1,354 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -// --------------------------------------------------------------------------- -// NativeFormatWriter -// -// Utilities to write native data to images, that can be read by the NativeFormat.Reader class -// --------------------------------------------------------------------------- - -#pragma once - -#include -#include - -// To reduce differences between C# and C++ versions -#define byte uint8_t - -#define UInt16 uint16_t -#define UInt32 uint32_t -#define UInt64 uint64_t - -#include - -namespace NativeFormat -{ - using namespace std; - - class NativeSection; - class NativeWriter; - - class Vertex - { - friend class NativeWriter; - friend class NativeSection; - - int m_offset; - int m_iteration; // Iteration that the offset is valid for - - static const int NotPlaced = -1; - static const int Placed = -2; - - public: - Vertex() - : m_offset(Vertex::NotPlaced), m_iteration(-1) - { - } - - virtual ~Vertex() {} - - virtual void Save(NativeWriter * pWriter) = 0; - - int GetOffset() - { - assert(m_offset >= 0); - return m_offset; - } - }; - - class NativeSection : vector - { - friend class NativeWriter; - - public: - Vertex * Place(Vertex * pVertex); - - Vertex * Pop() - { - Vertex * pVertex = *(end() - 1); - erase(end() - 1); - - assert(pVertex->m_offset == Vertex::Placed); - pVertex->m_offset = Vertex::NotPlaced; - - return pVertex; - } - }; - - class NativeWriter - { - vector m_Sections; - - enum SavePhase - { - Initial, - Shrinking, - Growing, - Done - }; - - vector m_Buffer; - int m_iteration; - SavePhase m_phase; // Current save phase - int m_offsetAdjustment; // Cumulative offset adjustment compared to previous iteration - int m_paddingSize; // How much padding was used - - public: - NativeWriter() - { - m_iteration = 0; - m_phase = Initial; - } - - NativeSection * NewSection() - { - NativeSection * pSection = new NativeSection(); - m_Sections.push_back(pSection); - return pSection; - } - - void WriteByte(byte b) - { - m_Buffer.push_back(b); - } - - void WriteUInt16(UInt16 value) - { - WriteByte((byte)value); - WriteByte((byte)(value>>8)); - } - - void WriteUInt32(UInt32 value) - { - WriteByte((byte)value); - WriteByte((byte)(value>>8)); - WriteByte((byte)(value>>16)); - WriteByte((byte)(value>>24)); - } - - void WritePad(unsigned size) - { - while (size > 0) - { - WriteByte(0); - size--; - } - } - - bool IsGrowing() - { - return m_phase == Growing; - } - - void UpdateOffsetAdjustment(int offsetDelta) - { - switch (m_phase) - { - case Shrinking: - m_offsetAdjustment = min(m_offsetAdjustment, offsetDelta); - break; - case Growing: - m_offsetAdjustment = max(m_offsetAdjustment, offsetDelta); - break; - default: - break; - } - } - - void RollbackTo(int offset) - { - m_Buffer.erase(m_Buffer.begin() + offset, m_Buffer.end()); - } - - void RollbackTo(int offset, int offsetAdjustment) - { - m_offsetAdjustment = offsetAdjustment; - RollbackTo(offset); - } - - void PatchByteAt(int offset, byte value) - { - m_Buffer[offset] = value; - } - - // - // Same encoding as what's used by CTL - // - void WriteUnsigned(unsigned d); - static unsigned GetUnsignedEncodingSize(unsigned d); - - template - void WriteUnsigned(T d) - { - WriteUnsigned((unsigned)d); - } - - void WriteSigned(int i); - - void WriteRelativeOffset(Vertex * pVal); - - int GetExpectedOffset(Vertex * pVal); - - int GetCurrentOffset(Vertex * pVal) - { - if (pVal->m_iteration != m_iteration) - return -1; - return pVal->m_offset; - } - - void SetCurrentOffset(Vertex * pVal) - { - pVal->m_iteration = m_iteration; - pVal->m_offset = GetCurrentOffset(); - } - - int GetCurrentOffset() - { - return (int)m_Buffer.size(); - } - - int GetNumberOfIterations() - { - return m_iteration; - } - - int GetPaddingSize() - { - return m_paddingSize; - } - - vector& Save(); - }; - - - // - // Data structure building blocks - // - - class UnsignedConstant : public Vertex - { - unsigned m_value; - - public: - UnsignedConstant(unsigned value) - : m_value(value) - { - } - - virtual void Save(NativeWriter * pWriter) - { - pWriter->WriteUnsigned(m_value); - } - }; - - // - // Sparse array. Good for random access based on index - // - class VertexArray : public Vertex - { - vector m_Entries; - - NativeSection * m_pSection; - vector m_Blocks; - - static const int _blockSize = 16; - - // Current size of index entry - int m_entryIndexSize; // 0 - uint8, 1 - uint16, 2 - uint32 - - class VertexLeaf : public Vertex - { - public: - Vertex * m_pVertex; - size_t m_leafIndex; - - virtual void Save(NativeWriter * pWriter); - }; - - class VertexTree : public Vertex - { - public: - Vertex * m_pFirst; - Vertex * m_pSecond; - - virtual void Save(NativeWriter * pWriter); - }; - - Vertex * ExpandBlock(size_t index, int depth, bool place, bool * pLeaf); - - public: - VertexArray(NativeSection * pSection) - : m_pSection(pSection) - { - } - - void Set(int index, Vertex * pElement) - { - while ((size_t)index >= m_Entries.size()) - m_Entries.push_back(nullptr); - - m_Entries[index] = pElement; - } - - void ExpandLayout(); - - virtual void Save(NativeWriter * pWriter); - }; - - // - // Hashtable. Good for random access based on hashcode + key - // - class VertexHashtable : public Vertex - { - struct Entry - { - Entry() - : offset(-1), hashcode(0), pVertex(NULL) - { - } - - Entry(unsigned hashcode, Vertex * pVertex) - : offset(0), hashcode(hashcode), pVertex(pVertex) - { - } - - int offset; - - unsigned hashcode; - Vertex * pVertex; - }; - - vector m_Entries; - - // How many entries to target per bucket. Higher fill factor means smaller size, but worse runtime perf. - int m_nFillFactor; - - // Number of buckets choosen for the table. Must be power of two. 0 means that the table is still open for mutation. - int m_nBuckets; - - // Current size of index entry - int m_entryIndexSize; // 0 - uint8, 1 - uint16, 2 - uint32 - - void ComputeLayout(); - - public: - static const int DefaultFillFactor = 13; - - VertexHashtable(int fillFactor = DefaultFillFactor) - { - m_nBuckets = 0; - - m_nFillFactor = fillFactor; - } - - void Append(unsigned hashcode, Vertex * pElement) - { - // The table needs to be open for mutation - assert(m_nBuckets == 0); - - m_Entries.push_back(Entry(hashcode, pElement)); - } - - virtual void Save(NativeWriter * pWriter); - }; -}; diff --git a/src/coreclr/zap/svcworker.cpp b/src/coreclr/zap/svcworker.cpp deleted file mode 100644 index 78f7b4f9eefda6..00000000000000 --- a/src/coreclr/zap/svcworker.cpp +++ /dev/null @@ -1,227 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -/********************************************************************** -svcworker.cpp -- logic for the runtime implementation of the native -image service. - -Overview: the runtime implementation is accessed via a local COM -server implemented in ngen.exe. That server is simply a stub that -loads the most recent runtime and calls into the actual implementation -in this file. There are three entrypoints in mscorwks.dll that -are called by the local service in ngen.exe: - -NGenWorkerRegisterServer -- called to register ngen.exe as the current - COM server for CLSID_CorSvcWorker -NGenWorkerUnregisterServer -- unregister ngen.exe as the current COM - server for CLSID_CorSvcWorker -NGenWorkerEmbedding() -- called when COM invoked the COM server with - the "-Embedding" flag. Implements the logic for registering the class - factory for CLSID_CorSvcWorker and controlling the lifetime of the - COM server. -**********************************************************************/ - -#include "common.h" - -ILocalServerLifetime *g_pLocalServerLifetime = NULL; - -SvcLogger::SvcLogger() - : pss(NULL), - pCorSvcLogger(NULL) -{ -} - -inline void SvcLogger::CheckInit() -{ - if(pss == NULL) - { - StackSString* psstemp = new StackSString(); - StackSString* pssOrig = InterlockedCompareExchangeT(&pss, psstemp, NULL); - if(pssOrig) - delete psstemp; - } -} - -SvcLogger::~SvcLogger() -{ - if (pCorSvcLogger) - { -// pCorSvcLogger->Release(); - pCorSvcLogger = NULL; - } - if (pss) - delete pss; -} - -void SvcLogger::ReleaseLogger() -{ - if (pCorSvcLogger) - { - pCorSvcLogger->Release(); - pCorSvcLogger = NULL; - } -} - -void SvcLogger::Printf(const CHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - if (pCorSvcLogger) - { - LogHelper(s); - } - else - { - wprintf( W("%s"), s.GetUnicode() ); - } -} - -void SvcLogger::SvcPrintf(const CHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - LogHelper(s); -} - -void SvcLogger::Printf(const WCHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - if (pCorSvcLogger) - { - LogHelper(s); - } - else - { - wprintf( W("%s"), s.GetUnicode() ); - } -} - -void SvcLogger::Printf(CorSvcLogLevel logLevel, const WCHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - if (pCorSvcLogger) - { - LogHelper(s, logLevel); - } - else - { - wprintf( W("%s"), s.GetUnicode()); - } -} - -void SvcLogger::SvcPrintf(const WCHAR *format, ...) -{ - StackSString s; - - va_list args; - va_start(args, format); - s.VPrintf(format, args); - va_end(args); - - LogHelper(s); -} - -void SvcLogger::Log(const WCHAR *message, CorSvcLogLevel logLevel) -{ - LogHelper(StackSString(message), logLevel); -} - -void SvcLogger::LogHelper(SString s, CorSvcLogLevel logLevel) -{ - CheckInit(); - pss->Append(s); - - // Does s contain a newline? - SString::Iterator i = pss->Begin(); - if (pss->FindASCII(i, "\n")) - { - if (pCorSvcLogger) - { - BSTRHolder bstrHolder(::SysAllocString(pss->GetUnicode())); - // Can't use the IfFailThrow macro here because in checked - // builds that macros will try to log an error message - // that will recursively return to this method. - HRESULT hr = pCorSvcLogger->Log(logLevel, bstrHolder); - if (FAILED(hr)) - ThrowHR(hr); - } - pss->Clear(); - } -} - -void SvcLogger::SetSvcLogger(ICorSvcLogger *pCorSvcLoggerArg) -{ - ReleaseLogger(); - this->pCorSvcLogger = pCorSvcLoggerArg; - if (pCorSvcLoggerArg) - { - pCorSvcLogger->AddRef(); - } -} - -BOOL SvcLogger::HasSvcLogger() -{ - return (this->pCorSvcLogger != NULL); -} - -ICorSvcLogger* SvcLogger::GetSvcLogger() -{ - return pCorSvcLogger; -} - - -namespace -{ - SvcLogger *g_SvcLogger = NULL; -} - -// As NGen is currently single-threaded, this function is intentionally not thread safe. -// If necessary, change it into an interlocked function. -SvcLogger *GetSvcLogger() -{ - if (g_SvcLogger == NULL) - { - g_SvcLogger = new SvcLogger(); - } - return g_SvcLogger; -} - -BOOL HasSvcLogger() -{ - if (g_SvcLogger != NULL) - { - return g_SvcLogger->HasSvcLogger(); - } - return FALSE; -} - -#ifdef CROSSGEN_COMPILE -void SetSvcLogger(ICorSvcLogger *pCorSvcLogger) -{ - GetSvcLogger()->SetSvcLogger(pCorSvcLogger); -} -#endif - diff --git a/src/coreclr/zap/zapcode.cpp b/src/coreclr/zap/zapcode.cpp deleted file mode 100644 index 039ed6763555f5..00000000000000 --- a/src/coreclr/zap/zapcode.cpp +++ /dev/null @@ -1,1786 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapCode.cpp -// - -// -// Everything directly related to zapping of native code -// - The code itself -// - Code headers -// - All XXX infos: GC Info, EH Info, Unwind Info, ... -// -// ====================================================================================== - -#include "common.h" - -#include "zapcode.h" - -#include "zapimport.h" - -#include "zapinnerptr.h" - -#ifdef FEATURE_READYTORUN_COMPILER -#include "zapreadytorun.h" -#endif - -#ifdef REDHAWK -#include "rhcodeinfo.h" -#include "rhbinder.h" -#include "modulegcinfoencoder.h" -#endif // REDHAWK - -// -// The image layout algorithm -// - -ZapVirtualSection * ZapImage::GetCodeSection(CodeType codeType) -{ - switch (codeType) - { - case ProfiledHot: - return m_pHotCodeSection; - case ProfiledCold: - return m_pColdCodeSection; - case Unprofiled: - return m_pCodeSection; - } - - UNREACHABLE(); -} - -#if defined(FEATURE_EH_FUNCLETS) -ZapVirtualSection * ZapImage::GetUnwindDataSection(CodeType codeType) -{ -#ifdef REDHAWK - return m_pUnwindDataSection; -#else - switch (codeType) - { - case ProfiledHot: - return m_pHotUnwindDataSection; - case ProfiledCold: - return m_pColdUnwindDataSection; - case Unprofiled: - return m_pUnwindDataSection; - } - -#endif // REDHAWK - UNREACHABLE(); -} -#endif // defined(FEATURE_EH_FUNCLETS) - -ZapVirtualSection * ZapImage::GetRuntimeFunctionSection(CodeType codeType) -{ - switch (codeType) - { - case ProfiledHot: - return m_pHotRuntimeFunctionSection; - case ProfiledCold: - return m_pColdRuntimeFunctionSection; - case Unprofiled: - return m_pRuntimeFunctionSection; - } - - UNREACHABLE(); -} - -ZapVirtualSection * ZapImage::GetCodeMethodDescSection(CodeType codeType) -{ - switch (codeType) - { - case ProfiledHot: - return m_pHotCodeMethodDescsSection; - case Unprofiled: - return m_pCodeMethodDescsSection; - default: - UNREACHABLE(); - } -} - -ZapVirtualSection* ZapImage::GetUnwindInfoLookupSection(CodeType codeType) -{ - switch(codeType) - { - case ProfiledHot: - return m_pHotRuntimeFunctionLookupSection; - case Unprofiled: - return m_pRuntimeFunctionLookupSection; - default: - UNREACHABLE(); - } -} - -void ZapImage::GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end) -{ - _ASSERTE(start && end); - -#ifdef REDHAWK - *start = 0; - *end = m_MethodCompilationOrder.GetCount(); -#else - switch (codeType) - { - case ProfiledHot: - *start = 0; - *end = m_iUntrainedMethod; - break; - case ProfiledCold: - *start = 0; - *end = m_MethodCompilationOrder.GetCount(); - break; - case Unprofiled: - *start = m_iUntrainedMethod; - *end = m_MethodCompilationOrder.GetCount(); - break; - } -#endif // REDHAWK -} - -void ZapImage::OutputCode(CodeType codeType) -{ - // Note there are three codeTypes: ProfiledHot, Unprofiled and ProfiledCold -#if defined(REDHAWK) - SectionMethodListGenerator map; -#endif - - bool fCold = (codeType == ProfiledCold); - CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD; - BeginRegion(regionKind); - - ZapVirtualSection * pCodeSection = GetCodeSection(codeType); - ZapVirtualSection * pRuntimeFunctionSection = GetRuntimeFunctionSection(codeType); - -#if defined (FEATURE_EH_FUNCLETS) - ZapVirtualSection * pUnwindDataSection = GetUnwindDataSection(codeType); -#endif // defined (FEATURE_EH_FUNCLETS) - - DWORD codeSize = 0; - - // We should start with empty code section - _ASSERTE(pRuntimeFunctionSection->GetNodeCount() == 0); - _ASSERTE(pCodeSection->GetNodeCount() == 0); - - COUNT_T startMethod, endMethod; -#ifdef REDHAWK // TritonTBD - DWORD currentOffset = 0; -#endif // REDHAWK - - GetCodeCompilationRange(codeType, &startMethod, &endMethod); - - DWORD dwStartMethodIndex = (codeType == Unprofiled) ? m_pHotRuntimeFunctionSection->GetNodeCount() : 0; - - for (COUNT_T curMethod = startMethod; curMethod < endMethod; curMethod++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[curMethod]; - - ZapBlobWithRelocs * pCode = fCold ? pMethod->m_pColdCode : pMethod->m_pCode; - if (pCode == NULL) - { - continue; - } - - if (!fCold) - { - pMethod->m_methodIndex = dwStartMethodIndex + pRuntimeFunctionSection->GetNodeCount(); - } - else - { - pMethod->m_methodIndex = (DWORD)-1; - } - - //Count the method size for use by ZapUnwindInfoLookupTable - codeSize = AlignUp(codeSize, pCode->GetAlignment()); - codeSize += pCode->GetSize(); - - pCodeSection->Place(pCode); - -#ifdef REDHAWK - DWORD codeOffset = AlignUp(currentOffset, pCode->GetAlignment()); - codeOffset = map.AlignToMethodStartGranularity(codeOffset); - map.NoticeMethod(codeOffset, pCode->GetSize()); - currentOffset = codeOffset + pCode->GetSize(); -#endif - - ZapReloc * pRelocs = pCode->GetRelocs(); - if (pRelocs != NULL) - { - for (ZapReloc * pReloc = pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++) - { - ZapNode * pTarget = pReloc->m_pTargetNode; - - ZapNodeType type = pTarget->GetType(); - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - switch (type) - { - case ZapNodeType_StubDispatchCell: - // Optimizations may create redundant references to the StubDispatchCell - if (!pTarget->IsPlaced()) - { - m_pStubDispatchDataTable->PlaceStubDispatchCell((ZapImport *)pTarget); - } - break; - case ZapNodeType_MethodEntryPoint: - pTarget = m_pMethodEntryPoints->CanDirectCall((ZapMethodEntryPoint *)pTarget, pMethod); - if (pTarget != NULL) - { - pReloc->m_pTargetNode = pTarget; - } - break; - case ZapNodeType_Stub: - if (!pTarget->IsPlaced()) - { - m_pStubsSection->Place(pTarget); - } - break; - case ZapNodeType_HelperThunk: - if (!pTarget->IsPlaced()) - { - // This should place the most frequently used JIT helpers first and together - m_pHelperTableSection->Place(pTarget); - } - break; - case ZapNodeType_LazyHelperThunk: - if (!pTarget->IsPlaced()) - { - ((ZapLazyHelperThunk *)pTarget)->Place(this); - } - break; - case ZapNodeType_Import_ModuleHandle: - case ZapNodeType_Import_ClassHandle: - case ZapNodeType_Import_StringHandle: - case ZapNodeType_Import_Helper: - // Place all potentially eager imports - if (!pTarget->IsPlaced()) - m_pImportTable->PlaceImport((ZapImport *)pTarget); - break; - - case ZapNodeType_ExternalMethodThunk: - if (!pTarget->IsPlaced()) - m_pExternalMethodDataTable->PlaceExternalMethodThunk((ZapImport *)pTarget); - break; - - case ZapNodeType_ExternalMethodCell: - if (!pTarget->IsPlaced()) - m_pExternalMethodDataTable->PlaceExternalMethodCell((ZapImport *)pTarget); - break; - -#ifdef FEATURE_READYTORUN_COMPILER - case ZapNodeType_DynamicHelperCell: - if (!pTarget->IsPlaced()) - m_pDynamicHelperDataTable->PlaceDynamicHelperCell((ZapImport *)pTarget); - break; - - case ZapNodeType_IndirectHelperThunk: - if (!pTarget->IsPlaced()) - m_pImportTable->PlaceIndirectHelperThunk(pTarget); - break; -#endif - - case ZapNodeType_GenericSignature: - if (!pTarget->IsPlaced()) - m_pImportTable->PlaceBlob((ZapBlob *)pTarget); - break; - default: - break; - } - } - } - -#if defined (FEATURE_EH_FUNCLETS) - // - // Place unwind data - // - - InlineSArray unwindInfos; - - ZapUnwindInfo * pFragment; - - // Go over all fragments and append their unwind infos in this section - for (pFragment = pMethod->m_pUnwindInfoFragments; - pFragment != NULL; - pFragment = pFragment->GetNextFragment()) - { - ZapNode * pFragmentCode = pFragment->GetCode(); - _ASSERTE(pFragmentCode == pMethod->m_pCode || pFragmentCode == pMethod->m_pColdCode); - - if (pFragmentCode == pCode) - { - unwindInfos.Append(pFragment); - } - } - - // The runtime function section must be ordered correctly relative to code layout - // in the image. Sort the unwind infos by their offset - _ASSERTE(unwindInfos.GetCount() > 0); - qsort(&unwindInfos[0], unwindInfos.GetCount(), sizeof(ZapUnwindInfo *), ZapUnwindInfo::CompareUnwindInfo); - - // Set the initial unwind info for the hot and cold sections - if (fCold) - { - _ASSERTE(pMethod->m_pColdUnwindInfo == NULL); - pMethod->m_pColdUnwindInfo = unwindInfos[0]; - } - else - { - _ASSERTE(pMethod->m_pUnwindInfo == NULL); - pMethod->m_pUnwindInfo = unwindInfos[0]; - } - - for (COUNT_T iUnwindInfo = 0; iUnwindInfo < unwindInfos.GetCount(); iUnwindInfo++) - { - ZapUnwindInfo * pUnwindInfo = unwindInfos[iUnwindInfo]; - pRuntimeFunctionSection->Place(pUnwindInfo); - - ZapNode * pUnwindData = pUnwindInfo->GetUnwindData(); - - if (!pUnwindData->IsPlaced()) - { - pUnwindDataSection->Place(pUnwindData); - } - } - -#else // defined (FEATURE_EH_FUNCLETS) - - ZapUnwindInfo * pUnwindInfo; - if (fCold) - { - // Chained unwind info - pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pUnwindInfo); - pMethod->m_pColdUnwindInfo = pUnwindInfo; - } - else - { - pUnwindInfo = new (GetHeap()) ZapUnwindInfo(pCode, 0, 0, pMethod->m_pGCInfo); - pMethod->m_pUnwindInfo = pUnwindInfo; - } - pRuntimeFunctionSection->Place(pUnwindInfo); - -#endif // defined (FEATURE_EH_FUNCLETS) - - if (m_stats != NULL) - { - CorInfoIndirectCallReason reason; - BOOL direct = m_pPreloader->CanSkipMethodPreparation(NULL, pMethod->GetHandle(), &reason); - - if (direct && pMethod->m_pFixupList != NULL) - { - reason = CORINFO_INDIRECT_CALL_FIXUPS; - direct = FALSE; - } - - if (direct) - { - m_stats->m_directMethods++; - } - else - { - m_stats->m_prestubMethods++; - m_stats->m_indirectMethodReasons[reason]++; - } - } - } - -#ifdef REDHAWK - // Redhawk needs any trailing padding to be 0xcc - DWORD cbPad = AlignUp(currentOffset, sizeof(DWORD)) - currentOffset; - if (cbPad != 0) - { - ZapBlob * pBlob = ZapBlob::NewBlob(this, NULL, cbPad); - memset(pBlob->GetData(), DEFAULT_CODE_BUFFER_INIT, cbPad); - pCodeSection->Place(pBlob); - currentOffset += cbPad; - } - - map.Output(this, m_pCodeMgrSection, numMethods); -#else - COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount(); - - if (nUnwindInfos != 0) - { - if (IsReadyToRunCompilation()) - { - // TODO: Implement - } - else - if (!fCold) - { - ZapVirtualSection * pCodeMethodDescSection = GetCodeMethodDescSection(codeType); - pCodeMethodDescSection->Place(new (GetHeap()) ZapCodeMethodDescs(startMethod, endMethod, nUnwindInfos)); - - ZapVirtualSection* pUnwindInfoLookupSection = GetUnwindInfoLookupSection(codeType); - pUnwindInfoLookupSection->Place(new (GetHeap()) ZapUnwindInfoLookupTable(pRuntimeFunctionSection, pCodeSection, codeSize)); - } - else - { - m_pColdCodeMapSection->Place(new (GetHeap()) ZapColdCodeMap(pRuntimeFunctionSection)); - } - } -#endif - - EndRegion(regionKind); -} - -void ZapImage::OutputCodeInfo(CodeType codeType) -{ - CorInfoRegionKind regionKind = (codeType == ProfiledHot) ? CORINFO_REGION_HOT : CORINFO_REGION_COLD; - BeginRegion(regionKind); - - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - // - // We are either outputing the ProfiledHot methods - // or the unprofiled and cold methods - // - if ((pMethod->m_ProfilingDataFlags & (1 << ReadMethodCode)) != (codeType == ProfiledHot)) - { - // Wrong kind so skip - continue; - } - - if (pMethod->m_pROData != NULL) - m_pReadOnlyDataSection->Place(pMethod->m_pROData); - -#ifndef REDHAWK - // Note: for Redhawk we place EH info via OutputEHInfo(). - if (pMethod->m_pExceptionInfo != NULL) - { - ZapNode* pCode = pMethod->m_pCode; - m_pExceptionInfoLookupTable->PlaceExceptionInfoEntry(pCode, pMethod->m_pExceptionInfo); - } -#endif // REDHAWK - - if (pMethod->m_pFixupList != NULL && !IsReadyToRunCompilation()) - pMethod->m_pFixupInfo = m_pImportTable->PlaceFixups(pMethod->m_pFixupList); - } - - EndRegion(regionKind); -} - -void ZapImage::OutputProfileData() -{ - if (m_pInstrumentSection == NULL) - { - return; - } - - ZapProfileData * pPrevious = NULL; - - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - if (pMethod->m_pProfileData == NULL) - { - continue; - } - - ZapProfileData * pHeader = new (GetHeap()) ZapProfileData(pMethod); - - m_pInstrumentSection->Place(pHeader); - m_pInstrumentSection->Place(pMethod->m_pProfileData); - - if (pPrevious != NULL) - { - pPrevious->SetNext(pHeader); - } - - pPrevious = pHeader; - } -} - -void ZapImage::OutputDebugInfo() -{ - m_pDebugInfoTable->PrepareLayout(); - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - m_pDebugInfoTable->PlaceDebugInfo(m_MethodCompilationOrder[i]); - } - m_pDebugInfoTable->FinishLayout(); -} - -void ZapImage::OutputGCInfo() -{ -#ifndef REDHAWK - struct MaskValue - { - DWORD mask; - DWORD value; - }; - - static const MaskValue gcInfoSequence[] = - { - { (1 << CommonReadGCInfo) , (1 << CommonReadGCInfo) }, // c flag on, r flag don't care - { (1 << CommonReadGCInfo)|(1 << ReadGCInfo), (1 << ReadGCInfo) }, // r flag on, c flag off - { (1 << CommonReadGCInfo)|(1 << ReadGCInfo), 0 }, // both flags off - { 0, 0 } - }; - - // Make three passes over the gc infos, emitting them in order of decreasing hotness, - // and for stuff that wasn't touched by anyone we put it in the cold section - for (const MaskValue *pMaskValue = gcInfoSequence; pMaskValue->mask; pMaskValue++) - { - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - if ((pMethod->m_ProfilingDataFlags & pMaskValue->mask) != pMaskValue->value) - { - continue; - } - - ZapGCInfo * pGCInfo = pMethod->m_pGCInfo; - - // Given that GC Info can be interned it may have been placed already on - // this or a previous pass through the compiled methods. If it hasn't already - // been placed then we place it in the appropriate section. - if (!pGCInfo->IsPlaced()) - { - // A) it was touched, and here they are placed in order of flags above - if (pMaskValue->value) - { - m_pHotTouchedGCSection->Place(pGCInfo); - } - // B) the method that it is attached to is in the trained section - else if (iPlace(pGCInfo); - } - // C) it wasn't touched _and_ it is related to untrained code - else - { - m_pGCSection->Place(pGCInfo); - } - } - } - - // Just after placing those touched in an IBC scenario, place those that - // should be prioritized regardless of the corresponding method's IBC information. - // (Currently, this is used to pack the gc info of IL stubs that cannot be directly tracked by IBC.) - if (pMaskValue->value == (1 << ReadGCInfo)) - { - for (COUNT_T i = 0; i < m_PrioritizedGCInfo.GetCount(); i++) - { - ZapGCInfo * pGCInfo = m_PrioritizedGCInfo[i]; - if (!pGCInfo->IsPlaced()) - { - m_pHotGCSection->Place(pGCInfo); - } - } - } - } -#else // REDHAWK - // - ModuleGcInfoEncoder * pEncoder = GetGcInfoEncoder(); - - m_pUnwindInfoBlob = pEncoder->ConstructUnwindInfoBlob(this); - m_pCallsiteInfoBlob = pEncoder->ConstructCallsiteInfoBlob(this); - ZapBlob * pShortcutMap = pEncoder->ConstructDeltaShortcutMap(this); - - // @TODO: we could fold this loop into ConstructMethodInfoBlob, but then we'd have to keep a separate - // list of method infos inside the ModuleGcInfoEncoder.. - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - pEncoder->EncodeMethodInfo(pMethod->m_pGCInfo); - } - ZapBlob * pMethodInfos = pEncoder->ConstructMethodInfoBlob(this); - - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - // At this point pMethod->m_pGCInfo is really a pointer that the encoder owns. - // We must pass it back to the encoder so it can encode it and pass back a proper ZapBlob * - pMethod->m_pGCInfo = pEncoder->FindMethodInfo(this, pMethod->m_pGCInfo); - } - - m_pGCSection->Place(pShortcutMap); - m_pGCSection->Place(pMethodInfos); - if (m_pUnwindInfoBlob) - m_pGCSection->Place(m_pUnwindInfoBlob); - - if (m_pCallsiteInfoBlob) - m_pGCSection->Place(m_pCallsiteInfoBlob); - - // - // Create the method-number-to-gc-info table - // - UINT32 methodInfoSize = pMethodInfos->GetSize(); - - COUNT_T nMethods = m_MethodCompilationOrder.GetCount(); - UINT16 elemSize = 4; - - if (methodInfoSize <= 0x10000) - { - elemSize = 2; - - // Remember the element size for this map in the module header - m_moduleHeaderFlags |= ModuleHeader::SmallGCInfoListEntriesFlag; - } - - // Create the table - SIZE_T tableSize = elemSize * nMethods; - ZapBlob * pMethodToGcInfoMap = ZapBlob::NewBlob(this, NULL, tableSize); - - UINT16* pwTableEntries = (UINT16*) pMethodToGcInfoMap->GetData(); - UINT32* pdwTableEntries = (UINT32*) pwTableEntries; - - for (COUNT_T i = 0; i < nMethods; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - ZapGCInfo * pGCInfo = pMethod->m_pGCInfo; - - UINT32 uOffset = 0; - if (pGCInfo->GetType() == ZapNodeType_InnerPtr) - { - uOffset = ((ZapInnerPtr*)pGCInfo)->GetOffset(); - } - else - { - assert(ZapNodeType_Blob == pGCInfo->GetType()); - assert(pGCInfo == pMethodInfos); - } - - if (2 == elemSize) - { - assert(uOffset <= 0xFFFF); - pwTableEntries[i] = uOffset; - } - else - { - pdwTableEntries[i] = uOffset; - } - } - - m_pMethodToGCInfoMap->Place(pMethodToGcInfoMap); -#endif // REDHAWK -} - -#ifdef REDHAWK -// Place all ZapExceptionInfo blobs into the exception section, and form the lookup table that we'll -// use at runtime to find EH info for a given method. -void ZapImage::OutputEHInfo() -{ - // For non-REDHAWK builds, we output EH info with the other per-method data in OutputCodeInfo(). - - // @TODO: consider emitting EH info in order of increasing hotness, like we do for GC info. - - // Place EH info for every method that has EH. - for (COUNT_T i = 0; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo; - - if ((pEHInfo != NULL) && !pEHInfo->IsPlaced()) - { - // We add relocs to the exception info here, at the last possible momement before placing - // them. That's because adding relocs changes the exception info, but prior to this we - // want to be able to use the data of the exception info as a hash key for interning. - AddRelocsForEHClauses(pEHInfo); - m_pExceptionSection->Place(pEHInfo); - } - } - - // Get the offsets for each EH blob that we will emit. - MapSHash ehinfoOffsets; - UINT32 ehinfoSize; - - ehinfoSize = m_pExceptionSection->FillInNodeOffsetMap(&ehinfoOffsets); - - // Chose a table entry size. - COUNT_T nMethods = m_MethodCompilationOrder.GetCount(); - UINT16 elemSize = 4; - - if (ehinfoSize <= 0x10000) - { - elemSize = 2; - - // Remember the element size for this map in the module header - m_moduleHeaderFlags |= ModuleHeader::SmallEHInfoListEntriesFlag; - } - - // Create the table. - SIZE_T tableSize = elemSize * nMethods; - SArray tableData(tableSize); - - UINT16* pwTableEntries = (UINT16*)&tableData[0]; - UINT32* pdwTableEntries = (UINT32*) pwTableEntries; - - // Fill in the offset for each method that has EH info. For methods that have no - // EH info, we will use a sentinel offset of -1. - for (COUNT_T i = 0; i < nMethods; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - ZapExceptionInfo * pEHInfo = pMethod->m_pExceptionInfo; - - UINT32 uOffset = -1; - - if (pEHInfo != NULL) - { - ehinfoOffsets.Lookup(pEHInfo, &uOffset); - assert(uOffset != -1); // Can't have a valid offset match the sentinel! - assert((4 == elemSize) || (uOffset <= 0xFFFF)); // Size must fit in 2 bytes if we're using hte small rep. - } - - if (2 == elemSize) - { - pwTableEntries[i] = uOffset; - } - else - { - pdwTableEntries[i] = uOffset; - } - } - - m_pMethodToEHInfoMap->Place(ZapBlob::NewBlob(this, &tableData[0], tableSize)); -} -#endif // REDHAWK - -#ifdef REDHAWK -// Add relocs for any EEType references in any typed EH clauses for the given EH Info. -void ZapImage::AddRelocsForEHClauses(ZapExceptionInfo * pExceptionInfo) -{ - EE_ILEXCEPTION *pEHInfo = (EE_ILEXCEPTION *)pExceptionInfo->GetData(); - _ASSERTE(pEHInfo != NULL); - - // One set of relocs for the entire set of clauses. Size assuming that every clause has a token. - ZapReloc * pRelocs = (ZapReloc *) - new (GetHeap()) BYTE[sizeof(ZapReloc) * pEHInfo->EHCount() + sizeof(ZapRelocationType)]; - - DWORD relocIndex = 0; - - // Add relocs for EEType references each typed clause. - for (int i = 0; i < pEHInfo->EHCount(); i++) - { - EE_ILEXCEPTION_CLAUSE *pClause = pEHInfo->EHClause(i); - - if ((pClause->Flags == COR_ILEXCEPTION_CLAUSE_NONE) || - (pClause->Flags == COR_ILEXCEPTION_CLAUSE_INDIRECT_TYPE_REFERENCE)) - { - ZapNode *pEETypeNode = (ZapNode*)pClause->EETypeReference; - - // @TODO: we're using a full pointer for each EEType reference in the EH clause. This will be - // 64bits on a 64bit system, though, which is twice as large as it needs to be. We should make - // these 32bit RVA's and compute the final address at runtime when we start supporting 64bit - // systems. See comments in ZapInfo::setEHinfo() for more details. - // - // N.B! If we move to RVAs, then the runtime structure that matches the EE_ILEXCEPTION struct - // needs to have a padding field removed. (The C++ compiler introduced 4 bytes of padding between - // 'DataSize' and 'Clauses' because 'Clauses' has a pointer field in it. This padding will - // disappear when we change the pointers to RVAs.) - pRelocs[relocIndex].m_type = IMAGE_REL_BASED_PTR; - pRelocs[relocIndex].m_pTargetNode = pEETypeNode; - pRelocs[relocIndex].m_offset = (BYTE*)pClause - (BYTE*)pEHInfo + offsetof(EE_ILEXCEPTION_CLAUSE, EETypeReference); - pExceptionInfo->ZeroPointer(pRelocs[relocIndex].m_offset); - relocIndex++; - } - } - - // Did we end up with any relocs? If so, then add them to the blob. - if (relocIndex > 0) - { - // Set sentinel - C_ASSERT(offsetof(ZapReloc, m_type) == 0); - pRelocs[relocIndex].m_type = IMAGE_REL_INVALID; - - pExceptionInfo->SetRelocs(pRelocs); - } -} -#endif // REDHAWK - -// -// ZapMethodHeader -// - -#ifdef TARGET_X86 -DWORD ZapCodeBlob::ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos) -{ - void * pData = GetData(); - SIZE_T size = GetSize(); - DWORD dwAlignment = GetAlignment(); - - dwPos = AlignUp(dwPos, dwAlignment); - - // - // Padding for straddler relocations. - // - - // The maximum size of padding - const DWORD cbAdjustForDynamicBaseMax = 256; - - // Find padding that gives us minimum number of straddlers - DWORD nMinStraddlers = MAXDWORD; - DWORD bestPad = 0; - for (DWORD pad = 0; pad < cbAdjustForDynamicBaseMax; pad += dwAlignment) - { - COUNT_T nStraddlers = GetCountOfStraddlerRelocations(dwPos + pad); - if (nStraddlers < nMinStraddlers) - { - nMinStraddlers = nStraddlers; - bestPad = pad; - - // It won't get better than this. - if (nMinStraddlers == 0) - break; - } - } - - DWORD dwPaddedPos = dwPos + bestPad; - SetRVA(dwPaddedPos); - - return dwPaddedPos + size; -} - -template -class ZapCodeBlobConst : public ZapCodeBlob -{ -protected: - ZapCodeBlobConst(SIZE_T cbSize) - : ZapCodeBlob(cbSize) - { - } - -public: - virtual UINT GetAlignment() - { - return alignment; - } - - static ZapCodeBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) - { - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapCodeBlobConst)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapCodeBlob * pZapCodeBlob = new (pMemory) ZapCodeBlobConst(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapCodeBlob + 1), pData, cbSize); - - return pZapCodeBlob; - } -}; - -ZapCodeBlob * ZapCodeBlob::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment) -{ - switch (cbAlignment) - { - case 1: - return ZapCodeBlobConst<1>::NewBlob(pWriter, pData, cbSize); - case 2: - return ZapCodeBlobConst<2>::NewBlob(pWriter, pData, cbSize); - case 4: - return ZapCodeBlobConst<4>::NewBlob(pWriter, pData, cbSize); - case 8: - return ZapCodeBlobConst<8>::NewBlob(pWriter, pData, cbSize); - case 16: - return ZapCodeBlobConst<16>::NewBlob(pWriter, pData, cbSize); - - default: - _ASSERTE(!"Requested alignment not supported"); - return NULL; - } -} -#endif // TARGET_X86 - -// See function prototype for details on why this iterator is "partial" -BOOL ZapMethodHeader::PartialTargetMethodIterator::GetNext(CORINFO_METHOD_HANDLE *pHnd) -{ - _ASSERTE(pHnd != NULL); - - if (m_pCurReloc == NULL) - { - return FALSE; - } - - while (m_pCurReloc->m_type != IMAGE_REL_INVALID) - { - ZapNode * pTarget = m_pCurReloc->m_pTargetNode; - ZapNodeType type = pTarget->GetType(); - - m_pCurReloc++; - - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - if (type == ZapNodeType_MethodEntryPoint) - { - *pHnd = ((ZapMethodEntryPoint *)pTarget)->GetHandle(); - return TRUE; - } - } - - return FALSE; -} - -void ZapCodeMethodDescs::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - COUNT_T nUnwindInfos = 0; - - for (COUNT_T curMethod = m_iStartMethod; curMethod < m_iEndMethod; curMethod++) - { - ZapMethodHeader * pMethod = pImage->m_MethodCompilationOrder[curMethod]; - DWORD dwRVA = pImage->m_pPreloader->MapMethodHandle(pMethod->GetHandle()); - - if (pMethod->m_pExceptionInfo != NULL) - dwRVA |= HAS_EXCEPTION_INFO_MASK; - - pImage->Write(&dwRVA, sizeof(dwRVA)); - nUnwindInfos++; - -#ifdef FEATURE_EH_FUNCLETS - ZapUnwindInfo * pFragment = pMethod->m_pUnwindInfoFragments; - while (pFragment != NULL) - { - if (pFragment != pMethod->m_pUnwindInfo && pFragment->GetCode() == pMethod->m_pCode) - { - dwRVA = 0; - pImage->Write(&dwRVA, sizeof(dwRVA)); - nUnwindInfos++; - } - - pFragment = pFragment->GetNextFragment(); - } -#endif - } - _ASSERTE(nUnwindInfos == m_nUnwindInfos); -} - -// -// ZapMethodEntryPoint -// - -void ZapMethodEntryPoint::Resolve(ZapImage * pImage) -{ - DWORD rvaValue = pImage->m_pPreloader->MapMethodEntryPoint(GetHandle()); -#ifdef _DEBUG - if (rvaValue == NULL) - { - mdMethodDef token; - pImage->GetCompileInfo()->GetMethodDef(GetHandle(), &token); - pImage->Error(token, S_OK, 0, W("MapMethodEntryPoint failed")); - } - else -#endif - { - SetRVA(rvaValue); - } -} - -ZapMethodEntryPoint * ZapMethodEntryPointTable::GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) -{ - ZapMethodEntryPoint * pMethodEntryPoint = m_entries.Lookup(MethodEntryPointKey(handle, accessFlags)); - - if (pMethodEntryPoint != NULL) - return pMethodEntryPoint; - -#ifdef _DEBUG - mdMethodDef token; - m_pImage->GetCompileInfo()->GetMethodDef(handle, &token); -#endif - - pMethodEntryPoint = new (m_pImage->GetHeap()) ZapMethodEntryPoint(handle, accessFlags); - m_entries.Add(pMethodEntryPoint); - return pMethodEntryPoint; -} - -void ZapMethodEntryPointTable::Resolve() -{ - for (MethodEntryPointTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - ZapMethodEntryPoint * pMethodEntryPoint = *i; - - // Skip unused entrypoints - they may be omitted in the image - if (!pMethodEntryPoint->IsUsed()) - continue; - - pMethodEntryPoint->Resolve(m_pImage); - } -} - -ZapNode * ZapMethodEntryPointTable::CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller) -{ - CORINFO_METHOD_HANDLE caller = pCaller->GetHandle(); - CORINFO_METHOD_HANDLE callee = pMethodEntryPoint->GetHandle(); - - CorInfoIndirectCallReason reason; - if (m_pImage->canIntraModuleDirectCall(caller, callee, &reason, pMethodEntryPoint->GetAccessFlags())) - { - ZapNode * pCode = m_pImage->GetCompiledMethod(callee)->GetCode(); -#ifdef TARGET_ARM - pCode = m_pImage->GetInnerPtr(pCode, THUMB_CODE); -#endif // TARGET_ARM - return pCode; - } - else - { - if (!pMethodEntryPoint->IsUsed()) - { - // This method entry point is going to be used for indirect call. - // Record this so that later we will assign it an RVA. - pMethodEntryPoint->SetIsUsed(); - } - return NULL; - } -} - -#ifdef FEATURE_EH_FUNCLETS -ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) -{ - ZapGCInfo * pNode = m_blobs.Lookup(GCInfoKey(pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo)); - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapGCInfo::NewGCInfo(m_pImage, pGCInfo, cbGCInfo, pUnwindInfo, cbUnwindInfo); - m_blobs.Add(pNode); - return pNode; -} - -ZapGCInfo * ZapGCInfo::NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) -{ - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapGCInfo)) + S_SIZE_T(cbGCInfo) + S_SIZE_T(cbUnwindInfo); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapGCInfo * pZapGCInfo = new (pMemory) ZapGCInfo(cbGCInfo, cbUnwindInfo); - - memcpy(pZapGCInfo->GetGCInfo(), pGCInfo, cbGCInfo); - memcpy(pZapGCInfo->GetUnwindInfo(), pUnwindInfo, cbUnwindInfo); - -#if !defined(TARGET_X86) - // Make sure the personality routine thunk is created - pZapGCInfo->GetPersonalityRoutine(ZapImage::GetImage(pWriter)); -#endif // !defined(TARGET_X86) - return pZapGCInfo; -} -#else -ZapGCInfo * ZapGCInfoTable::GetGCInfo(PVOID pBlob, SIZE_T cbBlob) -{ - ZapGCInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob)); - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob); - m_blobs.Add(pNode); - return pNode; -} -#endif - -// -// ZapUnwindInfo -// - -void ZapUnwindInfo::Save(ZapWriter * pZapWriter) -{ - T_RUNTIME_FUNCTION runtimeFunction; - -#if defined(TARGET_ARM) || defined(TARGET_ARM64) - RUNTIME_FUNCTION__SetBeginAddress(&runtimeFunction, GetStartAddress()); - runtimeFunction.UnwindData = m_pUnwindData->GetRVA(); -#elif defined(TARGET_AMD64) - runtimeFunction.BeginAddress = GetStartAddress(); - runtimeFunction.EndAddress = GetEndAddress(); - ULONG unwindData = m_pUnwindData->GetRVA(); - if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info - unwindData |= RUNTIME_FUNCTION_INDIRECT; - runtimeFunction.UnwindData = unwindData; -#elif defined(TARGET_X86) - runtimeFunction.BeginAddress = GetStartAddress(); - ULONG unwindData = m_pUnwindData->GetRVA(); - if (m_pUnwindData->GetType() == ZapNodeType_UnwindInfo) // Chained unwind info - unwindData |= RUNTIME_FUNCTION_INDIRECT; - runtimeFunction.UnwindData = unwindData; -#else - PORTABILITY_ASSERT("ZapUnwindInfo"); -#endif - - pZapWriter->Write(&runtimeFunction, sizeof(runtimeFunction)); -} - -#if defined(FEATURE_EH_FUNCLETS) -// Compare the unwind infos by their offset -int __cdecl ZapUnwindInfo::CompareUnwindInfo(const void* a_, const void* b_) -{ - ZapUnwindInfo * a = *(ZapUnwindInfo **)a_; - ZapUnwindInfo * b = *(ZapUnwindInfo **)b_; - - if (a->GetStartOffset() > b->GetStartOffset()) - { - _ASSERTE(a->GetStartOffset() >= b->GetEndOffset()); - return 1; - } - - if (a->GetStartOffset() < b->GetStartOffset()) - { - _ASSERTE(a->GetEndOffset() <= b->GetEndOffset()); - return -1; - } - - _ASSERTE(a == b); - return 0; -} - -#if defined(TARGET_AMD64) - -UINT ZapUnwindData::GetAlignment() -{ - return sizeof(ULONG); -} - -DWORD ZapUnwindData::GetSize() -{ - DWORD dwSize = ZapBlob::GetSize(); - -#ifndef REDHAWK - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO has already had its size included in size - dwSize = AlignUp(dwSize, sizeof(ULONG)); - - dwSize += sizeof(ULONG); -#endif //REDHAWK - - return dwSize; -} - -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - PVOID pData = GetData(); - DWORD dwSize = GetBlobSize(); - - UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData; - - // Check whether the size is what we expect it to be - _ASSERTE(dwSize == offsetof(UNWIND_INFO, UnwindCode) + pUnwindInfo->CountOfUnwindCodes * sizeof(UNWIND_CODE)); -#ifndef REDHAWK - pUnwindInfo->Flags = UNW_FLAG_EHANDLER | UNW_FLAG_UHANDLER; -#endif //REDHAWK - - pZapWriter->Write(pData, dwSize); - -#ifndef REDHAWK - DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD)); - if (dwPad != 0) - pZapWriter->WritePad(dwPad); - - ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA(); - pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine)); -#endif //REDHAWK -} - -#elif defined(TARGET_X86) - -UINT ZapUnwindData::GetAlignment() -{ - return sizeof(BYTE); -} - -DWORD ZapUnwindData::GetSize() -{ - return ZapBlob::GetSize(); -} - -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - PVOID pData = GetData(); - DWORD dwSize = GetBlobSize(); - - pZapWriter->Write(pData, dwSize); -} - -#elif defined(TARGET_ARM) || defined(TARGET_ARM64) - -UINT ZapUnwindData::GetAlignment() -{ - return sizeof(ULONG); -} - -DWORD ZapUnwindData::GetSize() -{ - DWORD dwSize = ZapBlob::GetSize(); - - // Add space for personality routine, it must be 4-byte aligned. - // Everything in the UNWIND_INFO has already had its size included in size - dwSize = AlignUp(dwSize, sizeof(ULONG)); - dwSize += sizeof(ULONG); - - return dwSize; -} - -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - PVOID pData = GetData(); - DWORD dwSize = GetBlobSize(); - - UNWIND_INFO * pUnwindInfo = (UNWIND_INFO *)pData; - - // Set the 'X' bit to indicate that there is a personality routine associated with this method - *(LONG *)pUnwindInfo |= (1<<20); - - pZapWriter->Write(pData, dwSize); - - DWORD dwPad = AlignmentPad(dwSize, sizeof(DWORD)); - if (dwPad != 0) - pZapWriter->WritePad(dwPad); - - ULONG personalityRoutine = GetPersonalityRoutine(pImage)->GetRVA(); - pZapWriter->Write(&personalityRoutine, sizeof(personalityRoutine)); -} - -#else -UINT ZapUnwindData::GetAlignment() -{ - PORTABILITY_ASSERT("ZapUnwindData::GetAlignment"); - return sizeof(ULONG); -} -DWORD ZapUnwindData::GetSize() -{ - PORTABILITY_ASSERT("ZapUnwindData::GetSize"); - return -1; -} -void ZapUnwindData::Save(ZapWriter * pZapWriter) -{ - PORTABILITY_ASSERT("ZapUnwindData::Save"); -} - -#endif - -ZapNode * ZapUnwindData::GetPersonalityRoutine(ZapImage * pImage) -{ - // Use different personality routine pointer for filter funclets so that we can quickly tell at runtime - // whether funclet is a filter. -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - ReadyToRunHelper helperNum = IsFilterFunclet() ? READYTORUN_HELPER_PersonalityRoutineFilterFunclet : READYTORUN_HELPER_PersonalityRoutine; - return pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helperNum); - } -#endif - return pImage->GetHelperThunk(IsFilterFunclet() ? CORINFO_HELP_EE_PERSONALITY_ROUTINE_FILTER_FUNCLET : CORINFO_HELP_EE_PERSONALITY_ROUTINE); -} - -ZapUnwindData * ZapUnwindData::NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet) -{ - SIZE_T cbAllocSize = sizeof(ZapUnwindData) + cbSize; - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize]; - - ZapUnwindData * pZapUnwindData = fIsFilterFunclet ? - (new (pMemory) ZapFilterFuncletUnwindData(cbSize)) : (new (pMemory) ZapUnwindData(cbSize)); - - memcpy((void*)(pZapUnwindData + 1), pData, cbSize); - -#if !defined(TARGET_X86) - // Make sure the personality routine thunk is created - pZapUnwindData->GetPersonalityRoutine(ZapImage::GetImage(pWriter)); -#endif // !defined(TARGET_X86) - - return pZapUnwindData; -} - -ZapUnwindData * ZapUnwindDataTable::GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet) -{ - ZapUnwindData * pNode = (ZapUnwindData *)m_blobs.Lookup(ZapUnwindDataKey(pBlob, cbBlob, fIsFilterFunclet)); - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapUnwindData::NewUnwindData(m_pImage, pBlob, cbBlob, fIsFilterFunclet); - m_blobs.Add(pNode); - return pNode; -} -#endif // FEATURE_EH_FUNCLETS - -// -// ZapDebugInfo -// - -ZapDebugInfo * ZapDebugInfoTable::GetDebugInfo(PVOID pBlob, SIZE_T cbBlob) -{ - ZapDebugInfo * pNode = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob)); - m_nCount++; - - if (pNode != NULL) - { - return pNode; - } - - pNode = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob); - m_blobs.Add(pNode); - return pNode; -} - -void ZapDebugInfoTable::PrepareLayout() -{ - if (m_nCount == 0) - return; - - // Make sure that the number of methods is odd number - m_nCount |= 1; - - m_pTable = new (m_pImage->GetHeap()) ZapNode * [m_nCount]; -} - -void ZapDebugInfoTable::PlaceDebugInfo(ZapMethodHeader * pMethod) -{ - // Place the debug info blob if it is not placed yet - ZapBlob * pDebugInfo = pMethod->GetDebugInfo(); - if (pDebugInfo == NULL) - { - return; - } - - if (!pDebugInfo->IsPlaced()) - { - m_pImage->m_pDebugSection->Place(pDebugInfo); - } - - mdMethodDef md; - IfFailThrow(m_pImage->GetCompileInfo()->GetMethodDef(pMethod->GetHandle(), &md)); - - COUNT_T index = GetDebugRidEntryHash(md) % m_nCount; - - ZapNode * pHead = m_pTable[index]; - if (pHead == NULL) - { - // The common case - single rid entry. - m_pTable[index] = pMethod; - return; - } - - // Create linked list of labelled entries if we do not have one yet - if (pHead->GetType() != ZapNodeType_DebugInfoLabelledEntry) - { - m_pTable[index] = new (m_pImage->GetHeap()) LabelledEntry((ZapMethodHeader *)pHead); - } - - // Insert the method at the end of the linked list - LabelledEntry * pEntry = (LabelledEntry *)m_pTable[index]; - while (pEntry->m_pNext != NULL) - pEntry = pEntry->m_pNext; - - pEntry->m_pNext = new (m_pImage->GetHeap()) LabelledEntry(pMethod); -} - -void ZapDebugInfoTable::FinishLayout() -{ - // Go over the table again and place all labelled entries - for (COUNT_T i = 0; i < m_nCount; i++) - { - ZapNode * pNode = m_pTable[i]; - - if (pNode == NULL || pNode->GetType() != ZapNodeType_DebugInfoLabelledEntry) - continue; - - LabelledEntry * pEntry = (LabelledEntry *)pNode; - - while (pEntry != NULL) - { - m_pImage->m_pDebugSection->Place(pEntry); - pEntry = pEntry->m_pNext; - } - } -} - -void ZapDebugInfoTable::Save(ZapWriter * pZapWriter) -{ - for (COUNT_T i = 0; i < m_nCount; i++) - { - CORCOMPILE_DEBUG_ENTRY entry = 0; - - ZapNode * pNode = m_pTable[i]; - - if (pNode != NULL) - { - if (pNode->GetType() == ZapNodeType_DebugInfoLabelledEntry) - entry |= pNode->GetRVA() | CORCOMPILE_DEBUG_MULTIPLE_ENTRIES; - else - entry = ((ZapMethodHeader *)pNode)->GetDebugInfo()->GetRVA(); - } - - pZapWriter->Write(&entry, sizeof(entry)); - } -} - -void ZapDebugInfoTable::LabelledEntry::Save(ZapWriter * pZapWriter) -{ - CORCOMPILE_DEBUG_LABELLED_ENTRY entry; - - entry.nativeCodeRVA = m_pMethod->GetCode()->GetRVA(); - entry.debugInfoOffset = m_pMethod->GetDebugInfo()->GetRVA(); - - if (m_pNext != NULL) - entry.debugInfoOffset |= CORCOMPILE_DEBUG_MULTIPLE_ENTRIES; - - pZapWriter->Write(&entry, sizeof(entry)); -} - -// -// ZapProfileData -// -void ZapProfileData::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - CORCOMPILE_METHOD_PROFILE_LIST profileData; - - ZeroMemory(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST)); - - if (m_pNext != NULL) - pImage->WriteReloc(&profileData, - offsetof(CORCOMPILE_METHOD_PROFILE_LIST, next), - m_pNext, 0, IMAGE_REL_BASED_PTR); - - pZapWriter->Write(&profileData, sizeof(CORCOMPILE_METHOD_PROFILE_LIST)); -} - - -// Zapping of ExeptionInfoTable -ZapExceptionInfoLookupTable::ZapExceptionInfoLookupTable(ZapImage *pImage) : m_pImage(pImage) -{ - _ASSERTE(m_pImage->m_pExceptionSection != NULL); - m_pImage->m_pExceptionSection->Place(this); -} - -void ZapExceptionInfoLookupTable::PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo) -{ - ExceptionInfoEntry entry; - entry.m_pCode = pCode; - entry.m_pExceptionInfo = pExceptionInfo; - m_exceptionInfoEntries.Append(entry); - m_pImage->m_pExceptionSection->Place(pExceptionInfo); -} - -DWORD ZapExceptionInfoLookupTable::GetSize() -{ - if (m_exceptionInfoEntries.GetCount() == 0) - return 0; - - DWORD numExceptionInfoEntries = m_exceptionInfoEntries.GetCount(); - // 1 sentential entry at the end of the table. - return (numExceptionInfoEntries + 1) * sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY); -} - -void ZapExceptionInfoLookupTable::Save(ZapWriter* pZapWriter) -{ - - if(m_exceptionInfoEntries.GetCount() == 0) - return; - - for(COUNT_T i = 0; i < m_exceptionInfoEntries.GetCount(); ++i) - { - DWORD methodStartRVA = m_exceptionInfoEntries[i].m_pCode->GetRVA(); - - ZapExceptionInfo* pExceptionInfo = m_exceptionInfoEntries[i].m_pExceptionInfo; - - CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY lookupEntry; - - lookupEntry.MethodStartRVA = methodStartRVA; - lookupEntry.ExceptionInfoRVA = pExceptionInfo->GetRVA(); - - pZapWriter->Write(&lookupEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY)); - -#ifdef _DEBUG - // Make sure there are no gaps between 2 consecutive CORCOMPILE_EXCEPTION_CLAUSE - // We use pointer arithmatic to calculate the number of EHClause for a method. - if (i != 0) - { - ZapExceptionInfo* pPreviousExceptionInfo = m_exceptionInfoEntries[i-1].m_pExceptionInfo; - DWORD size = pExceptionInfo->GetRVA() - pPreviousExceptionInfo->GetRVA(); - DWORD ehClauseSize = size % sizeof(CORCOMPILE_EXCEPTION_CLAUSE); - CONSISTENCY_CHECK_MSG(ehClauseSize == 0, "There must be no gaps between 2 successive clause arrays, please check ZapExceptionInfo alignment"); - } -#endif - } - - // write a sentinal entry.. this entry helps to find the number of EHClauses for the last entry - CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY sentinalEntry; - - ExceptionInfoEntry lastEntry = m_exceptionInfoEntries[m_exceptionInfoEntries.GetCount() -1]; - - ZapExceptionInfo* pLastExceptionInfo = lastEntry.m_pExceptionInfo; - - sentinalEntry.MethodStartRVA = (DWORD)-1; - - // points just after the end of the Exception table - // the sentinal node m_pExceptionInfo pointer actually points to an invalid CORCOMPILE_EXCEPTION_CLAUSE - // area. The lookup algorithm will never dereference the sentinal pointer, and hence this is safe - sentinalEntry.ExceptionInfoRVA = pLastExceptionInfo->GetRVA() + pLastExceptionInfo->GetSize(); - - pZapWriter->Write(&sentinalEntry, sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY)); -} - - -DWORD ZapUnwindInfoLookupTable::GetSize() -{ - // Sentinal entry at the end - return (GetNumEntries() + 1) * sizeof (DWORD); -} - -void ZapUnwindInfoLookupTable::Save(ZapWriter* pZapWriter) -{ - ZapVirtualSection * pRuntimeFunctionSection = m_pRuntimeFunctionSection; - - // Create Lookup entries. - // 1 lookup entry for each RUNTIME_FUNCTION_LOOKUP_STRIDE K of code. - COUNT_T nUnwindInfos = pRuntimeFunctionSection->GetNodeCount(); - - DWORD dwCodeSectionStartAddress = m_pCodeSection->GetRVA(); - - DWORD nLookupEntries = 0; - DWORD entry; - - DWORD nTotalLookupEntries = GetNumEntries(); - - // write out the first entry - entry = 0; - pZapWriter->Write(&entry, sizeof(DWORD)); - nLookupEntries++; - if (nLookupEntries == nTotalLookupEntries) - goto WriteSentinel; - - for (COUNT_T i = 1; i < nUnwindInfos; ++i) - { - ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)pRuntimeFunctionSection->GetNode(i); - DWORD RelativePC = pUnwindInfo->GetStartAddress() - dwCodeSectionStartAddress; - - COUNT_T iCurrentIndex = RelativePC / RUNTIME_FUNCTION_LOOKUP_STRIDE; - - // Note that we should not be using pUnwindInfo->GetEndAddress() here. The binary search - // in the VM that's accelerated by this table does not look at the EndAddress either, and - // so not using EndAddress here assures consistency. - COUNT_T iPreviousIndex = (RelativePC - 1)/ RUNTIME_FUNCTION_LOOKUP_STRIDE; - - while(iPreviousIndex >= nLookupEntries) - { - entry = i - 1; - pZapWriter->Write(&entry, sizeof(DWORD)); - nLookupEntries++; - if (nLookupEntries == nTotalLookupEntries) - goto WriteSentinel; - } - - if (iCurrentIndex == nLookupEntries) - { - entry = i; - pZapWriter->Write(&entry, sizeof(DWORD)); - nLookupEntries++; - if (nLookupEntries == nTotalLookupEntries) - goto WriteSentinel; - } - } - -WriteSentinel: - // There should always be one sentinel entry at the end. The sentinel entry will - // be good to cover the rest of the section to account for extra padding. - _ASSERTE(nLookupEntries <= nTotalLookupEntries); - - while (nLookupEntries <= nTotalLookupEntries) - { - entry = nUnwindInfos - 1; - pZapWriter->Write(&entry, sizeof (DWORD)); - nLookupEntries ++; - } -} - -DWORD ZapColdCodeMap::GetSize() -{ - return m_pRuntimeFunctionSection->GetNodeCount() * sizeof(CORCOMPILE_COLD_METHOD_ENTRY); -} - -void ZapColdCodeMap::Save(ZapWriter* pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - ZapNode * pPendingCode = NULL; - COUNT_T curMethod = 0; - - COUNT_T nUnwindInfos = m_pRuntimeFunctionSection->GetNodeCount(); - for (COUNT_T i = 0; i < nUnwindInfos; ++i) - { - CORCOMPILE_COLD_METHOD_ENTRY entry; - - ZapUnwindInfo* pUnwindInfo = (ZapUnwindInfo*)m_pRuntimeFunctionSection->GetNode(i); - -#ifdef FEATURE_EH_FUNCLETS - if (pUnwindInfo->GetCode() == pPendingCode) - { - entry.mainFunctionEntryRVA = 0; - entry.hotCodeSize = 0; - } - else -#endif - { - pPendingCode = pUnwindInfo->GetCode(); - - ZapMethodHeader * pMethod; - - for (;;) - { - pMethod = pImage->m_MethodCompilationOrder[curMethod]; - if (pMethod->m_pColdCode == pPendingCode) - break; - curMethod++; - } - -#ifdef FEATURE_EH_FUNCLETS - entry.mainFunctionEntryRVA = pMethod->m_pUnwindInfo->GetRVA(); -#endif - - entry.hotCodeSize = pMethod->m_pCode->GetSize(); - } - - pZapWriter->Write(&entry, sizeof(entry)); - } -} - -DWORD ZapHelperThunk::GetSize() -{ - return (m_dwHelper & CORCOMPILE_HELPER_PTR) ? TARGET_POINTER_SIZE : HELPER_TABLE_ENTRY_LEN; -} - -void ZapHelperThunk::Save(ZapWriter * pZapWriter) -{ -#ifdef _DEBUG - LOG((LF_ZAP, LL_INFO1000000, "Emitting JIT helper table entry for helper %3d (%s)\n", - (USHORT) m_dwHelper, s_rgHelperNames[(USHORT) m_dwHelper])); -#endif // _DEBUG - - // Save the index of the helper, the actual code for the thunk will be generated at runtime - pZapWriter->Write(&m_dwHelper, sizeof(DWORD)); - - DWORD pad = GetSize() - sizeof(DWORD); - if (pad > 0) - { - void * pPad = _alloca(pad); - memset(pPad, DEFAULT_CODE_BUFFER_INIT, pad); - pZapWriter->Write(pPad, pad); - } -} - -void ZapLazyHelperThunk::Place(ZapImage * pImage) -{ - m_pArg = pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE]; - - m_pTarget = pImage->GetHelperThunk(m_dwHelper); - - pImage->m_pLazyHelperSection->Place(this); -} - -DWORD ZapLazyHelperThunk::GetSize() -{ - return SaveWorker(NULL); -} - -void ZapLazyHelperThunk::Save(ZapWriter * pZapWriter) -{ - SaveWorker(pZapWriter); -} - -DWORD ZapLazyHelperThunk::SaveWorker(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - BYTE buffer[42]; // Buffer big enough to hold any reasonable helper thunk sequence - BYTE * p = buffer; - -#if defined(TARGET_X86) - // mov edx, module - *p++ = 0xBA; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR); - p += 4; - - // jmp JIT_StrCns - *p++ = 0xE9; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32); - p += 4; -#elif defined(TARGET_AMD64) - *p++ = 0x48; - *p++ = 0x8D; -#ifdef UNIX_AMD64_ABI - // lea rsi, module - *p++ = 0x35; -#else - // lea rdx, module - *p++ = 0x15; -#endif - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_REL32); - p += 4; - - // jmp JIT_StrCns - *p++ = 0xE9; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_REL32); - p += 4; -#elif defined(TARGET_ARM) - // movw r1, module - *(WORD *)(p + 0) = 0xf240; - *(WORD *)(p + 2) = 1 << 8; - // movt r1, module - *(WORD *)(p + 4) = 0xf2c0; - *(WORD *)(p + 6) = 1 << 8; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // b JIT_StrCns - *(WORD *)(p + 0) = 0xf000; - *(WORD *)(p + 2) = 0xb800; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_BASED_THUMB_BRANCH24); - p += 4; -#elif defined(TARGET_ARM64) - // ldr x1, [PC+8] - *(DWORD *)(p) =0x58000041; - p += 4; - // b JIT_StrCns - *(DWORD *)(p) = 0x14000000; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pTarget, 0, IMAGE_REL_ARM64_BRANCH26); - p += 4; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), m_pArg, 0, IMAGE_REL_BASED_PTR); - p += 8; -#else - PORTABILITY_ASSERT("ZapLazyHelperThunk::Save"); -#endif - - _ASSERTE((DWORD)(p - buffer) <= sizeof(buffer)); - - if (pZapWriter != NULL) - pZapWriter->Write(&buffer, (int)(p - buffer)); - - return (DWORD) (p - buffer); -} diff --git a/src/coreclr/zap/zapcode.h b/src/coreclr/zap/zapcode.h deleted file mode 100644 index cd9b7ccbf19310..00000000000000 --- a/src/coreclr/zap/zapcode.h +++ /dev/null @@ -1,956 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapCode.h -// - -// -// ZapNodes for everything directly related to zapping of native code -// -// code:ZapMethodHeader -// code:ZapMethodEntryPoint -// code:ZapMethodEntryPointTable -// code:ZapDebugInfo -// code:ZapProfileData -// code:ZapHelperTable -// code:ZapGCInfoTable - - -// -// ====================================================================================== - -#ifndef __ZAPCODE_H__ -#define __ZAPCODE_H__ - -// Forward declarations - -class ZapBlobWithRelocs; - -#ifdef REDHAWK -typedef ZapNode ZapGCInfo; -#else -#if defined(FEATURE_EH_FUNCLETS) -class ZapGCInfo; -#else -typedef ZapBlob ZapGCInfo; -#endif -#endif // REDHAWK - -typedef ZapBlob ZapDebugInfo; -typedef ZapBlob ZapFixupInfo; -#ifdef REDHAWK -typedef ZapBlobWithRelocs ZapExceptionInfo; -#else -typedef ZapBlob ZapExceptionInfo; -#endif - -class ZapUnwindInfo; - -class ZapImport; - -class ZapInfo; - -class ZapGCRefMapTable; - -//--------------------------------------------------------------------------------------- -// -// ZapMethodHeader is the main node that all information about the compiled code is hanging from -// -class ZapMethodHeader : public ZapNode -{ - // All other kinds of method headers are tightly coupled with the main method header - friend class ZapProfileData; - friend class ZapCodeMethodDescs; - friend class ZapColdCodeMap; - - friend class MethodCodeComparer; - - friend class ZapImage; - friend class ZapInfo; - - CORINFO_METHOD_HANDLE m_handle; - CORINFO_CLASS_HANDLE m_classHandle; - - ZapBlobWithRelocs * m_pCode; - ZapBlobWithRelocs * m_pColdCode; // May be NULL - - ZapUnwindInfo * m_pUnwindInfo; - ZapUnwindInfo * m_pColdUnwindInfo; // May be NULL - -#ifdef FEATURE_EH_FUNCLETS - ZapUnwindInfo * m_pUnwindInfoFragments; // Linked list of all unwind info fragments -#endif - - ZapBlobWithRelocs * m_pROData; // May be NULL - - ZapBlobWithRelocs * m_pProfileData; // May be NULL - - ZapGCInfo * m_pGCInfo; - ZapDebugInfo * m_pDebugInfo; - - union // May be NULL - { - ZapImport ** m_pFixupList; // Valid before place phase - ZapFixupInfo * m_pFixupInfo; // Valid after place phase - }; - - ZapExceptionInfo * m_pExceptionInfo; // May be NULL - - unsigned m_ProfilingDataFlags; - - unsigned m_compilationOrder; - unsigned m_cachedLayoutOrder; - - DWORD m_methodIndex; - - ZapMethodHeader() - { - } - -public: - CORINFO_METHOD_HANDLE GetHandle() - { - return m_handle; - } - - CORINFO_CLASS_HANDLE GetClassHandle() - { - return m_classHandle; - } - - DWORD GetMethodIndex() - { - return m_methodIndex; - } - - ZapBlobWithRelocs * GetCode() - { - return m_pCode; - } - - ZapBlobWithRelocs * GetColdCode() - { - return m_pColdCode; - } - - BOOL HasFixups() - { - return m_pFixupList != NULL; - } - - ZapNode * GetFixupList() - { - return m_pFixupInfo; - } - - ZapDebugInfo * GetDebugInfo() - { - return m_pDebugInfo; - } - - unsigned GetCompilationOrder() - { - return m_compilationOrder; - } - - unsigned GetCachedLayoutOrder() - { - return m_cachedLayoutOrder; - } - virtual ZapNodeType GetType() - { - return ZapNodeType_MethodHeader; - } - - // Iterate over as many of the methods called by this method - // as are easy to determine. Currently this is implemented - // by walking the Reloc list and so is only as complete as - // the current state of the Relocs. Note that the implementation - // ignores virtual calls and calls in the cold code section. - class PartialTargetMethodIterator - { - public: - PartialTargetMethodIterator(ZapMethodHeader* pMethod) - : m_pMethod(pMethod) - { - ZapBlobWithRelocs * pCode = pMethod->GetCode(); - m_pCurReloc = pCode ? pCode->GetRelocs() : NULL; - } - - BOOL GetNext(CORINFO_METHOD_HANDLE *pHnd); - - private: - ZapMethodHeader* m_pMethod; - ZapReloc* m_pCurReloc; - }; - -}; - -#if defined(TARGET_X86) -class ZapCodeBlob : public ZapBlobWithRelocs -{ -protected: - ZapCodeBlob(SIZE_T cbSize) - : ZapBlobWithRelocs(cbSize) - { - } - -public: - static ZapCodeBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); - - virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos); -}; -#else -typedef ZapBlobWithRelocs ZapCodeBlob; -#endif - -class ZapCodeMethodDescs : public ZapNode -{ - COUNT_T m_iStartMethod; - COUNT_T m_iEndMethod; - COUNT_T m_nUnwindInfos; - -public: - ZapCodeMethodDescs(COUNT_T startMethod, COUNT_T endMethod, COUNT_T nUnwindInfos) - : m_iStartMethod(startMethod), m_iEndMethod(endMethod), m_nUnwindInfos(nUnwindInfos) - { - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual DWORD GetSize() - { - return m_nUnwindInfos * sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_CodeManagerMap; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -//--------------------------------------------------------------------------------------- -// -// ZapMethodEntryPoint is special type of placeholder. Unlike normal placeholder, it -// carries extra CORINFO_ACCESS_FLAGS that is used to opt into the direct call even -// when it would not be otherwise possible. -// -class ZapMethodEntryPoint : public ZapNode -{ - CORINFO_METHOD_HANDLE m_handle; // Target method being called - BYTE m_accessFlags; // CORINFO_ACCESS_FLAGS - BYTE m_fUsed; // Entrypoint is used - needs to be resolved - - ZapNode *m_pEntryPoint; // only used for abstract methods to remember the precode - -public: - ZapMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) - : m_handle(handle), m_accessFlags(static_cast(accessFlags)) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_MethodEntryPoint; - } - - CORINFO_METHOD_HANDLE GetHandle() - { - return m_handle; - } - - CORINFO_ACCESS_FLAGS GetAccessFlags() - { - return (CORINFO_ACCESS_FLAGS)m_accessFlags; - } - - void SetIsUsed() - { - m_fUsed = true; - } - - BOOL IsUsed() - { - return m_fUsed; - } - - void Resolve(ZapImage * pImage); -}; - -class ZapMethodEntryPointTable -{ - struct MethodEntryPointKey - { - MethodEntryPointKey(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags) - : m_handle(handle), m_accessFlags(accessFlags) - { - } - - CORINFO_METHOD_HANDLE m_handle; // Target method being called - CORINFO_ACCESS_FLAGS m_accessFlags; - }; - - class MethodEntryPointTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef MethodEntryPointKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return MethodEntryPointKey(e->GetHandle(), e->GetAccessFlags()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1.m_handle == k2.m_handle) && (k1.m_accessFlags == k2.m_accessFlags); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k.m_handle ^ (count_t)k.m_accessFlags; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< MethodEntryPointTraits > MethodEntryPointTable; - - MethodEntryPointTable m_entries; - ZapImage * m_pImage; - -public: - ZapMethodEntryPointTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapMethodEntryPointTable::m_entries, 0.0018, cbILImage); - } - - ZapMethodEntryPoint * GetMethodEntryPoint(CORINFO_METHOD_HANDLE handle, CORINFO_ACCESS_FLAGS accessFlags); - - ZapNode * CanDirectCall(ZapMethodEntryPoint * pMethodEntryPoint, ZapMethodHeader * pCaller); - - void Resolve(); -}; - -//--------------------------------------------------------------------------------------- -// -// Zapping of unwind info -// -class ZapUnwindInfo : public ZapNode -{ - ZapNode * m_pCode; - - DWORD m_dwStartOffset; - DWORD m_dwEndOffset; - - ZapNode * m_pUnwindData; - - ZapUnwindInfo * m_pNextFragment; - -public: - ZapUnwindInfo(ZapNode * pCode, DWORD dwStartOffset, DWORD dwEndOffset, ZapNode * pUnwindData = NULL) - : m_pCode(pCode), - m_dwStartOffset(dwStartOffset), - m_dwEndOffset(dwEndOffset), - m_pUnwindData(pUnwindData) - { - } - - ZapNode * GetCode() - { - return m_pCode; - } - - DWORD GetStartOffset() - { - return m_dwStartOffset; - } - - DWORD GetEndOffset() - { - return m_dwEndOffset; - } - - DWORD GetStartAddress() - { - return m_pCode->GetRVA() + GetStartOffset(); - } - - DWORD GetEndAddress() - { - return m_pCode->GetRVA() + GetEndOffset(); - } - // Used to set unwind data lazily - void SetUnwindData(ZapNode * pUnwindData) - { - _ASSERTE(m_pUnwindData == NULL); - m_pUnwindData = pUnwindData; - } - - ZapNode * GetUnwindData() - { - return m_pUnwindData; - } - - void SetNextFragment(ZapUnwindInfo * pFragment) - { - _ASSERTE(m_pNextFragment == NULL); - m_pNextFragment = pFragment; - } - - ZapUnwindInfo * GetNextFragment() - { - return m_pNextFragment; - } - - virtual UINT GetAlignment() - { - return sizeof(ULONG); - } - - virtual DWORD GetSize() - { - return sizeof(T_RUNTIME_FUNCTION); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindInfo; - } - - virtual void Save(ZapWriter * pZapWriter); - - static int __cdecl CompareUnwindInfo(const void * a, const void * b); -}; - -#ifdef FEATURE_EH_FUNCLETS -//--------------------------------------------------------------------------------------- -// -// Zapping of unwind data -// -class ZapUnwindData : public ZapBlob -{ -public: - ZapUnwindData(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - - virtual UINT GetAlignment(); - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindData; - } - - BOOL IsFilterFunclet() - { - return GetType() == ZapNodeType_FilterFuncletUnwindData; - } - - ZapNode * GetPersonalityRoutine(ZapImage * pImage); - virtual void Save(ZapWriter * pZapWriter); - - static ZapUnwindData * NewUnwindData(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, BOOL fIsFilterFunclet); -}; - -class ZapFilterFuncletUnwindData : public ZapUnwindData -{ -public: - ZapFilterFuncletUnwindData(SIZE_T cbSize) - : ZapUnwindData(cbSize) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_FilterFuncletUnwindData; - } -}; -class ZapUnwindDataTable -{ - ZapImage * m_pImage; - - struct ZapUnwindDataKey - { - ZapUnwindDataKey(PVOID pUnwindData, SIZE_T cbUnwindData, BOOL fIsFilterFunclet) - : m_unwindData(pUnwindData, cbUnwindData), m_fIsFilterFunclet(fIsFilterFunclet) - { - } - - ZapBlob::SHashKey m_unwindData; - BOOL m_fIsFilterFunclet; - }; - - class ZapUnwindDataTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ZapUnwindDataKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return ZapUnwindDataKey(e->GetData(), e->GetBlobSize(), e->IsFilterFunclet()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Equals(k1.m_unwindData, k2.m_unwindData) && (k1.m_fIsFilterFunclet == k2.m_fIsFilterFunclet); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Hash(k.m_unwindData) ^ k.m_fIsFilterFunclet; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - // Hashtable with all unwind data blobs. If two methods have unwind data - // we store it just once. - SHash< ZapUnwindDataTraits > m_blobs; - -public: - ZapUnwindDataTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapUnwindDataTable::m_blobs, 0.0003, cbILImage); - } - - ZapUnwindData * GetUnwindData(PVOID pBlob, SIZE_T cbBlob, BOOL fIsFilterFunclet); -}; -#endif // FEATURE_EH_FUNCLETS - - -//--------------------------------------------------------------------------------------- -// -// Zapping of GC info -// -#ifdef FEATURE_EH_FUNCLETS -class ZapGCInfo : public ZapUnwindData -{ - DWORD m_cbGCInfo; - -public: - ZapGCInfo(SIZE_T cbGCInfo, SIZE_T cbUnwindInfo) - : ZapUnwindData(cbUnwindInfo), m_cbGCInfo((DWORD)cbGCInfo) - { - if (m_cbGCInfo > ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - } - - virtual PBYTE GetData() - { - return (PBYTE)(this + 1); - } - - PBYTE GetGCInfo() - { - return GetData() + GetUnwindInfoSize(); - } - - DWORD GetGCInfoSize() - { - return m_cbGCInfo; - } - - PBYTE GetUnwindInfo() - { - return GetData(); - } - - DWORD GetUnwindInfoSize() - { - return GetBlobSize(); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindDataAndGCInfo; - } - - virtual DWORD GetSize() - { - return ZapUnwindData::GetSize() + m_cbGCInfo; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapUnwindData::Save(pZapWriter); - - pZapWriter->Write(GetGCInfo(), GetGCInfoSize()); - } - - static ZapGCInfo * NewGCInfo(ZapWriter * pWriter, PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); -}; - -class ZapGCInfoTable -{ - ZapImage * m_pImage; - - struct GCInfoKey - { - GCInfoKey(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo) - : m_gcInfo(pGCInfo, cbGCInfo), m_unwindInfo(pUnwindInfo, cbUnwindInfo) - { - } - - ZapBlob::SHashKey m_gcInfo; - ZapBlob::SHashKey m_unwindInfo; - }; - - class GCInfoTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef GCInfoKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return GCInfoKey(e->GetGCInfo(), e->GetGCInfoSize(), e->GetUnwindInfo(), e->GetUnwindInfoSize()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Equals(k1.m_gcInfo, k2.m_gcInfo) && ZapBlob::SHashTraits::Equals(k1.m_unwindInfo, k2.m_unwindInfo); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return ZapBlob::SHashTraits::Hash(k.m_gcInfo) ^ ZapBlob::SHashTraits::Hash(k.m_unwindInfo); - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - // Hashtable with all GC info blobs. If two methods have same GC info - // we store it just once. - SHash< GCInfoTraits > m_blobs; - -public: - ZapGCInfoTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); - } - - // Returns interned instance of the GC info blob - ZapGCInfo * GetGCInfo(PVOID pGCInfo, SIZE_T cbGCInfo, PVOID pUnwindInfo, SIZE_T cbUnwindInfo); -}; -#else -class ZapGCInfoTable -{ - ZapImage * m_pImage; - - // Hashtable with all GC info blobs. If two methods have same GC info - // we store it just once. - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; - -public: - ZapGCInfoTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapGCInfoTable::m_blobs, 0.0021, cbILImage); - } - - // Returns interned instance of the GC info blob - ZapGCInfo * GetGCInfo(PVOID pBlob, SIZE_T cbBlob); -}; -#endif - -//--------------------------------------------------------------------------------------- -// -// Zapping of debug info for native code -// -class ZapDebugInfoTable : public ZapNode -{ - COUNT_T m_nCount; - ZapNode ** m_pTable; - - ZapImage * m_pImage; - - // Hashtable with all debug info blobs. If two methods have same debug info - // we store it just once. - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; - - class LabelledEntry : public ZapNode - { - public: - LabelledEntry * m_pNext; - ZapMethodHeader * m_pMethod; - - LabelledEntry(ZapMethodHeader * pMethod) - : m_pMethod(pMethod) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_DEBUG_LABELLED_ENTRY); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DebugInfoLabelledEntry; - } - - virtual void Save(ZapWriter * pZapWriter); - }; - -public: - ZapDebugInfoTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapDebugInfoTable::m_blobs, 0.0024, cbILImage); - } - - // Returns interned instance of the debug info blob - ZapDebugInfo * GetDebugInfo(PVOID pBlob, SIZE_T cbBlob); - - void PrepareLayout(); - void PlaceDebugInfo(ZapMethodHeader * pMethod); - void FinishLayout(); - - virtual DWORD GetSize() - { - return m_nCount * sizeof(CORCOMPILE_DEBUG_RID_ENTRY); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DebugInfoTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -//--------------------------------------------------------------------------------------- -// -// Zapping of IBC profile data collection area -// -class ZapProfileData : public ZapNode -{ - ZapMethodHeader * m_pMethod; - ZapProfileData * m_pNext; - -public: - ZapProfileData(ZapMethodHeader * pMethod) - : m_pMethod(pMethod) - { - } - - void SetNext(ZapProfileData * pNext) - { - m_pNext = pNext; - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_METHOD_PROFILE_LIST); - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ProfileData; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -// Zapping of ExceptionInfoTable -// ExceptionInfoTable is a lookup table that has 1 entry for each method with EH information. -// The table is sorted by method start address, so binary search is used during runtime to find -// the EH info for a given method given a method start address. -class ZapExceptionInfoLookupTable : public ZapNode -{ -private: - typedef struct - { - ZapNode* m_pCode; - ZapExceptionInfo* m_pExceptionInfo; - } ExceptionInfoEntry; - - SArray m_exceptionInfoEntries; - ZapImage* m_pImage; -public: - ZapExceptionInfoLookupTable(ZapImage *pImage); - - void PlaceExceptionInfoEntry(ZapNode* pCode, ZapExceptionInfo* pExceptionInfo); - - virtual ZapNodeType GetType() - { - return ZapNodeType_ExceptionInfoTable; - } - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - virtual DWORD GetSize(); - virtual void Save(ZapWriter* pZapWriter); -}; - - -class ZapUnwindInfoLookupTable : public ZapNode -{ - -public: - ZapUnwindInfoLookupTable(ZapVirtualSection * pRuntimeFunctionSection, ZapNode * pCodeSection, DWORD totalCodeSize): - m_pRuntimeFunctionSection(pRuntimeFunctionSection), m_pCodeSection(pCodeSection), m_TotalCodeSize(totalCodeSize) - { - } - - COUNT_T GetNumEntries() - { - return m_TotalCodeSize/RUNTIME_FUNCTION_LOOKUP_STRIDE + 1; - } - virtual ZapNodeType GetType() - { - return ZapNodeType_UnwindInfoLookupTable; - } - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - virtual DWORD GetSize(); - virtual void Save(ZapWriter* pZapWriter); - -private: - ZapVirtualSection * m_pRuntimeFunctionSection; - ZapNode * m_pCodeSection; - DWORD m_TotalCodeSize; -}; - -class ZapColdCodeMap : public ZapNode -{ -public: - ZapColdCodeMap(ZapVirtualSection * pRuntimeFunctionSection): - m_pRuntimeFunctionSection (pRuntimeFunctionSection) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ColdCodeMap; - } - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - virtual DWORD GetSize(); - virtual void Save(ZapWriter* pZapWriter); - -private: - ZapVirtualSection * m_pRuntimeFunctionSection; -}; - -// -//--------------------------------------------------------------------------------------- -// -// Jump thunk for JIT helper -// -#ifdef _DEBUG -const static PCSTR s_rgHelperNames[] = { -#define JITHELPER(code,pfnHelper,sig) #code , -#define DYNAMICJITHELPER(code,pfnHelper,sig) " " #code , -#include -}; -#endif // _DEBUG - -class ZapHelperThunk : public ZapNode -{ - DWORD m_dwHelper; - -public: - ZapHelperThunk(DWORD dwHelper) - : m_dwHelper(dwHelper) - { -#ifdef _DEBUG - static_assert_no_msg(COUNTOF(s_rgHelperNames) == CORINFO_HELP_COUNT); - LOG((LF_ZAP, LL_INFO1000000, "Created ZapHelperThunk for helper %3d (%s)\n", - (USHORT)m_dwHelper, s_rgHelperNames[(USHORT)m_dwHelper])); -#endif // _DEBUG - } - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_HelperThunk; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -class ZapLazyHelperThunk : public ZapNode -{ - CorInfoHelpFunc m_dwHelper; - - ZapNode * m_pArg; - ZapNode * m_pTarget; - - DWORD SaveWorker(ZapWriter * pZapWriter); - -public: - ZapLazyHelperThunk(CorInfoHelpFunc dwHelper) - : m_dwHelper(dwHelper) - { - } - - void Place(ZapImage * pImage); - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_LazyHelperThunk; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#endif // __ZAPCODE_H__ diff --git a/src/coreclr/zap/zapheaders.cpp b/src/coreclr/zap/zapheaders.cpp deleted file mode 100644 index f416e5a2884a9d..00000000000000 --- a/src/coreclr/zap/zapheaders.cpp +++ /dev/null @@ -1,720 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapHeaders.cpp -// - -// -// Zapping of headers (IMAGE_COR20_HEADER, CORCOMPILE_HEADER, etc.) -// -// ====================================================================================== - -#include "common.h" - -#include "zapheaders.h" - -#include "zapcode.h" -#include "zaprelocs.h" -#include "zapmetadata.h" -#include "zapimport.h" - -#include -#include - -// -// IMAGE_COR20_HEADER -// - -void ZapImage::SaveCorHeader() -{ - IMAGE_COR20_HEADER corHeader; - - ZeroMemory(&corHeader, sizeof(corHeader)); - - corHeader.cb = VAL32(sizeof(IMAGE_COR20_HEADER)); - corHeader.MajorRuntimeVersion = VAL16(COR_VERSION_MAJOR); - corHeader.MinorRuntimeVersion = VAL16(COR_VERSION_MINOR); - corHeader.Flags = VAL32(COMIMAGE_FLAGS_IL_LIBRARY); - -#ifdef TARGET_X86 - if (IsReadyToRunCompilation()) - { - // Mark the ready-to-run image as x86-specific - corHeader.Flags |= VAL32(COMIMAGE_FLAGS_32BITREQUIRED); - } -#endif - - if (m_ModuleDecoder.HasManagedEntryPoint()) - corHeader.EntryPointToken = VAL32(m_ModuleDecoder.GetEntryPointToken()); - - SetDirectoryData(&corHeader.ManagedNativeHeader, m_pNativeHeader); - SetDirectoryData(&corHeader.Resources, m_pResources); - SetDirectoryData(&corHeader.MetaData, m_pILMetaData); - - Write(&corHeader, sizeof(corHeader)); -} - -// -// CORCOMPILE_HEADER -// -void ZapImage::SaveNativeHeader() -{ - CORCOMPILE_HEADER nativeHeader; - - ZeroMemory(&nativeHeader, sizeof(nativeHeader)); - - nativeHeader.Signature = CORCOMPILE_SIGNATURE; - nativeHeader.MajorVersion = CORCOMPILE_MAJOR_VERSION; - nativeHeader.MinorVersion = CORCOMPILE_MINOR_VERSION; - - // - // Fill in data in native image header - // - - nativeHeader.ImageBase = (TADDR) GetNativeBaseAddress(); - - if (m_ModuleDecoder.HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_SECURITY)) - nativeHeader.Flags |= CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY; - - nativeHeader.COR20Flags = m_ModuleDecoder.GetCorHeader()->Flags; - -#ifdef CROSSGEN_COMPILE - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_CrossGenAssumeInputSigned)) - { - // Bug fix #814972 - // In buildlabs NI images are produced before binaries are strongname signed or authenticode signed. - // which results in crossgen'ed NI different on the user box vs. the one from build lab. - // Setting source IL authenticode signed and strong name bit for crossgen'ed images should make both the images identical. - nativeHeader.Flags |= CORCOMPILE_HEADER_HAS_SECURITY_DIRECTORY; - - if (m_ModuleDecoder.GetCorHeader()->StrongNameSignature.Size != 0) - nativeHeader.COR20Flags |= COMIMAGE_FLAGS_STRONGNAMESIGNED; - } -#endif - - if (m_ModuleDecoder.HasReadyToRunHeader()) - { - // Pretend that ready-to-run images are IL-only - nativeHeader.COR20Flags |= COMIMAGE_FLAGS_ILONLY; - - // Pretend that ready-to-run images do not have a native header - nativeHeader.COR20Flags &= ~COMIMAGE_FLAGS_IL_LIBRARY; - - // Remember whether the source IL image had ReadyToRun header - nativeHeader.Flags |= CORCOMPILE_HEADER_IS_READY_TO_RUN; - } - - if (m_fHaveProfileData) - nativeHeader.Flags |= CORCOMPILE_HEADER_IS_IBC_OPTIMIZED; - - DWORD dwPEKind, dwMachine; - m_ModuleDecoder.GetPEKindAndMachine(&dwPEKind, &dwMachine); - nativeHeader.PEKind = dwPEKind; - nativeHeader.Machine = (WORD)dwMachine; - - nativeHeader.Characteristics = m_ModuleDecoder.GetCharacteristics(); - - - SetDirectoryData(&nativeHeader.EEInfoTable, m_pEEInfoTable); - SetDirectoryData(&nativeHeader.HelperTable, m_pHelperTableSection); - SetDirectoryData(&nativeHeader.ImportSections, m_pImportSectionsTable); - SetDirectoryData(&nativeHeader.StubsData, m_pStubsSection); - SetDirectoryData(&nativeHeader.VersionInfo, m_pVersionInfo); - SetDirectoryData(&nativeHeader.Dependencies, m_pDependencies); - SetDirectoryData(&nativeHeader.DebugMap, m_pDebugInfoTable); - SetDirectoryData(&nativeHeader.VirtualSectionsTable, m_pVirtualSectionsTable); - SetDirectoryData(&nativeHeader.ModuleImage, m_pPreloadSections[CORCOMPILE_SECTION_MODULE]); - SetDirectoryData(&nativeHeader.CodeManagerTable, m_pCodeManagerEntry); - SetDirectoryData(&nativeHeader.ProfileDataList, m_pInstrumentSection); - SetDirectoryData(&nativeHeader.ManifestMetaData, m_pAssemblyMetaData); - - Write(&nativeHeader, sizeof(nativeHeader)); -} - -// -// CORCOMPILE_CODE_MANAGER_ENTRY -// -void ZapImage::SaveCodeManagerEntry() -{ - CORCOMPILE_CODE_MANAGER_ENTRY codeManagerEntry; - - ZeroMemory(&codeManagerEntry, sizeof(codeManagerEntry)); - - SetDirectoryData(&codeManagerEntry.HotCode, m_pHotCodeSection); - SetDirectoryData(&codeManagerEntry.Code, m_pCodeSection); - SetDirectoryData(&codeManagerEntry.ColdCode, m_pColdCodeSection); - - SetDirectoryData(&codeManagerEntry.ROData, m_pReadOnlyDataSection); - - // - //Initialize additional sections for diagnostics - // - - codeManagerEntry.HotIBCMethodOffset = (m_iIBCMethod < m_iUntrainedMethod && m_iIBCMethod < m_MethodCompilationOrder.GetCount()) ? - (m_MethodCompilationOrder[m_iIBCMethod]->GetCode()->GetRVA() - m_pHotCodeSection->GetRVA()) : m_pHotCodeSection->GetSize(); - - codeManagerEntry.HotGenericsMethodOffset = (m_iGenericsMethod < m_iUntrainedMethod && m_iGenericsMethod < m_MethodCompilationOrder.GetCount()) ? - (m_MethodCompilationOrder[m_iGenericsMethod]->GetCode()->GetRVA() - m_pHotCodeSection->GetRVA()) : m_pHotCodeSection->GetSize(); - - COUNT_T i; - for (i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapNode * pColdCode = m_MethodCompilationOrder[i]->GetColdCode(); - if (pColdCode != NULL) - { - codeManagerEntry.ColdUntrainedMethodOffset = pColdCode->GetRVA() - m_pColdCodeSection->GetRVA(); - break; - } - } - if (i == m_MethodCompilationOrder.GetCount()) - codeManagerEntry.ColdUntrainedMethodOffset = m_pColdCodeSection->GetSize(); - - - if (m_stats) - { -#define ACCUM_SIZE(dest, src) if( src != NULL ) dest+= src->GetSize() - // this is probably supposed to mean Hot+Unprofiled - ACCUM_SIZE(m_stats->m_totalHotCodeSize, m_pHotCodeSection); - ACCUM_SIZE(m_stats->m_totalUnprofiledCodeSize, m_pCodeSection); - ACCUM_SIZE(m_stats->m_totalColdCodeSize, m_pColdCodeSection); - ACCUM_SIZE(m_stats->m_totalCodeSizeInProfiledMethods, m_pHotCodeSection); -#undef ACCUM_SIZE - m_stats->m_totalColdCodeSizeInProfiledMethods = codeManagerEntry.ColdUntrainedMethodOffset; - } - - Write(&codeManagerEntry, sizeof(codeManagerEntry)); -} - -// -// Version Resource -// - -// Needed for RT_VERSION. -#define MAKEINTRESOURCE(v) MAKEINTRESOURCEW(v) - -void ZapWin32ResourceDirectory::Save(ZapWriter * pZapWriter) -{ - // - // The IMAGE_RESOURCE_DIRECTORY resource data structure is followed by a number of IMAGE_RESOURCE_DIRECTORY_ENTRY entries, which can either - // point to other resource directories (RVAs to other ZapWin32ResourceDirectory nodes), or point to actual resource data (RVAs to a number - // of IMAGE_RESOURCE_DATA_ENTRY entries that immediately follow the IMAGE_RESOURCE_DIRECTORY_ENTRY entries). - // - - // - // Sorting for resources is done in the following way accoring to the PE format specifications: - // 1) First, all the IMAGE_RESOURCE_DIRECTORY_ENTRY entries where the ID is a name string, sorted by names - // 2) Second, all the IMAGE_RESOURCE_DIRECTORY_ENTRY entries with non-string IDs, sorted by IDs. - // - struct ResourceSorter - { - bool operator() (DataOrSubDirectoryEntry& a, DataOrSubDirectoryEntry& b) - { - if (a.m_nameOrIdIsString && !b.m_nameOrIdIsString) - return true; - if (!a.m_nameOrIdIsString && b.m_nameOrIdIsString) - return false; - if (a.m_nameOrIdIsString) - return wcscmp(((ZapWin32ResourceString*)(a.m_pNameOrId))->GetString(), ((ZapWin32ResourceString*)(b.m_pNameOrId))->GetString()) < 0; - else - return a.m_pNameOrId < b.m_pNameOrId; - } - } resourceSorter; - std::sort(m_entries.begin(), m_entries.end(), resourceSorter); - - - IMAGE_RESOURCE_DIRECTORY directory; - ZeroMemory(&directory, sizeof(IMAGE_RESOURCE_DIRECTORY)); - - for (auto& entry : m_entries) - { - if (entry.m_nameOrIdIsString) - directory.NumberOfNamedEntries++; - else - directory.NumberOfIdEntries++; - } - pZapWriter->Write(&directory, sizeof(IMAGE_RESOURCE_DIRECTORY)); - - // Offsets are based from the beginning of the resources blob (see PE format documentation) - DWORD dataEntryRVA = this->GetRVA() - m_pWin32ResourceSection->GetRVA() - + sizeof(IMAGE_RESOURCE_DIRECTORY) + - (DWORD)m_entries.size() * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY); - - for (auto& entry : m_entries) - { - IMAGE_RESOURCE_DIRECTORY_ENTRY dirEntry; - ZeroMemory(&dirEntry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); - - if (entry.m_nameOrIdIsString) - { - // Offsets are based from the beginning of the resources blob (see PE format documentation) - dirEntry.NameOffset = ((ZapWin32ResourceString*)(entry.m_pNameOrId))->GetRVA() - m_pWin32ResourceSection->GetRVA(); - dirEntry.NameIsString = true; - } - else - { - _ASSERT(IS_INTRESOURCE(entry.m_pNameOrId)); - dirEntry.Id = (WORD)((ULONG_PTR)entry.m_pNameOrId & 0xffff); - } - - if (entry.m_dataIsSubDirectory) - { - // Offsets are based from the beginning of the resources blob (see PE format documentation) - dirEntry.OffsetToDirectory = entry.m_pDataOrSubDirectory->GetRVA() - m_pWin32ResourceSection->GetRVA(); - dirEntry.DataIsDirectory = true; - } - else - { - dirEntry.OffsetToData = dataEntryRVA; - dataEntryRVA += sizeof(IMAGE_RESOURCE_DATA_ENTRY); - } - - pZapWriter->Write(&dirEntry, sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY)); - } - - for (auto& entry : m_entries) - { - if (entry.m_dataIsSubDirectory) - continue; - - IMAGE_RESOURCE_DATA_ENTRY dataEntry; - ZeroMemory(&dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY)); - - dataEntry.OffsetToData = entry.m_pDataOrSubDirectory->GetRVA(); - dataEntry.Size = entry.m_pDataOrSubDirectory->GetSize(); - - pZapWriter->Write(&dataEntry, sizeof(IMAGE_RESOURCE_DATA_ENTRY)); - } -} - -void ZapImage::CopyWin32Resources() -{ -#ifdef FEATURE_PREJIT - if (!IsReadyToRunCompilation()) - { - // When compiling a fragile NGEN image, in order to avoid the risk of regression, only copy the RT_VERSION resource over so it - // is easy to see in the dumps where the ngened module came from. For R2R, we copy all resources (new behavior). - COUNT_T cbResourceData; - PVOID pResourceData = m_ModuleDecoder.GetWin32Resource(MAKEINTRESOURCE(1), RT_VERSION, &cbResourceData); - - if (!pResourceData || !cbResourceData) - return; - - ZapBlob * pVersionData = new (GetHeap()) ZapBlobPtr(pResourceData, cbResourceData); - - ZapWin32ResourceDirectory* pTypeDirectory = new (GetHeap()) ZapWin32ResourceDirectory(m_pWin32ResourceSection); - ZapWin32ResourceDirectory* pNameDirectory = new (GetHeap()) ZapWin32ResourceDirectory(m_pWin32ResourceSection); - ZapWin32ResourceDirectory* pLanguageDirectory = new (GetHeap()) ZapWin32ResourceDirectory(m_pWin32ResourceSection); - - pTypeDirectory->AddEntry(RT_VERSION, false, pNameDirectory, true); - pNameDirectory->AddEntry(MAKEINTRESOURCE(1), false, pLanguageDirectory, true); - pLanguageDirectory->AddEntry(MAKEINTRESOURCE(0), false, pVersionData, false); - - pTypeDirectory->PlaceNodeAndDependencies(m_pWin32ResourceSection); - - m_pWin32ResourceSection->Place(pVersionData); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE, m_pWin32ResourceSection); - - return; - } -#endif - - class ResourceEnumerationCallback - { - ZapImage* m_pZapImage; - PEDecoder* m_pModuleDecoder; - - std::vector m_dataEntries; - std::vector m_stringEntries; - - ZapWin32ResourceDirectory* m_pRootDirectory; - ZapWin32ResourceDirectory* m_pCurrentTypesDirectory; - ZapWin32ResourceDirectory* m_pCurrentNamesDirectory; - - bool AddResource(LPCWSTR lpszResourceName, LPCWSTR lpszResourceType, DWORD langID, BYTE* pResourceData, COUNT_T cbResourceData) - { - ZapBlob* pDataBlob = new (m_pZapImage->GetHeap()) ZapBlobPtr(pResourceData, cbResourceData); - m_dataEntries.push_back(pDataBlob); - - m_pCurrentNamesDirectory->AddEntry((PVOID)(ULONG_PTR)langID, false, pDataBlob, false); - - return true; - } - - ZapWin32ResourceDirectory* CreateResourceSubDirectory(ZapWin32ResourceDirectory* pRootDir, LPCWSTR pNameOrId) - { - bool nameIsString = !IS_INTRESOURCE(pNameOrId); - - PVOID pIdOrNameZapNode = (PVOID)pNameOrId; - if (nameIsString) - { - pIdOrNameZapNode = new (m_pZapImage->GetHeap()) ZapWin32ResourceString(pNameOrId); - m_stringEntries.push_back((ZapBlob*)pIdOrNameZapNode); - } - - ZapWin32ResourceDirectory* pResult = new (m_pZapImage->GetHeap()) ZapWin32ResourceDirectory(m_pZapImage->m_pWin32ResourceSection); - pRootDir->AddEntry(pIdOrNameZapNode, nameIsString, pResult, true); - - return pResult; - } - - public: - ResourceEnumerationCallback(PEDecoder* pModuleDecoder, ZapImage* pZapImage) - : m_pZapImage(pZapImage), m_pModuleDecoder(pModuleDecoder) - { - m_pRootDirectory = new (pZapImage->GetHeap()) ZapWin32ResourceDirectory(pZapImage->m_pWin32ResourceSection); - m_pCurrentTypesDirectory = m_pCurrentNamesDirectory = NULL; - } - - static bool EnumResourcesCallback(LPCWSTR lpszResourceName, LPCWSTR lpszResourceType, DWORD langID, BYTE* data, COUNT_T cbData, void *context) - { - ResourceEnumerationCallback* pCallback = (ResourceEnumerationCallback*)context; - // Third level in the enumeration: resources by langid for each name/type. - - // Note that this callback is not equivalent to the Windows enumeration apis as this api provides the resource data - // itself, and the resources are guaranteed to be present directly in the associated binary. This does not exactly - // match the Windows api, but it is exactly what we want when copying all resource data. - - return pCallback->AddResource(lpszResourceName, lpszResourceType, langID, data, cbData); - } - - static bool EnumResourceNamesCallback(LPCWSTR lpszResourceName, LPCWSTR lpszResourceType, void *context) - { - // Second level in the enumeration: resources by names for each resource type - - ResourceEnumerationCallback* pCallback = (ResourceEnumerationCallback*)context; - pCallback->m_pCurrentNamesDirectory = pCallback->CreateResourceSubDirectory(pCallback->m_pCurrentTypesDirectory, lpszResourceName); - - return pCallback->m_pModuleDecoder->EnumerateWin32Resources(lpszResourceName, lpszResourceType, ResourceEnumerationCallback::EnumResourcesCallback, context); - } - - static bool EnumResourceTypesCallback(LPCWSTR lpszType, void *context) - { - // First level in the enumeration: resources by types - - // Skip IBC resources - if (!IS_INTRESOURCE(lpszType) && (wcscmp(lpszType, W("IBC")) == 0)) - return true; - - ResourceEnumerationCallback* pCallback = (ResourceEnumerationCallback*)context; - pCallback->m_pCurrentTypesDirectory = pCallback->CreateResourceSubDirectory(pCallback->m_pRootDirectory, lpszType); - - return pCallback->m_pModuleDecoder->EnumerateWin32ResourceNames(lpszType, ResourceEnumerationCallback::EnumResourceNamesCallback, context); - } - - void PlaceResourceNodes(ZapVirtualSection* pWin32ResourceSection) - { - m_pRootDirectory->PlaceNodeAndDependencies(pWin32ResourceSection); - - // - // These strings are stored together after the last Resource Directory entry and before the first Resource Data entry. This - // minimizes the impact of these variable-length strings on the alignment of the fixed-size directory entries - // - for (auto& entry : m_stringEntries) - pWin32ResourceSection->Place(entry); - - for (auto& entry : m_dataEntries) - pWin32ResourceSection->Place(entry); - } - }; - - ResourceEnumerationCallback callbacks(&m_ModuleDecoder, this); - - HMODULE hModule = (HMODULE)dac_cast(m_ModuleDecoder.GetBase()); - - // - // Resources are binary-sorted tree structure. By convention, Windows uses three levels - // for resources: Type, Name, Language. To reduces the overall complexity, we'll copy and store resources in the - // "neutral" language only. - // - - if (!m_ModuleDecoder.EnumerateWin32ResourceTypes(ResourceEnumerationCallback::EnumResourceTypesCallback, &callbacks)) - { - ThrowHR(E_FAIL); - } - else - { - callbacks.PlaceResourceNodes(m_pWin32ResourceSection); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_RESOURCE, m_pWin32ResourceSection); - } -} -#undef MAKEINTRESOURCE - - -// -// Debug Directory -// - -void ZapDebugDirectory::SaveOriginalDebugDirectoryEntry(ZapWriter *pZapWriter) -{ - if (m_ppDebugData != nullptr) - { - for (DWORD i = 0; i < m_nDebugDirectory; i++) - { - if (m_ppDebugData[i] != nullptr) - { - m_pDebugDirectory[i].SizeOfData = m_ppDebugData[i]->GetSize(); - m_pDebugDirectory[i].AddressOfRawData = m_ppDebugData[i]->GetRVA(); - - // Compute the absolute file (seek) pointer. We need to reach to the matching physical section to do that. - ZapPhysicalSection * pPhysicalSection = ZapImage::GetImage(pZapWriter)->m_pTextSection; - - DWORD dwOffset = m_ppDebugData[i]->GetRVA() - pPhysicalSection->GetRVA(); - _ASSERTE(dwOffset < pPhysicalSection->GetSize()); - - m_pDebugDirectory[i].PointerToRawData = pPhysicalSection->GetFilePos() + dwOffset; - } - else - { - m_pDebugDirectory[i].SizeOfData = 0; - m_pDebugDirectory[i].AddressOfRawData = 0; - m_pDebugDirectory[i].PointerToRawData = 0; - } - } - - pZapWriter->Write(m_pDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY) * m_nDebugDirectory); - } -} - -void ZapDebugDirectory::SaveNGenDebugDirectoryEntry(ZapWriter *pZapWriter) -{ -#if !defined(NO_NGENPDB) - _ASSERTE(pZapWriter); - - IMAGE_DEBUG_DIRECTORY debugDirectory = {0}; - if (m_nDebugDirectory > 0) - { - memcpy(&debugDirectory, m_pDebugDirectory, sizeof(IMAGE_DEBUG_DIRECTORY)); - } - debugDirectory.Type = IMAGE_DEBUG_TYPE_CODEVIEW; - debugDirectory.SizeOfData = m_pNGenPdbDebugData->GetSize(); - debugDirectory.AddressOfRawData = m_pNGenPdbDebugData->GetRVA(); - // Make sure the "is portable pdb" indicator (MinorVersion == 0x504d) is clear - // for the NGen debug directory entry since this debug directory is copied - // from an existing entry which could be a portable pdb. - debugDirectory.MinorVersion = 0; - { - ZapPhysicalSection *pPhysicalSection = ZapImage::GetImage(pZapWriter)->m_pTextSection; - DWORD dwOffset = m_pNGenPdbDebugData->GetRVA() - pPhysicalSection->GetRVA(); - _ASSERTE(dwOffset < pPhysicalSection->GetSize()); - debugDirectory.PointerToRawData = pPhysicalSection->GetFilePos() + dwOffset; - } - pZapWriter->Write(&debugDirectory, sizeof(debugDirectory)); -#endif // NO_NGENPDB -} - -void ZapDebugDirectory::Save(ZapWriter * pZapWriter) -{ - _ASSERTE(pZapWriter); - - if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_NGenEnableCreatePdb)) { - SaveOriginalDebugDirectoryEntry(pZapWriter); - SaveNGenDebugDirectoryEntry(pZapWriter); - } else { - SaveNGenDebugDirectoryEntry(pZapWriter); - SaveOriginalDebugDirectoryEntry(pZapWriter); - } -} - -ZapPEExports::ZapPEExports(LPCWSTR dllPath) -{ - m_dllFileName = wcsrchr(dllPath, DIRECTORY_SEPARATOR_CHAR_W); - if (m_dllFileName != NULL) - m_dllFileName++; - else - m_dllFileName = dllPath; -} - -DWORD ZapPEExports::GetSize() -{ - return DWORD(sizeof(IMAGE_EXPORT_DIRECTORY) + wcslen(m_dllFileName) * sizeof(BYTE) + 1); -} - -void ZapPEExports::Save(ZapWriter * pZapWriter) -{ - _ASSERTE(pZapWriter); - - IMAGE_EXPORT_DIRECTORY exports; - ZeroMemory(&exports, sizeof(exports)); - - exports.Name = pZapWriter->GetCurrentRVA() + sizeof(exports); - - // Write out exports header - pZapWriter->Write(&exports, sizeof(exports)); - - // Write out string that exports.Name points at. - for (LPCWSTR ptr = m_dllFileName; ; ptr++) - { - pZapWriter->Write((PVOID) ptr, 1); - if (*ptr == 0) - break; - } -} - -// If the IL image has IMAGE_DIRECTORY_ENTRY_DEBUG with information about the PDB, -// copy that information over to the ngen image. -// This lets the debugger find out information about the PDB without loading -// the IL image. -// Note that we support using ngen images (from the GAC) without -// loading the ngen image. So not only is this a perf optimization for the debugger -// scenario, but it is also needed for dump-debugging where loading the IL -// is not an option. - -void ZapImage::CopyDebugDirEntry() -{ - // Insert an NGEN PDB debug directory entry *before* the IL PDB debug directory entry - // (if one exists), so that we don't break tools that look for an IL PDB. - { - // This entry is initially empty. It is filled in ZapImage::GenerateFile. - RSDS rsds = {0}; - m_pNGenPdbDebugData = ZapBlob::NewBlob(static_cast(this), &rsds, sizeof rsds); - } - - // IL PDB entry: copy of the (first of possibly many) IMAGE_DEBUG_DIRECTORY entry - // in the IL image - DWORD nDebugEntry = 0; - PIMAGE_DEBUG_DIRECTORY pDebugDir = NULL; - ZapNode **ppDebugData = NULL; - - if (m_ModuleDecoder.HasDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG)) { - COUNT_T debugEntrySize; - TADDR pDebugEntry = m_ModuleDecoder.GetDirectoryEntryData(IMAGE_DIRECTORY_ENTRY_DEBUG, &debugEntrySize); - - if (debugEntrySize != 0) { - - if (debugEntrySize < sizeof(IMAGE_DEBUG_DIRECTORY) || 0 != (debugEntrySize % sizeof(IMAGE_DEBUG_DIRECTORY))) { - m_zapper->Warning(W("IMAGE_DIRECTORY_ENTRY_DEBUG size (%d) should be a multiple of %d\n"), - debugEntrySize, sizeof(IMAGE_DEBUG_DIRECTORY)); - } else { - - // Since pDebugEntry is an array of IMAGE_DEBUG_DIRECTORYs, debugEntrySize - // should be a multiple of sizeof(IMAGE_DEBUG_DIRECTORY). - _ASSERTE(0 == (debugEntrySize % sizeof(IMAGE_DEBUG_DIRECTORY))); - - nDebugEntry = DWORD(debugEntrySize / sizeof(IMAGE_DEBUG_DIRECTORY)); - pDebugDir = new (GetHeap()) IMAGE_DEBUG_DIRECTORY[nDebugEntry]; - memcpy(pDebugDir, (const void *)pDebugEntry, sizeof(IMAGE_DEBUG_DIRECTORY) * nDebugEntry); - ppDebugData = new (GetHeap()) ZapNode*[nDebugEntry]; - memset(ppDebugData, 0, nDebugEntry * sizeof(ZapNode*)); - - for (DWORD i = 0; i < nDebugEntry; i++) - { - // Some compilers set PointerToRawData but not AddressOfRawData as they put the - // data at the end of the file in an unmapped part of the file - - RVA rvaOfRawData = (pDebugDir[i].AddressOfRawData != NULL) - ? pDebugDir[i].AddressOfRawData : m_ModuleDecoder.OffsetToRva(pDebugDir[i].PointerToRawData); - - ULONG cbDebugData = pDebugDir[i].SizeOfData; - - if (cbDebugData != 0) { - if (!m_ModuleDecoder.CheckRva(rvaOfRawData, cbDebugData)) - m_zapper->Warning(W("IMAGE_DIRECTORY_ENTRY_DEBUG points to bad data\n")); - else - ppDebugData[i] = new (GetHeap()) ZapBlobPtr((PVOID)m_ModuleDecoder.GetRvaData(rvaOfRawData), cbDebugData); - } - } - } - } - } - - ZapDebugDirectory * pDebugDirectory = new (GetHeap()) ZapDebugDirectory(m_pNGenPdbDebugData, - nDebugEntry, - pDebugDir, - ppDebugData); - - m_pDebugSection->Place(pDebugDirectory); - m_pDebugSection->Place(m_pNGenPdbDebugData); - if (ppDebugData) - { - for (DWORD i = 0; i < nDebugEntry; i++) - { - if (ppDebugData[i] != nullptr) - m_pDebugSection->Place(ppDebugData[i]); - } - } - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_DEBUG, pDebugDirectory); -} - -DWORD ZapVirtualSectionsTable::GetSize() -{ - DWORD nSectionInfos = 0; - - COUNT_T nPhysicalSections = m_pImage->GetPhysicalSectionCount(); - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < nPhysicalSections; iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_pImage->GetPhysicalSection(iPhysicalSection); - - DWORD dwPreviousType = 0; - - COUNT_T nVirtualSections = pPhysicalSection->GetVirtualSectionCount(); - for (COUNT_T iVirtualSection = 0; iVirtualSection < nVirtualSections; iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->GetVirtualSection(iVirtualSection); - - if (pVirtualSection->GetNodeCount() == 0) - continue; - - DWORD dwSectionType = pVirtualSection->GetSectionType(); - if (dwSectionType == 0) - continue; - - // Fold sections with the same type together - if (dwPreviousType != dwSectionType) - { - dwPreviousType = dwSectionType; - nSectionInfos++; - } - } - } - - return nSectionInfos * sizeof(CORCOMPILE_VIRTUAL_SECTION_INFO); -} - -void ZapVirtualSectionsTable::Save(ZapWriter * pZapWriter) -{ - COUNT_T nPhysicalSections = m_pImage->GetPhysicalSectionCount(); - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < nPhysicalSections; iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_pImage->GetPhysicalSection(iPhysicalSection); - - CORCOMPILE_VIRTUAL_SECTION_INFO sectionInfo; - - sectionInfo.SectionType = 0; - - COUNT_T nVirtualSections = pPhysicalSection->GetVirtualSectionCount(); - for (COUNT_T iVirtualSection = 0; iVirtualSection < nVirtualSections; iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->GetVirtualSection(iVirtualSection); - - if (pVirtualSection->GetNodeCount() == 0) - continue; - - DWORD dwSectionType = pVirtualSection->GetSectionType(); - if (dwSectionType == 0) - continue; - - // Fold sections with the same type together - if (sectionInfo.SectionType != dwSectionType) - { - if (sectionInfo.SectionType != 0) - { - pZapWriter->Write(§ionInfo, sizeof(sectionInfo)); - } - - sectionInfo.SectionType = dwSectionType; - sectionInfo.VirtualAddress = pVirtualSection->GetRVA(); - } - - // Update section size - sectionInfo.Size = (pVirtualSection->GetRVA() + pVirtualSection->GetSize()) - sectionInfo.VirtualAddress; - } - - if (sectionInfo.SectionType != 0) - { - pZapWriter->Write(§ionInfo, sizeof(sectionInfo)); - } - } -} diff --git a/src/coreclr/zap/zapheaders.h b/src/coreclr/zap/zapheaders.h deleted file mode 100644 index 0e27132b731da6..00000000000000 --- a/src/coreclr/zap/zapheaders.h +++ /dev/null @@ -1,402 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapHeaders.h -// - -// -// Zapping of headers (IMAGE_COR20_HEADER, CORCOMPILE_HEADER, etc.) -// -// ====================================================================================== - -#ifndef __ZAPHEADERS_H__ -#define __ZAPHEADERS_H__ - -#include - -// -// IMAGE_COR20_HEADER -// - -class ZapCorHeader : public ZapNode -{ -public: - ZapCorHeader(ZapImage * pImage) - { - } - - virtual DWORD GetSize() - { - return sizeof(IMAGE_COR20_HEADER); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_CorHeader; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage::GetImage(pZapWriter)->SaveCorHeader(); - } -}; - -// -// CORCOMPILE_HEADER -// - -class ZapNativeHeader : public ZapNode -{ -public: - ZapNativeHeader(ZapImage * pImage) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_HEADER); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_NativeHeader; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage::GetImage(pZapWriter)->SaveNativeHeader(); - } -}; - -// -// CORCOMPILE_VERSION_INFO -// -class ZapVersionInfo : public ZapNode -{ - CORCOMPILE_VERSION_INFO m_versionInfo; - -public: - ZapVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo) - { - memcpy(&m_versionInfo, pVersionInfo, sizeof(m_versionInfo)); - } - - CORCOMPILE_VERSION_INFO * GetData() - { - return &m_versionInfo; - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_VERSION_INFO); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_VersionInfo; - } - - virtual void Save(ZapWriter * pZapWriter) - { - pZapWriter->Write(&m_versionInfo, sizeof(m_versionInfo)); - } -}; - -// -// CORCOMPILE_CORCOMPILE_DEPENDENCY -// -class ZapDependencies : public ZapNode -{ - DWORD m_cDependencies; - CORCOMPILE_DEPENDENCY * m_pDependencies; - -public: - ZapDependencies(CORCOMPILE_DEPENDENCY * pDependencies, DWORD cDependencies) - : m_cDependencies(cDependencies), m_pDependencies(pDependencies) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_DEPENDENCY) * m_cDependencies; - } - - virtual UINT GetAlignment() - { - return sizeof(ULARGE_INTEGER); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Dependencies; - } - - virtual void Save(ZapWriter * pZapWriter) - { - pZapWriter->Write(m_pDependencies, sizeof(CORCOMPILE_DEPENDENCY) * m_cDependencies); - } -}; - -// -// CORCOMPILE_CODE_MANAGER_ENTRY -// - -class ZapCodeManagerEntry : public ZapNode -{ -public: - ZapCodeManagerEntry(ZapImage * pImage) - { - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_CODE_MANAGER_ENTRY); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_CodeManagerEntry; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage::GetImage(pZapWriter)->SaveCodeManagerEntry(); - } -}; - -// -// Win32 Resources -// - -class ZapWin32ResourceString : public ZapNode -{ - // - // This ZapNode maps the IMAGE_RESOURCE_DIR_STRING_U resource data structure for storing strings. - // - - LPWSTR m_pString; - -public: - ZapWin32ResourceString(LPCWSTR pString) - { - size_t strLen = wcslen(pString); - _ASSERT(pString != NULL && strLen < 0xffff); - - m_pString = new WCHAR[strLen + 1]; - wcscpy(m_pString, pString); - m_pString[strLen] = L'\0'; - } - - ~ZapWin32ResourceString() - { - delete[] m_pString; - } - - LPCWSTR GetString() { return m_pString; } - - virtual DWORD GetSize() - { - return sizeof(WORD) + sizeof(WCHAR) * (DWORD)wcslen(m_pString); - } - - virtual UINT GetAlignment() - { - return sizeof(WORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Blob; - } - - virtual void Save(ZapWriter * pZapWriter) - { - WORD size = (WORD)wcslen(m_pString); - pZapWriter->Write(&size, sizeof(WORD)); - pZapWriter->Write((PVOID)m_pString, sizeof(WCHAR) * size); - } -}; - -class ZapWin32ResourceDirectory : public ZapNode -{ - // - // This ZapNode maps the IMAGE_RESOURCE_DIRECTORY resource data structure for storing a resource directory. Each directory - // is then followed by a number of IMAGE_RESOURCE_DIRECTORY_ENTRY entries, which can either point to other resource directories (RVAs - // to other ZapWin32ResourceDirectory nodes), or point to actual resource data (RVAs to a number of IMAGE_RESOURCE_DATA_ENTRY entries - // that immediately follow the IMAGE_RESOURCE_DIRECTORY_ENTRY entries). - // - // Refer to the PE resources format for more information (https://docs.microsoft.com/en-us/windows/desktop/debug/pe-format#the-rsrc-section) - // - - struct DataOrSubDirectoryEntry - { - PVOID m_pNameOrId; - bool m_nameOrIdIsString; - ZapNode* m_pDataOrSubDirectory; - bool m_dataIsSubDirectory; - }; - std::vector m_entries; - ZapVirtualSection* m_pWin32ResourceSection; - -public: - ZapWin32ResourceDirectory(ZapVirtualSection* pWin32ResourceSection) - : m_pWin32ResourceSection(pWin32ResourceSection) - { } - - void AddEntry(PVOID pNameOrId, bool nameOrIdIsString, ZapNode* pDataOrSubDirectory, bool dataIsSubDirectory) - { - DataOrSubDirectoryEntry entry; - entry.m_pDataOrSubDirectory = pDataOrSubDirectory; - entry.m_dataIsSubDirectory = dataIsSubDirectory; - entry.m_pNameOrId = pNameOrId; - entry.m_nameOrIdIsString = nameOrIdIsString; - - m_entries.push_back(entry); - } - - virtual DWORD GetSize() - { - DWORD size = sizeof(IMAGE_RESOURCE_DIRECTORY) + (DWORD)m_entries.size() * sizeof(IMAGE_RESOURCE_DIRECTORY_ENTRY); - for (auto& entry : m_entries) - { - if (!entry.m_dataIsSubDirectory) - size += sizeof(IMAGE_RESOURCE_DATA_ENTRY); - } - return size; - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Win32Resources; - } - - void PlaceNodeAndDependencies(ZapVirtualSection* pWin32ResourceSection) - { - pWin32ResourceSection->Place(this); - - for (auto& entry : m_entries) - { - if (entry.m_dataIsSubDirectory) - { - ZapWin32ResourceDirectory* pSubDirNode = (ZapWin32ResourceDirectory*)entry.m_pDataOrSubDirectory; - pSubDirNode->PlaceNodeAndDependencies(pWin32ResourceSection); - } - } - } - - virtual void Save(ZapWriter * pZapWriter); -}; - - -// -// Debug Directory -// - -class ZapDebugDirectory : public ZapNode -{ - ZapNode * m_pNGenPdbDebugData; - DWORD m_nDebugDirectory; - IMAGE_DEBUG_DIRECTORY * m_pDebugDirectory; - ZapNode ** m_ppDebugData; - -public: - ZapDebugDirectory(ZapNode *pNGenPdbDebugData, DWORD nDebugDirectory, PIMAGE_DEBUG_DIRECTORY pDebugDirectory, ZapNode ** ppDebugData) - : m_pNGenPdbDebugData(pNGenPdbDebugData), - m_nDebugDirectory(nDebugDirectory), - m_pDebugDirectory(pDebugDirectory), - m_ppDebugData(ppDebugData) - { - } - - virtual DWORD GetSize() - { -#if defined(NO_NGENPDB) - return sizeof(IMAGE_DEBUG_DIRECTORY) * m_nDebugDirectory; -#else - // Add one for NGen PDB debug directory entry - return sizeof(IMAGE_DEBUG_DIRECTORY) * (m_nDebugDirectory + 1); -#endif // NO_NGENPDB - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DebugDirectory; - } - - void SaveOriginalDebugDirectoryEntry(ZapWriter *pZapWriter); - void SaveNGenDebugDirectoryEntry(ZapWriter *pZapWriter); - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// PE Style exports. Currently can only save an empty list of exports -// but this is useful because it avoids the DLL being seen as Resource Only -// (which then causes SymServer to avoid copying its PDB to the cloud). -// - -class ZapPEExports : public ZapNode -{ - LPCWSTR m_dllFileName; // Just he DLL name without the path. - -public: - ZapPEExports(LPCWSTR dllPath); - virtual DWORD GetSize(); - virtual UINT GetAlignment() { return sizeof(DWORD); } - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// List of all sections for diagnostic purposes - -class ZapVirtualSectionsTable : public ZapNode -{ - ZapImage * m_pImage; - -public: - - ZapVirtualSectionsTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_VirtualSectionsTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#endif // __ZAPHEADERS_H__ diff --git a/src/coreclr/zap/zapimage.cpp b/src/coreclr/zap/zapimage.cpp deleted file mode 100644 index 693921963d84a4..00000000000000 --- a/src/coreclr/zap/zapimage.cpp +++ /dev/null @@ -1,3764 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImage.cpp -// - -// -// NGEN-specific infrastructure for writing PE files. -// -// ====================================================================================== - -#include "common.h" -#include "strsafe.h" - -#include "zaprelocs.h" - -#include "zapinnerptr.h" -#include "zapwrapper.h" - -#include "zapheaders.h" -#include "zapmetadata.h" -#include "zapcode.h" -#include "zapimport.h" - -#ifdef FEATURE_READYTORUN_COMPILER -#include "zapreadytorun.h" -#endif - -#include "md5.h" - -// This is RTL_CONTAINS_FIELD from ntdef.h -#define CONTAINS_FIELD(Struct, Size, Field) \ - ( (((PCHAR)(&(Struct)->Field)) + sizeof((Struct)->Field)) <= (((PCHAR)(Struct))+(Size)) ) - -/* --------------------------------------------------------------------------- * - * Destructor wrapper objects - * --------------------------------------------------------------------------- */ - -ZapImage::ZapImage(Zapper *zapper) - : m_zapper(zapper), - m_stats(new ZapperStats()) - /* Everything else is initialized to 0 by default */ -{ -} - -ZapImage::~ZapImage() -{ -#ifdef ZAP_HASHTABLE_TUNING - // If ZAP_HASHTABLE_TUNING is defined, preallocate is overloaded to print the tuning constants - Preallocate(); -#endif - - // - // Clean up. - // - if (m_stats != NULL) - delete m_stats; - - if (m_pModuleFileName != NULL) - delete [] m_pModuleFileName; - - if (m_pMDImport != NULL) - m_pMDImport->Release(); - - if (m_pAssemblyEmit != NULL) - m_pAssemblyEmit->Release(); - - if (m_profileDataFile != NULL) - UnmapViewOfFile(m_profileDataFile); - - if (m_pPreloader) - m_pPreloader->Release(); - - if (m_pImportSectionsTable != NULL) - m_pImportSectionsTable->~ZapImportSectionsTable(); - - if (m_pGCInfoTable != NULL) - m_pGCInfoTable->~ZapGCInfoTable(); - -#ifdef FEATURE_EH_FUNCLETS - if (m_pUnwindDataTable != NULL) - m_pUnwindDataTable->~ZapUnwindDataTable(); -#endif - - if (m_pStubDispatchDataTable != NULL) - m_pStubDispatchDataTable->~ZapImportSectionSignatures(); - - if (m_pExternalMethodDataTable != NULL) - m_pExternalMethodDataTable->~ZapImportSectionSignatures(); - - if (m_pDynamicHelperDataTable != NULL) - m_pDynamicHelperDataTable->~ZapImportSectionSignatures(); - - if (m_pDebugInfoTable != NULL) - m_pDebugInfoTable->~ZapDebugInfoTable(); - - if (m_pVirtualSectionsTable != NULL) - m_pVirtualSectionsTable->~ZapVirtualSectionsTable(); - - if (m_pILMetaData != NULL) - m_pILMetaData->~ZapILMetaData(); - - if (m_pBaseRelocs != NULL) - m_pBaseRelocs->~ZapBaseRelocs(); - - if (m_pAssemblyMetaData != NULL) - m_pAssemblyMetaData->~ZapMetaData(); - - // - // Destruction of auxiliary tables in alphabetical order - // - - if (m_pImportTable != NULL) - m_pImportTable->~ZapImportTable(); - - if (m_pInnerPtrs != NULL) - m_pInnerPtrs->~ZapInnerPtrTable(); - - if (m_pMethodEntryPoints != NULL) - m_pMethodEntryPoints->~ZapMethodEntryPointTable(); - - if (m_pWrappers != NULL) - m_pWrappers->~ZapWrapperTable(); -} - -void ZapImage::InitializeSections() -{ - AllocateVirtualSections(); - - m_pCorHeader = new (GetHeap()) ZapCorHeader(this); - m_pHeaderSection->Place(m_pCorHeader); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER, m_pCorHeader); - - m_pNativeHeader = new (GetHeap()) ZapNativeHeader(this); - m_pHeaderSection->Place(m_pNativeHeader); - - m_pCodeManagerEntry = new (GetHeap()) ZapCodeManagerEntry(this); - m_pHeaderSection->Place(m_pCodeManagerEntry); - - m_pImportSectionsTable = new (GetHeap()) ZapImportSectionsTable(this); - m_pImportTableSection->Place(m_pImportSectionsTable); - - m_pExternalMethodDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pExternalMethodThunkSection, m_pGCSection); - m_pExternalMethodDataSection->Place(m_pExternalMethodDataTable); - - m_pStubDispatchDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pStubDispatchCellSection, m_pGCSection); - m_pStubDispatchDataSection->Place(m_pStubDispatchDataTable); - - m_pImportTable = new (GetHeap()) ZapImportTable(this); - - m_pGCInfoTable = new (GetHeap()) ZapGCInfoTable(this); - m_pExceptionInfoLookupTable = new (GetHeap()) ZapExceptionInfoLookupTable(this); - -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindDataTable = new (GetHeap()) ZapUnwindDataTable(this); -#endif - - m_pEEInfoTable = ZapBlob::NewAlignedBlob(this, NULL, sizeof(CORCOMPILE_EE_INFO_TABLE), TARGET_POINTER_SIZE); - m_pEETableSection->Place(m_pEEInfoTable); - - // - // Allocate Helper table, and fill it out - // - - m_pHelperThunks = new (GetHeap()) ZapNode * [CORINFO_HELP_COUNT]; - - m_pILMetaData = new (GetHeap()) ZapILMetaData(this); - m_pILMetaDataSection->Place(m_pILMetaData); - - m_pDebugInfoTable = new (GetHeap()) ZapDebugInfoTable(this); - m_pDebugSection->Place(m_pDebugInfoTable); - - m_pBaseRelocs = new (GetHeap()) ZapBaseRelocs(this); - m_pBaseRelocsSection->Place(m_pBaseRelocs); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_BASERELOC, m_pBaseRelocsSection); - - // - // Initialization of auxiliary tables in alphabetical order - // - m_pInnerPtrs = new (GetHeap()) ZapInnerPtrTable(this); - m_pMethodEntryPoints = new (GetHeap()) ZapMethodEntryPointTable(this); - m_pWrappers = new (GetHeap()) ZapWrapperTable(this); - - // Place the virtual sections tables in debug section. It exists for diagnostic purposes - // only and should not be touched under normal circumstances - m_pVirtualSectionsTable = new (GetHeap()) ZapVirtualSectionsTable(this); - m_pDebugSection->Place(m_pVirtualSectionsTable); - -#ifndef ZAP_HASHTABLE_TUNING - Preallocate(); -#endif -} - -#ifdef FEATURE_READYTORUN_COMPILER -void ZapImage::InitializeSectionsForReadyToRun() -{ - AllocateVirtualSections(); - - // Preload sections are not used for ready to run. Clear the pointers to them to catch accidental use. - for (int i = 0; i < CORCOMPILE_SECTION_COUNT; i++) - m_pPreloadSections[i] = NULL; - - m_pCorHeader = new (GetHeap()) ZapCorHeader(this); - m_pHeaderSection->Place(m_pCorHeader); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_COMHEADER, m_pCorHeader); - - m_pNativeHeader = new (GetHeap()) ZapReadyToRunHeader(this); - m_pHeaderSection->Place(m_pNativeHeader); - - m_pImportSectionsTable = new (GetHeap()) ZapImportSectionsTable(this); - m_pHeaderSection->Place(m_pImportSectionsTable); - - { -#define COMPILER_NAME "CoreCLR" - - const char* pCompilerIdentifier = COMPILER_NAME " " VER_FILEVERSION_STR; - ZapBlob * pCompilerIdentifierBlob = new (GetHeap()) ZapBlobPtr((PVOID)pCompilerIdentifier, strlen(pCompilerIdentifier) + 1); - - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::CompilerIdentifier, pCompilerIdentifierBlob); - m_pHeaderSection->Place(pCompilerIdentifierBlob); - } - - m_pImportTable = new (GetHeap()) ZapImportTable(this); - - for (int i=0; iPlace(m_pDelayLoadInfoDataTable[i]); - } - - m_pDynamicHelperDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pDynamicHelperCellSection); - m_pDynamicHelperDataSection->Place(m_pDynamicHelperDataTable); - - m_pExternalMethodDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pExternalMethodCellSection, m_pGCSection); - m_pExternalMethodDataSection->Place(m_pExternalMethodDataTable); - - m_pStubDispatchDataTable = new (GetHeap()) ZapImportSectionSignatures(this, m_pStubDispatchCellSection, m_pGCSection); - m_pStubDispatchDataSection->Place(m_pStubDispatchDataTable); - - m_pGCInfoTable = new (GetHeap()) ZapGCInfoTable(this); - -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindDataTable = new (GetHeap()) ZapUnwindDataTable(this); -#endif - - m_pILMetaData = new (GetHeap()) ZapILMetaData(this); - m_pILMetaDataSection->Place(m_pILMetaData); - - m_pBaseRelocs = new (GetHeap()) ZapBaseRelocs(this); - m_pBaseRelocsSection->Place(m_pBaseRelocs); - - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_BASERELOC, m_pBaseRelocsSection); - - // - // Initialization of auxiliary tables in alphabetical order - // - m_pInnerPtrs = new (GetHeap()) ZapInnerPtrTable(this); - - m_pExceptionInfoLookupTable = new (GetHeap()) ZapExceptionInfoLookupTable(this); - - // - // Always allocate slot for module - it is used to determine that the image is used - // - m_pImportTable->GetPlacedHelperImport(READYTORUN_HELPER_Module); - - // - // Make sure the import sections table is in the image, so we can find the slot for module - // - _ASSERTE(m_pImportSectionsTable->GetSize() != 0); - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::ImportSections, m_pImportSectionsTable); -} -#endif // FEATURE_READYTORUN_COMPILER - - -#define DATA_MEM_READONLY IMAGE_SCN_MEM_READ -#define DATA_MEM_WRITABLE IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE -#define XDATA_MEM IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ | IMAGE_SCN_MEM_WRITE -#define TEXT_MEM IMAGE_SCN_MEM_EXECUTE | IMAGE_SCN_MEM_READ - -void ZapImage::AllocateVirtualSections() -{ - // - // Allocate all virtual sections in the order they will appear in the final image - // - // To maximize packing of the data in the native image, the number of named physical sections is minimized - - // the named physical sections are used just for memory protection control. All items with the same memory - // protection are packed together in one physical section. - // - - { - // - // .data section - // - DWORD access = DATA_MEM_WRITABLE; - - ZapPhysicalSection * pDataSection = NewPhysicalSection(".data", IMAGE_SCN_CNT_INITIALIZED_DATA | access); - - m_pPreloadSections[CORCOMPILE_SECTION_MODULE] = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | ModuleSection); - - m_pEETableSection = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | EETableSection); // Could be marked bss if it makes sense - - // These are all known to be hot or writeable - m_pPreloadSections[CORCOMPILE_SECTION_WRITE] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | WriteDataSection); - m_pPreloadSections[CORCOMPILE_SECTION_HOT_WRITEABLE] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | WriteableDataSection); // hot for reading, potentially written to - m_pPreloadSections[CORCOMPILE_SECTION_WRITEABLE] = NewVirtualSection(pDataSection, IBCProfiledSection | ColdRange | WriteableDataSection); // Cold based on IBC profiling data. - m_pPreloadSections[CORCOMPILE_SECTION_HOT] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | DataSection); - - m_pPreloadSections[CORCOMPILE_SECTION_RVA_STATICS_HOT] = NewVirtualSection(pDataSection, IBCProfiledSection | HotRange | RVAStaticsSection); - - m_pDelayLoadInfoTableSection[ZapImportSectionType_Eager] = NewVirtualSection(pDataSection, IBCUnProfiledSection | HotRange | DelayLoadInfoTableEagerSection, TARGET_POINTER_SIZE); - - // - // Allocate dynamic info tables - // - - // Place the HOT CorCompileTables now, the cold ones would be placed later in this routine (after other HOT sections) - for (int i=0; im_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - { - m_pInstrumentSection = NewVirtualSection(pDataSection, IBCUnProfiledSection | ColdRange | InstrumentSection, TARGET_POINTER_SIZE); - } - } - - // No RWX pages in ready to run images - if (!IsReadyToRunCompilation()) - { - DWORD access = XDATA_MEM; - - // - // .xdata section - // - ZapPhysicalSection * pXDataSection = NewPhysicalSection(".xdata", IMAGE_SCN_CNT_INITIALIZED_DATA | access); - - // Some sections are placed in a sorted order. Hot items are placed first, - // then cold items. These sections are marked as HotColdSortedRange since - // they are neither completely hot, nor completely cold. - m_pVirtualImportThunkSection = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange | VirtualImportThunkSection, HELPER_TABLE_ALIGN); - m_pExternalMethodThunkSection = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodThunkSection, HELPER_TABLE_ALIGN); - m_pHelperTableSection = NewVirtualSection(pXDataSection, IBCProfiledSection | HotColdSortedRange| HelperTableSection, HELPER_TABLE_ALIGN); - - // hot for writing, i.e. profiling has indicated a write to this item, so at least one write likely per item at some point - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_WRITE] = NewVirtualSection(pXDataSection, IBCProfiledSection | HotRange | MethodPrecodeWriteSection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_HOT] = NewVirtualSection(pXDataSection, IBCProfiledSection | HotRange | MethodPrecodeSection, TARGET_POINTER_SIZE); - - // - // cold sections - // - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_COLD] = NewVirtualSection(pXDataSection, IBCProfiledSection | ColdRange | MethodPrecodeSection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_METHOD_PRECODE_COLD_WRITEABLE] = NewVirtualSection(pXDataSection, IBCProfiledSection | ColdRange | MethodPrecodeWriteableSection, TARGET_POINTER_SIZE); - } - - { - // code:NativeUnwindInfoLookupTable::LookupUnwindInfoForMethod and code:NativeImageJitManager::GetFunctionEntry expects - // sentinel value right after end of .pdata section. - static const DWORD dwRuntimeFunctionSectionSentinel = (DWORD)-1; - - - // - // .text section - // -#if defined(TARGET_ARM) - // for ARM, put the resource section at the end if it's very large - this - // is because b and bl instructions have a limited distance range of +-16MB - // which we should not exceed if we can avoid it. - // we draw the limit at 1 MB resource size, somewhat arbitrarily - COUNT_T resourceSize; - m_ModuleDecoder.GetResources(&resourceSize); - BOOL bigResourceSection = resourceSize >= 1024*1024; -#endif - ZapPhysicalSection * pTextSection = NewPhysicalSection(".text", IMAGE_SCN_CNT_CODE | TEXT_MEM); - m_pTextSection = pTextSection; - - // Marked as HotRange since it contains items that are always touched by - // the OS during NGEN image loading (i.e. VersionInfo) - m_pWin32ResourceSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | Win32ResourcesSection); - - // Marked as a HotRange since it is always touched during Ngen image load. - m_pHeaderSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HeaderSection); - - // Marked as a HotRange since it is always touched during Ngen image binding. - m_pMetaDataSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | MetadataSection); - - m_pImportTableSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | ImportTableSection, sizeof(DWORD)); - - m_pDelayLoadInfoDelayListSectionEager = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | DelayLoadInfoDelayListSection, sizeof(DWORD)); - - // - // GC Info for methods which were profiled hot AND had their GC Info touched during profiling - // - m_pHotTouchedGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | GCInfoSection, sizeof(DWORD)); - - m_pLazyHelperSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HelperTableSection, MINIMUM_CODE_ALIGN); - m_pLazyHelperSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - - m_pLazyMethodCallHelperSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | HotRange | HelperTableSection, MINIMUM_CODE_ALIGN); - m_pLazyMethodCallHelperSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - - int codeSectionAlign = DEFAULT_CODE_ALIGN; - - m_pHotCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | CodeSection, codeSectionAlign); - m_pHotCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - -#if defined(FEATURE_EH_FUNCLETS) - m_pHotUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | UnwindDataSection, sizeof(DWORD)); // .rdata area - - // All RuntimeFunctionSections have to be together for FEATURE_EH_FUNCLETS - m_pHotRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)); // .pdata area - m_pRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - m_pColdRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif // defined(FEATURE_EH_FUNCLETS) - - m_pStubsSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | StubsSection); - m_pReadOnlyDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ReadonlyDataSection); - - m_pDynamicHelperDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodDataSection, sizeof(DWORD)); - m_pExternalMethodDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExternalMethodDataSection, sizeof(DWORD)); - m_pStubDispatchDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | StubDispatchDataSection, sizeof(DWORD)); - - m_pHotRuntimeFunctionLookupSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)); -#if !defined(FEATURE_EH_FUNCLETS) - m_pHotRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif - m_pHotCodeMethodDescsSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | CodeManagerSection, sizeof(DWORD)); - - m_pDelayLoadInfoDelayListSectionHot = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | DelayLoadInfoDelayListSection, sizeof(DWORD)); - - // - // The hot set of read-only data structures. Note that read-only data structures are the things that we can (and aggressively do) intern - // to share between different owners. However, this can have a bad interaction with IBC, which performs its ordering optimizations without - // knowing that NGen may jumble around layout with interning. Thankfully, it is a relatively small percentage of the items that are duplicates - // (many of them used a great deal to add up to large interning savings). This means that we can track all of the interned items for which we - // actually find any duplicates and put those in a small section. For the rest, where there wasn't a duplicate in the entire image, we leave the - // singleton in its normal place in the READONLY_HOT section, which was selected carefully by IBC. - // - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_SHARED_HOT] = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | ReadonlySharedSection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_HOT] = NewVirtualSection(pTextSection, IBCProfiledSection | HotRange | ReadonlySection, TARGET_POINTER_SIZE); - - // - // GC Info for methods which were touched during profiling but didn't explicitly have - // their GC Info touched during profiling - // - m_pHotGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | GCInfoSection, sizeof(DWORD)); - -#if !defined(TARGET_ARM) - // For ARM, put these sections more towards the end because bl/b instructions have limited displacement - - // IL - m_pILSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILSection, sizeof(DWORD)); - - //ILMetadata/Resources sections are reported as a statically known warm ranges for now. - m_pILMetaDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILMetadataSection, sizeof(DWORD)); -#endif // TARGET_ARM - -#if defined(TARGET_ARM) - if (!bigResourceSection) // for ARM, put the resource section at the end if it's very large - see comment above -#endif - m_pResourcesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ResourcesSection); - - // - // Allocate the unprofiled code section and code manager nibble map here - // - m_pCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | CodeSection, codeSectionAlign); - m_pCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - - m_pRuntimeFunctionLookupSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); -#if !defined(FEATURE_EH_FUNCLETS) - m_pRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif - m_pCodeMethodDescsSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | CodeHeaderSection,sizeof(DWORD)); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - m_pAvailableTypesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ReadonlySection); - m_pAttributePresenceSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ReadonlyDataSection, 16/* Must be 16 byte aligned */); - } -#endif - -#if defined(FEATURE_EH_FUNCLETS) - m_pUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ColdRange | UnwindDataSection, sizeof(DWORD)); -#endif // defined(FEATURE_EH_FUNCLETS) - - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_WARM] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_VCHUNKS] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, TARGET_POINTER_SIZE); - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_DICTIONARY] = NewVirtualSection(pTextSection, IBCProfiledSection | WarmRange | ReadonlySection, TARGET_POINTER_SIZE); - - // - // GC Info for methods which were not touched in profiling - // - m_pGCSection = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | GCInfoSection, sizeof(DWORD)); - - m_pDelayLoadInfoDelayListSectionCold = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | DelayLoadInfoDelayListSection, sizeof(DWORD)); - - m_pPreloadSections[CORCOMPILE_SECTION_READONLY_COLD] = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | ReadonlySection, TARGET_POINTER_SIZE); - - // - // Allocate the cold code section near the end of the image - // - m_pColdCodeSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | CodeSection, codeSectionAlign); - m_pColdCodeSection->SetDefaultFill(DEFAULT_CODE_BUFFER_INIT); - -#if defined(TARGET_ARM) - // For ARM, put these sections more towards the end because bl/b instructions have limited displacement - - // IL - m_pILSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILSection, sizeof(DWORD)); - - //ILMetadata/Resources sections are reported as a statically known warm ranges for now. - m_pILMetaDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ILMetadataSection, sizeof(DWORD)); - - if (bigResourceSection) // for ARM, put the resource section at the end if it's very large - see comment above - m_pResourcesSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | WarmRange | ResourcesSection); -#endif // TARGET_ARM - m_pColdCodeMapSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | CodeManagerSection, sizeof(DWORD)); - -#if !defined(FEATURE_EH_FUNCLETS) - m_pColdRuntimeFunctionSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)); - - // The following sentinel section is just a padding for RuntimeFunctionSection - Apply same classification - NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | RuntimeFunctionSection, sizeof(DWORD)) - ->Place(new (GetHeap()) ZapBlobPtr((PVOID)&dwRuntimeFunctionSectionSentinel, sizeof(DWORD))); -#endif - -#if defined(FEATURE_EH_FUNCLETS) - m_pColdUnwindDataSection = NewVirtualSection(pTextSection, IBCProfiledSection | IBCUnProfiledSection | ColdRange | UnwindDataSection, sizeof(DWORD)); -#endif // defined(FEATURE_EH_FUNCLETS) - - // - // Allocate space for compressed LookupMaps (ridmaps). This needs to come after the .data physical - // section (which is currently true for the .text section) and late enough in the .text section to be - // after any structure referenced by the LookupMap (current MethodTables and MethodDescs). This is a - // hard requirement since the compression algorithm requires that all referenced data structures have - // been laid out by the time we come to lay out the compressed nodes. - // - m_pPreloadSections[CORCOMPILE_SECTION_COMPRESSED_MAPS] = NewVirtualSection(pTextSection, IBCProfiledSection | ColdRange | CompressedMapsSection, sizeof(DWORD)); - - m_pExceptionSection = NewVirtualSection(pTextSection, IBCProfiledSection | HotColdSortedRange | ExceptionSection, sizeof(DWORD)); - - // - // Debug info is sometimes used during exception handling to build stacktrace - // - m_pDebugSection = NewVirtualSection(pTextSection, IBCUnProfiledSection | ColdRange | DebugSection, sizeof(DWORD)); - } - - { - // - // .reloc section - // - - ZapPhysicalSection * pRelocSection = NewPhysicalSection(".reloc", IMAGE_SCN_CNT_INITIALIZED_DATA | IMAGE_SCN_MEM_DISCARDABLE | IMAGE_SCN_MEM_READ); - - // .reloc section is always read by the OS when the image is opted in ASLR - // (Vista+ default behavior). - m_pBaseRelocsSection = NewVirtualSection(pRelocSection, IBCUnProfiledSection | HotRange | BaseRelocsSection); - - } -} - -void ZapImage::Preallocate() -{ - COUNT_T cbILImage = m_ModuleDecoder.GetSize(); - - // Curb the estimate to handle corner cases gracefully - cbILImage = min(cbILImage, 50000000); - - PREALLOCATE_HASHTABLE(ZapImage::m_CompiledMethods, 0.0050, cbILImage); - PREALLOCATE_HASHTABLE(ZapImage::m_ClassLayoutOrder, 0.0003, cbILImage); - - // - // Preallocation of auxiliary tables in alphabetical order - // - m_pImportTable->Preallocate(cbILImage); - m_pInnerPtrs->Preallocate(cbILImage); - m_pMethodEntryPoints->Preallocate(cbILImage); - m_pWrappers->Preallocate(cbILImage); - - if (m_pILMetaData != NULL) - m_pILMetaData->Preallocate(cbILImage); - m_pGCInfoTable->Preallocate(cbILImage); -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindDataTable->Preallocate(cbILImage); -#endif // FEATURE_EH_FUNCLETS - m_pDebugInfoTable->Preallocate(cbILImage); -} - -void ZapImage::SetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo) -{ - m_pVersionInfo = new (GetHeap()) ZapVersionInfo(pVersionInfo); - m_pHeaderSection->Place(m_pVersionInfo); -} - -void ZapImage::SetDependencies(CORCOMPILE_DEPENDENCY *pDependencies, DWORD cDependencies) -{ - m_pDependencies = new (GetHeap()) ZapDependencies(pDependencies, cDependencies); - m_pHeaderSection->Place(m_pDependencies); -} - -void ZapImage::SetPdbFileName(const SString &strFileName) -{ - m_pdbFileName.Set(strFileName); -} - -#ifdef FEATURE_EH_FUNCLETS -void ZapImage::SetRuntimeFunctionsDirectoryEntry() -{ - // - // Runtime functions span multiple virtual sections and so there is no natural ZapNode * to cover them all. - // Create dummy ZapNode * that covers them all for IMAGE_DIRECTORY_ENTRY_EXCEPTION directory entry. - // - ZapVirtualSection * rgRuntimeFunctionSections[] = { - m_pHotRuntimeFunctionSection, - m_pRuntimeFunctionSection, - m_pColdRuntimeFunctionSection - }; - - DWORD dwTotalSize = 0, dwStartRVA = (DWORD)-1, dwEndRVA = 0; - - for (size_t i = 0; i < _countof(rgRuntimeFunctionSections); i++) - { - ZapVirtualSection * pSection = rgRuntimeFunctionSections[i]; - - DWORD dwSize = pSection->GetSize(); - if (dwSize == 0) - continue; - - DWORD dwRVA = pSection->GetRVA(); - - dwTotalSize += dwSize; - - dwStartRVA = min(dwStartRVA, dwRVA); - dwEndRVA = max(dwEndRVA, dwRVA + dwSize); - } - - if (dwTotalSize != 0) - { - // Verify that there are no holes between the sections - _ASSERTE(dwStartRVA + dwTotalSize == dwEndRVA); - - ZapNode * pAllRuntimeFunctionSections = new (GetHeap()) ZapDummyNode(dwTotalSize); - pAllRuntimeFunctionSections->SetRVA(dwStartRVA); - - // Write the address of the sorted pdata to the optionalHeader.DataDirectory - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXCEPTION, pAllRuntimeFunctionSections); - } -} -#endif // FEATURE_EH_FUNCLETS - -// Assign RVAs to all ZapNodes -void ZapImage::ComputeRVAs() -{ - ZapWriter::ComputeRVAs(); - - if (!IsReadyToRunCompilation()) - { - m_pMethodEntryPoints->Resolve(); - m_pWrappers->Resolve(); - } - - m_pInnerPtrs->Resolve(); - -#ifdef FEATURE_EH_FUNCLETS - SetRuntimeFunctionsDirectoryEntry(); -#endif - -#if defined(_DEBUG) -#ifdef FEATURE_SYMDIFF - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_SymDiffDump)) - { - COUNT_T curMethod = 0; - COUNT_T numMethods = m_MethodCompilationOrder.GetCount(); - - for (; curMethod < numMethods; curMethod++) - { - bool fCold = false; - //if(curMethod >= m_iUntrainedMethod) fCold = true; - - ZapMethodHeader * pMethod = m_MethodCompilationOrder[curMethod]; - - ZapBlobWithRelocs * pCode = fCold ? pMethod->m_pColdCode : pMethod->m_pCode; - if (pCode == NULL) - { - continue; - } - CORINFO_METHOD_HANDLE handle = pMethod->GetHandle(); - mdMethodDef token; - GetCompileInfo()->GetMethodDef(handle, &token); - GetSvcLogger()->Printf(W("(EntryPointRVAMap (MethodToken %0X) (RVA %0X) (SIZE %0X))\n"), token, pCode->GetRVA(), pCode->GetSize()); - } - - } -#endif // FEATURE_SYMDIFF -#endif //_DEBUG -} - -class ZapFileStream : public IStream -{ - HANDLE m_hFile; - MD5 m_hasher; - -public: - ZapFileStream() - : m_hFile(INVALID_HANDLE_VALUE) - { - m_hasher.Init(); - } - - ~ZapFileStream() - { - Close(); - } - - void SetHandle(HANDLE hFile) - { - _ASSERTE(m_hFile == INVALID_HANDLE_VALUE); - m_hFile = hFile; - } - - // IUnknown methods: - STDMETHODIMP_(ULONG) AddRef() - { - return 1; - } - - STDMETHODIMP_(ULONG) Release() - { - return 1; - } - - STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv) - { - HRESULT hr = S_OK; - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) { - *ppv = static_cast(this); - } - else { - hr = E_NOINTERFACE; - } - return hr; - } - - // ISequentialStream methods: - STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten) - { - HRESULT hr = S_OK; - - _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); - - m_hasher.HashMore(pv, cb); - - // We are calling with lpOverlapped == NULL so pcbWritten has to be present - // to prevent crashes in Win7 and below. - _ASSERTE(pcbWritten); - - if (!::WriteFile(m_hFile, pv, cb, pcbWritten, NULL)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - - Exit: - return hr; - } - - // IStream methods: - STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) - { - HRESULT hr = S_OK; - - _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); - - DWORD dwFileOrigin; - switch (dwOrigin) { - case STREAM_SEEK_SET: - dwFileOrigin = FILE_BEGIN; - break; - - case STREAM_SEEK_CUR: - dwFileOrigin = FILE_CURRENT; - break; - - case STREAM_SEEK_END: - dwFileOrigin = FILE_END; - break; - - default: - hr = E_UNEXPECTED; - goto Exit; - } - if (!::SetFilePointerEx(m_hFile, dlibMove, (LARGE_INTEGER *)plibNewPosition, dwFileOrigin)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - - Exit: - return hr; - } - - STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) - { - HRESULT hr = S_OK; - - _ASSERTE(m_hFile != INVALID_HANDLE_VALUE); - - hr = Seek(*(LARGE_INTEGER *)&libNewSize, FILE_BEGIN, NULL); - if (FAILED(hr)) - { - goto Exit; - } - - if (!::SetEndOfFile(m_hFile)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - - Exit: - return hr; - } - - STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Commit(DWORD grfCommitFlags) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Revert() - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Clone(IStream **ppIStream) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - HRESULT Close() - { - HRESULT hr = S_OK; - - HANDLE hFile = m_hFile; - if (hFile != INVALID_HANDLE_VALUE) - { - m_hFile = INVALID_HANDLE_VALUE; - - if (!::CloseHandle(hFile)) - { - hr = HRESULT_FROM_GetLastError(); - goto Exit; - } - } - - Exit: - return hr; - } - - void SuppressClose() - { - m_hFile = INVALID_HANDLE_VALUE; - } - - void GetHash(MD5HASHDATA* pHash) - { - m_hasher.GetHashValue(pHash); - } -}; - -HANDLE ZapImage::GenerateFile(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - ZapFileStream outputStream; - - HANDLE hFile = WszCreateFile(wszOutputFileName, - GENERIC_READ | GENERIC_WRITE, - FILE_SHARE_READ | FILE_SHARE_DELETE, - NULL, - CREATE_ALWAYS, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - - if (hFile == INVALID_HANDLE_VALUE) - ThrowLastError(); - - outputStream.SetHandle(hFile); - - Save(&outputStream); - - LARGE_INTEGER filePos; - - if (m_pNativeHeader != NULL) - { - // Write back the updated CORCOMPILE_HEADER (relocs and guid is not correct the first time around) - filePos.QuadPart = m_pTextSection->GetFilePos() + - (m_pNativeHeader->GetRVA() - m_pTextSection->GetRVA()); - IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL)); - m_pNativeHeader->Save(this); - FlushWriter(); - } - - GUID signature = {0}; - - static_assert_no_msg(sizeof(GUID) == sizeof(MD5HASHDATA)); - outputStream.GetHash((MD5HASHDATA*)&signature); - - { - // Write the debug directory entry for the NGEN PDB - RSDS rsds = {0}; - - rsds.magic = VAL32(0x53445352); // "SDSR"; - rsds.age = 1; - // our PDB signature will be the same as our NGEN signature. - // However we want the printed version of the GUID to be the same as the - // byte dump of the signature so we swap bytes to make this work. - // - // * See code:CCorSvcMgr::CreatePdb for where this is used. - BYTE* asBytes = (BYTE*) &signature; - rsds.signature.Data1 = ((asBytes[0] * 256 + asBytes[1]) * 256 + asBytes[2]) * 256 + asBytes[3]; - rsds.signature.Data2 = asBytes[4] * 256 + asBytes[5]; - rsds.signature.Data3 = asBytes[6] * 256 + asBytes[7]; - memcpy(&rsds.signature.Data4, &asBytes[8], 8); - - _ASSERTE(!m_pdbFileName.IsEmpty()); - ZeroMemory(&rsds.path[0], sizeof(rsds.path)); - if (WideCharToMultiByte(CP_UTF8, - 0, - m_pdbFileName.GetUnicode(), - m_pdbFileName.GetCount(), - &rsds.path[0], - sizeof(rsds.path) - 1, // -1 to keep the buffer zero terminated - NULL, - NULL) == 0) - ThrowHR(E_FAIL); - - ULONG cbWritten = 0; - filePos.QuadPart = m_pTextSection->GetFilePos() + (m_pNGenPdbDebugData->GetRVA() - m_pTextSection->GetRVA()); - IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL)); - IfFailThrow(outputStream.Write(&rsds, sizeof rsds, &cbWritten)); - } - - if (m_pVersionInfo != NULL) - { - ULONG cbWritten; - - filePos.QuadPart = m_pTextSection->GetFilePos() + - (m_pVersionInfo->GetRVA() - m_pTextSection->GetRVA()) + - offsetof(CORCOMPILE_VERSION_INFO, signature); - IfFailThrow(outputStream.Seek(filePos, STREAM_SEEK_SET, NULL)); - IfFailThrow(outputStream.Write(&signature, sizeof(signature), &cbWritten)); - - if (pNativeImageSig != NULL) - *pNativeImageSig = signature; - } - else - { - _ASSERTE(pNativeImageSig == NULL); - } - - outputStream.SuppressClose(); - return hFile; -} - - -HANDLE ZapImage::SaveImage(LPCWSTR wszOutputFileName, LPCWSTR wszDllPath, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - if(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()) - { - OutputManifestMetadata(); - } - - OutputTables(); - - // Create an empty export table. This makes tools like symchk not think - // that native images are resource-only DLLs. It is important to NOT - // be a resource-only DLL because those DLL's PDBS are not put up on the - // symbol server and we want NGEN PDBS to be placed there. - ZapPEExports* exports = new(GetHeap()) ZapPEExports(wszDllPath); - m_pDebugSection->Place(exports); - SetDirectoryEntry(IMAGE_DIRECTORY_ENTRY_EXPORT, exports); - - ComputeRVAs(); - - if (!IsReadyToRunCompilation()) - { - m_pPreloader->FixupRVAs(); - } - - HANDLE hFile = GenerateFile(wszOutputFileName, pNativeImageSig); - - if (m_zapper->m_pOpt->m_verbose) - { - PrintStats(wszOutputFileName); - } - - return hFile; -} - -void ZapImage::PrintStats(LPCWSTR wszOutputFileName) -{ -#define ACCUM_SIZE(dest, src) if( src != NULL ) dest+= src->GetSize() - ACCUM_SIZE(m_stats->m_gcInfoSize, m_pHotTouchedGCSection); - ACCUM_SIZE(m_stats->m_gcInfoSize, m_pHotGCSection); - ACCUM_SIZE(m_stats->m_gcInfoSize, m_pGCSection); -#if defined(FEATURE_EH_FUNCLETS) - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pUnwindDataSection); - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pHotRuntimeFunctionSection); - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pRuntimeFunctionSection); - ACCUM_SIZE(m_stats->m_unwindInfoSize, m_pColdRuntimeFunctionSection); -#endif // defined(FEATURE_EH_FUNCLETS) - - // - // Get the size of the input & output files - // - - { - WIN32_FIND_DATA inputData; - FindHandleHolder inputHandle = WszFindFirstFile(m_pModuleFileName, &inputData); - if (inputHandle != INVALID_HANDLE_VALUE) - m_stats->m_inputFileSize = inputData.nFileSizeLow; - } - - { - WIN32_FIND_DATA outputData; - FindHandleHolder outputHandle = WszFindFirstFile(wszOutputFileName, &outputData); - if (outputHandle != INVALID_HANDLE_VALUE) - m_stats->m_outputFileSize = outputData.nFileSizeLow; - } - - ACCUM_SIZE(m_stats->m_metadataSize, m_pAssemblyMetaData); - - DWORD dwPreloadSize = 0; - for (int iSection = 0; iSection < CORCOMPILE_SECTION_COUNT; iSection++) - ACCUM_SIZE(dwPreloadSize, m_pPreloadSections[iSection]); - m_stats->m_preloadImageSize = dwPreloadSize; - - ACCUM_SIZE(m_stats->m_hotCodeMgrSize, m_pHotCodeMethodDescsSection); - ACCUM_SIZE(m_stats->m_unprofiledCodeMgrSize, m_pCodeMethodDescsSection); - ACCUM_SIZE(m_stats->m_coldCodeMgrSize, m_pHotRuntimeFunctionLookupSection); - - ACCUM_SIZE(m_stats->m_eeInfoTableSize, m_pEEInfoTable); - ACCUM_SIZE(m_stats->m_helperTableSize, m_pHelperTableSection); - ACCUM_SIZE(m_stats->m_dynamicInfoTableSize, m_pImportSectionsTable); - - ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionEager); - ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionHot); - ACCUM_SIZE(m_stats->m_dynamicInfoDelayListSize, m_pDelayLoadInfoDelayListSectionCold); - - ACCUM_SIZE(m_stats->m_debuggingTableSize, m_pDebugSection); - ACCUM_SIZE(m_stats->m_headerSectionSize, m_pGCSection); - ACCUM_SIZE(m_stats->m_codeSectionSize, m_pHotCodeSection); - ACCUM_SIZE(m_stats->m_coldCodeSectionSize, m_pColdCodeSection); - ACCUM_SIZE(m_stats->m_exceptionSectionSize, m_pExceptionSection); - ACCUM_SIZE(m_stats->m_readOnlyDataSectionSize, m_pReadOnlyDataSection); - ACCUM_SIZE(m_stats->m_relocSectionSize, m_pBaseRelocsSection); - ACCUM_SIZE(m_stats->m_ILMetadataSize, m_pILMetaData); - ACCUM_SIZE(m_stats->m_virtualImportThunkSize, m_pVirtualImportThunkSection); - ACCUM_SIZE(m_stats->m_externalMethodThunkSize, m_pExternalMethodThunkSection); - ACCUM_SIZE(m_stats->m_externalMethodDataSize, m_pExternalMethodDataSection); -#undef ACCUM_SIZE - - if (m_stats->m_failedMethods) - m_zapper->Warning(W("Warning: %d methods (%d%%) could not be compiled.\n"), - m_stats->m_failedMethods, (m_stats->m_failedMethods*100) / m_stats->m_methods); - if (m_stats->m_failedILStubs) - m_zapper->Warning(W("Warning: %d IL STUB methods could not be compiled.\n"), - m_stats->m_failedMethods); - m_stats->PrintStats(); -} - -// Align native images to 64K -const SIZE_T BASE_ADDRESS_ALIGNMENT = 0xffff; -const double CODE_EXPANSION_FACTOR = 3.6; - -void ZapImage::CalculateZapBaseAddress() -{ - static SIZE_T nextBaseAddressForMultiModule; - - SIZE_T baseAddress = 0; - - { - // Read the actual preferred base address from the disk - - // Note that we are reopening the file here. We are not guaranteed to get the same file. - // The worst thing that can happen is that we will read a bogus preferred base address from the file. - HandleHolder hFile(WszCreateFile(m_pModuleFileName, - GENERIC_READ, - FILE_SHARE_READ|FILE_SHARE_DELETE, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL, - NULL)); - if (hFile == INVALID_HANDLE_VALUE) - ThrowLastError(); - - HandleHolder hFileMap(WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL)); - if (hFileMap == NULL) - ThrowLastError(); - - MapViewHolder base(MapViewOfFile(hFileMap, FILE_MAP_READ, 0, 0, 0)); - if (base == NULL) - ThrowLastError(); - - DWORD dwFileLen = SafeGetFileSize(hFile, 0); - if (dwFileLen == INVALID_FILE_SIZE) - ThrowLastError(); - - PEDecoder peFlat((void *)base, (COUNT_T)dwFileLen); - - baseAddress = (SIZE_T) peFlat.GetPreferredBase(); - } - - // See if the header has the linker's default preferred base address - if (baseAddress == (SIZE_T) 0x00400000) - { - if (m_fManifestModule) - { - // Set the base address for the main assembly with the manifest - - if (!m_ModuleDecoder.IsDll()) - { -#if defined(TARGET_X86) - // We use 30000000 for an exe - baseAddress = 0x30000000; -#elif defined(TARGET_64BIT) - // We use 04000000 for an exe - // which is remapped to 0x644`88000000 on x64 - baseAddress = 0x04000000; -#endif - } - else - { -#if defined(TARGET_X86) - // We start a 31000000 for the main assembly with the manifest - baseAddress = 0x31000000; -#elif defined(TARGET_64BIT) - // We start a 05000000 for the main assembly with the manifest - // which is remapped to 0x644`8A000000 on x64 - baseAddress = 0x05000000; -#endif - } - } - else // is dependent assembly of a multi-module assembly - { - // Set the base address for a dependent multi-module assembly - - // We should have already set the nextBaseAddressForMultiModule - // when we compiled the manifest module - _ASSERTE(nextBaseAddressForMultiModule != 0); - baseAddress = nextBaseAddressForMultiModule; - } - } - else - { - // - // For some assemblies we have to move the ngen image base address up - // past the end of IL image so that that we don't have a conflict. - // - // CoreCLR currently always loads both the IL and the native image, so - // move the native image out of the way. - { - baseAddress += m_ModuleDecoder.GetVirtualSize(); - } - } - - 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 - // currently.) - - baseAddress = (baseAddress + BASE_ADDRESS_ALIGNMENT) & ~BASE_ADDRESS_ALIGNMENT; - - // - // Calculate the nextBaseAddressForMultiModule - // - SIZE_T tempBaseAddress = baseAddress; - tempBaseAddress += (SIZE_T) (CODE_EXPANSION_FACTOR * (double) m_ModuleDecoder.GetVirtualSize()); - tempBaseAddress += BASE_ADDRESS_ALIGNMENT; - tempBaseAddress = (tempBaseAddress + BASE_ADDRESS_ALIGNMENT) & ~BASE_ADDRESS_ALIGNMENT; - - nextBaseAddressForMultiModule = tempBaseAddress; - - // - // Now we remap the 32-bit address range used for x86 and PE32 images into the - // upper address range used on 64-bit platforms - // -#if USE_UPPER_ADDRESS // Implies TARGET_64BIT - if (baseAddress < 0x80000000) - { - if (baseAddress < 0x40000000) - baseAddress += 0x40000000; // We map [00000000..3fffffff] to [644'80000000..644'ffffffff] - else - baseAddress -= 0x40000000; // We map [40000000..7fffffff] to [644'00000000..644'7fffffff] - - baseAddress *= UPPER_ADDRESS_MAPPING_FACTOR; - baseAddress += CLR_UPPER_ADDRESS_MIN; - } -#endif - - // Apply the calculated base address. - SetBaseAddress(baseAddress); - - m_NativeBaseAddress = baseAddress; -} - -void ZapImage::Open(CORINFO_MODULE_HANDLE hModule, - IMetaDataAssemblyEmit *pEmit) -{ - m_hModule = hModule; - m_fManifestModule = (hModule == m_zapper->m_pEECompileInfo->GetAssemblyModule(m_zapper->m_hAssembly)); - - m_ModuleDecoder = *m_zapper->m_pEECompileInfo->GetModuleDecoder(hModule); - - - // - // Get file name, and base address from module - // - - StackSString moduleFileName; - m_zapper->m_pEECompileInfo->GetModuleFileName(hModule, moduleFileName); - - DWORD fileNameLength = moduleFileName.GetCount(); - m_pModuleFileName = new WCHAR[fileNameLength+1]; - wcscpy_s(m_pModuleFileName, fileNameLength+1, moduleFileName.GetUnicode()); - - // - // Load the IBC Profile data for the assembly if it exists - // - LoadProfileData(); - - // - // Get metadata of module to be compiled - // - m_pMDImport = m_zapper->m_pEECompileInfo->GetModuleMetaDataImport(m_hModule); - _ASSERTE(m_pMDImport != NULL); - - // - // Open new assembly metadata data for writing. We may not use it, - // if so we'll just discard it at the end. - // - if (pEmit != NULL) - { - pEmit->AddRef(); - m_pAssemblyEmit = pEmit; - } - else - { - // Hardwire the metadata version to be the current runtime version so that the ngen image - // does not change when the directory runtime is installed in different directory (e.g. v2.0.x86chk vs. v2.0.80826). - BSTRHolder strVersion(SysAllocString(CLR_METADATA_VERSION_L)); - VARIANT versionOption; - V_VT(&versionOption) = VT_BSTR; - V_BSTR(&versionOption) = strVersion; - IfFailThrow(m_zapper->m_pMetaDataDispenser->SetOption(MetaDataRuntimeVersion, &versionOption)); - - IfFailThrow(m_zapper->m_pMetaDataDispenser-> - DefineScope(CLSID_CorMetaDataRuntime, 0, IID_IMetaDataAssemblyEmit, - (IUnknown **) &m_pAssemblyEmit)); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - InitializeSectionsForReadyToRun(); - } - else -#endif - { - InitializeSections(); - } - - // Set the module base address for the ngen native image - CalculateZapBaseAddress(); -} - - - - -// -// Load the module and populate all the data-structures -// - -void ZapImage::Preload() -{ - - CorProfileData * pProfileData = NewProfileData(); - m_pPreloader = m_zapper->m_pEECompileInfo->PreloadModule(m_hModule, this, pProfileData); -} - -// -// Store the module -// - -void ZapImage::LinkPreload() -{ - m_pPreloader->Link(); -} - -void ZapImage::OutputManifestMetadata() -{ - // - // Write out manifest metadata - // - - // - // First, see if we have useful metadata to store - // - - BOOL fMetadata = FALSE; - - if (m_pAssemblyEmit != NULL) - { - // - // We may have added some assembly refs for exports. - // - - NonVMComHolder pAssemblyImport; - IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMetaDataAssemblyImport, - (void **)&pAssemblyImport)); - - NonVMComHolder pImport; - IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMetaDataImport, - (void **)&pImport)); - - HCORENUM hEnum = 0; - ULONG cRefs; - IfFailThrow(pAssemblyImport->EnumAssemblyRefs(&hEnum, NULL, 0, &cRefs)); - IfFailThrow(pImport->CountEnum(hEnum, &cRefs)); - pImport->CloseEnum(hEnum); - - if (cRefs > 0) - fMetadata = TRUE; - - // - // If we are the main module, we have the assembly def for the zap file. - // - - mdAssembly a; - if (pAssemblyImport->GetAssemblyFromScope(&a) == S_OK) - fMetadata = TRUE; - } - - if (fMetadata) - { - // Metadata creates a new MVID for every instantiation. - // However, we want the generated ngen image to always be the same - // for the same input. So set the metadata MVID to NGEN_IMAGE_MVID. - - NonVMComHolder pMDInternalEmit; - IfFailThrow(m_pAssemblyEmit->QueryInterface(IID_IMDInternalEmit, - (void**)&pMDInternalEmit)); - - IfFailThrow(pMDInternalEmit->ChangeMvid(NGEN_IMAGE_MVID)); - - m_pAssemblyMetaData = new (GetHeap()) ZapMetaData(); - m_pAssemblyMetaData->SetMetaData(m_pAssemblyEmit); - - m_pMetaDataSection->Place(m_pAssemblyMetaData); - } -} - -void ZapImage::OutputTables() -{ - // - // Copy over any resources to the native image - // - - COUNT_T size; - PVOID resource = (PVOID)m_ModuleDecoder.GetResources(&size); - - if (size != 0) - { - m_pResources = new (GetHeap()) ZapBlobPtr(resource, size); - m_pResourcesSection->Place(m_pResources); - } - - CopyDebugDirEntry(); - CopyWin32Resources(); - - if (m_pILMetaData != NULL) - { - m_pILMetaData->CopyIL(); - m_pILMetaData->CopyMetaData(); - } - - if (IsReadyToRunCompilation()) - { - m_pILMetaData->CopyRVAFields(); - } - - // Copy over the timestamp from IL image for determinism - SetTimeDateStamp(m_ModuleDecoder.GetTimeDateStamp()); - - SetSubsystem(m_ModuleDecoder.GetSubsystem()); - - { - USHORT dllCharacteristics = 0; - -#ifndef TARGET_64BIT - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NO_SEH; -#endif - -#ifdef TARGET_ARM - // Images without NX compat bit set fail to load on ARM - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_NX_COMPAT; -#endif - - // Copy over selected DLL characteristics bits from IL image - dllCharacteristics |= (m_ModuleDecoder.GetDllCharacteristics() & - (IMAGE_DLLCHARACTERISTICS_NX_COMPAT | IMAGE_DLLCHARACTERISTICS_TERMINAL_SERVER_AWARE | IMAGE_DLLCHARACTERISTICS_APPCONTAINER)); - -#ifdef _DEBUG - if (0 == CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NoASLRForNgen)) -#endif // _DEBUG - { - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_DYNAMIC_BASE; -#ifdef TARGET_64BIT - // Large address aware, required for High Entry VA, is always enabled for 64bit native images. - dllCharacteristics |= IMAGE_DLLCHARACTERISTICS_HIGH_ENTROPY_VA; -#endif - } - - SetDllCharacteristics(dllCharacteristics); - } - - if (IsReadyToRunCompilation()) - { - - SetSizeOfStackReserve(m_ModuleDecoder.GetSizeOfStackReserve()); - SetSizeOfStackCommit(m_ModuleDecoder.GetSizeOfStackCommit()); - } - -#if defined(TARGET_UNIX) && !defined(TARGET_64BIT) - // To minimize wasted VA space on 32-bit systems, align file to page boundaries (presumed to be 4K). - SetFileAlignment(0x1000); -#elif defined(TARGET_ARM) && defined(FEATURE_CORESYSTEM) - if (!IsReadyToRunCompilation()) - { - // On ARM CoreSys builds, crossgen will use 4k file alignment, as requested by Phone perf team - // to improve perf on phones with compressed system partitions. - SetFileAlignment(0x1000); - } -#endif -} - -ZapImage::CompileStatus ZapImage::CompileProfileDataWorker(mdToken token, unsigned methodProfilingDataFlags) -{ - if ((TypeFromToken(token) != mdtMethodDef) || - (!m_pMDImport->IsValidToken(token))) - { - m_zapper->Info(W("Warning: Invalid method token %08x in profile data.\n"), token); - return NOT_COMPILED; - } - -#ifdef _DEBUG - static ConfigDWORD g_NgenOrder; - - if ((g_NgenOrder.val(CLRConfig::INTERNAL_NgenOrder) & 2) == 2) - { - const ProfileDataHashEntry * foundEntry = profileDataHashTable.LookupPtr(token); - - if (foundEntry == NULL) - return NOT_COMPILED; - - // The md must match. - _ASSERTE(foundEntry->md == token); - // The target position cannot be 0. - _ASSERTE(foundEntry->pos > 0); - } -#endif - - // Now compile the method - return TryCompileMethodDef(token, methodProfilingDataFlags); -} - -// ProfileDisableInlining -// Before we start compiling any methods we may need to suppress the inlining -// of certain methods based upon our profile data. -// This method will arrange to disable this inlining. -// -void ZapImage::ProfileDisableInlining() -{ - // We suppress the inlining of any Hot methods that have the ExcludeHotMethodCode flag. - // We want such methods to be Jitted at runtime rather than compiled in the AOT native image. - // The inlining of such a method also need to be suppressed. - // - ProfileDataSection* methodProfileData = &(m_profileDataSections[MethodProfilingData]); - if (methodProfileData->tableSize > 0) - { - for (DWORD i = 0; i < methodProfileData->tableSize; i++) - { - CORBBTPROF_TOKEN_INFO * pTokenInfo = &(methodProfileData->pTable[i]); - unsigned methodProfilingDataFlags = pTokenInfo->flags; - - // Hot methods can be marked to be excluded from the AOT native image. - // We also need to disable inlining of such methods. - // - if ((methodProfilingDataFlags & (1 << DisableInlining)) != 0) - { - // Disable the inlining of this method - // - // @ToDo: Figure out how to disable inlining for this method. - } - } - } -} - -// CompileHotRegion -// Performs the compilation and placement for all methods in the "Hot" code region -// Methods placed in this region typically correspond to all of the methods that were -// executed during any of the profiling scenarios. -// -void ZapImage::CompileHotRegion() -{ - // Compile all of the methods that were executed during profiling into the "Hot" code region. - // - BeginRegion(CORINFO_REGION_HOT); - - CorProfileData* pProfileData = GetProfileData(); - - ProfileDataSection* methodProfileData = &(m_profileDataSections[MethodProfilingData]); - if (methodProfileData->tableSize > 0) - { - // record the start of hot IBC methods. - m_iIBCMethod = m_MethodCompilationOrder.GetCount(); - - // - // Compile the hot methods in the order specified in the MethodProfilingData - // - for (DWORD i = 0; i < methodProfileData->tableSize; i++) - { - CompileStatus compileResult = NOT_COMPILED; - CORBBTPROF_TOKEN_INFO * pTokenInfo = &(methodProfileData->pTable[i]); - - mdToken token = pTokenInfo->token; - unsigned methodProfilingDataFlags = pTokenInfo->flags; - _ASSERTE(methodProfilingDataFlags != 0); - - if (TypeFromToken(token) == mdtMethodDef) - { - // - // Compile a non-generic method - // - compileResult = CompileProfileDataWorker(token, methodProfilingDataFlags); - } - else if (TypeFromToken(token) == ibcMethodSpec) - { - // - // Compile a generic/parameterized method - // - CORBBTPROF_BLOB_PARAM_SIG_ENTRY *pBlobSigEntry = pProfileData->GetBlobSigEntry(token); - - if (pBlobSigEntry == NULL) - { - m_zapper->Info(W("Warning: Did not find definition for method token %08x in profile data.\n"), token); - } - else // (pBlobSigEntry != NULL) - { - _ASSERTE(pBlobSigEntry->blob.token == token); - - // decode method desc - CORINFO_METHOD_HANDLE pMethod = m_pPreloader->FindMethodForProfileEntry(pBlobSigEntry); - - if (pMethod) - { - m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pMethod); - - compileResult = TryCompileInstantiatedMethod(pMethod, methodProfilingDataFlags); - } - else - { - // This generic/parameterized method is not part of the native image - // Either the IBC type specified no longer exists or it is a SIMD types - // or the type can't be loaded in a ReadyToRun native image because of - // a cross-module type dependencies. - // - compileResult = COMPILE_EXCLUDED; - } - } - } - - // Update the 'flags' and 'compileResult' saved in the profileDataHashTable hash table. - // - hashBBUpdateFlagsAndCompileResult(token, methodProfilingDataFlags, compileResult); - } - // record the start of hot Generics methods. - m_iGenericsMethod = m_MethodCompilationOrder.GetCount(); - } - - // record the start of untrained code - m_iUntrainedMethod = m_MethodCompilationOrder.GetCount(); - - EndRegion(CORINFO_REGION_HOT); -} - -// CompileColdRegion -// Performs the compilation and placement for all methods in the "Cold" code region -// Methods placed in this region typically correspond to all of the methods that were -// NOT executed during any of the profiling scenarios. -// -void ZapImage::CompileColdRegion() -{ - // Compile all of the methods that were NOT executed during profiling into the "Cold" code region. - // - - BeginRegion(CORINFO_REGION_COLD); - - IMDInternalImport * pMDImport = m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - // - // Compile the remaining methods that weren't compiled during the CompileHotRegion phase - // - TryCompileMethodDef(md, 0); - } - - // Compile any generic code which lands in this LoaderModule - // that resulted from the above compilations - CORINFO_METHOD_HANDLE handle = m_pPreloader->NextUncompiledMethod(); - while (handle != NULL) - { - TryCompileInstantiatedMethod(handle, 0); - handle = m_pPreloader->NextUncompiledMethod(); - } - - EndRegion(CORINFO_REGION_COLD); -} - -// PlaceMethodIL -// Copy the IL for all method into the AOT native image -// -void ZapImage::PlaceMethodIL() -{ - // Place the IL for all of the methods - // - IMDInternalImport * pMDImport = m_pMDImport; - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - if (m_pILMetaData != NULL) - { - // Copy IL for all methods. We treat errors during copying IL - // over as fatal error. These errors are typically caused by - // corrupted IL images. - // - m_pILMetaData->EmitMethodIL(md); - } - } -} - -void ZapImage::Compile() -{ - // - // Compile all of the methods for our AOT native image - // - - bool doNothingNgen = false; -#ifdef _DEBUG - static ConfigDWORD fDoNothingNGen; - doNothingNgen = !!fDoNothingNGen.val(CLRConfig::INTERNAL_ZapDoNothing); -#endif - - ProfileDisableInlining(); - - if (!doNothingNgen) - { - CompileHotRegion(); - - CompileColdRegion(); - } - - PlaceMethodIL(); - - // Compute a preferred class layout order based on analyzing the graph - // of which classes contain calls to other classes. - ComputeClassLayoutOrder(); - - // Sort the unprofiled methods by this preferred class layout, if available - if (m_fHasClassLayoutOrder) - { - SortUnprofiledMethodsByClassLayoutOrder(); - } - - if (IsReadyToRunCompilation()) - { - // Pretend that no methods are trained, so that everything is in single code section - // READYTORUN: FUTURE: More than one code section - m_iUntrainedMethod = 0; - } - - OutputCode(ProfiledHot); - OutputCode(Unprofiled); - OutputCode(ProfiledCold); - - OutputCodeInfo(ProfiledHot); - OutputCodeInfo(ProfiledCold); // actually both Unprofiled and ProfiledCold - - OutputGCInfo(); - OutputProfileData(); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - OutputEntrypointsTableForReadyToRun(); - OutputDebugInfoForReadyToRun(); - OutputTypesTableForReadyToRun(m_pMDImport); - OutputAttributePresenceFilter(m_pMDImport); - OutputInliningTableForReadyToRun(); - OutputProfileDataForReadyToRun(); - if (IsLargeVersionBubbleEnabled()) - { - OutputManifestMetadataForReadyToRun(); - } - } - else -#endif - { - OutputDebugInfo(); - } -} - -struct CompileMethodStubContext -{ - ZapImage * pImage; - unsigned methodProfilingDataFlags; - ZapImage::CompileStatus enumCompileStubResult; - - CompileMethodStubContext(ZapImage * _image, unsigned _methodProfilingDataFlags) - { - pImage = _image; - methodProfilingDataFlags = _methodProfilingDataFlags; - enumCompileStubResult = ZapImage::NOT_COMPILED; - } -}; - -//----------------------------------------------------------------------------- -// This method is a callback function use to compile any IL_STUBS that are -// associated with a normal IL method. It is called from CompileMethodStubIfNeeded -// via the function pointer stored in the CompileMethodStubContext. -// It handles the temporary change to the m_compilerFlags and removes any flags -// that we don't want set when compiling IL_STUBS. -//----------------------------------------------------------------------------- - -// static void __stdcall -void ZapImage::TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags) -{ - STANDARD_VM_CONTRACT; - - // The caller must always set the IL_STUB flag - _ASSERTE(jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)); - - CompileMethodStubContext *pCompileContext = reinterpret_cast(pContext); - ZapImage *pImage = pCompileContext->pImage; - - CORJIT_FLAGS oldFlags = pImage->m_zapper->m_pOpt->m_compilerFlags; - - CORJIT_FLAGS* pCompilerFlags = &pImage->m_zapper->m_pOpt->m_compilerFlags; - pCompilerFlags->Add(jitFlags); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_EnC); - pCompilerFlags->Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - - mdMethodDef md = mdMethodDefNil; - - pCompileContext->enumCompileStubResult = pImage->TryCompileMethodWorker(hStub, md, - pCompileContext->methodProfilingDataFlags); - - pImage->m_zapper->m_pOpt->m_compilerFlags = oldFlags; -} - -//----------------------------------------------------------------------------- -// Helper for ZapImage::TryCompileMethodDef that indicates whether a given method def token refers to a -// "vtable gap" method. These are pseudo-methods used to lay out the vtable for COM interop and as such don't -// have any associated code (or even a method handle). -//----------------------------------------------------------------------------- -BOOL ZapImage::IsVTableGapMethod(mdMethodDef md) -{ - HRESULT hr; - DWORD dwAttributes; - - // Get method attributes and check that RTSpecialName was set for the method (this means the name has - // semantic import to the runtime and must be formatted rigorously with one of a few well-known rules). - // Note that we just return false on any failure path since this will just lead to our caller continuing - // to throw the exception they were about to anyway. - hr = m_pMDImport->GetMethodDefProps(md, &dwAttributes); - if (FAILED(hr) || !IsMdRTSpecialName(dwAttributes)) - return FALSE; - - // Now check the name of the method. All vtable gap methods will have a prefix of "_VtblGap". - LPCSTR szMethod; - PCCOR_SIGNATURE pvSigBlob; - ULONG cbSigBlob; - hr = m_pMDImport->GetNameAndSigOfMethodDef(md, &pvSigBlob, &cbSigBlob, &szMethod); - if (FAILED(hr) || (strncmp(szMethod, "_VtblGap", 8) != 0)) - return FALSE; - - // If we make it to here we have a vtable gap method. - return TRUE; -} - -//----------------------------------------------------------------------------- -// This function is called for non-generic methods in the current assembly, -// and for the typical "System.__Canon" instantiations of generic methods -// in the current assembly. -//----------------------------------------------------------------------------- - -ZapImage::CompileStatus ZapImage::TryCompileMethodDef(mdMethodDef md, unsigned methodProfilingDataFlags) -{ - _ASSERTE(!IsNilToken(md)); - - CORINFO_METHOD_HANDLE handle = NULL; - CompileStatus result = NOT_COMPILED; - - if (ShouldCompileMethodDef(md)) - { - handle = m_pPreloader->LookupMethodDef(md); - if (handle == nullptr) - { - result = LOOKUP_FAILED; - } - } - else - { - result = COMPILE_EXCLUDED; - } - - if (handle == NULL) - return result; - - // compile the method - // - CompileStatus methodCompileStatus = TryCompileMethodWorker(handle, md, methodProfilingDataFlags); - - // Don't bother compiling the IL_STUBS if we failed to compile the parent IL method - // - if (methodCompileStatus == COMPILE_SUCCEED) - { - CompileMethodStubContext context(this, methodProfilingDataFlags); - - // compile stubs associated with the method - m_pPreloader->GenerateMethodStubs(handle, m_zapper->m_pOpt->m_ngenProfileImage, - &TryCompileMethodStub, - &context); - } - - return methodCompileStatus; -} - - -//----------------------------------------------------------------------------- -// This function is called for non-"System.__Canon" instantiations of generic methods. -// These could be methods defined in other assemblies too. -//----------------------------------------------------------------------------- - -ZapImage::CompileStatus ZapImage::TryCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle, - unsigned methodProfilingDataFlags) -{ - if (IsReadyToRunCompilation()) - { - if (!GetCompileInfo()->IsInCurrentVersionBubble(m_zapper->m_pEEJitInfo->getMethodModule(handle))) - return COMPILE_EXCLUDED; - } - - if (!ShouldCompileInstantiatedMethod(handle)) - return COMPILE_EXCLUDED; - - // If we compiling this method because it was specified by the IBC profile data - // then issue a warning if this method is not on our uncompiled method list. - // - if (methodProfilingDataFlags != 0) - { - if (methodProfilingDataFlags & (1 << ReadMethodCode)) - { - // When we have stale IBC data the method could have been rejected from this image. - if (!m_pPreloader->IsUncompiledMethod(handle)) - { - const char* szClsName; - const char* szMethodName = m_zapper->m_pEEJitInfo->getMethodName(handle, &szClsName); - - SString fullname(SString::Utf8, szClsName); - fullname.AppendUTF8(NAMESPACE_SEPARATOR_STR); - fullname.AppendUTF8(szMethodName); - - m_zapper->Info(W("Warning: Invalid method instantiation in profile data: %s\n"), fullname.GetUnicode()); - - return NOT_COMPILED; - } - } - } - - CompileStatus methodCompileStatus = TryCompileMethodWorker(handle, mdMethodDefNil, methodProfilingDataFlags); - - // Don't bother compiling the IL_STUBS if we failed to compile the parent IL method - // - if (methodCompileStatus == COMPILE_SUCCEED) - { - CompileMethodStubContext context(this, methodProfilingDataFlags); - - // compile stubs associated with the method - m_pPreloader->GenerateMethodStubs(handle, m_zapper->m_pOpt->m_ngenProfileImage, - &TryCompileMethodStub, - &context); - } - - return methodCompileStatus; -} - -//----------------------------------------------------------------------------- - -ZapImage::CompileStatus ZapImage::TryCompileMethodWorker(CORINFO_METHOD_HANDLE handle, mdMethodDef md, - unsigned methodProfilingDataFlags) -{ - _ASSERTE(handle != NULL); - - if (m_zapper->m_pOpt->m_onlyOneMethod && (m_zapper->m_pOpt->m_onlyOneMethod != md)) - return NOT_COMPILED; - - if (GetCompileInfo()->HasCustomAttribute(handle, "System.Runtime.BypassNGenAttribute")) - return NOT_COMPILED; - -#ifdef FEATURE_READYTORUN_COMPILER - // This is a quick workaround to opt specific methods out of ReadyToRun compilation to work around bugs. - if (IsReadyToRunCompilation()) - { - if (GetCompileInfo()->HasCustomAttribute(handle, "System.Runtime.BypassReadyToRunAttribute")) - return NOT_COMPILED; - } -#endif - - // Do we have a profile entry for this method? - // - if (methodProfilingDataFlags != 0) - { - // Report the profiling data flags for layout of the EE data structures - m_pPreloader->SetMethodProfilingFlags(handle, methodProfilingDataFlags); - - // Hot methods can be marked to be excluded from the AOT native image. - // A Jitted method executes faster than a ReadyToRun compiled method. - // - if ((methodProfilingDataFlags & (1 << ExcludeHotMethodCode)) != 0) - { - // returning COMPILE_HOT_EXCLUDED excludes this method from the AOT native image - return COMPILE_HOT_EXCLUDED; - } - - // Cold methods can be marked to be excluded from the AOT native image. - // We can reduce the size of the AOT native image by selectively - // excluding the code for some of the cold methods. - // - if ((methodProfilingDataFlags & (1 << ExcludeColdMethodCode)) != 0) - { - // returning COMPILE_COLD_EXCLUDED excludes this method from the AOT native image - return COMPILE_COLD_EXCLUDED; - } - - // If the code was never executed based on the profile data - // then don't compile this method now. Wait until later - // when we are compiling the methods in the cold section. - // - if ((methodProfilingDataFlags & (1 << ReadMethodCode)) == 0) - { - // returning NOT_COMPILED will defer until later the compilation of this method - return NOT_COMPILED; - } - } - else // we are compiling methods for the cold region - { - // Retrieve any information that we have about a previous compilation attempt of this method - const ProfileDataHashEntry* pEntry = profileDataHashTable.LookupPtr(md); - - // When Partial Ngen is specified we will omit the AOT native code for every - // method that does not have profile data - // - if (pEntry == nullptr && m_zapper->m_pOpt->m_fPartialNGen) - { - // returning COMPILE_COLD_EXCLUDED excludes this method from the AOT native image - return COMPILE_COLD_EXCLUDED; - } - - if (pEntry != nullptr) - { - if ((pEntry->status == COMPILE_HOT_EXCLUDED) || (pEntry->status == COMPILE_COLD_EXCLUDED)) - { - // returning COMPILE_HOT_EXCLUDED excludes this method from the AOT native image - return pEntry->status; - } - } - } - - // Have we already compiled it? - if (GetCompiledMethod(handle) != NULL) - return ALREADY_COMPILED; - - _ASSERTE(m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB) || IsNilToken(md) || handle == m_pPreloader->LookupMethodDef(md)); - - CompileStatus result = NOT_COMPILED; - - CORINFO_MODULE_HANDLE module; - - // We only compile IL_STUBs from the current assembly - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - module = m_hModule; - else - module = m_zapper->m_pEEJitInfo->getMethodModule(handle); - - ZapInfo zapInfo(this, md, handle, module, methodProfilingDataFlags); - - EX_TRY - { - zapInfo.CompileMethod(); - result = COMPILE_SUCCEED; - } - EX_CATCH - { - // Continue unwinding if fatal error was hit. - if (FAILED(g_hrFatalError)) - ThrowHR(g_hrFatalError); - - Exception *ex = GET_EXCEPTION(); - HRESULT hrException = ex->GetHR(); - - CorZapLogLevel level; - -#ifdef CROSSGEN_COMPILE - // Warnings should not go to stderr during crossgen - level = CORZAP_LOGLEVEL_WARNING; -#else - level = CORZAP_LOGLEVEL_ERROR; - - m_zapper->m_failed = TRUE; -#endif - - result = COMPILE_FAILED; - -#ifdef FEATURE_READYTORUN_COMPILER - // NYI features in R2R - Stop crossgen from spitting unnecessary - // messages to the console - if (IsReadyToRunCompilation()) - { - // When compiling the method, we may receive an exception when the - // method uses a feature that is Not Implemented for ReadyToRun - // or a Type Load exception if the method uses a SIMD type. - // - // We skip the compilation of such methods and we don't want to - // issue a warning or error - // - if ((hrException == E_NOTIMPL) || (hrException == (HRESULT)IDS_CLASSLOAD_GENERAL)) - { - result = NOT_COMPILED; - level = CORZAP_LOGLEVEL_INFO; - } - } -#endif - { - StackSString message; - ex->GetMessage(message); - - // FileNotFound errors here can be converted into a single error string per ngen compile, - // and the detailed error is available with verbose logging - if (hrException == COR_E_FILENOTFOUND) - { - StackSString logMessage(W("System.IO.FileNotFoundException: ")); - logMessage.Append(message); - FileNotFoundError(logMessage.GetUnicode()); - level = CORZAP_LOGLEVEL_INFO; - } - - m_zapper->Print(level, W("%s while compiling method %s\n"), message.GetUnicode(), zapInfo.m_currentMethodName.GetUnicode()); - - if ((result == COMPILE_FAILED) && (m_stats != NULL)) - { - if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - m_stats->m_failedMethods++; - else - m_stats->m_failedILStubs++; - } - } - } - EX_END_CATCH(SwallowAllExceptions); - - return result; -} - - -// Should we compile this method, defined in the ngen'ing module? -// Result is FALSE if any of the controls (only used by prejit.exe) exclude the method -BOOL ZapImage::ShouldCompileMethodDef(mdMethodDef md) -{ - DWORD partialNGenStressVal = PartialNGenStressPercentage(); - if (partialNGenStressVal) - { - _ASSERTE(partialNGenStressVal <= 100); - DWORD methodPercentageVal = (md % 100) + 1; - if (methodPercentageVal <= partialNGenStressVal) - return FALSE; - } - - mdTypeDef td; - IfFailThrow(m_pMDImport->GetParentToken(md, &td)); - -#ifdef FEATURE_COMINTEROP - mdToken tkExtends; - if (td != mdTypeDefNil) - { - IfFailThrow(m_pMDImport->GetTypeDefProps(td, NULL, &tkExtends)); - - mdAssembly tkAssembly; - DWORD dwAssemblyFlags; - - IfFailThrow(m_pMDImport->GetAssemblyFromScope(&tkAssembly)); - if (TypeFromToken(tkAssembly) == mdtAssembly) - { - IfFailThrow(m_pMDImport->GetAssemblyProps(tkAssembly, - NULL, NULL, // Public Key - NULL, // Hash Algorithm - NULL, // Name - NULL, // MetaData - &dwAssemblyFlags)); - - if (IsAfContentType_WindowsRuntime(dwAssemblyFlags)) - { - if (TypeFromToken(tkExtends) == mdtTypeRef) - { - LPCSTR szNameSpace = NULL; - LPCSTR szName = NULL; - IfFailThrow(m_pMDImport->GetNameOfTypeRef(tkExtends, &szNameSpace, &szName)); - - if (!strcmp(szNameSpace, "System") && !_stricmp((szName), "Attribute")) - { - return FALSE; - } - } - } - } - } -#endif - -#ifdef _DEBUG - static ConfigMethodSet fZapOnly; - fZapOnly.ensureInit(CLRConfig::INTERNAL_ZapOnly); - - static ConfigMethodSet fZapExclude; - fZapExclude.ensureInit(CLRConfig::INTERNAL_ZapExclude); - - PCCOR_SIGNATURE pvSigBlob; - ULONG cbSigBlob; - - // Get the name of the current method and its class - LPCSTR szMethod; - IfFailThrow(m_pMDImport->GetNameAndSigOfMethodDef(md, &pvSigBlob, &cbSigBlob, &szMethod)); - - LPCWSTR wszClass = W(""); - SString sClass; - - if (td != mdTypeDefNil) - { - LPCSTR szNameSpace = NULL; - LPCSTR szName = NULL; - - IfFailThrow(m_pMDImport->GetNameOfTypeDef(td, &szName, &szNameSpace)); - - const SString nameSpace(SString::Utf8, szNameSpace); - const SString name(SString::Utf8, szName); - sClass.MakeFullNamespacePath(nameSpace, name); - wszClass = sClass.GetUnicode(); - } - - MAKE_UTF8PTR_FROMWIDE(szClass, wszClass); - - if (!fZapOnly.isEmpty() && !fZapOnly.contains(szMethod, szClass, pvSigBlob)) - { - LOG((LF_ZAP, LL_INFO1000, "Rejecting compilation of method %08x, %s::%s\n", md, szClass, szMethod)); - return FALSE; - } - - if (fZapExclude.contains(szMethod, szClass, pvSigBlob)) - { - LOG((LF_ZAP, LL_INFO1000, "Rejecting compilation of method %08x, %s::%s\n", md, szClass, szMethod)); - return FALSE; - } - - LOG((LF_ZAP, LL_INFO1000, "Compiling method %08x, %s::%s\n", md, szClass, szMethod)); -#endif - - return TRUE; -} - - -BOOL ZapImage::ShouldCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle) -{ - DWORD partialNGenStressVal = PartialNGenStressPercentage(); - if (partialNGenStressVal) - { - _ASSERTE(partialNGenStressVal <= 100); - DWORD methodPercentageVal = (m_zapper->m_pEEJitInfo->getMethodHash(handle) % 100) + 1; - if (methodPercentageVal <= partialNGenStressVal) - return FALSE; - } - - return TRUE; -} - -HRESULT ZapImage::PrintTokenDescription(CorZapLogLevel level, mdToken token) -{ - HRESULT hr; - - if (RidFromToken(token) == 0) - return S_OK; - - LPCSTR szNameSpace = NULL; - LPCSTR szName = NULL; - - if (m_pMDImport->IsValidToken(token)) - { - switch (TypeFromToken(token)) - { - case mdtMemberRef: - { - mdToken parent; - IfFailRet(m_pMDImport->GetParentOfMemberRef(token, &parent)); - if (RidFromToken(parent) != 0) - { - PrintTokenDescription(level, parent); - m_zapper->Print(level, W(".")); - } - IfFailRet(m_pMDImport->GetNameAndSigOfMemberRef(token, NULL, NULL, &szName)); - break; - } - - case mdtMethodDef: - { - mdToken parent; - IfFailRet(m_pMDImport->GetParentToken(token, &parent)); - if (RidFromToken(parent) != 0) - { - PrintTokenDescription(level, parent); - m_zapper->Print(level, W(".")); - } - IfFailRet(m_pMDImport->GetNameOfMethodDef(token, &szName)); - break; - } - - case mdtTypeRef: - { - IfFailRet(m_pMDImport->GetNameOfTypeRef(token, &szNameSpace, &szName)); - break; - } - - case mdtTypeDef: - { - IfFailRet(m_pMDImport->GetNameOfTypeDef(token, &szName, &szNameSpace)); - break; - } - - default: - break; - } - } - else - { - szName = "InvalidToken"; - } - - SString fullName; - - if (szNameSpace != NULL) - { - const SString nameSpace(SString::Utf8, szNameSpace); - const SString name(SString::Utf8, szName); - fullName.MakeFullNamespacePath(nameSpace, name); - } - else - { - fullName.SetUTF8(szName); - } - - m_zapper->Print(level, W("%s"), fullName.GetUnicode()); - - return S_OK; -} - - -HRESULT ZapImage::LocateProfileData() -{ - if (m_zapper->m_pOpt->m_ignoreProfileData) - { - return S_FALSE; - } - - // - // In the past, we have ignored profile data when instrumenting the assembly. - // However, this creates significant differences between the tuning image and the eventual - // optimized image (e.g. generic instantiations) which in turn leads to missed data during - // training and cold touches during execution. Instead, we take advantage of any IBC data - // the assembly already has and attempt to make the tuning image as close as possible to - // the final image. - // -#if 0 - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - return S_FALSE; -#endif - - // - // See if there's profile data in the resource section of the PE - // - m_pRawProfileData = (BYTE*)m_ModuleDecoder.GetWin32Resource(W("PROFILE_DATA"), W("IBC"), &m_cRawProfileData); - - if ((m_pRawProfileData != NULL) && (m_cRawProfileData != 0)) - { - m_zapper->Info(W("Found embedded profile resource in %s.\n"), m_pModuleFileName); - return S_OK; - } - - static ConfigDWORD g_UseIBCFile; - if (g_UseIBCFile.val(CLRConfig::EXTERNAL_UseIBCFile) != 1) - return S_OK; - - // - // Couldn't find profile resource--let's see if there's an ibc file to use instead - // - - SString path(m_pModuleFileName); - - SString::Iterator dot = path.End(); - if (path.FindBack(dot, '.')) - { - SString slName(SString::Literal, "ibc"); - path.Replace(dot+1, path.End() - (dot+1), slName); - - HandleHolder hFile = WszCreateFile(path.GetUnicode(), - GENERIC_READ, - FILE_SHARE_READ, - NULL, - OPEN_EXISTING, - FILE_ATTRIBUTE_NORMAL | FILE_FLAG_SEQUENTIAL_SCAN, - NULL); - if (hFile != INVALID_HANDLE_VALUE) - { - HandleHolder hMapFile = WszCreateFileMapping(hFile, NULL, PAGE_READONLY, 0, 0, NULL); - DWORD dwFileLen = SafeGetFileSize(hFile, 0); - if (dwFileLen != INVALID_FILE_SIZE) - { - if (hMapFile == NULL) - { - m_zapper->Warning(W("Found profile data file %s, but could not open it"), path.GetUnicode()); - } - else - { - m_zapper->Info(W("Found ibc file %s.\n"), path.GetUnicode()); - - m_profileDataFile = (BYTE*) MapViewOfFile(hMapFile, FILE_MAP_READ, 0, 0, 0); - - m_pRawProfileData = m_profileDataFile; - m_cRawProfileData = dwFileLen; - } - } - } - } - - return S_OK; -} - - -bool ZapImage::CanConvertIbcData() -{ - static ConfigDWORD g_iConvertIbcData; - DWORD val = g_iConvertIbcData.val(CLRConfig::UNSUPPORTED_ConvertIbcData); - return (val != 0); -} - -HRESULT ZapImage::parseProfileData() -{ - if (m_pRawProfileData == NULL) - { - return S_FALSE; - } - - ProfileReader profileReader(m_pRawProfileData, m_cRawProfileData); - - CORBBTPROF_FILE_HEADER *fileHeader; - - READ(fileHeader, CORBBTPROF_FILE_HEADER); - if (fileHeader->HeaderSize < sizeof(CORBBTPROF_FILE_HEADER)) - { - _ASSERTE(!"HeaderSize is too small"); - return E_FAIL; - } - - // Read any extra header data. It will be needed for V3 files. - - DWORD extraHeaderDataSize = fileHeader->HeaderSize - sizeof(CORBBTPROF_FILE_HEADER); - void *extraHeaderData = profileReader.Read(extraHeaderDataSize); - - bool convertFromV1 = false; - bool minified = false; - - if (fileHeader->Magic != CORBBTPROF_MAGIC) - { - _ASSERTE(!"ibcHeader contains bad values"); - return E_FAIL; - } - - // CoreCLR should never be presented with V1 IBC data. - if (fileHeader->Version == CORBBTPROF_V3_VERSION) - { - CORBBTPROF_FILE_OPTIONAL_HEADER *optionalHeader = - (CORBBTPROF_FILE_OPTIONAL_HEADER *)extraHeaderData; - - if (!optionalHeader || - !CONTAINS_FIELD(optionalHeader, extraHeaderDataSize, Size) || - (optionalHeader->Size > extraHeaderDataSize)) - { - m_zapper->Info(W("Optional header missing or corrupt.")); - return E_FAIL; - } - - if (CONTAINS_FIELD(optionalHeader, optionalHeader->Size, FileFlags)) - { - minified = !!(optionalHeader->FileFlags & CORBBTPROF_FILE_FLAG_MINIFIED); - - if (!m_zapper->m_pOpt->m_fPartialNGenSet) - { - m_zapper->m_pOpt->m_fPartialNGen = !!(optionalHeader->FileFlags & CORBBTPROF_FILE_FLAG_PARTIAL_NGEN); - } - } - } - else if (fileHeader->Version != CORBBTPROF_V2_VERSION) - { - m_zapper->Info(W("Discarding profile data with unknown version.")); - return S_FALSE; - } - - // This module has profile data (this ends up controlling the layout of physical and virtual - // sections within the image, see ZapImage::AllocateVirtualSections. - m_fHaveProfileData = true; - m_zapper->m_pOpt->m_fHasAnyProfileData = true; - - CORBBTPROF_SECTION_TABLE_HEADER *sectionHeader; - READ(sectionHeader, CORBBTPROF_SECTION_TABLE_HEADER); - - // - // Parse the section table - // - - for (ULONG i = 0; i < sectionHeader->NumEntries; i++) - { - CORBBTPROF_SECTION_TABLE_ENTRY *entry; - READ(entry,CORBBTPROF_SECTION_TABLE_ENTRY); - - SectionFormat format = sectionHeader->Entries[i].FormatID; - _ASSERTE(format >= 0); - if (format < 0) - { - continue; - } - - if (convertFromV1) - { - if (format < LastTokenFlagSection) - { - format = (SectionFormat) (format + 1); - } - } - - _ASSERTE(format < SectionFormatCount); - - if (format < SectionFormatCount) - { - BYTE *start = m_pRawProfileData + sectionHeader->Entries[i].Data.Offset; - BYTE *end = start + sectionHeader->Entries[i].Data.Size; - - if ((start > m_pRawProfileData) && - (end < m_pRawProfileData + m_cRawProfileData) && - (start < end)) - { - _ASSERTE(m_profileDataSections[format].pData == 0); - _ASSERTE(m_profileDataSections[format].dataSize == 0); - - m_profileDataSections[format].pData = start; - m_profileDataSections[format].dataSize = (DWORD) (end - start); - } - else - { - _ASSERTE(!"Invalid profile section offset or size"); - return E_FAIL; - } - } - } - - HRESULT hr = S_OK; - - if (convertFromV1) - { - hr = convertProfileDataFromV1(); - if (FAILED(hr)) - { - return hr; - } - } - else if (minified) - { - hr = RehydrateProfileData(); - if (FAILED(hr)) - { - return hr; - } - } - else - { - // - // For those sections that are collections of tokens, further parse that format to get - // the token pointer and number of tokens - // - - for (int format = FirstTokenFlagSection; format < SectionFormatCount; format++) - { - if (m_profileDataSections[format].pData) - { - SEEK(((ULONG) (m_profileDataSections[format].pData - m_pRawProfileData))); - - CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header; - READ(header, CORBBTPROF_TOKEN_LIST_SECTION_HEADER); - - DWORD tableSize = header->NumTokens; - DWORD dataSize = (m_profileDataSections[format].dataSize - sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER)); - DWORD expectedSize = tableSize * sizeof (CORBBTPROF_TOKEN_INFO); - - if (dataSize == expectedSize) - { - BYTE * startOfTable = m_profileDataSections[format].pData + sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER); - m_profileDataSections[format].tableSize = tableSize; - m_profileDataSections[format].pTable = (CORBBTPROF_TOKEN_INFO *) startOfTable; - } - else - { - _ASSERTE(!"Invalid CORBBTPROF_TOKEN_LIST_SECTION_HEADER header"); - return E_FAIL; - } - } - } - } - - ZapImage::ProfileDataSection * DataSection_ScenarioInfo = & m_profileDataSections[ScenarioInfo]; - if (DataSection_ScenarioInfo->pData != NULL) - { - CORBBTPROF_SCENARIO_INFO_SECTION_HEADER * header = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) DataSection_ScenarioInfo->pData; - m_profileDataNumRuns = header->TotalNumRuns; - } - - return S_OK; -} - - -HRESULT ZapImage::convertProfileDataFromV1() -{ - if (m_pRawProfileData == NULL) - { - return S_FALSE; - } - - // - // For those sections that are collections of tokens, further parse that format to get - // the token pointer and number of tokens - // - - ProfileReader profileReader(m_pRawProfileData, m_cRawProfileData); - - for (SectionFormat format = FirstTokenFlagSection; format < SectionFormatCount; format = (SectionFormat) (format + 1)) - { - if (m_profileDataSections[format].pData) - { - SEEK(((ULONG) (m_profileDataSections[format].pData - m_pRawProfileData))); - - CORBBTPROF_TOKEN_LIST_SECTION_HEADER *header; - READ(header, CORBBTPROF_TOKEN_LIST_SECTION_HEADER); - - DWORD tableSize = header->NumTokens; - - if (tableSize == 0) - { - m_profileDataSections[format].tableSize = 0; - m_profileDataSections[format].pTable = NULL; - continue; - } - - DWORD dataSize = (m_profileDataSections[format].dataSize - sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER)); - DWORD expectedSize = tableSize * sizeof (CORBBTPROF_TOKEN_LIST_ENTRY_V1); - - if (dataSize == expectedSize) - { - DWORD newDataSize = tableSize * sizeof (CORBBTPROF_TOKEN_INFO); - - if (newDataSize < dataSize) - return E_FAIL; - - BYTE * startOfTable = new (GetHeap()) BYTE[newDataSize]; - - CORBBTPROF_TOKEN_LIST_ENTRY_V1 * pOldEntry; - CORBBTPROF_TOKEN_INFO * pNewEntry; - - pOldEntry = (CORBBTPROF_TOKEN_LIST_ENTRY_V1 *) (m_profileDataSections[format].pData + sizeof(CORBBTPROF_TOKEN_LIST_SECTION_HEADER)); - pNewEntry = (CORBBTPROF_TOKEN_INFO *) startOfTable; - - for (DWORD i=0; itoken = pOldEntry->token; - pNewEntry->flags = pOldEntry->flags; - pNewEntry->scenarios = 1; - - pOldEntry++; - pNewEntry++; - } - m_profileDataSections[format].tableSize = tableSize; - m_profileDataSections[format].pTable = (CORBBTPROF_TOKEN_INFO *) startOfTable; - } - else - { - _ASSERTE(!"Invalid CORBBTPROF_TOKEN_LIST_SECTION_HEADER header"); - return E_FAIL; - } - } - } - - _ASSERTE(m_profileDataSections[ScenarioInfo].pData == 0); - _ASSERTE(m_profileDataSections[ScenarioInfo].dataSize == 0); - - // - // Convert the MethodBlockCounts format from V1 to V2 - // - CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 * mbcSectionHeader = NULL; - if (m_profileDataSections[MethodBlockCounts].pData) - { - // - // Compute the size of the method block count stream - // - BYTE * dstPtr = NULL; - BYTE * srcPtr = m_profileDataSections[MethodBlockCounts].pData; - DWORD maxSizeToRead = m_profileDataSections[MethodBlockCounts].dataSize; - DWORD totalSizeNeeded = 0; - DWORD totalSizeRead = 0; - - mbcSectionHeader = (CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1 *) srcPtr; - - totalSizeRead += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1); - totalSizeNeeded += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER); - srcPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1); - - if (totalSizeRead > maxSizeToRead) - { - return E_FAIL; - } - - for (DWORD i=0; (i < mbcSectionHeader->NumMethods); i++) - { - CORBBTPROF_METHOD_HEADER_V1* methodEntry = (CORBBTPROF_METHOD_HEADER_V1 *) srcPtr; - DWORD sizeRead = 0; - DWORD sizeWrite = 0; - - sizeRead += methodEntry->HeaderSize; - sizeRead += methodEntry->Size; - sizeWrite += sizeof(CORBBTPROF_METHOD_HEADER); - sizeWrite += methodEntry->Size; - - totalSizeRead += sizeRead; - totalSizeNeeded += sizeWrite; - - if (totalSizeRead > maxSizeToRead) - { - return E_FAIL; - } - - srcPtr += sizeRead; - } - assert(totalSizeRead == maxSizeToRead); - - // Reset the srcPtr - srcPtr = m_profileDataSections[MethodBlockCounts].pData; - - BYTE * newMethodData = new (GetHeap()) BYTE[totalSizeNeeded]; - - dstPtr = newMethodData; - - memcpy(dstPtr, srcPtr, sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER)); - srcPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER_V1); - dstPtr += sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER); - - for (DWORD i=0; (i < mbcSectionHeader->NumMethods); i++) - { - CORBBTPROF_METHOD_HEADER_V1 * methodEntryV1 = (CORBBTPROF_METHOD_HEADER_V1 *) srcPtr; - CORBBTPROF_METHOD_HEADER * methodEntry = (CORBBTPROF_METHOD_HEADER *) dstPtr; - DWORD sizeRead = 0; - DWORD sizeWrite = 0; - - methodEntry->method.token = methodEntryV1->MethodToken; - methodEntry->method.ILSize = 0; - methodEntry->method.cBlock = (methodEntryV1->Size / sizeof(CORBBTPROF_BLOCK_DATA)); - sizeRead += methodEntryV1->HeaderSize; - sizeWrite += sizeof(CORBBTPROF_METHOD_HEADER); - - memcpy( dstPtr + sizeof(CORBBTPROF_METHOD_HEADER), - srcPtr + sizeof(CORBBTPROF_METHOD_HEADER_V1), - (methodEntry->method.cBlock * sizeof(CORBBTPROF_BLOCK_DATA))); - sizeRead += methodEntryV1->Size; - sizeWrite += (methodEntry->method.cBlock * sizeof(CORBBTPROF_BLOCK_DATA)); - - methodEntry->size = sizeWrite; - methodEntry->cDetail = 0; - srcPtr += sizeRead; - dstPtr += sizeWrite; - } - - m_profileDataSections[MethodBlockCounts].pData = newMethodData; - m_profileDataSections[MethodBlockCounts].dataSize = totalSizeNeeded; - } - - // - // Allocate the scenario info section - // - { - DWORD sizeNeeded = sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER) + sizeof(CORBBTPROF_SCENARIO_HEADER); - BYTE * newData = new (GetHeap()) BYTE[sizeNeeded]; - BYTE * dstPtr = newData; - { - CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *siHeader = (CORBBTPROF_SCENARIO_INFO_SECTION_HEADER *) dstPtr; - - if (mbcSectionHeader != NULL) - siHeader->TotalNumRuns = mbcSectionHeader->NumRuns; - else - siHeader->TotalNumRuns = 1; - - siHeader->NumScenarios = 1; - - dstPtr += sizeof(CORBBTPROF_SCENARIO_INFO_SECTION_HEADER); - } - { - CORBBTPROF_SCENARIO_HEADER *sHeader = (CORBBTPROF_SCENARIO_HEADER *) dstPtr; - - sHeader->scenario.ordinal = 1; - sHeader->scenario.mask = 1; - sHeader->scenario.priority = 0; - sHeader->scenario.numRuns = 0; - sHeader->scenario.cName = 0; - - sHeader->size = sHeader->Size(); - - dstPtr += sizeof(CORBBTPROF_SCENARIO_HEADER); - } - m_profileDataSections[ScenarioInfo].pData = newData; - m_profileDataSections[ScenarioInfo].dataSize = sizeNeeded; - } - - // - // Convert the BlobStream format from V1 to V2 - // - if (m_profileDataSections[BlobStream].dataSize > 0) - { - // - // Compute the size of the blob stream - // - - BYTE * srcPtr = m_profileDataSections[BlobStream].pData; - BYTE * dstPtr = NULL; - DWORD maxSizeToRead = m_profileDataSections[BlobStream].dataSize; - DWORD totalSizeNeeded = 0; - DWORD totalSizeRead = 0; - bool done = false; - - while (!done) - { - CORBBTPROF_BLOB_ENTRY_V1* blobEntry = (CORBBTPROF_BLOB_ENTRY_V1 *) srcPtr; - DWORD sizeWrite = 0; - DWORD sizeRead = 0; - - if ((blobEntry->blobType >= MetadataStringPool) && (blobEntry->blobType <= MetadataUserStringPool)) - { - sizeWrite += sizeof(CORBBTPROF_BLOB_POOL_ENTRY); - sizeWrite += blobEntry->cBuffer; - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntry->cBuffer; - } - else if ((blobEntry->blobType >= ParamTypeSpec) && (blobEntry->blobType <= ParamMethodSpec)) - { - sizeWrite += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY); - sizeWrite += blobEntry->cBuffer; - if (blobEntry->blobType == ParamMethodSpec) - { - sizeWrite -= 1; // Adjust for ENCODE_METHOD_SIG prefix removal - } - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntry->cBuffer; - } - else if (blobEntry->blobType == EndOfBlobStream) - { - sizeWrite += sizeof(CORBBTPROF_BLOB_ENTRY); - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - done = true; - } - else - { - return E_FAIL; - } - - totalSizeNeeded += sizeWrite; - totalSizeRead += sizeRead; - - if (sizeRead > maxSizeToRead) - { - return E_FAIL; - } - - srcPtr += sizeRead; - } - - assert(totalSizeRead == maxSizeToRead); - - // Reset the srcPtr - srcPtr = m_profileDataSections[BlobStream].pData; - - BYTE * newBlobData = new (GetHeap()) BYTE[totalSizeNeeded]; - - dstPtr = newBlobData; - done = false; - - while (!done) - { - CORBBTPROF_BLOB_ENTRY_V1* blobEntryV1 = (CORBBTPROF_BLOB_ENTRY_V1 *) srcPtr; - DWORD sizeWrite = 0; - DWORD sizeRead = 0; - - if ((blobEntryV1->blobType >= MetadataStringPool) && (blobEntryV1->blobType <= MetadataUserStringPool)) - { - CORBBTPROF_BLOB_POOL_ENTRY* blobPoolEntry = (CORBBTPROF_BLOB_POOL_ENTRY*) dstPtr; - - blobPoolEntry->blob.type = blobEntryV1->blobType; - blobPoolEntry->blob.size = sizeof(CORBBTPROF_BLOB_POOL_ENTRY) + blobEntryV1->cBuffer; - blobPoolEntry->cBuffer = blobEntryV1->cBuffer; - memcpy(blobPoolEntry->buffer, blobEntryV1->pBuffer, blobEntryV1->cBuffer); - - sizeWrite += sizeof(CORBBTPROF_BLOB_POOL_ENTRY); - sizeWrite += blobEntryV1->cBuffer; - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntryV1->cBuffer; - } - else if ((blobEntryV1->blobType >= ParamTypeSpec) && (blobEntryV1->blobType <= ParamMethodSpec)) - { - CORBBTPROF_BLOB_PARAM_SIG_ENTRY* blobSigEntry = (CORBBTPROF_BLOB_PARAM_SIG_ENTRY*) dstPtr; - - blobSigEntry->blob.type = blobEntryV1->blobType; - blobSigEntry->blob.size = sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY) + blobEntryV1->cBuffer; - blobSigEntry->blob.token = 0; - blobSigEntry->cSig = blobEntryV1->cBuffer; - - if (blobEntryV1->blobType == ParamMethodSpec) - { - // Adjust cSig and blob.size - blobSigEntry->cSig--; - blobSigEntry->blob.size--; - } - memcpy(blobSigEntry->sig, blobEntryV1->pBuffer, blobSigEntry->cSig); - - sizeWrite += sizeof(CORBBTPROF_BLOB_PARAM_SIG_ENTRY); - sizeWrite += blobSigEntry->cSig; - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - sizeRead += blobEntryV1->cBuffer; - } - else if (blobEntryV1->blobType == EndOfBlobStream) - { - CORBBTPROF_BLOB_ENTRY* blobEntry = (CORBBTPROF_BLOB_ENTRY*) dstPtr; - - blobEntry->type = blobEntryV1->blobType; - blobEntry->size = sizeof(CORBBTPROF_BLOB_ENTRY); - - sizeWrite += sizeof(CORBBTPROF_BLOB_ENTRY); - sizeRead += sizeof(CORBBTPROF_BLOB_ENTRY_V1); - done = true; - } - else - { - return E_FAIL; - } - srcPtr += sizeRead; - dstPtr += sizeWrite; - } - - m_profileDataSections[BlobStream].pData = newBlobData; - m_profileDataSections[BlobStream].dataSize = totalSizeNeeded; - } - else - { - m_profileDataSections[BlobStream].pData = NULL; - m_profileDataSections[BlobStream].dataSize = 0; - } - - return S_OK; -} - -void ZapImage::RehydrateBasicBlockSection() -{ - ProfileDataSection §ion = m_profileDataSections[MethodBlockCounts]; - if (!section.pData) - { - return; - } - - ProfileReader reader(section.pData, section.dataSize); - - m_profileDataNumRuns = reader.Read(); - - // The IBC data provides a hint to the number of basic blocks, which is - // used here to determine how much space to allocate for the rehydrated - // data. - unsigned int blockCountHint = reader.Read(); - - unsigned int numMethods = reader.Read(); - - unsigned int expectedLength = - sizeof(CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER) + - sizeof(CORBBTPROF_METHOD_HEADER) * numMethods + - sizeof(CORBBTPROF_BLOCK_DATA) * blockCountHint; - - BinaryWriter writer(expectedLength, GetHeap()); - - writer.Write(numMethods); - - mdToken lastMethodToken = 0x06000000; - - CORBBTPROF_METHOD_HEADER methodHeader; - methodHeader.cDetail = 0; - methodHeader.method.ILSize = 0; - - for (unsigned int i = 0; i < numMethods; ++i) - { - // Translate the method header - unsigned int size = reader.Read7BitEncodedInt(); - unsigned int startPosition = reader.GetCurrentPos(); - - mdToken token = reader.ReadTokenWithMemory(lastMethodToken); - unsigned int ilSize = reader.Read7BitEncodedInt(); - unsigned int firstBlockHitCount = reader.Read7BitEncodedInt(); - - unsigned int numOtherBlocks = reader.Read7BitEncodedInt(); - - methodHeader.method.cBlock = 1 + numOtherBlocks; - methodHeader.method.token = token; - methodHeader.method.ILSize = ilSize; - methodHeader.size = (DWORD)methodHeader.Size(); - - writer.Write(methodHeader); - - CORBBTPROF_BLOCK_DATA blockData; - - // The first block is handled specially. - blockData.ILOffset = 0; - blockData.ExecutionCount = firstBlockHitCount; - - writer.Write(blockData); - - // Translate the rest of the basic blocks - for (unsigned int j = 0; j < numOtherBlocks; ++j) - { - blockData.ILOffset = reader.Read7BitEncodedInt(); - blockData.ExecutionCount = reader.Read7BitEncodedInt(); - - writer.Write(blockData); - } - - if (!reader.Seek(startPosition + size)) - { - ThrowHR(E_FAIL); - } - } - - // If the expected and actual lengths differ, the result will still be - // correct but performance may suffer slightly because of reallocations. - _ASSERTE(writer.GetWrittenSize() == expectedLength); - - section.pData = writer.GetBuffer(); - section.dataSize = writer.GetWrittenSize(); -} - -void ZapImage::RehydrateTokenSection(int sectionFormat, unsigned int flagTable[255]) -{ - ProfileDataSection §ion = m_profileDataSections[sectionFormat]; - ProfileReader reader(section.pData, section.dataSize); - - unsigned int numTokens = reader.Read(); - - unsigned int dataLength = sizeof(unsigned int) + - numTokens * sizeof(CORBBTPROF_TOKEN_INFO); - BinaryWriter writer(dataLength, GetHeap()); - - writer.Write(numTokens); - - mdToken lastToken = (sectionFormat - FirstTokenFlagSection) << 24; - - CORBBTPROF_TOKEN_INFO tokenInfo; - tokenInfo.scenarios = 1; - - for (unsigned int i = 0; i < numTokens; ++i) - { - tokenInfo.token = reader.ReadTokenWithMemory(lastToken); - tokenInfo.flags = reader.ReadFlagWithLookup(flagTable); - - writer.Write(tokenInfo); - } - - _ASSERTE(writer.GetWrittenSize() == dataLength); - - section.pData = writer.GetBuffer(); - section.dataSize = writer.GetWrittenSize(); - section.pTable = (CORBBTPROF_TOKEN_INFO *)(section.pData + sizeof(unsigned int)); - section.tableSize = numTokens; -} - -void ZapImage::RehydrateBlobStream() -{ - ProfileDataSection §ion = m_profileDataSections[BlobStream]; - - ProfileReader reader(section.pData, section.dataSize); - - // Evidence suggests that rehydrating the blob stream in Framework binaries - // increases the size from 1.5-2x. When this was written, 1.85x minimized - // the amount of extra memory allocated (about 48K in the worst case). - BinaryWriter writer((DWORD)(section.dataSize * 1.85f), GetHeap()); - - mdToken LastBlobToken = 0; - mdToken LastAssemblyToken = 0x23000000; - mdToken LastExternalTypeToken = 0x62000000; - mdToken LastExternalNamespaceToken = 0x61000000; - mdToken LastExternalSignatureToken = 0x63000000; - - int blobType = 0; - do - { - // Read the blob header. - - unsigned int sizeToRead = reader.Read7BitEncodedInt(); - unsigned int startPositionRead = reader.GetCurrentPos(); - - blobType = reader.Read7BitEncodedInt(); - mdToken token = reader.ReadTokenWithMemory(LastBlobToken); - - // Write out the blob header. - - // Note the location in the write stream, and write a 0 there. Once - // this blob has been written in its entirety, this location can be - // used to calculate the real size and to go back to the right place - // to write it. - - unsigned int startPositionWrite = writer.GetWrittenSize(); - writer.Write(0U); - - writer.Write(blobType); - writer.Write(token); - - // All blobs (except the end-of-stream indicator) end as: - // - // Two blob types (handled immediately below) include tokens as well. - // Handle those first, then handle the common case. - - if (blobType == ExternalTypeDef) - { - writer.Write(reader.ReadTokenWithMemory(LastAssemblyToken)); - writer.Write(reader.ReadTokenWithMemory(LastExternalTypeToken)); - writer.Write(reader.ReadTokenWithMemory(LastExternalNamespaceToken)); - } - else if (blobType == ExternalMethodDef) - { - writer.Write(reader.ReadTokenWithMemory(LastExternalTypeToken)); - writer.Write(reader.ReadTokenWithMemory(LastExternalSignatureToken)); - } - - if ((blobType >= MetadataStringPool) && (blobType < IllegalBlob)) - { - // This blob is of known type and ends with data. - unsigned int dataLength = reader.Read7BitEncodedInt(); - char *data = (char *)reader.Read(dataLength); - - if (!data) - { - ThrowHR(E_FAIL); - } - - writer.Write(dataLength); - writer.Write(data, dataLength); - } - - // Write the size for this blob. - - writer.WriteAt(startPositionWrite, - writer.GetWrittenSize() - startPositionWrite); - - // Move to the next blob. - - if (!reader.Seek(startPositionRead + sizeToRead)) - { - ThrowHR(E_FAIL); - } - } - while (blobType != EndOfBlobStream); - - section.pData = writer.GetBuffer(); - section.dataSize = writer.GetWrittenSize(); -} - -HRESULT ZapImage::RehydrateProfileData() -{ - HRESULT hr = S_OK; - unsigned int flagTable[255]; - memset(flagTable, 0xFF, sizeof(flagTable)); - - EX_TRY - { - RehydrateBasicBlockSection(); - RehydrateBlobStream(); - for (int format = FirstTokenFlagSection; - format < SectionFormatCount; - ++format) - { - if (m_profileDataSections[format].pData) - { - RehydrateTokenSection(format, flagTable); - } - } - } - EX_CATCH_HRESULT_NO_ERRORINFO(hr); - - return hr; -} - -HRESULT ZapImage::hashMethodBlockCounts() -{ - ProfileDataSection * DataSection_MethodBlockCounts = & m_profileDataSections[MethodBlockCounts]; - - if (!DataSection_MethodBlockCounts->pData) - { - return E_FAIL; - } - - ProfileReader profileReader(DataSection_MethodBlockCounts->pData, DataSection_MethodBlockCounts->dataSize); - - CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER *mbcHeader; - READ(mbcHeader,CORBBTPROF_METHOD_BLOCK_COUNTS_SECTION_HEADER); - - for (DWORD i = 0; i < mbcHeader->NumMethods; i++) - { - ProfileDataHashEntry newEntry; - newEntry.pos = profileReader.GetCurrentPos(); - - CORBBTPROF_METHOD_HEADER *methodHeader; - READ(methodHeader,CORBBTPROF_METHOD_HEADER); - newEntry.md = methodHeader->method.token; - newEntry.size = methodHeader->size; - newEntry.flags = 0; - newEntry.status = NOT_COMPILED; - - // Add the new entry to the table - profileDataHashTable.Add(newEntry); - - // Skip the profileData so we can read the next method. - void *profileData; - READ_SIZE(profileData, void, (methodHeader->size - sizeof(CORBBTPROF_METHOD_HEADER))); - } - - return S_OK; -} - -void ZapImage::hashBBUpdateFlagsAndCompileResult(mdToken token, unsigned methodProfilingDataFlags, ZapImage::CompileStatus compileResult) -{ - // SHash only supports replacing an entry so we setup our newEntry and then perform a lookup - // - ProfileDataHashEntry newEntry; - newEntry.md = token; - newEntry.flags = methodProfilingDataFlags; - newEntry.status = compileResult; - - const ProfileDataHashEntry* pEntry = profileDataHashTable.LookupPtr(token); - if (pEntry != nullptr) - { - assert(pEntry->md == newEntry.md); - assert(pEntry->flags == 0); // the flags should not be set at this point. - - // Copy and keep the two fields that were previously set - newEntry.size = pEntry->size; - newEntry.pos = pEntry->pos; - } - else // We have a method that doesn't have basic block counts - { - newEntry.size = 0; - newEntry.pos = 0; - } - profileDataHashTable.AddOrReplace(newEntry); -} - -void ZapImage::LoadProfileData() -{ - HRESULT hr = E_FAIL; - - m_fHaveProfileData = false; - m_pRawProfileData = NULL; - m_cRawProfileData = 0; - - EX_TRY - { - hr = LocateProfileData(); - - if (hr == S_OK) - { - hr = parseProfileData(); - if (hr == S_OK) - { - hr = hashMethodBlockCounts(); - } - } - } - EX_CATCH - { - hr = E_FAIL; - } - EX_END_CATCH(SwallowAllExceptions); - - if (hr != S_OK) - { - m_fHaveProfileData = false; - m_pRawProfileData = NULL; - m_cRawProfileData = 0; - - if (FAILED(hr)) - { - m_zapper->Warning(W("Warning: Invalid profile data was ignored for %s\n"), m_pModuleFileName); - } - } - -#ifdef CROSSGEN_COMPILE - if (m_zapper->m_pOpt->m_fPartialNGen && (m_pRawProfileData == NULL || m_cRawProfileData == 0)) - { - ThrowHR(CLR_E_CROSSGEN_NO_IBC_DATA_FOUND); - } -#endif -} - -// Initializes our form of the profile data stored in the assembly. - -CorProfileData * ZapImage::NewProfileData() -{ - this->m_pCorProfileData = new CorProfileData(&m_profileDataSections[0]); - - return this->m_pCorProfileData; -} - -// Returns the profile data stored in the assembly. - -CorProfileData * ZapImage::GetProfileData() -{ - _ASSERTE(this->m_pCorProfileData != NULL); - - return this->m_pCorProfileData; -} - -CorProfileData::CorProfileData(void * rawProfileData) -{ - ZapImage::ProfileDataSection * profileData = (ZapImage::ProfileDataSection *) rawProfileData; - - for (DWORD format = 0; format < SectionFormatCount; format++) - { - this->profilingTokenFlagsData[format].count = profileData[format].tableSize; - this->profilingTokenFlagsData[format].data = profileData[format].pTable; - } - - this->blobStream = (CORBBTPROF_BLOB_ENTRY *) profileData[BlobStream].pData; -} - - -// Determines whether a method can be called directly from another method (without -// going through the prestub) in the current module. -// callerFtn=NULL implies any/unspecified caller in the current module. -// -// Returns NULL if 'calleeFtn' cannot be called directly *at the current time* -// Else returns the direct address that 'calleeFtn' can be called at. - - -bool ZapImage::canIntraModuleDirectCall( - CORINFO_METHOD_HANDLE callerFtn, - CORINFO_METHOD_HANDLE targetFtn, - CorInfoIndirectCallReason *pReason, - CORINFO_ACCESS_FLAGS accessFlags/*=CORINFO_ACCESS_ANY*/) -{ - CorInfoIndirectCallReason reason; - if (pReason == NULL) - pReason = &reason; - *pReason = CORINFO_INDIRECT_CALL_UNKNOWN; - - // The caller should have checked that the method is in current loader module - _ASSERTE(m_hModule == m_zapper->m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(targetFtn)); - - // No direct calls at all under some circumstances - - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE) - && !m_pPreloader->IsDynamicMethod(callerFtn)) - { - *pReason = CORINFO_INDIRECT_CALL_PROFILING; - goto CALL_VIA_ENTRY_POINT; - } - - // Does the method's class have a cctor, etc? - - if (!m_pPreloader->CanSkipMethodPreparation(callerFtn, targetFtn, pReason, accessFlags)) - goto CALL_VIA_ENTRY_POINT; - - ZapMethodHeader * pMethod; - pMethod = GetCompiledMethod(targetFtn); - - // If we have not compiled the method, then we can't call directly - - if (pMethod == NULL) - { - *pReason = CORINFO_INDIRECT_CALL_NO_CODE; - goto CALL_VIA_ENTRY_POINT; - } - - // Does the method have fixups? - - if (pMethod->HasFixups() != NULL) - { - *pReason = CORINFO_INDIRECT_CALL_FIXUPS; - goto CALL_VIA_ENTRY_POINT; - } - -#ifdef _DEBUG - const char* clsName, * methodName; - methodName = m_zapper->m_pEEJitInfo->getMethodName(targetFtn, &clsName); - LOG((LF_ZAP, LL_INFO10000, "getIntraModuleDirectCallAddr: Success %s::%s\n", - clsName, methodName)); -#endif - - return true; - -CALL_VIA_ENTRY_POINT: - -#ifdef _DEBUG - methodName = m_zapper->m_pEEJitInfo->getMethodName(targetFtn, &clsName); - LOG((LF_ZAP, LL_INFO10000, "getIntraModuleDirectCallAddr: Via EntryPoint %s::%s\n", - clsName, methodName)); -#endif - - return false; -} - -// -// Relocations -// - -void ZapImage::WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type) -{ - _ASSERTE(!IsWritingRelocs()); - - _ASSERTE(m_pBaseRelocs != NULL); - m_pBaseRelocs->WriteReloc(pSrc, offset, pTarget, targetOffset, type); -} - -ZapImage * ZapImage::GetZapImage() -{ - return this; -} - -void ZapImage::FileNotFoundError(LPCWSTR pszMessage) -{ - SString message(pszMessage); - - for (COUNT_T i = 0; i < fileNotFoundErrorsTable.GetCount(); i++) - { - // Check to see if same error has already been displayed for this ngen operation - if (message.Equals(fileNotFoundErrorsTable[i])) - return; - } - - CorZapLogLevel level; - -#ifdef CROSSGEN_COMPILE - // Warnings should not go to stderr during crossgen - level = CORZAP_LOGLEVEL_WARNING; -#else - level = CORZAP_LOGLEVEL_ERROR; -#endif - - m_zapper->Print(level, W("Warning: %s.\n"), pszMessage); - - fileNotFoundErrorsTable.Append(message); -} - -void ZapImage::Error(mdToken token, HRESULT hr, UINT resID, LPCWSTR message) -{ - // Missing dependencies are reported as fatal errors in code:CompilationDomain::BindAssemblySpec. - // Avoid printing redundant error message for them. - if (FAILED(g_hrFatalError)) - ThrowHR(g_hrFatalError); - - // COM introduces the notion of a vtable gap method, which is not a real method at all but instead - // aids in the explicit layout of COM interop vtables. These methods have no implementation and no - // direct runtime state tracking them. Trying to lookup a method handle for a vtable gap method will - // throw an exception but we choose to let that happen and filter out the warning here in the - // handler because (a) vtable gap methods are rare and (b) it's not all that cheap to identify them - // beforehand. - if ((TypeFromToken(token) == mdtMethodDef) && IsVTableGapMethod(token)) - { - return; - } - - CorZapLogLevel level = CORZAP_LOGLEVEL_ERROR; - - // Some warnings are demoted to informational level - if (resID == IDS_EE_SIMD_NGEN_DISALLOWED) - { - // Suppress printing of "Target-dependent SIMD vector types may not be used with ngen." - level = CORZAP_LOGLEVEL_INFO; - } - - if (resID == IDS_EE_HWINTRINSIC_NGEN_DISALLOWED) - { - // Suppress printing of "Hardware intrinsics may not be used with ngen." - level = CORZAP_LOGLEVEL_INFO; - } - -#ifdef CROSSGEN_COMPILE - if ((resID == IDS_IBC_MISSING_EXTERNAL_TYPE) || - (resID == IDS_IBC_MISSING_EXTERNAL_METHOD)) - { - // Suppress printing IBC related warnings except in verbose mode. - if (m_zapper->m_pOpt->m_ignoreErrors && !m_zapper->m_pOpt->m_verbose) - return; - - // Suppress printing of "The generic type/method specified by the IBC data is not available to this assembly" - level = CORZAP_LOGLEVEL_INFO; - } -#endif - - if (m_zapper->m_pOpt->m_ignoreErrors) - { -#ifdef CROSSGEN_COMPILE - // Warnings should not go to stderr during crossgen - if (level == CORZAP_LOGLEVEL_ERROR) - { - level = CORZAP_LOGLEVEL_WARNING; - } -#endif - m_zapper->Print(level, W("Warning: ")); - } - else - { - m_zapper->Print(level, W("Error: ")); - } - - if (message != NULL) - m_zapper->Print(level, W("%s"), message); - else - m_zapper->PrintErrorMessage(level, hr); - - m_zapper->Print(level, W(" while resolving 0x%x - "), token); - PrintTokenDescription(level, token); - m_zapper->Print(level, W(".\n")); - - if (m_zapper->m_pOpt->m_ignoreErrors) - return; - - IfFailThrow(hr); -} - -ZapNode * ZapImage::GetInnerPtr(ZapNode * pNode, SSIZE_T offset) -{ - return m_pInnerPtrs->Get(pNode, offset); -} - -ZapNode * ZapImage::GetHelperThunk(CorInfoHelpFunc ftnNum) -{ - ZapNode * pHelperThunk = m_pHelperThunks[ftnNum]; - - if (pHelperThunk == NULL) - { - pHelperThunk = new (GetHeap()) ZapHelperThunk(ftnNum); -#ifdef TARGET_ARM - pHelperThunk = GetInnerPtr(pHelperThunk, THUMB_CODE); -#endif - m_pHelperThunks[ftnNum] = pHelperThunk; - } - - // Ensure that the thunk is placed - ZapNode * pTarget = pHelperThunk; - if (pTarget->GetType() == ZapNodeType_InnerPtr) - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - if (!pTarget->IsPlaced()) - m_pHelperTableSection->Place(pTarget); - - return pHelperThunk; -} - -// -// Compute a class-layout order based on a breadth-first traversal of -// the class graph (based on what classes contain calls to other classes). -// We cannot afford time or space to build the graph, so we do processing -// in place. -// -void ZapImage::ComputeClassLayoutOrder() -{ - // In order to make the computation efficient, we need to store per-class - // intermediate values in the class layout field. These come in two forms: - // - // - An entry with the UNSEEN_CLASS_FLAG set is one that is yet to be encountered. - // - An entry with METHOD_INDEX_FLAG set is an index into the m_MethodCompilationOrder list - // indicating where the unprofiled methods of this class begin - // - // Both flags begin set (by InitializeClassLayoutOrder) since the value initialized is - // the method index and the class has not been encountered by the algorithm. - // When a class layout has been computed, both of these flags will have been stripped. - - - // Early-out in the (probably impossible) case that these bits weren't available - if (m_MethodCompilationOrder.GetCount() >= UNSEEN_CLASS_FLAG || - m_MethodCompilationOrder.GetCount() >= METHOD_INDEX_FLAG) - { - return; - } - - // Allocate the queue for the breadth-first traversal. - // Note that the use of UNSEEN_CLASS_FLAG ensures that no class is enqueued more - // than once, so we can use that bound for the size of the queue. - CORINFO_CLASS_HANDLE * classQueue = new CORINFO_CLASS_HANDLE[m_ClassLayoutOrder.GetCount()]; - - unsigned classOrder = 0; - for (COUNT_T i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++) - { - unsigned classQueueNext = 0; - unsigned classQueueEnd = 0; - COUNT_T methodIndex = 0; - - // - // Find an unprocessed method to seed the next breadth-first traversal. - // - - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - const ClassLayoutOrderEntry * pEntry = m_ClassLayoutOrder.LookupPtr(pMethod->m_classHandle); - _ASSERTE(pEntry); - - if ((pEntry->m_order & UNSEEN_CLASS_FLAG) == 0) - { - continue; - } - - // - // Enqueue the method's class and start the traversal. - // - - classQueue[classQueueEnd++] = pMethod->m_classHandle; - ((ClassLayoutOrderEntry *)pEntry)->m_order &= ~UNSEEN_CLASS_FLAG; - - while (classQueueNext < classQueueEnd) - { - // - // Dequeue a class and pull out the index of its first method - // - - CORINFO_CLASS_HANDLE dequeuedClassHandle = classQueue[classQueueNext++]; - _ASSERTE(dequeuedClassHandle != NULL); - - pEntry = m_ClassLayoutOrder.LookupPtr(dequeuedClassHandle); - _ASSERTE(pEntry); - _ASSERTE((pEntry->m_order & UNSEEN_CLASS_FLAG) == 0); - _ASSERTE((pEntry->m_order & METHOD_INDEX_FLAG) != 0); - - methodIndex = pEntry->m_order & ~METHOD_INDEX_FLAG; - _ASSERTE(methodIndex < m_MethodCompilationOrder.GetCount()); - - // - // Set the real layout order of the class, and examine its unprofiled methods - // - - ((ClassLayoutOrderEntry *)pEntry)->m_order = ++classOrder; - - pMethod = m_MethodCompilationOrder[methodIndex]; - _ASSERTE(pMethod->m_classHandle == dequeuedClassHandle); - - while (pMethod->m_classHandle == dequeuedClassHandle) - { - - // - // For each unprofiled method, find target classes and enqueue any that haven't been seen - // - - ZapMethodHeader::PartialTargetMethodIterator it(pMethod); - - CORINFO_METHOD_HANDLE targetMethodHandle; - while (it.GetNext(&targetMethodHandle)) - { - CORINFO_CLASS_HANDLE targetClassHandle = GetJitInfo()->getMethodClass(targetMethodHandle); - if (targetClassHandle != pMethod->m_classHandle) - { - pEntry = m_ClassLayoutOrder.LookupPtr(targetClassHandle); - - if (pEntry && (pEntry->m_order & UNSEEN_CLASS_FLAG) != 0) - { - _ASSERTE(classQueueEnd < m_ClassLayoutOrder.GetCount()); - classQueue[classQueueEnd++] = targetClassHandle; - - ((ClassLayoutOrderEntry *)pEntry)->m_order &= ~UNSEEN_CLASS_FLAG; - } - } - } - - if (++methodIndex == m_MethodCompilationOrder.GetCount()) - { - break; - } - - pMethod = m_MethodCompilationOrder[methodIndex]; - } - } - } - - for (COUNT_T i = m_iUntrainedMethod; i < m_MethodCompilationOrder.GetCount(); i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - pMethod->m_cachedLayoutOrder = LookupClassLayoutOrder(pMethod->m_classHandle); - } - - m_fHasClassLayoutOrder = true; - - delete [] classQueue; -} - -static int __cdecl LayoutOrderCmp(const void* a_, const void* b_) -{ - ZapMethodHeader * a = *((ZapMethodHeader**)a_); - ZapMethodHeader * b = *((ZapMethodHeader**)b_); - - int layoutDiff = a->GetCachedLayoutOrder() - b->GetCachedLayoutOrder(); - if (layoutDiff != 0) - return layoutDiff; - - // Use compilation order as secondary key to get predictable ordering within the bucket - return a->GetCompilationOrder() - b->GetCompilationOrder(); -} - -void ZapImage::SortUnprofiledMethodsByClassLayoutOrder() -{ - qsort(&m_MethodCompilationOrder[m_iUntrainedMethod], m_MethodCompilationOrder.GetCount() - m_iUntrainedMethod, sizeof(ZapMethodHeader *), LayoutOrderCmp); -} diff --git a/src/coreclr/zap/zapimage.h b/src/coreclr/zap/zapimage.h deleted file mode 100644 index 10705b98e36512..00000000000000 --- a/src/coreclr/zap/zapimage.h +++ /dev/null @@ -1,1103 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImage.h -// - -// -// NGEN-specific infrastructure for writing PE files. -// -// ====================================================================================== - -#ifndef __ZAPIMAGE_H__ -#define __ZAPIMAGE_H__ - -class ZapMetaData; -class ZapILMetaData; -class ZapCorHeader; -class ZapNativeHeader; -class ZapVersionInfo; -class ZapDependencies; -class ZapCodeManagerEntry; - -class ZapReadyToRunHeader; - -class ZapInnerPtrTable; -class ZapMethodEntryPointTable; -class ZapWrapperTable; - -class ZapBaseRelocs; - -class ZapBlobWithRelocs; - -//class ZapGCInfoTable; -#ifdef FEATURE_EH_FUNCLETS -class ZapUnwindDataTable; -#endif - -class ZapImportTable; -class ZapImportSectionsTable; -class ZapImportSectionSignatures; - -class ZapVirtualSectionsTable; -class DataImage; - -class ZapperStats; - -#undef SAFERELEASE -#define SAFERELEASE(p) if ((p) != NULL) { IUnknown * _ = (p); (p) = NULL; _->Release(); }; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) -#define DEFAULT_CODE_BUFFER_INIT 0xcc // breakpoint -#else -#define DEFAULT_CODE_BUFFER_INIT 0 -#endif - -#ifdef TARGET_64BIT -// Optimize for speed -#define DEFAULT_CODE_ALIGN 16 -#else -// Optimize for size. -#define DEFAULT_CODE_ALIGN 4 -#endif - -#ifdef TARGET_ARM -#define MINIMUM_CODE_ALIGN 2 -#elif TARGET_ARM64 -#define MINIMUM_CODE_ALIGN 4 -#else -#define MINIMUM_CODE_ALIGN 1 -#endif - -// Various zapper hashtables are preallocated based on the size of IL image to reduce amount of -// rehashing we have to do. Turn ZAP_HASHTABLE_TUNING on to collect data for the tuning of initial hashtable sizes. -// #define ZAP_HASHTABLE_TUNING - -#ifdef ZAP_HASHTABLE_TUNING - -#define PREALLOCATE_HASHTABLE(table, quotient, cbILImage) \ - PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) - -#define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) \ - do { \ - GetSvcLogger()->Printf(W("HashTable:\t%S\t%d\t%f\n"), #table, table.GetCount(), (double)table.GetCount() / (double)cbILImage); \ - } while (0) - -#define PREALLOCATE_ARRAY(array, quotient, cbILImage) \ - do { \ - GetSvcLogger()->Printf(W("Array:\t%S\t%d\t%f\n"), #array, array.GetCount(), (double)array.GetCount() / (double)cbILImage); \ - } while (0) - -#else // ZAP_HASHTABLE_TUNING - -#define PREALLOCATE_HASHTABLE(table, quotient, cbILImage) \ - do { \ - COUNT_T nSize = (COUNT_T)(quotient * \ - ((double)table.s_density_factor_denominator / (double)table.s_density_factor_numerator) * \ - cbILImage); \ - if (nSize > table.s_minimum_allocation) \ - table.Reallocate(nSize); \ - } while (0) - -#define PREALLOCATE_HASHTABLE_NOT_NEEDED(table, cbILImage) - -#define PREALLOCATE_ARRAY(array, quotient, cbILImage) \ - do { \ - COUNT_T nSize = (COUNT_T)(quotient * \ - cbILImage); \ - array.Preallocate(nSize); \ - } while (0) - -#endif // ZAP_HASHTABLE_TUNING - -//--------------------------------------------------------------------------------------- -// -// ZapImportSectionType is enum describing import sections allocated in the image -// -enum ZapImportSectionType -{ - ZapImportSectionType_Handle, // Unspecified handle - ZapImportSectionType_TypeHandle, // Type and method handles have to have their own section so we can restore them correctly - ZapImportSectionType_MethodHandle, -#ifdef TARGET_ARM - ZapImportSectionType_PCode, // Code pointers have to be in a own section on ARM because of they are tagged differently -#endif - ZapImportSectionType_StringHandle, // String handles require special handling for interning - ZapImportSectionType_Count, - - ZapImportSectionType_Hot = 0, // We have two sets of the section - hot and cold - ZapImportSectionType_Cold = ZapImportSectionType_Count, - - ZapImportSectionType_Eager = 2 * ZapImportSectionType_Count, // And one section for eager loaded handles - - ZapImportSectionType_Total = 2 * ZapImportSectionType_Count + 1, -}; - -#include "zaprelocs.h" -#include "zapinfo.h" -#include "zapcode.h" - -class ZapImage - : public ZapWriter - , public ICorCompileDataStore -{ - friend class Zapper; - friend class ZapInfo; - friend class ZapILMetaData; - friend class ZapImportTable; - friend class ZapCodeMethodDescs; - friend class ZapColdCodeMap; - friend class ZapReadyToRunHeader; - - private: - - Zapper *m_zapper; - - // - // Output module - // - - LPWSTR m_pOutputFileFullName; // Name of the temp ngen file to generate (including the path) - - // - // Make all virtual section pointers public for now. It should be cleaned up as we get more sophisticated layout - // algorithm in place. - // -public: - ZapPhysicalSection * m_pTextSection; - - // - // All virtual sections of the native image in alphabetical order - // - - ZapVirtualSection * m_pBaseRelocsSection; - ZapVirtualSection * m_pCodeSection; - ZapVirtualSection * m_pColdCodeSection; - ZapVirtualSection * m_pDebugSection; - ZapVirtualSection * m_pDelayLoadInfoDelayListSectionEager; - ZapVirtualSection * m_pDelayLoadInfoDelayListSectionCold; - ZapVirtualSection * m_pDelayLoadInfoDelayListSectionHot; - ZapVirtualSection * m_pDelayLoadInfoTableSection[ZapImportSectionType_Total]; - ZapVirtualSection * m_pStubsSection; - ZapVirtualSection * m_pEETableSection; - ZapVirtualSection * m_pExceptionSection; - ZapVirtualSection * m_pGCSection; - ZapVirtualSection * m_pHeaderSection; - ZapVirtualSection * m_pHelperTableSection; - ZapVirtualSection * m_pLazyHelperSection; - ZapVirtualSection * m_pLazyMethodCallHelperSection; - ZapVirtualSection * m_pHotCodeSection; - ZapVirtualSection * m_pHotGCSection; - ZapVirtualSection * m_pHotTouchedGCSection; - ZapVirtualSection * m_pILMetaDataSection; - ZapVirtualSection * m_pILSection; - ZapVirtualSection * m_pImportTableSection; - ZapVirtualSection * m_pInstrumentSection; - ZapVirtualSection * m_pMetaDataSection; - ZapVirtualSection * m_pReadOnlyDataSection; - ZapVirtualSection * m_pResourcesSection; - ZapVirtualSection * m_pWin32ResourceSection; - ZapVirtualSection * m_pStubDispatchCellSection; - ZapVirtualSection * m_pStubDispatchDataSection; - ZapVirtualSection * m_pDynamicHelperCellSection; - ZapVirtualSection * m_pDynamicHelperDataSection; - ZapVirtualSection * m_pVirtualImportThunkSection; - ZapVirtualSection * m_pExternalMethodThunkSection; - ZapVirtualSection * m_pExternalMethodCellSection; - ZapVirtualSection * m_pExternalMethodDataSection; - ZapVirtualSection * m_pHotRuntimeFunctionSection; - ZapVirtualSection * m_pRuntimeFunctionSection; - ZapVirtualSection * m_pColdRuntimeFunctionSection; - ZapVirtualSection * m_pHotCodeMethodDescsSection; - ZapVirtualSection * m_pCodeMethodDescsSection; - ZapVirtualSection * m_pHotRuntimeFunctionLookupSection; - ZapVirtualSection * m_pRuntimeFunctionLookupSection; - ZapVirtualSection * m_pColdCodeMapSection; -#if defined(FEATURE_EH_FUNCLETS) - ZapVirtualSection * m_pHotUnwindDataSection; - ZapVirtualSection * m_pUnwindDataSection; - ZapVirtualSection * m_pColdUnwindDataSection; -#endif // defined(FEATURE_EH_FUNCLETS) - -#ifdef FEATURE_READYTORUN_COMPILER - ZapVirtualSection * m_pAvailableTypesSection; - ZapVirtualSection * m_pAttributePresenceSection; -#endif - - // Preloader sections - ZapVirtualSection * m_pPreloadSections[CORCOMPILE_SECTION_COUNT]; - - ZapExceptionInfoLookupTable* m_pExceptionInfoLookupTable; -public: - // TODO: Remove once all EE datastructures are converted to ZapNodes - ICorCompilePreloader * m_pPreloader; - DataImage * m_pDataImage; - -public: - // TODO: The stats should be removed once we have all information available in nidump - ZapperStats *m_stats; - -private: - IMetaDataAssemblyEmit *m_pAssemblyEmit; // native image manifest - ZapMetaData * m_pAssemblyMetaData; - - ZapVersionInfo * m_pVersionInfo; - ZapDependencies * m_pDependencies; - - SString m_pdbFileName; - - ZapCodeManagerEntry * m_pCodeManagerEntry; - - ZapBlob * m_pEEInfoTable; - - // - // Auxiliary tables - // - ZapImportTable * m_pImportTable; - - ZapImportSectionsTable * m_pImportSectionsTable; - - ZapInnerPtrTable * m_pInnerPtrs; - - ZapMethodEntryPointTable * m_pMethodEntryPoints; - - ZapWrapperTable * m_pWrappers; - - ZapBaseRelocs * m_pBaseRelocs; - - ULONGLONG m_NativeBaseAddress; - - ULONGLONG GetNativeBaseAddress() - { - return m_NativeBaseAddress; - } - - void CalculateZapBaseAddress(); - - // Preallocate hashtables to avoid rehashing - void Preallocate(); - - ZapGCInfoTable * m_pGCInfoTable; - -#ifdef FEATURE_EH_FUNCLETS - ZapUnwindDataTable * m_pUnwindDataTable; -#endif - - ZapImportSectionSignatures * m_pDelayLoadInfoDataTable[ZapImportSectionType_Total]; - ZapImportSectionSignatures * m_pStubDispatchDataTable; - ZapImportSectionSignatures * m_pExternalMethodDataTable; - ZapImportSectionSignatures * m_pDynamicHelperDataTable; - - ZapVirtualSectionsTable * m_pVirtualSectionsTable; - - ZapDebugInfoTable * m_pDebugInfoTable; - - ZapILMetaData * m_pILMetaData; - - ZapCorHeader * m_pCorHeader; - - ZapNode * m_pResources; - - ZapNode * m_pNativeHeader; - - ZapBlob * m_pNGenPdbDebugData; - - ULONG m_totalHotCodeSize; - ULONG m_totalColdCodeSize; - - ULONG m_totalCodeSizeInProfiledMethods; - ULONG m_totalColdCodeSizeInProfiledMethods; - - //information to track the boundaries of the different subsections within - //the hot section. - COUNT_T m_iIBCMethod; - COUNT_T m_iGenericsMethod; - COUNT_T m_iUntrainedMethod; - - // - // Input module - // - - LPWSTR m_pModuleFileName; // file name of the module being compiled, including path - CORINFO_MODULE_HANDLE m_hModule; // Module being compiled - PEDecoder m_ModuleDecoder; - IMDInternalImport * m_pMDImport; - bool m_fManifestModule; // Is this the assembly-manifest-module - bool m_fHaveProfileData; - - ZapNode ** m_pHelperThunks; // Array of on demand allocated JIT helper thunks - - // - // Profile source - // - - BYTE * m_profileDataFile; - BYTE * m_pRawProfileData; - COUNT_T m_cRawProfileData; - CorProfileData * m_pCorProfileData; - -public: - enum CompileStatus { - // Failure status values are negative - LOOKUP_FAILED = -2, - COMPILE_FAILED = -1, - - // Info status values are [0..9] - NOT_COMPILED = 0, - COMPILE_EXCLUDED = 1, - COMPILE_HOT_EXCLUDED = 2, - COMPILE_COLD_EXCLUDED = 3, - - // Successful status values are 10 or greater - COMPILE_SUCCEED = 10, - ALREADY_COMPILED = 11 - }; - -private: - // A hash table entry that contains the profile infomation and the CompileStatus for a given method - struct ProfileDataHashEntry - { - mdMethodDef md; // The method.token, also used as the key for the ProfileDataHashTable - DWORD size; // The size of the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData() - ULONG pos; // the offset to the CORBBTPROF_BLOCK_DATA region, set by ZapImage::hashBBProfileData() - - unsigned flags; // The methodProfilingDataFlags, set by ZapImage::CompileHotRegion() - CompileStatus status; // The compileResult, set by ZapImage::CompileHotRegion() - }; - - class ProfileDataHashTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef const mdMethodDef key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.md; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)k; - } - - static const element_t Null() - { - LIMITED_METHOD_CONTRACT; - ProfileDataHashEntry e; - e.md = 0; - e.size = 0; - e.pos = 0; - e.flags = 0; - e.status = NOT_COMPILED; - return e; - } - - static bool IsNull(const element_t &e) - { - LIMITED_METHOD_CONTRACT; - // returns true if both md and pos are zero - return (e.md == 0) && (e.pos == 0); - } - }; - typedef SHash ProfileDataHashTable; - - ProfileDataHashTable profileDataHashTable; - - SArray fileNotFoundErrorsTable; - void FileNotFoundError(LPCWSTR pszMessage); - -public: - struct ProfileDataSection - { - BYTE *pData; - DWORD dataSize; - DWORD tableSize; - CORBBTPROF_TOKEN_INFO *pTable; - }; - -private: - ProfileDataSection m_profileDataSections[SectionFormatCount]; - - DWORD m_profileDataNumRuns; - - CorInfoRegionKind m_currentRegionKind; - - BOOL IsAssemblyBeingCompiled(CORINFO_MODULE_HANDLE module) { - return ((module == m_hModule) || - (m_zapper->m_pEECompileInfo->GetModuleAssembly(module) == m_zapper->m_hAssembly)); - } - - class ZapMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef CORINFO_METHOD_HANDLE key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetHandle(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - }; - - typedef SHash ZapMethodHashTable; - - ZapMethodHashTable m_CompiledMethods; - - SArray m_MethodCompilationOrder; - - SArray m_PrioritizedGCInfo; - -#ifndef FEATURE_FULL_NGEN - class MethodCodeTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ZapMethodHeader * key_t; - - static FORCEINLINE key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e; - } - - static BOOL Equals(key_t k1, key_t k2); - static COUNT_T Hash(key_t k); - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash ZapMethodCodeHashTable; - - ZapMethodCodeHashTable m_CodeDeduplicator; -#endif // FEATURE_FULL_NGEN - - struct ClassLayoutOrderEntry - { - CORINFO_CLASS_HANDLE m_cls; - unsigned m_order; - - ClassLayoutOrderEntry() - : m_cls(0), m_order(0) - { - } - - ClassLayoutOrderEntry(CORINFO_CLASS_HANDLE cls, unsigned order) - : m_cls(cls), m_order(order) - { - } - }; - - class ClassLayoutOrderTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef CORINFO_CLASS_HANDLE key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.m_cls; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - static const element_t Null() { LIMITED_METHOD_CONTRACT; return element_t(0,0); } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_cls == 0; } - }; - - typedef SHash ClassLayoutOrderHashTable; - - ClassLayoutOrderHashTable m_ClassLayoutOrder; - - // See ComputeClassLayoutOrder for an explanation of these flags - #define UNSEEN_CLASS_FLAG (0x80000000) - #define METHOD_INDEX_FLAG (0x40000000) - - // The class layout order needs to be initialized with the first index - // in m_MethodCompilationOrder of a method in the given class. - inline void InitializeClassLayoutOrder(CORINFO_CLASS_HANDLE cls, unsigned order) - { - WRAPPER_NO_CONTRACT; - - if (!m_ClassLayoutOrder.LookupPtr(cls)) - { - ClassLayoutOrderEntry entry(cls, order | UNSEEN_CLASS_FLAG | METHOD_INDEX_FLAG); - m_ClassLayoutOrder.Add(entry); - } - } - -public: - inline unsigned LookupClassLayoutOrder(CORINFO_CLASS_HANDLE cls) - { - WRAPPER_NO_CONTRACT; - - const ClassLayoutOrderEntry *pEntry = m_ClassLayoutOrder.LookupPtr(cls); - _ASSERTE(!pEntry || pEntry->m_order != 0); - - return pEntry ? pEntry->m_order : 0; - } - -private: - - // - // The image layout algorithm - // - - enum CodeType - { - ProfiledHot, - ProfiledCold, - Unprofiled - }; - - ZapVirtualSection * GetCodeSection(CodeType codeType); - ZapVirtualSection * GetRuntimeFunctionSection(CodeType codeType); - ZapVirtualSection * GetCodeMethodDescSection(CodeType codeType); - ZapVirtualSection * GetUnwindInfoLookupSection(CodeType codeType); - -#if defined(FEATURE_EH_FUNCLETS) - ZapVirtualSection * GetUnwindDataSection(CodeType codeType); -#endif - - void GetCodeCompilationRange(CodeType codeType, COUNT_T * start, COUNT_T * end); - - void OutputCode(CodeType codeType); - void OutputCodeInfo(CodeType codeType); - - void OutputGCInfo(); - - void OutputDebugInfo(); - void OutputProfileData(); - - void OutputEntrypointsTableForReadyToRun(); - void OutputDebugInfoForReadyToRun(); - void OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport); - void OutputInliningTableForReadyToRun(); - void OutputProfileDataForReadyToRun(); - void OutputManifestMetadataForReadyToRun(); - HRESULT ComputeAttributePresenceTable(IMDInternalImport * pMDImport, SArray *table); - void OutputAttributePresenceFilter(IMDInternalImport * pMDImport); - - void CopyDebugDirEntry(); - void CopyWin32Resources(); - - void OutputManifestMetadata(); - void OutputTables(); - - // Assign RVAs to all ZapNodes - void ComputeRVAs(); - - HANDLE GenerateFile(LPCWSTR wszOutputFileName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); - - void PrintStats(LPCWSTR wszOutputFileName); - - bool m_fHasClassLayoutOrder; - - void ComputeClassLayoutOrder(); - void SortUnprofiledMethodsByClassLayoutOrder(); - - HRESULT GetPdbFileNameFromModuleFilePath(__in_z const WCHAR* pwszModuleFilePath, - __out_ecount(dwPdbFileNameBufferSize) char * pwszPdbFileName, - DWORD dwPdbFileNameBufferSize); - -public: - ZapImage(Zapper *zapper); - virtual ~ZapImage(); - - // ---------------------------------------------------------------------------------------------------------- - // - // Utility function for converting ZapWriter * to ZapImage *. This cast should not be done directly by the code - // so that the relationship between ZapWriter and ZapImage is abstracted away. - // - static ZapImage * GetImage(ZapWriter * pZapWriter) - { - return (ZapImage *)pZapWriter; - } - - // ---------------------------------------------------------------------------------------------------------- - // - // Add relocation record. This method is meant to be called from the Save method of custom ZapNodes right - // before the given datastructure is written into the native image. - // - // Arguments: - // pSrc - the datastructure being written - // offset - offset of the relocation within the datastructure - // pTarget - target of the relocation - // targetOffset - adjusment of the target (usually 0) - // type - relocation type (IMAGE_REL_BASED_XXX enum, note that we have private additions to this enum: - // IMAGE_REL_BASED_PTR - architecture specific reloc of virtual address - // IMAGE_REL_BASED_ABSOLUTE_TAGGED - absolute stored in the middle 30-bits, used for fixups. - // IMAGE_REL_BASED_RELPTR - pointer stored as address relative delta - // IMAGE_REL_BASED_RELPTR32 - pointer stored as address relative 32-bit delta - // - void WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type); - - void Open(CORINFO_MODULE_HANDLE hModule, IMetaDataAssemblyEmit *pEmit); - - void InitializeSections(); - void InitializeSectionsForReadyToRun(); - - // Wrapper of ZapWriter::NewVirtualSection that sets sectionType - ZapVirtualSection * NewVirtualSection(ZapPhysicalSection * pPhysicalSection, DWORD sectionType /* ZapVirtualSectionType */, DWORD dwAlignment = 16, ZapVirtualSection * pInsertAfter = NULL) - { - ZapVirtualSection * pSection = ZapWriter::NewVirtualSection(pPhysicalSection, dwAlignment, pInsertAfter); - pSection->SetSectionType(sectionType); - return pSection; - } - - void AllocateVirtualSections(); - - HANDLE SaveImage(LPCWSTR wszOutputFileName, LPCWSTR wszDllPath, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig); - - void Preload(); - void LinkPreload(); - - void SetVersionInfo(CORCOMPILE_VERSION_INFO * pVersionInfo); - void SetDependencies(CORCOMPILE_DEPENDENCY *pDependencies, DWORD cDependencies); - void SetPdbFileName(const SString &strFileName); - -#ifdef FEATURE_EH_FUNCLETS - void SetRuntimeFunctionsDirectoryEntry(); -#endif - - void SaveCorHeader(); - void SaveNativeHeader(); - void SaveCodeManagerEntry(); - - void Compile(); - - ZapMethodHeader * GetCompiledMethod(CORINFO_METHOD_HANDLE handle) - { - return m_CompiledMethods.Lookup(handle); - } - - static void __stdcall TryCompileMethodStub(LPVOID pContext, CORINFO_METHOD_HANDLE hStub, CORJIT_FLAGS jitFlags); - static DWORD EncodeModuleHelper(LPVOID compileContext, CORINFO_MODULE_HANDLE referencedModule); - - BOOL IsVTableGapMethod(mdMethodDef md); - - CompileStatus TryCompileMethodDef(mdMethodDef md, unsigned methodProfilingDataFlags); - CompileStatus TryCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle, unsigned methodProfilingDataFlags); - CompileStatus TryCompileMethodWorker(CORINFO_METHOD_HANDLE handle, mdMethodDef md, unsigned methodProfilingDataFlags); - - BOOL ShouldCompileMethodDef(mdMethodDef md); - BOOL ShouldCompileInstantiatedMethod(CORINFO_METHOD_HANDLE handle); - - bool canIntraModuleDirectCall(CORINFO_METHOD_HANDLE callerFtn, - CORINFO_METHOD_HANDLE targetFtn, - CorInfoIndirectCallReason *pReason = NULL, - CORINFO_ACCESS_FLAGS accessFlags = CORINFO_ACCESS_ANY); - - CORINFO_MODULE_HANDLE GetModuleHandle() - { - return m_hModule; - } - - IMetaDataAssemblyEmit * GetAssemblyEmit() - { - return m_pAssemblyEmit; - } - - ZapWrapperTable * GetWrappers() - { - return m_pWrappers; - } - - ZapImportTable * GetImportTable() - { - return m_pImportTable; - } - - ZapImportSectionsTable * GetImportSectionsTable() - { - return m_pImportSectionsTable; - } - - ZapNode * GetEEInfoTable() - { - return m_pEEInfoTable; - } - - ZapReadyToRunHeader * GetReadyToRunHeader() - { - _ASSERTE(IsReadyToRunCompilation()); - return (ZapReadyToRunHeader *)m_pNativeHeader; - } - - ZapNode * GetInnerPtr(ZapNode * pNode, SSIZE_T offset); - - CorInfoRegionKind GetCurrentRegionKind() - { - return m_currentRegionKind; - } - - // - // Called from ZapImportTable::PlaceBlob - // to determine wheather to place the new signature Blob - // into the HotImports or the ColdImports section. - // - // The Assert will fire if BeginRegion was not called - // to setup the region - // - bool IsCurrentCodeRegionHot() - { - if (GetCurrentRegionKind() == CORINFO_REGION_HOT) - { - return true; - } - else if (GetCurrentRegionKind() == CORINFO_REGION_COLD) - { - return false; - } - _ASSERTE(!"unsupported RegionKind"); - return false; - } - - // - // Marks the start of a region where we want to place any - // new signature Blobs into the Hot/Cold region - // - void BeginRegion(CorInfoRegionKind regionKind) - { - _ASSERTE(GetCurrentRegionKind() == CORINFO_REGION_NONE); - m_currentRegionKind = regionKind; - } - - // - // Marks the end of a region and we no longer expect to - // need any new signature Blobs - // - void EndRegion(CorInfoRegionKind regionKind) - { - _ASSERTE(GetCurrentRegionKind() == regionKind); - m_currentRegionKind = CORINFO_REGION_NONE; - } - - ICorCompilationDomain * GetDomain() - { - return m_zapper->m_pDomain; - } - - ICorDynamicInfo * GetJitInfo() - { - return m_zapper->m_pEEJitInfo; - } - - ICorCompileInfo * GetCompileInfo() - { - return m_zapper->m_pEECompileInfo; - } - - ZapperOptions * GetZapperOptions() - { - return m_zapper->m_pOpt; - } - - ZapNode * GetHelperThunkIfExists(CorInfoHelpFunc ftnNum) - { - return m_pHelperThunks[ftnNum]; - } - - ZapNode * GetHelperThunk(CorInfoHelpFunc ftnNum); - - BOOL HasClassLayoutOrder() - { - return m_fHasClassLayoutOrder; - } - - HRESULT PrintTokenDescription(CorZapLogLevel level, mdToken token); - - // ICorCompileDataStore - - // Returns ZapImage - virtual ZapImage * GetZapImage(); - void Error(mdToken token, HRESULT error, UINT resID, LPCWSTR message); - - // Returns virtual section for EE datastructures - ZapVirtualSection * GetSection(CorCompileSection section) - { - return m_pPreloadSections[section]; - } - - HRESULT LocateProfileData(); - HRESULT parseProfileData(); - HRESULT convertProfileDataFromV1(); - HRESULT hashMethodBlockCounts(); - void hashBBUpdateFlagsAndCompileResult(mdToken token, unsigned methodProfilingDataFlags, CompileStatus compileResult); - - void RehydrateBasicBlockSection(); - void RehydrateTokenSection(int sectionFormat, unsigned int flagTable[255]); - void RehydrateBlobStream(); - HRESULT RehydrateProfileData(); - - void LoadProfileData(); - CorProfileData * NewProfileData(); - CorProfileData * GetProfileData(); - bool CanConvertIbcData(); - - CompileStatus CompileProfileDataWorker(mdToken token, unsigned methodProfilingDataFlags); - - void ProfileDisableInlining(); - void CompileHotRegion(); - void CompileColdRegion(); - void PlaceMethodIL(); -}; - -class BinaryWriter -{ -private: - char *m_buffer; - unsigned int m_length; - unsigned int m_currentPosition; - ZapHeap *m_heap; - -private: - // Make sure that the buffer is at least newLength bytes long; - // expand it if necessary. - void RequireLength(unsigned int newLength) - { - if (newLength <= m_length) - { - return; - } - - if (newLength < (m_length * 3) / 2) - { - newLength = (m_length * 3) / 2; - } - - char *newBuffer = new (m_heap) char[newLength]; - - memcpy(newBuffer, m_buffer, m_length); - - m_length = newLength; - m_buffer = newBuffer; - } - -public: - BinaryWriter(unsigned int initialLength, ZapHeap *heap) - { - m_heap = heap; - m_length = initialLength; - m_buffer = new (m_heap) char[initialLength]; - m_currentPosition = 0; - } - - template - void WriteAt(unsigned int position, const T &v) - { - RequireLength(position + sizeof(T)); - - *(T *)(m_buffer + position) = v; - } - - template - void Write(const T &v) - { - WriteAt(m_currentPosition, v); - m_currentPosition += sizeof(T); - } - - void Write(const char *data, unsigned int length) - { - RequireLength(m_currentPosition + length); - - memcpy(m_buffer + m_currentPosition, data, length); - m_currentPosition += length; - } - - BYTE *GetBuffer() - { - return (BYTE *)m_buffer; - } - - unsigned int GetWrittenSize() - { - return m_currentPosition; - } -}; - -class ProfileReader -{ -public: - ProfileReader(void *buffer, ULONG length) - { - profileBuffer = (char *) buffer; - bufferSize = length; - currentPos = 0; - } - - bool Seek(ULONG pos) - { - if (pos <= bufferSize) - { - currentPos = pos; - return true; - } - else - { - _ASSERTE(!"ProfileReader: attempt to seek out of bounds"); - return false; - } - } - - void *Read(ULONG size) - { - ULONG oldPos = currentPos; - - if (!Seek(currentPos + size)) - { - return NULL; - } - - return (void *)(profileBuffer + oldPos); - } - - template T Read() - { - T* pResult = (T*)Read(sizeof(T)); - - if (!pResult) - { - ThrowHR(E_FAIL); - } - - return *pResult; - } - - // Read an integer a la BinaryReader.Read7BitEncodedInt. - unsigned int Read7BitEncodedInt() - { - unsigned int result = 0; - int shift = 0; - unsigned char current = 0x80; - - while ((currentPos < bufferSize) && - (shift <= 28)) - { - current = profileBuffer[currentPos++]; - result |= (current & 0x7f) << shift; - shift += 7; - - if (!(current & 0x80)) - { - return result; - } - } - - _ASSERTE(!"Improperly encoded value"); - ThrowHR(E_FAIL); - } - - // Read a token given a 'memory' value--the last token of this type read - // from the stream. The encoding takes advantage of the fact that two - // adjacent tokens in the file are usually of the same type, and therefore - // share a high byte. With the high byte removed the rest of the token can - // be encoded more efficiently. - mdToken ReadTokenWithMemory(mdToken &memory) - { - mdToken current; - mdToken result; - - current = Read7BitEncodedInt(); - - unsigned char highByte = ((current >> 24) & 0xff); - - if (highByte == 0) - { - result = current | (memory & 0xff000000); - } - else if (highByte == 0xff) - { - result = current & 0x00ffffff; - } - else - { - result = current; - } - - memory = result; - - return result; - } - - // Read a 32-bit flag value using a lookup table built while processing the - // file. Flag values are represented by a one-byte index. If the index - // hasn't occurred before in the file, it is followed by the four-byte flag - // value it represents. The index 255 is used as an escape code--it is - // always followed by a flag value. - // flagTable must have 255 entries and they must all start as 0xFFFFFFFF. - unsigned int ReadFlagWithLookup(unsigned int flagTable[255]) - { - unsigned char index; - unsigned int flags; - - index = Read(); - - if ((index < 255) && (flagTable[index] != 0xffffffff)) - { - return flagTable[index]; - } - - flags = Read(); - - if (index < 255) - { - flagTable[index] = flags; - } - - return flags; - } - - ULONG GetCurrentPos() - { - _ASSERTE(currentPos <= bufferSize); - return currentPos; - } - -private: - char *profileBuffer; - ULONG bufferSize; - ULONG currentPos; -}; - -struct RSDS { - DWORD magic; - GUID signature; - DWORD age; - char path[MAX_LONGPATH]; -}; - -#define SEEK(pos) \ - if (!profileReader.Seek(pos)) return E_FAIL; - -#define READ_SIZE(dst,type,size) \ - dst = (type *) profileReader.Read(size); \ - if (!dst) return E_FAIL; - -#define READ(dst,type) \ - READ_SIZE(dst,type,sizeof(type)) - -#endif // __ZAPIMAGE_H__ diff --git a/src/coreclr/zap/zapimport.cpp b/src/coreclr/zap/zapimport.cpp deleted file mode 100644 index c60868f60ea271..00000000000000 --- a/src/coreclr/zap/zapimport.cpp +++ /dev/null @@ -1,2284 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImport.cpp -// - -// -// Zapping of soft bound references to elements outside the current module -// -// ====================================================================================== - -#include "common.h" - -#include "zapimport.h" - -#include "nibblestream.h" -#include "sigbuilder.h" - -#if defined(FEATURE_READYTORUN_COMPILER) -// A flag to indicate that a helper call uses VSD -const DWORD READYTORUN_HELPER_FLAG_VSD = 0x10000000; -#endif - -// -// ZapImportTable -// - -ZapImportTable::ModuleReferenceEntry * ZapImportTable::GetModuleReference(CORINFO_MODULE_HANDLE handle) -{ - ModuleReferenceEntry * pEntry = m_moduleReferences.Lookup(handle); - - if (pEntry != NULL) - return pEntry; - - if (!GetCompileInfo()->IsInCurrentVersionBubble(handle)) - { - // FUTURE TODO: Version resilience - _ASSERTE(!"Invalid reference to module outside of current version bubble"); - ThrowHR(E_FAIL); - } - - pEntry = new (m_pImage->GetHeap()) ModuleReferenceEntry(); - pEntry->m_module = handle; - - GetCompileInfo()->EncodeModuleAsIndex(m_pImage->GetModuleHandle(), handle, - &pEntry->m_index, - m_pImage->GetAssemblyEmit()); - - m_moduleReferences.Add(pEntry); - - return pEntry; -} - -ZapBlob * ZapImportTable::GetBlob(SigBuilder * pSigBuilder, BOOL fEager) -{ - DWORD cbBlob; - PVOID pSignature = pSigBuilder->GetSignature(&cbBlob); - - if (fEager) - { - // Use dedicated section for blobs of eager fixups - return ZapBlob::NewBlob(m_pImage, pSignature, cbBlob); - } - - ZapBlob * pBlob = m_blobs.Lookup(ZapBlob::SHashKey(pSignature, cbBlob)); - - if (pBlob == NULL) - { - pBlob = ZapBlob::NewBlob(m_pImage, pSignature, cbBlob); - - m_blobs.Add(pBlob); - } - - return pBlob; -} - -ZapBlob * ZapImportTable::PlaceImportBlob(ZapImport * pImport, BOOL fEager) -{ - ZapBlob * pBlob; - if (pImport->HasBlob()) - { - pBlob = pImport->GetBlob(); - } - else - { - SigBuilder sigBuilder; - pImport->EncodeSignature(this, &sigBuilder); - - pBlob = GetBlob(&sigBuilder, fEager); - - pImport->SetBlob(pBlob); - } - - if (!pBlob->IsPlaced()) - PlaceBlob(pBlob, fEager); - - return pBlob; -} - -static const struct ImportSectionProperties -{ - BYTE Type; - BYTE EntrySize; - WORD Flags; -} -c_ImportSectionProperties[ZapImportSectionType_Count] = -{ - { /* ZapImportSectionType_Handle, */ CORCOMPILE_IMPORT_TYPE_UNKNOWN, 0, 0 }, - { /* ZapImportSectionType_TypeHandle, */ CORCOMPILE_IMPORT_TYPE_TYPE_HANDLE, TARGET_POINTER_SIZE, 0 }, - { /* ZapImportSectionType_MethodHandle, */ CORCOMPILE_IMPORT_TYPE_METHOD_HANDLE, TARGET_POINTER_SIZE, 0 }, -#ifdef TARGET_ARM - { /* ZapImportSectionType_PCode, */ CORCOMPILE_IMPORT_TYPE_UNKNOWN, 0, CORCOMPILE_IMPORT_FLAGS_PCODE }, -#endif - { /* ZapImportSectionType_StringHandle, */ CORCOMPILE_IMPORT_TYPE_STRING_HANDLE, TARGET_POINTER_SIZE, 0 }, -}; - -void ZapImportTable::PlaceImport(ZapImport * pImport) -{ - BOOL fIsEager, fNeedsSignature; - ZapImportSectionType table = pImport->ComputePlacement(m_pImage, &fIsEager, &fNeedsSignature); - - if (fIsEager) - { - table = ZapImportSectionType_Eager; - } - else - if (!m_pImage->IsCurrentCodeRegionHot()) - { - table = (ZapImportSectionType)(table + ZapImportSectionType_Cold); - } - - _ASSERTE(table < ZapImportSectionType_Total); - - - if (fNeedsSignature) - { - PlaceImportBlob(pImport, fIsEager); - } - - ZapVirtualSection * pVirtualSection = m_pImage->m_pDelayLoadInfoTableSection[table]; - - if (m_nImportSectionSizes[table] == 0) - { - const ImportSectionProperties * pProps = &c_ImportSectionProperties[table % ZapImportSectionType_Count]; - - WORD flags = pProps->Flags; - - if (fIsEager) - flags |= CORCOMPILE_IMPORT_FLAGS_EAGER; - - m_nImportSectionIndices[table] = m_pImage->GetImportSectionsTable()->Append(pProps->Type, flags, pProps->EntrySize, - pVirtualSection, m_pImage->m_pDelayLoadInfoDataTable[table]); - } - - pImport->SetSectionIndexAndOffset(m_nImportSectionIndices[table], m_nImportSectionSizes[table]); - - pVirtualSection->Place(pImport); - - m_nImportSectionSizes[table] += pImport->GetSize(); -} - -// Sort ZapImport* by CorCompileTokenTable as primary key and offset within the table as secondary key -static int __cdecl fixupCmp(const void* a_, const void* b_) -{ - ZapImport *a = *(ZapImport **)a_; - ZapImport *b = *(ZapImport **)b_; - - int tableDiff = a->GetSectionIndex() - b->GetSectionIndex(); - if (tableDiff != 0) - return tableDiff; - - // Sort by offset within the table - return (a->GetOffset() - b->GetOffset()); -} - -void ZapImportTable::PlaceFixups(ZapImport ** pImports, NibbleWriter& writer) -{ - COUNT_T nImports = 0; - - for (;;) - { - ZapImport * pImport = pImports[nImports]; - if (pImport == NULL) // end of the list - break; - if (!pImport->IsPlaced()) - PlaceImport(pImport); - nImports++; - } - - qsort(pImports, nImports, sizeof(ZapImport *), fixupCmp); - - // - // Build the encoded fixup list - // - - int curTableIndex = -1; - DWORD curOffset = 0; - - for (COUNT_T iImport = 0; iImport < nImports; iImport++) - { - ZapImport * pImport = pImports[iImport]; - - int tableIndex = pImport->GetSectionIndex(); - unsigned offset = pImport->GetOffset(); - - _ASSERTE(offset % TARGET_POINTER_SIZE == 0); - offset /= TARGET_POINTER_SIZE; - - if (tableIndex != curTableIndex) - { - // Write delta relative to the previous table index - _ASSERTE(tableIndex > curTableIndex); - if (curTableIndex != -1) - { - writer.WriteEncodedU32(0); // table separator, so add except for the first entry - writer.WriteEncodedU32(tableIndex - curTableIndex); // add table index delta - } - else - { - writer.WriteEncodedU32(tableIndex); - } - curTableIndex = tableIndex; - - // This is the first fixup in the current table. - // We will write it out completely (without delta-encoding) - writer.WriteEncodedU32(offset); - } - else - { - // This is not the first entry in the current table. - // We will write out the delta relative to the previous fixup value - int delta = offset - curOffset; - _ASSERTE(delta > 0); - writer.WriteEncodedU32(delta); - } - - // future entries for this table would be relative to this rva - curOffset = offset; - } - - writer.WriteEncodedU32(0); // table separator - writer.WriteEncodedU32(0); // fixup list ends - - writer.Flush(); -} - -ZapFixupInfo * ZapImportTable::PlaceFixups(ZapImport ** pImports) -{ - NibbleWriter writer; - - PlaceFixups(pImports, writer); - - DWORD cbBlob; - PVOID pBlob = writer.GetBlob(&cbBlob); - - // - // Intern the fixup info - // - - ZapFixupInfo * pFixupInfo = m_blobs.Lookup(ZapBlob::SHashKey(pBlob, cbBlob)); - - if (pFixupInfo == NULL) - { - // Fixup infos are mixed with other blobs - pFixupInfo = ZapBlob::NewBlob(m_pImage, pBlob, cbBlob); - m_blobs.Add(pFixupInfo); - } - - if (!pFixupInfo->IsPlaced()) - PlaceBlob(pFixupInfo); - - return pFixupInfo; -} - -void ZapImportTable::PlaceBlob(ZapBlob * pBlob, BOOL fEager) -{ - ZapVirtualSection * pSection; - if (fEager) - pSection = m_pImage->m_pDelayLoadInfoDelayListSectionEager; - else - if (m_pImage->IsCurrentCodeRegionHot()) - pSection = m_pImage->m_pDelayLoadInfoDelayListSectionHot; - else - pSection = m_pImage->m_pDelayLoadInfoDelayListSectionCold; - pSection->Place(pBlob); -} - -// ====================================================================================== -// -// Generic signatures -// -ZapGenericSignature * ZapImportTable::GetGenericSignature(PVOID signature, BOOL fMethod) -{ -#ifdef REDHAWK - _ASSERTE(!"NYI"); - return NULL; -#else - SigBuilder sigBuilder; - GetCompileInfo()->EncodeGenericSignature(signature, fMethod, &sigBuilder, this, EncodeModuleHelper); - - DWORD cbSig; - PVOID pSig = sigBuilder.GetSignature(&cbSig); - - ZapGenericSignature * pGenericSignature = (ZapGenericSignature *)m_genericSignatures.Lookup(ZapBlob::SHashKey(pSig, cbSig)); - - if (pGenericSignature != NULL) - return pGenericSignature; - - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapGenericSignature)) + S_SIZE_T(cbSig); - - if (cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (m_pImage->GetHeap()) BYTE[cbAllocSize.Value()]; - - pGenericSignature = new (pMemory) ZapGenericSignature(cbSig); - memcpy((void *)(pGenericSignature + 1), pSig, cbSig); - - m_genericSignatures.Add(pGenericSignature); - - return pGenericSignature; -#endif // REDHAWK -} - -// At ngen time Zapper::CompileModule PlaceFixups called from -// code:ZapSig.GetSignatureForTypeHandle -// -/*static*/ DWORD ZapImportTable::EncodeModuleHelper( LPVOID compileContext, - CORINFO_MODULE_HANDLE referencedModule) -{ - _ASSERTE(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()); - ZapImportTable * pTable = (ZapImportTable *)compileContext; - return pTable->GetIndexOfModule(referencedModule); -} - -void ZapImport::Save(ZapWriter * pZapWriter) -{ - if (IsReadyToRunCompilation()) - { - TARGET_POINTER_TYPE value = 0; - pZapWriter->Write(&value, sizeof(value)); - return; - } - - TARGET_POINTER_TYPE token = CORCOMPILE_TAG_TOKEN(GetBlob()->GetRVA()); - pZapWriter->Write(&token, sizeof(token)); -} - -// -// CORCOMPILE_CODE_IMPORT_SECTION -// - -COUNT_T ZapImportSectionsTable::Append(BYTE Type, USHORT Flags, BYTE EntrySize, ZapVirtualSection * pSection, ZapNode * pSignatures, ZapNode * pAuxiliaryData) -{ - ImportSection entry; - - entry.m_pSection = pSection; - entry.m_pSignatures = pSignatures; - entry.m_pAuxiliaryData = pAuxiliaryData; - entry.m_Flags = Flags; - entry.m_Type = Type; - entry.m_EntrySize = EntrySize; - - m_ImportSectionsTable.Append(entry); - - return m_ImportSectionsTable.GetCount() - 1; -} - -DWORD ZapImportSectionsTable::GetSize() -{ - return m_ImportSectionsTable.GetCount() * sizeof(CORCOMPILE_IMPORT_SECTION); -} - -void ZapImportSectionsTable::Save(ZapWriter * pZapWriter) -{ - COUNT_T nSections = m_ImportSectionsTable.GetCount(); - for (COUNT_T iSection = 0; iSection < nSections; iSection++) - { - ImportSection * p = &m_ImportSectionsTable[iSection]; - - CORCOMPILE_IMPORT_SECTION entry; - - ZapWriter::SetDirectoryData(&entry.Section, p->m_pSection); - - entry.Flags = p->m_Flags; - entry.Type = p->m_Type; - entry.EntrySize = p->m_EntrySize; - - entry.Signatures = (p->m_pSignatures != NULL) ? p->m_pSignatures->GetRVA() : NULL; - entry.AuxiliaryData = (p->m_pAuxiliaryData != NULL) ? p->m_pAuxiliaryData->GetRVA() : NULL; - - pZapWriter->Write(&entry, sizeof(entry)); - } -} - - -ZapImportSectionSignatures::ZapImportSectionSignatures(ZapImage * pImage, ZapVirtualSection * pImportSection, ZapVirtualSection * pGCSection) - : m_pImportSection(pImportSection), m_pImage(pImage) -{ - if (pGCSection != NULL) - { - m_pGCRefMapTable = new (pImage->GetHeap()) ZapGCRefMapTable(pImage); - pGCSection->Place(m_pGCRefMapTable); - } -} - -ZapImportSectionSignatures::~ZapImportSectionSignatures() -{ - if (m_pGCRefMapTable != NULL) - m_pGCRefMapTable->~ZapGCRefMapTable(); -} - -DWORD ZapImportSectionSignatures::GetSize() -{ - return m_pImportSection->GetNodeCount() * sizeof(DWORD); -} - -void ZapImportSectionSignatures::Save(ZapWriter * pZapWriter) -{ - COUNT_T nCount = m_pImportSection->GetNodeCount(); - for (COUNT_T i = 0; i < nCount; i++) - { - ZapNode * pNode = m_pImportSection->GetNode(i); - DWORD dwRVA = ((ZapImport *)pNode)->GetBlob()->GetRVA(); - pZapWriter->Write(&dwRVA, sizeof(dwRVA)); - } -} - -// ====================================================================================== -// -// Special lazy imports for lazily resolved method calls -// - -// -// External method thunk is a patchable thunk used for cross-module direct calls -// -class ZapExternalMethodThunk : public ZapImport -{ -public: - ZapExternalMethodThunk() - { - } - - CORINFO_METHOD_HANDLE GetMethod() - { - return (CORINFO_METHOD_HANDLE)GetHandle(); - } - - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ExternalMethodThunk; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - pTable->EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, pSigBuilder); - - pSigBuilder->AppendData(RidFromToken(token)); - } - else - { - pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder); - } - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -void ZapExternalMethodThunk::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - ZapNode * helper = pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP); - - CORCOMPILE_EXTERNAL_METHOD_THUNK thunk; - memset(&thunk, DEFAULT_CODE_BUFFER_INIT, sizeof(thunk)); -#if defined(TARGET_X86) || defined(TARGET_AMD64) - thunk.callJmp[0] = 0xE8; // call rel32 - pImage->WriteReloc(&thunk, 1, helper, 0, IMAGE_REL_BASED_REL32); - thunk.precodeType = _PRECODE_EXTERNAL_METHOD_THUNK; -#elif defined(TARGET_ARM) - // Setup the call to ExternalMethodFixupStub - // - // mov r12, pc - // - // Per ARM architecture reference manual section A2.3, - // reading the value of PC register will read the address - // of the current instruction plus 4. In this case, - // R12 will containing the address of "F004" below once - // the "mov" is executed. - // - // Since this is 4 bytes ahead of the start of the thunk, - // the assembly helper we will call into will adjust this - // so that we point to the start of the thunk correctly. - thunk.m_rgCode[0] = 0x46fc; - - // ldr pc, [pc, #4] - thunk.m_rgCode[1] = 0xf8df; - thunk.m_rgCode[2] = 0xf004; - - // Setup the initial target to be our assembly helper. - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_EXTERNAL_METHOD_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); -#elif defined(TARGET_ARM64) - - thunk.m_rgCode[0] = 0x1000000C; //adr x12, #0 - thunk.m_rgCode[1] = 0xF940098A; //ldr x10, [x12, #16] - thunk.m_rgCode[2] = 0xD61F0140; //br x10 - - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_EXTERNAL_METHOD_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); -#else - PORTABILITY_ASSERT("ZapExternalMethodThunk::Save"); - -#endif - - pZapWriter->Write(&thunk, sizeof(thunk)); - _ASSERTE(sizeof(thunk) == GetSize()); -} - -void ZapImportSectionSignatures::PlaceExternalMethodThunk(ZapImport * pImport) -{ - ZapExternalMethodThunk * pThunk = (ZapExternalMethodThunk *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_EXTERNAL_METHOD, CORCOMPILE_IMPORT_FLAGS_CODE, - sizeof(CORCOMPILE_EXTERNAL_METHOD_THUNK), m_pImportSection, this, m_pGCRefMapTable); - - // Make sure the helper created - m_pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP); - } - - // Add entry to both the the cell and data sections - m_pImportSection->Place(pThunk); - - m_pImage->GetImportTable()->PlaceImportBlob(pThunk); - - m_pGCRefMapTable->Append(pThunk->GetMethod()); -} - -ZapImport * ZapImportTable::GetExternalMethodThunk(CORINFO_METHOD_HANDLE handle) -{ - return GetImport((PVOID)handle); -} - -// -// Stub dispatch cell is lazily initialized indirection used for virtual stub dispatch -// -class ZapStubDispatchCell : public ZapImport -{ - ZapNode * m_pDelayLoadHelper; - -public: - void SetDelayLoadHelper(ZapNode * pDelayLoadHelper) - { - _ASSERTE(m_pDelayLoadHelper == NULL); - m_pDelayLoadHelper = pDelayLoadHelper; - } - - CORINFO_METHOD_HANDLE GetMethod() - { - return (CORINFO_METHOD_HANDLE)GetHandle(); - } - - CORINFO_CLASS_HANDLE GetClass() - { - return (CORINFO_CLASS_HANDLE)GetHandle2(); - } - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_StubDispatchCell; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_MODULE_HANDLE referencingModule = pTable->GetJitInfo()->getClassModule(GetClass()); - referencingModule = pTable->TryEncodeModule(ENCODE_VIRTUAL_ENTRY_SLOT, referencingModule, pSigBuilder); - - DWORD slot = pTable->GetCompileInfo()->TryEncodeMethodSlot(GetMethod()); - - // We expect the encoding to always succeed - _ASSERTE(slot != (DWORD)-1); - - pSigBuilder->AppendData(slot); - - pTable->EncodeClassInContext(referencingModule, GetClass(), pSigBuilder); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - TARGET_POINTER_TYPE cell; - pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } -}; - -ZapImport * ZapImportTable::GetStubDispatchCell(CORINFO_CLASS_HANDLE typeHnd, CORINFO_METHOD_HANDLE methHnd) -{ - // Do not intern stub dispatch imports. Each callsite should get own cell. - ZapImport * pImport = new (m_pImage->GetHeap()) ZapStubDispatchCell(); - pImport->SetHandle(methHnd); - pImport->SetHandle2(typeHnd); - return pImport; -} - -void ZapImportSectionSignatures::PlaceStubDispatchCell(ZapImport * pImport) -{ - ZapStubDispatchCell * pCell = (ZapStubDispatchCell *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH, CORCOMPILE_IMPORT_FLAGS_PCODE, - TARGET_POINTER_SIZE, m_pImportSection, this, m_pGCRefMapTable); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - // Create the delay load helper - ReadyToRunHelper helper = (ReadyToRunHelper)(READYTORUN_HELPER_DelayLoad_MethodCall | READYTORUN_HELPER_FLAG_VSD); - ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helper, (PVOID)(SIZE_T)m_dwIndex); - pCell->SetDelayLoadHelper(pDelayLoadHelper); - } - else -#endif - { - pCell->SetDelayLoadHelper(m_pImage->GetHelperThunk(CORINFO_HELP_EE_VSD_FIXUP)); - } - - // Add entry to both the cell and data sections - m_pImportSection->Place(pCell); - - m_pImage->GetImportTable()->PlaceImportBlob(pCell); - - m_pGCRefMapTable->Append(pCell->GetMethod(), true); -} - -// -// External method cell is lazily initialized indirection used for method calls -// -class ZapExternalMethodCell : public ZapImport -{ - ZapNode * m_pDelayLoadHelper; - -public: - void SetDelayLoadHelper(ZapNode * pDelayLoadHelper) - { - _ASSERTE(m_pDelayLoadHelper == NULL); - m_pDelayLoadHelper = pDelayLoadHelper; - } - CORINFO_METHOD_HANDLE GetMethod() - { - return (CORINFO_METHOD_HANDLE)GetHandle(); - } - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ExternalMethodCell; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - pTable->EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, pSigBuilder); - - pSigBuilder->AppendData(RidFromToken(token)); - } - else - { - pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder); - } - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - TARGET_POINTER_TYPE cell; - pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } -}; - -ZapImport * ZapImportTable::GetExternalMethodCell(CORINFO_METHOD_HANDLE handle) -{ - return GetImport((PVOID)handle); -} - -void ZapImportSectionSignatures::PlaceExternalMethodCell(ZapImport * pImport) -{ - ZapExternalMethodCell * pCell = (ZapExternalMethodCell *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_STUB_DISPATCH, CORCOMPILE_IMPORT_FLAGS_PCODE, - TARGET_POINTER_SIZE, m_pImportSection, this, m_pGCRefMapTable); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - // Create the delay load helper - ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(READYTORUN_HELPER_DelayLoad_MethodCall, (PVOID)(SIZE_T)m_dwIndex); - pCell->SetDelayLoadHelper(pDelayLoadHelper); - } - else -#endif - { - pCell->SetDelayLoadHelper(m_pImage->GetHelperThunk(CORINFO_HELP_EE_EXTERNAL_FIXUP)); - } - - // Add entry to both the cell and data sections - m_pImportSection->Place(pCell); - - m_pImage->GetImportTable()->PlaceImportBlob(pCell); - - m_pGCRefMapTable->Append(pCell->GetMethod()); -} - -// -// Virtual import thunk is a patchable thunk used for cross-module virtual calls. -// -class ZapVirtualMethodThunk : public ZapImport -{ -public: - virtual DWORD GetSize() - { - return sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_VirtualMethodThunk; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Virtual import thunks do not have signatures - _ASSERTE(false); - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -void ZapVirtualMethodThunk::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - CORCOMPILE_VIRTUAL_IMPORT_THUNK thunk; - memset(&thunk, DEFAULT_CODE_BUFFER_INIT, sizeof(thunk)); - - // On ARM, the helper would already have the thumb-bit set. Refer to - // GetHelperThunk implementation. - ZapNode * helper = pImage->GetHelperThunk(CORINFO_HELP_EE_VTABLE_FIXUP); - _ASSERTE(FitsIn((SIZE_T)GetHandle2() - 1)); - USHORT slotNum = (USHORT)((SIZE_T)GetHandle2() - 1); - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - thunk.callJmp[0] = 0xE8; // call rel32 - pImage->WriteReloc(&thunk, 1, helper, 0, IMAGE_REL_BASED_REL32); - - // Mark this as a Virtual Import Thunk - thunk.precodeType = _PRECODE_VIRTUAL_IMPORT_THUNK; -#elif defined(TARGET_ARM) - // Setup the call to VirtualMethodFixupStub - // - // mov r12, pc - // - // Per ARM architecture reference manual section A2.3, - // reading the value of PC register will read the address - // of the current instruction plus 4. In this case, - // R12 will containing the address of "F004" below once - // the "mov" is executed. - // - // Since this is 4 bytes ahead of the start of the thunk, - // the assembly helper we will call into will adjust this - // so that we point to the start of the thunk correctly. - thunk.m_rgCode[0] = 0x46fc; - - // ldr pc, [pc, #4] - thunk.m_rgCode[1] = 0xf8df; - thunk.m_rgCode[2] = 0xf004; - - // Slot ID is setup below, so now setup the initial target - // to be our assembly helper. - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_VIRTUAL_IMPORT_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); - #elif defined(TARGET_ARM64) - - thunk.m_rgCode[0] = 0x1000000C; //adr x12, #0 - thunk.m_rgCode[1] = 0xF940098A; //ldr x10, [x12, #16] - thunk.m_rgCode[2] = 0xD61F0140; //br x10 - - // Slot ID is setup below, so now setup the initial target - // to be our assembly helper. - pImage->WriteReloc(&thunk, offsetof(CORCOMPILE_VIRTUAL_IMPORT_THUNK, m_pTarget), helper, 0, IMAGE_REL_BASED_PTR); -#else - PORTABILITY_ASSERT("ZapVirtualMethodThunk::Save"); -#endif - - thunk.slotNum = slotNum; - - pZapWriter->Write(&thunk, sizeof(thunk)); -} - -void ZapImportTable::PlaceVirtualImportThunk(ZapImport * pVirtualImportThunk) -{ - if (m_pImage->m_pVirtualImportThunkSection->GetNodeCount() == 0) - { - m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_VIRTUAL_METHOD, CORCOMPILE_IMPORT_FLAGS_CODE, - sizeof(CORCOMPILE_VIRTUAL_IMPORT_THUNK), m_pImage->m_pVirtualImportThunkSection); - - // Make sure the helper created - m_pImage->GetHelperThunk(CORINFO_HELP_EE_VTABLE_FIXUP); - } - - m_pImage->m_pVirtualImportThunkSection->Place(pVirtualImportThunk); -} - -ZapImport * ZapImportTable::GetVirtualImportThunk(CORINFO_METHOD_HANDLE handle, int slot) -{ - return GetImport(handle, (PVOID)(SIZE_T)(slot+1)); -} - -// ====================================================================================== -// -// GCRefMapTable is used to encode for GC references locations for lazily resolved calls -// - -void ZapGCRefMapTable::Append(CORINFO_METHOD_HANDLE handle, bool isDispatchCell) -{ - m_pImage->GetCompileInfo()->GetCallRefMap(handle, &m_GCRefMapBuilder, isDispatchCell); - m_nCount++; -} - -DWORD ZapGCRefMapTable::GetSize() -{ - if (m_nCount == 0) return 0; - - COUNT_T nLookupEntries = (1 + m_nCount / GCREFMAP_LOOKUP_STRIDE); - - return (nLookupEntries * sizeof(DWORD)) + m_GCRefMapBuilder.GetBlobLength(); -} - -void ZapGCRefMapTable::Save(ZapWriter * pZapWriter) -{ - if (m_nCount == 0) return; - - COUNT_T nLookupEntries = (1 + m_nCount / GCREFMAP_LOOKUP_STRIDE); - - DWORD dwBlobLength; - BYTE * pBlob = (BYTE *)m_GCRefMapBuilder.GetBlob(&dwBlobLength); - - DWORD pos = 0; - COUNT_T iLookupEntry = 0; - for (;;) - { - DWORD relOfs = (nLookupEntries * sizeof(DWORD)) + pos; - pZapWriter->Write(&relOfs, sizeof(relOfs)); - iLookupEntry++; - - if (iLookupEntry >= nLookupEntries) - break; - - for (int i = 0; i < GCREFMAP_LOOKUP_STRIDE; i++) - { - while ((*(pBlob + pos) & 0x80) != 0) - pos++; - pos++; - - _ASSERTE(pos <= dwBlobLength); - } - } - - pZapWriter->Write(pBlob, dwBlobLength); -} - -// ====================================================================================== -// -// Getters for existing imports. -// - -ZapImport * ZapImportTable::GetExistingClassHandleImport(CORINFO_CLASS_HANDLE handle) -{ - return GetExistingImport(ZapNodeType_Import_ClassHandle, handle); -} - -ZapImport * ZapImportTable::GetExistingFieldHandleImport(CORINFO_FIELD_HANDLE handle) -{ - return GetExistingImport(ZapNodeType_Import_FieldHandle, handle); -} - -ZapImport * ZapImportTable::GetExistingMethodHandleImport(CORINFO_METHOD_HANDLE handle) -{ - return GetExistingImport(ZapNodeType_Import_MethodHandle, handle); -} - -CORINFO_MODULE_HANDLE ZapImportTable::TryEncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder) -{ - if (!GetCompileInfo()->IsInCurrentVersionBubble(module)) - module = GetImage()->GetModuleHandle(); - - EncodeModule(kind, module, pSigBuilder); - return module; -} - -void ZapImportTable::EncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder) -{ - if (module != GetImage()->GetModuleHandle()) - { - _ASSERTE(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()); - pSigBuilder->AppendByte(kind | ENCODE_MODULE_OVERRIDE); - pSigBuilder->AppendData(GetIndexOfModule(module)); - } - else - { - pSigBuilder->AppendByte(kind); - } -} - -void ZapImportTable::EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder) -{ - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(handle); - referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder); - GetCompileInfo()->EncodeClass(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper); -} - -void ZapImportTable::EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder) -{ - GetCompileInfo()->EncodeClass(context, handle, pSigBuilder, this, EncodeModuleHelper); -} - -void ZapImportTable::EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams) -{ - CORINFO_CLASS_HANDLE clsHandle = GetJitInfo()->getFieldClass(handle); - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle); - referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder); - GetCompileInfo()->EncodeField(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper, - pResolvedToken, fEncodeUsingResolvedTokenSpecStreams); -} - -void ZapImportTable::EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, BOOL fEncodeUsingResolvedTokenSpecStreams) -{ - CORINFO_CLASS_HANDLE clsHandle = GetJitInfo()->getMethodClass(handle); - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle); - referencingModule = TryEncodeModule(kind, referencingModule, pSigBuilder); - GetCompileInfo()->EncodeMethod(referencingModule, handle, pSigBuilder, this, EncodeModuleHelper, - pResolvedToken, pConstrainedResolvedToken, fEncodeUsingResolvedTokenSpecStreams); -} - -// ====================================================================================== -// -// Actual imports -// - -class ZapModuleHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ModuleHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - CORINFO_MODULE_HANDLE handle = (CORINFO_MODULE_HANDLE)GetHandle(); - if (pImage->m_pPreloader->CanEmbedModuleHandle(handle)) - { - *pfIsEager = TRUE; - } - - return ZapImportSectionType_Handle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeModule(ENCODE_MODULE_HANDLE, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetModuleHandleImport(CORINFO_MODULE_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapClassHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ClassHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - if (IsReadyToRunCompilation()) - return ZapImportSectionType_Handle; - - CORINFO_CLASS_HANDLE handle = (CORINFO_CLASS_HANDLE)GetHandle(); - if (pImage->m_pPreloader->CanEmbedClassHandle(handle)) - { - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (pImage->GetCompileInfo()->GetLoaderModuleForEmbeddableType(handle) == pImage->GetModuleHandle()) - { - *pfNeedsSignature = FALSE; - } - else - { - *pfIsEager = TRUE; - } - } - - return ZapImportSectionType_TypeHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeClass(ENCODE_TYPE_HANDLE, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (!HasBlob()) - { - PVOID cell; - ZapNode handle(pImage->m_pPreloader->MapClassHandle((CORINFO_CLASS_HANDLE)GetHandle())); - pImage->WriteReloc(&cell, 0, &handle, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } - else - { - ZapImport::Save(pZapWriter); - } - } -}; - -ZapImport * ZapImportTable::GetClassHandleImport(CORINFO_CLASS_HANDLE handle, PVOID pUniqueId) -{ - // pUniqueId is workaround for loading of generic parent method table. It would be nice to clean it up. - if (pUniqueId != NULL) - { - return GetImport(handle, pUniqueId); - } - - ZapImport * pImport = GetImport(handle); - - if (IsReadyToRunCompilation() && !pImport->HasBlob()) - { - SigBuilder sigBuilder; - - EncodeClass(ENCODE_TYPE_HANDLE, handle, &sigBuilder); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -class ZapFieldHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_FieldHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeField(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetFieldHandleImport(CORINFO_FIELD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapMethodHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_MethodHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - if (IsReadyToRunCompilation()) - return ZapImportSectionType_Handle; - - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - if (pImage->m_pPreloader->CanEmbedMethodHandle(handle)) - { - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (pImage->GetCompileInfo()->GetLoaderModuleForEmbeddableMethod(handle) == pImage->GetModuleHandle()) - { - *pfNeedsSignature = FALSE; - } - } - - return ZapImportSectionType_MethodHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeMethod(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - // We may have entries pointing to our module that exist in the handle table to trigger restore. - if (!HasBlob()) - { - PVOID cell; - ZapNode handle(pImage->m_pPreloader->MapMethodHandle((CORINFO_METHOD_HANDLE)GetHandle())); - pImage->WriteReloc(&cell, 0, &handle, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } - else - { - ZapImport::Save(pZapWriter); - } - } -}; - -ZapImport * ZapImportTable::GetMethodHandleImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapStringHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_StringHandle; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - - // Empty string - if ((mdString)(size_t)GetHandle2() == mdtString) - { - *pfIsEager = TRUE; - return ZapImportSectionType_Handle; - } - - return ZapImportSectionType_StringHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_MODULE_HANDLE referencingModule = (CORINFO_MODULE_HANDLE)GetHandle(); - - pTable->EncodeModule(ENCODE_STRING_HANDLE, referencingModule, pSigBuilder); - - mdString token = (mdString)(size_t)GetHandle2(); - pSigBuilder->AppendData(RidFromToken(token)); - } -}; - -ZapImport * ZapImportTable::GetStringHandleImport(CORINFO_MODULE_HANDLE tokenScope, mdString metaTok) -{ - return GetImport(tokenScope, (PVOID)(size_t)metaTok); -} - -class ZapFunctionEntryImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_FunctionEntry; - } - -#ifdef TARGET_ARM - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - ZapImport::ComputePlacement(pImage, pfIsEager, pfNeedsSignature); - return ZapImportSectionType_PCode; - } -#endif - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - CORINFO_METHOD_HANDLE handle = (CORINFO_METHOD_HANDLE)GetHandle(); - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = pTable->GetCompileInfo()->TryEncodeMethodAsToken(handle, NULL, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - _ASSERTE(!pTable->GetCompileInfo()->IsUnmanagedCallersOnlyMethod(handle)); - - pTable->EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, pSigBuilder); - - pSigBuilder->AppendData(RidFromToken(token)); - } - else - { - pTable->EncodeMethod(ENCODE_METHOD_ENTRY, handle, pSigBuilder); - } - } - - virtual void Save(ZapWriter * pZapWriter) - { - SIZE_T token = CORCOMPILE_TAG_PCODE(GetBlob()->GetRVA()); - pZapWriter->Write(&token, sizeof(token)); - } -}; - -ZapImport * ZapImportTable::GetFunctionEntryImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapStaticFieldAddressImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_StaticFieldAddress; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeField(ENCODE_STATIC_FIELD_ADDRESS, (CORINFO_FIELD_HANDLE)GetHandle(), pSigBuilder); - } - - virtual DWORD GetSize() - { - return 2 * TARGET_POINTER_SIZE; - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImport::Save(pZapWriter); - - TADDR value = 0; - pZapWriter->Write(&value, sizeof(value)); - } -}; - -ZapImport * ZapImportTable::GetStaticFieldAddressImport(CORINFO_FIELD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapClassDomainIdImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ClassDomainId; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeClass(ENCODE_CLASS_ID_FOR_STATICS, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetClassDomainIdImport(CORINFO_CLASS_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapModuleDomainIdImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ModuleDomainId; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - if (GetHandle() != NULL) - { - pTable->EncodeModule(ENCODE_MODULE_ID_FOR_STATICS, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder); - } - else - { - _ASSERTE(GetHandle2() != NULL); - - pTable->EncodeClass(ENCODE_MODULE_ID_FOR_GENERIC_STATICS, (CORINFO_CLASS_HANDLE)GetHandle2(), pSigBuilder); - } - } -}; - -ZapImport * ZapImportTable::GetModuleDomainIdImport(CORINFO_MODULE_HANDLE handleToModule, CORINFO_CLASS_HANDLE handleToClass) -{ - _ASSERTE(((void *)handleToModule != (void *)handleToClass) && ((handleToModule == NULL) || (handleToClass == NULL))); - - return GetImport(handleToModule, handleToClass); -} - -class ZapSyncLockImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_SyncLock; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeClass(ENCODE_SYNC_LOCK, (CORINFO_CLASS_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetSyncLockImport(CORINFO_CLASS_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapIndirectPInvokeTargetImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_IndirectPInvokeTarget; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeMethod(ENCODE_INDIRECT_PINVOKE_TARGET, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetIndirectPInvokeTargetImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapPInvokeTargetImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_PInvokeTarget; - } - - virtual void EncodeSignature(ZapImportTable* pTable, SigBuilder* pSigBuilder) - { - pTable->EncodeMethod(ENCODE_PINVOKE_TARGET, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } -}; - -ZapImport * ZapImportTable::GetPInvokeTargetImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapProfilingHandleImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ProfilingHandle; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeMethod(ENCODE_PROFILING_HANDLE, (CORINFO_METHOD_HANDLE)GetHandle(), pSigBuilder); - } - - virtual DWORD GetSize() - { - // fixup cell, 3 pointers to interception method (Enter/Leave/Tailcall) and opaque handle - return kZapProfilingHandleImportValueIndexCount * TARGET_POINTER_SIZE; - } - - virtual void Save(ZapWriter * pZapWriter) - { - // Save fixup cell - ZapImport::Save(pZapWriter); - - // Save zeroes for the rest of the entries - - // If this assert fires, someone changed the - // kZapProfilingHandleImportValueIndex... enum values without updating me! - _ASSERTE(kZapProfilingHandleImportValueIndexCount == 5); - - TADDR value = 0; - pZapWriter->Write(&value, sizeof(value)); - pZapWriter->Write(&value, sizeof(value)); - pZapWriter->Write(&value, sizeof(value)); - pZapWriter->Write(&value, sizeof(value)); - } -}; - -ZapImport * ZapImportTable::GetProfilingHandleImport(CORINFO_METHOD_HANDLE handle) -{ - return GetImport(handle); -} - -class ZapVarArgImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_VarArg; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - _ASSERTE((CORINFO_MODULE_HANDLE)GetHandle() == pTable->GetImage()->GetModuleHandle()); - - mdToken token = (mdToken)(size_t)GetHandle2(); - switch (TypeFromToken(token)) - { - case mdtSignature: - pSigBuilder->AppendByte(ENCODE_VARARGS_SIG); - break; - - case mdtMemberRef: - pSigBuilder->AppendByte(ENCODE_VARARGS_METHODREF); - break; - - case mdtMethodDef: - pSigBuilder->AppendByte(ENCODE_VARARGS_METHODDEF); - break; - - default: - _ASSERTE(!"Bogus token for signature"); - } - - pSigBuilder->AppendData(RidFromToken(token)); - } -}; - -ZapImport * ZapImportTable::GetVarArgImport(CORINFO_MODULE_HANDLE handle, mdToken sigOrMemberRefOrDef) -{ - return GetImport(handle, (PVOID)(size_t)sigOrMemberRefOrDef); -} - -class ZapActiveDependencyImport : public ZapImport -{ -public: - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_ActiveDependency; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - pTable->EncodeModule(ENCODE_ACTIVE_DEPENDENCY, (CORINFO_MODULE_HANDLE)GetHandle(), pSigBuilder); - pSigBuilder->AppendData(pTable->GetIndexOfModule((CORINFO_MODULE_HANDLE)GetHandle2())); - } -}; - -ZapImport * ZapImportTable::GetActiveDependencyImport(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo) -{ - return GetImport(moduleFrom, moduleTo); -} - -ZapImport * ZapImportTable::GetClassImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - CORINFO_CLASS_HANDLE handle = (CORINFO_CLASS_HANDLE) pResolvedToken->hClass; - - ZapImport * pImport = GetImport(handle, (PVOID)kind); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - EncodeClass(kind, handle, &sigBuilder); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetMethodImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, - CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken /*=NULL*/) -{ - SigBuilder sigBuilder; - EncodeMethod(kind, handle, &sigBuilder, pResolvedToken, pConstrainedResolvedToken); - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - -ZapImport * ZapImportTable::GetFieldImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - SigBuilder sigBuilder; - EncodeField(kind, handle, &sigBuilder, pResolvedToken); - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - -#ifdef FEATURE_READYTORUN_COMPILER -ZapImport * ZapImportTable::GetCheckTypeLayoutImport(CORINFO_CLASS_HANDLE handle) -{ - ZapImport * pImport = GetImport(handle, (PVOID)ENCODE_CHECK_TYPE_LAYOUT); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - sigBuilder.AppendData(ENCODE_CHECK_TYPE_LAYOUT); - - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), handle, &sigBuilder, NULL, NULL); - - GetCompileInfo()->EncodeTypeLayout(handle, &sigBuilder); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetCheckFieldOffsetImport(CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, DWORD offset) -{ - SigBuilder sigBuilder; - - sigBuilder.AppendData(ENCODE_CHECK_FIELD_OFFSET); - - sigBuilder.AppendData(offset); - - GetCompileInfo()->EncodeField(m_pImage->GetModuleHandle(), handle, &sigBuilder, NULL, NULL, pResolvedToken); - - EncodeField(ENCODE_CHECK_FIELD_OFFSET, handle, &sigBuilder, pResolvedToken); - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} -#endif // FEATURE_READYTORUN_COMPILER - -ZapImport * ZapImportTable::GetStubDispatchCell(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - CORINFO_METHOD_HANDLE handle = pResolvedToken->hMethod; - - SigBuilder sigBuilder; - - DWORD slot = GetCompileInfo()->TryEncodeMethodSlot(handle); - if (slot != (DWORD) -1) - { - CORINFO_CLASS_HANDLE clsHandle = pResolvedToken->hClass; - - CORINFO_MODULE_HANDLE referencingModule = GetJitInfo()->getClassModule(clsHandle); - - referencingModule = TryEncodeModule(ENCODE_VIRTUAL_ENTRY_SLOT, referencingModule, &sigBuilder); - - sigBuilder.AppendData(slot); - - EncodeClassInContext(referencingModule, clsHandle, &sigBuilder); - } - else - { - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = GetCompileInfo()->TryEncodeMethodAsToken(handle, pResolvedToken, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_VIRTUAL_ENTRY_DEF_TOKEN : ENCODE_VIRTUAL_ENTRY_REF_TOKEN, - referencingModule, &sigBuilder); - - sigBuilder.AppendData(RidFromToken(token)); - } - else - { - EncodeMethod(ENCODE_VIRTUAL_ENTRY, handle, &sigBuilder, pResolvedToken); - } - } - - // For now, always optimize ready to run for size and startup performance - share cells between callsites - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - -ZapImport * ZapImportTable::GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken) -{ - SigBuilder sigBuilder; - - CORINFO_MODULE_HANDLE referencingModule; - mdToken token = GetCompileInfo()->TryEncodeMethodAsToken(handle, pResolvedToken, &referencingModule); - if (token != mdTokenNil) - { - _ASSERTE(TypeFromToken(token) == mdtMethodDef || TypeFromToken(token) == mdtMemberRef); - - EncodeModule( - (TypeFromToken(token) == mdtMethodDef) ? ENCODE_METHOD_ENTRY_DEF_TOKEN : ENCODE_METHOD_ENTRY_REF_TOKEN, - referencingModule, &sigBuilder); - - sigBuilder.AppendData(RidFromToken(token)); - } - else - { - EncodeMethod(ENCODE_METHOD_ENTRY, handle, &sigBuilder, pResolvedToken, pConstrainedResolvedToken, false); - } - - return GetImportForSignature((PVOID)handle, &sigBuilder); -} - - -#ifdef FEATURE_READYTORUN_COMPILER - -class ZapDynamicHelperCell : public ZapImport -{ - ZapNode * m_pDelayLoadHelper; - -public: - void SetDelayLoadHelper(ZapNode * pDelayLoadHelper) - { - _ASSERTE(m_pDelayLoadHelper == NULL); - m_pDelayLoadHelper = pDelayLoadHelper; - } - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_DynamicHelperCell; - } - - CORCOMPILE_FIXUP_BLOB_KIND GetKind() - { - int kind = (int)(SIZE_T)GetHandle(); - - if ((kind & 1) == 1) - { - return (CORCOMPILE_FIXUP_BLOB_KIND)(kind >> 1); - } - else - { - _ASSERTE( - (GetBlob()->GetSize() > 0) && ( - GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_THISOBJ || - GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_METHOD || - GetBlob()->GetData()[0] == ENCODE_DICTIONARY_LOOKUP_TYPE)); - - return (CORCOMPILE_FIXUP_BLOB_KIND)GetBlob()->GetData()[0]; - } - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Encode should be unreachable for ready-to-run cells - _ASSERTE(false); - } - - virtual void Save(ZapWriter * pZapWriter) - { - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - TARGET_POINTER_TYPE cell; - pImage->WriteReloc(&cell, 0, m_pDelayLoadHelper, 0, IMAGE_REL_BASED_PTR); - pZapWriter->Write(&cell, sizeof(cell)); - } -}; - -static ReadyToRunHelper GetDelayLoadHelperForDynamicHelper(CORCOMPILE_FIXUP_BLOB_KIND kind) -{ - switch (kind) - { - case ENCODE_NEW_HELPER: - case ENCODE_NEW_ARRAY_HELPER: - case ENCODE_STATIC_BASE_NONGC_HELPER: - case ENCODE_STATIC_BASE_GC_HELPER: - case ENCODE_THREAD_STATIC_BASE_NONGC_HELPER: - case ENCODE_THREAD_STATIC_BASE_GC_HELPER: - case ENCODE_CCTOR_TRIGGER: - case ENCODE_FIELD_ADDRESS: - case ENCODE_DICTIONARY_LOOKUP_THISOBJ: - case ENCODE_DICTIONARY_LOOKUP_TYPE: - case ENCODE_DICTIONARY_LOOKUP_METHOD: - return READYTORUN_HELPER_DelayLoad_Helper; - - case ENCODE_CHKCAST_HELPER: - case ENCODE_ISINSTANCEOF_HELPER: - return READYTORUN_HELPER_DelayLoad_Helper_Obj; - - case ENCODE_VIRTUAL_ENTRY: - // case ENCODE_VIRTUAL_ENTRY_DEF_TOKEN: - // case ENCODE_VIRTUAL_ENTRY_REF_TOKEN: - // case ENCODE_VIRTUAL_ENTRY_SLOT: - return READYTORUN_HELPER_DelayLoad_Helper_Obj; - - case ENCODE_DELEGATE_CTOR: - return READYTORUN_HELPER_DelayLoad_Helper_ObjObj; - - default: - UNREACHABLE(); - } -} - -void ZapImportSectionSignatures::PlaceDynamicHelperCell(ZapImport * pImport) -{ - ZapDynamicHelperCell * pCell = (ZapDynamicHelperCell *)pImport; - - if (m_pImportSection->GetNodeCount() == 0) - { - m_dwIndex = m_pImage->GetImportSectionsTable()->Append(CORCOMPILE_IMPORT_TYPE_UNKNOWN, CORCOMPILE_IMPORT_FLAGS_PCODE, - TARGET_POINTER_SIZE, m_pImportSection, this, m_pGCRefMapTable); - } - - // Create the delay load helper - ReadyToRunHelper helperNum = GetDelayLoadHelperForDynamicHelper(pCell->GetKind()); - ZapNode * pDelayLoadHelper = m_pImage->GetImportTable()->GetPlacedIndirectHelperThunk(helperNum, (PVOID)(SIZE_T)m_dwIndex); - - pCell->SetDelayLoadHelper(pDelayLoadHelper); - - // Add entry to both the the cell and data sections - m_pImportSection->Place(pCell); - - m_pImage->GetImportTable()->PlaceImportBlob(pCell); -} - -ZapImport * ZapImportTable::GetDictionaryLookupCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE containingMethod, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pLookup) -{ - _ASSERTE(pLookup->needsRuntimeLookup); - - SigBuilder sigBuilder; - - sigBuilder.AppendData(kind); - - if (kind == ENCODE_DICTIONARY_LOOKUP_THISOBJ) - { - CORINFO_CLASS_HANDLE hClassContext = GetJitInfo()->getMethodClass(containingMethod); - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), hClassContext, &sigBuilder, this, EncodeModuleHelper); - } - - switch (pLookup->runtimeLookupFlags) - { - case READYTORUN_FIXUP_TypeHandle: - case READYTORUN_FIXUP_DeclaringTypeHandle: - { - if (pResolvedToken->pTypeSpec == NULL) - { - _ASSERTE(!"Invalid IL that directly references __Canon"); - ThrowHR(E_NOTIMPL); - } - - if (pLookup->runtimeLookupFlags == READYTORUN_FIXUP_DeclaringTypeHandle) - { - _ASSERTE(pLookup->runtimeLookupArgs != NULL); - sigBuilder.AppendData(ENCODE_DECLARINGTYPE_HANDLE); - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), (CORINFO_CLASS_HANDLE)pLookup->runtimeLookupArgs, &sigBuilder, this, EncodeModuleHelper); - } - else - { - sigBuilder.AppendData(ENCODE_TYPE_HANDLE); - } - - if (pResolvedToken->tokenType == CORINFO_TOKENKIND_Newarr) - sigBuilder.AppendElementType(ELEMENT_TYPE_SZARRAY); - sigBuilder.AppendBlob((PVOID)pResolvedToken->pTypeSpec, pResolvedToken->cbTypeSpec); - } - break; - - case READYTORUN_FIXUP_MethodHandle: - EncodeMethod(ENCODE_METHOD_HANDLE, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, NULL, TRUE); - break; - - case READYTORUN_FIXUP_MethodEntry: - EncodeMethod(ENCODE_METHOD_ENTRY, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, (CORINFO_RESOLVED_TOKEN*)pLookup->runtimeLookupArgs, TRUE); - break; - - case READYTORUN_FIXUP_VirtualEntry: - EncodeMethod(ENCODE_VIRTUAL_ENTRY, pResolvedToken->hMethod, &sigBuilder, pResolvedToken, NULL, TRUE); - break; - - case READYTORUN_FIXUP_FieldHandle: - EncodeField(ENCODE_FIELD_HANDLE, pResolvedToken->hField, &sigBuilder, pResolvedToken, TRUE); - break; - - default: - _ASSERTE(!"Invalid R2R fixup kind!"); - ThrowHR(E_NOTIMPL); - } - - return GetImportForSignature((void*)containingMethod, &sigBuilder); -} - -ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle) -{ - ZapImport * pImport = GetImport((void *)(uintptr_t)((kind << 1) | 1), handle); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - sigBuilder.AppendData(kind); - - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), handle, &sigBuilder, this, EncodeModuleHelper); - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_CLASS_HANDLE delegateType /*=NULL*/) -{ - SigBuilder sigBuilder; - - EncodeMethod(kind, handle, &sigBuilder, pResolvedToken); - - if (delegateType != NULL) - { - _ASSERTE(kind == ENCODE_DELEGATE_CTOR); - GetCompileInfo()->EncodeClass(m_pImage->GetModuleHandle(), delegateType, &sigBuilder, this, EncodeModuleHelper); - } - - return GetImportForSignature((void *)(uintptr_t)((kind << 1) | 1), &sigBuilder); -} - -ZapImport * ZapImportTable::GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - SigBuilder sigBuilder; - - EncodeField(kind, handle, &sigBuilder, pResolvedToken); - - return GetImportForSignature((void *)(uintptr_t)((kind << 1) | 1), &sigBuilder); -} - -class ZapIndirectHelperThunk : public ZapImport -{ - DWORD SaveWorker(ZapWriter * pZapWriter); - -public: - ReadyToRunHelper GetReadyToRunHelper() - { - return (ReadyToRunHelper)((DWORD)(SIZE_T)GetHandle() & ~READYTORUN_HELPER_FLAG_VSD); - } - - DWORD GetSectionIndex() - { - return (DWORD)(SIZE_T)GetHandle2(); - } - - BOOL IsDelayLoadHelper() - { - ReadyToRunHelper helper = GetReadyToRunHelper(); - return (helper == READYTORUN_HELPER_DelayLoad_MethodCall) || - (helper == READYTORUN_HELPER_DelayLoad_Helper) || - (helper == READYTORUN_HELPER_DelayLoad_Helper_Obj) || - (helper == READYTORUN_HELPER_DelayLoad_Helper_ObjObj); - } - - BOOL IsDelayLoadMethodCallHelper() - { - ReadyToRunHelper helper = GetReadyToRunHelper(); - return (helper == READYTORUN_HELPER_DelayLoad_MethodCall); - } - - BOOL IsVSD() - { - return ((DWORD)(SIZE_T)GetHandle() & READYTORUN_HELPER_FLAG_VSD) != 0; - } - - BOOL IsLazyHelper() - { - ReadyToRunHelper helper = GetReadyToRunHelper(); - return (helper == READYTORUN_HELPER_GetString); - } - - DWORD GetSize() - { - return SaveWorker(NULL); - } - - void Save(ZapWriter * pZapWriter) - { - SaveWorker(pZapWriter); - } - - virtual UINT GetAlignment() - { - return MINIMUM_CODE_ALIGN; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_IndirectHelperThunk; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Encode should be unreachable for ready-to-run cells - _ASSERTE(false); - } -}; - -#ifdef TARGET_ARM -static void MovRegImm(BYTE* p, int reg) -{ - *(WORD *)(p + 0) = 0xF240; - *(WORD *)(p + 2) = (UINT16)(reg << 8); - *(WORD *)(p + 4) = 0xF2C0; - *(WORD *)(p + 6) = (UINT16)(reg << 8); -} -#endif // TARGET_ARM - -DWORD ZapIndirectHelperThunk::SaveWorker(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - BYTE buffer[44]; - BYTE * p = buffer; - -#if defined(TARGET_X86) - if (IsDelayLoadHelper()) - { - // xor eax, eax - *p++ = 0x33; - *p++ = 0xC0; - - // push index - *p++ = 0x6A; - _ASSERTE(GetSectionIndex() <= 0x7F); - *p++ = (BYTE)GetSectionIndex(); - - // push [module] - *p++ = 0xFF; - *p++ = 0x35; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR); - p += 4; - } - else - if (IsLazyHelper()) - { - // mov edx, [module] - *p++ = 0x8B; - *p++ = 0x15; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR); - p += 4; - } - - // jmp [helper] - *p++ = 0xFF; - *p++ = 0x25; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR); - p += 4; -#elif defined(TARGET_AMD64) - if (IsDelayLoadHelper()) - { - if (IsVSD()) - { - // mov rax, r11 - *p++ = 0x49; - *p++ = 0x8b; - *p++ = 0xc3; - } - else - { - // xor eax, eax - *p++ = 0x33; - *p++ = 0xC0; - } - - // push index - *p++ = 0x6A; - _ASSERTE(GetSectionIndex() <= 0x7F); - *p++ = (BYTE)GetSectionIndex(); - - // push [module] - *p++ = 0xFF; - *p++ = 0x35; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_REL32); - p += 4; - } - else - if (IsLazyHelper()) - { - *p++ = 0x48; - *p++ = 0x8B; -#ifdef UNIX_AMD64_ABI - // mov rsi, [module] - *p++ = 0x35; -#else - // mov rdx, [module] - *p++ = 0x15; -#endif - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_REL32); - p += 4; - } - - // jmp [helper] - *p++ = 0xFF; - *p++ = 0x25; - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_REL32); - p += 4; -#elif defined(TARGET_ARM) - if (IsDelayLoadHelper()) - { - // r4 contains indirection cell - // push r4 - *(WORD *)(p + 0) = 0xB410; - p += 2; - - // mov r4, index - _ASSERTE(GetSectionIndex() <= 0x7F); - *(WORD *)(p + 0) = 0x2400 | (BYTE)GetSectionIndex(); - p += 2; - - // push r4 - *(WORD *)(p + 0) = 0xB410; - p += 2; - - // mov r4, [module] - MovRegImm(p, 4); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r4, [r4] - *(WORD *)p = 0x6824; - p += 2; - - // push r4 - *(WORD *)(p + 0) = 0xB410; - p += 2; - - // mov r4, [helper] - MovRegImm(p, 4); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r4, [r4] - *(WORD *)p = 0x6824; - p += 2; - - // bx r4 - *(WORD *)p = 0x4720; - p += 2; - } - else - { - if (IsLazyHelper()) - { - // mov r1, [helper] - MovRegImm(p, 1); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r1, [r1] - *(WORD *)p = 0x6809; - p += 2; - } - - // mov r12, [helper] - MovRegImm(p, 12); - if (pImage != NULL) - pImage->WriteReloc(buffer, (int) (p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_THUMB_MOV32); - p += 8; - - // ldr r12, [r12] - *(DWORD *)p = 0xC000F8DC; - p += 4; - - // bx r12 - *(WORD *)p = 0x4760; - p += 2; - } -#elif defined(TARGET_ARM64) - if (IsDelayLoadHelper()) - { - // x11 contains indirection cell - // Do nothing x11 contains our first param - - // movz x9, #index - DWORD index = GetSectionIndex(); - _ASSERTE(index <= 0x7F); - *(DWORD*)p = 0xd2800009 | (index << 5); - p += 4; - - // move Module* -> x10 - // ldr x10, [PC+0x14] - *(DWORD*)p = 0x580000AA; - p += 4; - - //ldr x10, [x10] - *(DWORD*)p = 0xf940014A; - p += 4; - } - else - if (IsLazyHelper()) - { - // Move Module* -> x1 - // ldr x1, [PC+0x14] - *(DWORD*)p = 0x580000A1; - p += 4; - - // ldr x1, [x1] - *(DWORD*)p = 0xf9400021; - p += 4; - } - - // branch to helper - // ldr x12, [PC+0x14] - *(DWORD*)p = 0x580000AC; - p += 4; - - // ldr x12, [x12] - *(DWORD *)p = 0xf940018c; - p += 4; - - // br x12 - *(DWORD *)p = 0xd61f0180; - p += 4; - - // [Module*] - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_Module), 0, IMAGE_REL_BASED_PTR); - p += 8; - - // [helper] - if (pImage != NULL) - pImage->WriteReloc(buffer, (int)(p - buffer), pImage->GetImportTable()->GetHelperImport(GetReadyToRunHelper()), 0, IMAGE_REL_BASED_PTR); - p += 8; -#else - PORTABILITY_ASSERT("ZapIndirectHelperThunk::SaveWorker"); -#endif - - _ASSERTE((DWORD)(p - buffer) <= sizeof(buffer)); - - if (pZapWriter != NULL) - pZapWriter->Write(&buffer, (int)(p - buffer)); - - return (DWORD)(p - buffer); -} - -void ZapImportTable::PlaceIndirectHelperThunk(ZapNode * pImport) -{ - ZapIndirectHelperThunk * pThunk = (ZapIndirectHelperThunk *)pImport; - - if (pThunk->IsDelayLoadMethodCallHelper()) - m_pImage->m_pLazyMethodCallHelperSection->Place(pThunk); - else - m_pImage->m_pLazyHelperSection->Place(pThunk); - - if (pThunk->IsDelayLoadHelper() || pThunk->IsLazyHelper()) - GetPlacedHelperImport(READYTORUN_HELPER_Module); - - GetPlacedHelperImport(pThunk->GetReadyToRunHelper()); -} - -ZapNode * ZapImportTable::GetIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg) -{ - ZapNode * pImport = GetImport((void *)helperNum, pArg); -#if defined(TARGET_ARM) - pImport = m_pImage->GetInnerPtr(pImport, THUMB_CODE); -#endif - return pImport; -} - -ZapNode * ZapImportTable::GetPlacedIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg) -{ - ZapNode * pImport = GetImport((void *)helperNum, pArg); - if (!pImport->IsPlaced()) - PlaceIndirectHelperThunk(pImport); -#if defined(TARGET_ARM) - pImport = m_pImage->GetInnerPtr(pImport, THUMB_CODE); -#endif - return pImport; -} - -class ZapHelperImport : public ZapImport -{ -public: - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - *pfIsEager = TRUE; - *pfNeedsSignature = TRUE; - return ZapImportSectionType_Handle; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Import_Helper; - } - - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) - { - // Encode should be unreachable for ready-to-run cells - _ASSERTE(false); - } -}; - -ZapImport * ZapImportTable::GetHelperImport(ReadyToRunHelper helperNum) -{ - ZapImport * pImport = GetImport((void *)helperNum); - - if (!pImport->HasBlob()) - { - SigBuilder sigBuilder; - - sigBuilder.AppendByte(ENCODE_READYTORUN_HELPER); - sigBuilder.AppendData(helperNum); - - pImport->SetBlob(GetBlob(&sigBuilder)); - } - - return pImport; -} - -ZapImport * ZapImportTable::GetPlacedHelperImport(ReadyToRunHelper helperNum) -{ - ZapImport * pImport = GetHelperImport(helperNum); - if (!pImport->IsPlaced()) - PlaceImport(pImport); - return pImport; -} - -#endif // FEATURE_READYTORUN_COMPILER diff --git a/src/coreclr/zap/zapimport.h b/src/coreclr/zap/zapimport.h deleted file mode 100644 index e1d33286a4d11e..00000000000000 --- a/src/coreclr/zap/zapimport.h +++ /dev/null @@ -1,553 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapImport.h -// - -// -// Import is soft bound references to elements outside the current module -// -// ====================================================================================== - -#ifndef __ZAPIMPORT_H__ -#define __ZAPIMPORT_H__ - -class ZapImportTable; -class ZapGCRefMapTable; -class NibbleWriter; - -//--------------------------------------------------------------------------------------- -// -// ZapImport is the import cell itself -// -// Every import cell is uniquely identified by its ZapNodeType and two handles -// (the second handle is optional and is often NULL) -// -// Actual implementations inherits from this abstract base class. -// -class ZapImport : public ZapNode -{ - COUNT_T m_index; - DWORD m_offset; - - PVOID m_handle; - PVOID m_handle2; - - ZapBlob * m_pBlob; - -public: - void SetHandle(PVOID handle) - { - _ASSERTE(m_handle == NULL); - m_handle = handle; - } - - void SetHandle2(PVOID handle2) - { - _ASSERTE(m_handle2 == NULL); - m_handle2 = handle2; - } - - PVOID GetHandle() - { - return m_handle; - } - - PVOID GetHandle2() - { - return m_handle2; - } - - void SetBlob(ZapBlob * pBlob) - { - _ASSERTE(m_pBlob == NULL); - m_pBlob = pBlob; - } - - ZapBlob * GetBlob() - { - _ASSERTE(m_pBlob != NULL); - return m_pBlob; - } - - BOOL HasBlob() - { - return m_pBlob != NULL; - } - - virtual ZapImportSectionType ComputePlacement(ZapImage * pImage, BOOL * pfIsEager, BOOL * pfNeedsSignature) - { - *pfIsEager = FALSE; - *pfNeedsSignature = TRUE; - return ZapImportSectionType_Handle; - } - - // All subtypes have to override - virtual void EncodeSignature(ZapImportTable * pTable, SigBuilder * pSigBuilder) = 0; - - virtual DWORD GetSize() - { - return TARGET_POINTER_SIZE; - } - - virtual UINT GetAlignment() - { - return TARGET_POINTER_SIZE; - } - - virtual void Save(ZapWriter * pZapWriter); - - // - // Offset of the fixup cell within its section - // - - void SetSectionIndexAndOffset(COUNT_T index, DWORD offset) - { - m_index = index; - m_offset = offset; - } - - DWORD GetSectionIndex() - { - return m_index; - } - - DWORD GetOffset() - { - return m_offset; - } -}; - -//--------------------------------------------------------------------------------------- -// -// ZapGenericSignature is signature of generic dictionary entry. -// -class ZapGenericSignature : public ZapBlob -{ -public: - ZapGenericSignature(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_GenericSignature; - } -}; - -//--------------------------------------------------------------------------------------- -// -// ZapImportTable is the main class that keeps track of all ZapImports. -// -// There is a single instance of it per image. -// -class ZapImportTable -{ - // - // Hashtable key of the import - // The same key is used for both ZapImport and ZapImportBlob - // - struct ImportKey - { - FORCEINLINE ImportKey(PVOID handle, ZapNodeType type) - : m_handle(handle), m_handle2(NULL), m_type(type) - { - } - - FORCEINLINE ImportKey(PVOID handle, PVOID handle2, ZapNodeType type) - : m_handle(handle), m_handle2(handle2), m_type(type) - { - } - - PVOID m_handle; - PVOID m_handle2; - ZapNodeType m_type; - }; - - // - // Hashtable of ZapImports - // - class ImportTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ImportKey key_t; - - static FORCEINLINE key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return ImportKey(e->GetHandle(), e->GetHandle2(), e->GetType()); - } - static FORCEINLINE BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1.m_handle == k2.m_handle) && (k1.m_handle2 == k2.m_handle2) && (k1.m_type == k2.m_type); - } - static FORCEINLINE count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k.m_handle ^ ((count_t)(size_t)k.m_handle2 << 1) ^ k.m_type; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< ImportTraits > ImportTable; - - // - // Hashtable of module indices - // - struct ModuleReferenceEntry - { - CORINFO_MODULE_HANDLE m_module; - DWORD m_index; - }; - - class ModuleReferenceTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef CORINFO_MODULE_HANDLE key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->m_module; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1 == k2); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< ModuleReferenceTraits > ModuleReferenceTable; - - // - // Helpers for inserting actual implementations of ZapImports into hashtable - // - template < typename impl, ZapNodeType type > - ZapImport * GetImport(PVOID handle) - { - ZapImport * pImport = m_imports.Lookup(ImportKey(handle, type)); - - if (pImport != NULL) - { - return pImport; - } - - pImport = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pImport->GetType() == type); - pImport->SetHandle(handle); - m_imports.Add(pImport); - return pImport; - } - - template < typename impl, ZapNodeType type > - ZapImport * GetImport(PVOID handle, PVOID handle2) - { - ZapImport * pImport = m_imports.Lookup(ImportKey(handle, handle2, type)); - - if (pImport != NULL) - { - return pImport; - } - - pImport = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pImport->GetType() == type); - pImport->SetHandle(handle); - pImport->SetHandle2(handle2); - m_imports.Add(pImport); - return pImport; - } - - template < typename impl, ZapNodeType type > - ZapImport * GetImportForSignature(PVOID handle, SigBuilder * pSigBuilder) - { - ZapBlob * pBlob = GetBlob(pSigBuilder); - - ZapImport * pImport = m_imports.Lookup(ImportKey(handle, pBlob, type)); - - if (pImport != NULL) - { - return pImport; - } - - pImport = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pImport->GetType() == type); - pImport->SetHandle(handle); - pImport->SetHandle2(pBlob); - pImport->SetBlob(pBlob); - m_imports.Add(pImport); - return pImport; - } - - ZapImport * GetExistingImport(ZapNodeType type, PVOID handle) - { - return m_imports.Lookup(ImportKey(handle, type)); - } - - ModuleReferenceEntry * GetModuleReference(CORINFO_MODULE_HANDLE handle); - - static DWORD EncodeModuleHelper(LPVOID referencingModule, CORINFO_MODULE_HANDLE referencedModule); - - ImportTable m_imports; // Interned ZapImport * - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; // Interned ZapBlos for signatures and fixups - - ModuleReferenceTable m_moduleReferences; - - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_genericSignatures; - - DWORD m_nImportSectionSizes[ZapImportSectionType_Total]; - COUNT_T m_nImportSectionIndices[ZapImportSectionType_Total]; - - ZapImage * m_pImage; - -public: - ZapImportTable(ZapImage * pImage) - : m_pImage(pImage) - { - // Everything else is zero initialized by the allocator - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapImportTable::m_imports, 0.0030, cbILImage); - PREALLOCATE_HASHTABLE(ZapImportTable::m_blobs, 0.0025, cbILImage); - - PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapImportTable::m_moduleReferences, cbILImage); - } - - // - // Helpers for encoding import blobs - // - - void EncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder); - void EncodeClass(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder); - void EncodeClassInContext(CORINFO_MODULE_HANDLE context, CORINFO_CLASS_HANDLE handle, SigBuilder * pSigBuilder); - void EncodeField(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); - void EncodeMethod(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, SigBuilder * pSigBuilder, - CORINFO_RESOLVED_TOKEN * pResolvedToken = NULL, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL, - BOOL fEncodeUsingResolvedTokenSpecStreams = FALSE); - - // Encode module if the reference is within current version bubble. If not, return a suitable module within current version bubble. - CORINFO_MODULE_HANDLE TryEncodeModule(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_MODULE_HANDLE module, SigBuilder * pSigBuilder); - - ICorDynamicInfo * GetJitInfo() - { - return m_pImage->GetJitInfo(); - } - - ICorCompileInfo * GetCompileInfo() - { - return m_pImage->GetCompileInfo(); - } - - ZapImage * GetImage() - { - return m_pImage; - } - - // Returns index of module in the import table for encoding module fixups in EE datastructures. - DWORD GetIndexOfModule(CORINFO_MODULE_HANDLE handle) - { - ZapImportTable::ModuleReferenceEntry * pModuleReference = GetModuleReference(handle); - _ASSERTE(pModuleReference != NULL); - return pModuleReference->m_index; - } - - // Get the import blob for given signature - ZapBlob * GetBlob(SigBuilder * pSigBuilder, BOOL fEager = FALSE); - - // Place give import blob - void PlaceBlob(ZapBlob * pBlob, BOOL fEager = FALSE); - - // Encodes the import blob and places it into the image - ZapBlob * PlaceImportBlob(ZapImport * pImport, BOOL fEager = FALSE); - - // Places import cell into the image. - // This also encoded and places all the import blobs if they are not placed yet. - void PlaceImport(ZapImport * pImport); - - // Encodes list of fixups and places it into the image. - // This also places all the import cells if they are not placed yet. - ZapFixupInfo * PlaceFixups(ZapImport ** pImports); - void PlaceFixups(ZapImport ** pImports, NibbleWriter& writer); - - ZapGenericSignature * GetGenericSignature(PVOID signature, BOOL fMethod); - - // - // The actual implementations of import cells - // - ZapImport * GetFunctionEntryImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetModuleHandleImport(CORINFO_MODULE_HANDLE handle); - ZapImport * GetClassHandleImport(CORINFO_CLASS_HANDLE handle, PVOID pUniqueId = NULL); - ZapImport * GetMethodHandleImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetFieldHandleImport(CORINFO_FIELD_HANDLE handle); - ZapImport * GetStringHandleImport(CORINFO_MODULE_HANDLE tokenScope, mdString metaTok); - ZapImport * GetStaticFieldAddressImport(CORINFO_FIELD_HANDLE handle); - ZapImport * GetClassDomainIdImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetModuleDomainIdImport(CORINFO_MODULE_HANDLE handleToModule, CORINFO_CLASS_HANDLE handleToClass); - ZapImport * GetSyncLockImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetIndirectPInvokeTargetImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetPInvokeTargetImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetProfilingHandleImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetVarArgImport(CORINFO_MODULE_HANDLE handle, mdToken sigOrMemberRefOrDef); - ZapImport * GetActiveDependencyImport(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo); - - ZapImport * GetExistingClassHandleImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetExistingMethodHandleImport(CORINFO_METHOD_HANDLE handle); - ZapImport * GetExistingFieldHandleImport(CORINFO_FIELD_HANDLE handle); - - ZapImport * GetVirtualImportThunk(CORINFO_METHOD_HANDLE handle, int slot); - void PlaceVirtualImportThunk(ZapImport * pImportThunk); - - ZapImport * GetExternalMethodThunk(CORINFO_METHOD_HANDLE handle); - ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle); - ZapImport * GetStubDispatchCell(CORINFO_CLASS_HANDLE typeHnd, CORINFO_METHOD_HANDLE methHnd); - - // - // Ready-to-run imports - // - ZapImport * GetClassImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_RESOLVED_TOKEN * pResolvedToken); - ZapImport * GetMethodImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken = NULL); - ZapImport * GetFieldImport(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken); - - ZapImport * GetCheckTypeLayoutImport(CORINFO_CLASS_HANDLE handle); - ZapImport * GetCheckFieldOffsetImport(CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, DWORD offset); - - ZapImport * GetStubDispatchCell(CORINFO_RESOLVED_TOKEN * pResolvedToken); - ZapImport * GetExternalMethodCell(CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken); - - ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_CLASS_HANDLE handle); - ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_CLASS_HANDLE delegateType = NULL); - ZapImport * GetDynamicHelperCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_FIELD_HANDLE handle, CORINFO_RESOLVED_TOKEN * pResolvedToken); - - ZapImport * GetDictionaryLookupCell(CORCOMPILE_FIXUP_BLOB_KIND kind, CORINFO_METHOD_HANDLE containingMethod, CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_LOOKUP_KIND * pLookup); - -#ifdef FEATURE_READYTORUN_COMPILER - ZapNode * GetPlacedIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL); - ZapNode * GetIndirectHelperThunk(ReadyToRunHelper helperNum, PVOID pArg = NULL); - void PlaceIndirectHelperThunk(ZapNode * pImport); - - ZapImport * GetPlacedHelperImport(ReadyToRunHelper helperNum); - ZapImport * GetHelperImport(ReadyToRunHelper helperNum); -#endif -}; - -// -// CORCOMPILE_CODE_IMPORT_SECTION -// -class ZapImportSectionsTable : public ZapNode -{ - struct ImportSection - { - ZapVirtualSection * m_pSection; - ZapNode * m_pSignatures; - ZapNode * m_pAuxiliaryData; - USHORT m_Flags; - BYTE m_Type; - BYTE m_EntrySize; - }; - - SArray m_ImportSectionsTable; - -public: - ZapImportSectionsTable(ZapImage * pImage) - { - } - - COUNT_T Append(BYTE Type, USHORT Flags, BYTE EntrySize, ZapVirtualSection * pSection, ZapNode * pSignatures = NULL, ZapNode * pAuxiliaryData = NULL); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual DWORD GetSize(); - - virtual ZapNodeType GetType() - { - return ZapNodeType_ImportSectionsTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// ZapImportSectionSignatures contains an array of signature RVAs for given import section. -// -class ZapImportSectionSignatures : public ZapNode -{ - ZapVirtualSection * m_pImportSection; - ZapGCRefMapTable * m_pGCRefMapTable; - - DWORD m_dwIndex; - - ZapImage * m_pImage; - -public: - ZapImportSectionSignatures(ZapImage * pImage, ZapVirtualSection * pImportSection, ZapVirtualSection * pGCSection = NULL); - ~ZapImportSectionSignatures(); - - void PlaceExternalMethodThunk(ZapImport * pImport); - void PlaceExternalMethodCell(ZapImport * pImport); - void PlaceStubDispatchCell(ZapImport * pImport); - void PlaceDynamicHelperCell(ZapImport * pImport); - - virtual DWORD GetSize(); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ImportSectionSignatures; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#include "gcrefmap.h" - -class ZapGCRefMapTable : public ZapNode -{ - ZapImage * m_pImage; - GCRefMapBuilder m_GCRefMapBuilder; - COUNT_T m_nCount; - -public: - ZapGCRefMapTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Append(CORINFO_METHOD_HANDLE handle, bool isDispatchCell = false); - - virtual DWORD GetSize(); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_GCRefMapTable; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -#endif // __ZAPIMPORT_H__ diff --git a/src/coreclr/zap/zapinfo.cpp b/src/coreclr/zap/zapinfo.cpp deleted file mode 100644 index b1066dcf807345..00000000000000 --- a/src/coreclr/zap/zapinfo.cpp +++ /dev/null @@ -1,4326 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInfo.cpp -// - -// -// JIT-EE interface for zapping -// -// ====================================================================================== - -#include "common.h" - -#include "zapcode.h" -#include "zapimport.h" -#include "zapwrapper.h" -#include "zapinnerptr.h" -#include "zapmetadata.h" - -#ifdef FEATURE_READYTORUN_COMPILER -#include "zapreadytorun.h" -#endif - -ZapInfo::ZapInfo(ZapImage * pImage, mdMethodDef md, CORINFO_METHOD_HANDLE handle, CORINFO_MODULE_HANDLE module, unsigned methodProfilingDataFlags) - : m_pImage(pImage), - m_currentMethodToken(md), - m_currentMethodHandle(handle), - m_currentMethodModule(module), - m_currentMethodProfilingDataFlags(methodProfilingDataFlags), - - m_pNativeVarInfo(NULL), - m_iNativeVarInfo(0), - m_pOffsetMapping(NULL), - m_iOffsetMapping(0), - m_pGCInfo(NULL), - m_cbGCInfo(0), - m_pCode(NULL), - m_pColdCode(NULL), - m_pROData(NULL), -#ifdef FEATURE_EH_FUNCLETS - // Unwind info of the main method body. It will get merged with GC info. - m_pMainUnwindInfo(NULL), - m_cbMainUnwindInfo(0), - - m_pUnwindInfo(NULL), - m_pUnwindInfoFragments(NULL), -#if defined(TARGET_AMD64) - m_pChainedColdUnwindInfo(NULL), -#endif -#endif // FEATURE_EH_FUNCLETS - m_pExceptionInfo(NULL), - m_pProfileData(NULL), - m_pProfilingHandle(NULL), - - m_ClassLoadTable(pImage), - m_MethodLoadTable(pImage) -{ - m_zapper = m_pImage->m_zapper; - - m_pEEJitInfo = m_zapper->m_pEEJitInfo; - m_pEEJitInfo->setOverride(this, handle); - - m_pEECompileInfo = m_zapper->m_pEECompileInfo; -} - -ZapInfo::~ZapInfo() -{ - m_pEEJitInfo->setOverride(NULL, NULL); - - delete [] m_pNativeVarInfo; - delete [] m_pOffsetMapping; - - delete [] m_pGCInfo; -#ifdef FEATURE_EH_FUNCLETS - delete [] m_pMainUnwindInfo; -#endif - if (m_pgoResults != nullptr) - { - ProfileDataResults* current = m_pgoResults; - while (current != nullptr) - { - ProfileDataResults* next = current->m_next; - delete current; - current = next; - } - } -} - -#ifdef ALLOW_SXS_JIT_NGEN -// The AltJit failed and we're going to retry. Forget everything the JIT told us and prepare to JIT again. -void ZapInfo::ResetForJitRetry() -{ - delete [] m_pNativeVarInfo; - m_pNativeVarInfo = NULL; - - m_iNativeVarInfo = 0; - - delete [] m_pOffsetMapping; - m_pOffsetMapping = NULL; - - m_iOffsetMapping = 0; - - delete [] m_pGCInfo; - m_pGCInfo = NULL; - - m_cbGCInfo = 0; - -#ifdef FEATURE_EH_FUNCLETS - delete [] m_pMainUnwindInfo; - m_pMainUnwindInfo = NULL; - - m_cbMainUnwindInfo = 0; -#endif // FEATURE_EH_FUNCLETS - - // The rest of these pointers are in the ZapWriter's ZapHeap, and will go away when the ZapWriter - // goes away. That's ok for altjit fallback; we'll use extra memory until the ZapWriter goes away, - // but we won't write anything to the image. We just zero out the pointers and constants, and we're good. - - m_pCode = NULL; - m_pColdCode = NULL; - m_pROData = NULL; - -#ifdef FEATURE_EH_FUNCLETS - m_pUnwindInfoFragments = NULL; - m_pUnwindInfo = NULL; -#if defined(TARGET_AMD64) - m_pChainedColdUnwindInfo = NULL; -#endif -#endif // FEATURE_EH_FUNCLETS - - m_pExceptionInfo = NULL; - m_pProfileData = NULL; - m_pProfilingHandle = NULL; - - m_ImportSet.RemoveAll(); - m_Imports.Clear(); - m_CodeRelocations.Clear(); -} -#endif // ALLOW_SXS_JIT_NGEN - -void ZapInfo::InitMethodName() -{ - const char* szClsName; - const char* szMethodName = m_pEEJitInfo->getMethodName( - m_currentMethodHandle, - &szClsName); - - m_currentMethodName.SetUTF8(szClsName); - m_currentMethodName.AppendUTF8(NAMESPACE_SEPARATOR_STR); - m_currentMethodName.AppendUTF8(szMethodName); -} - -CORJIT_FLAGS ZapInfo::ComputeJitFlags(CORINFO_METHOD_HANDLE handle) -{ - CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags; - - CORJIT_FLAGS flags; - IfFailThrow(m_pEECompileInfo->GetBaseJitFlags(handle, &flags)); - jitFlags.Add(flags); - - // COMPlus_JitFramed specifies the default fpo setting for jitted and NGened code. - // You can override the behavior for NGened code using COMPlus_NGenFramed. - static ConfigDWORD g_NGenFramed; - DWORD dwNGenFramed = g_NGenFramed.val(CLRConfig::UNSUPPORTED_NGenFramed); - if (dwNGenFramed == 0) - { - // NGened code should enable fpo - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); - } - else if (dwNGenFramed == 1) - { - // NGened code should disable fpo - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FRAMED); - } - - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SKIP_VERIFICATION); - - if (m_pImage->m_profileDataSections[MethodBlockCounts].pData && - !m_zapper->m_pOpt->m_ignoreProfileData) - { - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); - } - - // - // By default we always enable Hot/Cold procedure splitting - // - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - - if (m_zapper->m_pOpt->m_noProcedureSplitting) - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - - // If the method is specified for min-opts then turn everything off - if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT)) - { - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_BBOPT); - jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - } - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_READYTORUN); - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_PINVOKE_HELPERS); - } -#endif // FEATURE_READYTORUN_COMPILER - -#ifdef ARM_SOFTFP - jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_SOFTFP_ABI); -#endif - - return jitFlags; -} - -ZapDebugInfo * ZapInfo::EmitDebugInfo() -{ - if (m_iNativeVarInfo == 0 && m_iOffsetMapping == 0) - { - return NULL; - } - - // We create a temporary buffer which is conservatily estimated to be - // bigger than we need. We then copy the used portion into the ngen image. - - StackSBuffer debugInfoBuffer; - m_pEECompileInfo->CompressDebugInfo( - m_pOffsetMapping, m_iOffsetMapping, - m_pNativeVarInfo, m_iNativeVarInfo, - &debugInfoBuffer); - - if (IsReadyToRunCompilation()) - return ZapBlob::NewBlob(m_pImage, &debugInfoBuffer[0], debugInfoBuffer.GetSize()); - - return m_pImage->m_pDebugInfoTable->GetDebugInfo(&debugInfoBuffer[0], debugInfoBuffer.GetSize()); -} - -ZapGCInfo * ZapInfo::EmitGCInfo() -{ - _ASSERTE(m_pGCInfo != NULL); - -#ifdef FEATURE_EH_FUNCLETS - return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo, m_pMainUnwindInfo, m_cbMainUnwindInfo); -#else - return m_pImage->m_pGCInfoTable->GetGCInfo(m_pGCInfo, m_cbGCInfo); -#endif // FEATURE_EH_FUNCLETS -} - -ZapImport ** ZapInfo::EmitFixupList() -{ - ZapImport ** pFixupList = NULL; - - if (m_Imports.GetCount() != 0) - { - pFixupList = new (m_pImage->GetHeap()) ZapImport * [m_Imports.GetCount() + 1]; - memcpy(pFixupList, &(m_Imports[0]), m_Imports.GetCount() * sizeof(ZapImport *)); - } - - return pFixupList; -} - -// Used by qsort -int __cdecl ZapInfo::CompareCodeRelocation(const void * a_, const void * b_) -{ - ZapInfo::CodeRelocation * a = (ZapInfo::CodeRelocation *)a_; - ZapInfo::CodeRelocation * b = (ZapInfo::CodeRelocation *)b_; - - if (a->m_pNode != b->m_pNode) - { - return (a->m_pNode > b->m_pNode) ? 1 : -1; - } - - return a->m_offset - b->m_offset; -} - -void ZapInfo::EmitCodeRelocations() -{ - if (m_CodeRelocations.IsEmpty()) - return; - - qsort(&m_CodeRelocations[0], m_CodeRelocations.GetCount(), sizeof(CodeRelocation), CompareCodeRelocation); - - COUNT_T startIndex = 0; - while (startIndex < m_CodeRelocations.GetCount()) - { - ZapBlobWithRelocs * pNode = m_CodeRelocations[startIndex].m_pNode; - - COUNT_T endIndex = startIndex + 1; - for ( ; endIndex < m_CodeRelocations.GetCount(); endIndex++) - { - if (m_CodeRelocations[endIndex].m_pNode != pNode) - break; - } - - ZapReloc * pRelocs = (ZapReloc *) - new (m_pImage->GetHeap()) BYTE[sizeof(ZapReloc) * (endIndex - startIndex) + sizeof(ZapRelocationType)]; - - for (COUNT_T i = 0; i < endIndex - startIndex; i++) - pRelocs[i] = m_CodeRelocations[startIndex + i]; - - // Set sentinel - static_assert_no_msg(offsetof(ZapReloc, m_type) == 0); - *(ZapRelocationType *)(pRelocs + (endIndex - startIndex)) = IMAGE_REL_INVALID; - - pNode->SetRelocs(pRelocs); - - startIndex = endIndex; - } -} - -void ZapInfo::ProcessReferences() -{ - COUNT_T count = m_CodeRelocations.GetCount(); - for (COUNT_T i = 0; i < count; i++) - { - CORINFO_METHOD_HANDLE hMethod = NULL; - CORINFO_CLASS_HANDLE hClass = NULL; - bool fMaybeConditionalImport = false; - - ZapNode * pTarget = m_CodeRelocations[i].m_pTargetNode; - - ZapNodeType type = pTarget->GetType(); - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - switch (type) - { - case ZapNodeType_MethodEntryPoint: - hMethod = ((ZapMethodEntryPoint*)pTarget)->GetHandle(); - - if (m_pImage->m_pPreloader->DoesMethodNeedRestoringBeforePrestubIsRun(hMethod)) - { - methodMustBeLoadedBeforeCodeIsRun(hMethod); - } - break; - - case ZapNodeType_Import_MethodHandle: - case ZapNodeType_Import_FunctionEntry: - case ZapNodeType_Import_IndirectPInvokeTarget: - case ZapNodeType_Import_PInvokeTarget: - hMethod = (CORINFO_METHOD_HANDLE)(((ZapImport *)pTarget)->GetHandle()); - fMaybeConditionalImport = true; - break; - case ZapNodeType_Import_ClassHandle: - case ZapNodeType_Import_ClassDomainId: - case ZapNodeType_Import_SyncLock: - hClass = (CORINFO_CLASS_HANDLE)((ZapImport *)pTarget)->GetHandle(); - fMaybeConditionalImport = true; - break; - case ZapNodeType_Import_FieldHandle: - case ZapNodeType_Import_StaticFieldAddress: - hClass = m_pEEJitInfo->getFieldClass((CORINFO_FIELD_HANDLE)(((ZapImport *)pTarget)->GetHandle())); - fMaybeConditionalImport = true; - break; - case ZapNodeType_Import_StringHandle: - case ZapNodeType_Import_ModuleHandle: - case ZapNodeType_Import_ModuleDomainId: - case ZapNodeType_Import_VarArg: - fMaybeConditionalImport = true; - break; - - case ZapNodeType_MethodHandle: - hMethod = (CORINFO_METHOD_HANDLE)(((ZapWrapper *)pTarget)->GetHandle()); - break; - - case ZapNodeType_ExternalMethodThunk: - case ZapNodeType_ExternalMethodCell: - hMethod = (CORINFO_METHOD_HANDLE)((ZapImport*)pTarget)->GetHandle(); - break; - - default: - break; - } - - if (fMaybeConditionalImport) - { - const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr((ZapImport *)pTarget); - if (pExistingEntry != NULL && pExistingEntry->fConditional) - { - const_cast(pExistingEntry)->fConditional = false; - m_Imports.Append((ZapImport *)pTarget); - - // 'handle' does not have to be added to CORCOMPILE_LOAD_TABLE since we adding - // it to CORCOMPILE_HANDLE_TABLE - if (hMethod != NULL) - m_MethodLoadTable.Load(hMethod, TRUE); - else - if (hClass != NULL) - m_ClassLoadTable.Load(hClass, TRUE); - } - } - - if (hMethod != NULL) - { - m_pImage->m_pPreloader->MethodReferencedByCompiledCode(hMethod); - } - } -} - -// Compile a method using the JIT or Module compiler, and emit fixups - -void ZapInfo::CompileMethod() -{ - PRECONDITION(m_zapper->m_pJitCompiler != NULL); - - InitMethodName(); - - if (m_zapper->m_pOpt->m_verbose) - { - // The evaluation of m_currentMethodName.GetUnicode() is expensive - // only do it when we are truely logging - m_zapper->Info(W("Compiling method %s\n"), m_currentMethodName.GetUnicode()); - } - - if (GetCompileInfo()->IsUnmanagedCallersOnlyMethod(m_currentMethodHandle)) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Methods with UnmanagedCallersOnlyAttribute not implemented\n")); - ThrowHR(E_NOTIMPL); - } - - if (GetCompileInfo()->IsUnmanagedCallConvMethod(m_currentMethodHandle)) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Methods with UnmanagedCallConvAttribute not implemented\n")); - ThrowHR(E_NOTIMPL); - } - - m_currentMethodInfo = CORINFO_METHOD_INFO(); - if (!getMethodInfo(m_currentMethodHandle, &m_currentMethodInfo)) - { - return; - } - - // Method does not have IL (e.g. an abstract method) - if (m_currentMethodInfo.ILCodeSize == 0) - return; - - // If we are doing partial ngen, only compile methods with profile data - if (!CurrentMethodHasProfileData() && m_zapper->m_pOpt->m_fPartialNGen) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Info(W("Skipped because of no profile data\n")); - return; - } - - // During ngen we look for a hint attribute on the method that indicates - // the method should be preprocessed for early - // preparation. This normally happens automatically, but for methods that - // are prepared explicitly at runtime the needed - // information is missing from the ngen image, causing costly overheads - // at runtime. When the author of the method knows about - // this they can add the hint and reduce the perf cost at runtime. - m_pImage->m_pPreloader->PrePrepareMethodIfNecessary(m_currentMethodHandle); - - // Retrieve method attributes from EEJitInfo - the ZapInfo's version updates - // some of the flags related to hardware intrinsics but we don't want that. - DWORD methodAttribs = m_pEEJitInfo->getMethodAttribs(m_currentMethodHandle); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation() && (methodAttribs & CORINFO_FLG_AGGRESSIVE_OPT)) - { - // Skip methods marked with MethodImplOptions.AggressiveOptimization, they will be jitted instead. In the future, - // consider letting the JIT determine whether aggressively optimized code can/should be pregenerated for the method - // instead of this check. - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Info(W("Skipped because of aggressive optimization flag\n")); - return; - } -#endif - -#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) - if (methodAttribs & CORINFO_FLG_JIT_INTRINSIC) - { - // Skip generating hardware intrinsic method bodies. - // - // We don't know what the implementation should do (whether it can do the actual intrinsic thing, or whether - // it should throw a PlatformNotSupportedException). - - const char* namespaceName; - getMethodNameFromMetadata(m_currentMethodHandle, nullptr, &namespaceName, nullptr); - if (strcmp(namespaceName, "System.Runtime.Intrinsics.X86") == 0 - || strcmp(namespaceName, "System.Runtime.Intrinsics.Arm") == 0 - || strcmp(namespaceName, "System.Runtime.Intrinsics") == 0) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Info(W("Skipped due to being a hardware intrinsic\n")); - return; - } - } -#endif - - m_jitFlags = ComputeJitFlags(m_currentMethodHandle); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - // READYTORUN: FUTURE: Producedure spliting - m_jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROCSPLIT); - } -#endif - - if (m_pImage->m_stats) - { - m_pImage->m_stats->m_methods++; - m_pImage->m_stats->m_ilCodeSize += m_currentMethodInfo.ILCodeSize; - } - - CorJitResult res = CORJIT_SKIPPED; // FAILED() returns true for this value - - uint8_t *pCode; - uint32_t cCode; - bool doNormalCompile = true; - -#ifdef ALLOW_SXS_JIT_NGEN - - // Only retry the JIT compilation when we have a different JIT to run - // Often we see both COMPlus_AltJIT and COMPlus_AltJitNgen set - // which results in both JIT compilers set to the same altjit - // - doNormalCompile = (m_zapper->m_alternateJit != m_zapper->m_pJitCompiler); - - // Compile this method using the AltJitNgen compiler - // - if (m_zapper->m_alternateJit) - { - m_jitFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_ALT_JIT); - res = m_zapper->m_alternateJit->compileMethod( this, - &m_currentMethodInfo, - CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, - &pCode, - &cCode); - - // The above compileMethod call will typically return CORJIT_SKIPPED - if (doNormalCompile && FAILED(res)) - { - // We will fall back to the "main" JIT on failure. - ResetForJitRetry(); - } - } - m_jitFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_ALT_JIT); - -#endif // ALLOW_SXS_JIT_NGEN - - // Compile this method using the normal JIT compiler - // - if (doNormalCompile && FAILED(res)) - { - ICorJitCompiler * pCompiler = m_zapper->m_pJitCompiler; - res = pCompiler->compileMethod(this, - &m_currentMethodInfo, - CORJIT_FLAGS::CORJIT_FLAG_CALL_GETJITFLAGS, - &pCode, - &cCode); - if (FAILED(res)) - { - ThrowExceptionForJitResult(res); - } - } - - MethodCompileComplete(m_currentMethodInfo.ftn); - -#ifdef TARGET_X86 - // The x86 JIT over estimates the code size. Trim the blob size down to - // the actual size. - // We can do this only for non-split code. Adjusting the code size for split - // methods would hose offsets in GC info. - if (m_pColdCode == NULL) - { - m_pCode->AdjustBlobSize(cCode); - } -#endif - - PublishCompiledMethod(); -} - -#ifndef FEATURE_FULL_NGEN -class MethodCodeComparer -{ - static BOOL NodeEquals(ZapNode * k1, ZapNode * k2) - { - return k1 == k2; - } - - static BOOL BlobEquals(ZapBlob * k1, ZapBlob * k2) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - if (k1->GetBlobSize() != k2->GetBlobSize()) - return FALSE; - if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0) - return FALSE; - - return TRUE; - } - - typedef ZapNode * EquivalentNodes[4][2]; - - static BOOL EquivalentNode(ZapNode * k1, ZapNode * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == k2) - return TRUE; - - for (unsigned int i = 0; i < _countof(equivalentNodes); i++) - { - if (k1 == equivalentNodes[i][0] && k2 == equivalentNodes[i][1]) - return TRUE; - } - - return FALSE; - } - - static BOOL BlobWithRelocsEquals(ZapBlobWithRelocs * k1, ZapBlobWithRelocs * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - if (k1->GetBlobSize() != k2->GetBlobSize()) - return FALSE; - if (memcmp(k1->GetData(), k2->GetData(), k1->GetBlobSize()) != 0) - return FALSE; - - ZapReloc * pRelocs1 = k1->GetRelocs(); - ZapReloc * pRelocs2 = k2->GetRelocs(); - - if (pRelocs1 == NULL && pRelocs2 == NULL) - return TRUE; - if (pRelocs1 == NULL || pRelocs2 == NULL) - return FALSE; - - while (pRelocs1->m_type != IMAGE_REL_INVALID || pRelocs2->m_type != IMAGE_REL_INVALID) - { - if (pRelocs1->m_type != pRelocs2->m_type || pRelocs1->m_offset != pRelocs2->m_offset) - return FALSE; - - if (!EquivalentNode(pRelocs1->m_pTargetNode, pRelocs2->m_pTargetNode, equivalentNodes)) - return FALSE; - - pRelocs1++; pRelocs2++; - } - - return TRUE; - } - - static BOOL UnwindInfoEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - return (k1->GetStartOffset() == k2->GetStartOffset()) && - (k1->GetEndOffset() == k2->GetEndOffset()) && - (k1->GetUnwindData() == k2->GetUnwindData()) && - EquivalentNode(k1->GetCode(), k2->GetCode(), equivalentNodes); - } - - static BOOL UnwindInfoFragmentsEquals(ZapUnwindInfo * k1, ZapUnwindInfo * k2, EquivalentNodes & equivalentNodes) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - while (k1 != NULL || k2 != NULL) - { - if (!UnwindInfoEquals(k1, k2, equivalentNodes)) - return FALSE; - - k1 = k1->GetNextFragment(); k2 = k2->GetNextFragment(); - } - - return TRUE; - } - - static BOOL FixupListEquals(ZapImport ** k1, ZapImport ** k2) - { - if (k1 == NULL && k2 == NULL) - return TRUE; - if (k1 == NULL || k2 == NULL) - return FALSE; - - while (*k1 != NULL || *k2 != NULL) - { - if (*k1 != *k2) - return FALSE; - k1++; k2++; - } - - return TRUE; - } - -public: - static BOOL MethodCodeEquals(ZapMethodHeader * k1, ZapMethodHeader * k2) - { - LIMITED_METHOD_CONTRACT; - - EquivalentNodes equivalentNodes = - { - { k1->m_pCode, k2->m_pCode }, - { k1->m_pColdCode, k2->m_pColdCode }, - { k1->m_pROData, k2->m_pROData }, - { k1->m_pProfileData, k2->m_pProfileData } - }; - - if (!BlobWithRelocsEquals(k1->m_pCode, k2->m_pCode, equivalentNodes)) - return FALSE; - - if (!BlobWithRelocsEquals(k1->m_pColdCode, k2->m_pColdCode, equivalentNodes)) - return FALSE; - - if (!UnwindInfoEquals(k1->m_pUnwindInfo, k2->m_pUnwindInfo, equivalentNodes)) - return FALSE; - - if (!UnwindInfoEquals(k1->m_pColdUnwindInfo, k2->m_pColdUnwindInfo, equivalentNodes)) - return FALSE; - -#ifdef FEATURE_EH_FUNCLETS - if (!UnwindInfoFragmentsEquals(k1->m_pUnwindInfoFragments, k2->m_pUnwindInfoFragments, equivalentNodes)) - return FALSE; -#endif - - if (!BlobWithRelocsEquals(k1->m_pROData, k2->m_pROData, equivalentNodes)) - return FALSE; - - if (!BlobWithRelocsEquals(k1->m_pProfileData, k2->m_pProfileData, equivalentNodes)) - return FALSE; - - if (!NodeEquals(k1->m_pGCInfo, k2->m_pGCInfo)) // interned - return FALSE; - - if (!NodeEquals(k1->m_pDebugInfo, k2->m_pDebugInfo)) // interned - return FALSE; - - if (!FixupListEquals(k1->m_pFixupList, k2->m_pFixupList)) - return FALSE; - - if (!BlobEquals(k1->m_pExceptionInfo, k2->m_pExceptionInfo)) - return FALSE; - - return TRUE; - } -}; - -extern BOOL CanDeduplicateCode(CORINFO_METHOD_HANDLE method, CORINFO_METHOD_HANDLE duplicateMethod); - -BOOL ZapImage::MethodCodeTraits::Equals(key_t k1, key_t k2) -{ - if (!MethodCodeComparer::MethodCodeEquals(k1, k2)) - return FALSE; - - // Check additional VM conditions that has to be satisfied for deduplication - if (!CanDeduplicateCode(k1->GetHandle(), k2->GetHandle())) - return FALSE; - - return TRUE; -} - -COUNT_T ZapImage::MethodCodeTraits::Hash(key_t k) -{ - COUNT_T hash = ZapBlob::SHashTraits::Hash(ZapBlob::SHashTraits::GetKey(k->m_pCode)); - - ZapReloc * pRelocs = k->m_pCode->GetRelocs(); - if (pRelocs != NULL) - { - while (pRelocs->m_type != IMAGE_REL_INVALID) - { - ZapNode * pTarget = pRelocs->m_pTargetNode; - ZapNodeType type = pTarget->GetType(); - - if (type == ZapNodeType_InnerPtr) - { - pTarget = ((ZapInnerPtr *)pTarget)->GetBase(); - type = pTarget->GetType(); - } - - // The IL stubs code often differs by just a method call or class handle. Include - // these in the hash code. - switch (type) - { - case ZapNodeType_MethodEntryPoint: - case ZapNodeType_ExternalMethodThunk: - case ZapNodeType_ClassHandle: - case ZapNodeType_Import_ClassHandle: - case ZapNodeType_MethodHandle: - case ZapNodeType_Import_MethodHandle: - hash = ((hash << 5) + hash) ^ (COUNT_T)((SIZE_T)pTarget); - break; - default: - break; - } - - pRelocs++; - } - } - - return hash; -} -#endif - -void ZapInfo::PublishCompiledMethod() -{ - EmitCodeRelocations(); - - // Go through all references in the code, make sure that we have fixups for them, - // and ensure that they will be otherwise present in the image if necessary - ProcessReferences(); - - // See if there are load fixups to emit. - m_ClassLoadTable.EmitLoadFixups(m_currentMethodHandle, this); - - if (!IsReadyToRunCompilation()) - m_MethodLoadTable.EmitLoadFixups(m_currentMethodHandle, this); - - ZapMethodHeader * pMethod = new (m_pImage->GetHeap()) ZapMethodHeader(); - - pMethod->m_handle = m_currentMethodHandle; - pMethod->m_classHandle = getMethodClass(m_currentMethodHandle); - - pMethod->m_pCode = m_pCode; - pMethod->m_pColdCode = m_pColdCode; - pMethod->m_pROData = m_pROData; - - pMethod->m_pProfileData = m_pProfileData; - - pMethod->m_pExceptionInfo = m_pExceptionInfo; - - pMethod->m_pFixupList = EmitFixupList(); - - pMethod->m_pDebugInfo = EmitDebugInfo(); - pMethod->m_pGCInfo = EmitGCInfo(); - -#ifdef FEATURE_EH_FUNCLETS - pMethod->m_pUnwindInfoFragments = m_pUnwindInfoFragments; - - // Set the combined GCInfo + UnwindInfo blob - m_pUnwindInfo->SetUnwindData(pMethod->m_pGCInfo); - -#if defined(TARGET_AMD64) - if (m_pChainedColdUnwindInfo != NULL) - { - // Chain the cold unwind info with the hot unwind info - m_pChainedColdUnwindInfo->SetUnwindData(m_pUnwindInfo); - } -#endif // TARGET_AMD64 - -#endif // FEATURE_EH_FUNCLETS - -#ifndef FEATURE_FULL_NGEN - // - // Method code deduplication - // - // For now, the only methods eligible for de-duplication are IL stubs - // - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - ZapMethodHeader * pDuplicateMethod = m_pImage->m_CodeDeduplicator.Lookup(pMethod); - if (pDuplicateMethod != NULL) - { - m_pImage->m_pPreloader->NoteDeduplicatedCode(pMethod->m_handle, pDuplicateMethod->m_handle); - return; - } - - m_pImage->m_CodeDeduplicator.Add(pMethod); - } -#endif - - // Remember the gc info for IL stubs associated with hot methods so they can be packed well. - // Stubs that have no metadata token cannot be tracked by IBC data. - if (m_currentMethodProfilingDataFlags & (1 << ReadMethodCode)) - { - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - m_pImage->m_PrioritizedGCInfo.Append(pMethod->m_pGCInfo); - } - - pMethod->m_ProfilingDataFlags = m_currentMethodProfilingDataFlags; - - COUNT_T methodCompilationOrder = m_pImage->m_MethodCompilationOrder.GetCount(); - pMethod->m_compilationOrder = methodCompilationOrder; - - // We need to remember the first index into m_MethodCompilationOrder where we saw a method from this class - m_pImage->InitializeClassLayoutOrder(pMethod->m_classHandle, methodCompilationOrder); - - m_pImage->m_CompiledMethods.Add(pMethod); - m_pImage->m_MethodCompilationOrder.Append(pMethod); -} - -void ZapInfo::getGSCookie(GSCookie * pCookieVal, GSCookie ** ppCookieVal) -{ - *pCookieVal = 0; - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - *ppCookieVal = (GSCookie *)m_pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_GSCookie); - return; - } -#endif - - *ppCookieVal = (GSCookie *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, gsCookie)); -} - -uint32_t ZapInfo::getJitFlags(CORJIT_FLAGS* jitFlags, uint32_t sizeInBytes) -{ - _ASSERTE(jitFlags != NULL); - _ASSERTE(sizeInBytes >= sizeof(m_jitFlags)); - - *jitFlags = m_jitFlags; - return sizeof(m_jitFlags); -} - -bool ZapInfo::runWithErrorTrap(void (*function)(void*), void* param) -{ - return m_pEEJitInfo->runWithErrorTrap(function, param); -} - -HRESULT ZapInfo::allocPgoInstrumentationBySchema(CORINFO_METHOD_HANDLE ftnHnd, - PgoInstrumentationSchema* pSchema, - uint32_t countSchemaItems, - uint8_t** pInstrumentationData) -{ - HRESULT hr; - - *pInstrumentationData = nullptr; - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - return E_NOTIMPL; - } - - // Only allocation of PGO data for the current method is supported. - if (m_currentMethodHandle != ftnHnd) - { - return E_NOTIMPL; - } - - // @TODO: support generic methods from other assemblies - if (m_currentMethodModule != m_pImage->m_hModule) - { - return E_NOTIMPL; - } - - - mdMethodDef md = m_currentMethodToken; - - if (IsNilToken(md)) - { - // This must be the non-System.Object instantiation of a generic type/method. - IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &md)); - } -#ifdef _DEBUG - else - { - mdMethodDef mdTemp; - IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(m_currentMethodHandle, &mdTemp)); - _ASSERTE(md == mdTemp); - } -#endif - if (IsNilToken(md)) - { - return E_FAIL; - } - - // Validate that each schema item is only used for a basic block count - for (UINT32 iSchema = 0; iSchema < countSchemaItems; iSchema++) - { - if (pSchema[iSchema].InstrumentationKind != PgoInstrumentationKind::BasicBlockIntCount) - return E_NOTIMPL; - if (pSchema[iSchema].Count != 1) - return E_NOTIMPL; - } - - // If the JIT retries the compilation (especially during JIT stress), it can - // try to allocate the profiling data multiple times. We will just keep track - // of the latest copy in this case. - // _ASSERTE(m_pProfileData == NULL); - - DWORD totalSize = (DWORD) (countSchemaItems * sizeof(ICorJitInfo::BlockCounts)) + sizeof(CORBBTPROF_METHOD_HEADER); - m_pProfileData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, totalSize, sizeof(DWORD)); - CORBBTPROF_METHOD_HEADER * profileData = (CORBBTPROF_METHOD_HEADER *) m_pProfileData->GetData(); - profileData->size = totalSize; - profileData->cDetail = 0; - profileData->method.token = md; - profileData->method.ILSize = m_currentMethodInfo.ILCodeSize; - profileData->method.cBlock = countSchemaItems; - - ICorJitInfo::BlockCounts* blockCounts = (ICorJitInfo::BlockCounts *)(&profileData->method.block[0]); - *pInstrumentationData = (BYTE*)blockCounts; - - for (UINT32 iSchema = 0; iSchema < countSchemaItems; iSchema++) - { - // Update schema have correct offsets - pSchema[iSchema].Offset = (BYTE*)&blockCounts[iSchema].ExecutionCount - (BYTE*)blockCounts; - // Insert IL Offsets into block data to match schema - blockCounts[iSchema].ILOffset = pSchema[iSchema].ILOffset; - } - - return S_OK; -} - -HRESULT ZapInfo::getPgoInstrumentationResults(CORINFO_METHOD_HANDLE ftnHnd, - PgoInstrumentationSchema **pSchema, // pointer to the schema table which describes the instrumentation results (pointer will not remain valid after jit completes) - uint32_t * pCountSchemaItems, // pointer to the count schema items - uint8_t ** pInstrumentationData, // pointer to the actual instrumentation data (pointer will not remain valid after jit completes) - PgoSource* pPgoSource) -{ - _ASSERTE(pCountSchemaItems != nullptr); - _ASSERTE(pInstrumentationData != nullptr); - _ASSERTE(pSchema != nullptr); - - HRESULT hr; - - // Initialize outputs in case we return E_FAIL - *pCountSchemaItems = 0; - *pSchema = nullptr; - *pInstrumentationData = nullptr; - *pPgoSource = PgoSource::Unknown; - - int32_t numRuns = 0; - - // For generic instantiations whose IL is in another module, - // the profile data is in that module - // @TODO: Fetch the profile data from the other module. - if ((m_currentMethodModule != m_pImage->m_hModule) || - m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - return E_FAIL; - } - - ZapImage::ProfileDataSection * DataSection_MethodBlockCounts = & m_pImage->m_profileDataSections[MethodBlockCounts]; - - if (!DataSection_MethodBlockCounts->pData) - { - return E_FAIL; - } - - mdMethodDef md; - IfFailRet(m_zapper->m_pEECompileInfo->GetMethodDef(ftnHnd, &md)); - - if (IsNilToken(md)) - { - return E_FAIL; - } - - ProfileDataResults* pgoResults = m_pgoResults; - while (pgoResults != nullptr) - { - if (pgoResults->m_ftn == ftnHnd) - break; - pgoResults = pgoResults->m_next; - } - - if (pgoResults == nullptr) - { - const ZapImage::ProfileDataHashEntry * foundEntry = m_pImage->profileDataHashTable.LookupPtr(md); - - if (foundEntry == NULL) - { - return E_FAIL; - } - - // The md must match. - _ASSERTE(foundEntry->md == md); - - if (foundEntry->pos == 0) - { - // We might not have profile data and instead only have CompileStatus and flags - assert(foundEntry->size == 0); - return E_FAIL; - } - - // - // - // We found the md. Let's retrieve the profile data. - // - _ASSERTE(foundEntry->size >= sizeof(CORBBTPROF_METHOD_HEADER)); // The size must at least this - - ProfileReader profileReader(DataSection_MethodBlockCounts->pData, DataSection_MethodBlockCounts->dataSize); - - // Locate the method in interest. - SEEK(foundEntry->pos); - CORBBTPROF_METHOD_HEADER * profileData; - READ_SIZE(profileData, CORBBTPROF_METHOD_HEADER, foundEntry->size); - _ASSERTE(profileData->method.token == foundEntry->md); // We should be looking at the right method - _ASSERTE(profileData->size == foundEntry->size); // and the cached size must match - - // Find method's IL size - // - unsigned ilSize = m_currentMethodInfo.ILCodeSize; - - if (ftnHnd != m_currentMethodHandle) - { - CORINFO_METHOD_INFO methodInfo; - if (!getMethodInfo(ftnHnd, &methodInfo)) - { - return E_FAIL; - } - ilSize = methodInfo.ILCodeSize; - } - - // If the ILSize is non-zero the the ILCodeSize also must match - // - if ((profileData->method.ILSize != 0) && (profileData->method.ILSize != ilSize)) - { - // IL code for this method does not match the IL code for the method when it was profiled - // in such cases we tell the JIT to discard the profile data by returning E_FAIL - // - return E_FAIL; - } - - pgoResults = new ProfileDataResults(ftnHnd); - pgoResults->m_next = m_pgoResults; - m_pgoResults = pgoResults; - - pgoResults->pInstrumentationData = (BYTE*)&profileData->method.block[0]; - - ICorJitInfo::BlockCounts *blockCounts = (ICorJitInfo::BlockCounts *) &profileData->method.block[0]; - - PgoInstrumentationSchema numRunsSchema = {}; - numRunsSchema.Count = 1; - numRunsSchema.Other = m_pImage->m_profileDataNumRuns; - numRunsSchema.InstrumentationKind = ICorJitInfo::PgoInstrumentationKind::NumRuns; - pgoResults->m_schema.Append(numRunsSchema); - for (UINT32 iSchema = 0; iSchema < profileData->method.cBlock; iSchema++) - { - PgoInstrumentationSchema blockCountSchema = {}; - blockCountSchema.Count = 1; - blockCountSchema.InstrumentationKind = ICorJitInfo::PgoInstrumentationKind::BasicBlockIntCount; - blockCountSchema.ILOffset = blockCounts[iSchema].ILOffset; - blockCountSchema.Offset = (BYTE *)&blockCounts[iSchema].ExecutionCount - (BYTE*)blockCounts; - pgoResults->m_schema.Append(blockCountSchema); - } - pgoResults->m_hr = S_OK; - } - - *pCountSchemaItems = pgoResults->m_schema.GetCount(); - *pSchema = pgoResults->m_schema.GetElements(); - *pInstrumentationData = pgoResults->pInstrumentationData; - *pPgoSource = PgoSource::IBC; - - return pgoResults->m_hr; -} - -void ZapInfo::allocMem(AllocMemArgs *pArgs) -{ - bool optForSize = m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_SIZE_OPT); - - UINT align = DEFAULT_CODE_ALIGN; - - if ((pArgs->flag & CORJIT_ALLOCMEM_FLG_16BYTE_ALIGN) && !IsReadyToRunCompilation()) align = max(align, 16); - - m_pCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, pArgs->hotCodeSize, align); - pArgs->hotCodeBlock = m_pCode->GetData(); - pArgs->hotCodeBlockRW = m_pCode->GetData(); - - if (pArgs->coldCodeSize != 0) - { - align = sizeof(DWORD); - - m_pColdCode = ZapCodeBlob::NewAlignedBlob(m_pImage, NULL, pArgs->coldCodeSize, align); - pArgs->coldCodeBlock = m_pColdCode->GetData(); - pArgs->coldCodeBlockRW = m_pColdCode->GetData(); - } - - // - // Allocate data - // - - if (pArgs->roDataSize > 0) - { - if (pArgs->flag & CORJIT_ALLOCMEM_FLG_RODATA_16BYTE_ALIGN) - { - align = 16; - } - else if (optForSize || (pArgs->roDataSize < 8)) - { - align = TARGET_POINTER_SIZE; - } - else - { - align = 8; - } - m_pROData = ZapBlobWithRelocs::NewAlignedBlob(m_pImage, NULL, pArgs->roDataSize, align); - pArgs->roDataBlock = m_pROData->GetData(); - pArgs->roDataBlockRW = m_pROData->GetData(); - } - - if (m_pImage->m_stats) - { - m_pImage->m_stats->m_nativeCodeSize += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSize += pArgs->coldCodeSize; - m_pImage->m_stats->m_nativeRODataSize += pArgs->roDataSize; - - BOOL haveProfileData = CurrentMethodHasProfileData(); - - if (haveProfileData) - { - m_pImage->m_stats->m_nativeCodeSizeInProfiledMethods += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInProfiledMethods += pArgs->coldCodeSize; - } - - if (pArgs->coldCodeSize) - { - m_pImage->m_stats->m_NumHotColdAllocations++; - - m_pImage->m_stats->m_nativeCodeSizeInSplitMethods += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInSplitMethods += pArgs->coldCodeSize; - - if (haveProfileData) - { - m_pImage->m_stats->m_nativeCodeSizeInSplitProfiledMethods += pArgs->hotCodeSize; - m_pImage->m_stats->m_nativeColdCodeSizeInSplitProfiledMethods += pArgs->coldCodeSize; - } - } - else - { - m_pImage->m_stats->m_NumHotAllocations++; - } - } -} - -void * ZapInfo::allocGCInfo(size_t size) -{ - _ASSERTE(m_pGCInfo == NULL); - -#ifdef HOST_64BIT - if (size & 0xFFFFFFFF80000000LL) - { - IfFailThrow(CORJIT_OUTOFMEM); - } -#endif // HOST_64BIT - - m_pGCInfo = new BYTE[size]; - m_cbGCInfo = size; - - return m_pGCInfo; -} - -void ZapInfo::setEHcount(unsigned cEH) -{ - // - // Must call after header has been allocated - // - - if (cEH == 0) - { - _ASSERTE(!"Should not be called"); - return; - } - - ULONG size = (sizeof(CORCOMPILE_EXCEPTION_CLAUSE) * cEH); - - _ASSERTE(m_pExceptionInfo == NULL); - m_pExceptionInfo = ZapBlob::NewAlignedBlob(m_pImage, NULL, size, sizeof(DWORD)); -} - -void ZapInfo::setEHinfo(unsigned EHnumber, - const CORINFO_EH_CLAUSE *clause) -{ - // - // Must call after EH info has been allocated - // - - _ASSERTE(m_pExceptionInfo != NULL); - - CORCOMPILE_EXCEPTION_CLAUSE *ehClauseArray = (CORCOMPILE_EXCEPTION_CLAUSE *)m_pExceptionInfo->GetData(); - CORCOMPILE_EXCEPTION_CLAUSE *ilClause = &ehClauseArray[EHnumber]; - - ilClause->TryStartPC = clause->TryOffset; - ilClause->TryEndPC = clause->TryLength; - ilClause->HandlerStartPC= clause->HandlerOffset; - ilClause->HandlerEndPC = clause->HandlerLength; - ilClause->Flags = (CorExceptionFlag) clause->Flags; - - if (clause->Flags & CORINFO_EH_CLAUSE_FILTER) - { - ilClause->FilterOffset = clause->FilterOffset; - } - else - { - ilClause->ClassToken = clause->ClassToken; - - if (ilClause->ClassToken != 0) - { - CORINFO_RESOLVED_TOKEN resolvedToken = { 0 }; - resolvedToken.tokenContext = MAKE_METHODCONTEXT(m_currentMethodInfo.ftn); - resolvedToken.tokenScope = m_currentMethodInfo.scope; - resolvedToken.token = ilClause->ClassToken; - resolvedToken.tokenType = CORINFO_TOKENKIND_Class; - - resolveToken(&resolvedToken); - - if (m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_IL_STUB)) - { - // IL stub tokens are 'private' and do not resolve correctly in their parent module's metadata. - - // Currently, the only place we are using a token here is for a COM-to-CLR exception-to-HRESULT - // mapping catch clause. We want this catch clause to catch all exceptions, so we override the - // token to be mdTypeRefNil, which used by the EH system to mean catch(...) -#ifdef _DEBUG - // The proper way to do this, should we ever want to support arbitrary types here, is to "pre- - // resolve" the token and store the TypeHandle in the clause. But this requires additional - // infrastructure to ensure the TypeHandle is saved and fixed-up properly. For now, we will - // simply assert that the original type was System.Object. - - CORINFO_CLASS_HANDLE systemObjectHandle = getBuiltinClass(CLASSID_SYSTEM_OBJECT); - _ASSERTE(systemObjectHandle == resolvedToken.hClass); -#endif // _DEBUG - ilClause->ClassToken = mdTypeRefNil; - } - else - { - // For all clause types add fixup to ensure the types are loaded before the code of the method - // containing the catch blocks is executed. This ensures that a failure to load the types would - // not happen when the exception handling is in progress and it is looking for a catch handler. - // At that point, we could only fail fast. - classMustBeLoadedBeforeCodeIsRun(resolvedToken.hClass); - } - } - } - - // - // @TODO: this does not support DynamicMethods - // -} - -int ZapInfo::canHandleException(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - return (EXCEPTION_EXECUTE_HANDLER); -} - -int ZapInfo::doAssert(const char* szFile, int iLine, const char* szExpr) -{ - -#if defined(_DEBUG) - return(_DbgBreakCheck(szFile, iLine, szExpr)); -#else - return(true); // break into debugger -#endif - -} -void ZapInfo::reportFatalError(CorJitResult result) -{ - m_zapper->Info(W("Jit reported error 0x%x while compiling %s\n"), (int)result, - m_currentMethodName.GetUnicode()); -} - -// Reserve memory for the method/funclet's unwind information -// Note that this must be called before allocMem, it should be -// called once for the main method, once for every funclet region, and -// once for every non-funclet cold region for which we will call -// allocUnwindinfo. -// -// For prejitted code we need to count how many funclet regions -// we have so that we can allocate and sort a contiguous .rdata block. -// -void ZapInfo::reserveUnwindInfo(bool isFunclet, bool isColdCode, uint32_t unwindSize) -{ - // Nothing to do -} - - -// -// Allocate and initialize the .xdata and .pdata for this method or -// funclet region and get the block of memory needed for the machine-specific -// unwind information (the info for crawling the stack frame). -// Note that allocMem must be called first. -// -// The pHotCode parameter points at the first byte of the code of the method. -// The startOffset and endOffset are the region (main or funclet) that -// we are to allocate and create .xdata and .pdata for. -// The pUnwindBlock is copied and contains the .xdata unwind info. -// -// Parameters: -// -// pHotCode main method code buffer, always filled in -// pColdCode cold code buffer, only filled in if this is cold code, -// null otherwise -// startOffset start of code block, relative to appropriate code buffer -// (e.g. pColdCode if cold, pHotCode if hot). -// endOffset end of code block, relative to appropriate code buffer -// unwindSize size of unwind info pointed to by pUnwindBlock -// pUnwindBlock pointer to unwind info -// funcKind type of funclet (main method code, handler, filter) -// -void ZapInfo::allocUnwindInfo ( - uint8_t * pHotCode, /* IN */ - uint8_t * pColdCode, /* IN */ - uint32_t startOffset, /* IN */ - uint32_t endOffset, /* IN */ - uint32_t unwindSize, /* IN */ - uint8_t * pUnwindBlock, /* IN */ - CorJitFuncKind funcKind /* IN */ - ) -{ -#ifdef FEATURE_EH_FUNCLETS - _ASSERTE(pHotCode == m_pCode->GetData()); - _ASSERTE(pColdCode == NULL || pColdCode == m_pColdCode->GetData()); - - ZapNode * pCode = (pColdCode != NULL) ? m_pColdCode : m_pCode; - - ZapUnwindInfo * pUnwindInfo = new (m_pImage->GetHeap()) ZapUnwindInfo(pCode, startOffset, endOffset); - - // Prepend the new unwind info to the linked list of all fragments - pUnwindInfo->SetNextFragment(m_pUnwindInfoFragments); - m_pUnwindInfoFragments = pUnwindInfo; - - if (funcKind == CORJIT_FUNC_ROOT && pColdCode == NULL && startOffset == 0) - { - // - // Main method unwind data - // - - _ASSERTE(m_pMainUnwindInfo == NULL); - - m_pMainUnwindInfo = new BYTE[unwindSize]; - m_cbMainUnwindInfo = unwindSize; - - memcpy(m_pMainUnwindInfo, pUnwindBlock, unwindSize); - - // UnwindData Will be set to the combined GCInfo + UnwindInfo blob later as the compiled method is published - - _ASSERTE(m_pUnwindInfo == NULL); - m_pUnwindInfo = pUnwindInfo; - } -#if defined(TARGET_AMD64) - else - if (funcKind == CORJIT_FUNC_ROOT && pColdCode != NULL) - { - // - // Chained cold code unwind data - // - - _ASSERTE(unwindSize == 0); - - // UnwindData Will be chained to the parent unwind info later as the compiled method is published - - _ASSERTE(m_pChainedColdUnwindInfo == NULL); - m_pChainedColdUnwindInfo = pUnwindInfo; - } -#endif - else - { - - // - // Normal unwind data - // - - ZapUnwindData * pUnwindData = m_pImage->m_pUnwindDataTable->GetUnwindData(pUnwindBlock, unwindSize, funcKind == CORJIT_FUNC_FILTER); - pUnwindInfo->SetUnwindData(pUnwindData); - } -#endif // FEATURE_EH_FUNCLETS -} - -bool ZapInfo::logMsg(unsigned level, const char *fmt, va_list args) -{ - if (HasSvcLogger()) - { - if (level <= LL_INFO10) - { - StackSString ss; - ss.VPrintf(fmt,args); - GetSvcLogger()->Log(ss.GetUnicode(), LogLevel_Success); - return TRUE; - } - } - -#ifdef LOGGING - if (LoggingOn(LF_JIT, level)) - { - LogSpewValist(LF_JIT, level, (char*) fmt, args); - return TRUE; - } -#endif // LOGGING - - return FALSE; -} - -// -// ICorDynamicInfo -// - -uint32_t ZapInfo::getThreadTLSIndex(void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = NULL; - return (uint32_t)-1; -} - -const void * ZapInfo::getInlinedCallFrameVptr(void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, inlinedCallFrameVptr)); - return NULL; -} - -int32_t * ZapInfo::getAddrOfCaptureThreadGlobal(void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = NULL; - if (IsReadyToRunCompilation()) - { - *ppIndirection = m_pImage->GetImportTable()->GetHelperImport(READYTORUN_HELPER_IndirectTrapThreads); - } - else - { - *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfCaptureThreadGlobal)); - } - - return NULL; -} - -// Get slow lazy string literal helper to use (CORINFO_HELP_STRCNS*). -// Returns CORINFO_HELP_UNDEF if lazy string literal helper cannot be used. -CorInfoHelpFunc ZapInfo::getLazyStringLiteralHelper(CORINFO_MODULE_HANDLE handle) -{ - if (handle == m_pImage->m_hModule) - return CORINFO_HELP_STRCNS_CURRENT_MODULE; - - return CORINFO_HELP_STRCNS; -} - -CORINFO_MODULE_HANDLE ZapInfo::embedModuleHandle(CORINFO_MODULE_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - _ASSERTE(!"embedModuleHandle"); - ThrowHR(E_NOTIMPL); - } - - BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedModuleHandle(handle); - if (fHardbound) - { - if (handle == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we will - // assume that Module is the very first thing in the preload section - *ppIndirection = NULL; - return (CORINFO_MODULE_HANDLE)m_pImage->m_pPreloadSections[CORCOMPILE_SECTION_MODULE]; - } - - *ppIndirection = m_pImage->GetImportTable()->GetModuleHandleImport(handle); - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetModuleHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - } - return NULL; -} - -// -// The following functions indicate whether a handle can be directly embedded into -// the code being compiled, or if it needs to be accessed with a (fixable) indirection. -// Embeddable handles are those that will be persisted in the zap image. -// -// These functions are gradually being all moved across to ceeload.cpp and compile.cpp. -// - -CORINFO_CLASS_HANDLE ZapInfo::embedClassHandle(CORINFO_CLASS_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - // This is supported by crossgen2 - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: embedding class handle not supported\n")); - - ThrowHR(E_NOTIMPL); - } - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle); - - BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedClassHandle(handle); - if (fHardbound) - { - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableType(handle); - - if (moduleHandle == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we can - // embed it after its resolved. So use a deferred reloc - - *ppIndirection = NULL; - return CORINFO_CLASS_HANDLE(m_pImage->GetWrappers()->GetClassHandle(handle)); - } - - *ppIndirection = m_pImage->GetImportTable()->GetClassHandleImport(handle); - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetClassHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - } - return NULL; -} - -CORINFO_FIELD_HANDLE ZapInfo::embedFieldHandle(CORINFO_FIELD_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - _ASSERTE(!"embedFieldHandle"); - ThrowHR(E_NOTIMPL); - } - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(m_pEEJitInfo->getFieldClass(handle)); - - BOOL fHardbound = m_pImage->m_pPreloader->CanEmbedFieldHandle(handle); - if (fHardbound) - { - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableField(handle); - - if (moduleHandle == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we can - // embed it after its resolved. So use a deferred reloc - - *ppIndirection = NULL; - return CORINFO_FIELD_HANDLE(m_pImage->GetWrappers()->GetFieldHandle(handle)); - } - } - - - ZapImport * pImport = m_pImage->GetImportTable()->GetFieldHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -CORINFO_METHOD_HANDLE ZapInfo::embedMethodHandle(CORINFO_METHOD_HANDLE handle, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - // READYTORUN FUTURE: Handle this case correctly - ThrowHR(E_NOTIMPL); - } - - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(handle); - if (moduleHandle == m_pImage->m_hModule - && m_pImage->m_pPreloader->CanEmbedMethodHandle(handle, m_currentMethodHandle)) - { - // If the handle is the module we are currently ngening, we can - // embed it after its resolved. So use a deferred reloc - - *ppIndirection = NULL; - return CORINFO_METHOD_HANDLE(m_pImage->GetWrappers()->GetMethodHandle(handle)); - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetMethodHandleImport(handle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -CORINFO_CLASS_HANDLE ZapInfo::getTokenTypeAsHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - return m_pEEJitInfo->getTokenTypeAsHandle(pResolvedToken); -} - -void ZapInfo::getLocationOfThisType(CORINFO_METHOD_HANDLE context, CORINFO_LOOKUP_KIND * pLookupKind) -{ - m_pEEJitInfo->getLocationOfThisType(context, pLookupKind); -} - -void -ZapInfo::embedGenericHandle(CORINFO_RESOLVED_TOKEN * pResolvedToken, - bool fEmbedParent, - CORINFO_GENERICHANDLE_RESULT *pResult) -{ - _ASSERTE(pResult); - - m_pEEJitInfo->embedGenericHandle( pResolvedToken, - fEmbedParent, - pResult); - - _ASSERTE(pResult->compileTimeHandle); - - if (pResult->lookup.lookupKind.needsRuntimeLookup) - { - if (!IsReadyToRunCompilation()) - embedGenericSignature(&pResult->lookup); - - if (pResult->handleType == CORINFO_HANDLETYPE_METHOD) - { - // There is no easy way to detect method referenced via generic lookups in generated code. - // Report this method reference unconditionally. - m_pImage->m_pPreloader->MethodReferencedByCompiledCode((CORINFO_METHOD_HANDLE)pResult->compileTimeHandle); - } - } - else - { - void *pIndirection = 0; - CORINFO_GENERIC_HANDLE handle = 0; - - switch (pResult->handleType) - { - case CORINFO_HANDLETYPE_CLASS: - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_HANDLE, pResolvedToken); - AppendConditionalImport(pImport); - pIndirection = pImport; - handle = NULL; - } - else - { - CORINFO_CLASS_HANDLE clsHnd = (CORINFO_CLASS_HANDLE) pResult->compileTimeHandle; - handle = CORINFO_GENERIC_HANDLE(embedClassHandle(clsHnd, &pIndirection)); - } - break; - - case CORINFO_HANDLETYPE_METHOD: - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_HANDLE, (CORINFO_METHOD_HANDLE)pResult->compileTimeHandle, pResolvedToken); - AppendConditionalImport(pImport); - pIndirection = pImport; - handle = NULL; - } - else - { - CORINFO_METHOD_HANDLE methHnd = (CORINFO_METHOD_HANDLE) pResult->compileTimeHandle; - handle = CORINFO_GENERIC_HANDLE(embedMethodHandle(methHnd, &pIndirection)); - } - break; - - case CORINFO_HANDLETYPE_FIELD: - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_HANDLE, (CORINFO_FIELD_HANDLE)pResult->compileTimeHandle, pResolvedToken); - AppendConditionalImport(pImport); - pIndirection = pImport; - handle = NULL; - } - else - { - CORINFO_FIELD_HANDLE fldHnd = (CORINFO_FIELD_HANDLE) pResult->compileTimeHandle; - handle = CORINFO_GENERIC_HANDLE(embedFieldHandle(fldHnd, &pIndirection)); - } - break; - - default: - ThrowHR(COR_E_BADIMAGEFORMAT, BFA_INVALID_TOKEN_TYPE); - } - - if (handle) - { - pResult->lookup.constLookup.accessType = IAT_VALUE; - pResult->lookup.constLookup.handle = CORINFO_GENERIC_HANDLE(handle); - } - else - { - pResult->lookup.constLookup.accessType = IAT_PVALUE; - pResult->lookup.constLookup.addr = pIndirection; - } - } -} - -void ZapInfo::embedGenericSignature(CORINFO_LOOKUP * pLookup) -{ - _ASSERTE(pLookup->lookupKind.needsRuntimeLookup); - - if (IsReadyToRunCompilation()) - { - UNREACHABLE_MSG("We should never get here for the ReadyToRun compilation."); - ThrowHR(E_NOTIMPL); - } - - if (pLookup->runtimeLookup.signature != NULL) - { - pLookup->runtimeLookup.signature = m_pImage->GetImportTable()->GetGenericSignature( - pLookup->runtimeLookup.signature, pLookup->lookupKind.runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM); - } -} - -bool ZapInfo::getTailCallHelpers( - CORINFO_RESOLVED_TOKEN* callToken, - CORINFO_SIG_INFO* sig, - CORINFO_GET_TAILCALL_HELPERS_FLAGS flags, - CORINFO_TAILCALL_HELPERS* pResult) -{ - ThrowHR(E_NOTIMPL); - return false; -} - -bool ZapInfo::convertPInvokeCalliToCall( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - bool fMustConvert) -{ - return false; -} - -#ifdef FEATURE_READYTORUN_COMPILER -ReadyToRunHelper MapReadyToRunHelper(CorInfoHelpFunc func, bool * pfOptimizeForSize) -{ - switch (func) - { -#define OPTIMIZEFORSIZE *pfOptimizeForSize = true; -#define HELPER(readyToRunHelper, corInfoHelpFunc, flags) \ - case corInfoHelpFunc: flags return readyToRunHelper; -#include "readytorunhelpers.h" - - case CORINFO_HELP_TYPEHANDLE_TO_RUNTIMETYPEHANDLE: - return READYTORUN_HELPER_GetRuntimeTypeHandle; - - case CORINFO_HELP_STRCNS_CURRENT_MODULE: - *pfOptimizeForSize = true; - return READYTORUN_HELPER_GetString; - - default: - return READYTORUN_HELPER_Invalid; - } -} -#endif // FEATURE_READYTORUN_COMPILER - -void * ZapInfo::getHelperFtn (CorInfoHelpFunc ftnNum, void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - *ppIndirection = NULL; - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - bool fOptimizeForSize = false; - ReadyToRunHelper helperNum = MapReadyToRunHelper(ftnNum, &fOptimizeForSize); - - if (helperNum == READYTORUN_HELPER_Invalid) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: JIT helper not supported: %S\n"), m_pEEJitInfo->getHelperName(ftnNum)); - ThrowHR(E_NOTIMPL); - } - - if (fOptimizeForSize) - { - *ppIndirection = NULL; - return m_pImage->GetImportTable()->GetIndirectHelperThunk(helperNum); - } - else - { - *ppIndirection = m_pImage->GetImportTable()->GetHelperImport(helperNum); - return NULL; - } - } -#endif - - DWORD dwHelper = ftnNum; - - switch (ftnNum) - { - case CORINFO_HELP_PROF_FCN_ENTER: - *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexEnterAddr * TARGET_POINTER_SIZE); - return NULL; - case CORINFO_HELP_PROF_FCN_LEAVE: - *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexLeaveAddr * TARGET_POINTER_SIZE); - return NULL; - case CORINFO_HELP_PROF_FCN_TAILCALL: - *ppIndirection = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexTailcallAddr * TARGET_POINTER_SIZE); - return NULL; -#ifdef TARGET_AMD64 - case CORINFO_HELP_STOP_FOR_GC: - // Force all calls in ngen images for this helper to use an indirect call. - // We cannot use a jump stub to reach this helper because - // the RAX register can contain a return value. - dwHelper |= CORCOMPILE_HELPER_PTR; - break; -#endif - default: - break; - } - - if (m_pImage->m_pHelperThunks[ftnNum] == NULL) - { - ZapNode * pHelperThunk; - if (ftnNum == CORINFO_HELP_STRCNS_CURRENT_MODULE) - { - pHelperThunk = new (m_pImage->GetHeap()) ZapLazyHelperThunk(CORINFO_HELP_STRCNS); - } - else - { - pHelperThunk = new (m_pImage->GetHeap()) ZapHelperThunk(dwHelper); - } -#if defined(TARGET_ARM) - if ((dwHelper & CORCOMPILE_HELPER_PTR) == 0) - pHelperThunk = m_pImage->GetInnerPtr(pHelperThunk, THUMB_CODE); -#endif - m_pImage->m_pHelperThunks[ftnNum] = pHelperThunk; - } - - void * ptr = m_pImage->m_pHelperThunks[ftnNum]; - - if (dwHelper & CORCOMPILE_HELPER_PTR) - { - *ppIndirection = ptr; - return NULL; - } - - return ptr; -} - -ULONG ZapInfo::GetNumFixups() -{ - return m_Imports.GetCount(); -} - -void ZapInfo::AppendConditionalImport(ZapImport * pImport) -{ - if (m_ImportSet.LookupPtr(pImport) != NULL) - return; - - ImportEntry entry; - entry.pImport = pImport; - entry.fConditional = true; - m_ImportSet.Add(entry); -} - -void ZapInfo::AppendImport(ZapImport * pImport) -{ - const ImportEntry * pExistingEntry = m_ImportSet.LookupPtr(pImport); - if (pExistingEntry != NULL) - { - if (!pExistingEntry->fConditional) - return; - const_cast(pExistingEntry)->fConditional = false; - } - else - { - ImportEntry entry; - entry.pImport = pImport; - entry.fConditional = false; - m_ImportSet.Add(entry); - } - - m_Imports.Append(pImport); -} - -// -// This function indicates whether a method entry point be directly embedded into -// the code being compiled, or if we can use a (fixable) cross module thunk. -// If we can't use either of these then we return NULL and we will use an -// (fixable) indirection cell to perform the call. -// -PVOID ZapInfo::embedDirectCall(CORINFO_METHOD_HANDLE ftn, - CORINFO_ACCESS_FLAGS accessFlags, - BOOL fAllowThunk) -{ - if (!m_pImage->m_pPreloader->CanEmbedFunctionEntryPoint(ftn, m_currentMethodHandle, accessFlags)) - { - return NULL; - } - - ZapNode * pEntryPointOrThunkToEmbed = NULL; - - // - // If it's in the same module then we can call it directly - // - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(ftn); - if (moduleHandle == m_pImage->m_hModule - && m_pImage->m_pPreloader->CanEmbedMethodHandle(ftn, m_currentMethodHandle)) - { - pEntryPointOrThunkToEmbed = m_pImage->m_pMethodEntryPoints->GetMethodEntryPoint(ftn, accessFlags); - } - else // otherwise we are calling into an external module - { - if (!fAllowThunk) - { - return NULL; - } - - pEntryPointOrThunkToEmbed = m_pImage->GetImportTable()->GetExternalMethodThunk(ftn); - } - -#ifdef TARGET_ARM - pEntryPointOrThunkToEmbed = m_pImage->GetInnerPtr(pEntryPointOrThunkToEmbed, THUMB_CODE); -#endif - - return pEntryPointOrThunkToEmbed; -} - -bool ZapInfo::notifyInstructionSetUsage(CORINFO_InstructionSet instructionSet, bool supportEnabled) -{ - return m_pEEJitInfo->notifyInstructionSetUsage(instructionSet, supportEnabled); -} - -void ZapInfo::getFunctionEntryPoint( - CORINFO_METHOD_HANDLE ftn, /* IN */ - CORINFO_CONST_LOOKUP * pResult, /* OUT */ - CORINFO_ACCESS_FLAGS accessFlags/*=CORINFO_ACCESS_ANY*/) -{ - if (IsReadyToRunCompilation()) - { - // READYTORUN: FUTURE: JIT still calls this for tail. and jmp instructions - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Method entrypoint cannot be encoded\n")); - ThrowHR(E_NOTIMPL); - } - - // Must deal with methods that are methodImpl'd within their own type. - ftn = mapMethodDeclToMethodImpl(ftn); - - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn); - - void * entryPointOrThunkToEmbed = embedDirectCall(ftn, accessFlags, TRUE); - if (entryPointOrThunkToEmbed != NULL) - { - pResult->accessType = IAT_VALUE; - pResult->addr = entryPointOrThunkToEmbed; - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn); - AppendConditionalImport(pImport); - - // Tell the JIT to use an indirections - pResult->accessType = IAT_PVALUE; - pResult->addr = pImport; - } -} - -void ZapInfo::getFunctionFixedEntryPoint(CORINFO_METHOD_HANDLE ftn, - CORINFO_CONST_LOOKUP * pResult) -{ - _ASSERTE(pResult); - - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(ftn); - - // We can only embed entrypoints from the module being NGened since we do not support mapping of external - // import thunks to MethodDesc. It should be ok since the delegate targets are typically from the same module. - void * entryPointToEmbed = embedDirectCall(ftn, CORINFO_ACCESS_ANY, FALSE); - - if (entryPointToEmbed != NULL) - { - pResult->accessType = IAT_VALUE; - pResult->addr = entryPointToEmbed; - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFunctionEntryImport(ftn); - AppendConditionalImport(pImport); - - pResult->accessType = IAT_PVALUE; - pResult->addr = pImport; - } -} - -void * ZapInfo::getMethodSync(CORINFO_METHOD_HANDLE ftn, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - CORINFO_CLASS_HANDLE classHandle = getMethodClass(ftn); - - ZapImport * pImport = m_pImage->GetImportTable()->GetSyncLockImport(classHandle); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -void * ZapInfo::getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method,void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - *ppIndirection = NULL; - - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(method); - - if (!IsReadyToRunCompilation()) - { - CORINFO_MODULE_HANDLE moduleHandle = m_pEECompileInfo->GetLoaderModuleForEmbeddableMethod(method); - if (moduleHandle == m_pImage->m_hModule - && m_pImage->m_pPreloader->CanEmbedMethodHandle(method, m_currentMethodHandle)) - { - return PVOID(m_pImage->GetWrappers()->GetAddrOfPInvokeFixup(method)); - } - } - - // - // The indirect P/Invoke target enables the traditional semantics of - // resolving the P/Invoke target at the callsite. Providing a non-indirect - // fixup indicates the P/Invoke target will be resolved when the enclosing - // function is compiled. This subtle semantic difference is chosen for - // scenarios when resolution of the target must occur under a specific GC mode. - // - - void *fixup = NULL; - ZapImport *pImport = NULL; - if (m_pImage->m_pPreloader->ShouldSuppressGCTransition(method)) - { - pImport = m_pImage->GetImportTable()->GetPInvokeTargetImport(method); - fixup = pImport; - } - else - { - pImport = m_pImage->GetImportTable()->GetIndirectPInvokeTargetImport(method); - *ppIndirection = pImport; - } - - _ASSERTE(pImport != NULL); - AppendConditionalImport(pImport); - - return fixup; -} - -void ZapInfo::getAddressOfPInvokeTarget(CORINFO_METHOD_HANDLE method, CORINFO_CONST_LOOKUP *pLookup) -{ - _ASSERTE(pLookup != NULL); - - void * pIndirection; - void * pResult = getAddressOfPInvokeFixup(method, &pIndirection); - if (pResult != NULL) - { - pLookup->accessType = IAT_PVALUE; - pLookup->addr = pResult; - return; - } - - _ASSERTE(pIndirection != NULL); - pLookup->accessType = IAT_PPVALUE; - pLookup->addr = pIndirection; -} - -CORINFO_JUST_MY_CODE_HANDLE ZapInfo::getJustMyCodeHandle( - CORINFO_METHOD_HANDLE method, - CORINFO_JUST_MY_CODE_HANDLE **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - if (IsReadyToRunCompilation()) - { - *ppIndirection = NULL; - return NULL; - } - - *ppIndirection = (CORINFO_JUST_MY_CODE_HANDLE *)m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, addrOfJMCFlag)); - return NULL; -} - -ZapImport * ZapInfo::GetProfilingHandleImport() -{ - if (m_pProfilingHandle == NULL) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetProfilingHandleImport(m_currentMethodHandle); - AppendImport(pImport); - - m_pProfilingHandle = pImport; - } - - return m_pProfilingHandle; -} - -void ZapInfo::GetProfilingHandle(bool *pbHookFunction, - void **pProfilerHandle, - bool *pbIndirectedHandles) -{ - // - // Return the location within the fixup table - // - // Profiling handle is opaque token. It does not have to be aligned thus we can not store it in the same location as token. - // - *pProfilerHandle = m_pImage->GetInnerPtr(GetProfilingHandleImport(), kZapProfilingHandleImportValueIndexClientData * TARGET_POINTER_SIZE); - - // All functions get hooked in ngen /Profile - *pbHookFunction = TRUE; - - // - // This is the NGEN case, where we always do indirection on the handle so we can fix it up at load time. - // - *pbIndirectedHandles = TRUE; -} - -// -// This strips the CORINFO_FLG_JIT_INTRINSIC flag from some of the named intrinsic methods. -// -DWORD FilterNamedIntrinsicMethodAttribs(ZapInfo* pZapInfo, DWORD attribs, CORINFO_METHOD_HANDLE ftn, ICorDynamicInfo* pJitInfo) -{ - if (attribs & CORINFO_FLG_JIT_INTRINSIC) - { - // Figure out which intrinsic we are dealing with. - const char* namespaceName; - const char* className; - const char* enclosingClassName; - const char* methodName = pJitInfo->getMethodNameFromMetadata(ftn, &className, &namespaceName, &enclosingClassName); - - // Is this the get_IsSupported method that checks whether intrinsic is supported? - bool fIsGetIsSupportedMethod = strcmp(methodName, "get_IsSupported") == 0; - bool fIsPlatformHWIntrinsic = false; - bool fIsHWIntrinsic = false; - bool fTreatAsRegularMethodCall = false; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - fIsPlatformHWIntrinsic = strcmp(namespaceName, "System.Runtime.Intrinsics.X86") == 0; -#elif defined(TARGET_ARM64) - fIsPlatformHWIntrinsic = strcmp(namespaceName, "System.Runtime.Intrinsics.Arm") == 0; -#endif - - fIsHWIntrinsic = fIsPlatformHWIntrinsic || (strcmp(namespaceName, "System.Runtime.Intrinsics") == 0); - - // By default, we want to treat the get_IsSupported method for platform specific HWIntrinsic ISAs as - // method calls. This will be modified as needed below based on what ISAs are considered baseline. - // - // We also want to treat the non-platform specific hardware intrinsics as regular method calls. This - // is because they often change the code they emit based on what ISAs are supported by the compiler, - // but we don't know what the target machine will support. - // - // Additionally, we make sure none of the hardware intrinsic method bodies get pregenerated in crossgen - // (see ZapInfo::CompileMethod) but get JITted instead. The JITted method will have the correct - // answer for the CPU the code is running on. - - fTreatAsRegularMethodCall = fIsGetIsSupportedMethod && fIsPlatformHWIntrinsic; - -#if defined(TARGET_ARM64) - // On Arm64 AdvSimd ISA is required by CoreCLR, so we can expand Vector64 and Vector128 generic methods (e.g. Vector64.get_Zero) - // as well as Vector64 and Vector128 methods (e.g. Vector128.CreateScalarUnsafe). - fTreatAsRegularMethodCall |= !fIsPlatformHWIntrinsic && fIsHWIntrinsic - && (strncmp(className, "Vector64", _countof("Vector64") - 1) != 0) - && (strncmp(className, "Vector128", _countof("Vector128") - 1) != 0); - -#elif defined(TARGET_X86) || defined(TARGET_AMD64) - // The following methods should be safe to expand unconditionally, since JIT either - // 1) does not generate code for them (e.g. for Vector128.AsByte() or get_Count) or - // 2) uses instructions that belong to Sse or Sse2 (these are required baseline ISAs). - static const char* vector128MethodsSafeToExpand[] = { "As", "AsByte", "AsDouble", "AsInt16", "AsInt32", "AsInt64", "AsSByte", - "AsSingle", "AsUInt16", "AsUInt32", "AsUInt64", "Create", "CreateScalarUnsafe", "ToScalar", "get_Count", "get_Zero" }; - - if (!fIsPlatformHWIntrinsic && fIsHWIntrinsic) - { - fTreatAsRegularMethodCall = true; - - if (strncmp(className, "Vector128", _countof("Vector128") - 1) == 0) - { - for (size_t i = 0; i < _countof(vector128MethodsSafeToExpand); i++) - { - if (strcmp(methodName, vector128MethodsSafeToExpand[i]) == 0) - { - fTreatAsRegularMethodCall = false; - break; - } - } - } - } -#else - fTreatAsRegularMethodCall |= !fIsPlatformHWIntrinsic && fIsHWIntrinsic; -#endif - - if (fIsPlatformHWIntrinsic) - { - // Simplify the comparison logic by grabbing the name of the ISA - const char* isaName = (enclosingClassName == nullptr) ? className : enclosingClassName; - - bool fIsPlatformRequiredISA = false; - bool fIsPlatformSubArchitecture = false; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - fIsPlatformRequiredISA = (strcmp(isaName, "X86Base") == 0) || (strcmp(isaName, "Sse") == 0) || (strcmp(isaName, "Sse2") == 0); - fIsPlatformSubArchitecture = strcmp(className, "X64") == 0; -#elif defined(TARGET_ARM64) - fIsPlatformRequiredISA = (strcmp(isaName, "ArmBase") == 0) || (strcmp(isaName, "AdvSimd") == 0); - fIsPlatformSubArchitecture = strcmp(className, "Arm64") == 0; -#endif - - if (fIsPlatformRequiredISA) - { - if ((enclosingClassName == nullptr) || fIsPlatformSubArchitecture) - { - // If the ISA is required by CoreCLR for the platform, we can expand unconditionally - fTreatAsRegularMethodCall = false; - } - } -#if defined(TARGET_X86) || defined(TARGET_AMD64) - else if ((strcmp(isaName, "Avx") == 0) || (strcmp(isaName, "Fma") == 0) || (strcmp(isaName, "Avx2") == 0) - || (strcmp(isaName, "Bmi1") == 0) || (strcmp(isaName, "Bmi2") == 0) || (strcmp(isaName, "Lzcnt") == 0)) - { - if ((enclosingClassName == nullptr) || fIsPlatformSubArchitecture) - { - // If it is the get_IsSupported method for an ISA which is intentionally not enabled - // for crossgen, we want to expand unconditionally. This will force those code - // paths to be treated as dead code and dropped from the compilation. - // See Zapper::InitializeCompilerFlags - // - // For all of the other intrinsics in an ISA which requires the VEX encoding - // we need to treat them as regular method calls. This is done because RyuJIT - // doesn't currently support emitting both VEX and non-VEX encoded instructions - // for a single method. - fTreatAsRegularMethodCall = !fIsGetIsSupportedMethod; - } - } -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) -#ifdef TARGET_X86 - else if (fIsPlatformSubArchitecture) - { - // For ISAs not handled explicitly above, the IsSupported check will always - // be treated as a regular method call. If we are evaulating a method in the X64 - // namespace, we know it will never be supported on x86, so we can allow the code - // to be treated as dead. We treat all non-IsSupported methods as regular method - // calls so they throw PNSE if used withoug the IsSupported check. - fTreatAsRegularMethodCall = !fIsGetIsSupportedMethod; - } -#endif // TARGET_X86 - } -#if defined(TARGET_X86) || defined(TARGET_AMD64) - else if (strcmp(namespaceName, "System") == 0) - { - if (strcmp(className, "Math") == 0 || strcmp(className, "MathF") == 0) - { - // These are normally handled via the SSE4.1 instructions ROUNDSS/ROUNDSD. - // However, we don't know the ISAs the target machine supports so we should - // fallback to the method call implementation instead. - fTreatAsRegularMethodCall = strcmp(methodName, "Round") == 0 || strcmp(methodName, "Ceiling") == 0 || - strcmp(methodName, "Floor") == 0; - } - } - else if (strcmp(namespaceName, "System.Numerics") == 0) - { - if ((strcmp(className, "Vector3") == 0) || (strcmp(className, "Vector4") == 0)) - { - // Vector3 and Vector4 have constructors which take a smaller Vector and create bolt on - // a larger vector. This uses insertps instruction when compiled with SSE4.1 instruction support - // which must not be generated inline in R2R images that actually support an SSE2 only mode. - if (strcmp(methodName, ".ctor") == 0) - { - CORINFO_SIG_INFO sig; - pZapInfo->getMethodSig(ftn, &sig, NULL); - CORINFO_CLASS_HANDLE argClass; - if ((CorInfoType)pZapInfo->getArgType(&sig, sig.args, &argClass) == CORINFO_TYPE_VALUECLASS) - { - fTreatAsRegularMethodCall = TRUE; - } - } - else if (strcmp(methodName, "Dot") == 0) - { - // The dot product operations uses the dpps instruction when compiled with SSE4.1 instruction - // support. This must not be generated inline in R2R images that actually support an SSE2 only mode. - fTreatAsRegularMethodCall = TRUE; - } - } - else if ((strcmp(className, "Vector2") == 0) || (strcmp(className, "Vector") == 0) || (strcmp(className, "Vector`1") == 0)) - { - if (strcmp(methodName, "Dot") == 0) - { - // The dot product operations uses the dpps instruction when compiled with SSE4.1 instruction - // support. This must not be generated inline in R2R images that actually support an SSE2 only mode. - fTreatAsRegularMethodCall = TRUE; - } - } - } -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) - - if (fTreatAsRegularMethodCall) - { - // Treat as a regular method call (into a JITted method). - attribs = (attribs & ~CORINFO_FLG_JIT_INTRINSIC) | CORINFO_FLG_DONT_INLINE; - } - } - - return attribs; -} - -//return a callable stub that will do the virtual or interface call - - -void ZapInfo::getCallInfo(CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_RESOLVED_TOKEN * pConstrainedResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_CALLINFO_FLAGS flags, - CORINFO_CALL_INFO *pResult) -{ - void * pTarget = NULL; - - _ASSERTE(pResult); - - if ((flags & CORINFO_CALLINFO_CALLVIRT) == 0 && pConstrainedResolvedToken != nullptr) - { - // Defer constrained call / ldftn instructions used for static virtual methods - // to runtime resolution. - ThrowHR(E_NOTIMPL); - } - - // Fill in the kind of the virtual call. - // We set kindOnly=true since we don't want the EE to actually give us - // a call stub - instead we want to generate an indirection ourselves. - m_pEEJitInfo->getCallInfo(pResolvedToken, - pConstrainedResolvedToken, - callerHandle, - /* REVISIT_TODO - * Addition of this flag. - */ - (CORINFO_CALLINFO_FLAGS)(flags | CORINFO_CALLINFO_KINDONLY), - pResult); - - pResult->methodFlags = FilterNamedIntrinsicMethodAttribs(this, pResult->methodFlags, pResult->hMethod, m_pEEJitInfo); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - if (pResult->sig.isVarArg()) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: VarArg methods not supported\n")); - ThrowHR(E_NOTIMPL); - } - - if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Runtime method access checks not supported\n")); - ThrowHR(E_NOTIMPL); - } - } -#endif - -#ifdef TARGET_X86 - if (GetCompileInfo()->IsUnmanagedCallersOnlyMethod(pResult->hMethod)) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: References to methods with UnmanagedCallersOnlyAttribute not implemented\n")); - ThrowHR(E_NOTIMPL); - } -#endif // TARGET_X86 - - if (flags & CORINFO_CALLINFO_KINDONLY) - return; - - if (IsReadyToRunCompilation()) - { - if (pResult->thisTransform == CORINFO_BOX_THIS) - { - // READYTORUN: FUTURE: Optionally create boxing stub at runtime - // We couldn't resolve the constrained call into a valuetype instance method and we're asking the JIT - // to box and do a virtual dispatch. If we were to allow the boxing to happen now, it could break future code - // when the user adds a method to the valuetype that makes it possible to avoid boxing (if there is state - // mutation in the method). - - // We allow this at least for primitives and enums because we control them - // and we know there's no state mutation. - CorInfoType constrainedType = getTypeForPrimitiveValueClass(pConstrainedResolvedToken->hClass); - if (constrainedType == CORINFO_TYPE_UNDEF) - ThrowHR(E_NOTIMPL); - } - } - - // OK, if the EE said we're not doing a stub dispatch then just return the kind to - // the caller. No other kinds of virtual calls have extra information attached. - switch (pResult->kind) - { - case CORINFO_VIRTUALCALL_STUB: - { - if (pResult->stubLookup.lookupKind.needsRuntimeLookup) - { - if (!IsReadyToRunCompilation()) - embedGenericSignature(&pResult->stubLookup); - return; - } - - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetStubDispatchCell(pResolvedToken); - - pResult->stubLookup.constLookup.accessType = IAT_PVALUE; - pResult->stubLookup.constLookup.addr = pImport; - } - else - { - - CORINFO_CLASS_HANDLE calleeOwner = pResolvedToken->hClass; - CORINFO_METHOD_HANDLE callee = pResolvedToken->hMethod; - _ASSERTE(callee == pResult->hMethod); - - // - // Create the indirection cell - // - pTarget = m_pImage->GetImportTable()->GetStubDispatchCell(calleeOwner, callee); - - pResult->stubLookup.constLookup.accessType = IAT_PVALUE; - pResult->stubLookup.constLookup.addr = pTarget; - } - } - break; - - - case CORINFO_CALL_CODE_POINTER: - _ASSERTE(pResult->codePointerLookup.lookupKind.needsRuntimeLookup); - if (!IsReadyToRunCompilation()) - embedGenericSignature(&pResult->codePointerLookup); - - // There is no easy way to detect method referenced via generic lookups in generated code. - // Report this method reference unconditionally. - m_pImage->m_pPreloader->MethodReferencedByCompiledCode(pResult->hMethod); - return; - - case CORINFO_CALL: - if (IsReadyToRunCompilation()) - { - // Constrained token is not interesting with this transforms - if (pResult->thisTransform != CORINFO_NO_THIS_TRANSFORM) - pConstrainedResolvedToken = NULL; - - ZapImport * pImport; - - if (flags & CORINFO_CALLINFO_LDFTN) - { - pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_ENTRY, pResult->hMethod, pResolvedToken, pConstrainedResolvedToken); - - AppendConditionalImport(pImport); - } - else - { - if (pResult->methodFlags & CORINFO_FLG_INTRINSIC) - { - bool unused; - CorInfoIntrinsics intrinsic = getIntrinsicID(pResult->hMethod, &unused); - if ((intrinsic == CORINFO_INTRINSIC_StubHelpers_GetStubContext) - || (intrinsic == CORINFO_INTRINSIC_StubHelpers_GetStubContextAddr) - ) - { - // These intrinsics are always expanded directly in the jit and do not correspond to external methods - return; - } - } - pImport = m_pImage->GetImportTable()->GetExternalMethodCell(pResult->hMethod, pResolvedToken, pConstrainedResolvedToken); - } - - // READYTORUN: FUTURE: Direct calls if possible - pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE; - pResult->codePointerLookup.constLookup.addr = pImport; - } - break; - - case CORINFO_VIRTUALCALL_VTABLE: - // Only calls within the CoreLib version bubble support fragile NI codegen with vtable based calls, for better performance (because - // CoreLib and the runtime will always be updated together anyways - this is a special case) - break; - - case CORINFO_VIRTUALCALL_LDVIRTFTN: -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation() && !pResult->exactContextNeedsRuntimeLookup) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_VIRTUAL_ENTRY, pResult->hMethod, pResolvedToken); - - pResult->codePointerLookup.constLookup.accessType = IAT_PVALUE; - pResult->codePointerLookup.constLookup.addr = pImport; - - _ASSERTE(!pResult->sig.hasTypeArg()); - } -#endif - - // Include the declaring instantiation of virtual generic methods in the NGen image. - m_pImage->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(pResult->hMethod); - break; - - default: - _ASSERTE(!"Unknown call type"); - break; - } - - if (IsReadyToRunCompilation() && pResult->sig.hasTypeArg()) - { - if (pResult->exactContextNeedsRuntimeLookup) - { - // Nothing to do... The generic handle lookup gets embedded in to the codegen - // during the jitting of the call. - // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by - // codegen emitted at crossgen time) - } - else - { - ZapImport * pImport; - if (((SIZE_T)pResult->contextHandle & CORINFO_CONTEXTFLAGS_MASK) == CORINFO_CONTEXTFLAGS_METHOD) - { - CORINFO_METHOD_HANDLE exactMethodHandle = (CORINFO_METHOD_HANDLE)((SIZE_T)pResult->contextHandle & ~CORINFO_CONTEXTFLAGS_MASK); - - pImport = m_pImage->GetImportTable()->GetMethodImport(ENCODE_METHOD_DICTIONARY, exactMethodHandle, - pResolvedToken, pConstrainedResolvedToken); - } - else - { - pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_TYPE_DICTIONARY, - (pConstrainedResolvedToken != NULL) ? pConstrainedResolvedToken : pResolvedToken); - } - - pResult->instParamLookup.accessType = IAT_PVALUE; - pResult->instParamLookup.addr = pImport; - - AppendConditionalImport(pImport); - } - } -} - -bool ZapInfo::canAccessFamily(CORINFO_METHOD_HANDLE hCaller, - CORINFO_CLASS_HANDLE hInstanceType) -{ - return m_pEEJitInfo->canAccessFamily(hCaller, hInstanceType); -} - -bool ZapInfo::isRIDClassDomainID (CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isRIDClassDomainID(cls); -} - -unsigned ZapInfo::getClassDomainID (CORINFO_CLASS_HANDLE cls, void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(cls); - - if (!m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE)) - { - if (isRIDClassDomainID(cls)) - { - // Token is invariant to loading order, so we can go ahead and use it - - // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless - // someone else adds some other type of fixup for 'cls'. - m_ClassLoadTable.Load(cls, FALSE); - - return m_pEEJitInfo->getClassDomainID(cls, ppIndirection); - } - - if (m_pImage->m_pPreloader->CanEmbedClassID(cls)) - { - // Ensure that 'cls' gets added to CORCOMPILE_LOAD_TABLE, unless - // someone else adds some other type of fixup for 'cls'. - m_ClassLoadTable.Load(cls, FALSE); - return m_pEEJitInfo->getClassDomainID(cls, ppIndirection); - } - } - - // We will have to insert a fixup - ZapImport * pImport = m_pImage->GetImportTable()->GetClassDomainIdImport(cls); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -void * ZapInfo::getFieldAddress(CORINFO_FIELD_HANDLE field, void **ppIndirection) -{ - if (IsReadyToRunCompilation()) - { - void * pAddress = m_pEEJitInfo->getFieldAddress(field, ppIndirection); - - return m_pImage->m_pILMetaData->GetRVAField(pAddress); - } - - _ASSERTE(ppIndirection != NULL); - - CORINFO_CLASS_HANDLE hClass = m_pEEJitInfo->getFieldClass(field); - - m_pImage->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(hClass); - - ZapImport * pImport = m_pImage->GetImportTable()->GetStaticFieldAddressImport(field); - AppendConditionalImport(pImport); - - // Field address is not aligned thus we can not store it in the same location as token. - *ppIndirection = m_pImage->GetInnerPtr(pImport, TARGET_POINTER_SIZE); - - return NULL; -} - -CORINFO_CLASS_HANDLE ZapInfo::getStaticFieldCurrentClass(CORINFO_FIELD_HANDLE field, bool* pIsSpeculative) -{ - if (pIsSpeculative != NULL) - { - *pIsSpeculative = true; - } - - return NULL; -} - -uint32_t ZapInfo::getFieldThreadLocalStoreID(CORINFO_FIELD_HANDLE field, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - *ppIndirection = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, rvaStaticTlsIndex)); - return NULL; -} - -CORINFO_VARARGS_HANDLE ZapInfo::getVarArgsHandle(CORINFO_SIG_INFO *sig, - void **ppIndirection) -{ - _ASSERTE(ppIndirection != NULL); - - // Zapper does not support embedding these as they are created dynamically - - if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil) - { - _ASSERTE(!"Don't have enough info to be able to create a sig token."); - - *ppIndirection = NULL; - return NULL; - } - - // @perf: If the sig cookie construction code actually will restore the value types in - // the sig, we should call LoadClass on all of those types to avoid redundant - // restore cookies. - - ZapImport * pImport = m_pImage->GetImportTable()->GetVarArgImport(sig->scope, sig->token); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -bool ZapInfo::canGetVarArgsHandle(CORINFO_SIG_INFO *sig) -{ - // Zapper does not support embedding these as they are created dynamically - if (sig->scope != m_pImage->m_hModule || sig->token == mdTokenNil) - { - return false; - } - - return true; -} - -void ZapInfo::setOverride(ICorDynamicInfo *pOverride, CORINFO_METHOD_HANDLE currentMethod) -{ - UNREACHABLE(); -} - -void ZapInfo::addActiveDependency(CORINFO_MODULE_HANDLE moduleFrom, CORINFO_MODULE_HANDLE moduleTo) -{ - if (IsReadyToRunCompilation()) - return; - - _ASSERT(moduleFrom != moduleTo); - - if (m_pImage->m_pPreloader->CanSkipDependencyActivation(m_currentMethodHandle, moduleFrom, moduleTo)) - { - // No need to add dependency fixup since we will have an unconditional dependency - // already - } - else if (!GetCompileInfo()->IsInCurrentVersionBubble(moduleTo)) - { - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetActiveDependencyImport(moduleFrom, moduleTo); - AppendImport(pImport); - - CORINFO_DEPENDENCY dep; - dep.moduleFrom = moduleFrom; - dep.moduleTo = moduleTo; - } -} - - -InfoAccessType - ZapInfo::constructStringLiteral(CORINFO_MODULE_HANDLE tokenScope, - unsigned metaTok, void **ppValue) -{ - if (m_pEECompileInfo->IsEmptyString(metaTok, tokenScope)) - { - return emptyStringLiteral(ppValue); - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(tokenScope, metaTok); - AppendConditionalImport(pImport); - - *ppValue = pImport; - - return IAT_PPVALUE; -} - -InfoAccessType ZapInfo::emptyStringLiteral(void **ppValue) -{ -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetStringHandleImport(m_pImage->m_hModule, mdtString); - *ppValue = pImport; - return IAT_PPVALUE; - } -#endif - - *ppValue = m_pImage->GetInnerPtr(m_pImage->m_pEEInfoTable, - offsetof(CORCOMPILE_EE_INFO_TABLE, emptyString)); - - return IAT_PPVALUE; -} - -void ZapInfo::recordCallSite(uint32_t instrOffset, CORINFO_SIG_INFO *callSig, CORINFO_METHOD_HANDLE methodHandle) -{ - return; -} - -void ZapInfo::recordRelocation(void *location, void *locationRW, void *target, - uint16_t fRelocType, uint16_t slotNum, int32_t addlDelta) -{ - // Factor slotNum into the location address - switch (fRelocType) - { - case IMAGE_REL_BASED_ABSOLUTE: - case IMAGE_REL_BASED_PTR: -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: -#endif // TARGET_X86 || TARGET_AMD64 - location = (PBYTE)location + slotNum; - break; - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - case IMAGE_REL_BASED_THUMB_BRANCH24: - -# ifdef _DEBUG - { - CORJIT_FLAGS jitFlags = m_zapper->m_pOpt->m_compilerFlags; - - if (jitFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS)) - { - _ASSERTE(fRelocType == IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL - || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24); - } - else - { - _ASSERTE(fRelocType == IMAGE_REL_BASED_THUMB_MOV32 - || fRelocType == IMAGE_REL_BASED_THUMB_BRANCH24); - } - } -# endif // _DEBUG - break; -#endif - -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - case IMAGE_REL_ARM64_PAGEBASE_REL21: - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - break; -#endif - - default: - _ASSERTE(!"Unknown reloc type"); - break; - } - - ZapBlobWithRelocs * knownNodes[] = - { - m_pCode, - m_pColdCode, - m_pROData, - m_pProfileData - }; - - // - // The location of the relocation reported by the JIT has to fall into one of the code or data blobs - // - - CodeRelocation r; - - ZapBlobWithRelocs * pSrcNode = NULL; - for (size_t i = 0; i < _countof(knownNodes); i++) - { - ZapBlobWithRelocs * pNode = knownNodes[i]; - if (pNode == NULL) - continue; - - if (pNode->GetData() <= location && location < pNode->GetData() + pNode->GetSize()) - { - pSrcNode = pNode; - break; - } - } - PREFIX_ASSUME(pSrcNode != NULL); - r.m_pNode = pSrcNode; - r.m_offset = (DWORD)((PBYTE)location - (PBYTE)pSrcNode->GetData()); - - // - // The target of the relocation reported by the JIT can be one of: - // - Inner pointer into into one of the code or data blobs. We can detect this case by searching - // through the blobs. - // - Hardbound target. We can detect this case by searching through all hardbound assemblies. - // - Otherwise, it has to be ZapNode *. - // - - ZapNode * pTargetNode = NULL; - INT32 targetOffset = 0; - for (size_t i = 0; i < _countof(knownNodes); i++) - { - ZapBlobWithRelocs * pNode = knownNodes[i]; - if (pNode == NULL) - continue; - - if (pNode->GetData() <= target && target < pNode->GetData() + pNode->GetSize()) - { - pTargetNode = pNode; - targetOffset = (INT32)((PBYTE)target - (PBYTE)pNode->GetData()); - break; - } - } - - if (pTargetNode != NULL) - { - r.m_pTargetNode = pTargetNode; - } - else - { - // Must be ZapNode otherwise - pTargetNode = (ZapNode *)target; - _ASSERTE(pTargetNode->GetType() != ZapNodeType_Unknown); - r.m_pTargetNode = pTargetNode; - } - - r.m_type = (ZapRelocationType)fRelocType; - - switch (fRelocType) - { - case IMAGE_REL_BASED_ABSOLUTE: - *(UNALIGNED DWORD *)location = (DWORD)targetOffset; - break; - - case IMAGE_REL_BASED_PTR: - *(UNALIGNED TARGET_POINTER_TYPE *)location = (TARGET_POINTER_TYPE)targetOffset; - break; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: - *(UNALIGNED INT32 *)location = targetOffset + addlDelta; - break; -#endif // TARGET_X86 || TARGET_AMD64 - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - PutThumb2Mov32((UINT16 *)location, targetOffset); - break; - - case IMAGE_REL_BASED_THUMB_BRANCH24: - if (!FitsInThumb2BlRel24(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutThumb2BlRel24((UINT16 *)location, targetOffset); - break; -#endif - -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - if (!FitsInRel28(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutArm64Rel28((UINT32 *)location, targetOffset); - break; - case IMAGE_REL_ARM64_PAGEBASE_REL21: - if (!FitsInRel21(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutArm64Rel21((UINT32 *)location, targetOffset); - break; - - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - if (!FitsInRel12(targetOffset)) - ThrowHR(COR_E_OVERFLOW); - PutArm64Rel12((UINT32 *)location, targetOffset); - break; -#endif - - default: - _ASSERTE(!"Unknown reloc type"); - break; - } - - if (m_CodeRelocations.IsEmpty()) - { - SIZE_T totalCodeSize = m_pCode->GetSize() + ((m_pColdCode != NULL) ? m_pColdCode->GetSize() : 0); - - // Prealocate relocations (assume that every other pointer may need relocation) - COUNT_T nEstimatedRelocations = (COUNT_T)(totalCodeSize / (2 * TARGET_POINTER_SIZE)); - if (nEstimatedRelocations > 1) - m_CodeRelocations.Preallocate(nEstimatedRelocations); - } - - m_CodeRelocations.Append(r); -} - -WORD ZapInfo::getRelocTypeHint(void * target) -{ -#ifdef TARGET_AMD64 - // There should be no external pointers - return IMAGE_REL_BASED_REL32; -#elif defined(TARGET_ARM) - // Use full 32-bit branch targets when retrying compilation on ARM - if (m_zapper->m_pOpt->m_fNGenLastRetry) - return (WORD)-1; - return IMAGE_REL_BASED_THUMB_BRANCH24; -#elif defined(TARGET_ARM64) - return IMAGE_REL_ARM64_BRANCH26; -#else - // No hints - return (WORD)-1; -#endif -} - -uint32_t ZapInfo::getExpectedTargetArchitecture() -{ - return IMAGE_FILE_MACHINE_NATIVE; -} - -CORINFO_METHOD_HANDLE ZapInfo::GetDelegateCtor(CORINFO_METHOD_HANDLE methHnd, - CORINFO_CLASS_HANDLE clsHnd, - CORINFO_METHOD_HANDLE targetMethodHnd, - DelegateCtorArgs * pCtorData) -{ - // For ReadyToRun, this optimization is done via ZapInfo::getReadyToRunDelegateCtorHelper - if (IsReadyToRunCompilation()) - return methHnd; - - // forward the call to the standard GetDelegateCtor - CORINFO_METHOD_HANDLE delegateCtor = m_pEEJitInfo->GetDelegateCtor(methHnd, clsHnd, targetMethodHnd, pCtorData); - if (delegateCtor != methHnd) - { - if (pCtorData->pArg4) - { - // cannot optimize any wrapper delegate, give up - delegateCtor = methHnd; - } - else if (pCtorData->pArg3) - { - pCtorData->pArg3 = m_pImage->GetWrappers()->GetStub(pCtorData->pArg3); - } - } - return delegateCtor; -} - -void ZapInfo::MethodCompileComplete( - CORINFO_METHOD_HANDLE methHnd) -{ - m_pEEJitInfo->MethodCompileComplete(methHnd); -} - - -// -// ICorStaticInfo -// - -void ZapInfo::getEEInfo(CORINFO_EE_INFO *pEEInfoOut) -{ - m_pEEJitInfo->getEEInfo(pEEInfoOut); -} - -const char16_t * ZapInfo::getJitTimeLogFilename() -{ - return m_pEEJitInfo->getJitTimeLogFilename(); -} - -// -// ICorArgInfo -// - -CORINFO_ARG_LIST_HANDLE ZapInfo::getArgNext(CORINFO_ARG_LIST_HANDLE args) -{ - return m_pEEJitInfo->getArgNext(args); -} - -CorInfoTypeWithMod ZapInfo::getArgType(CORINFO_SIG_INFO* sig, - CORINFO_ARG_LIST_HANDLE args, - CORINFO_CLASS_HANDLE *vcTypeRet) -{ - return m_pEEJitInfo->getArgType(sig, args, vcTypeRet); -} - -CORINFO_CLASS_HANDLE ZapInfo::getArgClass(CORINFO_SIG_INFO* sig, - CORINFO_ARG_LIST_HANDLE args) -{ - return m_pEEJitInfo->getArgClass(sig, args); -} - -CorInfoHFAElemType ZapInfo::getHFAType(CORINFO_CLASS_HANDLE hClass) -{ - return m_pEEJitInfo->getHFAType(hClass); -} - -// -// ICorDebugInfo -// - -void ZapInfo::getBoundaries(CORINFO_METHOD_HANDLE ftn, unsigned int *cILOffsets, - uint32_t **pILOffsets, ICorDebugInfo::BoundaryTypes *implicitBoundaries) -{ - m_pEEJitInfo->getBoundaries(ftn, cILOffsets, pILOffsets, - implicitBoundaries); -} - -void ZapInfo::setBoundaries(CORINFO_METHOD_HANDLE ftn, ULONG32 cMap, - ICorDebugInfo::OffsetMapping *pMap) -{ - _ASSERTE(ftn == m_currentMethodHandle); - - if (cMap == 0) - return; - - m_pOffsetMapping = pMap; - m_iOffsetMapping = cMap; - return; -} - -void ZapInfo::getVars(CORINFO_METHOD_HANDLE ftn, - ULONG32 *cVars, - ICorDebugInfo::ILVarInfo **vars, - bool *extendOthers) -{ - m_pEEJitInfo->getVars(ftn, cVars, vars, extendOthers); -} - -void ZapInfo::setVars(CORINFO_METHOD_HANDLE ftn, - ULONG32 cVars, - ICorDebugInfo::NativeVarInfo * vars) -{ - _ASSERTE(ftn == m_currentMethodHandle); - - if (cVars == 0) - return; - - m_pNativeVarInfo = vars; - m_iNativeVarInfo = cVars; - - return; -} - -void ZapInfo::setPatchpointInfo(PatchpointInfo* patchpointInfo) -{ - // No patchpoint info when prejitting - UNREACHABLE(); -} - -PatchpointInfo* ZapInfo::getOSRInfo(unsigned * ilOffset) -{ - // No patchpoint info when prejitting - UNREACHABLE(); -} - -void * ZapInfo::allocateArray(size_t cBytes) -{ - return new BYTE[cBytes]; -} - -void ZapInfo::freeArray(void *array) -{ - delete [] ((BYTE*) array); -} - -// -// ICorFieldInfo -// - -const char* ZapInfo::getFieldName(CORINFO_FIELD_HANDLE ftn, const char **moduleName) -{ - return m_pEEJitInfo->getFieldName(ftn, moduleName); -} - -CORINFO_CLASS_HANDLE ZapInfo::getFieldClass(CORINFO_FIELD_HANDLE field) -{ - return m_pEEJitInfo->getFieldClass(field); -} - -CorInfoType ZapInfo::getFieldType(CORINFO_FIELD_HANDLE field, - CORINFO_CLASS_HANDLE *structType, - CORINFO_CLASS_HANDLE memberParent) - -{ - return m_pEEJitInfo->getFieldType(field, structType, memberParent); -} - -unsigned ZapInfo::getFieldOffset(CORINFO_FIELD_HANDLE field) -{ - return m_pEEJitInfo->getFieldOffset(field); -} - -void ZapInfo::getFieldInfo (CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_ACCESS_FLAGS flags, - CORINFO_FIELD_INFO *pResult) -{ - m_pEEJitInfo->getFieldInfo(pResolvedToken, callerHandle, flags, pResult); - -#ifdef FEATURE_READYTORUN_COMPILER - CORINFO_EE_INFO eeInfo; - m_pEEJitInfo->getEEInfo(&eeInfo); - - if (IsReadyToRunCompilation()) - { - if (pResult->accessAllowed != CORINFO_ACCESS_ALLOWED) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Runtime field access checks not supported\n")); - ThrowHR(E_NOTIMPL); - } - - switch (pResult->fieldAccessor) - { - case CORINFO_FIELD_INSTANCE: - { - DWORD dwBaseOffset = (DWORD)-1; - CORCOMPILE_FIXUP_BLOB_KIND fixupKind = m_pImage->GetCompileInfo()->GetFieldBaseOffset(pResolvedToken->hClass, &dwBaseOffset); - - switch (fixupKind) - { - case ENCODE_FIELD_OFFSET: - { - ZapImport * pImport = m_pImage->GetImportTable()->GetFieldImport(ENCODE_FIELD_OFFSET, pResolvedToken->hField, pResolvedToken); - - if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Cross-module instance fields with large offsets not supported\n")); - ThrowHR(E_NOTIMPL); - } - pResult->offset = 0; - - pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE; - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - AppendImport(pImport); - } - break; - - case ENCODE_CHECK_FIELD_OFFSET: - { - ZapImport * pImport = m_pImage->GetImportTable()->GetCheckFieldOffsetImport(pResolvedToken->hField, pResolvedToken, pResult->offset); - AppendImport(pImport); - } - break; - - case ENCODE_FIELD_BASE_OFFSET: - { - ZapImport * pImport = m_pImage->GetImportTable()->GetClassImport(ENCODE_FIELD_BASE_OFFSET, pResolvedToken); - - if (pResult->offset > eeInfo.maxUncheckedOffsetForNullObject / 2) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Large objects crossing module boundaries not supported\n")); - ThrowHR(E_NOTIMPL); - } - _ASSERTE(pResult->offset >= dwBaseOffset); - pResult->offset -= dwBaseOffset; - - pResult->fieldAccessor = CORINFO_FIELD_INSTANCE_WITH_BASE; - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - AppendImport(pImport); - } - break; - - case ENCODE_NONE: - break; - - default: - UNREACHABLE_MSG("Unexpected field base fixup"); - } - } - break; - - case CORINFO_FIELD_INSTANCE_HELPER: - case CORINFO_FIELD_INSTANCE_ADDR_HELPER: - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Special instance fields not supported\n")); - ThrowHR(E_NOTIMPL); - break; - - case CORINFO_FIELD_STATIC_SHARED_STATIC_HELPER: - { - if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass))) - { - CORCOMPILE_FIXUP_BLOB_KIND kind; - - switch (pResult->helper) - { - case CORINFO_HELP_GETSHARED_GCSTATIC_BASE: - case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_GCSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_STATIC_BASE_GC_HELPER; - break; - case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE: - case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_NONGCSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_STATIC_BASE_NONGC_HELPER; - break; - case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE: - case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_GCTHREADSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_THREAD_STATIC_BASE_GC_HELPER; - break; - case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE: - case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_NOCTOR: - case CORINFO_HELP_GETSHARED_NONGCTHREADSTATIC_BASE_DYNAMICCLASS: - kind = ENCODE_THREAD_STATIC_BASE_NONGC_HELPER; - break; - default: - UNREACHABLE_MSG("Unexpected static helper"); - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(kind, pResolvedToken->hClass); - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE; - } - else - { - ZapImport * pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_FIELD_ADDRESS, pResolvedToken->hField, pResolvedToken); - - pResult->fieldLookup.accessType = IAT_PVALUE; - pResult->fieldLookup.addr = pImport; - - pResult->helper = CORINFO_HELP_READYTORUN_STATIC_BASE; - - pResult->offset = 0; - pResult->fieldFlags &= ~CORINFO_FLG_FIELD_STATIC_IN_HEAP; // The dynamic helper takes care of the unboxing - } - } - break; - - case CORINFO_FIELD_STATIC_GENERICS_STATIC_HELPER: - { - // Nothing to do... The generic handle lookup gets embedded in to the codegen - // during the jitting of the field lookup. - // (Note: The generic lookup in R2R is performed by a call to a helper at runtime, not by - // codegen emitted at crossgen time) - // TODO: replace the call to the generic lookup helper and the call to the static helper function - // with a single call to a R2R cell that performs: - // 1) Generic handle lookup - // 2) Computes the statics base address - // 3) Generates a stub for subsequent lookups that includes dictionary access - // (For perf reasons) - } - break; - - case CORINFO_FIELD_STATIC_RVA_ADDRESS: // RVA field at given address - if (m_pEEJitInfo->getClassModule(pResolvedToken->hClass) != m_pImage->m_hModule) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Cross-module RVA static fields not supported\n")); - ThrowHR(E_NOTIMPL); - } - break; - - case CORINFO_FIELD_STATIC_ADDRESS: // field at given address - case CORINFO_FIELD_STATIC_ADDR_HELPER: // static field accessed using address-of helper (argument is FieldDesc *) - case CORINFO_FIELD_STATIC_TLS: - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Rare kinds of static fields not supported\n")); - ThrowHR(E_NOTIMPL); - break; - - case CORINFO_FIELD_INTRINSIC_ZERO: - case CORINFO_FIELD_INTRINSIC_EMPTY_STRING: - case CORINFO_FIELD_INTRINSIC_ISLITTLEENDIAN: - break; - - default: - UNREACHABLE_MSG("Unexpected field acccess type"); - } - } -#endif // FEATURE_READYTORUN_COMPILER -} - -bool ZapInfo::isFieldStatic(CORINFO_FIELD_HANDLE fldHnd) -{ - return m_pEEJitInfo->isFieldStatic(fldHnd); -} - -// -// ICorClassInfo -// - -CorInfoType ZapInfo::asCorInfoType(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->asCorInfoType(cls); -} - -const char* ZapInfo::getClassName(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassName(cls); -} - -const char* ZapInfo::getClassNameFromMetadata(CORINFO_CLASS_HANDLE cls, const char** namespaceName) -{ - return m_pEEJitInfo->getClassNameFromMetadata(cls, namespaceName); -} - -CORINFO_CLASS_HANDLE ZapInfo::getTypeInstantiationArgument(CORINFO_CLASS_HANDLE cls, unsigned index) -{ - return m_pEEJitInfo->getTypeInstantiationArgument(cls, index); -} - -const char* ZapInfo::getHelperName(CorInfoHelpFunc func) -{ - return m_pEEJitInfo->getHelperName(func); -} - -int ZapInfo::appendClassName(__deref_inout_ecount(*pnBufLen) char16_t** ppBuf, int* pnBufLen, - CORINFO_CLASS_HANDLE cls, - bool fNamespace, - bool fFullInst, - bool fAssembly) -{ - return m_pEEJitInfo->appendClassName(ppBuf,pnBufLen,cls,fNamespace,fFullInst,fAssembly); -} - -bool ZapInfo::isValueClass(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isValueClass(cls); -} - -CorInfoInlineTypeCheck ZapInfo::canInlineTypeCheck (CORINFO_CLASS_HANDLE cls, CorInfoInlineTypeCheckSource source) -{ - return m_pEEJitInfo->canInlineTypeCheck(cls, source); -} - -uint32_t ZapInfo::getClassAttribs(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassAttribs(cls); -} - -bool ZapInfo::isStructRequiringStackAllocRetBuf(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isStructRequiringStackAllocRetBuf(cls); -} - -CorInfoInitClassResult ZapInfo::initClass( - CORINFO_FIELD_HANDLE field, - CORINFO_METHOD_HANDLE method, - CORINFO_CONTEXT_HANDLE context) -{ - return m_pEEJitInfo->initClass(field, method, context); -} - -void ZapInfo::classMustBeLoadedBeforeCodeIsRun(CORINFO_CLASS_HANDLE cls) -{ - // This adds an entry to the table of fixups. The table gets iterated later - // to add entries to the delayed fixup list for the code being generated. - m_ClassLoadTable.Load(cls, FALSE); -} - -CORINFO_METHOD_HANDLE ZapInfo::mapMethodDeclToMethodImpl(CORINFO_METHOD_HANDLE methHnd) -{ - return (CORINFO_METHOD_HANDLE)m_pEEJitInfo->mapMethodDeclToMethodImpl(methHnd); -} - -void ZapInfo::methodMustBeLoadedBeforeCodeIsRun(CORINFO_METHOD_HANDLE meth) -{ - // This adds an entry to the table of fixups. The table gets iterated later - // to add entries to the delayed fixup list for the code being generated. - m_MethodLoadTable.Load(meth, FALSE); -} - -CORINFO_CLASS_HANDLE ZapInfo::getBuiltinClass(CorInfoClassId classId) -{ - return m_pEEJitInfo->getBuiltinClass(classId); -} - -CorInfoType ZapInfo::getTypeForPrimitiveValueClass(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getTypeForPrimitiveValueClass(cls); -} - -CorInfoType ZapInfo::getTypeForPrimitiveNumericClass(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getTypeForPrimitiveNumericClass(cls); -} - -bool ZapInfo::canCast(CORINFO_CLASS_HANDLE child, - CORINFO_CLASS_HANDLE parent) -{ - return m_pEEJitInfo->canCast(child, parent); -} - -bool ZapInfo::areTypesEquivalent(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->areTypesEquivalent(cls1, cls2); -} - -TypeCompareState ZapInfo::compareTypesForCast(CORINFO_CLASS_HANDLE fromClass, CORINFO_CLASS_HANDLE toClass) -{ - return m_pEEJitInfo->compareTypesForCast(fromClass, toClass); -} - -TypeCompareState ZapInfo::compareTypesForEquality(CORINFO_CLASS_HANDLE cls1, CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->compareTypesForEquality(cls1, cls2); -} - -CORINFO_CLASS_HANDLE ZapInfo::mergeClasses( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->mergeClasses(cls1, cls2); -} - -bool ZapInfo::isMoreSpecificType( - CORINFO_CLASS_HANDLE cls1, - CORINFO_CLASS_HANDLE cls2) -{ - return m_pEEJitInfo->isMoreSpecificType(cls1, cls2); -} - -CORINFO_CLASS_HANDLE ZapInfo::getParentType ( - CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getParentType(cls); -} - -CorInfoType ZapInfo::getChildType ( - CORINFO_CLASS_HANDLE clsHnd, - CORINFO_CLASS_HANDLE *clsRet) -{ - return m_pEEJitInfo->getChildType(clsHnd, clsRet); -} - -bool ZapInfo::satisfiesClassConstraints( - CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->satisfiesClassConstraints(cls); -} - -bool ZapInfo::isSDArray(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->isSDArray(cls); -} - -unsigned ZapInfo::getArrayRank(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getArrayRank(cls); -} - -void * ZapInfo::getArrayInitializationData(CORINFO_FIELD_HANDLE field, uint32_t size) -{ - if (m_pEEJitInfo->getClassModule(m_pEEJitInfo->getFieldClass(field)) != m_pImage->m_hModule) - return NULL; - - void * arrayData = m_pEEJitInfo->getArrayInitializationData(field, size); - if (!arrayData) - return NULL; - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - return m_pImage->m_pILMetaData->GetRVAField(arrayData); -#endif - - return (void *) m_pImage->GetWrappers()->GetGenericHandle(CORINFO_GENERIC_HANDLE(arrayData)); -} - -CorInfoIsAccessAllowedResult ZapInfo::canAccessClass( CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_METHOD_HANDLE callerHandle, - CORINFO_HELPER_DESC *throwHelper) -{ - CorInfoIsAccessAllowedResult ret = m_pEEJitInfo->canAccessClass(pResolvedToken, callerHandle, throwHelper); - -#ifdef FEATURE_READYTORUN_COMPILER - if (ret != CORINFO_ACCESS_ALLOWED) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Runtime access checks not supported\n")); - ThrowHR(E_NOTIMPL); - } -#endif - - return ret; -} - - -CORINFO_MODULE_HANDLE ZapInfo::getClassModule(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassModule(cls); -} - -CORINFO_ASSEMBLY_HANDLE ZapInfo::getModuleAssembly(CORINFO_MODULE_HANDLE mod) -{ - return m_pEEJitInfo->getModuleAssembly(mod); -} - -const char* ZapInfo::getAssemblyName(CORINFO_ASSEMBLY_HANDLE assem) -{ - return m_pEEJitInfo->getAssemblyName(assem); -} - -void* ZapInfo::LongLifetimeMalloc(size_t sz) -{ - return m_pEEJitInfo->LongLifetimeMalloc(sz); -} - -void ZapInfo::LongLifetimeFree(void* obj) -{ - return m_pEEJitInfo->LongLifetimeFree(obj); -} - -size_t ZapInfo::getClassModuleIdForStatics(CORINFO_CLASS_HANDLE cls, CORINFO_MODULE_HANDLE *pModule, void **ppIndirection) -{ - if (IsReadyToRunCompilation()) - { - _ASSERTE(!"getClassModuleIdForStatics"); - ThrowHR(E_NOTIMPL); - } - - _ASSERTE(ppIndirection != NULL); - _ASSERTE(pModule == NULL); - CORINFO_MODULE_HANDLE module; - size_t moduleId = m_pEEJitInfo->getClassModuleIdForStatics(cls, &module, ppIndirection); - CORINFO_MODULE_HANDLE pzmModule = m_pImage->m_pPreloader->GetPreferredZapModuleForClassHandle(cls); - - if (module == pzmModule) - { - // Use the module for the moduleid lookup if we have to do so. This causes us to have fewer fixups than - // if the fixups were exclusively based on the moduleforstatics lookup - cls = NULL; - - - if (module == m_pImage->m_hModule) - { - // If the handle is the module we are currently ngening, we use - // an indirection to the slot where the module pointer gets - // stored when the module gets reloaded. - - *ppIndirection = PVOID(m_pImage->GetWrappers()->GetModuleIDHandle(module)); - return NULL; - } - - // Fall through to regular import - } - else - { - // Use the class for the moduleid lookup. This causes us to generate a fixup for the ModuleForStatics explicitly. - module = NULL; - } - - ZapImport * pImport = m_pImage->GetImportTable()->GetModuleDomainIdImport(module, cls); - AppendConditionalImport(pImport); - - *ppIndirection = pImport; - return NULL; -} - -unsigned ZapInfo::getClassSize(CORINFO_CLASS_HANDLE cls) -{ - DWORD size = m_pEEJitInfo->getClassSize(cls); - -#ifdef FEATURE_READYTORUN_COMPILER - if (IsReadyToRunCompilation()) - { - if (m_pEECompileInfo->NeedsTypeLayoutCheck(cls)) - { - ZapImport * pImport = m_pImage->GetImportTable()->GetCheckTypeLayoutImport(cls); - AppendImport(pImport); - - m_ClassLoadTable.Load(cls, TRUE); - } - } -#endif - - return size; -} - -unsigned ZapInfo::getHeapClassSize(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getHeapClassSize(cls); -} - -bool ZapInfo::canAllocateOnStack(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->canAllocateOnStack(cls); -} - -unsigned ZapInfo::getClassAlignmentRequirement(CORINFO_CLASS_HANDLE cls, bool fDoubleAlignHint) -{ - return m_pEEJitInfo->getClassAlignmentRequirement(cls, fDoubleAlignHint); -} - -CORINFO_FIELD_HANDLE ZapInfo::getFieldInClass(CORINFO_CLASS_HANDLE clsHnd, INT num) -{ - return m_pEEJitInfo->getFieldInClass(clsHnd,num); -} - -mdMethodDef ZapInfo::getMethodDefFromMethod(CORINFO_METHOD_HANDLE hMethod) -{ - return m_pEEJitInfo->getMethodDefFromMethod(hMethod); -} - -bool ZapInfo::checkMethodModifier(CORINFO_METHOD_HANDLE hMethod, LPCSTR modifier, bool fOptional) -{ - return m_pEEJitInfo->checkMethodModifier(hMethod, modifier, fOptional); -} - -unsigned ZapInfo::getClassGClayout(CORINFO_CLASS_HANDLE cls, BYTE *gcPtrs) -{ - return m_pEEJitInfo->getClassGClayout(cls, gcPtrs); -} - -// returns the enregister info for a struct based on type of fields, alignment, etc.. -bool ZapInfo::getSystemVAmd64PassStructInRegisterDescriptor( - /*IN*/ CORINFO_CLASS_HANDLE _structHnd, - /*OUT*/ SYSTEMV_AMD64_CORINFO_STRUCT_REG_PASSING_DESCRIPTOR* structPassInRegDescPtr) -{ - return m_pEEJitInfo->getSystemVAmd64PassStructInRegisterDescriptor(_structHnd, structPassInRegDescPtr); -} - -unsigned ZapInfo::getClassNumInstanceFields(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getClassNumInstanceFields(cls); -} - -CorInfoHelpFunc ZapInfo::getNewHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, CORINFO_METHOD_HANDLE callerHandle, bool * pHasSideEffects) -{ - if (!IsReadyToRunCompilation()) - { - classMustBeLoadedBeforeCodeIsRun(pResolvedToken->hClass); - } - - CorInfoHelpFunc helper = m_pEEJitInfo->getNewHelper(pResolvedToken, callerHandle, pHasSideEffects); - - return IsReadyToRunCompilation() ? CORINFO_HELP_NEWFAST : helper; -} - -CorInfoHelpFunc ZapInfo::getSharedCCtorHelper(CORINFO_CLASS_HANDLE clsHnd) -{ - return m_pEEJitInfo->getSharedCCtorHelper(clsHnd); -} - -CORINFO_CLASS_HANDLE ZapInfo::getTypeForBox(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getTypeForBox(cls); -} - -CorInfoHelpFunc ZapInfo::getBoxHelper(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getBoxHelper(cls); -} - -CorInfoHelpFunc ZapInfo::getUnBoxHelper(CORINFO_CLASS_HANDLE cls) -{ - return m_pEEJitInfo->getUnBoxHelper(cls); -} - -CorInfoHelpFunc ZapInfo::getCastingHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, bool fThrowing) -{ - if (IsReadyToRunCompilation()) - return (fThrowing ? CORINFO_HELP_CHKCASTANY : CORINFO_HELP_ISINSTANCEOFANY); - - return m_pEEJitInfo->getCastingHelper(pResolvedToken, fThrowing); -} - -CorInfoHelpFunc ZapInfo::getNewArrHelper(CORINFO_CLASS_HANDLE arrayCls) -{ - if (IsReadyToRunCompilation()) - return CORINFO_HELP_NEWARR_1_DIRECT; - - return m_pEEJitInfo->getNewArrHelper(arrayCls); -} - -bool ZapInfo::getReadyToRunHelper(CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_LOOKUP_KIND * pGenericLookupKind, - CorInfoHelpFunc id, - CORINFO_CONST_LOOKUP * pLookup) -{ -#ifdef FEATURE_READYTORUN_COMPILER - _ASSERTE(IsReadyToRunCompilation()); - - ZapImport * pImport = NULL; - - bool ignoredSideEffects = false; - switch (id) - { - case CORINFO_HELP_READYTORUN_NEW: - // Call CEEInfo::getNewHelper to validate the request (e.g., check for abstract class). - m_pEEJitInfo->getNewHelper(pResolvedToken, m_currentMethodHandle, &ignoredSideEffects); - - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_NEW_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_NEWARR_1: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_NEW_ARRAY_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_ISINSTANCEOF: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_ISINSTANCEOF_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_CHKCAST: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_CHKCAST_HELPER, pResolvedToken->hClass); - break; - - case CORINFO_HELP_READYTORUN_STATIC_BASE: - if ((getClassAttribs(pResolvedToken->hClass) & CORINFO_FLG_SHAREDINST) != 0) - return false; // Requires runtime lookup. - if (m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getClassModule(pResolvedToken->hClass))) - { - pImport = m_pImage->GetImportTable()->GetDynamicHelperCell(ENCODE_CCTOR_TRIGGER, pResolvedToken->hClass); - } - else - { - // READYTORUN: FUTURE: Cross-module static cctor triggers - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Cross-module static cctor triggers not supported\n")); - ThrowHR(E_NOTIMPL); - } - break; - - case CORINFO_HELP_READYTORUN_GENERIC_HANDLE: - _ASSERTE(pGenericLookupKind != NULL && pGenericLookupKind->needsRuntimeLookup); - if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_METHODPARAM) - { - pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell( - ENCODE_DICTIONARY_LOOKUP_METHOD, m_currentMethodHandle, pResolvedToken, pGenericLookupKind); - } - else if (pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_THISOBJ) - { - pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell( - ENCODE_DICTIONARY_LOOKUP_THISOBJ, m_currentMethodHandle, pResolvedToken, pGenericLookupKind); - } - else - { - _ASSERTE(pGenericLookupKind->runtimeLookupKind == CORINFO_LOOKUP_CLASSPARAM); - pImport = m_pImage->GetImportTable()->GetDictionaryLookupCell( - ENCODE_DICTIONARY_LOOKUP_TYPE, m_currentMethodHandle, pResolvedToken, pGenericLookupKind); - } - break; - - default: - _ASSERTE(false); - ThrowHR(E_NOTIMPL); - } - - pLookup->accessType = IAT_PVALUE; - pLookup->addr = pImport; - return true; -#else - return false; -#endif -} - -void ZapInfo::getReadyToRunDelegateCtorHelper( - CORINFO_RESOLVED_TOKEN * pTargetMethod, - CORINFO_CLASS_HANDLE delegateType, - CORINFO_LOOKUP * pLookup - ) -{ -#ifdef FEATURE_READYTORUN_COMPILER - _ASSERTE(IsReadyToRunCompilation()); - pLookup->lookupKind.needsRuntimeLookup = false; - pLookup->constLookup.accessType = IAT_PVALUE; - pLookup->constLookup.addr = m_pImage->GetImportTable()->GetDynamicHelperCell( - (CORCOMPILE_FIXUP_BLOB_KIND)(ENCODE_DELEGATE_CTOR), pTargetMethod->hMethod, pTargetMethod, delegateType); -#endif -} - - -// -// ICorModuleInfo -// - -//----------------------------------------------------------------------------- -void ZapInfo::resolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - m_pEEJitInfo->resolveToken(pResolvedToken); -} - -//----------------------------------------------------------------------------- -bool ZapInfo::tryResolveToken(CORINFO_RESOLVED_TOKEN * pResolvedToken) -{ - return m_pEEJitInfo->tryResolveToken(pResolvedToken); -} - -//----------------------------------------------------------------------------- -void ZapInfo::findSig(CORINFO_MODULE_HANDLE tokenScope, - unsigned sigTOK, - CORINFO_CONTEXT_HANDLE tokenContext, - CORINFO_SIG_INFO *sig) -{ - m_pEEJitInfo->findSig(tokenScope, sigTOK, tokenContext, sig); -} - -void ZapInfo::findCallSiteSig(CORINFO_MODULE_HANDLE tokenScope, - unsigned methTOK, - CORINFO_CONTEXT_HANDLE tokenContext, CORINFO_SIG_INFO *sig) -{ - m_pEEJitInfo->findCallSiteSig(tokenScope, methTOK, tokenContext, sig); -} - -size_t ZapInfo::findNameOfToken(CORINFO_MODULE_HANDLE tokenScope, - unsigned token, - __out_ecount (FQNameCapacity) char * szFQName, - size_t FQNameCapacity) -{ - return m_pEEJitInfo->findNameOfToken(tokenScope, token, szFQName, FQNameCapacity); -} - -bool ZapInfo::isValidToken ( - CORINFO_MODULE_HANDLE tokenScope, - unsigned token) -{ - return m_pEEJitInfo->isValidToken(tokenScope, token); -} - -bool ZapInfo::isValidStringRef ( - CORINFO_MODULE_HANDLE tokenScope, - unsigned token) -{ - return m_pEEJitInfo->isValidStringRef(tokenScope, token); -} - -const char16_t* ZapInfo::getStringLiteral ( - CORINFO_MODULE_HANDLE tokenScope, - unsigned token, - int* length) -{ - return m_pEEJitInfo->getStringLiteral(tokenScope, token, length); -} - -// -// ICorMethodInfo -// - -const char* ZapInfo::getMethodName(CORINFO_METHOD_HANDLE ftn, const char **moduleName) -{ - return m_pEEJitInfo->getMethodName(ftn, moduleName); -} - -const char* ZapInfo::getMethodNameFromMetadata(CORINFO_METHOD_HANDLE ftn, const char **className, const char** namespaceName, const char **enclosingClassName) -{ - return m_pEEJitInfo->getMethodNameFromMetadata(ftn, className, namespaceName, enclosingClassName); -} - -unsigned ZapInfo::getMethodHash(CORINFO_METHOD_HANDLE ftn) -{ - return m_pEEJitInfo->getMethodHash(ftn); -} - -bool ZapInfo::isJitIntrinsic(CORINFO_METHOD_HANDLE ftn) -{ - return m_pEEJitInfo->isJitIntrinsic(ftn); -} - -uint32_t ZapInfo::getMethodAttribs(CORINFO_METHOD_HANDLE ftn) -{ - DWORD result = m_pEEJitInfo->getMethodAttribs(ftn); - return FilterNamedIntrinsicMethodAttribs(this, result, ftn, m_pEEJitInfo); -} - -void ZapInfo::setMethodAttribs(CORINFO_METHOD_HANDLE ftn, CorInfoMethodRuntimeFlags attribs) -{ - m_pEEJitInfo->setMethodAttribs(ftn, attribs); -} - -void ZapInfo::getMethodSig(CORINFO_METHOD_HANDLE ftn, CORINFO_SIG_INFO *sig,CORINFO_CLASS_HANDLE memberParent) -{ - m_pEEJitInfo->getMethodSig(ftn, sig, memberParent); -} - -bool ZapInfo::getMethodInfo(CORINFO_METHOD_HANDLE ftn,CORINFO_METHOD_INFO* info) -{ - bool result = m_pImage->m_pPreloader->GetMethodInfo(m_currentMethodToken, ftn, info); - info->regionKind = m_pImage->GetCurrentRegionKind(); - return result; -} - -CorInfoInline ZapInfo::canInline(CORINFO_METHOD_HANDLE caller, - CORINFO_METHOD_HANDLE callee, - uint32_t* pRestrictions) -{ - return m_pEEJitInfo->canInline(caller, callee, pRestrictions); - -} - -void ZapInfo::reportInliningDecision (CORINFO_METHOD_HANDLE inlinerHnd, - CORINFO_METHOD_HANDLE inlineeHnd, - CorInfoInline inlineResult, - const char * reason) -{ - if (!dontInline(inlineResult) && inlineeHnd != NULL) - { - // We deliberately report m_currentMethodHandle (not inlinerHnd) as inliner, because - // if m_currentMethodHandle != inlinerHnd, it simply means that inlinerHnd is intermediate link - // in inlining into m_currentMethodHandle, and we have no interest to track those intermediate links now. - m_pImage->m_pPreloader->ReportInlining(m_currentMethodHandle, inlineeHnd); - } - return m_pEEJitInfo->reportInliningDecision(inlinerHnd, inlineeHnd, inlineResult, reason); -} - -bool ZapInfo::canTailCall(CORINFO_METHOD_HANDLE caller, - CORINFO_METHOD_HANDLE declaredCallee, - CORINFO_METHOD_HANDLE exactCallee, - bool fIsTailPrefix) -{ -#ifdef FEATURE_READYTORUN_COMPILER - // READYTORUN: FUTURE: Delay load fixups for tailcalls - if (IsReadyToRunCompilation()) - { - if (fIsTailPrefix) - { - if (m_zapper->m_pOpt->m_verbose) - m_zapper->Warning(W("ReadyToRun: Explicit tailcalls not supported\n")); - ThrowHR(E_NOTIMPL); - } - - return false; - } -#endif - - return m_pEEJitInfo->canTailCall(caller, declaredCallee, exactCallee, fIsTailPrefix); -} - -void ZapInfo::reportTailCallDecision(CORINFO_METHOD_HANDLE callerHnd, - CORINFO_METHOD_HANDLE calleeHnd, - bool fIsTailPrefix, - CorInfoTailCall tailCallResult, - const char * reason) -{ - return m_pEEJitInfo->reportTailCallDecision(callerHnd, calleeHnd, fIsTailPrefix, tailCallResult, reason); -} - -void ZapInfo::getEHinfo(CORINFO_METHOD_HANDLE ftn, - unsigned EHnumber, CORINFO_EH_CLAUSE* clause) -{ - m_pEEJitInfo->getEHinfo(ftn, EHnumber, clause); -} - -CORINFO_CLASS_HANDLE ZapInfo::getMethodClass(CORINFO_METHOD_HANDLE method) -{ - return m_pEEJitInfo->getMethodClass(method); -} - -CORINFO_MODULE_HANDLE ZapInfo::getMethodModule(CORINFO_METHOD_HANDLE method) -{ - return m_pEEJitInfo->getMethodModule(method); -} - -void ZapInfo::getMethodVTableOffset(CORINFO_METHOD_HANDLE method, - unsigned * pOffsetOfIndirection, - unsigned * pOffsetAfterIndirection, - bool * isRelative) -{ - m_pEEJitInfo->getMethodVTableOffset(method, pOffsetOfIndirection, pOffsetAfterIndirection, isRelative); -} - -bool ZapInfo::resolveVirtualMethod(CORINFO_DEVIRTUALIZATION_INFO * info) -{ - bool result = m_pEEJitInfo->resolveVirtualMethod(info); - if (result) - { - // First, cons up a suitable resolved token. - CORINFO_RESOLVED_TOKEN derivedResolvedToken = {}; - info->resolvedTokenDevirtualizedMethod = derivedResolvedToken; - - info->resolvedTokenDevirtualizedMethod.tokenScope = getMethodModule(info->devirtualizedMethod); - info->resolvedTokenDevirtualizedMethod.tokenContext = MAKE_METHODCONTEXT(info->devirtualizedMethod); - info->resolvedTokenDevirtualizedMethod.token = getMethodDefFromMethod(info->devirtualizedMethod); - info->resolvedTokenDevirtualizedMethod.tokenType = CORINFO_TOKENKIND_DevirtualizedMethod; - info->resolvedTokenDevirtualizedMethod.hClass = (CORINFO_CLASS_HANDLE)((size_t)info->exactContext & ~CORINFO_CONTEXTFLAGS_MASK);; - info->resolvedTokenDevirtualizedMethod.hMethod = info->devirtualizedMethod; - - // Then, if the method is on a valuetype, cons up a unboxed method resolution stub - info->resolvedTokenDevirtualizedUnboxedMethod = derivedResolvedToken; - bool unused; - CORINFO_METHOD_HANDLE unboxedMethod = getUnboxedEntry(info->devirtualizedMethod, &unused); - if (unboxedMethod != NULL) - { - info->resolvedTokenDevirtualizedUnboxedMethod.tokenScope = getMethodModule(unboxedMethod); - info->resolvedTokenDevirtualizedUnboxedMethod.tokenContext = MAKE_METHODCONTEXT(unboxedMethod); - info->resolvedTokenDevirtualizedUnboxedMethod.token = getMethodDefFromMethod(unboxedMethod); - info->resolvedTokenDevirtualizedUnboxedMethod.tokenType = CORINFO_TOKENKIND_DevirtualizedMethod; - info->resolvedTokenDevirtualizedUnboxedMethod.hClass = (CORINFO_CLASS_HANDLE)((size_t)info->exactContext & ~CORINFO_CONTEXTFLAGS_MASK);; - info->resolvedTokenDevirtualizedUnboxedMethod.hMethod = unboxedMethod; - } - } - - return result; -} - -CORINFO_METHOD_HANDLE ZapInfo::getUnboxedEntry( - CORINFO_METHOD_HANDLE ftn, - bool* requiresInstMethodTableArg) -{ - return m_pEEJitInfo->getUnboxedEntry(ftn, requiresInstMethodTableArg); -} - -CORINFO_CLASS_HANDLE ZapInfo::getDefaultComparerClass( - CORINFO_CLASS_HANDLE elemType) -{ - return m_pEEJitInfo->getDefaultComparerClass(elemType); -} - -CORINFO_CLASS_HANDLE ZapInfo::getDefaultEqualityComparerClass( - CORINFO_CLASS_HANDLE elemType) -{ - return m_pEEJitInfo->getDefaultEqualityComparerClass(elemType); -} - -void ZapInfo::expandRawHandleIntrinsic( - CORINFO_RESOLVED_TOKEN * pResolvedToken, - CORINFO_GENERICHANDLE_RESULT * pResult) -{ - m_pEEJitInfo->expandRawHandleIntrinsic(pResolvedToken, pResult); -} - -CorInfoIntrinsics ZapInfo::getIntrinsicID(CORINFO_METHOD_HANDLE method, - bool * pMustExpand) -{ - return m_pEEJitInfo->getIntrinsicID(method, pMustExpand); -} - -bool ZapInfo::isIntrinsicType(CORINFO_CLASS_HANDLE classHnd) -{ - return m_pEEJitInfo->isIntrinsicType(classHnd); -} - -CorInfoCallConvExtension ZapInfo::getUnmanagedCallConv(CORINFO_METHOD_HANDLE method, CORINFO_SIG_INFO* sig, bool* pSuppressGCTransition) -{ - return m_pEEJitInfo->getUnmanagedCallConv(method, sig, pSuppressGCTransition); -} - -bool ZapInfo::pInvokeMarshalingRequired(CORINFO_METHOD_HANDLE method, - CORINFO_SIG_INFO* sig) -{ -#if defined(TARGET_X86) && defined(TARGET_UNIX) - // FUTURE ReadyToRun: x86 pinvoke stubs on Unix platforms - if (IsReadyToRunCompilation()) - return TRUE; -#endif - - if (IsReadyToRunCompilation() && method != NULL && !m_pImage->GetCompileInfo()->IsInCurrentVersionBubble(m_pEEJitInfo->getMethodModule(method))) - { - // FUTURE: ZapSig::EncodeMethod does not yet handle cross module references for ReadyToRun - // See zapsig.cpp around line 1217. - // Once this is implemented, we'll be able to inline pinvokes of extern methods declared in other modules (Ex: PresentationCore.dll) - return TRUE; - } - - return m_pEEJitInfo->pInvokeMarshalingRequired(method, sig); -} - -LPVOID ZapInfo::GetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig, - void ** ppIndirection) -{ - return getVarArgsHandle(szMetaSig, ppIndirection); -} - -bool ZapInfo::canGetCookieForPInvokeCalliSig(CORINFO_SIG_INFO* szMetaSig) -{ - return canGetVarArgsHandle(szMetaSig); -} - -bool ZapInfo::satisfiesMethodConstraints( - CORINFO_CLASS_HANDLE parent, - CORINFO_METHOD_HANDLE method) -{ - return m_pEEJitInfo->satisfiesMethodConstraints(parent, method); -} - - -bool ZapInfo::isCompatibleDelegate( - CORINFO_CLASS_HANDLE objCls, - CORINFO_CLASS_HANDLE methodParentCls, - CORINFO_METHOD_HANDLE method, - CORINFO_CLASS_HANDLE delegateCls, - bool* pfIsOpenDelegate) -{ - return m_pEEJitInfo->isCompatibleDelegate(objCls, methodParentCls, method, delegateCls, pfIsOpenDelegate); -} - -// -// ICorErrorInfo -// - -HRESULT ZapInfo::GetErrorHRESULT(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - return m_pEEJitInfo->GetErrorHRESULT(pExceptionPointers); -} - -uint32_t ZapInfo::GetErrorMessage(__in_ecount(bufferLength) char16_t* buffer, uint32_t bufferLength) -{ - return m_pEEJitInfo->GetErrorMessage(buffer, bufferLength); -} - -int ZapInfo::FilterException(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - // Continue unwinding if fatal error was hit. - if (FAILED(g_hrFatalError)) - return EXCEPTION_CONTINUE_SEARCH; - - return m_pEEJitInfo->FilterException(pExceptionPointers); -} - -void ZapInfo::HandleException(struct _EXCEPTION_POINTERS *pExceptionPointers) -{ - m_pEEJitInfo->HandleException(pExceptionPointers); -} - -void ZapInfo::ThrowExceptionForJitResult(HRESULT result) -{ - m_pEEJitInfo->ThrowExceptionForJitResult(result); -} -void ZapInfo::ThrowExceptionForHelper(const CORINFO_HELPER_DESC * throwHelper) -{ - m_pEEJitInfo->ThrowExceptionForHelper(throwHelper); -} - -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo) -{ - // - // Find all of our un-fixed entries, and emit a restore fixup for each of them. - // Note that we don't need a restore fixups for prerestored classes. - // - - InlineSArray unfixed; - - for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - if (i->order == -1 - || m_pModule->m_pPreloader->CanPrerestoreEmbedClassHandle(i->handle) - // @TODO: Skip transitive closure of currentMethodHandle (parents, instantiations, etc.) - || m_pModule->GetJitInfo()->getMethodClass(currentMethodHandle) == i->handle) - continue; - - unfixed.Append(*i); - } - - // - // Now clear the table. - // - - m_entries.RemoveAll(); - - if (unfixed.IsEmpty()) - return; - - // Save the fixups in the order they got emited for determinism - qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp); - - for(COUNT_T j = 0; j < unfixed.GetCount(); j++) - { - CORINFO_CLASS_HANDLE handle = unfixed[j].handle; - m_pModule->m_pPreloader->AddTypeToTransitiveClosureOfInstantiations(handle); - ZapImport * pImport = m_pModule->GetImportTable()->GetClassHandleImport(handle); - pZapInfo->AppendImport(pImport); - } -} - - -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo) -{ - // - // Find all of our un-fixed entries, and emit a restore fixup for each of them. - // Note that we don't need a restore fixups for prerestored methods. - // - - InlineSArray unfixed; - - for (LoadEntryHashTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - if (i->order == -1 - || m_pModule->m_pPreloader->CanPrerestoreEmbedMethodHandle(i->handle) - || currentMethodHandle == i->handle) - continue; - - unfixed.Append(*i); - } - - // - // Now clear the table. - // - - m_entries.RemoveAll(); - - if (unfixed.IsEmpty()) - return; - - // Save the fixups in the order they got emited for determinism - qsort(&unfixed[0], unfixed.GetCount(), sizeof(LoadEntry), LoadEntryCmp); - - for(COUNT_T j = 0; j < unfixed.GetCount(); j++) - { - CORINFO_METHOD_HANDLE handle = unfixed[j].handle; - m_pModule->m_pPreloader->AddMethodToTransitiveClosureOfInstantiations(handle); - ZapImport * pImport = m_pModule->GetImportTable()->GetMethodHandleImport(handle); - pZapInfo->AppendImport(pImport); - } -} - -BOOL ZapInfo::CurrentMethodHasProfileData() -{ - WRAPPER_NO_CONTRACT; - UINT32 size; - ICorJitInfo::PgoInstrumentationSchema * pSchema; - BYTE* pData; - ICorJitInfo::PgoSource pgoSource; - return SUCCEEDED(getPgoInstrumentationResults(m_currentMethodHandle, &pSchema, &size, &pData, &pgoSource)); -} - diff --git a/src/coreclr/zap/zapinfo.h b/src/coreclr/zap/zapinfo.h deleted file mode 100644 index 2731bdc8954d10..00000000000000 --- a/src/coreclr/zap/zapinfo.h +++ /dev/null @@ -1,288 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInfo.h -// - -// -// JIT-EE interface for zapping -// -// ====================================================================================== - -#ifndef __ZAPINFO_H__ -#define __ZAPINFO_H__ - -#include "zapcode.h" - -class ZapInfo; -struct InlineContext; - -// The compiled code often implicitly needs fixups for various subtle reasons. -// We only emit explict fixups while compiling the method, while collecting -// implicit fixups in the LoadTable. At the end of compiling, we expect -// many of the LoadTable entries to be subsumed by the explicit entries -// and will not need to be emitted. -// This is also used to detect duplicate explicit fixups for the same type. - -template -class LoadTable -{ -private: - ZapImage *m_pModule; - - struct LoadEntry - { - HandleType handle; - int order; // -1 = fixed - }; - - static int __cdecl LoadEntryCmp(const void* a_, const void* b_) - { - return ((LoadEntry*)a_)->order - ((LoadEntry*)b_)->order; - } - - class LoadEntryTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef typename NoRemoveSHashTraits >::count_t count_t; - typedef typename NoRemoveSHashTraits >::element_t element_t; - typedef HandleType key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.handle; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static const element_t Null() { LIMITED_METHOD_CONTRACT; LoadEntry e; e.handle = NULL; e.order = 0; return e; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return (e.handle == NULL); } - }; - - typedef SHash LoadEntryHashTable; - - LoadEntryHashTable m_entries; - -public: - LoadTable(ZapImage *pModule) - : m_pModule(pModule) - { - } - - // fixed=TRUE if the caller can guarantee that type will be fixed up because - // of some implicit fixup. In this case, we track 'handle' only to avoid - // duplicates and will not actually emit an explicit fixup for 'handle' - // - // fixed=FALSE if the caller needs an explicit fixup. We will emit an - // explicit fixup for 'handle' if there are no other implicit fixups. - - void Load(HandleType handle, BOOL fixed) - { - CONTRACTL - { - THROWS; - GC_NOTRIGGER; - } - CONTRACTL_END; - - const LoadEntry *result = m_entries.LookupPtr(handle); - - if (result != NULL) - { - if (fixed) - ((LoadEntry*)result)->order = -1; - return; - } - - LoadEntry newEntry; - - newEntry.handle = handle; - newEntry.order = fixed ? -1 : m_entries.GetCount(); - - m_entries.Add(newEntry); - } - - void EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo); -}; - -// Declare some specializations of EmitLoadFixups(). -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo); -template<> void LoadTable::EmitLoadFixups(CORINFO_METHOD_HANDLE currentMethodHandle, ZapInfo * pZapInfo); - - -class ZapInfo - : public ICorJitInfo -{ - friend class ZapImage; - - // Owning ZapImage - ZapImage * m_pImage; - - Zapper * m_zapper; - ICorDynamicInfo * m_pEEJitInfo; - ICorCompileInfo * m_pEECompileInfo; - - // Current method being compiled; it is non-nil only for - // method defs whose IL is in this module and (for generic code) - // have instantiation. It is also nil for IL_STUBs. - mdMethodDef m_currentMethodToken; - CORINFO_METHOD_HANDLE m_currentMethodHandle; - CORINFO_METHOD_INFO m_currentMethodInfo; - - // m_currentMethodModule==m_hModule except for generic types/methods - // defined in another assembly but instantiated in the current assembly. - CORINFO_MODULE_HANDLE m_currentMethodModule; - - unsigned m_currentMethodProfilingDataFlags; - - // Debug information reported by the JIT compiler for the current method - ICorDebugInfo::NativeVarInfo *m_pNativeVarInfo; - ULONG32 m_iNativeVarInfo; - ICorDebugInfo::OffsetMapping *m_pOffsetMapping; - ULONG32 m_iOffsetMapping; - - BYTE * m_pGCInfo; - SIZE_T m_cbGCInfo; - - - ZapBlobWithRelocs * m_pCode; - ZapBlobWithRelocs * m_pColdCode; - ZapBlobWithRelocs * m_pROData; - -#ifdef FEATURE_EH_FUNCLETS - // Unwind info of the main method body. It will get merged with GC info. - BYTE * m_pMainUnwindInfo; - ULONG m_cbMainUnwindInfo; - - ZapUnwindInfo * m_pUnwindInfo; - ZapUnwindInfo * m_pUnwindInfoFragments; -#if defined(TARGET_AMD64) - ZapUnwindInfo * m_pChainedColdUnwindInfo; -#endif -#endif // FEATURE_EH_FUNCLETS - - ZapExceptionInfo * m_pExceptionInfo; - - ZapBlobWithRelocs * m_pProfileData; - - ZapImport * m_pProfilingHandle; - - struct CodeRelocation : ZapReloc - { - ZapBlobWithRelocs * m_pNode; - }; - - SArray m_CodeRelocations; - - static int __cdecl CompareCodeRelocation(const void * a, const void * b); - - struct ImportEntry - { - ZapImport * pImport; - bool fConditional; // Conditional imports are emitted only if they are actually referenced by the code. - }; - - class ImportTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef ZapImport * key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.pImport; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static const element_t Null() { LIMITED_METHOD_CONTRACT; ImportEntry e; e.pImport = NULL; return e; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.pImport == NULL; } - }; - - SHash m_ImportSet; - SArray m_Imports; - - InlineSString<128> m_currentMethodName; - - // Cache to reduce the number of entries in CORCOMPILE_LOAD_TABLE if it - // is implied by some other fixup type - LoadTable m_ClassLoadTable; - LoadTable m_MethodLoadTable; - - CORJIT_FLAGS m_jitFlags; - - void InitMethodName(); - - CORJIT_FLAGS ComputeJitFlags(CORINFO_METHOD_HANDLE handle); - - ZapDebugInfo * EmitDebugInfo(); - ZapGCInfo * EmitGCInfo(); - ZapImport ** EmitFixupList(); - - void PublishCompiledMethod(); - - void EmitCodeRelocations(); - - void ProcessReferences(); - - BOOL CurrentMethodHasProfileData(); - - void embedGenericSignature(CORINFO_LOOKUP * pLookup); - - PVOID embedDirectCall(CORINFO_METHOD_HANDLE ftn, - CORINFO_ACCESS_FLAGS accessFlags, - BOOL fAllowThunk); - - struct ProfileDataResults - { - ProfileDataResults(CORINFO_METHOD_HANDLE ftn) : m_ftn(ftn) {} - ProfileDataResults* m_next = nullptr; - CORINFO_METHOD_HANDLE m_ftn; - SArray m_schema; - BYTE *pInstrumentationData = nullptr; - HRESULT m_hr = E_FAIL; - }; - ProfileDataResults *m_pgoResults = nullptr; - -public: - ZapInfo(ZapImage * pImage, mdMethodDef md, CORINFO_METHOD_HANDLE handle, CORINFO_MODULE_HANDLE module, unsigned methodProfilingDataFlags); - ~ZapInfo(); - -#ifdef ALLOW_SXS_JIT_NGEN - void ResetForJitRetry(); -#endif // ALLOW_SXS_JIT_NGEN - - void CompileMethod(); - - void AppendImport(ZapImport * pImport); - void AppendConditionalImport(ZapImport * pImport); - - ULONG GetNumFixups(); - - // ICorJitInfo -#include "icorjitinfoimpl_generated.h" - - int canHandleException(struct _EXCEPTION_POINTERS *pExceptionPointers); - void * getAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE method, - void **ppIndirection); - ZapImport * GetProfilingHandleImport(); -}; - -#endif // __ZAPINFO_H__ diff --git a/src/coreclr/zap/zapinnerptr.cpp b/src/coreclr/zap/zapinnerptr.cpp deleted file mode 100644 index ec8baec4fa8852..00000000000000 --- a/src/coreclr/zap/zapinnerptr.cpp +++ /dev/null @@ -1,66 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInnerPtr.h -// - -// -// ZapNode that points into middle of other ZapNode -// -// ====================================================================================== - -#include "common.h" - -#include "zapinnerptr.h" - -ZapNode * ZapInnerPtrTable::Get(ZapNode * pBase, SSIZE_T offset) -{ - // Nothing to do if the offset is zero - if (offset == 0) - return pBase; - - // Flatten the hiearchy of inner ptrs. Inner ptrs pointing to other inner ptrs - // would not work well during the Resolve phase - while (pBase->GetType() == ZapNodeType_InnerPtr) - { - ZapInnerPtr * pWrapper = (ZapInnerPtr *)pBase; - - offset += pWrapper->GetOffset(); - pBase = pWrapper->GetBase(); - } - - ZapInnerPtr * pInnerPtr = m_entries.Lookup(InnerPtrKey(pBase, offset)); - - if (pInnerPtr != NULL) - return pInnerPtr; - - switch (offset) - { - case 1: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<1>(pBase); - break; - case 2: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<2>(pBase); - break; - case 4: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<4>(pBase); - break; - case 8: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrConst<8>(pBase); - break; - default: - pInnerPtr = new (m_pWriter->GetHeap()) InnerPtrVar(pBase, offset); - break; - } - - m_entries.Add(pInnerPtr); - return pInnerPtr; -} - -void ZapInnerPtrTable::Resolve() -{ - for (InnerPtrTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - (*i)->Resolve(); - } -} diff --git a/src/coreclr/zap/zapinnerptr.h b/src/coreclr/zap/zapinnerptr.h deleted file mode 100644 index 7c3ef0aa6c8c14..00000000000000 --- a/src/coreclr/zap/zapinnerptr.h +++ /dev/null @@ -1,143 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapInnerPtr.h -// - -// -// ZapNode that points into middle of other ZapNode. It is used to create -// pointers into datastructures that are not convenient to split into smaller zap nodes. -// -// ====================================================================================== - -#ifndef __ZAPINNERPTR_H__ -#define __ZAPINNERPTR_H__ - -class ZapInnerPtr : public ZapNode -{ - ZapNode * m_pBase; - -public: - ZapInnerPtr(ZapNode * pBase) - : m_pBase(pBase) - { - } - - ZapNode * GetBase() - { - return m_pBase; - } - - virtual int GetOffset() = 0; - - void Resolve() - { - if (m_pBase->IsPlaced()) - { - SetRVA(m_pBase->GetRVA() + GetOffset()); - } - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_InnerPtr; - } -}; - -class ZapInnerPtrTable -{ - // Create more space efficient nodes for a few common constant offsets - template - class InnerPtrConst : public ZapInnerPtr - { - public: - InnerPtrConst(ZapNode * pBase) - : ZapInnerPtr(pBase) - { - } - - virtual int GetOffset() - { - return offset; - } - }; - - // The generic node for arbitrary offsets - class InnerPtrVar : public ZapInnerPtr - { - int m_offset; - - public: - InnerPtrVar(ZapNode * pBase, SSIZE_T offset) - : ZapInnerPtr(pBase), m_offset((int)offset) - { - if (offset != (int)offset) - ThrowHR(COR_E_OVERFLOW); - } - - virtual int GetOffset() - { - return m_offset; - } - }; - - struct InnerPtrKey - { - InnerPtrKey(ZapNode * pBase, SSIZE_T offset) - : m_pBase(pBase), m_offset(offset) - { - } - - ZapNode * m_pBase; - SSIZE_T m_offset; - }; - - class InnerPtrTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef const InnerPtrKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return InnerPtrKey(e->GetBase(), e->GetOffset()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return (k1.m_pBase == k2.m_pBase) && (k1.m_offset == k2.m_offset); - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k.m_pBase ^ (count_t)k.m_offset; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< InnerPtrTraits > InnerPtrTable; - - InnerPtrTable m_entries; - ZapWriter * m_pWriter; - -public: - ZapInnerPtrTable(ZapWriter * pWriter) - : m_pWriter(pWriter) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE_NOT_NEEDED(ZapInnerPtrTable::m_entries, cbILImage); - } - - // Returns ZapNode that points at given offset in base ZapNode - ZapNode * Get(ZapNode * pBase, SSIZE_T offset); - - // Assign offsets to the inner-ptr ZapNodes - void Resolve(); -}; - -#endif // __ZAPINNERPTR_H__ diff --git a/src/coreclr/zap/zaplog.h b/src/coreclr/zap/zaplog.h deleted file mode 100644 index a9f5e2e27798e4..00000000000000 --- a/src/coreclr/zap/zaplog.h +++ /dev/null @@ -1,43 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -/* - * Hook IfFailThrow calls to do some logging when exceptions are thrown. - * - */ - -#ifndef __ZAPLOG_H__ -#define __ZAPLOG_H__ - -#undef IfFailThrow -#define IfFailThrow(x) \ - do { \ - HRESULT hrMacro = x; \ - if (FAILED(hrMacro)) { \ - /* don't embed file names in retail to save space and avoid IP */ \ - /* a findstr /n will allow you to locate it in a pinch */ \ - ThrowAndLog(hrMacro, INDEBUG_COMMA(#x) INDEBUG_COMMA(__FILE__) __LINE__); \ - } \ - } while(FALSE) - -inline void ThrowAndLog(HRESULT hr, INDEBUG_COMMA(__in_z const char * szMsg) INDEBUG_COMMA(__in_z const char * szFile) int lineNum) -{ - WRAPPER_NO_CONTRACT; - - // Log failures when StressLog is on - static ConfigDWORD g_iStressLog; - BOOL bLog = g_iStressLog.val(CLRConfig::UNSUPPORTED_StressLog); - if (bLog) - { -#ifdef _DEBUG - GetSvcLogger()->Printf("IfFailThrow about to throw in file %s line %d, msg = %s, hr: 0x%X\n", szFile, lineNum, szMsg, hr); -#else - GetSvcLogger()->Printf("IfFailThrow about to throw on line %d. hr: 0x%X\n", lineNum, hr); -#endif - } - - ThrowHR(hr); -} - -#endif // __ZAPLOG_H__ diff --git a/src/coreclr/zap/zapmetadata.cpp b/src/coreclr/zap/zapmetadata.cpp deleted file mode 100644 index 2e7c3dc570e1b2..00000000000000 --- a/src/coreclr/zap/zapmetadata.cpp +++ /dev/null @@ -1,362 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapMetadata.cpp -// - -// -// Metadata zapping -// -// ====================================================================================== - -#include "common.h" - -#include "zapmetadata.h" - -//----------------------------------------------------------------------------- -// -// ZapMetaData is the barebone ZapNode to save metadata scope -// - -void ZapMetaData::SetMetaData(IUnknown * pEmit) -{ - _ASSERTE(m_pEmit == NULL); - _ASSERTE(pEmit != NULL); - - IfFailThrow(pEmit->QueryInterface(IID_IMetaDataEmit, (void **)&m_pEmit)); -} - -DWORD ZapMetaData::GetSize() -{ - if (m_dwSize == 0) - { - IfFailThrow(m_pEmit->GetSaveSize(cssAccurate, &m_dwSize)); - _ASSERTE(m_dwSize != 0); - } - return m_dwSize; -} - -void ZapMetaData::Save(ZapWriter * pZapWriter) -{ - IfFailThrow(m_pEmit->SaveToStream(pZapWriter, 0)); -} - -//----------------------------------------------------------------------------- -// -// ZapILMetaData copies both the metadata and IL to the NGEN image. -// - -void ZapILMetaData::Save(ZapWriter * pZapWriter) -{ - IMDInternalImport * pMDImport = m_pImage->m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - DWORD flags; - ULONG rva; - IfFailThrow(pMDImport->GetMethodImplProps(md, &rva, &flags)); - - if (!IsMiIL(flags) || (rva == 0)) - continue; - - // Set the actual RVA of the method - const ILMethod * pILMethod = m_ILMethods.LookupPtr(md); - - IfFailThrow(m_pEmit->SetRVA(md, (pILMethod != NULL) ? pILMethod->m_pIL->GetRVA() : 0)); - } - - if (IsReadyToRunCompilation()) - { - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtFieldDef); - - mdFieldDef fd; - while (pMDImport->EnumNext(&hEnum, &fd)) - { - DWORD dwRVA = 0; - if (pMDImport->GetFieldRVA(fd, &dwRVA) == S_OK) - { - PVOID pData = NULL; - DWORD cbSize = 0; - DWORD cbAlignment = 0; - - m_pImage->m_pPreloader->GetRVAFieldData(fd, &pData, &cbSize, &cbAlignment); - - ZapRVADataNode * pRVADataNode = m_rvaData.Lookup(pData); - m_pEmit->SetRVA(fd, pRVADataNode->GetRVA()); - } - } - } - else - { - ZapImage::GetImage(pZapWriter)->m_pPreloader->SetRVAsForFields(m_pEmit); - } - - ZapMetaData::Save(pZapWriter); -} - -ZapRVADataNode * ZapILMetaData::GetRVAField(void * pData) -{ - ZapRVADataNode * pRVADataNode = m_rvaData.Lookup(pData); - - if (pRVADataNode == NULL) - { - pRVADataNode = new (m_pImage->GetHeap()) ZapRVADataNode(pData); - - m_rvaData.Add(pRVADataNode); - } - - return pRVADataNode; -} - -struct RVAField -{ - PVOID pData; - DWORD cbSize; - DWORD cbAlignment; -}; - -// Used by qsort -int __cdecl RVAFieldCmp(const void * a_, const void * b_) -{ - RVAField * a = (RVAField *)a_; - RVAField * b = (RVAField *)b_; - - if (a->pData != b->pData) - { - return (a->pData > b->pData) ? 1 : -1; - } - - return 0; -} - -void ZapILMetaData::CopyRVAFields() -{ - IMDInternalImport * pMDImport = m_pImage->m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtFieldDef); - - SArray fields; - - mdFieldDef fd; - while (pMDImport->EnumNext(&hEnum, &fd)) - { - DWORD dwRVA = 0; - if (pMDImport->GetFieldRVA(fd, &dwRVA) == S_OK) - { - RVAField field; - m_pImage->m_pPreloader->GetRVAFieldData(fd, &field.pData, &field.cbSize, &field.cbAlignment); - fields.Append(field); - } - } - - if (fields.GetCount() == 0) - return; - - // Managed C++ binaries depend on the order of RVA fields - qsort(&fields[0], fields.GetCount(), sizeof(RVAField), RVAFieldCmp); - -#ifdef _DEBUG - for (COUNT_T i = 0; i < fields.GetCount(); i++) - { - // Make sure no RVA field node has been placed during compilation. This would mess up the ordering - // and can potentially break the Managed C++ scenarios. - _ASSERTE(!GetRVAField(fields[i].pData)->IsPlaced()); - } -#endif - - for (COUNT_T i = 0; i < fields.GetCount(); i++) - { - RVAField field = fields[i]; - - ZapRVADataNode * pRVADataNode = GetRVAField(field.pData); - - // Handle overlapping fields by reusing blobs based on the address, and just updating size and alignment. - pRVADataNode->UpdateSizeAndAlignment(field.cbSize, field.cbAlignment); - - if (!pRVADataNode->IsPlaced()) - m_pImage->m_pReadOnlyDataSection->Place(pRVADataNode); - } -} - -void ZapILMetaData::CopyIL() -{ - // The IL is emited into NGen image in the following priority order: - // 1. Public inlineable method (may be needed by JIT inliner) - // 2. Generic method (may be needed to compile non-NGened instantiations) - // 3. Other potentially warm instances (private inlineable methods, methods that failed to NGen) - // 4. Everything else (should be touched in rare scenarios like reflection or profiling only) - - SArray priorityLists[CORCOMPILE_ILREGION_COUNT]; - - IMDInternalImport * pMDImport = m_pImage->m_pMDImport; - - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtMethodDef); - - // - // Build the list for each priority in first pass, and then place - // the IL blobs in each list. The two passes are needed because of - // interning of IL blobs (one IL blob can be on multiple lists). - // - - mdMethodDef md; - while (pMDImport->EnumNext(&hEnum, &md)) - { - const ILMethod * pILMethod = m_ILMethods.LookupPtr(md); - - if (pILMethod == NULL) - continue; - - CorCompileILRegion region = m_pImage->m_pPreloader->GetILRegion(md); - _ASSERTE(region < CORCOMPILE_ILREGION_COUNT); - - // Preallocate space to avoid wasting too much time by reallocations - if (priorityLists[region].IsEmpty()) - priorityLists[region].Preallocate(m_ILMethods.GetCount() / 16); - - priorityLists[region].Append(pILMethod->m_pIL); - } - - for (int iList = 0; iList < CORCOMPILE_ILREGION_COUNT; iList++) - { - SArray & priorityList = priorityLists[iList]; - - // Use just one section for IL for now. Once the touches of IL for method preparation are fixed change it to: - // ZapVirtualSection * pSection = (iList == CORCOMPILE_ILREGION_COLD) ? m_pImage->m_pColdILSection : m_pImage->m_pILSection; - - ZapVirtualSection * pSection = m_pImage->m_pILSection; - - COUNT_T nBlobs = priorityList.GetCount(); - for (COUNT_T iBlob = 0; iBlob < nBlobs; iBlob++) - { - ZapBlob * pIL = priorityList[iBlob]; - if (!pIL->IsPlaced()) - pSection->Place(pIL); - } - } -} - -void ZapILMetaData::CopyMetaData() -{ - // - // Copy metadata from IL image and open it so we can update IL rva's - // - - COUNT_T cMeta; - const void *pMeta = m_pImage->m_ModuleDecoder.GetMetadata(&cMeta); - - IMetaDataDispenserEx * pMetaDataDispenser = m_pImage->m_zapper->m_pMetaDataDispenser; - - // - // Transfer the metadata version string from IL image to native image - // - LPCSTR pRuntimeVersionString; - IfFailThrow(GetImageRuntimeVersionString((PVOID)pMeta, &pRuntimeVersionString)); - - SString ssRuntimeVersion; - ssRuntimeVersion.SetUTF8(pRuntimeVersionString); - - BSTRHolder strVersion(SysAllocString(ssRuntimeVersion.GetUnicode())); - - VARIANT versionOption; - V_VT(&versionOption) = VT_BSTR; - V_BSTR(&versionOption) = strVersion; - IfFailThrow(pMetaDataDispenser->SetOption(MetaDataRuntimeVersion, &versionOption)); - - // Preserve local refs. - VARIANT preserveLocalRefsOption; - V_VT(&preserveLocalRefsOption) = VT_UI4; - V_UI4(&preserveLocalRefsOption) = MDPreserveLocalTypeRef | MDPreserveLocalMemberRef; - IfFailThrow(pMetaDataDispenser->SetOption(MetaDataPreserveLocalRefs, &preserveLocalRefsOption)); - - // ofNoTransform - Get the raw metadata for WinRT, not the adapter view - HRESULT hr = pMetaDataDispenser->OpenScopeOnMemory(pMeta, cMeta, - ofWrite | ofNoTransform, - IID_IMetaDataEmit, - (IUnknown **) &m_pEmit); - if (hr == CLDB_E_BADUPDATEMODE) - { - // This must be incrementally-updated metadata. It needs to be opened - // specially. - VARIANT incOption; - V_VT(&incOption) = VT_UI4; - V_UI4(&incOption) = MDUpdateIncremental; - IfFailThrow(pMetaDataDispenser->SetOption(MetaDataSetUpdate, &incOption)); - - hr = pMetaDataDispenser->OpenScopeOnMemory(pMeta, cMeta, - ofWrite | ofNoTransform, - IID_IMetaDataEmit, - (IUnknown **) &m_pEmit); - } - - // Check the result of OpenScopeOnMemory() - IfFailThrow(hr); - - if (!IsReadyToRunCompilation()) - { - // Communicate the profile data to the meta data emitter so it can hot/cold split it - NonVMComHolder pIMetaDataCorProfileData; - IfFailThrow(m_pEmit->QueryInterface(IID_IMetaDataCorProfileData, - (void**)&pIMetaDataCorProfileData)); - - // unless we're producing an instrumented version - the IBC logging for meta data doesn't - // work for the hot/cold split version. - if (m_pImage->m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - IfFailThrow(pIMetaDataCorProfileData->SetCorProfileData(NULL)); - else - IfFailThrow(pIMetaDataCorProfileData->SetCorProfileData(m_pImage->GetProfileData())); - } - - // If we are ngening with the tuning option, the IBC data that is - // generated gets reordered and may be inconsistent with the - // metadata in the original IL image. Let's just skip that case. - if (!m_pImage->m_zapper->m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR)) - { - // Communicate the reordering option for saving - NonVMComHolder pIMDInternalMetadataReorderingOptions; - IfFailThrow(m_pEmit->QueryInterface(IID_IMDInternalMetadataReorderingOptions, - (void**)&pIMDInternalMetadataReorderingOptions)); - IfFailThrow(pIMDInternalMetadataReorderingOptions->SetMetaDataReorderingOptions(ReArrangeStringPool)); - } -} - -// Emit IL for a method def into the ngen image -void ZapILMetaData::EmitMethodIL(mdMethodDef md) -{ - DWORD flags; - ULONG rva; - IfFailThrow(m_pImage->m_pMDImport->GetMethodImplProps(md, &rva, &flags)); - - if (!IsMiIL(flags) || (rva == 0)) - return; - - if (!m_pImage->m_ModuleDecoder.CheckILMethod(rva)) - IfFailThrow(COR_E_BADIMAGEFORMAT); // BFA_BAD_IL_RANGE - - PVOID pMethod = (PVOID)m_pImage->m_ModuleDecoder.GetRvaData(rva); - - SIZE_T cMethod = PEDecoder::ComputeILMethodSize((TADDR)pMethod); - - // - // Emit copy of IL method in native image. - // - ZapBlob * pIL = m_blobs.Lookup(ZapBlob::SHashKey(pMethod, cMethod)); - - if (pIL == NULL) - { - pIL = new (m_pImage->GetHeap()) ILBlob(pMethod, cMethod); - - m_blobs.Add(pIL); - } - - ILMethod ilMethod; - ilMethod.m_md = md; - ilMethod.m_pIL = pIL; - m_ILMethods.Add(ilMethod); -} diff --git a/src/coreclr/zap/zapmetadata.h b/src/coreclr/zap/zapmetadata.h deleted file mode 100644 index c23774cffb1f19..00000000000000 --- a/src/coreclr/zap/zapmetadata.h +++ /dev/null @@ -1,221 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapMetadata.h -// - -// -// Metadata zapping -// -// ====================================================================================== - -#ifndef __ZAPMETADATA_H__ -#define __ZAPMETADATA_H__ - -//----------------------------------------------------------------------------- -// -// ZapMetaData is the barebone ZapNode to save metadata scope -// - -class ZapMetaData : public ZapNode -{ - DWORD m_dwSize; - -protected: - IMetaDataEmit * m_pEmit; - -public: - ZapMetaData() - { - } - - ~ZapMetaData() - { - SAFERELEASE(m_pEmit); - } - - void SetMetaData(IUnknown * pEmit); - - virtual DWORD GetSize(); - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_MetaData; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -//----------------------------------------------------------------------------- -// -// Helper node to copy RVA data to from IL to the NGEN image. -// - -class ZapRVADataNode : public ZapNode -{ - PVOID m_pData; - DWORD m_dwSize; - DWORD m_dwAlignment; - -public: - ZapRVADataNode(PVOID pData) - { - m_pData = pData; - m_dwSize = 0; - m_dwAlignment = 1; - } - - void UpdateSizeAndAlignment(DWORD dwSize, DWORD dwAlignment) - { - if (dwSize > m_dwSize) - m_dwSize = dwSize; - - if (dwAlignment > m_dwAlignment) - m_dwAlignment = dwAlignment; - } - - PVOID GetData() - { - return m_pData; - } - - virtual DWORD GetSize() - { - return m_dwSize; - } - - virtual UINT GetAlignment() - { - return m_dwAlignment; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_RVAFieldData; - } - - virtual void Save(ZapWriter * pZapWriter) - { - pZapWriter->Write(m_pData, m_dwSize); - } -}; - - -//----------------------------------------------------------------------------- -// -// ZapILMetaData copies both the metadata and IL to the NGEN image. -// - -class ZapILMetaData : public ZapMetaData -{ - ZapImage * m_pImage; - - class ILBlob : public ZapBlobPtr - { - public: - ILBlob(PVOID pData, SIZE_T cbSize) - : ZapBlobPtr(pData, cbSize) - { - } - - virtual UINT GetAlignment() - { - // The tiny header does not have any alignment requirements - return ((COR_ILMETHOD_TINY *)GetData())->IsTiny() ? sizeof(BYTE) : sizeof(DWORD); - } - }; - - // Hashtable with all IL method blobs. If two methods have same IL code - // we store it just once. - SHash< NoRemoveSHashTraits < ZapBlob::SHashTraits > > m_blobs; - - struct ILMethod - { - mdMethodDef m_md; - ZapBlob * m_pIL; - }; - - class ILMethodTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef const mdMethodDef key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e.m_md; - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return k; - } - - static const element_t Null() { LIMITED_METHOD_CONTRACT; ILMethod e; e.m_md = 0; e.m_pIL = NULL; return e; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e.m_md == 0; } - }; - - SHash< ILMethodTraits > m_ILMethods; - -public: - ZapILMetaData(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapILMetaData::m_blobs, 0.0040, cbILImage); - PREALLOCATE_HASHTABLE(ZapILMetaData::m_ILMethods, 0.0044, cbILImage); - } - - void EmitMethodIL(mdMethodDef md); - - void CopyIL(); - void CopyMetaData(); - void CopyRVAFields(); - - virtual void Save(ZapWriter * pZapWriter); - - ZapRVADataNode * GetRVAField(void * pData); - -private: - class RVADataTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef PVOID key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetData(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(SIZE_T)k; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - SHash< RVADataTraits > m_rvaData; -}; - -#endif // __ZAPMETADATA_H__ diff --git a/src/coreclr/zap/zapnodetype.h b/src/coreclr/zap/zapnodetype.h deleted file mode 100644 index 6f73833eb84101..00000000000000 --- a/src/coreclr/zap/zapnodetype.h +++ /dev/null @@ -1,117 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapNoteType.h -// - -// -// Enum for ZapNode types -// -// ====================================================================================== - -#ifndef __ZAPNODETYPE_H__ -#define __ZAPNODETYPE_H__ - -enum ZapNodeType { - -// System types - - ZapNodeType_Unknown, - - ZapNodeType_PhysicalSection, - ZapNodeType_VirtualSection, - ZapNodeType_Blob, - ZapNodeType_InnerPtr, - - ZapNodeType_Relocs, - -// Headers - - ZapNodeType_CorHeader, - ZapNodeType_NativeHeader, - ZapNodeType_VersionInfo, - ZapNodeType_Dependencies, - ZapNodeType_CodeManagerEntry, - ZapNodeType_MetaData, - ZapNodeType_DebugDirectory, - ZapNodeType_Win32Resources, - -// PlaceHolders - - ZapNodeType_MethodEntryPoint, - ZapNodeType_ClassHandle, - ZapNodeType_MethodHandle, - ZapNodeType_FieldHandle, - ZapNodeType_AddrOfPInvokeFixup, - ZapNodeType_GenericHandle, - ZapNodeType_ModuleIDHandle, - -// Code references - - ZapNodeType_MethodHeader, - ZapNodeType_CodeManagerMap, - ZapNodeType_UnwindInfo, - ZapNodeType_UnwindData, - ZapNodeType_UnwindDataAndGCInfo, - ZapNodeType_FilterFuncletUnwindData, - - ZapNodeType_ProfileData, - ZapNodeType_VirtualSectionsTable, - - ZapNodeType_DebugInfoTable, - ZapNodeType_DebugInfoLabelledEntry, - - ZapNodeType_HelperThunk, - ZapNodeType_LazyHelperThunk, - ZapNodeType_IndirectHelperThunk, - - ZapNodeType_ExceptionInfoTable, - ZapNodeType_UnwindInfoLookupTable, - ZapNodeType_ColdCodeMap, - -// Wrappers - - ZapNodeType_Stub, - -// Imports - - ZapNodeType_ExternalMethodThunk, - ZapNodeType_VirtualMethodThunk, - - ZapNodeType_ExternalMethodCell, - ZapNodeType_StubDispatchCell, - ZapNodeType_DynamicHelperCell, - - ZapNodeType_Import_FunctionEntry, - ZapNodeType_Import_ModuleHandle, - ZapNodeType_Import_ClassHandle, - ZapNodeType_Import_MethodHandle, - ZapNodeType_Import_FieldHandle, - ZapNodeType_Import_IndirectPInvokeTarget, - ZapNodeType_Import_PInvokeTarget, - ZapNodeType_Import_StringHandle, - ZapNodeType_Import_StaticFieldAddress, - ZapNodeType_Import_ClassDomainId, - ZapNodeType_Import_ModuleDomainId, - ZapNodeType_Import_SyncLock, - ZapNodeType_Import_ProfilingHandle, - ZapNodeType_Import_VarArg, - ZapNodeType_Import_ActiveDependency, - ZapNodeType_Import_Helper, - - ZapNodeType_GenericSignature, - - ZapNodeType_ImportTable, - - ZapNodeType_ImportSectionsTable, - ZapNodeType_ImportSectionSignatures, - - ZapNodeType_GCRefMapTable, - - ZapNodeType_RVAFieldData, - ZapNodeType_EntryPointsTable, - - ZapNodeType_StoredStructure, // The ZapNodeTypes of the legacy stored structures start here -}; - -#endif // __ZAPNODETYPE_H__ diff --git a/src/coreclr/zap/zapper.cpp b/src/coreclr/zap/zapper.cpp deleted file mode 100644 index c0d65d34c46498..00000000000000 --- a/src/coreclr/zap/zapper.cpp +++ /dev/null @@ -1,1699 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - - -#include "common.h" - -#include "coregen.h" - -#pragma warning(push) -#pragma warning(disable: 4995) -#include "shlwapi.h" -#pragma warning(pop) - -extern const WCHAR g_pwBaseLibrary[]; -extern bool g_fAllowNativeImages; -bool g_fNGenMissingDependenciesOk; - -#ifdef FEATURE_READYTORUN_COMPILER -bool g_fReadyToRunCompilation; -bool g_fLargeVersionBubble; -#endif - -/* --------------------------------------------------------------------------- * - * Public entry points for ngen - * --------------------------------------------------------------------------- */ -// For side by side issues, it's best to use the exported API calls to generate a -// 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, SIZE_T customBaseAddress=0, ICorSvcLogger *pLogger = NULL, LPCWSTR pwszCLRJITPath = nullptr) -{ - HRESULT hr = S_OK; - - BEGIN_ENTRYPOINT_NOTHROW; - - Zapper* zap = NULL; - - EX_TRY - { - NGenOptions ngo = {0}; - ngo.dwSize = sizeof(NGenOptions); - - // V1 - - ngo.fDebug = false; - ngo.fDebugOpt = false; - ngo.fProf = false; - ngo.fSilent = (dwFlags & NGENWORKER_FLAGS_SILENT) != 0; - ngo.lpszExecutableFileName = pwzFilename; - - // V2 (Whidbey) - - ngo.fInstrument = !!(dwFlags & NGENWORKER_FLAGS_TUNING); - ngo.fWholeProgram = false; - ngo.fProfInfo = false; - - ngo.lpszRepositoryDir = NULL; - ngo.repositoryFlags = RepositoryDefault; - - ngo.dtRequested = DT_NIL; - ngo.lpszDebugDir = NULL; - - ngo.fNoInstall = false; - - ngo.fEmitFixups = false; - ngo.fFatHeaders = false; - - ngo.fVerbose = (dwFlags & NGENWORKER_FLAGS_VERBOSE) != 0; - ngo.uStats = false; - - ngo.fNgenLastRetry = false; - - zap = Zapper::NewZapper(&ngo); - - if (pwzOutputFilename) - zap->SetOutputFilename(pwzOutputFilename); - - zap->SetCustomBaseAddress(customBaseAddress); - - if (pwzPlatformAssembliesPaths != nullptr) - zap->SetPlatformAssembliesPaths(pwzPlatformAssembliesPaths); - - if (pwzTrustedPlatformAssemblies != nullptr) - zap->SetTrustedPlatformAssemblies(pwzTrustedPlatformAssemblies); - - if (pwzPlatformResourceRoots != nullptr) - zap->SetPlatformResourceRoots(pwzPlatformResourceRoots); - - if (pwzAppPaths != nullptr) - zap->SetAppPaths(pwzAppPaths); - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - if (pwszCLRJITPath != nullptr) - zap->SetCLRJITPath(pwszCLRJITPath); -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - - g_fNGenMissingDependenciesOk = !!(dwFlags & NGENWORKER_FLAGS_MISSINGDEPENDENCIESOK); - -#ifdef FEATURE_READYTORUN_COMPILER - g_fReadyToRunCompilation = !!(dwFlags & NGENWORKER_FLAGS_READYTORUN); - g_fLargeVersionBubble = !!(dwFlags & NGENWORKER_FLAGS_LARGEVERSIONBUBBLE); -#endif - - if (pLogger != NULL) - { - GetSvcLogger()->SetSvcLogger(pLogger); - } - - hr = zap->Compile(pwzFilename); - } - EX_CATCH_HRESULT(hr); - - END_ENTRYPOINT_NOTHROW; - - return hr; -} - -STDAPI CreatePDBWorker(LPCWSTR pwzAssemblyPath, LPCWSTR pwzPlatformAssembliesPaths, LPCWSTR pwzTrustedPlatformAssemblies, LPCWSTR pwzPlatformResourceRoots, LPCWSTR pwzAppPaths, LPCWSTR pwzAppNiPaths, LPCWSTR pwzPdbPath, BOOL fGeneratePDBLinesInfo, LPCWSTR pwzManagedPdbSearchPath, LPCWSTR pwzDiasymreaderPath) -{ - HRESULT hr = S_OK; - - BEGIN_ENTRYPOINT_NOTHROW; - - EX_TRY - { - GetCompileInfo()->SetIsGeneratingNgenPDB(TRUE); - - NGenOptions ngo = {0}; - ngo.dwSize = sizeof(NGenOptions); - - NewHolder zap(Zapper::NewZapper(&ngo)); - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - zap->SetDontLoadJit(); -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - - if (pwzPlatformAssembliesPaths != nullptr) - zap->SetPlatformAssembliesPaths(pwzPlatformAssembliesPaths); - - if (pwzTrustedPlatformAssemblies != nullptr) - zap->SetTrustedPlatformAssemblies(pwzTrustedPlatformAssemblies); - - if (pwzPlatformResourceRoots != nullptr) - zap->SetPlatformResourceRoots(pwzPlatformResourceRoots); - - if (pwzAppPaths != nullptr) - zap->SetAppPaths(pwzAppPaths); - - if (pwzAppNiPaths != nullptr) - zap->SetAppNiPaths(pwzAppNiPaths); - -#if !defined(NO_NGENPDB) - if (pwzDiasymreaderPath != nullptr) - zap->SetDiasymreaderPath(pwzDiasymreaderPath); -#endif // !defined(NO_NGENPDB) - - BSTRHolder strAssemblyPath(::SysAllocString(pwzAssemblyPath)); - BSTRHolder strPdbPath(::SysAllocString(pwzPdbPath)); - BSTRHolder strManagedPdbSearchPath(::SysAllocString(pwzManagedPdbSearchPath)); - - // Zapper::CreatePdb is shared code for both desktop NGEN PDBs and coreclr - // crossgen PDBs. - zap->CreatePdb( - strAssemblyPath, - - // On desktop with fusion AND on the phone, the various binders always expect - // the native image to be specified here. - strAssemblyPath, - - strPdbPath, - fGeneratePDBLinesInfo, - strManagedPdbSearchPath); - } - EX_CATCH_HRESULT(hr); - - END_ENTRYPOINT_NOTHROW; - - return hr; -} - - -/* --------------------------------------------------------------------------- * - * Options class - * --------------------------------------------------------------------------- */ - -ZapperOptions::ZapperOptions() : - m_repositoryDir(NULL), - m_repositoryFlags(RepositoryDefault), - m_autodebug(false), - m_onlyOneMethod(0), - m_silent(true), - m_verbose(false), - m_ignoreErrors(true), - m_statOptions(0), - m_ngenProfileImage(false), - m_ignoreProfileData(false), - m_noProcedureSplitting(false), - m_fHasAnyProfileData(false), - m_fPartialNGen(false), - m_fPartialNGenSet(false), - m_fNGenLastRetry(false), - m_compilerFlags() -{ - SetCompilerFlags(); - - m_zapSet = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_ZapSet); - if (m_zapSet != NULL && wcslen(m_zapSet) > 3) - { - delete [] m_zapSet; - m_zapSet = NULL; - } - - if (CLRConfig::GetConfigValue(CLRConfig::UNSUPPORTED_DisableIBC)) - { - m_ignoreProfileData = true; - } - - if (CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_NoProcedureSplitting)) - { - m_noProcedureSplitting = true; - } - - DWORD partialNGen = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_PartialNGen); - if (partialNGen != (DWORD)(-1)) - { - m_fPartialNGenSet = true; - m_fPartialNGen = partialNGen != 0; - } - -#ifdef _DEBUG - m_onlyOneMethod = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NGenOnlyOneMethod); -#endif -} - -ZapperOptions::~ZapperOptions() -{ - if (m_zapSet != NULL) - delete [] m_zapSet; - - if (m_repositoryDir != NULL) - delete [] m_repositoryDir; -} - -void ZapperOptions::SetCompilerFlags(void) -{ - m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELOC); - m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PREJIT); - -#if defined(TARGET_ARM) -# if defined(TARGET_UNIX) - m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_RELATIVE_CODE_RELOCS); -# endif // defined(TARGET_UNIX) -#endif // defined(TARGET_ARM) -} - -/* --------------------------------------------------------------------------- * - * Zapper class - * --------------------------------------------------------------------------- */ - -Zapper::Zapper(NGenOptions *pOptions, bool fromDllHost) -{ - ZapperOptions *zo = new ZapperOptions(); - - // We can version NGenOptions by looking at the dwSize variable - - NGenOptions currentVersionOptions; - memcpy(¤tVersionOptions, pOptions, pOptions->dwSize); - - if (pOptions->dwSize < sizeof(currentVersionOptions)) - { - // Clear out the memory. This is redundant with the explicit - // initializations below, but is meant to be a backup. - - ZeroMemory(PBYTE(¤tVersionOptions) + pOptions->dwSize, - sizeof(currentVersionOptions) - pOptions->dwSize); - - // Initialize all the fields added in the current version - - currentVersionOptions.fInstrument = false; - currentVersionOptions.fWholeProgram = false; - currentVersionOptions.fProfInfo = false; - - currentVersionOptions.dtRequested = DT_NIL; - currentVersionOptions.lpszDebugDir = NULL; - - currentVersionOptions.lpszRepositoryDir = NULL; - currentVersionOptions.repositoryFlags = RepositoryDefault; - - currentVersionOptions.fNoInstall = false; - - currentVersionOptions.fEmitFixups = false; - currentVersionOptions.fFatHeaders = false; - - currentVersionOptions.fVerbose = false; - currentVersionOptions.uStats = 0; - - currentVersionOptions.fNgenLastRetry = false; - - currentVersionOptions.fAutoNGen = false; - - currentVersionOptions.fRepositoryOnly = false; - } - - pOptions = ¤tVersionOptions; - - zo->m_compilerFlags.Reset(); - zo->SetCompilerFlags(); - zo->m_autodebug = true; - - if (pOptions->fDebug) - { - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - zo->m_autodebug = false; - } - - if (pOptions->fProf) - { - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - } - - - if (pOptions->fInstrument) - zo->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - - zo->m_verbose = pOptions->fVerbose; - zo->m_statOptions = pOptions->uStats; - - zo->m_silent = pOptions->fSilent; - - if (pOptions->lpszExecutableFileName != NULL) - { - m_exeName.Set(pOptions->lpszExecutableFileName); - } - - if (pOptions->fNgenLastRetry) - { - zo->m_fNGenLastRetry = true; - - // - // Things that we turn off when this is the last retry for ngen - // - zo->m_ignoreProfileData = true; // ignore any IBC profile data - -#ifdef TARGET_ARM - // - // On ARM, we retry compilation for large images when we hit overflow of IMAGE_REL_BASED_THUMB_BRANCH24 relocations. - // Disable procedure spliting for retry because of it depends on IMAGE_REL_BASED_THUMB_BRANCH24 relocations. - // See related code in code:ZapInfo::getRelocTypeHint - // - zo->m_noProcedureSplitting = true; -#endif - } - - zo->m_fAutoNGen = pOptions->fAutoNGen; - - zo->m_fRepositoryOnly = pOptions->fRepositoryOnly; - - m_fromDllHost = fromDllHost; - - Init(zo, true); -} - - -Zapper::Zapper(ZapperOptions *pOptions) -{ - Init(pOptions); -} - -void Zapper::Init(ZapperOptions *pOptions, bool fFreeZapperOptions) -{ - m_pEEJitInfo = NULL; - m_pEECompileInfo = NULL; - m_pJitCompiler = NULL; - m_pMetaDataDispenser = NULL; - m_hJitLib = NULL; -#ifdef TARGET_AMD64 - m_hJitLegacy = NULL; -#endif - - m_pOpt = pOptions; - - m_pDomain = NULL; - m_hAssembly = NULL; - m_pAssemblyImport = NULL; - m_failed = FALSE; - m_currentRegionKind = CORINFO_REGION_NONE; - - m_pAssemblyEmit = NULL; - m_fFreeZapperOptions = fFreeZapperOptions; - - m_customBaseAddress = 0; - -#ifdef LOGGING - InitializeLogging(); -#endif - - HRESULT hr; - - // - // Get metadata dispenser interface - // - - IfFailThrow(MetaDataGetDispenser(CLSID_CorMetaDataDispenser, - IID_IMetaDataDispenserEx, (void **)&m_pMetaDataDispenser)); - - // - // Make sure we don't duplicate assembly refs and file refs - // - - VARIANT opt; - hr = m_pMetaDataDispenser->GetOption(MetaDataCheckDuplicatesFor, &opt); - _ASSERTE(SUCCEEDED(hr)); - - _ASSERTE(V_VT(&opt) == VT_UI4); - V_UI4(&opt) |= MDDupAssemblyRef | MDDupFile; - - hr = m_pMetaDataDispenser->SetOption(MetaDataCheckDuplicatesFor, &opt); - _ASSERTE(SUCCEEDED(hr)); - - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - m_fDontLoadJit = false; -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) -} - -// LoadAndInitializeJITForNgen: load the JIT dll into the process, and initialize it (call the UtilCode initialization function, -// check the JIT-EE interface GUID, etc.). (This is similar to LoadAndInitializeJIT.) -// -// Parameters: -// -// pwzJitName - The filename of the JIT .dll file to load. E.g., "altjit.dll". -// phJit - On return, *phJit is the Windows module handle of the loaded JIT dll. It will be NULL if the load failed. -// ppICorJitCompiler - On return, *ppICorJitCompiler is the ICorJitCompiler* returned by the JIT's getJit() entrypoint. -// It is NULL if the JIT returns a NULL interface pointer, or if the JIT-EE interface GUID is mismatched. -// -// Note that both *phJit and *ppICorJitCompiler will be non-NULL on success. On failure, an exception is thrown. -void Zapper::LoadAndInitializeJITForNgen(LPCWSTR pwzJitName, OUT HINSTANCE* phJit, OUT ICorJitCompiler** ppICorJitCompiler) -{ - _ASSERTE(phJit != NULL); - _ASSERTE(ppICorJitCompiler != NULL); - - *phJit = NULL; - *ppICorJitCompiler = NULL; - - HRESULT hr = E_FAIL; - - // Note: FEATURE_MERGE_JIT_AND_ENGINE is defined for the Desktop crossgen compilation as well. - // - PathString CoreClrFolder; - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) - if (m_fDontLoadJit) - { - return; - } - - if (m_CLRJITPath.GetCount() > 0) - { - // If we have been asked to load a specific JIT binary, load it. - CoreClrFolder.Set(m_CLRJITPath); - hr = S_OK; - } - else -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - { - hr = GetClrModuleDirectory(CoreClrFolder); - if (SUCCEEDED(hr)) - { - CoreClrFolder.Append(pwzJitName); - } - } - - if (SUCCEEDED(hr)) - { - *phJit = ::WszLoadLibrary(CoreClrFolder); - if (*phJit == NULL) - { - hr = HRESULT_FROM_GetLastError(); - } - else - { - hr = S_OK; - } - } - - if (FAILED(hr)) - { - Error(W("Unable to load Jit Compiler: %s, hr=0x%08x\r\n"), pwzJitName, hr); - ThrowLastError(); - } - - typedef void (__stdcall* pJitStartup)(ICorJitHost* host); - pJitStartup jitStartupFn = (pJitStartup)GetProcAddress(*phJit, "jitStartup"); - if (jitStartupFn != nullptr) - { - jitStartupFn(m_pEECompileInfo->GetJitHost()); - } - - //get the appropriate compiler interface - typedef ICorJitCompiler* (__stdcall* pGetJitFn)(); - pGetJitFn getJitFn = (pGetJitFn) GetProcAddress(*phJit, "getJit"); - if (getJitFn == NULL) - { - Error(W("Unable to load main Jit function: %s\r\n"), pwzJitName); - ThrowLastError(); - } - - ICorJitCompiler* pICorJitCompiler = (*getJitFn)(); - if (pICorJitCompiler == NULL) - { - Error(W("Unable to initialize Jit Compiler: %s\r\n"), pwzJitName); - ThrowLastError(); - } - - // Check the JIT version identifier. - - GUID versionId; - memset(&versionId, 0, sizeof(GUID)); - pICorJitCompiler->getVersionIdentifier(&versionId); - - if (memcmp(&versionId, &JITEEVersionIdentifier, sizeof(GUID)) != 0) - { - // Mismatched version ID. Fail the load. - Error(W("Jit Compiler has wrong version identifier\r\n")); - ThrowHR(E_FAIL); - } - - // The JIT has loaded and passed the version identifier test, so publish the JIT interface to the caller. - *ppICorJitCompiler = pICorJitCompiler; -} - -void Zapper::InitEE(BOOL fForceDebug, BOOL fForceProfile, BOOL fForceInstrument) -{ - if (m_pEECompileInfo != NULL) - return; - -#if defined(FEATURE_COMINTEROP) - // - // Initialize COM - // - - if (!m_fromDllHost) - { - CoInitializeEx(NULL, COINIT_MULTITHREADED); - } - -#endif // FEATURE_COMINTEROP - - // - // Get EE compiler interface and initialize the EE - // - - m_pEECompileInfo = GetCompileInfo(); - - if (m_pOpt->m_statOptions) - IfFailThrow(m_pEECompileInfo->SetVerboseLevel (CORCOMPILE_STATS)); - - if (m_pOpt->m_verbose) - IfFailThrow(m_pEECompileInfo->SetVerboseLevel (CORCOMPILE_VERBOSE)); - - IfFailThrow(m_pEECompileInfo->Startup(fForceDebug, fForceProfile, fForceInstrument)); - - m_pEEJitInfo = GetZapJitInfo(); - - // - // Get JIT interface - // - -#ifdef FEATURE_MERGE_JIT_AND_ENGINE - jitStartup(m_pEECompileInfo->GetJitHost()); - m_pJitCompiler = getJit(); - - if (m_pJitCompiler == NULL) - { - Error(W("Unable to initialize Jit Compiler\r\n")); - ThrowLastError(); - } -#else - - LPCWSTR pwzJitName = nullptr; - - // Try to obtain a name for the jit library from the env. variable - IfFailThrow(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_JitName, const_cast(&pwzJitName))); - if (pwzJitName == nullptr) - { - pwzJitName = CorCompileGetRuntimeDllName(CROSSGEN_COMPILER_INFO); - } - - LoadAndInitializeJITForNgen(pwzJitName, &m_hJitLib, &m_pJitCompiler); - -#endif // FEATURE_MERGE_JIT_AND_ENGINE - -#ifdef ALLOW_SXS_JIT_NGEN - - // Do not load altjit unless COMPlus_AltJitNgen is set. - LPWSTR altJit; - HRESULT hr = CLRConfig::GetConfigValue(CLRConfig::INTERNAL_AltJitNgen, &altJit); - if (FAILED(hr)) - { - Error(W("Unable to load alternative Jit Compiler\r\n")); - ThrowHR(hr); - } - - m_hAltJITCompiler = NULL; - m_alternateJit = NULL; - - if (altJit != NULL) - { - // Allow a second jit to be loaded into the system. - // - LPCWSTR altName; - hr = CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_AltJitName, (LPWSTR*)&altName); - if (FAILED(hr)) - { - Error(W("Unable to load alternative Jit Compiler\r\n")); - ThrowHR(hr); - } - - if (altName == NULL) - { - #ifdef TARGET_WINDOWS -#ifdef TARGET_X86 - altName = MAKEDLLNAME_W(W("clrjit_win_x86_x86")); -#elif defined(TARGET_AMD64) - altName = MAKEDLLNAME_W(W("clrjit_win_x64_x64")); -#elif defined(TARGET_ARM) - altName = MAKEDLLNAME_W(W("clrjit_win_arm_arm")); -#elif defined(TARGET_ARM64) - altName = MAKEDLLNAME_W(W("clrjit_win_arm64_arm64")); -#endif -#else // TARGET_WINDOWS -#ifdef TARGET_X86 - altName = MAKEDLLNAME_W(W("clrjit_unix_x86_x86")); -#elif defined(TARGET_AMD64) - altName = MAKEDLLNAME_W(W("clrjit_unix_x64_x64")); -#elif defined(TARGET_ARM) - altName = MAKEDLLNAME_W(W("clrjit_unix_arm_arm")); -#elif defined(TARGET_ARM64) - altName = MAKEDLLNAME_W(W("clrjit_unix_arm64_arm64")); -#endif -#endif // TARGET_WINDOWS - } - - LoadAndInitializeJITForNgen(altName, &m_hAltJITCompiler, &m_alternateJit); - } -#endif // ALLOW_SXS_JIT_NGEN -} - -Zapper::~Zapper() -{ - DestroyDomain(); - - if (m_pMetaDataDispenser != NULL) - m_pMetaDataDispenser->Release(); - - if (m_fFreeZapperOptions) - { - if (m_pOpt != NULL) - delete m_pOpt; - m_pOpt = NULL; - } - - if (m_pEECompileInfo != NULL) - { -#ifndef FEATURE_MERGE_JIT_AND_ENGINE -#ifdef TARGET_AMD64 - if (m_hJitLegacy != NULL) - { - _ASSERTE(m_hJitLib != NULL); - _ASSERTE(m_pJitCompiler != NULL); - - FreeLibrary(m_hJitLegacy); - } -#endif - if (m_hJitLib != NULL) - FreeLibrary(m_hJitLib); -#endif - -#ifdef ALLOW_SXS_JIT_NGEN - if (m_hAltJITCompiler != NULL) - FreeLibrary(m_hAltJITCompiler); -#endif - -#ifdef FEATURE_COMINTEROP - if (!m_fromDllHost) - { - CoUninitialize(); - } -#endif // FEATURE_COMINTEROP - } -} - -void Zapper::DestroyDomain() -{ - CleanupAssembly(); - - // - // Shut down JIT compiler. - // - - if (m_pJitCompiler != NULL) - { - m_pJitCompiler->ProcessShutdownWork(NULL); - } - - // - // Get rid of domain. - // - - if (m_pDomain != NULL) - { - m_pEECompileInfo->DestroyDomain(m_pDomain); - m_pDomain = NULL; - } -} - -void Zapper::CleanupAssembly() -{ - if (m_pAssemblyEmit != NULL) - { - m_pAssemblyEmit->Release(); - m_pAssemblyEmit = NULL; - } - - if (m_pAssemblyImport != NULL) - { - m_pAssemblyImport->Release(); - m_pAssemblyImport = NULL; - } -} - - -//********************************************************************** -// Copy of vm\i386\cgenCpu.h -// @TODO : clean this up. There has to be a way of sharing this code - -//********************************************************************** -// To be used with GetSpecificCpuInfo() -#ifdef TARGET_X86 - -#define CPU_X86_FAMILY(cpuType) (((cpuType) & 0x0F00) >> 8) -#define CPU_X86_MODEL(cpuType) (((cpuType) & 0x00F0) >> 4) -// Stepping is masked out by GetSpecificCpuInfo() -// #define CPU_X86_STEPPING(cpuType) (((cpuType) & 0x000F) ) - -#define CPU_X86_USE_CMOV(cpuFeat) (((cpuFeat) & 0x00008001) == 0x00008001) -#define CPU_X86_USE_SSE2(cpuFeat) (((cpuFeat) & 0x04000000) == 0x04000000) - -// Values for CPU_X86_FAMILY(cpuType) -#define CPU_X86_486 4 -#define CPU_X86_PENTIUM 5 -#define CPU_X86_PENTIUM_PRO 6 -#define CPU_X86_PENTIUM_4 0xF - -// Values for CPU_X86_MODEL(cpuType) for CPU_X86_PENTIUM_PRO -#define CPU_X86_MODEL_PENTIUM_PRO_BANIAS 9 // Pentium M (Mobile PPro with P4 feautres) - -#endif - - -BOOL Zapper::IsAssembly(LPCWSTR path) -{ - HandleHolder hFile = WszCreateFile(path, - GENERIC_READ, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, OPEN_EXISTING, 0, NULL); - - if (hFile == INVALID_HANDLE_VALUE) - return FALSE; - - IMAGE_DOS_HEADER dos; - - DWORD count; - if (!ReadFile(hFile, &dos, sizeof(dos), &count, NULL) - || count != sizeof(dos)) - return FALSE; - - if (dos.e_magic != IMAGE_DOS_SIGNATURE || dos.e_lfanew == 0) - return FALSE; - - if( SetFilePointer(hFile, dos.e_lfanew, NULL, FILE_BEGIN) == INVALID_SET_FILE_POINTER) - return FALSE; - - IMAGE_NT_HEADERS nt; - if (!ReadFile(hFile, &nt, sizeof(nt), &count, NULL) - || count != sizeof(nt)) - return FALSE; - - if (nt.Signature != IMAGE_NT_SIGNATURE) - return FALSE; - - IMAGE_DATA_DIRECTORY* pDataDirectory = NULL; - - // We accept pe32 or pe64 file formats - - if (nt.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR32_MAGIC) - { - if (nt.FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER32)) - return FALSE; - - IMAGE_NT_HEADERS32* pNTHeader32 = (IMAGE_NT_HEADERS32*) &nt.OptionalHeader; - pDataDirectory = &pNTHeader32->OptionalHeader.DataDirectory[0]; - } - else if (nt.OptionalHeader.Magic == IMAGE_NT_OPTIONAL_HDR64_MAGIC) - { - if (nt.FileHeader.SizeOfOptionalHeader != sizeof(IMAGE_OPTIONAL_HEADER64)) - return FALSE; - - IMAGE_NT_HEADERS64* pNTHeader64 = (IMAGE_NT_HEADERS64*) &nt.OptionalHeader; - pDataDirectory = &pNTHeader64->OptionalHeader.DataDirectory[0]; - } - else - return FALSE; - - if ((pDataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].VirtualAddress == 0) || - (pDataDirectory[IMAGE_DIRECTORY_ENTRY_COMHEADER].Size < sizeof(IMAGE_COR20_HEADER))) - { - return FALSE; - } - - return TRUE; -} - -void Zapper::SetContextInfo(LPCWSTR assemblyName) -{ - // A special case: If we're compiling CoreLib, ignore m_exeName and don't set any context. - // There can only be one CoreLib in the runtime, independent of any context. If we don't - // check for CoreLib, and isExe == true, then CompilationDomain::SetContextInfo will call - // into CoreLib and cause the resulting System.Private.CoreLib.ni.dll to be slightly different (checked - // build only). - if (assemblyName != NULL && _wcsnicmp(assemblyName, CoreLibName_W, CoreLibNameLen) == 0 && (wcslen(assemblyName) == CoreLibNameLen || assemblyName[CoreLibNameLen] == W(','))) - { - return; - } - - // Determine whether the root is an exe or a dll - - StackSString s(m_exeName); - - //These locals seem necessary for gcc do resolve the overload correctly - SString literalExe(SString::Literal, W(".exe")); - SString literalDll(SString::Literal, W(".dll")); - BOOL isExe = (s.GetCount() > 4) && s.MatchCaseInsensitive(s.End() - 4, literalExe); - BOOL isDll = (s.GetCount() > 4) && s.MatchCaseInsensitive(s.End() - 4, literalDll); - - DWORD attributes = WszGetFileAttributes(m_exeName); - if (attributes != INVALID_FILE_ATTRIBUTES) - { - if (isExe) - { - // If it's an exe, set it as the config - m_pDomain->SetContextInfo(m_exeName, TRUE); - } - else if ((attributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY) - { - // If it's a directory, set it as the default app base - m_pDomain->SetContextInfo(m_exeName, FALSE); - } - else if (isDll) - { - // If it's a dll, then set a default app base of the directory containing the dll - SString::Iterator i = s.End(); - if (s.FindBack(i, W("\\"))) - { - s.Truncate(i); - m_pDomain->SetContextInfo(s.GetUnicode(), FALSE); - } - } - } -} - -void Zapper::CreateDependenciesLookupDomainInCurrentDomain() -{ - SetContextInfo(); -} - - -void ZapperSetBindingPaths(ICorCompilationDomain *pDomain, SString &trustedPlatformAssemblies, SString &platformResourceRoots, SString &appPaths, SString &appNiPaths); - -void Zapper::CreateCompilationDomain() -{ - - BOOL fForceDebug = FALSE; - if (!m_pOpt->m_autodebug) - fForceDebug = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - - BOOL fForceProfile = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - BOOL fForceInstrument = m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - - InitEE(fForceDebug, fForceProfile, fForceInstrument); - - // Make a compilation domain for the assembly. Note that this will - // collect the assembly dependencies for use in the version info, as - // well as isolating the compilation code. - - IfFailThrow(m_pEECompileInfo->CreateDomain(&m_pDomain, - CreateAssemblyEmitter(), - fForceDebug, - fForceProfile, - fForceInstrument)); - - // we support only TPA binding on CoreCLR - - if (!m_trustedPlatformAssemblies.IsEmpty()) - { - // TPA-based binding - // Add the trusted paths and apppath to the binding list - ZapperSetBindingPaths(m_pDomain, m_trustedPlatformAssemblies, m_platformResourceRoots, m_appPaths, m_appNiPaths); - } -} - -void Zapper::CreateDependenciesLookupDomain() -{ - CreateCompilationDomain(); - CreateDependenciesLookupDomainInCurrentDomain(); -} - -void Zapper::CreatePdb(BSTR pAssemblyPathOrName, BSTR pNativeImagePath, BSTR pPdbPath, BOOL pdbLines, BSTR pManagedPdbSearchPath) -{ -#ifdef CROSSGEN_COMPILE - CreateCompilationDomain(); -#endif - - EX_TRY - { - CORINFO_ASSEMBLY_HANDLE hAssembly = NULL; - - IfFailThrow(m_pEECompileInfo->LoadAssemblyByPath( - pAssemblyPathOrName, - - // fExplicitBindToNativeImage: On the phone, a path to the NI is specified - // explicitly (even with .ni. in the name). All other callers specify a path to - // the IL, and the NI is inferred, so this is normally FALSE in those other - // cases. - TRUE, - - &hAssembly)); - - - // Ensure all modules belonging to this assembly get loaded. The CreatePdb() call - // below will iterate through them via the ModuleIterator to generate PDB files for each - // one, and the ModuleIterator assumes they've been loaded. - IMDInternalImport * pMDImport = m_pEECompileInfo->GetAssemblyMetaDataImport(hAssembly); - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtFile); - mdFile tkFile; - while (pMDImport->EnumNext(&hEnum, &tkFile)) - { - LPCSTR szName; - DWORD flags; - IfFailThrow(pMDImport->GetFileProps(tkFile, &szName, NULL, NULL, &flags)); - - if (!IsFfContainsMetaData(flags)) - continue; - - CORINFO_MODULE_HANDLE hModule; - IfFailThrow(m_pEECompileInfo->LoadAssemblyModule(hAssembly, - tkFile, &hModule)); - } - - LPCWSTR pDiasymreaderPath = nullptr; -#if !defined(NO_NGENPDB) - if (m_DiasymreaderPath.GetCount() > 0) - { - pDiasymreaderPath = m_DiasymreaderPath.GetUnicode(); - } -#endif //!defined(NO_NGENPDB) - - IfFailThrow(::CreatePdb(hAssembly, pNativeImagePath, pPdbPath, pdbLines, pManagedPdbSearchPath, pDiasymreaderPath)); - } - EX_CATCH - { - // Print the error message - - Error(W("Error generating PDB for '%s': "), pNativeImagePath); - PrintErrorMessage(CORZAP_LOGLEVEL_ERROR, GET_EXCEPTION()); - Error(W("\n")); - EX_RETHROW; - } - EX_END_CATCH(RethrowTerminalExceptions); -} - -void Zapper::ComputeDependencies(LPCWSTR pAssemblyName, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ -} - - -// -// Compile a module by name -// - -HRESULT Zapper::Compile(LPCWSTR string, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - HRESULT hr = S_OK; - - bool fCoreLib = false; - LPCWSTR fileName = PathFindFileName(string); - if (fileName != NULL && SString::_wcsicmp(fileName, g_pwBaseLibrary) == 0) - { - fCoreLib = true; - } - - - if (fCoreLib) - { - // - // Disallow use of native image to force a new native image generation for CoreLib - // - g_fAllowNativeImages = false; - } - - // the errors in CreateCompilationDomain are fatal - propogate them up - CreateCompilationDomain(); - - EX_TRY - { - CompileInCurrentDomain(string, pNativeImageSig); - } - EX_CATCH - { - // Print the error message - - Error(W("Error compiling %s: "), string); - PrintErrorMessage(CORZAP_LOGLEVEL_ERROR, GET_EXCEPTION()); - Error(W("\n")); - - hr = GET_EXCEPTION()->GetHR(); - } - EX_END_CATCH(SwallowAllExceptions); - - // the errors in DestroyDomain are fatal - propogate them up - DestroyDomain(); - - return hr; -} - -void Zapper::DontUseProfileData() -{ - // Call this before calling Compile() - - m_pOpt->m_ignoreProfileData = true; -} - -bool Zapper::HasProfileData() -{ - // Only valid after calling Compile() - return m_pOpt->m_fHasAnyProfileData; -} - -// Helper function for Zapper::Compile(LPCWSTR string) -// - -void Zapper::CompileInCurrentDomain(__in LPCWSTR string, CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - STATIC_CONTRACT_ENTRY_POINT; - - BEGIN_ENTRYPOINT_VOIDRET; - - - - // - // Load the assembly. - // - // "string" may be a path or assembly display name. - // To decide, we see if it is the name of a valid file. - // - - _ASSERTE(m_hAssembly == NULL); - - //without fusion, this has to be a file name - { - IfFailThrow(m_pEECompileInfo->LoadAssemblyByPath(string, FALSE /* fExplicitBindToNativeImage */, &m_hAssembly)); - } - - - // - // Compile the assembly - // - CompileAssembly(pNativeImageSig); - - goto Exit; // Avoid warning about unreferenced label - -Exit: - END_ENTRYPOINT_VOIDRET; - - return; -} - - -//------------------------------------------------------------------------------ - -// Is this is a valid file-system file name? - -bool StringHasLegalFileNameChars(LPCWSTR assemblyName) -{ - if (wcschr(assemblyName, ':') || wcschr(assemblyName, '/') || wcschr(assemblyName, '\\') || - wcschr(assemblyName, '*') || wcschr(assemblyName, '?') || wcschr(assemblyName, '"') || - wcschr(assemblyName, '<') || wcschr(assemblyName, '>') || wcschr(assemblyName, '|')) - return false; - - return true; -} - -IMetaDataAssemblyEmit * Zapper::CreateAssemblyEmitter() -{ - _ASSERTE(!m_pAssemblyEmit); - - // - // Make a manifest emitter for the zapped assembly. - // - - // Hardwire the metadata version to be the current runtime version so that the ngen image - // does not change when the directory runtime is installed in different directory (e.g. v2.0.x86chk vs. v2.0.80826). - BSTRHolder strVersion(SysAllocString(CLR_METADATA_VERSION_L)); - VARIANT versionOption; - V_VT(&versionOption) = VT_BSTR; - V_BSTR(&versionOption) = strVersion; - IfFailThrow(m_pMetaDataDispenser->SetOption(MetaDataRuntimeVersion, &versionOption)); - - IfFailThrow(m_pMetaDataDispenser->DefineScope(CLSID_CorMetaDataRuntime, - 0, IID_IMetaDataAssemblyEmit, - (IUnknown **) &m_pAssemblyEmit)); - - return m_pAssemblyEmit; -} - -void Zapper::InitializeCompilerFlags(CORCOMPILE_VERSION_INFO * pVersionInfo) -{ - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - m_pOpt->m_compilerFlags.Clear(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE); - - // We track debug info all the time in the ngen image - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - - if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_DEBUGGING) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE); - } - - if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_PROFILING) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_PROF_NO_PINVOKE_INLINE); - m_pOpt->m_ngenProfileImage = true; - } - - if (pVersionInfo->wCodegenFlags & CORCOMPILE_CODEGEN_PROF_INSTRUMENTING) - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_BBINSTR); - - // Set CORJIT_FLAG_MIN_OPT only if COMPlus_JitMinOpts == 1 - static ConfigDWORD g_jitMinOpts; - if (g_jitMinOpts.val(CLRConfig::UNSUPPORTED_JITMinOpts) == 1) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_MIN_OPT); - } - -#if defined(TARGET_X86) - - // @TODO: This is a copy of SetCpuInfo() in vm\codeman.cpp. Unify the implementaion - - switch (CPU_X86_FAMILY(pVersionInfo->cpuInfo.dwCPUType)) - { - case CPU_X86_PENTIUM_4: - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_TARGET_P4); - break; - - default: - break; - } - - if (CPU_X86_USE_CMOV(pVersionInfo->cpuInfo.dwFeatures)) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_CMOV); - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_USE_FCOMI); - } - -#endif // TARGET_X86 - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - // .NET Core requires SSE2. - m_pOpt->m_compilerFlags.Set(InstructionSet_X86Base); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE2); -#endif -#if defined(TARGET_ARM64) - m_pOpt->m_compilerFlags.Set(InstructionSet_ArmBase); - m_pOpt->m_compilerFlags.Set(InstructionSet_AdvSimd); -#endif - -#if defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) - // If we're crossgenning CoreLib, allow generating non-VEX intrinsics. The generated code might - // not actually be supported by the processor at runtime so we compensate for it by - // not letting the get_IsSupported method to be intrinsically expanded in crossgen - // (see special handling around CORINFO_FLG_JIT_INTRINSIC in ZapInfo). - // That way the actual support checks will always be jitted. - // We only do this for CoreLib because forgetting to wrap intrinsics under IsSupported - // checks can lead to illegal instruction traps (instead of a nice managed exception). - if (m_pEECompileInfo->GetAssemblyModule(m_hAssembly) == m_pEECompileInfo->GetLoaderModuleForCoreLib()) - { - m_pOpt->m_compilerFlags.Set(CORJIT_FLAGS::CORJIT_FLAG_FEATURE_SIMD); - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - m_pOpt->m_compilerFlags.Set(InstructionSet_AES); - m_pOpt->m_compilerFlags.Set(InstructionSet_PCLMULQDQ); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE3); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSSE3); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE41); - m_pOpt->m_compilerFlags.Set(InstructionSet_SSE42); - m_pOpt->m_compilerFlags.Set(InstructionSet_POPCNT); - // Leaving out InstructionSet_AVX, InstructionSet_FMA, InstructionSet_AVX2, - // InstructionSet_BMI1, InstructionSet_BMI2 on purpose - these require VEX encodings - // and the JIT doesn't support generating code for methods with mixed encodings. - // Also leaving out InstructionSet_LZCNT because BSR from InstructionSet_X86Base - // is used as a fallback in CoreLib and doesn't require an IsSupported check. -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) - } -#endif // defined(TARGET_X86) || defined(TARGET_AMD64) || defined(TARGET_ARM64) - m_pOpt->m_compilerFlags.Set64BitInstructionSetVariants(); - m_pOpt->m_compilerFlags.EnsureValidInstructionSetSupport(); - - if ( m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_INFO) - && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_DEBUG_CODE) - && m_pOpt->m_compilerFlags.IsSet(CORJIT_FLAGS::CORJIT_FLAG_PROF_ENTERLEAVE)) - { - // - // We've decided not to support debugging + optimizations disabled + profiling to - // cut down on the testing matrix, under the assertion that the combination isn't - // particularly common or useful. (It's still supported in normal jit mode though.) - // - - Error(W("The CLR doesn't support precompiled code when using both debugging and profiling") - W(" instrumentation.\n")); - ThrowHR(E_NOTIMPL); - } -} - -void Zapper::DefineOutputAssembly(SString& strAssemblyName, ULONG * pHashAlgId) -{ - mdAssembly tkAssembly; - IfFailThrow(m_pAssemblyImport->GetAssemblyFromScope(&tkAssembly)); - - AssemblyMetaDataInternal internalMetadata; - - const void *pbPublicKey; - ULONG cbPublicKey; - ULONG hashAlgId; - LPCSTR szAssemblyName; - DWORD flags; - - IfFailThrow(m_pAssemblyImport->GetAssemblyProps(tkAssembly, &pbPublicKey, &cbPublicKey, - &hashAlgId, &szAssemblyName, &internalMetadata, &flags)); - - strAssemblyName.SetUTF8(szAssemblyName); - - ASSEMBLYMETADATA metadata; - SString strLocale; - - metadata.usMajorVersion = internalMetadata.usMajorVersion; - metadata.usMinorVersion = internalMetadata.usMinorVersion; - metadata.usBuildNumber = internalMetadata.usBuildNumber; - metadata.usRevisionNumber = internalMetadata.usRevisionNumber; - if (internalMetadata.szLocale) - { - strLocale.SetUTF8(internalMetadata.szLocale); - metadata.szLocale = (LPWSTR)strLocale.GetUnicode(); - metadata.cbLocale = strLocale.GetCount() + 1; - } - else - { - metadata.szLocale = NULL; - metadata.cbLocale = 0; - } - metadata.rProcessor = NULL; - metadata.ulProcessor = 0; - metadata.rOS = NULL; - metadata.ulOS = 0; - - LPCWSTR wszAssemblyName = strAssemblyName.GetUnicode(); - - // If assembly name (and hence fileName) has invalid characters, - // GenerateFile() will fail later on. - // StringHasLegalFileNameChars is a ngen restriction. - - if (!StringHasLegalFileNameChars(wszAssemblyName)) - { - Error(W("Error: Assembly name \"%s\" contains illegal (unsupported) file name characters.\n"), wszAssemblyName); - ThrowHR(HRESULT_FROM_WIN32(ERROR_INVALID_NAME)); - } - -#ifndef TARGET_UNIX - // - // We always need a hash since our assembly module is separate from the manifest. - // Use MD5 by default. - // - - if (hashAlgId == 0) - hashAlgId = CALG_MD5; -#endif - - mdAssembly tkEmitAssembly; - IfFailThrow(m_pAssemblyEmit->DefineAssembly(pbPublicKey, cbPublicKey, hashAlgId, - wszAssemblyName, &metadata, - flags, &tkEmitAssembly)); - - *pHashAlgId = hashAlgId; -} - -// -// This is the main worker function (at the assembly level). -// -// Zapper::CompileInCurrentDomain() ends up calling this function. - -void Zapper::CompileAssembly(CORCOMPILE_NGEN_SIGNATURE * pNativeImageSig) -{ - _ASSERTE(m_pDomain != NULL); // This must be set up by this time. - _ASSERTE(m_hAssembly != NULL); - - CORINFO_MODULE_HANDLE hAssemblyModule = m_pEECompileInfo->GetAssemblyModule(m_hAssembly); - - CORCOMPILE_VERSION_INFO versionInfo; - - IfFailThrow(m_pEECompileInfo->GetAssemblyVersionInfo(m_hAssembly, - &versionInfo)); - - InitializeCompilerFlags(&versionInfo); - - // - // Set up the output path. - // - - // - // If we don't have fusion, we just create the file right at the target. No need to do an install. - // - { - SString strAssemblyPath = GetOutputFileName(); - - if (strAssemblyPath.IsEmpty()) - { - m_pEECompileInfo->GetModuleFileName(hAssemblyModule, strAssemblyPath); - } - - const WCHAR * assemblyPath = strAssemblyPath.GetUnicode(); - const WCHAR * pathend = wcsrchr( assemblyPath, DIRECTORY_SEPARATOR_CHAR_W ); - if( pathend ) - { - m_outputPath.Set(assemblyPath, COUNT_T(pathend - assemblyPath)); - } - else - { - m_outputPath.Set(W(".") DIRECTORY_SEPARATOR_STR_W); - } - } - - // - // Get the manifest metadata. - // - - m_pAssemblyImport = m_pEECompileInfo->GetAssemblyMetaDataImport(m_hAssembly); - - // - // Copy the relevant assembly info to the zap manifest - // - - SString strAssemblyName; - ULONG hashAlgId; - DefineOutputAssembly(strAssemblyName, &hashAlgId); - - SString strNativeImagePath; - SString strNativeImageTempPath; - HANDLE hFile = INVALID_HANDLE_VALUE; - StackSArray hFiles; - - { - // - // Compile the manifest module (if manifest is not stand-alone). - // - - NewHolder pAssemblyModule; - - pAssemblyModule = CompileModule(hAssemblyModule, m_pAssemblyEmit); - - // - // The loader (currently) requires all modules of an ngen-ed multi-module - // assembly to be ngen-ed. - // - - - // - // Record the version info - // - - pAssemblyModule->SetVersionInfo(&versionInfo); - - // - // Record Dependencies - // - - if (!IsReadyToRunCompilation()) - { - CORCOMPILE_DEPENDENCY *pDependencies; - DWORD cDependencies; - IfFailThrow(m_pDomain->GetDependencies(&pDependencies, &cDependencies)); - - pAssemblyModule->SetDependencies(pDependencies, cDependencies); - } - - // Write the main assembly module - strNativeImagePath = GetOutputFileName(); - - if (strNativeImagePath.IsEmpty()) - { - strNativeImagePath.Set(m_outputPath, SL(DIRECTORY_SEPARATOR_STR_W), strAssemblyName, - pAssemblyModule->m_ModuleDecoder.IsDll() ? SL(W(".ni.dll")) : SL(W(".ni.exe"))); - } - - pAssemblyModule->SetPdbFileName(SString(strAssemblyName, SL(W(".ni.pdb")))); - - strNativeImageTempPath = strNativeImagePath; - strNativeImageTempPath.Append(W(".tmp")); - - hFile = pAssemblyModule->SaveImage(strNativeImageTempPath.GetUnicode(), strNativeImagePath.GetUnicode(), pNativeImageSig); - } - - // Throw away the assembly if we have hit fatal error during compilation - if (FAILED(g_hrFatalError)) - ThrowHR(g_hrFatalError); - - - // Close the file - CloseHandle(hFile); - for (SArray::Iterator i = hFiles.Begin(); i != hFiles.End(); ++i) - { - CloseHandle(*i); - } - - if (!WszMoveFileEx(strNativeImageTempPath.GetUnicode(), strNativeImagePath.GetUnicode(), MOVEFILE_REPLACE_EXISTING)) - { - ThrowLastError(); - } - - if (!m_pOpt->m_silent) - { - GetSvcLogger()->Printf(W("Native image %s generated successfully.\n"), strNativeImagePath.GetUnicode()); - } - -} - - -ZapImage * Zapper::CompileModule(CORINFO_MODULE_HANDLE hModule, - IMetaDataAssemblyEmit *pAssemblyEmit) -{ - NewHolder module; - - BYTE * pMemory = new BYTE[sizeof(ZapImage)]; - ZeroMemory(pMemory, sizeof(ZapImage)); - - module = new (pMemory) ZapImage(this); - - // Finish initializing the ZapImage object - // any calls that could throw an exception are done in ZapImage::Initialize() - // - module->ZapWriter::Initialize(); - - // - // Set target - // - - IfFailThrow(m_pEECompileInfo->SetCompilationTarget(m_hAssembly, hModule)); - - // - // Open input file - // - - Info(W("Opening input file\n")); - - module->Open(hModule, pAssemblyEmit); - - // - // input module. - // - - Info(W("Preloading input file %s\n"), module->m_pModuleFileName); - - module->Preload(); - - // - // Compile input module - // - - Info(W("Compiling input file %s\n"), module->m_pModuleFileName); - - module->Compile(); - - if (!IsReadyToRunCompilation()) - { - // - // Link preloaded module. - // - - Info(W("Linking preloaded input file %s\n"), module->m_pModuleFileName); - - module->LinkPreload(); - } - return module.Extract(); -} - - -void Zapper::Success(LPCWSTR format, ...) -{ - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_SUCCESS, format, args); - - va_end(args); -} - -void Zapper::Error(LPCWSTR format, ...) -{ - // Preserve last error so we can still do ThrowLastError() after printing the message - DWORD err = GetLastError(); - - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_ERROR, format, args); - - va_end(args); - - SetLastError(err); -} - -void Zapper::Warning(LPCWSTR format, ...) -{ - // Preserve last error so we can still do ThrowLastError() after printing the message - DWORD err = GetLastError(); - - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_WARNING, format, args); - - va_end(args); - - SetLastError(err); -} - -void Zapper::Info(LPCWSTR format, ...) -{ - va_list args; - va_start(args, format); - - Print(CORZAP_LOGLEVEL_INFO, format, args); - - va_end(args); -} - -void Zapper::Print(CorZapLogLevel level, LPCWSTR format, ...) -{ - va_list args; - va_start(args, format); - - Print(level, format, args); - - va_end(args); -} - -void Zapper::Print(CorZapLogLevel level, LPCWSTR format, va_list args) -{ - const int BUFF_SIZE = 1024; - WCHAR output[BUFF_SIZE]; - - switch (level) - { - case CORZAP_LOGLEVEL_INFO: - if (!m_pOpt->m_verbose) - return; - break; - - case CORZAP_LOGLEVEL_ERROR: - case CORZAP_LOGLEVEL_WARNING: - break; - - case CORZAP_LOGLEVEL_SUCCESS: - if (m_pOpt->m_silent) - return; - break; - } - - CorSvcLogLevel logLevel = (CorSvcLogLevel)0; - switch (level) - { - case CORZAP_LOGLEVEL_INFO: - logLevel = LogLevel_Info; - break; - - case CORZAP_LOGLEVEL_ERROR: - logLevel = LogLevel_Error; - break; - - case CORZAP_LOGLEVEL_WARNING: - logLevel = LogLevel_Warning; - break; - - case CORZAP_LOGLEVEL_SUCCESS: - logLevel = LogLevel_Success; - break; - } - - _vsnwprintf_s(output, BUFF_SIZE, BUFF_SIZE - 1, format, args); - output[BUFF_SIZE-1] = 0; - - GetSvcLogger()->Log(output, logLevel); -} - -void Zapper::PrintErrorMessage(CorZapLogLevel level, Exception *ex) -{ - StackSString message; - ex->GetMessage(message); - Print(level, W("%s"), message.GetUnicode()); -} - -void Zapper::PrintErrorMessage(CorZapLogLevel level, HRESULT hr) -{ - StackSString message; - GetHRMsg(hr, message); - Print(level, W("%s"), message.GetUnicode()); -} - -#if !defined(FEATURE_MERGE_JIT_AND_ENGINE) -void Zapper::SetCLRJITPath(LPCWSTR pwszCLRJITPath) -{ - m_CLRJITPath.Set(pwszCLRJITPath); -} - -void Zapper::SetDontLoadJit() -{ - m_fDontLoadJit = true; -} -#endif // !defined(FEATURE_MERGE_JIT_AND_ENGINE) - -#if !defined(NO_NGENPDB) -void Zapper::SetDiasymreaderPath(LPCWSTR pwzDiasymreaderPath) -{ - m_DiasymreaderPath.Set(pwzDiasymreaderPath); -} -#endif // !defined(NO_NGENPDB) - - -void Zapper::SetPlatformAssembliesPaths(LPCWSTR pwzPlatformAssembliesPaths) -{ - m_platformAssembliesPaths.Set(pwzPlatformAssembliesPaths); -} - -void Zapper::SetTrustedPlatformAssemblies(LPCWSTR pwzTrustedPlatformAssemblies) -{ - m_trustedPlatformAssemblies.Set(pwzTrustedPlatformAssemblies); -} - -void Zapper::SetPlatformResourceRoots(LPCWSTR pwzPlatformResourceRoots) -{ - m_platformResourceRoots.Set(pwzPlatformResourceRoots); -} - -void Zapper::SetAppPaths(LPCWSTR pwzAppPaths) -{ - m_appPaths.Set(pwzAppPaths); -} - -void Zapper::SetAppNiPaths(LPCWSTR pwzAppNiPaths) -{ - m_appNiPaths.Set(pwzAppNiPaths); -} - -void Zapper::SetOutputFilename(LPCWSTR pwzOutputFilename) -{ - m_outputFilename.Set(pwzOutputFilename); -} - - -SString Zapper::GetOutputFileName() -{ - return m_outputFilename; -} - - -void Zapper::SetCustomBaseAddress(SIZE_T baseAddress) -{ - m_customBaseAddress = baseAddress; -} - -SIZE_T Zapper::GetCustomBaseAddress() -{ - return m_customBaseAddress; -} diff --git a/src/coreclr/zap/zapperstats.cpp b/src/coreclr/zap/zapperstats.cpp deleted file mode 100644 index 9379cd39239968..00000000000000 --- a/src/coreclr/zap/zapperstats.cpp +++ /dev/null @@ -1,246 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/* - - */ - - -#include "common.h" - -namespace -{ -// some helper functions -// - -template < typename T > -void init_array( T * arr, size_t size ) -{ - ::ZeroMemory( arr, size * sizeof( T ) ); -} - - -// locals -// - -const char * const fixupNames[] = -{ - "Class Handle", - "Field Handle", - "Method Handle", - "Function Call/Pointer", - "Sync", - "Pinvoke", - "Profiling Handle", - "Interface Table", - "Module Handle", - "Module Domain ID", - "Class Domain ID", - "Field Address", - "Varargs Handle", - "String", - "Init Class", - "Load Class", - "Stub Dispatch", - "Active Dependency" -}; - -const char * const callReasons[] = -{ - "Unknown", - "Exotic (Not IL or ECall)", - "PInvoke", - "Has Generic Instantiation", - "No code generated yet", - "Method has fixups", - "Prestub may produce stub", - "Remoting interception", - "Contains Cer root", - "Restore method (Generics)", - "Restore first call", - "Restore value type", - "Restore", - "Can't patch", - "Profiling", - "Other loader module", -}; - -static_assert_no_msg((sizeof(callReasons)/sizeof(callReasons[0])) == CORINFO_INDIRECT_CALL_COUNT); - -} - -ZapperStats::ZapperStats() - : m_methods( 0 ) - , m_failedMethods( 0 ) - , m_failedILStubs( 0 ) - , m_ilCodeSize( 0 ) - , m_nativeCodeSize( 0 ) - , m_nativeColdCodeSize( 0 ) - , m_nativeRODataSize( 0 ) - , m_gcInfoSize( 0 ) -#ifdef FEATURE_EH_FUNCLETS - , m_unwindInfoSize( 0 ) -#endif // FEATURE_EH_FUNCLETS - , m_NumHotAllocations( 0 ) - , m_NumHotColdAllocations( 0 ) - , m_NumMediumHeaders( 0 ) - , m_nativeCodeSizeInSplitMethods( 0 ) - , m_nativeColdCodeSizeInSplitMethods( 0 ) - , m_nativeCodeSizeInSplitProfiledMethods( 0 ) - , m_nativeColdCodeSizeInSplitProfiledMethods( 0 ) - , m_nativeCodeSizeInProfiledMethods( 0 ) - , m_nativeColdCodeSizeInProfiledMethods( 0 ) - , m_totalHotCodeSize( 0 ) - , m_totalUnprofiledCodeSize( 0 ) - , m_totalColdCodeSize( 0 ) - , m_totalCodeSizeInProfiledMethods( 0 ) - , m_totalColdCodeSizeInProfiledMethods( 0 ) - , m_inputFileSize( 0 ) - , m_outputFileSize( 0 ) - , m_metadataSize( 0 ) - , m_preloadImageSize( 0 ) - , m_hotCodeMgrSize( 0 ) - , m_unprofiledCodeMgrSize( 0 ) - , m_coldCodeMgrSize( 0 ) - , m_eeInfoTableSize( 0 ) - , m_helperTableSize( 0 ) - , m_dynamicInfoTableSize( 0 ) - , m_dynamicInfoDelayListSize( 0 ) - , m_debuggingTableSize( 0 ) - , m_headerSectionSize( 0 ) - , m_codeSectionSize( 0 ) - , m_coldCodeSectionSize( 0 ) - , m_exceptionSectionSize( 0 ) - , m_readOnlyDataSectionSize( 0 ) - , m_relocSectionSize( 0 ) - , m_ILMetadataSize( 0 ) - , m_externalMethodThunkSize( 0 ) - , m_externalMethodDataSize( 0 ) - , m_prestubMethods( 0 ) - , m_directMethods( 0 ) -{ - init_array( m_indirectMethodReasons, CORINFO_INDIRECT_CALL_COUNT ); -} - -#ifdef _PREFAST_ -#pragma warning(push) -#pragma warning(disable:21000) // Suppress PREFast warning about overly large function -#endif -void ZapperStats::PrintStats() -{ - if (m_outputFileSize > 0) { - - GetSvcLogger()->Printf( "-------------------------------------------------------\n"); - GetSvcLogger()->Printf( "Input file size: %8d\n", m_inputFileSize); - GetSvcLogger()->Printf( "Output file size: %8d\n", m_outputFileSize); - GetSvcLogger()->Printf( "Input file size/Output file size ratio:\t%8.2fx\n", double( m_outputFileSize ) / m_inputFileSize); - GetSvcLogger()->Printf( "\n"); - GetSvcLogger()->Printf( "Metadata: %8d\t%8.2f%%\n", m_metadataSize, (double)m_metadataSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Debugging maps: %8d\t%8.2f%%\n", m_debuggingTableSize, (double)m_debuggingTableSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Hot Code manager: %8d\t%8.2f%%\n", m_hotCodeMgrSize, (double)m_hotCodeMgrSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Unprofiled Code manager: %8d\t%8.2f%%\n", m_unprofiledCodeMgrSize, (double)m_unprofiledCodeMgrSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Cold Code manager: %8d\t%8.2f%%\n", m_coldCodeMgrSize, (double)m_coldCodeMgrSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "GC info: %8d\t%8.2f%%\n", m_headerSectionSize, (double)m_headerSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Native code & r/o data: %8d\t%8.2f%%\n", m_codeSectionSize, (double)m_codeSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Cold code: %8d\t%8.2f%%\n", m_coldCodeSectionSize, (double)m_coldCodeSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Exception tables: %8d\t%8.2f%%\n", m_exceptionSectionSize, (double)m_exceptionSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Relocs: %8d\t%8.2f%%\n", m_relocSectionSize, (double)m_relocSectionSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "IL metadata: %8d\t%8.2f%%\n", m_ILMetadataSize, (double)m_ILMetadataSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "External Method Thunks: %8d\t%8.2f%%\n", m_externalMethodThunkSize, (double)m_externalMethodThunkSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "External Method Data: %8d\t%8.2f%%\n", m_externalMethodDataSize, (double)m_externalMethodDataSize/m_outputFileSize*100); - GetSvcLogger()->Printf( "Image of EE structures: %8d\t%8.2f%%\n", m_preloadImageSize, (double)m_preloadImageSize/m_outputFileSize*100); - - unsigned totalIndirections = - m_dynamicInfoDelayListSize + - m_eeInfoTableSize + - m_helperTableSize + - m_dynamicInfoTableSize; - - GetSvcLogger()->Printf( "Indirections: %8d\t%8.2f%%\n", - totalIndirections, (double)totalIndirections/m_outputFileSize*100); - GetSvcLogger()->Printf( " ----- Breakdown of Indirections ----\n"); - - GetSvcLogger()->Printf( " Delay load lists: %8d\t%8.2f%%\n", - m_dynamicInfoDelayListSize, (double)m_dynamicInfoDelayListSize/totalIndirections*100); - GetSvcLogger()->Printf( " Tables: %8d\t%8.2f%%\n", - m_dynamicInfoTableSize, (double)m_dynamicInfoTableSize/totalIndirections*100); - GetSvcLogger()->Printf( " EE Values: %8d\t%8.2f%%\n", - m_eeInfoTableSize, (double)m_eeInfoTableSize/totalIndirections*100); - GetSvcLogger()->Printf( " Helper functions: %8d\t%8.2f%%\n", - m_helperTableSize, (double)m_helperTableSize/totalIndirections*100); - } - - GetSvcLogger()->Printf( " Direct method descs:\t%5d/%5d %8.2f%%\n", - m_directMethods, m_prestubMethods+m_directMethods, - (double)m_directMethods/(m_directMethods+m_prestubMethods)*100); - GetSvcLogger()->Printf( " Indirect method descs:\t%5d/%5d %8.2f%%\n", - m_prestubMethods, m_prestubMethods+m_directMethods, - (double)m_prestubMethods/(m_directMethods+m_prestubMethods)*100); - - for (int i=0; i < CORINFO_INDIRECT_CALL_COUNT; i++) - GetSvcLogger()->Printf( " %-30s %5d %8.2f%%\n", - callReasons[i], - m_indirectMethodReasons[i], - double(m_indirectMethodReasons[i])/(m_directMethods+m_prestubMethods)*100); - - GetSvcLogger()->Printf( "-------------------------------------------------------\n"); - GetSvcLogger()->Printf( "Total Methods: \t\t\t\t%8d\n", m_methods); - GetSvcLogger()->Printf( "Total Hot Only: \t\t\t%8d\n", m_NumHotAllocations); - GetSvcLogger()->Printf( "Total Split (Hot/Cold): \t\t%8d\n", m_NumHotColdAllocations); - GetSvcLogger()->Printf( "Total Medium Headers: \t\t\t%8d\n", m_NumMediumHeaders); - GetSvcLogger()->Printf( "Split Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInSplitMethods); - GetSvcLogger()->Printf( "Split Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInSplitMethods); - GetSvcLogger()->Printf( "Split Profiled Methods: Hot Code \t%8d\n", m_nativeCodeSizeInSplitProfiledMethods); - GetSvcLogger()->Printf( "Split Profiled Methods: Cold Code \t%8d\n", m_nativeColdCodeSizeInSplitProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Hot Code \t\t%8d\n", m_nativeCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Cold Code \t\t%8d\n", m_nativeColdCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Total Hot Code+Headers %7d\n", m_totalCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "Profiled Methods: Total Cold Code+Headers %6d\n", m_totalColdCodeSizeInProfiledMethods); - GetSvcLogger()->Printf( "All Methods: Total Hot+Unprofiled Code \t\t%8d\n", m_nativeCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Cold Code \t\t%8d\n", m_nativeColdCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Hot Code+Headers \t%8d\n", m_totalHotCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Unprofiled Code+Headers \t%8d\n", m_totalUnprofiledCodeSize); - GetSvcLogger()->Printf( "All Methods: Total Cold Code+Headers \t%8d\n", m_totalColdCodeSize); - - GetSvcLogger()->Printf( "-------------------------------------------------------\n"); - GetSvcLogger()->Printf( "Total IL Code: %8d\n", m_ilCodeSize); - GetSvcLogger()->Printf( "Total Native Code: %8d\n", m_nativeCodeSize + m_nativeColdCodeSize); - GetSvcLogger()->Printf( "Total Code+Headers: %8d\n", m_totalHotCodeSize + m_totalUnprofiledCodeSize + m_totalColdCodeSize); - - GetSvcLogger()->Printf( "Total Native RO Data: %8d\n", m_nativeRODataSize); - GetSvcLogger()->Printf( "Total Native GC Info: %8d\n", m_gcInfoSize); - size_t nativeTotal = m_nativeCodeSize + m_nativeRODataSize + m_gcInfoSize; -#ifdef FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Total Native UnwindInfo:%8d\n", m_unwindInfoSize); - nativeTotal += m_unwindInfoSize; -#endif // FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Total Native Total : %8d\n", nativeTotal); - - if (m_methods > 0) { - GetSvcLogger()->Printf( "\n"); - GetSvcLogger()->Printf( "Average IL Code: %8.2f\n", double(m_ilCodeSize) / m_methods); - GetSvcLogger()->Printf( "Average NativeCode: %8.2f\n", double(m_nativeCodeSize) / m_methods); - GetSvcLogger()->Printf( "Average Native RO Data: %8.2f\n", double(m_nativeRODataSize) / m_methods); - GetSvcLogger()->Printf( "Average Native GC Info: %8.2f\n", double(m_gcInfoSize) / m_methods); -#ifdef FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Average Native UnwindInfo: %8.2f\n", double(m_unwindInfoSize) / m_methods); -#endif // FEATURE_EH_FUNCLETS - GetSvcLogger()->Printf( "Average Native: %8.2f\n", double(nativeTotal) / m_methods); - GetSvcLogger()->Printf( "\n"); - GetSvcLogger()->Printf( "NativeGC / Native: %8.2f\n", double(m_gcInfoSize) / nativeTotal); - GetSvcLogger()->Printf( "Native / IL: %8.2f\n", double(nativeTotal) / m_ilCodeSize); - } - - if (m_failedMethods > 0) - GetSvcLogger()->Printf( "Methods which did not compile: %d\n", m_failedMethods); - if (m_failedILStubs > 0) - GetSvcLogger()->Printf( "IL STUBS which did not compile: %d\n", m_failedILStubs); -} -#ifdef _PREFAST_ -#pragma warning(pop) -#endif - -char const * GetCallReasonString( CorInfoIndirectCallReason reason ) -{ - return callReasons[ reason ]; -} diff --git a/src/coreclr/zap/zapperstats.h b/src/coreclr/zap/zapperstats.h deleted file mode 100644 index 585b1bdd0e28a4..00000000000000 --- a/src/coreclr/zap/zapperstats.h +++ /dev/null @@ -1,91 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -/* - - */ - - -#ifndef ZAPPER_STATS_H_0170123740208327 -#define ZAPPER_STATS_H_0170123740208327 - -#include "sarray.h" -#include "sstring.h" -#include "corcompile.h" -#include "arraylist.h" -#include "log.h" -#include "shash.h" -#include "utilcode.h" - - -// forward declarations -class ZapperOptions; - -class ZapperStats -{ - public: - - unsigned m_methods; // Total number of methods - unsigned m_failedMethods; // Methods which failed to compile correctly - unsigned m_failedILStubs; // ILSTUB methods which failed to compile correctly - - ULONG m_ilCodeSize; - ULONG m_nativeCodeSize; // Really just the Hot Code Size + Unprofiled size - ULONG m_nativeColdCodeSize; - ULONG m_nativeRODataSize; - ULONG m_gcInfoSize; -#ifdef FEATURE_EH_FUNCLETS - ULONG m_unwindInfoSize; -#endif // FEATURE_EH_FUNCLETS - - ULONG m_NumHotAllocations; - ULONG m_NumHotColdAllocations; - ULONG m_NumMediumHeaders; - - ULONG m_nativeCodeSizeInSplitMethods; - ULONG m_nativeColdCodeSizeInSplitMethods; - ULONG m_nativeCodeSizeInSplitProfiledMethods; - ULONG m_nativeColdCodeSizeInSplitProfiledMethods; - ULONG m_nativeCodeSizeInProfiledMethods; - ULONG m_nativeColdCodeSizeInProfiledMethods; - ULONG m_totalHotCodeSize; - ULONG m_totalUnprofiledCodeSize; - ULONG m_totalColdCodeSize; - ULONG m_totalCodeSizeInProfiledMethods; - ULONG m_totalColdCodeSizeInProfiledMethods; - - unsigned m_inputFileSize; - unsigned m_outputFileSize; - unsigned m_metadataSize; - unsigned m_preloadImageSize; - unsigned m_hotCodeMgrSize; - unsigned m_unprofiledCodeMgrSize; - unsigned m_coldCodeMgrSize; - unsigned m_eeInfoTableSize; - unsigned m_helperTableSize; - unsigned m_dynamicInfoTableSize; - unsigned m_dynamicInfoDelayListSize; - unsigned m_debuggingTableSize; - unsigned m_headerSectionSize; - unsigned m_codeSectionSize; - unsigned m_coldCodeSectionSize; - unsigned m_exceptionSectionSize; - unsigned m_readOnlyDataSectionSize; - unsigned m_relocSectionSize; - unsigned m_ILMetadataSize; - unsigned m_virtualImportThunkSize; - unsigned m_externalMethodThunkSize; - unsigned m_externalMethodDataSize; - - unsigned m_prestubMethods; - unsigned m_directMethods; - unsigned m_indirectMethodReasons[CORINFO_INDIRECT_CALL_COUNT]; - - ZapperStats(); - void PrintStats(); -}; - -char const * GetCallReasonString( CorInfoIndirectCallReason reason ); - -#endif // ZAPPER_STATS_H_0170123740208327 - diff --git a/src/coreclr/zap/zapreadytorun.cpp b/src/coreclr/zap/zapreadytorun.cpp deleted file mode 100644 index e5e0a236e44319..00000000000000 --- a/src/coreclr/zap/zapreadytorun.cpp +++ /dev/null @@ -1,874 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapReadyToRun.cpp -// - -// -// Zapping of ready-to-run specific structures -// -// ====================================================================================== - -#include "common.h" - -#include "zapreadytorun.h" - -#include "zapimport.h" - -#include "nativeformatwriter.h" - -#include "nibblestream.h" - -#include "../vm/typehashingalgorithms.h" -#include "../vm/nativeformatreader.h" - -using namespace NativeFormat; - -void ZapReadyToRunHeader::Save(ZapWriter * pZapWriter) -{ - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - - READYTORUN_HEADER readyToRunHeader; - - ZeroMemory(&readyToRunHeader, sizeof(readyToRunHeader)); - - readyToRunHeader.Signature = READYTORUN_SIGNATURE; - readyToRunHeader.MajorVersion = READYTORUN_MAJOR_VERSION; - readyToRunHeader.MinorVersion = READYTORUN_MINOR_VERSION; - - if (pImage->m_ModuleDecoder.IsPlatformNeutral()) - readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_PLATFORM_NEUTRAL_SOURCE; - - // If all types loaded succesfully, set a flag to skip type loading sanity checks at runtime - if (pImage->GetCompileInfo()->AreAllClassesFullyLoaded(pImage->GetModuleHandle())) - readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_SKIP_TYPE_VALIDATION; - - if (pImage->GetZapperOptions()->m_fPartialNGen) - readyToRunHeader.CoreHeader.Flags |= READYTORUN_FLAG_PARTIAL; - - readyToRunHeader.CoreHeader.NumberOfSections = m_Sections.GetCount(); - - pZapWriter->Write(&readyToRunHeader, sizeof(readyToRunHeader)); - - qsort(&m_Sections[0], m_Sections.GetCount(), sizeof(Section), SectionCmp); - - for(COUNT_T i = 0; i < m_Sections.GetCount(); i++) - { - READYTORUN_SECTION section; - section.Type = m_Sections[i].type; - ZapWriter::SetDirectoryData(§ion.Section, m_Sections[i].pSection); - pZapWriter->Write(§ion, sizeof(section)); - } -} - -class BlobVertex : public NativeFormat::Vertex -{ - int m_cbSize; - -public: - BlobVertex(int cbSize) - : m_cbSize(cbSize) - { - } - - void * GetData() - { - return this + 1; - } - - int GetSize() - { - return m_cbSize; - } - - virtual void Save(NativeWriter * pWriter) - { - byte * pData = (byte *)GetData(); - for (int i = 0; i < m_cbSize; i++) - pWriter->WriteByte(pData[i]); - } -}; - -class BlobVertexKey -{ - PVOID _pData; - int _cbSize; - -public: - BlobVertexKey(PVOID pData, int cbSize) - : _pData(pData), _cbSize(cbSize) - { - } - - void * GetData() - { - return _pData; - } - - int GetSize() - { - return _cbSize; - } -}; - -class BlobVertexSHashTraits : public DefaultSHashTraits -{ -public: - typedef BlobVertexKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return key_t(e->GetData(), e->GetSize()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - if (k1.GetSize() != k2.GetSize()) - return FALSE; - return memcmp(k1.GetData(), k2.GetData(), k1.GetSize()) == 0; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - count_t hash = 5381 + (count_t)(k.GetSize() << 7); - - PBYTE pbData = (PBYTE)k.GetData(); - PBYTE pbDataEnd = pbData + k.GetSize(); - - for (/**/ ; pbData < pbDataEnd; pbData++) - { - hash = ((hash << 5) + hash) ^ *pbData; - } - return hash; - } -}; - - -class EntryPointVertex : public NativeFormat::Vertex -{ - DWORD m_methodIndex; - BlobVertex * m_pFixups; - -public: - EntryPointVertex(DWORD methodIndex, BlobVertex * pFixups) - : m_methodIndex(methodIndex), m_pFixups(pFixups) - { - } - - virtual void Save(NativeWriter * pWriter) - { - if (m_pFixups != NULL) - { - int existingOffset = pWriter->GetCurrentOffset(m_pFixups); - if (existingOffset != -1) - { - pWriter->WriteUnsigned((m_methodIndex << 2) | 3); - pWriter->WriteUnsigned(pWriter->GetCurrentOffset() - existingOffset); - } - else - { - pWriter->WriteUnsigned((m_methodIndex << 2) | 1); - pWriter->SetCurrentOffset(m_pFixups); - m_pFixups->Save(pWriter); - } - } - else - { - pWriter->WriteUnsigned(m_methodIndex << 1); - } - } -}; - -class EntryPointWithBlobVertex : public EntryPointVertex -{ - BlobVertex * m_pBlob; - -public: - EntryPointWithBlobVertex(DWORD methodIndex, BlobVertex * pFixups, BlobVertex * pBlob) - : EntryPointVertex(methodIndex, pFixups), m_pBlob(pBlob) - { - } - - virtual void Save(NativeWriter * pWriter) - { - m_pBlob->Save(pWriter); - EntryPointVertex::Save(pWriter); - } -}; - -void ZapImage::OutputEntrypointsTableForReadyToRun() -{ - BeginRegion(CORINFO_REGION_COLD); - - NativeWriter arrayWriter; - NativeWriter hashtableWriter; - - NativeSection * pArraySection = arrayWriter.NewSection(); - NativeSection * pHashtableSection = hashtableWriter.NewSection(); - - VertexArray vertexArray(pArraySection); - pArraySection->Place(&vertexArray); - VertexHashtable vertexHashtable; - pHashtableSection->Place(&vertexHashtable); - - bool fEmpty = true; - - SHash< NoRemoveSHashTraits < BlobVertexSHashTraits > > fixupBlobs; - - COUNT_T nCount = m_MethodCompilationOrder.GetCount(); - for (COUNT_T i = 0; i < nCount; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - - BlobVertex * pFixupBlob = NULL; - - if (pMethod->m_pFixupList != NULL) - { - NibbleWriter writer; - m_pImportTable->PlaceFixups(pMethod->m_pFixupList, writer); - - DWORD cbBlob; - PVOID pBlob = writer.GetBlob(&cbBlob); - - pFixupBlob = fixupBlobs.Lookup(BlobVertexKey(pBlob, cbBlob)); - if (pFixupBlob == NULL) - { - void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob]; - pFixupBlob = new (pMemory) BlobVertex(cbBlob); - memcpy(pFixupBlob->GetData(), pBlob, cbBlob); - - fixupBlobs.Add(pFixupBlob); - } - } - - CORINFO_SIG_INFO sig; - GetJitInfo()->getMethodSig(pMethod->GetHandle(), &sig); - - mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(pMethod->GetHandle()); - int rid = RidFromToken(token); - - if (sig.sigInst.classInstCount > 0 || sig.sigInst.methInstCount > 0) - { - _ASSERTE(rid != 0); - - CORINFO_MODULE_HANDLE module = GetJitInfo()->getClassModule(pMethod->GetClassHandle()); - _ASSERTE(GetCompileInfo()->IsInCurrentVersionBubble(module)); - SigBuilder sigBuilder; - CORINFO_RESOLVED_TOKEN resolvedToken = {}; - resolvedToken.tokenScope = module; - resolvedToken.token = token; - resolvedToken.hClass = pMethod->GetClassHandle(); - resolvedToken.hMethod = pMethod->GetHandle(); - GetCompileInfo()->EncodeMethod(module, pMethod->GetHandle(), &sigBuilder, m_pImportTable, EncodeModuleHelper, &resolvedToken); - - DWORD cbBlob; - PVOID pBlob = sigBuilder.GetSignature(&cbBlob); - void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob]; - BlobVertex * pSigBlob = new (pMemory) BlobVertex(cbBlob); - memcpy(pSigBlob->GetData(), pBlob, cbBlob); - - int dwHash = GetCompileInfo()->GetVersionResilientMethodHashCode(pMethod->GetHandle()); - vertexHashtable.Append(dwHash, pHashtableSection->Place(new (GetHeap()) EntryPointWithBlobVertex(pMethod->GetMethodIndex(), pFixupBlob, pSigBlob))); - } - else - { - int rid = RidFromToken(token); - if (rid != 0) - { - vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob)); - } - else - { - // This is a p/invoke stub, get the list of methods associated with the stub, and put this code in that set of rids - void *targetMethodEnum; - BOOL isStubWithTargetMethods = GetCompileInfo()->EnumMethodsForStub(pMethod->GetHandle(), &targetMethodEnum); - _ASSERTE(isStubWithTargetMethods); - - CORINFO_METHOD_HANDLE hTargetMethod; - while (GetCompileInfo()->EnumNextMethodForStub(targetMethodEnum, &hTargetMethod)) - { - mdMethodDef token = GetJitInfo()->getMethodDefFromMethod(hTargetMethod); - int rid = RidFromToken(token); - _ASSERTE(rid != 0); - vertexArray.Set(rid - 1, new (GetHeap()) EntryPointVertex(pMethod->GetMethodIndex(), pFixupBlob)); - } - - GetCompileInfo()->EnumCloseForStubEnumerator(targetMethodEnum); - } - } - - fEmpty = false; - } - - if (fEmpty) - return; - - vertexArray.ExpandLayout(); - - vector& arrayBlob = arrayWriter.Save(); - ZapNode * pArrayBlob = ZapBlob::NewBlob(this, &arrayBlob[0], arrayBlob.size()); - m_pCodeMethodDescsSection->Place(pArrayBlob); - - vector& hashtableBlob = hashtableWriter.Save(); - ZapNode * pHashtableBlob = ZapBlob::NewBlob(this, &hashtableBlob[0], hashtableBlob.size()); - m_pCodeMethodDescsSection->Place(pHashtableBlob); - - ZapReadyToRunHeader * pReadyToRunHeader = GetReadyToRunHeader(); - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::MethodDefEntryPoints, pArrayBlob); - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::InstanceMethodEntryPoints, pHashtableBlob); - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::RuntimeFunctions, m_pRuntimeFunctionSection); - - if (m_pLazyMethodCallHelperSection->GetNodeCount() != 0) - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::DelayLoadMethodCallThunks, m_pLazyMethodCallHelperSection); - - if (m_pExceptionInfoLookupTable->GetSize() != 0) - pReadyToRunHeader->RegisterSection(ReadyToRunSectionType::ExceptionInfo, m_pExceptionInfoLookupTable); - - EndRegion(CORINFO_REGION_COLD); -} - -class DebugInfoVertex : public NativeFormat::Vertex -{ - BlobVertex * m_pDebugInfo; - -public: - DebugInfoVertex(BlobVertex * pDebugInfo) - : m_pDebugInfo(pDebugInfo) - { - } - - virtual void Save(NativeWriter * pWriter) - { - int existingOffset = pWriter->GetCurrentOffset(m_pDebugInfo); - if (existingOffset != -1) - { - _ASSERTE(pWriter->GetCurrentOffset() > existingOffset); - pWriter->WriteUnsigned(pWriter->GetCurrentOffset() - existingOffset); - } - else - { - pWriter->WriteUnsigned(0); - pWriter->SetCurrentOffset(m_pDebugInfo); - m_pDebugInfo->Save(pWriter); - } - } -}; -// At ngen time Zapper::CompileModule PlaceFixups called from -// code:ZapSig.GetSignatureForTypeHandle -// -/*static*/ DWORD ZapImage::EncodeModuleHelper(LPVOID compileContext, - CORINFO_MODULE_HANDLE referencedModule) -{ - _ASSERTE(!IsReadyToRunCompilation() || IsLargeVersionBubbleEnabled()); - ZapImportTable * pTable = (ZapImportTable *)compileContext; - return pTable->GetIndexOfModule(referencedModule); -} - -void ZapImage::OutputDebugInfoForReadyToRun() -{ - NativeWriter writer; - - NativeSection * pSection = writer.NewSection(); - - VertexArray vertexArray(pSection); - pSection->Place(&vertexArray); - - bool fEmpty = true; - - SHash< NoRemoveSHashTraits < BlobVertexSHashTraits > > debugInfoBlobs; - - COUNT_T nCount = m_MethodCompilationOrder.GetCount(); - for (COUNT_T i = 0; i < nCount; i++) - { - ZapMethodHeader * pMethod = m_MethodCompilationOrder[i]; - - ZapBlob * pDebugInfo = pMethod->GetDebugInfo(); - if (pDebugInfo == NULL) - continue; - - DWORD cbBlob = pDebugInfo->GetBlobSize(); - PVOID pBlob = pDebugInfo->GetData(); - - BlobVertex * pDebugInfoBlob = debugInfoBlobs.Lookup(BlobVertexKey(pBlob, cbBlob)); - if (pDebugInfoBlob == NULL) - { - void * pMemory = new (GetHeap()) BYTE[sizeof(BlobVertex) + cbBlob]; - pDebugInfoBlob = new (pMemory) BlobVertex(cbBlob); - memcpy(pDebugInfoBlob->GetData(), pBlob, cbBlob); - - debugInfoBlobs.Add(pDebugInfoBlob); - } - - vertexArray.Set(pMethod->GetMethodIndex(), new (GetHeap()) DebugInfoVertex(pDebugInfoBlob)); - - fEmpty = false; - } - - if (fEmpty) - return; - - vertexArray.ExpandLayout(); - - vector& blob = writer.Save(); - - ZapNode * pBlob = ZapBlob::NewBlob(this, &blob[0], blob.size()); - m_pDebugSection->Place(pBlob); - - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::DebugInfo, pBlob); -} - -void ZapImage::OutputInliningTableForReadyToRun() -{ - SBuffer serializedInlineTrackingBuffer; - m_pPreloader->GetSerializedInlineTrackingMap(&serializedInlineTrackingBuffer); - ZapNode * pBlob = ZapBlob::NewAlignedBlob(this, (PVOID)(const BYTE*) serializedInlineTrackingBuffer, serializedInlineTrackingBuffer.GetSize(), 4); - m_pDebugSection->Place(pBlob); - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::InliningInfo, pBlob); -} - -void ZapImage::OutputProfileDataForReadyToRun() -{ - if (m_pInstrumentSection != nullptr) - { - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::ProfileDataInfo, m_pInstrumentSection); - } -} - -void ZapImage::OutputManifestMetadataForReadyToRun() -{ - if (m_pMetaDataSection != nullptr) - { - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::ManifestMetadata, m_pMetaDataSection); - } -} - -void ZapImage::OutputTypesTableForReadyToRun(IMDInternalImport * pMDImport) -{ - NativeWriter writer; - VertexHashtable typesHashtable; - - NativeSection * pSection = writer.NewSection(); - pSection->Place(&typesHashtable); - - // Note on duplicate types with same name: there is not need to perform that check when building - // the hashtable. If such types were encountered, the R2R compilation would fail before reaching here. - - // Save the TypeDefs to the hashtable - { - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtTypeDef); - - mdToken mdTypeToken; - while (pMDImport->EnumNext(&hEnum, &mdTypeToken)) - { - mdTypeDef mdCurrentToken = mdTypeToken; - DWORD dwHash = GetCompileInfo()->GetVersionResilientTypeHashCode(GetModuleHandle(), mdTypeToken); - - typesHashtable.Append(dwHash, pSection->Place(new UnsignedConstant(RidFromToken(mdTypeToken) << 1))); - } - } - - // Save the ExportedTypes to the hashtable - { - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumInit(mdtExportedType, mdTokenNil); - - mdToken mdTypeToken; - while (pMDImport->EnumNext(&hEnum, &mdTypeToken)) - { - DWORD dwHash = GetCompileInfo()->GetVersionResilientTypeHashCode(GetModuleHandle(), mdTypeToken); - - typesHashtable.Append(dwHash, pSection->Place(new UnsignedConstant((RidFromToken(mdTypeToken) << 1) | 1))); - } - } - - vector& blob = writer.Save(); - - ZapNode * pBlob = ZapBlob::NewBlob(this, &blob[0], blob.size()); - _ASSERTE(m_pAvailableTypesSection); - m_pAvailableTypesSection->Place(pBlob); - - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::AvailableTypes, pBlob); -} - -template -HRESULT EnumerateAllCustomAttributes(IMDInternalImport *pMDImport, Tlambda lambda) -{ - HENUMInternalHolder hEnum(pMDImport); - hEnum.EnumAllInit(mdtCustomAttribute); - - HRESULT hr = S_OK; - - mdCustomAttribute tkCustomAttribute; - while (pMDImport->EnumNext(&hEnum, &tkCustomAttribute)) - { - LPCUTF8 szNamespace; - LPCUTF8 szName; - - hr = pMDImport->GetNameOfCustomAttribute(tkCustomAttribute, &szNamespace, &szName); - if (FAILED(hr)) - return hr; - - if (szNamespace == NULL) - continue; - - if (szName == NULL) - continue; - - // System.Runtime.CompilerServices.NullableAttribute is NEVER added to the table (There are *many* of these, and they provide no useful value to the runtime) - if ((strcmp(szNamespace, "System.Runtime.CompilerServices") == 0) && (strcmp(szName, "NullableAttribute") == 0)) - continue; - - bool addToTable = false; - // Other than Nullable attribute, all attributes under System.Runtime are added to the table - if (strncmp(szNamespace, "System.Runtime.", strlen("System.Runtime.")) == 0) - { - addToTable = true; - } - else if (strcmp(szNamespace, "Windows.Foundation.Metadata") == 0) - { - // Windows.Foundation.Metadata attributes are a similar construct to compilerservices attributes. Add them to the table - addToTable = true; - } - else if (strcmp(szNamespace, "System") == 0) - { - // Some historical well known attributes were placed in the System namespace. Special case them - if (strcmp(szName, "ParamArrayAttribute") == 0) - addToTable = true; - else if (strcmp(szName, "ThreadStaticAttribute") == 0) - addToTable = true; - } - else if (strcmp(szNamespace, "System.Reflection") == 0) - { - // Historical attribute in the System.Reflection namespace - if (strcmp(szName, "DefaultMemberAttribute") == 0) - addToTable = true; - } - - if (!addToTable) - continue; - - mdToken tkParent; - hr = pMDImport->GetParentToken(tkCustomAttribute, &tkParent); - if (FAILED(hr)) - return hr; - - hr = lambda(szNamespace, szName, tkParent); - if (FAILED(hr)) - return hr; - } - - return hr; -} - -static inline uint32_t RotateLeft(const uint32_t x, int k) { - return (x << k) | (x >> (32 - k)); -} - -uint32_t Xoshiro128StarStar(uint32_t s[]) { - const uint32_t result = RotateLeft(s[1] * 5, 7) * 9; - const uint32_t t = s[1] << 9; - - s[2] ^= s[0]; - s[3] ^= s[1]; - s[1] ^= s[2]; - s[0] ^= s[3]; - - s[2] ^= t; - s[3] = RotateLeft(s[3], 11); - - return result; -} - -HRESULT ZapImage::ComputeAttributePresenceTable(IMDInternalImport * pMDImport, SArray *table) -{ - int countOfEntries = 0; - HRESULT hr = EnumerateAllCustomAttributes(pMDImport, [&countOfEntries](LPCUTF8 szNamespace, LPCUTF8 szName, mdToken tkParent) - { - countOfEntries++; - return S_OK; - }); - if (FAILED(hr)) - return hr; - - if (countOfEntries == 0) - { - table->Clear(); - _ASSERTE(table->IsEmpty()); - return S_OK; - } - - // Buckets have 8 entries - UINT minTableBucketCount = (countOfEntries / 8) + 1; - UINT bucketCount = 1; - - // Bucket count must be power of two - while (bucketCount < minTableBucketCount) - bucketCount *= 2; - - // Resize the array. - bool tryAgainWithBiggerTable = false; - int countOfRetries = 0; - do - { - tryAgainWithBiggerTable = false; - UINT actualSizeOfTable = bucketCount * 8; // Buckets have 8 entries in them - UINT16* pTable = table->OpenRawBuffer(actualSizeOfTable); - memset(pTable, 0, sizeof(UINT16) * actualSizeOfTable); - table->CloseRawBuffer(); - - uint32_t state[4] = {729055690, 833774698, 218408041, 493449127}; // 4 randomly generated numbers to initialize random number state - - // Attempt to fill table - - hr = EnumerateAllCustomAttributes(pMDImport, [&](LPCUTF8 szNamespace, LPCUTF8 szName, mdToken tkParent) - { - StackSString name(SString::Utf8); - name.AppendUTF8(szNamespace); - name.AppendUTF8(NAMESPACE_SEPARATOR_STR); - name.AppendUTF8(szName); - - StackScratchBuffer buff; - const char* pDebugNameUTF8 = name.GetUTF8(buff); - size_t len = strlen(pDebugNameUTF8); - - // This hashing algorithm MUST match exactly the logic in NativeCuckooFilter - DWORD hashOfAttribute = ComputeNameHashCode(pDebugNameUTF8); - UINT32 hash = CombineTwoValuesIntoHash(hashOfAttribute, tkParent); - UINT16 fingerprint = (UINT16)(hash >> 16); - if (fingerprint == 0) - fingerprint = 1; - - UINT bucketAIndex = hash % bucketCount; - UINT bucketBIndex = (bucketAIndex ^ (NativeFormat::NativeCuckooFilter::ComputeFingerprintHash(fingerprint) % bucketCount)); - - _ASSERTE(bucketAIndex == (bucketBIndex ^ (NativeFormat::NativeCuckooFilter::ComputeFingerprintHash(fingerprint) % bucketCount))); - - if (Xoshiro128StarStar(state) & 1) // Randomly choose which bucket to attempt to fill first - { - UINT temp = bucketAIndex; - bucketAIndex = bucketBIndex; - bucketBIndex = temp; - } - - auto hasEntryInBucket = [&table](UINT bucketIndex, UINT16 fprint) - { - for (int i = 0; i < 8; i++) - { - if ((*table)[(bucketIndex * 8) + i] == fprint) - return true; - } - return false; - }; - - auto isEmptyEntryInBucket = [&table](UINT bucketIndex) - { - for (int i = 0; i < 8; i++) - { - if ((*table)[(bucketIndex * 8) + i] == 0) - return true; - } - return false; - }; - - auto fillEmptyEntryInBucket = [&table](UINT bucketIndex, UINT16 fprint) - { - for (int i = 0; i < 8; i++) - { - if ((*table)[(bucketIndex * 8) + i] == 0) - { - (*table)[(bucketIndex * 8) + i] = fprint; - return; - } - } - _ASSERTE(!"Not possible to reach here"); - return; - }; - - // Scan for pre-existing fingerprint entry in buckets - if (hasEntryInBucket(bucketAIndex, fingerprint) || hasEntryInBucket(bucketBIndex, fingerprint)) - return S_OK; - - // Determine if there is space in a bucket to add a new entry - if (isEmptyEntryInBucket(bucketAIndex)) - { - fillEmptyEntryInBucket(bucketAIndex, fingerprint); - return S_OK; - } - if (isEmptyEntryInBucket(bucketBIndex)) - { - fillEmptyEntryInBucket(bucketBIndex, fingerprint); - return S_OK; - } - - int MaxNumKicks = 256; - // Note, that bucketAIndex itself was chosen randomly above. - for (int n = 0; n < MaxNumKicks; n++) - { - // Randomly swap an entry in bucket bucketAIndex with fingerprint - UINT entryIndexInBucket = Xoshiro128StarStar(state) & 0x7; - UINT16 temp = fingerprint; - fingerprint = (*table)[(bucketAIndex * 8) + entryIndexInBucket]; - (*table)[(bucketAIndex * 8) + entryIndexInBucket] = temp; - - // Find other bucket - bucketAIndex = bucketAIndex ^ (NativeFormat::NativeCuckooFilter::ComputeFingerprintHash(fingerprint) % bucketCount); - if (isEmptyEntryInBucket(bucketAIndex)) - { - fillEmptyEntryInBucket(bucketAIndex, fingerprint); - return S_OK; - } - } - - tryAgainWithBiggerTable = true; - return E_FAIL; - }); - - if (tryAgainWithBiggerTable) - { - // bucket entry kicking path requires bucket counts to be power of two in size due to use of xor to retrieve second hash - bucketCount *= 2; - } - } while(tryAgainWithBiggerTable && ((countOfRetries++) < 2)); - - if (tryAgainWithBiggerTable) - { - return E_FAIL; - } - - return S_OK; -} - -void ZapImage::OutputAttributePresenceFilter(IMDInternalImport * pMDImport) -{ - // Core library attributes are checked FAR more often than other dlls - // attributes, so produce a highly efficient table for determining if they are - // present. Other assemblies *MAY* benefit from this feature, but it doesn't show - // as useful at this time. - - if (m_hModule != m_zapper->m_pEECompileInfo->GetLoaderModuleForCoreLib()) - return; - - SArray table; - if (SUCCEEDED(ComputeAttributePresenceTable(pMDImport, &table))) - { - UINT16* pRawTable = table.OpenRawBuffer(table.GetCount()); - ZapNode * pBlob = ZapBlob::NewBlob(this, pRawTable, table.GetCount() * sizeof(UINT16)); - table.CloseRawBuffer(); - - _ASSERTE(m_pAttributePresenceSection); - m_pAttributePresenceSection->Place(pBlob); - GetReadyToRunHeader()->RegisterSection(ReadyToRunSectionType::AttributePresence, pBlob); - } -} - -// -// Verify that data structures and flags shared between NGen and ReadyToRun are in sync -// - -// -// READYTORUN_IMPORT_SECTION -// -static_assert_no_msg(sizeof(READYTORUN_IMPORT_SECTION) == sizeof(CORCOMPILE_IMPORT_SECTION)); - -static_assert_no_msg((int)READYTORUN_IMPORT_SECTION_TYPE_UNKNOWN == (int)CORCOMPILE_IMPORT_TYPE_UNKNOWN); - -static_assert_no_msg((int)READYTORUN_IMPORT_SECTION_FLAGS_EAGER == (int)CORCOMPILE_IMPORT_FLAGS_EAGER); - -// -// READYTORUN_METHOD_SIG -// -static_assert_no_msg((int)READYTORUN_METHOD_SIG_UnboxingStub == (int)ENCODE_METHOD_SIG_UnboxingStub); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_InstantiatingStub == (int)ENCODE_METHOD_SIG_InstantiatingStub); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_MethodInstantiation == (int)ENCODE_METHOD_SIG_MethodInstantiation); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_SlotInsteadOfToken == (int)ENCODE_METHOD_SIG_SlotInsteadOfToken); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_MemberRefToken == (int)ENCODE_METHOD_SIG_MemberRefToken); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_Constrained == (int)ENCODE_METHOD_SIG_Constrained); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_OwnerType == (int)ENCODE_METHOD_SIG_OwnerType); -static_assert_no_msg((int)READYTORUN_METHOD_SIG_UpdateContext == (int)ENCODE_METHOD_SIG_UpdateContext); - -// -// READYTORUN_FIELD_SIG -// -static_assert_no_msg((int)READYTORUN_FIELD_SIG_IndexInsteadOfToken == (int)ENCODE_FIELD_SIG_IndexInsteadOfToken); -static_assert_no_msg((int)READYTORUN_FIELD_SIG_MemberRefToken == (int)ENCODE_FIELD_SIG_MemberRefToken); -static_assert_no_msg((int)READYTORUN_FIELD_SIG_OwnerType == (int)ENCODE_FIELD_SIG_OwnerType); - -// -// READYTORUN_FIXUP -// -static_assert_no_msg((int)READYTORUN_FIXUP_ThisObjDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_THISOBJ); -static_assert_no_msg((int)READYTORUN_FIXUP_TypeDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_TYPE); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodDictionaryLookup == (int)ENCODE_DICTIONARY_LOOKUP_METHOD); - -static_assert_no_msg((int)READYTORUN_FIXUP_TypeHandle == (int)ENCODE_TYPE_HANDLE); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodHandle == (int)ENCODE_METHOD_HANDLE); -static_assert_no_msg((int)READYTORUN_FIXUP_FieldHandle == (int)ENCODE_FIELD_HANDLE); - -static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry == (int)ENCODE_METHOD_ENTRY); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry_DefToken == (int)ENCODE_METHOD_ENTRY_DEF_TOKEN); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodEntry_RefToken == (int)ENCODE_METHOD_ENTRY_REF_TOKEN); - -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry == (int)ENCODE_VIRTUAL_ENTRY); -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_DefToken == (int)ENCODE_VIRTUAL_ENTRY_DEF_TOKEN); -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_RefToken == (int)ENCODE_VIRTUAL_ENTRY_REF_TOKEN); -static_assert_no_msg((int)READYTORUN_FIXUP_VirtualEntry_Slot == (int)ENCODE_VIRTUAL_ENTRY_SLOT); - -static_assert_no_msg((int)READYTORUN_FIXUP_Helper == (int)ENCODE_READYTORUN_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_StringHandle == (int)ENCODE_STRING_HANDLE); - -static_assert_no_msg((int)READYTORUN_FIXUP_NewObject == (int)ENCODE_NEW_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_NewArray == (int)ENCODE_NEW_ARRAY_HELPER); - -static_assert_no_msg((int)READYTORUN_FIXUP_IsInstanceOf == (int)ENCODE_ISINSTANCEOF_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_ChkCast == (int)ENCODE_CHKCAST_HELPER); - -static_assert_no_msg((int)READYTORUN_FIXUP_FieldAddress == (int)ENCODE_FIELD_ADDRESS); -static_assert_no_msg((int)READYTORUN_FIXUP_CctorTrigger == (int)ENCODE_CCTOR_TRIGGER); - -static_assert_no_msg((int)READYTORUN_FIXUP_StaticBaseNonGC == (int)ENCODE_STATIC_BASE_NONGC_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_StaticBaseGC == (int)ENCODE_STATIC_BASE_GC_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_ThreadStaticBaseNonGC == (int)ENCODE_THREAD_STATIC_BASE_NONGC_HELPER); -static_assert_no_msg((int)READYTORUN_FIXUP_ThreadStaticBaseGC == (int)ENCODE_THREAD_STATIC_BASE_GC_HELPER); - -static_assert_no_msg((int)READYTORUN_FIXUP_FieldBaseOffset == (int)ENCODE_FIELD_BASE_OFFSET); -static_assert_no_msg((int)READYTORUN_FIXUP_FieldOffset == (int)ENCODE_FIELD_OFFSET); - -static_assert_no_msg((int)READYTORUN_FIXUP_TypeDictionary == (int)ENCODE_TYPE_DICTIONARY); -static_assert_no_msg((int)READYTORUN_FIXUP_MethodDictionary == (int)ENCODE_METHOD_DICTIONARY); - -static_assert_no_msg((int)READYTORUN_FIXUP_Check_TypeLayout == (int)ENCODE_CHECK_TYPE_LAYOUT); -static_assert_no_msg((int)READYTORUN_FIXUP_Check_FieldOffset == (int)ENCODE_CHECK_FIELD_OFFSET); - -static_assert_no_msg((int)READYTORUN_FIXUP_DelegateCtor == (int)ENCODE_DELEGATE_CTOR); - -static_assert_no_msg((int)READYTORUN_FIXUP_DeclaringTypeHandle == (int)ENCODE_DECLARINGTYPE_HANDLE); - -static_assert_no_msg((int)READYTORUN_FIXUP_IndirectPInvokeTarget == (int)ENCODE_INDIRECT_PINVOKE_TARGET); -static_assert_no_msg((int)READYTORUN_FIXUP_PInvokeTarget == (int)ENCODE_PINVOKE_TARGET); - -static_assert_no_msg((int)READYTORUN_FIXUP_Check_InstructionSetSupport== (int)ENCODE_CHECK_INSTRUCTION_SET_SUPPORT); - -static_assert_no_msg((int)READYTORUN_FIXUP_Verify_FieldOffset == (int)ENCODE_VERIFY_FIELD_OFFSET); -static_assert_no_msg((int)READYTORUN_FIXUP_Verify_TypeLayout == (int)ENCODE_VERIFY_TYPE_LAYOUT); - -static_assert_no_msg((int)READYTORUN_FIXUP_Check_VirtualFunctionOverride == (int)ENCODE_CHECK_VIRTUAL_FUNCTION_OVERRIDE); -static_assert_no_msg((int)READYTORUN_FIXUP_Verify_VirtualFunctionOverride == (int)ENCODE_VERIFY_VIRTUAL_FUNCTION_OVERRIDE); - -// -// READYTORUN_EXCEPTION -// -static_assert_no_msg(sizeof(READYTORUN_EXCEPTION_LOOKUP_TABLE_ENTRY) == sizeof(CORCOMPILE_EXCEPTION_LOOKUP_TABLE_ENTRY)); -static_assert_no_msg(sizeof(READYTORUN_EXCEPTION_CLAUSE) == sizeof(CORCOMPILE_EXCEPTION_CLAUSE)); - -// -// ReadyToRunHFAElemType -// -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_None == (int)CORINFO_HFA_ELEM_NONE); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Float32 == (int)CORINFO_HFA_ELEM_FLOAT); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Float64 == (int)CORINFO_HFA_ELEM_DOUBLE); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Vector64 == (int)CORINFO_HFA_ELEM_VECTOR64); -static_assert_no_msg((int)READYTORUN_HFA_ELEMTYPE_Vector128 == (int)CORINFO_HFA_ELEM_VECTOR128); - diff --git a/src/coreclr/zap/zapreadytorun.h b/src/coreclr/zap/zapreadytorun.h deleted file mode 100644 index 66fe3adb391aef..00000000000000 --- a/src/coreclr/zap/zapreadytorun.h +++ /dev/null @@ -1,65 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapReadyToRun.h -// - -// -// Zapping of ready-to-run specific structures -// -// ====================================================================================== - -#ifndef __ZAPREADYTORUN_H__ -#define __ZAPREADYTORUN_H__ - -#include "readytorun.h" - -class ZapReadyToRunHeader : public ZapNode -{ - struct Section - { - ReadyToRunSectionType type; - ZapNode * pSection; - }; - - SArray
m_Sections; - - static int __cdecl SectionCmp(const void* a_, const void* b_) - { - return (uint32_t)((Section*)a_)->type - (uint32_t)((Section*)b_)->type; - } - -public: - ZapReadyToRunHeader(ZapImage * pImage) - { - } - - void RegisterSection(ReadyToRunSectionType type, ZapNode * pSection) - { - Section section; - section.type = type; - section.pSection = pSection; - m_Sections.Append(section); - } - - virtual DWORD GetSize() - { - return sizeof(READYTORUN_HEADER) + sizeof(READYTORUN_SECTION) * m_Sections.GetCount(); - } - - virtual UINT GetAlignment() - { - return sizeof(DWORD); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_NativeHeader; - } - - virtual void Save(ZapWriter * pZapWriter); - - DWORD EncodeModuleHelper(LPVOID compileContext, CORINFO_MODULE_HANDLE referencedModule); -}; - -#endif // __ZAPREADYTORUN_H__ diff --git a/src/coreclr/zap/zaprelocs.cpp b/src/coreclr/zap/zaprelocs.cpp deleted file mode 100644 index 028a30e0154bf5..00000000000000 --- a/src/coreclr/zap/zaprelocs.cpp +++ /dev/null @@ -1,427 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapRelocs.cpp -// - -// -// Zapping of relocations -// -// ====================================================================================== - -#include "common.h" - -#include "zaprelocs.h" - -#ifdef REDHAWK -void PDB_NoticeReloc(ZapRelocationType type, DWORD rvaReloc, ZapNode * pTarget, int targetOffset); -#endif - -void ZapBaseRelocs::WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type) -{ - _ASSERTE(pTarget != NULL); - - PBYTE pLocation = (PBYTE)pSrc + offset; - DWORD rva = m_pImage->GetCurrentRVA() + offset; - TADDR pActualTarget = (TADDR)m_pImage->GetBaseAddress() + pTarget->GetRVA() + targetOffset; - -#ifdef REDHAWK - PDB_NoticeReloc(type, rva, pTarget, targetOffset); -#endif - - switch (type) - { - case IMAGE_REL_BASED_ABSOLUTE: - *(UNALIGNED DWORD *)pLocation = pTarget->GetRVA() + targetOffset; - // IMAGE_REL_BASED_ABSOLUTE does not need base reloc entry - return; - - case IMAGE_REL_BASED_ABSOLUTE_TAGGED: - _ASSERTE(targetOffset == 0); - *(UNALIGNED DWORD *)pLocation = (DWORD)CORCOMPILE_TAG_TOKEN(pTarget->GetRVA()); - // IMAGE_REL_BASED_ABSOLUTE_TAGGED does not need base reloc entry - return; - - case IMAGE_REL_BASED_PTR: -#ifdef TARGET_ARM - // Misaligned relocs disable ASLR on ARM. We should never ever emit them. - _ASSERTE(IS_ALIGNED(rva, TARGET_POINTER_SIZE)); -#endif - *(UNALIGNED TARGET_POINTER_TYPE *)pLocation = (TARGET_POINTER_TYPE)pActualTarget; - break; - - case IMAGE_REL_BASED_RELPTR: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - *(UNALIGNED TADDR *)pLocation = (INT32)(pActualTarget - pSite); - } - // neither IMAGE_REL_BASED_RELPTR nor IMAGE_REL_BASED_MD_METHODENTRY need base reloc entry - return; - - case IMAGE_REL_BASED_RELPTR32: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - *(UNALIGNED INT32 *)pLocation = (INT32)(pActualTarget - pSite); - } - // IMAGE_REL_BASED_RELPTR32 does not need base reloc entry - return; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - *(UNALIGNED INT32 *)pLocation = (INT32)(pActualTarget - (pSite + sizeof(INT32))); - } - // IMAGE_REL_BASED_REL32 does not need base reloc entry - return; -#endif // TARGET_X86 || TARGET_AMD64 - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - { - PutThumb2Mov32((UINT16 *)pLocation, (UINT32)pActualTarget); - break; - } - - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - - // For details about how the value is calculated, see - // description of IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL - const UINT32 offsetCorrection = 12; - - UINT32 imm32 = UINT32(pActualTarget - (pSite + offsetCorrection)); - - PutThumb2Mov32((UINT16 *)pLocation, imm32); - - // IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL does not need base reloc entry - return; - } - - case IMAGE_REL_BASED_THUMB_BRANCH24: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - - // Kind of a workaround: make this reloc work both for calls (which have the thumb bit set), - // and for relative jumps used for hot/cold splitting (which don't). - pActualTarget &= ~THUMB_CODE; - - // Calculate the reloffset without the ThumbBit set so that it can be correctly encoded. - _ASSERTE(!(pActualTarget & THUMB_CODE));// we expect pActualTarget not to have the thumb bit set - _ASSERTE(!(pSite & THUMB_CODE)); // we expect pSite not to have the thumb bit set - INT32 relOffset = (INT32)(pActualTarget - (pSite + sizeof(INT32))); - if (!FitsInThumb2BlRel24(relOffset)) - { - // Retry the compilation with IMAGE_REL_BASED_THUMB_BRANCH24 relocations disabled - // (See code:ZapInfo::getRelocTypeHint) - ThrowHR(COR_E_OVERFLOW); - } - PutThumb2BlRel24((UINT16 *)pLocation, relOffset); - } - // IMAGE_REL_BASED_THUMB_BRANCH24 does not need base reloc entry - return; -#endif // defined(TARGET_ARM) -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - { - TADDR pSite = (TADDR)m_pImage->GetBaseAddress() + rva; - - INT32 relOffset = (INT32)(pActualTarget - pSite); - if (!FitsInRel28(relOffset)) - { - ThrowHR(COR_E_OVERFLOW); - } - PutArm64Rel28((UINT32 *)pLocation,relOffset); - } - return; - - case IMAGE_REL_ARM64_PAGEBASE_REL21: - { - TADDR pSitePage = ((TADDR)m_pImage->GetBaseAddress() + rva) & 0xFFFFFFFFFFFFF000LL; - TADDR pActualTargetPage = pActualTarget & 0xFFFFFFFFFFFFF000LL; - - INT64 relPage = (INT64)(pActualTargetPage - pSitePage); - INT32 imm21 = (INT32)(relPage >> 12) & 0x1FFFFF; - PutArm64Rel21((UINT32 *)pLocation, imm21); - } - return; - - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - { - INT32 imm12 = (INT32)(pActualTarget & 0xFFFLL); - PutArm64Rel12((UINT32 *)pLocation, imm12); - } - return; -#endif - - default: - _ASSERTE(!"Unknown relocation type"); - break; - } - - DWORD page = AlignDown(rva, RELOCATION_PAGE_SIZE); - - if (page != m_page) - { - FlushWriter(); - - m_page = page; - m_pageIndex = m_SerializedRelocs.GetCount(); - - // Reserve space for IMAGE_BASE_RELOCATION - for (size_t iSpace = 0; iSpace < sizeof(IMAGE_BASE_RELOCATION) / sizeof(USHORT); iSpace++) - m_SerializedRelocs.Append(0); - } - - m_SerializedRelocs.Append((USHORT)(AlignmentTrim(rva, RELOCATION_PAGE_SIZE) | (type << 12))); -} - -void ZapBaseRelocs::FlushWriter() -{ - if (m_page != 0) - { - // The blocks has to be 4-byte aligned - if (m_SerializedRelocs.GetCount() & 1) - m_SerializedRelocs.Append(0); - - IMAGE_BASE_RELOCATION * pBaseRelocation = (IMAGE_BASE_RELOCATION *)&(m_SerializedRelocs[m_pageIndex]); - pBaseRelocation->VirtualAddress = m_page; - pBaseRelocation->SizeOfBlock = (m_SerializedRelocs.GetCount() - m_pageIndex) * sizeof(USHORT); - - m_page = 0; - } -} - -void ZapBaseRelocs::Save(ZapWriter * pZapWriter) -{ - FlushWriter(); - - pZapWriter->SetWritingRelocs(); - - // Write the relocs as blob - pZapWriter->Write(&m_SerializedRelocs[0], m_SerializedRelocs.GetCount() * sizeof(USHORT)); -} - -////////////////////////////////////////////////////////////////////////////// -// -// ZapBlobWithRelocs -// - -int _cdecl CmpZapRelocs(const void *p1, const void *p2) -{ - LIMITED_METHOD_CONTRACT; - - const ZapReloc *relocTemp1 = (ZapReloc *)p1; - const ZapReloc *relocTemp2 = (ZapReloc *)p2; - if (relocTemp1->m_offset < relocTemp2->m_offset) - return -1; - else if (relocTemp1->m_offset > relocTemp2->m_offset) - return 1; - else - return 0; -} - -void ZapBlobWithRelocs::Save(ZapWriter * pZapWriter) -{ - if (m_pRelocs != NULL) - { - - // pre-pass to figure out if we need to sort - // if the offsets are not in ascending order AND the offsets within this - // array ending up describing locations in different pages, the relocation - // writer generates bad relocation info (e.g. multiple entries for the same page) - // that is no longer accepted by the OS loader - // Also, having relocs in ascending order allows a more compact representation. - - ZapReloc *pReloc = m_pRelocs; - - // we need to check only for more than one reloc entry - if (pReloc->m_type != IMAGE_REL_INVALID && pReloc[1].m_type != IMAGE_REL_INVALID) - { - bool isSorted = true; - DWORD lastOffset = pReloc->m_offset; - DWORD cReloc = 1; - - // we start with the second entry (the first entry is already consumed) - while (pReloc[cReloc].m_type != IMAGE_REL_INVALID) - { - // we cannot abort the loop here because we need to count the entries - // to properly sort the relocs!!! - if (pReloc[cReloc].m_offset < lastOffset) - isSorted = false; - lastOffset = pReloc[cReloc].m_offset; - cReloc++; - } - if (!isSorted) - { - qsort(pReloc, cReloc, sizeof(ZapReloc), CmpZapRelocs); - } - } - - ZapImage * pImage = ZapImage::GetImage(pZapWriter); - PBYTE pData = GetData(); - - for (pReloc = m_pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++) - { - PBYTE pLocation = pData + pReloc->m_offset; - int targetOffset = 0; - - // Decode the offset - switch (pReloc->m_type) - { - case IMAGE_REL_BASED_ABSOLUTE: - targetOffset = *(UNALIGNED DWORD *)pLocation; - break; - - case IMAGE_REL_BASED_ABSOLUTE_TAGGED: - targetOffset = 0; - break; - - case IMAGE_REL_BASED_PTR: - targetOffset = (int)*(UNALIGNED TADDR *)pLocation; - break; - case IMAGE_REL_BASED_RELPTR: - targetOffset = (int)*(UNALIGNED TADDR *)pLocation; - break; - - case IMAGE_REL_BASED_RELPTR32: - targetOffset = (int)*(UNALIGNED INT32 *)pLocation; - break; - -#if defined(TARGET_X86) || defined(TARGET_AMD64) - case IMAGE_REL_BASED_REL32: - targetOffset = *(UNALIGNED INT32 *)pLocation; - break; -#endif // TARGET_X86 || TARGET_AMD64 - -#if defined(TARGET_ARM) - case IMAGE_REL_BASED_THUMB_MOV32: - case IMAGE_REL_BASED_REL_THUMB_MOV32_PCREL: - targetOffset = (int)GetThumb2Mov32((UINT16 *)pLocation); - break; - - case IMAGE_REL_BASED_THUMB_BRANCH24: - targetOffset = GetThumb2BlRel24((UINT16 *)pLocation); - break; -#endif // defined(TARGET_ARM) - -#if defined(TARGET_ARM64) - case IMAGE_REL_ARM64_BRANCH26: - targetOffset = (int)GetArm64Rel28((UINT32*)pLocation); - break; - - case IMAGE_REL_ARM64_PAGEBASE_REL21: - targetOffset = (int)GetArm64Rel21((UINT32*)pLocation); - break; - - case IMAGE_REL_ARM64_PAGEOFFSET_12A: - targetOffset = (int)GetArm64Rel12((UINT32*)pLocation); - break; - -#endif // defined(TARGET_ARM64) - - default: - _ASSERTE(!"Unknown reloc type"); - break; - } - - pImage->WriteReloc(pData, pReloc->m_offset, - pReloc->m_pTargetNode, targetOffset, pReloc->m_type); - } - } - - ZapBlob::Save(pZapWriter); -} - -COUNT_T ZapBlobWithRelocs::GetCountOfStraddlerRelocations(DWORD dwPos) -{ - if (m_pRelocs == NULL) - return 0; - - // Straddlers can exist only if the node is crossing page boundary - if (AlignDown(dwPos, RELOCATION_PAGE_SIZE) == AlignDown(dwPos + GetSize() - 1, RELOCATION_PAGE_SIZE)) - return 0; - - COUNT_T nStraddlers = 0; - - for (ZapReloc * pReloc = m_pRelocs; pReloc->m_type != IMAGE_REL_INVALID; pReloc++) - { - if (pReloc->m_type == IMAGE_REL_BASED_PTR) - { - if (AlignmentTrim(dwPos + pReloc->m_offset, RELOCATION_PAGE_SIZE) > RELOCATION_PAGE_SIZE - TARGET_POINTER_SIZE) - nStraddlers++; - } - } - - return nStraddlers; -} - -ZapBlobWithRelocs * ZapBlobWithRelocs::NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) -{ - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapBlobWithRelocs)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapBlobWithRelocs * pZapBlobWithRelocs = new (pMemory) ZapBlobWithRelocs(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapBlobWithRelocs + 1), pData, cbSize); - - return pZapBlobWithRelocs; -} - -template -class ZapAlignedBlobWithRelocsConst : public ZapBlobWithRelocs -{ -protected: - ZapAlignedBlobWithRelocsConst(SIZE_T cbSize) - : ZapBlobWithRelocs(cbSize) - { - } - -public: - virtual UINT GetAlignment() - { - return alignment; - } - - static ZapBlobWithRelocs * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) - { - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapAlignedBlobWithRelocsConst)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapAlignedBlobWithRelocsConst * pZapBlob = new (pMemory) ZapAlignedBlobWithRelocsConst(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapBlob + 1), pData, cbSize); - - return pZapBlob; - } -}; - -ZapBlobWithRelocs * ZapBlobWithRelocs::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment) -{ - switch (cbAlignment) - { - case 1: - return ZapBlobWithRelocs::NewBlob(pWriter, pData, cbSize); - case 2: - return ZapAlignedBlobWithRelocsConst<2>::NewBlob(pWriter, pData, cbSize); - case 4: - return ZapAlignedBlobWithRelocsConst<4>::NewBlob(pWriter, pData, cbSize); - case 8: - return ZapAlignedBlobWithRelocsConst<8>::NewBlob(pWriter, pData, cbSize); - case 16: - return ZapAlignedBlobWithRelocsConst<16>::NewBlob(pWriter, pData, cbSize); - - default: - _ASSERTE(!"Requested alignment not supported"); - return NULL; - } -} diff --git a/src/coreclr/zap/zaprelocs.h b/src/coreclr/zap/zaprelocs.h deleted file mode 100644 index 9b06450e8c8f1d..00000000000000 --- a/src/coreclr/zap/zaprelocs.h +++ /dev/null @@ -1,128 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapRelocs.h -// - -// -// Zapping of relocations -// -// ====================================================================================== - -#ifndef __ZAPRELOCS_H__ -#define __ZAPRELOCS_H__ - -typedef BYTE ZapRelocationType; // IMAGE_REL_XXX enum - -// Special NGEN-specific relocation type for fixups (absolute RVA in the middle 30 bits) -#define IMAGE_REL_BASED_ABSOLUTE_TAGGED 0x7E - -// Special NGEN-specific relocation type for relative pointer (used to make NGen relocation section smaller) -#define IMAGE_REL_BASED_RELPTR 0x7D -#define IMAGE_REL_BASED_RELPTR32 0x7C - -// Invalid reloc marker (used to mark end of the reloc array) -#define IMAGE_REL_INVALID 0xFF - -// IMAGE_REL_BASED_PTR is architecture specific reloc of virtual address -#ifdef TARGET_64BIT -#define IMAGE_REL_BASED_PTR IMAGE_REL_BASED_DIR64 -#else -#define IMAGE_REL_BASED_PTR IMAGE_REL_BASED_HIGHLOW -#endif - -// Size of base relocs relocation page -#define RELOCATION_PAGE_SIZE 0x1000 - -// -// The ZapNode for regular PE base relocs -// - -class ZapBaseRelocs : public ZapNode -{ - ZapImage * m_pImage; - - // The page currently being written - DWORD m_page; - COUNT_T m_pageIndex; - - // Reloc writer output - SArray m_SerializedRelocs; - - void FlushWriter(); - -public: - ZapBaseRelocs(ZapImage * pImage) - : m_pImage(pImage) - { - // Everything is zero initialized by the allocator - } - - void WriteReloc(PVOID pSrc, int offset, ZapNode * pTarget, int targetOffset, ZapRelocationType type); - - virtual DWORD GetSize() - { - return m_SerializedRelocs.GetCount() * sizeof(USHORT); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Relocs; - } - - virtual void Save(ZapWriter * pZapWriter); -}; - -// -// -// Blob with associated relocations. Used for compiled code. -// - -struct ZapReloc -{ - ZapRelocationType m_type; - DWORD m_offset; - ZapNode * m_pTargetNode; -}; - -class ZapBlobWithRelocs : public ZapBlob -{ - ZapReloc * m_pRelocs; - -protected: - ZapBlobWithRelocs(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - -public: - void SetRelocs(ZapReloc * pRelocs) - { - _ASSERTE(m_pRelocs == NULL); - _ASSERTE(pRelocs != NULL); - m_pRelocs = pRelocs; - } - - ZapReloc * GetRelocs() - { - return m_pRelocs; - } - - virtual PBYTE GetData() - { - return (PBYTE)(this + 1); - } - - virtual void Save(ZapWriter * pZapWriter); - - // Returns number of straddler relocs, assuming RVA of the node is dwPos - COUNT_T GetCountOfStraddlerRelocations(DWORD dwPos); - - // Create new zap blob node. The node *does* own copy of the memory. - static ZapBlobWithRelocs * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize); - - // Create new aligned zap blob node. - static ZapBlobWithRelocs * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); -}; - -#endif // __ZAPRELOCS_H__ diff --git a/src/coreclr/zap/zapwrapper.cpp b/src/coreclr/zap/zapwrapper.cpp deleted file mode 100644 index b9dc87c8a0afdd..00000000000000 --- a/src/coreclr/zap/zapwrapper.cpp +++ /dev/null @@ -1,200 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWrapper.cpp -// - -// -// ZapNode that wraps EE datastructure for zapping -// -// ====================================================================================== - -#include "common.h" - -#include "zapwrapper.h" - -void ZapWrapperTable::Resolve() -{ - for (WrapperTable::Iterator i = m_entries.Begin(), end = m_entries.End(); i != end; i++) - { - (*i)->Resolve(m_pImage); - } -} - -// ====================================================================================== -// Actual placeholders - -class ZapMethodHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapMethodHandle(CORINFO_METHOD_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_MethodHandle; - } -}; - -ZapNode * ZapWrapperTable::GetMethodHandle(CORINFO_METHOD_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapClassHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapClassHandle(CORINFO_CLASS_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ClassHandle; - } -}; - -ZapNode * ZapWrapperTable::GetClassHandle(CORINFO_CLASS_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapFieldHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapFieldHandle(CORINFO_FIELD_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_FieldHandle; - } -}; - -ZapNode * ZapWrapperTable::GetFieldHandle(CORINFO_FIELD_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapAddrOfPInvokeFixup : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapAddressOfPInvokeFixup(CORINFO_METHOD_HANDLE((BYTE *)GetHandle() - 1))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_AddrOfPInvokeFixup; - } -}; - -ZapNode * ZapWrapperTable::GetAddrOfPInvokeFixup(CORINFO_METHOD_HANDLE handle) -{ - // Disambiguate the normal method handle and address of P/Invoke fixup by adding 1 - return GetPlaceHolder((BYTE *)handle + 1); -} - -class ZapGenericHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapGenericHandle(CORINFO_GENERIC_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_GenericHandle; - } -}; - -ZapNode * ZapWrapperTable::GetGenericHandle(CORINFO_GENERIC_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapModuleIDHandle : public ZapWrapper -{ -public: - virtual void Resolve(ZapImage * pImage) - { - SetRVA(pImage->m_pPreloader->MapModuleIDHandle(CORINFO_MODULE_HANDLE(GetHandle()))); - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_ModuleIDHandle; - } -}; - -ZapNode * ZapWrapperTable::GetModuleIDHandle(CORINFO_MODULE_HANDLE handle) -{ - return GetPlaceHolder(handle); -} - -class ZapStub : public ZapWrapper -{ - DWORD m_dwStubSize; - -public: - ZapStub(PVOID pStubData, DWORD dwStubSize) - : ZapWrapper(pStubData), m_dwStubSize(dwStubSize) - { - } - - virtual DWORD GetSize() - { - return m_dwStubSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Stub; - } - - virtual UINT GetAlignment() - { - return DEFAULT_CODE_ALIGN; - } - - virtual void Save(ZapWriter * pZapWriter) - { - DWORD dwSize = GetSize(); - PVOID pStub = GetHandle(); - - SBuffer stubClone(dwSize); - - ICorCompileInfo *pCompileInfo = ZapImage::GetImage(pZapWriter)->GetCompileInfo(); - IfFailThrow(pCompileInfo->GetStubClone(pStub, - const_cast(static_cast(stubClone)), dwSize)); - - pZapWriter->Write(const_cast(static_cast(stubClone)), dwSize); - } -}; - -ZapNode * ZapWrapperTable::GetStub(void * pStub) -{ - DWORD dwStubSize = 0; - void * pStubData = m_pImage->GetCompileInfo()->GetStubSize(pStub, &dwStubSize); - _ASSERTE(pStubData < pStub && pStub < (BYTE*)pStubData + dwStubSize); - - ZapStub * pZapStub = (ZapStub *)m_entries.Lookup(pStubData); - if (pZapStub == NULL) - { - // did not find the delegate stub, need to emit the stub in the native image - pZapStub = new (m_pImage->GetHeap()) ZapStub(pStubData, dwStubSize); - - m_entries.Add(pZapStub); - } - - // Return inner ptr for the entrypoint - _ASSERTE(pZapStub->GetType() == ZapNodeType_Stub); - return m_pImage->GetInnerPtr(pZapStub, (PBYTE)pStub - (PBYTE)pStubData); -} diff --git a/src/coreclr/zap/zapwrapper.h b/src/coreclr/zap/zapwrapper.h deleted file mode 100644 index ea914da749710c..00000000000000 --- a/src/coreclr/zap/zapwrapper.h +++ /dev/null @@ -1,141 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWrapper.h -// - -// -// ZapNode that wraps EE datastructure for zapping -// -// ====================================================================================== - -#ifndef __ZAPWRAPPER_H__ -#define __ZAPWRAPPER_H__ - -// -// When generating compiled code for IL, the compiler will need to embed -// handles, which are pointers to various data structures. The data -// structures may either not exist, or we may not have some information -// we need for optimal code gen. -// -// In such cases, we use placeholders. Compiled code embed pointers -// to placeholders, which then have rich information about the -// referenced data structure. -// -// Once information is finally available for the exact code required, -// ZapWrapper::Resolve makes the place holder to point to the intended target. -// - -class ZapWrapper : public ZapNode -{ - PVOID m_handle; - -public: - ZapWrapper(PVOID handle) - : m_handle(handle) - { - } - - ZapWrapper() - { - } - - void SetHandle(PVOID handle) - { - _ASSERTE(m_handle == NULL); - _ASSERTE(handle != NULL); - m_handle = handle; - } - - PVOID GetHandle() - { - return m_handle; - } - - virtual ZapNode * GetBase() - { - return this; - } - - virtual void Resolve(ZapImage * pImage) - { - } -}; - -class ZapWrapperTable -{ - class WrapperTraits : public NoRemoveSHashTraits< DefaultSHashTraits > - { - public: - typedef PVOID key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return e->GetHandle(); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - return k1 == k2; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - return (count_t)(size_t)k; - } - - static element_t Null() { LIMITED_METHOD_CONTRACT; return NULL; } - static bool IsNull(const element_t &e) { LIMITED_METHOD_CONTRACT; return e == NULL; } - }; - - typedef SHash< WrapperTraits > WrapperTable; - - WrapperTable m_entries; - ZapImage * m_pImage; - - // - // Helper for inserting actual implementations of placeholders into hashtable - // - template < typename impl, ZapNodeType type > - ZapNode * GetPlaceHolder(PVOID handle) - { - ZapWrapper * pPlaceHolder = m_entries.Lookup(handle); - - if (pPlaceHolder != NULL) - { - _ASSERTE(pPlaceHolder->GetType() == type); - return pPlaceHolder; - } - - pPlaceHolder = new (m_pImage->GetHeap()) impl(); - _ASSERTE(pPlaceHolder->GetType() == type); - pPlaceHolder->SetHandle(handle); - m_entries.Add(pPlaceHolder); - return pPlaceHolder; - } - -public: - ZapWrapperTable(ZapImage * pImage) - : m_pImage(pImage) - { - } - - void Preallocate(COUNT_T cbILImage) - { - PREALLOCATE_HASHTABLE(ZapWrapperTable::m_entries, 0.0013, cbILImage); - } - - ZapNode * GetMethodHandle(CORINFO_METHOD_HANDLE handle); - ZapNode * GetClassHandle(CORINFO_CLASS_HANDLE handle); - ZapNode * GetFieldHandle(CORINFO_FIELD_HANDLE handle); - ZapNode * GetAddrOfPInvokeFixup(CORINFO_METHOD_HANDLE handle); - ZapNode * GetGenericHandle(CORINFO_GENERIC_HANDLE handle); - ZapNode * GetModuleIDHandle(CORINFO_MODULE_HANDLE handle); - - ZapNode * GetStub(void * pStub); - - void Resolve(); -}; - -#endif // __ZAPWRAPPER_H__ diff --git a/src/coreclr/zap/zapwriter.cpp b/src/coreclr/zap/zapwriter.cpp deleted file mode 100644 index 4642c2af698abe..00000000000000 --- a/src/coreclr/zap/zapwriter.cpp +++ /dev/null @@ -1,697 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWriter.cpp -// - -// -// Infrastructure for writing PE files. (Not NGEN specific) -// -// ====================================================================================== - -#include "common.h" - -//--------------------------------------------------------------------------------------- -// ZapNode - -void * operator new(size_t size, ZapHeap * pHeap) -{ - return ((LoaderHeap*)pHeap)->AllocMem(S_SIZE_T(size)); -} - -void * operator new[](size_t size, ZapHeap * pHeap) -{ - return ((LoaderHeap*)pHeap)->AllocMem(S_SIZE_T(size)); -} - -//--------------------------------------------------------------------------------------- -// ZapWriter - -ZapWriter::ZapWriter() -{ -} - -ZapWriter::~ZapWriter() -{ - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - pPhysicalSection->~ZapPhysicalSection(); - } - delete (LoaderHeap*)m_pHeap; -} - -void ZapWriter::Initialize() -{ - const DWORD dwReserveSize = 0x1000000; - const DWORD dwCommitSize = 0x10000; - - m_pHeap = reinterpret_cast(new LoaderHeap(dwReserveSize, dwCommitSize)); - - m_isDll = true; - - // Default file alignment - m_FileAlignment = 0x200; -} - -#if defined(TARGET_UNIX) && defined(TARGET_64BIT) -#define SECTION_ALIGNMENT m_FileAlignment -#define PAL_MAX_PAGE_SIZE 0x10000 -#else -#define SECTION_ALIGNMENT 0x1000 -#define PAL_MAX_PAGE_SIZE 0 -#endif - -void ZapWriter::Save(IStream * pStream) -{ - INDEBUG(m_fSaving = TRUE;) - - InitializeWriter(pStream); - - _ASSERTE(m_Sections.GetCount() > 0); - - ZapPhysicalSection * pLastPhysicalSection = m_Sections[m_Sections.GetCount() - 1]; - - ULARGE_INTEGER estimatedFileSize; - estimatedFileSize.QuadPart = pLastPhysicalSection->m_dwFilePos + pLastPhysicalSection->m_dwSizeOfRawData; - - if (CLRConfig::GetConfigValue(CLRConfig::INTERNAL_NGenSimulateDiskFull) != 0) - { - ThrowHR(HRESULT_FROM_WIN32(ERROR_DISK_FULL)); - } - - // Set the file size upfront to reduce disk fragmentation - IfFailThrow(pStream->SetSize(estimatedFileSize)); - - LARGE_INTEGER zero; - zero.QuadPart = 0; - - // Write the content of all sections - IfFailThrow(pStream->Seek(zero, STREAM_SEEK_SET, NULL)); - SaveContent(); - FlushWriter(); - - // Finally write the NT headers - IfFailThrow(pStream->Seek(zero, STREAM_SEEK_SET, NULL)); - SaveHeaders(); - FlushWriter(); -} - -DWORD ZapNode::ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos) -{ - dwPos = AlignUp(dwPos, GetAlignment()); - - SetRVA(dwPos); - - dwPos += GetSize(); - - return dwPos; -} - -void ZapWriter::ComputeRVAs() -{ - DWORD dwHeaderSize = GetSizeOfNTHeaders(); - - DWORD dwPos = dwHeaderSize; - DWORD dwFilePos = dwHeaderSize; - - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - - DWORD dwAlignedFilePos = AlignUp(dwFilePos, m_FileAlignment); - dwFilePos = dwAlignedFilePos; - - pPhysicalSection->m_dwFilePos = dwFilePos; - - dwPos = AlignUp(dwPos, SECTION_ALIGNMENT) + PAL_MAX_PAGE_SIZE; - pPhysicalSection->SetRVA(dwPos); - - DWORD dwEndOfRawData = dwPos; - -#ifdef REDHAWK - printf("Physical Section \"%s\" {\n", pPhysicalSection->m_pszName); -#endif // REDHAWK - - for (COUNT_T iVirtualSection = 0; iVirtualSection < pPhysicalSection->m_Sections.GetCount(); iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->m_Sections[iVirtualSection]; - - // Do not bother with empty virtual sections - if (pVirtualSection->m_Nodes.GetCount() == 0) - continue; - - dwPos = AlignUp(dwPos, pVirtualSection->m_dwAlignment); - pVirtualSection->SetRVA(dwPos); - - for (COUNT_T iNode = 0; iNode < pVirtualSection->m_Nodes.GetCount(); iNode++) - { - ZapNode * pNode = pVirtualSection->m_Nodes[iNode]; - - DWORD dwNextPos = pNode->ComputeRVA(this, dwPos); - _ASSERTE(dwNextPos >= dwPos); - - if (dwNextPos < dwPos || dwNextPos > ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - - dwPos = dwNextPos; - } - - pVirtualSection->m_dwSize = dwPos - pVirtualSection->GetRVA(); - - if (iVirtualSection < pPhysicalSection->m_Sections.GetCount() - pPhysicalSection->m_nBssSections) - dwEndOfRawData = dwPos; -#ifdef REDHAWK - if (pVirtualSection->m_dwSize > 0) - { - printf(" %08x (%6u bytes): %s\n", pVirtualSection->GetRVA(), pVirtualSection->m_dwSize, pVirtualSection->m_pszTag); - } -#endif // REDHAWK - } - - pPhysicalSection->m_dwSize = dwPos - pPhysicalSection->GetRVA(); - - pPhysicalSection->m_dwSizeOfRawData = dwEndOfRawData - pPhysicalSection->GetRVA(); - - dwFilePos += pPhysicalSection->m_dwSizeOfRawData; - -#ifdef REDHAWK - printf(" %08x: end\n", dwPos); - printf("}\n"); -#endif // REDHAWK - } -} - -void ZapWriter::SaveContent() -{ - DWORD dwHeaderSize = GetSizeOfNTHeaders(); - - WritePad(dwHeaderSize); - - DWORD dwPos = dwHeaderSize; - DWORD dwFilePos = dwHeaderSize; - - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - DWORD dwAlignedFilePos = AlignUp(dwFilePos, m_FileAlignment); - WritePad(dwAlignedFilePos - dwFilePos); - dwFilePos = dwAlignedFilePos; - - dwPos = AlignUp(dwPos, SECTION_ALIGNMENT) + PAL_MAX_PAGE_SIZE; - - if (m_fWritingRelocs) - { - pPhysicalSection->m_RVA = dwPos; - pPhysicalSection->m_dwFilePos = dwFilePos; - } - _ASSERTE(pPhysicalSection->GetRVA() == dwPos); - _ASSERTE(pPhysicalSection->m_dwFilePos == dwFilePos); - _ASSERTE(m_dwWriterFilePos == dwFilePos); - - for (COUNT_T iVirtualSection = 0; iVirtualSection < pPhysicalSection->m_Sections.GetCount() - pPhysicalSection->m_nBssSections; iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = pPhysicalSection->m_Sections[iVirtualSection]; - - // Do not bother with empty virtual sections - if (pVirtualSection->m_Nodes.GetCount() == 0) - continue; - - if (m_fWritingRelocs) - { - pVirtualSection->m_RVA = dwPos; - - _ASSERTE(pVirtualSection->m_Nodes.GetCount() == 1); - pVirtualSection->m_Nodes[0]->m_RVA = dwPos; - } - - DWORD dwVirtualSectionPos = pVirtualSection->GetRVA(); - if (dwVirtualSectionPos != dwPos) - WritePad(dwVirtualSectionPos - dwPos); - dwPos = dwVirtualSectionPos; - - for (COUNT_T iNode = 0; iNode < pVirtualSection->m_Nodes.GetCount(); iNode++) - { - ZapNode * pNode = pVirtualSection->m_Nodes[iNode]; - - DWORD dwNodePos = pNode->GetRVA(); - if (dwNodePos != dwPos) - WritePad(dwNodePos - dwPos, pVirtualSection->m_defaultFill); - dwPos = dwNodePos; - - m_dwCurrentRVA = dwPos; - pNode->Save(this); - -#ifdef _DEBUG - if (dwPos + pNode->GetSize() != m_dwCurrentRVA) - { - _ASSERTE(!"Mismatch between ZapNode::GetSize() and ZapNode::Save() implementations"); - pNode->GetSize(); - pNode->Save(this); - } -#endif - - dwPos = m_dwCurrentRVA; - } - - DWORD dwVirtualSectionSize = dwPos - pVirtualSection->GetRVA(); - if (m_fWritingRelocs) - { - pVirtualSection->m_dwSize = dwVirtualSectionSize; - } - _ASSERTE(pVirtualSection->m_dwSize == dwVirtualSectionSize); - } - - DWORD dwPhysicalSectionSize = dwPos - pPhysicalSection->GetRVA(); - if (m_fWritingRelocs) - { - pPhysicalSection->m_dwSize = dwPhysicalSectionSize; - pPhysicalSection->m_dwSizeOfRawData = dwPhysicalSectionSize; - } - _ASSERTE(pPhysicalSection->m_dwSizeOfRawData == dwPhysicalSectionSize); - - dwPos = pPhysicalSection->GetRVA() + pPhysicalSection->m_dwSize; - - dwFilePos += pPhysicalSection->m_dwSizeOfRawData; - } - - WritePad(AlignmentPad(dwFilePos, m_FileAlignment)); -} - -//--------------------------------------------------------------------------------------- -// -// ZapVirtualSection -// -#ifdef REDHAWK -UINT32 ZapVirtualSection::FillInNodeOffsetMap(MapSHash * pMap) -{ - UINT32 dataSize = 0; - for (int i = 0; i < m_Nodes.GetCount(); i++) - { - ZapNode* pNode = m_Nodes[i]; - pMap->Add(pNode, dataSize); - dataSize += pNode->GetSize(); - } - - return dataSize; -} -#endif // REDHAWK - -//--------------------------------------------------------------------------------------- -// Simple buffered writer - -#define WRITE_BUFFER_SIZE 0x10000 - -void ZapWriter::InitializeWriter(IStream * pStream) -{ - m_pBuffer = new (GetHeap()) BYTE[WRITE_BUFFER_SIZE]; - m_nBufferPos = 0; - - m_pStream = pStream; - - INDEBUG(m_dwWriterFilePos = 0;) -} - -void ZapWriter::FlushWriter() -{ - if (m_nBufferPos > 0) - { - ULONG cbWritten; - IfFailThrow(m_pStream->Write(m_pBuffer, m_nBufferPos, &cbWritten)); - _ASSERTE(cbWritten == m_nBufferPos); - - m_nBufferPos = 0; - } -} - -void ZapWriter::Write(PVOID p, DWORD dwSize) -{ - m_dwCurrentRVA += dwSize; - INDEBUG(m_dwWriterFilePos += dwSize;) - - if (m_dwCurrentRVA >= ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - - DWORD cbAvailable = min(dwSize, WRITE_BUFFER_SIZE - m_nBufferPos); - - memcpy(m_pBuffer + m_nBufferPos, p, cbAvailable); - p = (PBYTE)p + cbAvailable; - dwSize -= cbAvailable; - - m_nBufferPos += cbAvailable; - - if (m_nBufferPos < WRITE_BUFFER_SIZE) - return; - - FlushWriter(); - - if (dwSize == 0) - return; - - cbAvailable = AlignDown(dwSize, WRITE_BUFFER_SIZE); - - if (cbAvailable > 0) - { - ULONG cbWritten; - IfFailThrow(m_pStream->Write(p, cbAvailable, &cbWritten)); - _ASSERTE(cbWritten == cbAvailable); - - p = (PBYTE)p + cbAvailable; - dwSize -= cbAvailable; - } - - _ASSERTE(m_nBufferPos == 0); - memcpy(m_pBuffer, p, dwSize); - m_nBufferPos = dwSize; -} - -void ZapWriter::WritePad(DWORD dwSize, BYTE fill) -{ - m_dwCurrentRVA += dwSize; - INDEBUG(m_dwWriterFilePos += dwSize;) - - if (m_dwCurrentRVA >= ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - - DWORD cbAvailable = min(dwSize, WRITE_BUFFER_SIZE - m_nBufferPos); - - memset(m_pBuffer + m_nBufferPos, fill, cbAvailable); - dwSize -= cbAvailable; - - m_nBufferPos += cbAvailable; - - if (m_nBufferPos < WRITE_BUFFER_SIZE) - return; - - FlushWriter(); - - if (dwSize == 0) - return; - - memset(m_pBuffer, fill, min(WRITE_BUFFER_SIZE, dwSize)); - - while (dwSize >= WRITE_BUFFER_SIZE) - { - ULONG cbWritten; - cbAvailable = min(WRITE_BUFFER_SIZE, dwSize); - IfFailThrow(m_pStream->Write(m_pBuffer, cbAvailable, &cbWritten)); - _ASSERTE(cbWritten == cbAvailable); - - dwSize -= cbAvailable; - } - - m_nBufferPos = dwSize; -} - -STDMETHODIMP ZapWriter::Write(void const *pv, ULONG cb, ULONG *pcbWritten) -{ - HRESULT hr = S_OK; - - EX_TRY - { - Write((PVOID)pv, cb); - - if (pcbWritten != 0) - *pcbWritten = cb; - } - EX_CATCH_HRESULT(hr) - - return hr; -} - -//--------------------------------------------------------------------------------------- -// NT Headers - -void ZapWriter::SaveHeaders() -{ - SaveDosHeader(); - SaveSignature(); - SaveFileHeader(); - SaveOptionalHeader(); - SaveSections(); -} - -void ZapWriter::SaveDosHeader() -{ - IMAGE_DOS_HEADER header; - - ZeroMemory(&header, sizeof(header)); - - header.e_magic = VAL16(IMAGE_DOS_SIGNATURE); - header.e_lfanew = VAL32(sizeof(IMAGE_DOS_HEADER)); - - // Legacy tools depend on e_lfarlc to be 0x40 - header.e_lfarlc = VAL16(0x40); - - // We put the PE Signature at 0x80 so that we are the same offset for IL Images - - header.e_lfanew = VAL32(sizeof(IMAGE_DOS_HEADER) + 0x40); - Write(&header, sizeof(header)); - - // Write out padding to get to offset 0x80 - WritePad(0x40); -} - -void ZapWriter::SaveSignature() -{ - ULONG Signature = VAL32(IMAGE_NT_SIGNATURE); - Write(&Signature, sizeof(Signature)); -} - -void ZapWriter::SaveFileHeader() -{ - IMAGE_FILE_HEADER fileHeader; - ZeroMemory(&fileHeader, sizeof(fileHeader)); - - fileHeader.Machine = VAL16(GetMachine()); - fileHeader.TimeDateStamp = VAL32(m_dwTimeDateStamp); - fileHeader.SizeOfOptionalHeader = Is64Bit() ? VAL16(sizeof(IMAGE_OPTIONAL_HEADER64)) : VAL16(sizeof(IMAGE_OPTIONAL_HEADER32)); - - // Count the number of non-empty physical sections - int nSections = 0; - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - if (m_Sections[iPhysicalSection]->m_dwSize != 0) - nSections++; - } - fileHeader.NumberOfSections = VAL16(nSections); - - fileHeader.Characteristics = VAL16(IMAGE_FILE_EXECUTABLE_IMAGE | - (Is64Bit() ? 0 : IMAGE_FILE_32BIT_MACHINE) | - (m_isDll ? IMAGE_FILE_DLL : 0) | - (Is64Bit() ? IMAGE_FILE_LARGE_ADDRESS_AWARE : 0) ); - - Write(&fileHeader, sizeof(fileHeader)); -} - -void ZapWriter::SaveOptionalHeader() -{ - // Write the correct flavor of the optional header - union - { - IMAGE_OPTIONAL_HEADER32 header32; - IMAGE_OPTIONAL_HEADER64 header64; - } - optionalHeader; - - ZeroMemory(&optionalHeader, sizeof(optionalHeader)); - - PIMAGE_OPTIONAL_HEADER pHeader = (PIMAGE_OPTIONAL_HEADER)&optionalHeader; - - // Common fields between 32-bit and 64-bit - - // Linker version should be consistent with current VC level - pHeader->MajorLinkerVersion = 11; - - pHeader->SectionAlignment = VAL32(SECTION_ALIGNMENT); - pHeader->FileAlignment = VAL32(m_FileAlignment); - - // Win2k = 5.0 for 32-bit images, Win2003 = 5.2 for 64-bit images - pHeader->MajorOperatingSystemVersion = VAL16(5); - pHeader->MinorOperatingSystemVersion = Is64Bit() ? VAL16(2) : VAL16(0); - - pHeader->MajorSubsystemVersion = pHeader->MajorOperatingSystemVersion; - pHeader->MinorSubsystemVersion = pHeader->MinorOperatingSystemVersion; - -#ifdef REDHAWK - pHeader->AddressOfEntryPoint = m_entryPointRVA; -#endif - - ZapPhysicalSection * pLastPhysicalSection = m_Sections[m_Sections.GetCount() - 1]; - pHeader->SizeOfImage = VAL32(AlignUp(pLastPhysicalSection->GetRVA() + pLastPhysicalSection->m_dwSize, SECTION_ALIGNMENT)); - - pHeader->SizeOfHeaders = VAL32(AlignUp(GetSizeOfNTHeaders(), m_FileAlignment)); - - pHeader->Subsystem = VAL16(m_Subsystem); - pHeader->DllCharacteristics = VAL16(m_DllCharacteristics); - - - // Different fields between 32-bit and 64-bit - - PIMAGE_DATA_DIRECTORY pDataDirectory; - - if (Is64Bit()) - { - PIMAGE_OPTIONAL_HEADER64 pHeader64 = (PIMAGE_OPTIONAL_HEADER64)pHeader; - - pHeader64->Magic = VAL16(IMAGE_NT_OPTIONAL_HDR64_MAGIC); - - pHeader64->ImageBase = VAL64(m_BaseAddress); - pHeader64->NumberOfRvaAndSizes = VAL32(IMAGE_NUMBEROF_DIRECTORY_ENTRIES); - - pHeader64->SizeOfStackReserve = VAL64(m_SizeOfStackReserve); - pHeader64->SizeOfStackCommit = VAL64(m_SizeOfStackCommit); - - pDataDirectory = pHeader64->DataDirectory; - } - else - { - PIMAGE_OPTIONAL_HEADER32 pHeader32 = (PIMAGE_OPTIONAL_HEADER32)pHeader; - - pHeader32->Magic = VAL16(IMAGE_NT_OPTIONAL_HDR32_MAGIC); - - pHeader32->ImageBase = VAL32((ULONG)m_BaseAddress); - pHeader32->NumberOfRvaAndSizes = VAL32(IMAGE_NUMBEROF_DIRECTORY_ENTRIES); - - pHeader32->SizeOfStackReserve = VAL32((ULONG)m_SizeOfStackReserve); - pHeader32->SizeOfStackCommit = VAL32((ULONG)m_SizeOfStackCommit); - - pDataDirectory = pHeader32->DataDirectory; - } - - for (int i = 0; i < IMAGE_NUMBEROF_DIRECTORY_ENTRIES; i++) - { - SetDirectoryData(&pDataDirectory[i], m_DirectoryEntries[i]); - } - - Write(&optionalHeader, Is64Bit() ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32)); -} - -void ZapWriter::SaveSections() -{ - for (COUNT_T iPhysicalSection = 0; iPhysicalSection < m_Sections.GetCount(); iPhysicalSection++) - { - ZapPhysicalSection * pPhysicalSection = m_Sections[iPhysicalSection]; - - // Do not save empty sections - if (pPhysicalSection->m_dwSize == 0) - continue; - - IMAGE_SECTION_HEADER header; - ZeroMemory(&header, sizeof(header)); - - SIZE_T cbName = strlen(pPhysicalSection->m_pszName); - _ASSERTE(cbName <= sizeof(header.Name)); - memcpy(header.Name, pPhysicalSection->m_pszName, min(sizeof(header.Name), cbName)); - - header.Misc.VirtualSize = VAL32(pPhysicalSection->m_dwSize); - header.VirtualAddress = VAL32(pPhysicalSection->GetRVA()); - - header.SizeOfRawData = VAL32(AlignUp(pPhysicalSection->m_dwSizeOfRawData, m_FileAlignment)); - - if (header.SizeOfRawData != 0) - header.PointerToRawData = VAL32(pPhysicalSection->m_dwFilePos); - - header.Characteristics = VAL32(pPhysicalSection->m_dwCharacteristics); - - Write(&header, sizeof(header)); - } -} - -DWORD ZapWriter::GetSizeOfNTHeaders() -{ - return sizeof(IMAGE_DOS_HEADER) + 0x40 + /* Padding for DOS Header */ - sizeof(ULONG) + - sizeof(IMAGE_FILE_HEADER) + - (Is64Bit() ? sizeof(IMAGE_OPTIONAL_HEADER64) : sizeof(IMAGE_OPTIONAL_HEADER32)) + - (m_Sections.GetCount() * sizeof(IMAGE_SECTION_HEADER)); -} - -void ZapWriter::SetDirectoryData(IMAGE_DATA_DIRECTORY * pDir, ZapNode * pZapNode) -{ - DWORD size = (pZapNode != NULL) ? pZapNode->GetSize() : 0; - - if (size != 0) - { - pDir->VirtualAddress = pZapNode->GetRVA(); - pDir->Size = size; - } - else - { - pDir->VirtualAddress = 0; - pDir->Size = 0; - } -} - -//--------------------------------------------------------------------------------------- -// ZapBlob - -ZapBlob * ZapBlob::NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) -{ - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapBlob)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapBlob * pZapBlob = new (pMemory) ZapBlob(cbSize); - - if (pData != NULL) - memcpy((void*)(pZapBlob + 1), pData, cbSize); - - return pZapBlob; -} - -template -class ZapAlignedBlobConst : public ZapBlob -{ -protected: - ZapAlignedBlobConst(SIZE_T cbSize) - : ZapBlob(cbSize) - { - } - -public: - virtual UINT GetAlignment() - { - return alignment; - } - - static ZapBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize) - { - S_SIZE_T cbAllocSize = S_SIZE_T(sizeof(ZapAlignedBlobConst)) + S_SIZE_T(cbSize); - if(cbAllocSize.IsOverflow()) - ThrowHR(COR_E_OVERFLOW); - - void * pMemory = new (pWriter->GetHeap()) BYTE[cbAllocSize.Value()]; - - ZapAlignedBlobConst * pZapBlob = new (pMemory) ZapAlignedBlobConst(cbSize); - - if (pData != NULL) - memcpy((void *)(pZapBlob + 1), pData, cbSize); - - return pZapBlob; - } -}; - -ZapBlob * ZapBlob::NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment) -{ - switch (cbAlignment) - { - case 4: - return ZapAlignedBlobConst<4>::NewBlob(pWriter, pData, cbSize); - case 8: - return ZapAlignedBlobConst<8>::NewBlob(pWriter, pData, cbSize); - case 16: - return ZapAlignedBlobConst<16>::NewBlob(pWriter, pData, cbSize); - - default: - _ASSERTE(!"Requested alignment not supported"); - return NULL; - } -} - -void ZapBlob::Save(ZapWriter * pZapWriter) -{ - pZapWriter->Write(GetData(), GetSize()); -} diff --git a/src/coreclr/zap/zapwriter.h b/src/coreclr/zap/zapwriter.h deleted file mode 100644 index 295a38ade3958a..00000000000000 --- a/src/coreclr/zap/zapwriter.h +++ /dev/null @@ -1,752 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. -// -// ZapWriter.h -// - -// -// Infrastructure for writing PE files. (Not NGEN specific) -// -// ====================================================================================== - - - -#ifndef __ZAPWRITER_H__ -#define __ZAPWRITER_H__ - -#include "zapnodetype.h" - -class ZapWriter; -class ZapHeap; - -// This is maximum size of anything in the image written by ZapWriter. Used for overflow checking. -#define ZAPWRITER_MAX_SIZE 0x3FFFFFFF - -// All ZapNodes should be allocated from ZapHeap returned by ZapWriter::GetHeap() -void *operator new(size_t size, ZapHeap * pZapHeap); -void *operator new[](size_t size, ZapHeap * pZapHeap); - -// -// ZapHeap does not support deallocation. Empty operators delete avoids deallocating memory -// if the constructor fails -// -inline void operator delete(void *, ZapHeap * pZapHeap) -{ - // Memory allocated by ZapHeap is never freed -} -inline void operator delete[](void *, ZapHeap * pZapHeap) -{ - // Memory allocated by ZapHeap is never freed -} - - -//------------------------------------------------------------------------------------------------------ -// ZapNode is the basic building block of the native image. Every ZapNode must know how to persist itself. -// -// The basic contract for a ZapNode is that it understands its allocations requirements (size and alignment), -// and knows how to save itself (given a ZapWriter). At some point a ZapNode is given a location in the -// executable (an RVA), which it is responsible remembering. -// -// See file:../../doc/BookOfTheRuntime/NGEN/NGENDesign.doc for an overview. -// -class ZapNode -{ - friend class ZapWriter; - - DWORD m_RVA; - -public: - void SetRVA(DWORD dwRVA) - { - _ASSERTE(m_RVA == 0 || m_RVA == (DWORD)-1); - m_RVA = dwRVA; - } - - ZapNode() - { - // All ZapNodes are expected to be allocate from ZapWriter::GetHeap() that returns zero filled memory -#ifdef __GNUC__ -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wuninitialized" -#endif - _ASSERTE(m_RVA == 0); -#ifdef __GNUC__ -#pragma GCC diagnostic pop -#endif - } - - // This constructor should be used to allocate temporary ZapNodes on the stack only - ZapNode(DWORD rva) - : m_RVA(rva) - { - } - - virtual ~ZapNode() - { - } - - // Returns the size of the node in the image. All nodes that are written into the image should override this method. - virtual DWORD GetSize() - { -#if defined(_MSC_VER) //UNREACHABLE doesn't work in GCC, when the method has a non-void return - UNREACHABLE(); -#else - _ASSERTE(!"Unreachable"); - return 0; -#endif - } - - // Alignment for this node. - virtual UINT GetAlignment() - { - return 1; - } - - // Returns the type of the ZapNode. All nodes should override this method. - virtual ZapNodeType GetType() - { - return ZapNodeType_Unknown; - } - - // Assign RVA to this node. dwPos is current RVA, returns updated current RVA. - virtual DWORD ComputeRVA(ZapWriter * pZapWriter, DWORD dwPos); - - // All nodes that are written into the image should override this method. The implementation should write exactly GetSize() bytes - // using ZapWriter::Write method - virtual void Save(ZapWriter * pZapWriter) - { - UNREACHABLE(); - } - - // Returns the RVA of the node. Valid only after ComputeRVA phase - DWORD GetRVA() - { - _ASSERTE(m_RVA != 0 && m_RVA != (DWORD)-1); - return m_RVA; - } - - // Returns whether the node was placed into a virtual section - BOOL IsPlaced() - { - return m_RVA != 0; - } -}; - -//--------------------------------------------------------------------------------------- -// Virtual section of PE image. -class ZapVirtualSection : public ZapNode -{ - friend class ZapWriter; - - DWORD m_dwAlignment; - - SArray m_Nodes; - - // State initialized once the section is placed - DWORD m_dwSize; - - DWORD m_dwSectionType; - - BYTE m_defaultFill; - - ZapVirtualSection(DWORD dwAlignment) - : m_dwAlignment(dwAlignment) - { - } - -public: - virtual DWORD GetSize() - { - return m_dwSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_VirtualSection; - } - - DWORD GetSectionType() - { - return m_dwSectionType; - } - - void SetSectionType(DWORD dwSectionType) - { - _ASSERTE((dwSectionType & IBCTypeReservedFlag) != 0 || !"IBCType flag is not specified"); - _ASSERTE((dwSectionType & RangeTypeReservedFlag) != 0 || !"RangeType flag is not specified"); - _ASSERTE((dwSectionType & VirtualSectionTypeReservedFlag) != 0 || !"VirtualSectionType flag is not specified"); - _ASSERTE((dwSectionType & VirtualSectionTypeReservedFlag) < CORCOMPILE_SECTION_TYPE_COUNT || !"Invalid VirtualSectionType flag"); - m_dwSectionType = dwSectionType; - } - - void SetDefaultFill(BYTE fill) - { - m_defaultFill = fill; - } - - void Place(ZapNode * pNode) - { - _ASSERTE(!pNode->IsPlaced()); - m_Nodes.Append(pNode); - pNode->SetRVA((DWORD)-1); - } - - COUNT_T GetNodeCount() - { - return m_Nodes.GetCount(); - } - - ZapNode * GetNode(COUNT_T iNode) - { - return m_Nodes[iNode]; - } -}; - -//--------------------------------------------------------------------------------------- -// The named physical section of the PE Image. It contains one or more virtual sections. -class ZapPhysicalSection : public ZapNode -{ - friend class ZapWriter; - - SArray m_Sections; - - LPCSTR m_pszName; - DWORD m_dwCharacteristics; - - // Number of zero filled sections (zero filled sections are always last in m_Sections array) - COUNT_T m_nBssSections; - - // State initialized once the section is placed - DWORD m_dwSize; - DWORD m_dwFilePos; - DWORD m_dwSizeOfRawData; - - ZapPhysicalSection(LPCSTR pszName, DWORD dwCharacteristics) - : m_pszName(pszName), - m_dwCharacteristics(dwCharacteristics) - { - } - -public: - ~ZapPhysicalSection() - { - for (COUNT_T iVirtualSection = 0; iVirtualSection < m_Sections.GetCount(); iVirtualSection++) - { - ZapVirtualSection * pVirtualSection = m_Sections[iVirtualSection]; - pVirtualSection->~ZapVirtualSection(); - } - } - - virtual DWORD GetSize() - { - return m_dwSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_PhysicalSection; - } - - DWORD GetFilePos() - { - _ASSERTE(m_dwFilePos != 0); - return m_dwFilePos; - } - - COUNT_T GetVirtualSectionCount() - { - return m_Sections.GetCount(); - } - - ZapVirtualSection * GetVirtualSection(COUNT_T iSection) - { - return m_Sections[iSection]; - } - -}; - -//--------------------------------------------------------------------------------------- -// -// The ZapWriter -// -// Notice that ZapWriter implements IStream that can be passed to APIs that write to stream -// -// The main API in a ZapWriter is (not suprisingly) the code:ZapWriter.Write method. -// -// Relocations are handled by a higher level object, code:ZapImage, which knows about all the sections of a -// ngen image and how to do relections. Every ZapWriter has an associated ZapImage which you get to by -// calling code:ZapImage.GetImage. -// -class ZapWriter : public IStream -{ - ZapHeap * m_pHeap; - - SArray m_Sections; - - ZapNode * m_DirectoryEntries[IMAGE_NUMBEROF_DIRECTORY_ENTRIES]; - DWORD m_dwTimeDateStamp; - ULONGLONG m_BaseAddress; - ULONGLONG m_SizeOfStackReserve; - ULONGLONG m_SizeOfStackCommit; - USHORT m_Subsystem; - USHORT m_DllCharacteristics; - BOOL m_isDll; - DWORD m_FileAlignment; - - // Current state of the writer for debug checks - INDEBUG(BOOL m_fSaving;) - - DWORD m_dwCurrentRVA; - BOOL m_fWritingRelocs; // Set to true once we start reloc sections at the end of the file - - void SaveContent(); - - DWORD GetSizeOfNTHeaders(); - void SaveHeaders(); - - // Simple buffered writer - void InitializeWriter(IStream * pStream); - - IStream * m_pStream; - PBYTE m_pBuffer; - ULONG m_nBufferPos; - INDEBUG(DWORD m_dwWriterFilePos;) - - // - // NT Headers - // - - BOOL Is64Bit() - { -#ifdef TARGET_64BIT - return TRUE; -#else // !TARGET_64BIT - return FALSE; -#endif // !TARGET_64BIT - } - - USHORT GetMachine() - { - return IMAGE_FILE_MACHINE_NATIVE_NI; - } - - void SaveDosHeader(); - void SaveSignature(); - void SaveFileHeader(); - void SaveOptionalHeader(); - void SaveSections(); - - // IStream support - the only actually implemented method is IStream::Write - - // IUnknown methods - STDMETHODIMP_(ULONG) AddRef() - { - return 1; - } - - STDMETHODIMP_(ULONG) Release() - { - return 1; - } - - STDMETHODIMP QueryInterface(REFIID riid, LPVOID *ppv) - { - HRESULT hr = S_OK; - if (IsEqualIID(riid, IID_IUnknown) || IsEqualIID(riid, IID_IStream)) { - *ppv = static_cast(this); - } - else { - *ppv = NULL; - hr = E_NOINTERFACE; - } - return hr; - } - - // ISequentialStream methods: - STDMETHODIMP Read(void *pv, ULONG cb, ULONG *pcbRead) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Write(void const *pv, ULONG cb, ULONG *pcbWritten); - - // IStream methods: - STDMETHODIMP Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) - { - // IMetaDataEmit::SaveToStream calls Seek(0) but ignores the returned error - //_ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP SetSize(ULARGE_INTEGER libNewSize) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Commit(DWORD grfCommitFlags) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Revert() - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Stat(STATSTG *pstatstg, DWORD grfStatFlag) - { - _ASSERTE(false); - return E_NOTIMPL; - } - - STDMETHODIMP Clone(IStream **ppIStream) - { - _ASSERTE(false); - return E_NOTIMPL; - } - -public: - ZapWriter(); - ~ZapWriter(); - - void Initialize(); - - // Create new section in the PE file. The sections will be saved in the order they are created. - ZapPhysicalSection * NewPhysicalSection(LPCSTR pszName, DWORD dwCharacteristics) - { - _ASSERTE(!IsSaving()); - ZapPhysicalSection * pSection = new (GetHeap()) ZapPhysicalSection(pszName, dwCharacteristics); - m_Sections.Append(pSection); - return pSection; - } - - // Create new virtual section within the physical section. The sections will be saved in the order they are created. - // The default virtual section alignment is 16. - ZapVirtualSection * NewVirtualSection(ZapPhysicalSection * pPhysicalSection, DWORD dwAlignment = 16, ZapVirtualSection * pInsertAfter = NULL) - { - _ASSERTE(!IsSaving()); - ZapVirtualSection * pSection = new (GetHeap()) ZapVirtualSection(dwAlignment); - if (pInsertAfter != NULL) - { - // pInsertAfter is workaround to get decent layout with the current scheme of virtual sections. It should not be necessary - // once we have better layout algorithms in place. - for (COUNT_T iSection = 0; iSection < pPhysicalSection->m_Sections.GetCount(); iSection++) - { - if (pPhysicalSection->m_Sections[iSection] == pInsertAfter) - { - pPhysicalSection->m_Sections.Insert(pPhysicalSection->m_Sections+(iSection+1)); - pPhysicalSection->m_Sections[iSection+1] = pSection; - return pSection; - } - } - _ASSERTE(false); - } - - pPhysicalSection->m_Sections.Append(pSection); - return pSection; - } - - void MarkBssSection(ZapPhysicalSection * pPhysicalSection, ZapVirtualSection * pSection) - { - _ASSERTE(!IsSaving()); - _ASSERTE(pPhysicalSection->m_Sections[pPhysicalSection->m_Sections.GetCount() - 1] == pSection); - pPhysicalSection->m_nBssSections++; - } - - void Append(ZapVirtualSection * pVirtualSection, ZapNode * pNode) - { - _ASSERTE(!IsSaving()); - pVirtualSection->m_Nodes.Append(pNode); - } - - // Set the directory entry in the image to match the given ZapNode - void SetDirectoryEntry(DWORD entry, ZapNode * pNode) - { - _ASSERTE(!IsSaving()); - _ASSERTE(entry < IMAGE_NUMBEROF_DIRECTORY_ENTRIES); - _ASSERTE(m_DirectoryEntries[entry] == NULL); - m_DirectoryEntries[entry] = pNode; - } - - // Set the timedate stamp of the image - void SetTimeDateStamp(DWORD dwTimeDateStamp) - { - _ASSERTE(!IsSaving()); - m_dwTimeDateStamp = dwTimeDateStamp; - } - - // Set the base address of the image - void SetBaseAddress(ULONGLONG baseAddress) - { - _ASSERTE(!IsSaving()); - m_BaseAddress = baseAddress; - } - - ULONGLONG GetBaseAddress() - { - _ASSERTE(m_BaseAddress != 0); - return m_BaseAddress; - } - - void SetSizeOfStackReserve(ULONGLONG sizeOfStackReserve) - { - _ASSERTE(!IsSaving()); - m_SizeOfStackReserve = sizeOfStackReserve; - } - - void SetSizeOfStackCommit(ULONGLONG sizeOfStackCommit) - { - _ASSERTE(!IsSaving()); - m_SizeOfStackCommit = sizeOfStackCommit; - } - - void SetSubsystem(USHORT subsystem) - { - _ASSERTE(!IsSaving()); - m_Subsystem = subsystem; - } - - void SetDllCharacteristics(USHORT dllCharacteristics) - { - _ASSERTE(!IsSaving()); - m_DllCharacteristics = dllCharacteristics; - } - - void SetIsDll(BOOL isDLL) - { - m_isDll = isDLL; - } - - void SetFileAlignment(DWORD fileAlignment) - { - m_FileAlignment = fileAlignment; - } - - // Compute RVAs for everything in the file - void ComputeRVAs(); - - // Save the content into stream - void Save(IStream * pStream); - - // Get the heap. The lifetime of this heap is same as the lifetime of the ZapWriter. All ZapNodes should - // be allocated from this heap. - ZapHeap * GetHeap() - { - return m_pHeap; - } - - COUNT_T GetPhysicalSectionCount() - { - return m_Sections.GetCount(); - } - - ZapPhysicalSection * GetPhysicalSection(COUNT_T iSection) - { - return m_Sections[iSection]; - } - -#ifdef _DEBUG - // Certain methods can be called only during the save phase - BOOL IsSaving() - { - return m_fSaving; - } -#endif - - DWORD GetCurrentRVA() - { - _ASSERTE(IsSaving()); - return m_dwCurrentRVA; - } - - - // This is the main entrypoint used to write the image. Every implementation of ZapNode::Save will call this method. - void Write(PVOID p, DWORD dwSize); - - // Writes padding - void WritePad(DWORD size, BYTE fill = 0); - - // Flush any buffered data - void FlushWriter(); - - BOOL IsWritingRelocs() - { - return m_fWritingRelocs; - } - - void SetWritingRelocs() - { - m_fWritingRelocs = TRUE; - } - - // Convenience helper to initialize IMAGE_DATA_DIRECTORY - static void SetDirectoryData(IMAGE_DATA_DIRECTORY * pDir, ZapNode * pZapNode); -}; - -//--------------------------------------------------------------------------------------- -// ZapBlob -// -// Generic node for unstructured sequence of bytes. -// Includes SHash support (ZapBlob::SHashTraits) -// -class ZapBlob : public ZapNode -{ - DWORD m_cbSize; - -protected: - ZapBlob(SIZE_T cbSize) - : m_cbSize((DWORD)cbSize) - { - if (cbSize > ZAPWRITER_MAX_SIZE) - ThrowHR(COR_E_OVERFLOW); - } - -public: - class SHashKey - { - PBYTE m_pData; - SIZE_T m_cbSize; - - public: - SHashKey(PVOID pData, SIZE_T cbSize) - : m_pData((PBYTE)pData), m_cbSize(cbSize) - { - } - - PBYTE GetData() const - { - return m_pData; - } - - SIZE_T GetBlobSize() const - { - return m_cbSize; - } - }; - - class SHashTraits : public DefaultSHashTraits - { - public: - typedef const ZapBlob::SHashKey key_t; - - static key_t GetKey(element_t e) - { - LIMITED_METHOD_CONTRACT; - return key_t(e->GetData(), e->GetBlobSize()); - } - static BOOL Equals(key_t k1, key_t k2) - { - LIMITED_METHOD_CONTRACT; - if (k1.GetBlobSize() != k2.GetBlobSize()) - return FALSE; - return memcmp(k1.GetData(), k2.GetData(), k1.GetBlobSize()) == 0; - } - static count_t Hash(key_t k) - { - LIMITED_METHOD_CONTRACT; - count_t hash = 5381 + (count_t)(k.GetBlobSize() << 7); - - PBYTE pbData = k.GetData(); - PBYTE pbDataEnd = pbData + k.GetBlobSize(); - - for (/**/ ; pbData < pbDataEnd; pbData++) - { - hash = ((hash << 5) + hash) ^ *pbData; - } - return hash; - } - }; - - virtual PBYTE GetData() - { - return (PBYTE)(this + 1); - } - - // Used to shrink the size of the blob - void AdjustBlobSize(SIZE_T cbSize) - { - _ASSERTE(cbSize <= m_cbSize); - _ASSERTE(cbSize != 0); - m_cbSize = (DWORD)cbSize; - } - - // Raw size of the blob - DWORD GetBlobSize() - { - return m_cbSize; - } - - virtual DWORD GetSize() - { - return m_cbSize; - } - - virtual ZapNodeType GetType() - { - return ZapNodeType_Blob; - } - - virtual void Save(ZapWriter * pZapWriter); - - // Create new zap blob node. The node *does* own copy of the memory. - static ZapBlob * NewBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize); - - // Create new aligned zap blob node. - static ZapBlob * NewAlignedBlob(ZapWriter * pWriter, PVOID pData, SIZE_T cbSize, SIZE_T cbAlignment); -}; - -class ZapBlobPtr : public ZapBlob -{ - PBYTE m_pData; - -public: - ZapBlobPtr(PVOID pData, SIZE_T cbSize) - : ZapBlob(cbSize), m_pData((PBYTE)pData) - { - } - - virtual PBYTE GetData() - { - return m_pData; - } -}; - -class ZapDummyNode : public ZapNode -{ - DWORD m_cbSize; - -public: - ZapDummyNode(DWORD cbSize) - : m_cbSize(cbSize) - { - } - - virtual DWORD GetSize() - { - return m_cbSize; - } -}; - -#endif // __ZAPWRITER_H__