Skip to content

Commit db5d3c7

Browse files
committed
Enhancement: support for platform-specific patterns for procedure entries.
1 parent 432fc95 commit db5d3c7

8 files changed

Lines changed: 112 additions & 77 deletions

src/Core/Configuration/PlatformArchitectureDefinition.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,12 @@ public PlatformArchitectureDefinition()
3535
{
3636
this.TrashedRegisters = new List<string>();
3737
this.TypeLibraries = new List<TypeLibraryDefinition>();
38+
this.ProcedurePrologs = new List<MaskedPattern>();
3839
}
3940

4041
public string? Name { get; set; }
41-
public List<string> TrashedRegisters { get; internal set; }
42-
public List<TypeLibraryDefinition> TypeLibraries { get; internal set; }
42+
public List<string> TrashedRegisters { get; set; }
43+
public List<TypeLibraryDefinition> TypeLibraries { get; set; }
44+
public List<MaskedPattern> ProcedurePrologs { get; set; }
4345
}
4446
}

src/Core/Configuration/PlatformDefinition.cs

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,7 @@ private PlatformHeuristics LoadHeuristics(PlatformHeuristics_v1? heuristics)
114114
else
115115
{
116116
prologs = heuristics.ProcedurePrologs
117-
.Select(p => LoadMaskedPattern(p)!)
117+
.Select(p => MaskedPattern.Load(p.Bytes, p.Mask)!)
118118
.Where(p => p != null && p.Bytes != null)
119119
.ToArray();
120120
}
@@ -125,68 +125,6 @@ private PlatformHeuristics LoadHeuristics(PlatformHeuristics_v1? heuristics)
125125
};
126126
}
127127

128-
public MaskedPattern? LoadMaskedPattern(BytePattern_v1 sPattern)
129-
{
130-
if (sPattern.Bytes == null)
131-
return null;
132-
if (sPattern.Mask == null)
133-
{
134-
var bytes = new List<byte>();
135-
var mask = new List<byte>();
136-
int shift = 4;
137-
int bb = 0;
138-
int mm = 0;
139-
for (int i = 0; i < sPattern.Bytes.Length; ++i)
140-
{
141-
char c = sPattern.Bytes[i];
142-
if (BytePattern.TryParseHexDigit(c, out byte b))
143-
{
144-
bb |= (b << shift);
145-
mm |= (0x0F << shift);
146-
shift -= 4;
147-
if (shift < 0)
148-
{
149-
bytes.Add((byte)bb);
150-
mask.Add((byte)mm);
151-
shift = 4;
152-
bb = mm = 0;
153-
}
154-
}
155-
else if (c == '?' || c == '.')
156-
{
157-
shift -= 4;
158-
if (shift < 0)
159-
{
160-
bytes.Add((byte)bb);
161-
mask.Add((byte)mm);
162-
shift = 4;
163-
bb = mm = 0;
164-
}
165-
}
166-
}
167-
Debug.Assert(bytes.Count == mask.Count);
168-
if (bytes.Count == 0)
169-
return null;
170-
return new MaskedPattern
171-
{
172-
Bytes = bytes.ToArray(),
173-
Mask = mask.ToArray()
174-
};
175-
}
176-
else
177-
{
178-
var bytes = BytePattern.FromHexBytes(sPattern.Bytes);
179-
var mask = BytePattern.FromHexBytes(sPattern.Mask);
180-
if (bytes.Length == 0)
181-
return null;
182-
return new MaskedPattern
183-
{
184-
Bytes = bytes.ToArray(),
185-
Mask = mask.ToArray()
186-
};
187-
}
188-
}
189-
190128
private Dictionary<Address, ExternalProcedure> LoadPlatformProcedures(Platform platform)
191129
{
192130
if (platform.MemoryMap != null && platform.MemoryMap.Segments != null)

src/Core/Configuration/RekoConfigurationService.cs

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -207,15 +207,28 @@ private TypeLibraryDefinition LoadTypeLibraryReference(TypeLibraryReference_v1 t
207207
private PlatformArchitectureDefinition LoadPlatformArchitecture(PlatformArchitecture_v1 spa)
208208
{
209209
var sTrashedRegs = spa.TrashedRegisters ?? "";
210-
var sLibraries = spa.TypeLibraries ?? new TypeLibraryReference_v1[0];
210+
List<MaskedPattern> prologs;
211+
if (spa.ProcedurePrologs is null)
212+
{
213+
prologs = new();
214+
}
215+
else
216+
{
217+
prologs = spa.ProcedurePrologs
218+
.Select(p => MaskedPattern.Load(p.Bytes, p.Mask)!)
219+
.Where(p => p != null && p.Bytes != null)
220+
.ToList();
221+
}
222+
211223
return new PlatformArchitectureDefinition
212224
{
213225
Name = spa.Name,
214226
TrashedRegisters = sTrashedRegs
215227
.Split(',')
216228
.Select(s => s.Trim())
217229
.ToList(),
218-
TypeLibraries = LoadCollection(sLibraries, LoadTypeLibraryReference)
230+
TypeLibraries = LoadCollection(spa.TypeLibraries, LoadTypeLibraryReference),
231+
ProcedurePrologs = prologs
219232
};
220233
}
221234

src/Core/Configuration/RekoConfiguration_v1.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,6 +355,11 @@ public class PlatformArchitecture_v1
355355
[XmlArray("TypeLibraries")]
356356
[XmlArrayItem("TypeLibrary")]
357357
public TypeLibraryReference_v1[]? TypeLibraries;
358+
359+
[XmlArray("ProcedurePrologs")]
360+
[XmlArrayItem("Pattern")]
361+
public BytePattern_v1[]? ProcedurePrologs;
362+
358363
}
359364

360365
/// <summary>

src/Core/PlatformHeuristics.cs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
using System;
2222
using System.Collections.Generic;
23+
using System.Diagnostics;
2324
using System.Linq;
2425
using System.Text;
2526

@@ -34,5 +35,67 @@ public class MaskedPattern
3435
{
3536
public byte[]? Bytes;
3637
public byte[]? Mask;
38+
39+
public static MaskedPattern? Load(string? sBytes, string? sMask)
40+
{
41+
if (sBytes == null)
42+
return null;
43+
if (sMask == null)
44+
{
45+
var bytes = new List<byte>();
46+
var mask = new List<byte>();
47+
int shift = 4;
48+
int bb = 0;
49+
int mm = 0;
50+
for (int i = 0; i < sBytes.Length; ++i)
51+
{
52+
char c = sBytes[i];
53+
if (BytePattern.TryParseHexDigit(c, out byte b))
54+
{
55+
bb |= (b << shift);
56+
mm |= (0x0F << shift);
57+
shift -= 4;
58+
if (shift < 0)
59+
{
60+
bytes.Add((byte) bb);
61+
mask.Add((byte) mm);
62+
shift = 4;
63+
bb = mm = 0;
64+
}
65+
}
66+
else if (c == '?' || c == '.')
67+
{
68+
shift -= 4;
69+
if (shift < 0)
70+
{
71+
bytes.Add((byte) bb);
72+
mask.Add((byte) mm);
73+
shift = 4;
74+
bb = mm = 0;
75+
}
76+
}
77+
}
78+
Debug.Assert(bytes.Count == mask.Count);
79+
if (bytes.Count == 0)
80+
return null;
81+
return new MaskedPattern
82+
{
83+
Bytes = bytes.ToArray(),
84+
Mask = mask.ToArray()
85+
};
86+
}
87+
else
88+
{
89+
var bytes = BytePattern.FromHexBytes(sBytes);
90+
var mask = BytePattern.FromHexBytes(sMask);
91+
if (bytes.Length == 0)
92+
return null;
93+
return new MaskedPattern
94+
{
95+
Bytes = bytes.ToArray(),
96+
Mask = mask.ToArray()
97+
};
98+
}
99+
}
37100
}
38101
}

src/Drivers/reko.config

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,12 @@
195195
<Architectures>
196196
<Architecture name="x86-protected-32">
197197
<TrashedRegisters>eax,ecx,edx</TrashedRegisters>
198+
<ProcedurePrologs>
199+
<Pattern>
200+
<Bytes>55 8B EC</Bytes>
201+
<Mask>FF FF FF</Mask>
202+
</Pattern>
203+
</ProcedurePrologs>
198204
</Architecture>
199205
<Architecture name="x86-protected-64">
200206
<TrashedRegisters>rax,rcx,rdx,rsi,rdi,r8,r9,r10,r11</TrashedRegisters>

src/UnitTests/Core/Configuration/OperatingEnvironmentElementTests.cs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#region License
1+
#region License
22
/*
33
* Copyright (C) 1999-2022 John Källén.
44
*
@@ -40,7 +40,7 @@ public void Oee_LoadPrologPattern_WithMask()
4040
Mask = "FF C0 0F",
4141
};
4242
var element = new PlatformDefinition();
43-
var pattern = element.LoadMaskedPattern(sPattern);
43+
var pattern = MaskedPattern.Load(sPattern.Bytes, sPattern.Mask);
4444
Assert.AreEqual(new byte[] { 0x55, 0x32, 0x12 }, pattern.Bytes);
4545
Assert.AreEqual(new byte[] { 0xFF, 0xC0, 0x0F }, pattern.Mask);
4646
}
@@ -53,7 +53,7 @@ public void Oee_LoadPrologPattern_WithoutMask()
5353
Bytes = "55 3? ?2",
5454
};
5555
var element = new PlatformDefinition();
56-
var pattern = element.LoadMaskedPattern(sPattern);
56+
var pattern = MaskedPattern.Load(sPattern.Bytes, sPattern.Mask);
5757
Assert.AreEqual(new byte[] { 0x55, 0x30, 0x02 }, pattern.Bytes);
5858
Assert.AreEqual(new byte[] { 0xFF, 0xF0, 0x0F }, pattern.Mask);
5959
}

src/UnitTests/Core/Configuration/RekoConfigurationServiceTests.cs

Lines changed: 15 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -81,13 +81,20 @@ public void Rcfg_LoadOperatingEnvironment()
8181
new PlatformArchitecture_v1
8282
{
8383
Name="testCPU",
84-
TypeLibraries = new[]
85-
{
86-
new TypeLibraryReference_v1
87-
{
88-
Name = "lp32.xml",
89-
}
90-
}
84+
TypeLibraries = new[]
85+
{
86+
new TypeLibraryReference_v1
87+
{
88+
Name = "lp32.xml",
89+
}
90+
},
91+
ProcedurePrologs = new[]
92+
{
93+
new BytePattern_v1
94+
{
95+
Bytes = "55 8B EC"
96+
}
97+
}
9198
}
9299
}
93100
}
@@ -107,6 +114,7 @@ public void Rcfg_LoadOperatingEnvironment()
107114
var archs = env.Architectures;
108115
Assert.AreEqual(1, archs.Count);
109116
Assert.AreEqual("lp32.xml", archs[0].TypeLibraries[0].Name);
117+
Assert.AreEqual(0xEC, archs[0].ProcedurePrologs[0].Bytes[2]);
110118
}
111119

112120
[Test]

0 commit comments

Comments
 (0)