Skip to content

Instantly share code, notes, and snippets.

@pardeike
Last active April 2, 2020 09:47
Show Gist options
  • Save pardeike/a91a4db955f221730b2c07cc8f3da07f to your computer and use it in GitHub Desktop.
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
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