Skip to content

Commit 870ce3e

Browse files
authored
Fix RVA field alignment (#888)
* Fix RVA field alignment * Use non-latest images to run tests * Revert windows-2019 change * Don't align code segment This wasn't aligned to begin with. Attempting to align it causes problems due to the way CodeWriter gets the code RVA - it computes the RVA from the CLI Header length, which doesn't take into account the code's alignment requirements. * Revert "Don't align code segment" This reverts commit 9410f1e. * Keep alignment values for code
1 parent 4ad9c0f commit 870ce3e

File tree

6 files changed

+47
-6
lines changed

6 files changed

+47
-6
lines changed

.github/workflows/main.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ jobs:
2020
- name: Test
2121
run: dotnet test --no-build -c Debug Mono.Cecil.sln
2222
linux:
23-
runs-on: ubuntu-latest
23+
runs-on: ubuntu-20.04
2424
steps:
2525
- uses: actions/checkout@v1
2626
- name: Build

Mono.Cecil.Cil/CodeWriter.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ sealed class CodeWriter : ByteBuffer {
3232
public CodeWriter (MetadataBuilder metadata)
3333
: base (0)
3434
{
35-
this.code_base = metadata.text_map.GetNextRVA (TextSegment.CLIHeader);
35+
this.code_base = metadata.text_map.GetRVA (TextSegment.Code);
3636
this.metadata = metadata;
3737
this.standalone_signatures = new Dictionary<uint, MetadataToken> ();
3838
this.tiny_method_bodies = new Dictionary<ByteBuffer, RVA> (new ByteBufferEqualityComparer ());

Mono.Cecil.PE/TextMap.cs

+23-2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
//
1010

1111
using System;
12+
using System.Diagnostics;
1213

1314
using RVA = System.UInt32;
1415

@@ -47,11 +48,31 @@ public void AddMap (TextSegment segment, int length)
4748
map [(int) segment] = new Range (GetStart (segment), (uint) length);
4849
}
4950

50-
public void AddMap (TextSegment segment, int length, int align)
51+
uint AlignUp (uint value, uint align)
5152
{
5253
align--;
54+
return (value + align) & ~align;
55+
}
5356

54-
AddMap (segment, (length + align) & ~align);
57+
public void AddMap (TextSegment segment, int length, int align)
58+
{
59+
var index = (int) segment;
60+
uint start;
61+
if (index != 0) {
62+
// Align up the previous segment's length so that the new
63+
// segment's start will be aligned.
64+
index--;
65+
Range previous = map [index];
66+
start = AlignUp (previous.Start + previous.Length, (uint) align);
67+
map [index].Length = start - previous.Start;
68+
} else {
69+
start = ImageWriter.text_rva;
70+
// Should already be aligned.
71+
Debug.Assert (start == AlignUp (start, (uint) align));
72+
}
73+
Debug.Assert (start == GetStart (segment));
74+
75+
map [(int) segment] = new Range (start, (uint) length);
5576
}
5677

5778
public void AddMap (TextSegment segment, Range range)

Mono.Cecil/AssemblyWriter.cs

+5
Original file line numberDiff line numberDiff line change
@@ -987,6 +987,11 @@ TextMap CreateTextMap ()
987987
var map = new TextMap ();
988988
map.AddMap (TextSegment.ImportAddressTable, module.Architecture == TargetArchitecture.I386 ? 8 : 0);
989989
map.AddMap (TextSegment.CLIHeader, 0x48, 8);
990+
var pe64 = module.Architecture == TargetArchitecture.AMD64 || module.Architecture == TargetArchitecture.IA64 || module.Architecture == TargetArchitecture.ARM64;
991+
// Alignment of the code segment must be set before the code is written
992+
// These alignment values are probably not necessary, but are being left in
993+
// for now in case something requires them.
994+
map.AddMap (TextSegment.Code, 0, !pe64 ? 4 : 16);
990995
return map;
991996
}
992997

Test/Mono.Cecil.Tests/FieldTests.cs

+3-2
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,7 @@ public void FieldRVAAlignment ()
160160
var priv_impl = GetPrivateImplementationType (module);
161161
Assert.IsNotNull (priv_impl);
162162

163-
Assert.AreEqual (6, priv_impl.Fields.Count);
163+
Assert.AreEqual (8, priv_impl.Fields.Count);
164164

165165
foreach (var field in priv_impl.Fields)
166166
{
@@ -170,7 +170,8 @@ public void FieldRVAAlignment ()
170170
Assert.IsNotNull (field.InitialValue);
171171

172172
int rvaAlignment = AlignmentOfInteger (field.RVA);
173-
int desiredAlignment = Math.Min(8, AlignmentOfInteger (field.InitialValue.Length));
173+
var fieldType = field.FieldType.Resolve ();
174+
int desiredAlignment = fieldType.PackingSize;
174175
Assert.GreaterOrEqual (rvaAlignment, desiredAlignment);
175176
}
176177
}

Test/Resources/il/FieldRVAAlignment.il

+14
Original file line numberDiff line numberDiff line change
@@ -46,12 +46,22 @@
4646
.size 6
4747
} // end of class '__StaticArrayInitTypeSize=6'
4848

49+
.class explicit ansi sealed nested private '__StaticArrayInitTypeSize=4Align=32'
50+
extends [mscorlib]System.ValueType
51+
{
52+
.pack 32
53+
.size 4
54+
}
55+
4956
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=3' '$$method0x6000001-1' at I_000020F0
5057
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=20' '$$method0x6000001-2' at I_000020F8
5158
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=5' '$$method0x6000001-3' at I_00002108
5259
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=20' '$$method0x6000001-4' at I_00002110
5360
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=6' '$$method0x6000001-5' at I_00002120
5461
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=16' '$$method0x6000001-6' at I_00002130
62+
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=3' 'separator' at I_00002140
63+
.field static assembly valuetype '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'/'__StaticArrayInitTypeSize=4Align=32' '32_align' at I_00002150
64+
5565
} // end of class '<PrivateImplementationDetails>{9B33BB20-87EF-4094-9948-34882DB2F001}'
5666

5767

@@ -69,3 +79,7 @@
6979
08 00 0C 00 0D 00)
7080
.data cil I_00002130 = bytearray (
7181
01 00 00 00 02 00 00 00 03 00 00 00 05 00 00 00)
82+
.data cil I_00002140 = bytearray (
83+
01 02 03)
84+
.data cil I_00002150 = bytearray (
85+
01 02 03 04)

0 commit comments

Comments
 (0)