Skip to content

Commit 461f7cb

Browse files
authored
Add custom architecture instruction info (#146)
1 parent 1ad066b commit 461f7cb

3 files changed

Lines changed: 144 additions & 32 deletions

File tree

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
using System;
2+
using System.Runtime.InteropServices;
3+
4+
namespace BinaryNinja
5+
{
6+
public abstract partial class CustomArchitecture
7+
{
8+
[UnmanagedFunctionPointer(System.Runtime.InteropServices.CallingConvention.Cdecl)]
9+
[return: MarshalAs(UnmanagedType.I1)]
10+
private delegate bool GetInstructionInfoCallback(
11+
IntPtr context,
12+
IntPtr data,
13+
ulong address,
14+
ulong maximumLength,
15+
IntPtr result);
16+
17+
private void AddInstructionCallbacks(ref BNCustomArchitecture callbacks)
18+
{
19+
callbacks.getInstructionInfo = UnsafeUtils.PinCallback<GetInstructionInfoCallback>(
20+
this.GetInstructionInfoAdapter);
21+
}
22+
23+
private bool GetInstructionInfoAdapter(
24+
IntPtr context,
25+
IntPtr data,
26+
ulong address,
27+
ulong maximumLength,
28+
IntPtr result)
29+
{
30+
try
31+
{
32+
byte[] bytes = new byte[checked((int)maximumLength)];
33+
if (0 != bytes.Length)
34+
{
35+
Marshal.Copy(data, bytes, 0, bytes.Length);
36+
}
37+
38+
InstructionInfo? info = this.GetInstructionInfo(bytes, address);
39+
if (null == info)
40+
{
41+
return false;
42+
}
43+
44+
Marshal.StructureToPtr(info.ToNative(), result, false);
45+
46+
return true;
47+
}
48+
catch (Exception exception)
49+
{
50+
Core.LogError(
51+
"Unhandled exception in CustomArchitecture.GetInstructionInfo: {0}",
52+
exception);
53+
54+
return false;
55+
}
56+
}
57+
}
58+
}

Architecture/CustomArchitectureRegistration.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,7 @@ public Architecture Register(string name)
6161
};
6262
this.AddRegisterCallbacks(ref callbacks);
6363
this.AddFlagCallbacks(ref callbacks);
64+
this.AddInstructionCallbacks(ref callbacks);
6465

6566
using (ScopedAllocator allocator = new ScopedAllocator())
6667
{

Struct/BNInstructionInfo.cs

Lines changed: 85 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -58,21 +58,23 @@ public unsafe struct BNInstructionInfo
5858
internal IntPtr branchArch_2;
5959
}
6060

61-
public sealed class InstructionInfo
62-
{
63-
public ulong Length { get;} = 0;
64-
65-
public ulong BranchCount { get;} = 0;
61+
public sealed class InstructionInfo
62+
{
63+
private const int MaximumBranchCount = 3;
6664

67-
public bool ArchTransitionByTargetAddr { get;} = false;
68-
69-
public byte DelaySlots { get; } = 0;
70-
71-
public BranchType[] BranchType { get;} = Array.Empty<BranchType>();
72-
73-
public ulong[] BranchTarget { get;} = Array.Empty<ulong>();
74-
75-
public Architecture[] BranchArch { get;} = Array.Empty<Architecture>();
65+
public ulong Length { get; set; } = 0;
66+
67+
public ulong BranchCount { get; private set; } = 0;
68+
69+
public bool ArchTransitionByTargetAddr { get; set; } = false;
70+
71+
public byte DelaySlots { get; set; } = 0;
72+
73+
public BranchType[] BranchType { get; private set; } = Array.Empty<BranchType>();
74+
75+
public ulong[] BranchTarget { get; private set; } = Array.Empty<ulong>();
76+
77+
public Architecture?[] BranchArch { get; private set; } = Array.Empty<Architecture?>();
7678

7779
public InstructionInfo()
7880
{
@@ -83,7 +85,7 @@ public InstructionInfo(BNInstructionInfo native)
8385
{
8486
this.Length = native.length;
8587

86-
this.BranchCount = native.branchCount;
88+
this.BranchCount = Math.Min(native.branchCount, (ulong)MaximumBranchCount);
8789

8890
this.ArchTransitionByTargetAddr = native.archTransitionByTargetAddr;
8991

@@ -116,38 +118,89 @@ public InstructionInfo(BNInstructionInfo native)
116118
this.BranchTarget = branchTargets.ToArray();
117119

118120
// BranchArch
119-
List<Architecture> branchArches = new List<Architecture>();
121+
List<Architecture?> branchArches = new List<Architecture?>();
120122

121-
if (this.BranchCount >= 1)
123+
if (1 <= this.BranchCount)
122124
{
123-
if (IntPtr.Zero != native.branchArch_0)
124-
{
125-
branchArches.Add( new Architecture( native.branchArch_0 ) );
126-
}
125+
branchArches.Add(Architecture.FromHandle(native.branchArch_0));
127126
}
128127

129-
if (this.BranchCount >= 2)
128+
if (2 <= this.BranchCount)
130129
{
131-
if (IntPtr.Zero != native.branchArch_1)
132-
{
133-
branchArches.Add( new Architecture( native.branchArch_1 ) );
134-
}
130+
branchArches.Add(Architecture.FromHandle(native.branchArch_1));
135131
}
136132

137-
if (this.BranchCount >= 3)
133+
if (3 <= this.BranchCount)
138134
{
139-
if (IntPtr.Zero != native.branchArch_2)
140-
{
141-
branchArches.Add( new Architecture( native.branchArch_2 ) );
142-
}
135+
branchArches.Add(Architecture.FromHandle(native.branchArch_2));
143136
}
144137

145138
this.BranchArch = branchArches.ToArray();
146139
}
147140

141+
public void AddBranch(
142+
BranchType type,
143+
ulong target = 0,
144+
Architecture? architecture = null,
145+
byte delaySlots = 0)
146+
{
147+
if (MaximumBranchCount <= this.BranchCount)
148+
{
149+
return;
150+
}
151+
152+
List<BranchType> branchTypes = new List<BranchType>(this.BranchType);
153+
List<ulong> branchTargets = new List<ulong>(this.BranchTarget);
154+
List<Architecture?> branchArchitectures =
155+
new List<Architecture?>(this.BranchArch);
156+
157+
branchTypes.Add(type);
158+
branchTargets.Add(target);
159+
branchArchitectures.Add(architecture);
160+
161+
this.BranchType = branchTypes.ToArray();
162+
this.BranchTarget = branchTargets.ToArray();
163+
this.BranchArch = branchArchitectures.ToArray();
164+
this.BranchCount = (ulong)this.BranchType.Length;
165+
this.DelaySlots = delaySlots;
166+
}
167+
168+
internal unsafe BNInstructionInfo ToNative()
169+
{
170+
BNInstructionInfo native = new BNInstructionInfo
171+
{
172+
length = this.Length,
173+
branchCount = this.BranchCount,
174+
archTransitionByTargetAddr = this.ArchTransitionByTargetAddr,
175+
delaySlots = this.DelaySlots
176+
};
177+
178+
for (int index = 0; index < this.BranchType.Length; index++)
179+
{
180+
native.branchType[index] = (byte)this.BranchType[index];
181+
native.branchTarget[index] = this.BranchTarget[index];
182+
}
183+
184+
native.branchArch_0 = this.GetBranchArchitectureHandle(0);
185+
native.branchArch_1 = this.GetBranchArchitectureHandle(1);
186+
native.branchArch_2 = this.GetBranchArchitectureHandle(2);
187+
188+
return native;
189+
}
190+
191+
private IntPtr GetBranchArchitectureHandle(int index)
192+
{
193+
if (this.BranchArch.Length <= index || null == this.BranchArch[index])
194+
{
195+
return IntPtr.Zero;
196+
}
197+
198+
return this.BranchArch[index]!.DangerousGetHandle();
199+
}
200+
148201
internal static InstructionInfo FromNative(BNInstructionInfo native)
149202
{
150203
return new InstructionInfo(native);
151204
}
152205
}
153-
}
206+
}

0 commit comments

Comments
 (0)