diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs index 41bf7f7c79c1ec..81635d1109e697 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/CodeGen/ReadyToRunObjectWriter.cs @@ -206,7 +206,7 @@ public void EmitPortableExecutable() if (_nodeFactory.CompilationModuleGroup.IsCompositeBuildMode && _componentModule == null) { - headerBuilder = PEHeaderProvider.Create(Subsystem.Unknown, _nodeFactory.Target); + headerBuilder = PEHeaderProvider.Create(Subsystem.Unknown, _nodeFactory.Target, _nodeFactory.ImageBase); peIdProvider = new Func, BlobContentId>(content => BlobContentId.FromHash(CryptographicHashProvider.ComputeSourceHash(content))); timeDateStamp = null; r2rHeaderExportSymbol = _nodeFactory.Header; @@ -214,7 +214,7 @@ public void EmitPortableExecutable() else { PEReader inputPeReader = (_componentModule != null ? _componentModule.PEReader : _nodeFactory.CompilationModuleGroup.CompilationModuleSet.First().PEReader); - headerBuilder = PEHeaderProvider.Create(inputPeReader.PEHeaders.PEHeader.Subsystem, _nodeFactory.Target); + headerBuilder = PEHeaderProvider.Create(inputPeReader.PEHeaders.PEHeader.Subsystem, _nodeFactory.Target, _nodeFactory.ImageBase); timeDateStamp = inputPeReader.PEHeaders.CoffHeader.TimeDateStamp; r2rHeaderExportSymbol = null; } diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs index 4fd1f958d9c3b1..0bdfd7f59f403e 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRunCodegenNodeFactory.cs @@ -63,6 +63,8 @@ public sealed class NodeFactory public CompositeImageSettings CompositeImageSettings { get; set; } + public ulong ImageBase; + public bool MarkingComplete => _markingComplete; public void SetMarkingComplete() @@ -155,7 +157,8 @@ public NodeFactory( CopiedCorHeaderNode corHeaderNode, DebugDirectoryNode debugDirectoryNode, ResourceData win32Resources, - ReadyToRunFlags flags) + ReadyToRunFlags flags, + ulong imageBase) { TypeSystemContext = context; CompilationModuleGroup = compilationModuleGroup; @@ -167,6 +170,7 @@ public NodeFactory( DebugDirectoryNode = debugDirectoryNode; Resolver = compilationModuleGroup.Resolver; Header = new GlobalHeaderNode(Target, flags); + ImageBase = imageBase; if (!win32Resources.IsEmpty) Win32ResourcesNode = new Win32ResourcesNode(win32Resources); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs index ad6f407ff7d800..69876fa3c50bf1 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilation.cs @@ -411,7 +411,8 @@ private void RewriteComponentFile(string inputFile, string outputFile, string ow copiedCorHeader, debugDirectory, win32Resources: new Win32Resources.ResourceData(inputModule), - flags); + flags, + _nodeFactory.ImageBase); IComparer> comparer = new SortableDependencyNode.ObjectNodeComparer(new CompilerComparer()); DependencyAnalyzerBase componentGraph = new DependencyAnalyzer, NodeFactory>(componentFactory, comparer); diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs index 46ed11d236a953..e5c6b050dae3a3 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/ReadyToRunCodegenCompilationBuilder.cs @@ -40,6 +40,7 @@ public sealed class ReadyToRunCodegenCompilationBuilder : CompilationBuilder private int _customPESectionAlignment; private bool _verifyTypeAndFieldLayout; private CompositeImageSettings _compositeImageSettings; + private ulong _imageBase; private string _jitPath; private string _outputFile; @@ -198,6 +199,12 @@ public ReadyToRunCodegenCompilationBuilder UseCompositeImageSettings(CompositeIm return this; } + public ReadyToRunCodegenCompilationBuilder UseImageBase(ulong imageBase) + { + _imageBase = imageBase; + return this; + } + public override ICompilation ToCompilation() { // TODO: only copy COR headers for single-assembly build and for composite build with embedded MSIL @@ -240,7 +247,9 @@ public override ICompilation ToCompilation() corHeaderNode, debugDirectoryNode, win32Resources, - flags); + flags, + _imageBase + ); factory.CompositeImageSettings = _compositeImageSettings; diff --git a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs index 608e159f7f6e36..697ce213ec4647 100644 --- a/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs +++ b/src/coreclr/tools/aot/ILCompiler.ReadyToRun/ObjectWriter/R2RPEBuilder.cs @@ -673,15 +673,13 @@ static class PEHeaderProvider /// /// Targeting subsystem /// Target architecture to set in the header - public static PEHeaderBuilder Create(Subsystem subsystem, TargetDetails target) + public static PEHeaderBuilder Create(Subsystem subsystem, TargetDetails target, ulong imageBase) { bool is64BitTarget = target.PointerSize == sizeof(long); Characteristics imageCharacteristics = Characteristics.ExecutableImage | Characteristics.Dll; imageCharacteristics |= is64BitTarget ? Characteristics.LargeAddressAware : Characteristics.Bit32Machine; - ulong imageBase = is64BitTarget ? PE64HeaderConstants.DllImageBase : PE32HeaderConstants.ImageBase; - int fileAlignment = 0x200; bool isWindowsOr32bit = target.IsWindows || !is64BitTarget; if (isWindowsOr32bit) diff --git a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs index 752b1194259e49..0c431a29863963 100644 --- a/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs +++ b/src/coreclr/tools/aot/crossgen2/CommandLineOptions.cs @@ -65,6 +65,7 @@ internal class CommandLineOptions public string FileLayout; public bool VerifyTypeAndFieldLayout; public string CallChainProfileFile; + public string ImageBase; public string SingleMethodTypeName; public string SingleMethodName; @@ -143,6 +144,7 @@ public CommandLineOptions(string[] args) syntax.DefineOption("waitfordebugger", ref WaitForDebugger, SR.WaitForDebuggerOption); syntax.DefineOptionList("codegenopt|codegen-options", ref CodegenOptions, SR.CodeGenOptions); syntax.DefineOption("resilient", ref Resilient, SR.ResilientOption); + syntax.DefineOption("imagebase", ref ImageBase, SR.ImageBase); syntax.DefineOption("targetarch", ref TargetArch, SR.TargetArchOption); syntax.DefineOption("targetos", ref TargetOS, SR.TargetOSOption); diff --git a/src/coreclr/tools/aot/crossgen2/Program.cs b/src/coreclr/tools/aot/crossgen2/Program.cs index 6eedd33da4a6d0..1c983735102cf5 100644 --- a/src/coreclr/tools/aot/crossgen2/Program.cs +++ b/src/coreclr/tools/aot/crossgen2/Program.cs @@ -29,6 +29,7 @@ internal class Program public TargetArchitecture _targetArchitecture; private bool _armelAbi = false; public OptimizationMode _optimizationMode; + private ulong _imageBase; // File names as strings in args private Dictionary _inputFilePaths = new Dictionary(StringComparer.OrdinalIgnoreCase); @@ -318,6 +319,16 @@ private InstructionSetSupport ConfigureInstructionSetSupport() _targetArchitecture); } + private void ConfigureImageBase(TargetDetails targetDetails) + { + bool is64BitTarget = targetDetails.PointerSize == sizeof(long); + + if (_commandLineOptions.ImageBase != null) + _imageBase = is64BitTarget ? Convert.ToUInt64(_commandLineOptions.ImageBase, 16) : Convert.ToUInt32(_commandLineOptions.ImageBase, 16); + else + _imageBase = is64BitTarget ? PEWriter.PE64HeaderConstants.DllImageBase : PEWriter.PE32HeaderConstants.ImageBase; + } + private int Run(string[] args) { InitializeDefaultOptions(); @@ -343,6 +354,8 @@ private int Run(string[] args) var targetDetails = new TargetDetails(_targetArchitecture, _targetOS, _armelAbi ? TargetAbi.CoreRTArmel : TargetAbi.CoreRT, instructionSetSupport.GetVectorTSimdVector()); + ConfigureImageBase(targetDetails); + bool versionBubbleIncludesCoreLib = false; if (_commandLineOptions.InputBubble) { @@ -743,6 +756,7 @@ private void RunSingleCompilation(Dictionary inFilePaths, Instru .UseCustomPESectionAlignment(_commandLineOptions.CustomPESectionAlignment) .UseVerifyTypeAndFieldLayout(_commandLineOptions.VerifyTypeAndFieldLayout) .GenerateOutputFile(outFile) + .UseImageBase(_imageBase) .UseILProvider(ilProvider) .UseBackendOptions(_commandLineOptions.CodegenOptions) .UseLogger(logger) diff --git a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx index 903ae55086e320..04ef03c237af9c 100644 --- a/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx +++ b/src/coreclr/tools/aot/crossgen2/Properties/Resources.resx @@ -372,4 +372,7 @@ Input file with '{0}' extension not supported + + Hexademical value to set target PE-file ImageBase field +