From 146456902a6893d67848c331e0e2797f7154667b Mon Sep 17 00:00:00 2001 From: rushiiMachine <33725716+rushiiMachine@users.noreply.github.com> Date: Sat, 23 Mar 2024 23:35:54 -0700 Subject: [PATCH] feat: add `entireMethod` option to signature matching --- Osu.Stubs/Color.cs | 3 +-- Osu.Stubs/Opcode/LazyMethod.cs | 5 +++-- Osu.Stubs/Opcode/OpCodeMatcher.cs | 14 +++++++++----- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/Osu.Stubs/Color.cs b/Osu.Stubs/Color.cs index 1116abf..c3cc923 100644 --- a/Osu.Stubs/Color.cs +++ b/Osu.Stubs/Color.cs @@ -1,9 +1,8 @@ -using System; using Osu.Stubs.Opcode; namespace Osu.Stubs; -using XnaColor = Object; +using XnaColor = object; /// /// Original: Microsoft.Xna.Framework.Graphics.Color diff --git a/Osu.Stubs/Opcode/LazyMethod.cs b/Osu.Stubs/Opcode/LazyMethod.cs index 96cd5ff..9625a48 100644 --- a/Osu.Stubs/Opcode/LazyMethod.cs +++ b/Osu.Stubs/Opcode/LazyMethod.cs @@ -18,10 +18,11 @@ public class LazyMethod /// /// Class#Method name of what this signature is matching. /// Sequential opcodes to search the target method with. - internal LazyMethod(string name, IReadOnlyList signature) + /// Whether the signature is the entire method. + internal LazyMethod(string name, IReadOnlyList signature, bool entireMethod = false) { _name = name; - _lazy = new Lazy(() => OpCodeMatcher.FindMethodBySignature(signature)); + _lazy = new Lazy(() => OpCodeMatcher.FindMethodBySignature(signature, entireMethod)); } /// diff --git a/Osu.Stubs/Opcode/OpCodeMatcher.cs b/Osu.Stubs/Opcode/OpCodeMatcher.cs index 40620ca..67f1a4b 100644 --- a/Osu.Stubs/Opcode/OpCodeMatcher.cs +++ b/Osu.Stubs/Opcode/OpCodeMatcher.cs @@ -10,8 +10,9 @@ public static class OpCodeMatcher /// Search for a method inside the osu! assembly by an IL OpCode signature. /// /// A set of sequential OpCodes to match. + /// Whether the signature is the entire method to search for. /// The found method or null if none found. - public static MethodInfo? FindMethodBySignature(IReadOnlyList signature) + public static MethodInfo? FindMethodBySignature(IReadOnlyList signature, bool entireMethod = false) { if (signature.Count <= 0) return null; @@ -24,7 +25,7 @@ public static class OpCodeMatcher var instructions = method.GetMethodBody()?.GetILAsByteArray(); if (instructions == null) continue; - if (InstructionsMatchesSignature(instructions, signature)) + if (InstructionsMatchesSignature(instructions, signature, entireMethod)) return method; } @@ -49,7 +50,7 @@ public static class OpCodeMatcher var instructions = method.GetMethodBody()?.GetILAsByteArray(); if (instructions == null) continue; - if (InstructionsMatchesSignature(instructions, signature)) + if (InstructionsMatchesSignature(instructions, signature, false)) return method; } @@ -64,18 +65,21 @@ public static class OpCodeMatcher /// for example. /// /// A set of sequential OpCodes to search for in instructions. + /// Whether the signature should be the entire method. /// private static bool InstructionsMatchesSignature( IReadOnlyList ilInstructions, - IReadOnlyList signature) + IReadOnlyList signature, + bool entireMethod) { var sequentialMatching = 0; foreach (var instruction in new OpCodeReader(ilInstructions).GetOpCodes()) { if (instruction == signature[sequentialMatching]) sequentialMatching++; - else + else if (!entireMethod) sequentialMatching = 0; + else return false; if (sequentialMatching == signature.Count) return true;