Last active
April 2, 2020 09:47
-
-
Save pardeike/a91a4db955f221730b2c07cc8f3da07f to your computer and use it in GitHub Desktop.
Search through all methods that exist in all assemblies and run a test on their method bodies
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using HarmonyLib; | |
using MonoMod.Utils; | |
using System; | |
using System.Linq; | |
using System.Reflection; | |
class Program | |
{ | |
static void Main() | |
{ | |
// prepare search term outside the loop for efficiency | |
var operandSearchTerm = AccessTools.Constructor(typeof(ArgumentNullException)); | |
// create a ILGenerator from scratch (required by PatchProcessor.GetOriginalInstructions) | |
var dummyMethod = new DynamicMethodDefinition("Dummy", typeof(void), Array.Empty<Type>()); | |
var generator = dummyMethod.GetILGenerator(); | |
// use current appdomain to get all types and all methods and their instructions | |
// this code excludes any generics because you cannot get a method body without | |
// specifying the concrete types and we don't know which ones we would use | |
AppDomain.CurrentDomain.GetAssemblies() | |
.SelectMany(assembly => assembly.GetTypes()) | |
.Where(type => type.IsGenericType == false) | |
.SelectMany(type => | |
{ | |
var methods = AccessTools.GetDeclaredMethods(type).Cast<MethodBase>(); | |
var constructors = AccessTools.GetDeclaredConstructors(type).Cast<MethodBase>(); | |
return methods.Union(constructors); | |
}) | |
.Where(member => member.IsGenericMethod == false && member.GetMethodBody() != null) | |
.Do(member => | |
{ | |
var instructions = PatchProcessor.GetOriginalInstructions(member, generator); | |
// here, we can apply any logic necessary - replace with your own logic | |
if (instructions.Any(instructions => instructions.OperandIs(operandSearchTerm))) | |
Console.WriteLine($"=> {member.DeclaringType.Name}::{member.Name}"); | |
}); | |
} | |
// for .NET Core 3.1 it should output something like: | |
// => ArgIterator::GetNextArg | |
// => RuntimeType::SanityCheckGenericArguments | |
// => RuntimeType::GetPropertyImpl | |
// => RuntimeType::GetEvent | |
// => RuntimeType::GetField | |
// => RuntimeType::GetInterface | |
// => RuntimeType::GetNestedType | |
// => RuntimeType::GetMember | |
// => RuntimeType::MakeGenericType | |
// => Type::GetTypeArray | |
// => TaskToApm::End | |
// => HStringMarshaler::ConvertToNative | |
// => HStringMarshaler::ConvertToNativeReference | |
// => RuntimeMethodInfo::MakeGenericMethod | |
// => TaskToApm::End | |
// => MetadataBuilder::LookupToken | |
// => SignatureWriter::WriteTypeSignature | |
// => SignatureWriter::WritePrimitiveValue | |
// => GenericParameter::.ctor | |
// => EmbeddedPortablePdbReader::.ctor | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment