diff --git a/Dalamud/Game/SigScanner.cs b/Dalamud/Game/SigScanner.cs
index b19024098..b5fe0b5b3 100644
--- a/Dalamud/Game/SigScanner.cs
+++ b/Dalamud/Game/SigScanner.cs
@@ -15,12 +15,17 @@ using Serilog;
namespace Dalamud.Game;
+// TODO(v9): There are static functions here that we can't keep due to interfaces
+
///
/// A SigScanner facilitates searching for memory signatures in a given ProcessModule.
///
[PluginInterface]
[InterfaceVersion("1.0")]
-public class SigScanner : IDisposable, IServiceType
+#pragma warning disable SA1015
+[ResolveVia]
+#pragma warning restore SA1015
+public class SigScanner : IDisposable, IServiceType, ISigScanner
{
private readonly FileInfo? cacheFile;
@@ -65,69 +70,43 @@ public class SigScanner : IDisposable, IServiceType
this.Load();
}
- ///
- /// Gets a value indicating whether or not the search on this module is performed on a copy.
- ///
+ ///
public bool IsCopy { get; }
- ///
- /// Gets a value indicating whether or not the ProcessModule is 32-bit.
- ///
+ ///
public bool Is32BitProcess { get; }
- ///
- /// Gets the base address of the search area. When copied, this will be the address of the copy.
- ///
+ ///
public IntPtr SearchBase => this.IsCopy ? this.moduleCopyPtr : this.Module.BaseAddress;
- ///
- /// Gets the base address of the .text section search area.
- ///
+ ///
public IntPtr TextSectionBase => new(this.SearchBase.ToInt64() + this.TextSectionOffset);
- ///
- /// Gets the offset of the .text section from the base of the module.
- ///
+ ///
public long TextSectionOffset { get; private set; }
- ///
- /// Gets the size of the text section.
- ///
+ ///
public int TextSectionSize { get; private set; }
- ///
- /// Gets the base address of the .data section search area.
- ///
+ ///
public IntPtr DataSectionBase => new(this.SearchBase.ToInt64() + this.DataSectionOffset);
- ///
- /// Gets the offset of the .data section from the base of the module.
- ///
+ ///
public long DataSectionOffset { get; private set; }
- ///
- /// Gets the size of the .data section.
- ///
+ ///
public int DataSectionSize { get; private set; }
- ///
- /// Gets the base address of the .rdata section search area.
- ///
+ ///
public IntPtr RDataSectionBase => new(this.SearchBase.ToInt64() + this.RDataSectionOffset);
- ///
- /// Gets the offset of the .rdata section from the base of the module.
- ///
+ ///
public long RDataSectionOffset { get; private set; }
- ///
- /// Gets the size of the .rdata section.
- ///
+ ///
public int RDataSectionSize { get; private set; }
- ///
- /// Gets the ProcessModule on which the search is performed.
- ///
+ ///
public ProcessModule Module { get; }
private IntPtr TextSectionTop => this.TextSectionBase + this.TextSectionSize;
@@ -229,11 +208,7 @@ public class SigScanner : IDisposable, IServiceType
}
}
- ///
- /// Scan for a byte signature in the .data section.
- ///
- /// The signature.
- /// The real offset of the found signature.
+ ///
public IntPtr ScanData(string signature)
{
var scanRet = Scan(this.DataSectionBase, this.DataSectionSize, signature);
@@ -244,12 +219,7 @@ public class SigScanner : IDisposable, IServiceType
return scanRet;
}
- ///
- /// Try scanning for a byte signature in the .data section.
- ///
- /// The signature.
- /// The real offset of the signature, if found.
- /// true if the signature was found.
+ ///
public bool TryScanData(string signature, out IntPtr result)
{
try
@@ -264,11 +234,7 @@ public class SigScanner : IDisposable, IServiceType
}
}
- ///
- /// Scan for a byte signature in the whole module search area.
- ///
- /// The signature.
- /// The real offset of the found signature.
+ ///
public IntPtr ScanModule(string signature)
{
var scanRet = Scan(this.SearchBase, this.Module.ModuleMemorySize, signature);
@@ -279,12 +245,7 @@ public class SigScanner : IDisposable, IServiceType
return scanRet;
}
- ///
- /// Try scanning for a byte signature in the whole module search area.
- ///
- /// The signature.
- /// The real offset of the signature, if found.
- /// true if the signature was found.
+ ///
public bool TryScanModule(string signature, out IntPtr result)
{
try
@@ -299,23 +260,14 @@ public class SigScanner : IDisposable, IServiceType
}
}
- ///
- /// Resolve a RVA address.
- ///
- /// The address of the next instruction.
- /// The relative offset.
- /// The calculated offset.
+ ///
public IntPtr ResolveRelativeAddress(IntPtr nextInstAddr, int relOffset)
{
if (this.Is32BitProcess) throw new NotSupportedException("32 bit is not supported.");
return nextInstAddr + relOffset;
}
- ///
- /// Scan for a byte signature in the .text section.
- ///
- /// The signature.
- /// The real offset of the found signature.
+ ///
public IntPtr ScanText(string signature)
{
if (this.textCache != null)
@@ -347,12 +299,7 @@ public class SigScanner : IDisposable, IServiceType
return scanRet;
}
- ///
- /// Try scanning for a byte signature in the .text section.
- ///
- /// The signature.
- /// The real offset of the signature, if found.
- /// true if the signature was found.
+ ///
public bool TryScanText(string signature, out IntPtr result)
{
try
diff --git a/Dalamud/Plugin/Services/ISigScanner.cs b/Dalamud/Plugin/Services/ISigScanner.cs
new file mode 100644
index 000000000..c3bb7d6c1
--- /dev/null
+++ b/Dalamud/Plugin/Services/ISigScanner.cs
@@ -0,0 +1,150 @@
+using System;
+using System.Diagnostics;
+
+namespace Dalamud.Game;
+
+///
+/// A SigScanner facilitates searching for memory signatures in a given ProcessModule.
+///
+public interface ISigScanner
+{
+ ///
+ /// Gets a value indicating whether or not the search on this module is performed on a copy.
+ ///
+ public bool IsCopy { get; }
+
+ ///
+ /// Gets a value indicating whether or not the ProcessModule is 32-bit.
+ ///
+ public bool Is32BitProcess { get; }
+
+ ///
+ /// Gets the base address of the search area. When copied, this will be the address of the copy.
+ ///
+ public IntPtr SearchBase { get; }
+
+ ///
+ /// Gets the base address of the .text section search area.
+ ///
+ public IntPtr TextSectionBase { get; }
+
+ ///
+ /// Gets the offset of the .text section from the base of the module.
+ ///
+ public long TextSectionOffset { get; }
+
+ ///
+ /// Gets the size of the text section.
+ ///
+ public int TextSectionSize { get; }
+
+ ///
+ /// Gets the base address of the .data section search area.
+ ///
+ public IntPtr DataSectionBase { get; }
+
+ ///
+ /// Gets the offset of the .data section from the base of the module.
+ ///
+ public long DataSectionOffset { get; }
+
+ ///
+ /// Gets the size of the .data section.
+ ///
+ public int DataSectionSize { get; }
+
+ ///
+ /// Gets the base address of the .rdata section search area.
+ ///
+ public IntPtr RDataSectionBase { get; }
+
+ ///
+ /// Gets the offset of the .rdata section from the base of the module.
+ ///
+ public long RDataSectionOffset { get; }
+
+ ///
+ /// Gets the size of the .rdata section.
+ ///
+ public int RDataSectionSize { get; }
+
+ ///
+ /// Gets the ProcessModule on which the search is performed.
+ ///
+ public ProcessModule Module { get; }
+
+ ///
+ /// Scan for a .data address using a .text function.
+ /// This is intended to be used with IDA sigs.
+ /// Place your cursor on the line calling a static address, and create and IDA sig.
+ /// The signature and offset should not break through instruction boundaries.
+ ///
+ /// The signature of the function using the data.
+ /// The offset from function start of the instruction using the data.
+ /// An IntPtr to the static memory location.
+ public nint GetStaticAddressFromSig(string signature, int offset = 0);
+
+ ///
+ /// Try scanning for a .data address using a .text function.
+ /// This is intended to be used with IDA sigs.
+ /// Place your cursor on the line calling a static address, and create and IDA sig.
+ ///
+ /// The signature of the function using the data.
+ /// An IntPtr to the static memory location, if found.
+ /// The offset from function start of the instruction using the data.
+ /// true if the signature was found.
+ public bool TryGetStaticAddressFromSig(string signature, out nint result, int offset = 0);
+
+ ///
+ /// Scan for a byte signature in the .data section.
+ ///
+ /// The signature.
+ /// The real offset of the found signature.
+ public nint ScanData(string signature);
+
+ ///
+ /// Try scanning for a byte signature in the .data section.
+ ///
+ /// The signature.
+ /// The real offset of the signature, if found.
+ /// true if the signature was found.
+ public bool TryScanData(string signature, out nint result);
+
+ ///
+ /// Scan for a byte signature in the whole module search area.
+ ///
+ /// The signature.
+ /// The real offset of the found signature.
+ public nint ScanModule(string signature);
+
+ ///
+ /// Try scanning for a byte signature in the whole module search area.
+ ///
+ /// The signature.
+ /// The real offset of the signature, if found.
+ /// true if the signature was found.
+ public bool TryScanModule(string signature, out nint result);
+
+ ///
+ /// Resolve a RVA address.
+ ///
+ /// The address of the next instruction.
+ /// The relative offset.
+ /// The calculated offset.
+ public nint ResolveRelativeAddress(nint nextInstAddr, int relOffset);
+
+ ///
+ /// Scan for a byte signature in the .text section.
+ ///
+ /// The signature.
+ /// The real offset of the found signature.
+ public nint ScanText(string signature);
+
+ ///
+ /// Try scanning for a byte signature in the .text section.
+ ///
+ /// The signature.
+ /// The real offset of the signature, if found.
+ /// true if the signature was found.
+ public bool TryScanText(string signature, out nint result);
+}