ChrisW
ChrisW

Reputation: 56083

How to parse a method invocation in IL bytes?

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

Answers (2)

ChrisW
ChrisW

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:

    Support resolving metadata tokens in MetadataLoadContext

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

thehennyy
thehennyy

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

Related Questions