Reputation: 56083
I know how to use the System.Reflection
API, but not how to parse IL (Intermediate Language), though I do know how to parse x86 opcodes for what that's worth.
Now I want to find all the methods in an assembly which invoke a given method -- e.g., given a method named Namespace.Classname.Methodname
, which methods in the assembly invoke it?
Assume I have the MethodInfo
for the method in question.
To do this I suppose I must parse the bytes returned from the MethodBody.GetILAsByteArray method (which I don't know how to do).
The Note in the API Help says,
Parsing method bodies requires a thorough understanding of metadata and MSIL instruction formats. Information can be found in the Common Language Infrastructure (CLI) documentation, especially "Partition II: Metadata Definition and Semantics".
... which is a 500-page document.
Can you give me any hint of how to do it, outline the algorithm I'll implement, suggest an easy way to do it using a tool or library like ILSpy, or reference a suitable introduction to the topic before I start the wade through the referfence manual?
If it helps, I don't want to parse everything in the IL -- only to parse it just enough to find the method calls, especially the calls to constructors.
Upvotes: 0
Views: 259
Reputation: 56083
I'm currently doing it with the ICSharpCode.Decompiler
package as shown here:
I tried disassembling the IL myself however I had a problem/exception:
I was trying to use a method named Module.ResolveMethod
The subclass of Module
which I instantiated was System.Reflection.TypeLoading.RoModule
Its ResolveMethod
throws:
Resolving tokens is not supported on assemblies loaded by a MetadataLoadContext
Apparently the problem was my using MetadataLoadContext
to load the assembly to be decompiled -- if I do that then "I can't get there from here" i.e. it's the wrong technology.
See also this topic which says the functionality is missing/unimplemented:
I don't know what technology the ICSharpCode.Decompiler
uses instead to load assemblies, or why it's different, but apparently it has no such problem -- so I used it.
Its "abstract syntax tree" is optimized towards decompiling to a high-level-language (C#) syntax, so its AST output wasn't what I wanted. Instead I used it to get the IL, and I made my own subclass of "Visitor" to do what I wanted with the various types of opcode.
The classes or interfaces of the package are mostly public
so I was able to do that.
I only had to copy-and-paste a little of the code from the CSharpDecompiler
in order to instantiate another of its types I needed i.e. MetadataModule
.
Upvotes: 0
Reputation: 4218
The IL byte stream can be parsed using the System.Reflection.Emit.OpCodes
class. The opcodes OperandType
field tells you how many bytes to read, to reach the next opcode. While iterating over the stream, metadata tokens can be resolved using the Module.ResolveMember
method. Have a look here for an example on how to find property getter tokens: Find all property references using reflection. The code can easily adapted to search for any kind of tokens or instructions you are interested in.
Upvotes: 1