Skip to content

Commit addf696

Browse files
authored
Use an ObjectWriter-based PE writer for crossgen2 (#120454)
1 parent da2e367 commit addf696

File tree

84 files changed

+2995
-3535
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

84 files changed

+2995
-3535
lines changed

src/coreclr/tools/Common/Compiler/DependencyAnalysis/ISymbolNode.cs

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,40 @@ public interface ISymbolDefinitionNode : ISymbolNode
7373
new int Offset { get; }
7474
}
7575

76+
/// <summary>
77+
/// Represents a symbol that should encompass the full range between the start and end symbols specified.
78+
/// </summary>
79+
public interface ISymbolRangeNode : ISymbolNode
80+
{
81+
/// <summary>
82+
/// Return a node that determines the start of the range.
83+
/// This node will be used for linkage.
84+
/// </summary>
85+
ISymbolNode StartNode(NodeFactory factory);
86+
87+
/// <summary>
88+
/// Return a node that is used to determine the symbol size.
89+
/// </summary>
90+
ISymbolNode EndNode(NodeFactory factory);
91+
}
92+
93+
/// <summary>
94+
/// Represents a node that generates a checksum for the resulting output blob.
95+
/// </summary>
96+
public interface IChecksumNode : ISymbolNode
97+
{
98+
int ChecksumSize { get; }
99+
100+
void EmitChecksum(ReadOnlySpan<byte> outputBlob, Span<byte> checksumLocation);
101+
}
102+
103+
/// <summary>
104+
/// Represents a symbol that should not be shared with another symbol during writing of the object file.
105+
/// </summary>
106+
public interface IUniqueSymbolNode : ISymbolNode
107+
{
108+
}
109+
76110
public static class ISymbolNodeExtensions
77111
{
78112
[ThreadStatic]

src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectDataBuilder.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,6 +305,10 @@ public void EmitReloc(ISymbolNode symbol, RelocType relocType, int delta = 0)
305305
// Do not vacate space for this kind of relocation, because
306306
// the space is embedded in the instruction.
307307
break;
308+
309+
case RelocType.IMAGE_REL_FILE_CHECKSUM_CALLBACK:
310+
EmitZeros(delta);
311+
break;
308312
default:
309313
throw new NotImplementedException();
310314
}
@@ -315,6 +319,11 @@ public void EmitPointerReloc(ISymbolNode symbol, int delta = 0)
315319
EmitReloc(symbol, (_target.PointerSize == 8) ? RelocType.IMAGE_REL_BASED_DIR64 : RelocType.IMAGE_REL_BASED_HIGHLOW, delta);
316320
}
317321

322+
public void EmitChecksumReloc(IChecksumNode checksum)
323+
{
324+
EmitReloc(checksum, RelocType.IMAGE_REL_FILE_CHECKSUM_CALLBACK, checksum.ChecksumSize);
325+
}
326+
318327
public ObjectNode.ObjectData ToObjectData()
319328
{
320329
#if DEBUG

src/coreclr/tools/Common/Compiler/DependencyAnalysis/ObjectNodeSection.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,5 +51,10 @@ public ObjectNodeSection(string name, SectionType type) : this(name, type, null)
5151

5252
public static readonly ObjectNodeSection ModulesWindowsContentSection = new ObjectNodeSection(".modules$I", SectionType.ReadOnly);
5353
public static readonly ObjectNodeSection ModulesUnixContentSection = new ObjectNodeSection("__modules", SectionType.Writeable);
54+
55+
public static readonly ObjectNodeSection DebugDirectorySection = new ObjectNodeSection("debug", SectionType.Debug);
56+
public static readonly ObjectNodeSection CorMetaSection = new ObjectNodeSection("cormeta", SectionType.ReadOnly);
57+
public static readonly ObjectNodeSection Win32ResourcesSection = new ObjectNodeSection("rsrc", SectionType.ReadOnly);
58+
public static readonly ObjectNodeSection PDataSection = new ObjectNodeSection("pdata", SectionType.ReadOnly);
5459
}
5560
}

src/coreclr/tools/Common/Compiler/DependencyAnalysis/Relocation.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,11 +8,16 @@ namespace ILCompiler.DependencyAnalysis
88
{
99
public enum RelocType
1010
{
11+
// PE base relocation types.
1112
IMAGE_REL_BASED_ABSOLUTE = 0x00, // No relocation required
12-
IMAGE_REL_BASED_ADDR32NB = 0x02, // The 32-bit address without an image base (RVA)
1313
IMAGE_REL_BASED_HIGHLOW = 0x03, // 32 bit address base
1414
IMAGE_REL_BASED_THUMB_MOV32 = 0x07, // Thumb2: based MOVW/MOVT
1515
IMAGE_REL_BASED_DIR64 = 0x0A, // 64 bit address base
16+
17+
// COFF relocation types
18+
IMAGE_REL_BASED_ADDR32NB = 0x0B, // The 32-bit address without an image base (RVA)
19+
20+
// General relocation types
1621
IMAGE_REL_BASED_REL32 = 0x10, // 32-bit relative address from byte following reloc
1722
IMAGE_REL_BASED_THUMB_BRANCH24 = 0x13, // Thumb2: based B, BL
1823
IMAGE_REL_BASED_THUMB_MOV32_PCREL = 0x14, // Thumb2: based MOVW/MOVT
@@ -24,6 +29,7 @@ public enum RelocType
2429
// This is a special NGEN-specific relocation type
2530
// for relative pointer (used to make NGen relocation
2631
// section smaller)
32+
2733
IMAGE_REL_SECTION = 0x79, // 16 bit section index containing target
2834

2935
IMAGE_REL_BASED_ARM64_PAGEBASE_REL21 = 0x81, // ADRP
@@ -63,9 +69,12 @@ public enum RelocType
6369

6470
//
6571
// Relocations for R2R image production
72+
// None of these are "real" relocations that map to an object file's relocation.
73+
// All must be emulated by the object writer.
6674
//
6775
IMAGE_REL_SYMBOL_SIZE = 0x1000, // The size of data in the image represented by the target symbol node
6876
IMAGE_REL_FILE_ABSOLUTE = 0x1001, // 32 bit offset from beginning of image
77+
IMAGE_REL_FILE_CHECKSUM_CALLBACK = 0x1002, // After the image has been emitted, call the IChecksumNode.EmitChecksum method on the target symbol to emit the checksum data.
6978
}
7079

7180
public struct Relocation
@@ -560,7 +569,20 @@ public static int GetSize(RelocType relocType)
560569
{
561570
RelocType.IMAGE_REL_BASED_DIR64 => 8,
562571
RelocType.IMAGE_REL_BASED_HIGHLOW => 4,
572+
RelocType.IMAGE_REL_BASED_ADDR32NB => 4,
573+
RelocType.IMAGE_REL_BASED_REL32 => 4,
563574
RelocType.IMAGE_REL_BASED_RELPTR32 => 4,
575+
RelocType.IMAGE_REL_FILE_ABSOLUTE => 4,
576+
// The relocation itself aren't these sizes, but their values
577+
// are immediates in instructions within
578+
// a span of this many bytes.
579+
RelocType.IMAGE_REL_BASED_ARM64_PAGEBASE_REL21 => 4,
580+
RelocType.IMAGE_REL_BASED_ARM64_PAGEOFFSET_12A => 4,
581+
RelocType.IMAGE_REL_BASED_THUMB_MOV32 => 8,
582+
RelocType.IMAGE_REL_BASED_THUMB_MOV32_PCREL => 8,
583+
RelocType.IMAGE_REL_BASED_LOONGARCH64_PC => 16,
584+
RelocType.IMAGE_REL_BASED_LOONGARCH64_JIR => 16,
585+
RelocType.IMAGE_REL_BASED_RISCV64_PC => 16,
564586
_ => throw new NotSupportedException(),
565587
};
566588
}

src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_ARM64/ARM64Emitter.cs

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,14 +150,22 @@ public void EmitJMP(ISymbolNode symbol)
150150
{
151151
if (symbol.RepresentsIndirectionCell)
152152
{
153+
Builder.RequireInitialPointerAlignment();
154+
155+
if (Builder.CountBytes % Builder.TargetPointerSize == 0)
156+
{
157+
// Emit a NOP instruction to align the 64-bit reloc below.
158+
EmitNOP();
159+
}
160+
153161
// ldr x12, [PC+0xc]
154162
EmitLDR(Register.X12, 0xc);
155163

156164
// ldr x12, [x12]
157165
EmitLDR(Register.X12, Register.X12);
158166

159167
// br x12
160-
Builder.EmitUInt(0xd61f0180);
168+
EmitJMP(Register.X12);
161169

162170
Builder.EmitReloc(symbol, RelocType.IMAGE_REL_BASED_DIR64);
163171
}
@@ -215,6 +223,11 @@ public void EmitJNE(ISymbolNode symbol)
215223
EmitJMP(symbol);
216224
}
217225

226+
public void EmitNOP()
227+
{
228+
Builder.EmitUInt(0xD503201F);
229+
}
230+
218231
private static bool InSignedByteRange(int i)
219232
{
220233
return i == (int)(sbyte)i;

src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_LoongArch64/LoongArch64Emitter.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,14 @@ public void EmitJMP(ISymbolNode symbol)
107107
{
108108
if (symbol.RepresentsIndirectionCell)
109109
{
110+
Builder.RequireInitialPointerAlignment();
111+
112+
if (Builder.CountBytes % Builder.TargetPointerSize != 0)
113+
{
114+
// Emit a NOP instruction to align the 64-bit reloc below.
115+
EmitNOP();
116+
}
117+
110118
// pcaddi R21, 0
111119
EmitPCADDI(Register.R21);
112120

@@ -150,5 +158,11 @@ public void EmitDBAR()
150158
{
151159
Builder.EmitUInt(0x38720000);
152160
}
161+
162+
// nop
163+
public void EmitNOP()
164+
{
165+
Builder.EmitUInt(0x03400000);
166+
}
153167
}
154168
}

src/coreclr/tools/Common/Compiler/DependencyAnalysis/Target_RiscV64/RiscV64Emitter.cs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,14 @@ public void EmitJMP(ISymbolNode symbol)
103103
{
104104
if (symbol.RepresentsIndirectionCell)
105105
{
106+
Builder.RequireInitialPointerAlignment();
107+
108+
if (Builder.CountBytes % Builder.TargetPointerSize != 0)
109+
{
110+
// Emit a NOP instruction to align the 64-bit reloc below.
111+
EmitNOP();
112+
}
113+
106114
// auipc x29, 0
107115
EmitPC(Register.X29);
108116
// ld x29,16(x29)
@@ -137,5 +145,10 @@ public void EmitJMPIfZero(Register regSrc, ISymbolNode symbol)
137145
Builder.EmitUInt((uint)(0x00001063 | ((uint)regSrc << 15) | encodedOffset));
138146
EmitJMP(symbol);
139147
}
148+
149+
public void EmitNOP()
150+
{
151+
Builder.EmitUInt(0x00000013);
152+
}
140153
}
141154
}

0 commit comments

Comments
 (0)