Il code in the parsing method body

Source: Internet
Author: User
Tags reflector
Document directory
  • Il code structure
  • Ilinstruction
  • Methodbodyreader
Il code in the parsing method body

This article is translated by loyee. e is poor, and some words are incorrectly translated. please correct me more. The translation is hard. Please indicate the source for reprinting.

  • Click here to view the original article
  • Click to download Demo project-8.52 KB
  • Click to download source code-21.9 KB

    Introduction

    . NetSystem.ReflectionThe namespace provides a complete reflection mechanism for viewing the structure of an assembly. You can use it to obtain all types of definitions, fields, and attributes in the Assembly, which can basically meet all your requirements [including method definition, Translator's note]. Despite this, some content is still invisible, and the code in the method body is like this.

    When you carefully check the code, you may want to know the variables used in the method body, their lifecycles, and what results are generated. Microsoft ignored this requirement, but provided some things: il code. But this is not enough. It is actually a byte array, which makes no sense for ordinary programmers without professional training.

    What we need is a series of actual operation commands in the form of IL encoding. This is what I will talk about below.

    Background

    Any programmer who has used reflection must have heard of the daunting reflector written by Lutz roeder. Reflector can decompile any. Net assembly into code that is almost the same as the source code.

    You must have doubts about the "almost consistent" I said, because the reflection mechanism cannot provide you with the initial source code. The compiler first removes all code comments, even including unused variables, and only valid and necessary code is compiled into the program. Therefore, we cannot obtain the most accurate source code.

    Okay, reflector is very good. But how can we achieve this in our own code?

    First, we use a typical example "Hello World" to see the expected results and the actual results obtained by using the. NET Framework:

    C # code:

    public void SayHello()
    {
        Console.Out.WriteLine("Hello world");
    }

    When we use the reflection method to obtain the Il code in the sayhello method body, we get a byte array, as shown below:

    0,40,52,0,0,10,114,85,1,0,112,111,53,0,0,10,0,42

    OK. This is hard to understand. All we know is to convert these il codes so that we can handle [read or understand, Translator's note] it. The easiest way is to convert it to the msil (Microsoft intermediate language) language. The following is the msil code converted from the sayhello method body (the result of my assembly should be returned ):

    0000 : nop0001 : call System.IO.TextWriter System.Console::get_Out()0006 : ldstr "Hello world"0011 : callvirt instance System.Void System.IO.TextWriter::WriteLine()0016 : nop0017 : ret
    Use Code

    Sdilreader is a dynamic library file that only contains three classes. To obtain the msil code of the method body, you need to createAn instance of the methodbodyreader object that constructsMethodInfoInstance.

    Methodinfo MI = NULL;
    // Obtain somehow the method info of the method we want to dissasemble
    // Ussually you open the Assembly, get the module, get the type and then
    // Method from that type
    //

    // Instancate a method body Reader
    Sdilreader. methodbodyreader mr = new methodbodyreader (MI );
    // Get the text representation of the msil
    String msil = mr. getbodycode ();
    // Or parse the list of instructions of the msil
    For (INT I = 0; I <mr. Instructions. Count; I ++)
    {
    // Do something with mr. Instructions [I]
    }

     

    How to work?

    Good. This is a good question. To get started [do not know how to translate get started], we first need to know the Il code structure obtained by the. NET reflection mechanism.

    Il code structure

    Il is actually an enumeration of commands that execute operations. A command contains two parts:<Command code[The following operators also represent the instruction code. Note:], Operand>. Command code isThe binary value of system. reflection. emit. opcode, And the operand is the metadata address (method, type, value, and so on) of the entity to which it acts). This address is called a metadata flag in. NET Framework.

    Therefore, to interpret this string of IL bytes, we must do the following:

    • Get the next byte and view its operator;
    • Obtain the metadata address defined in 1 to 4 bytes based on the operator;
    • UseMethodInfo.ModuleGet the object defined in the metadata address;
    • Save the <operator, operand>.
    • Repeat the above work until the string of IL Code is fully explained.
    Ilinstruction

      ILInstructionClass is used to store the <operator, operand> of an instruction pair. Similarly, we provide a simple method in the class to convert internal information into a readable string.

    Methodbodyreader

      MethodBodyReaderClass to do all the actual work. The private method is called in the constructor.ConstructInstructionsThis method parses the Il code:

    int position = 0;
    instructions = new List<ILInstruction>();
    while (position < il.Length)
    {
      ILInstruction instruction = new ILInstruction();
      // get the operation code of the current instruction
      OpCode code = OpCodes.Nop;
      ushort value = il[position++];
      if (value != 0xfe)
      {
        code = Globals.singleByteOpCodes[(int)value];
      }
      else
      {
        value = il[position++];
        code = Globals.multiByteOpCodes[(int)value];
        value = (ushort)(value | 0xfe00);
      }
      instruction.Code = code;
      instruction.Offset = position - 1;
      int metadataToken = 0;
      // get the operand of the current operation
      switch (code.OperandType)
      {
        case OperandType.InlineBrTarget:
          metadataToken = ReadInt32(il, ref position);
          metadataToken += position;
          instruction.Operand = metadataToken;
          break;
        case OperandType.InlineField:
          metadataToken = ReadInt32(il, ref position);
          instruction.Operand = module.ResolveField(metadataToken);
          break;
        .
      }
      instructions.Add(instruction);
    }

    Here we can see a simple loop for parsing Il. In fact, it is not simple, including 18 case statements. I did not consider all operators, but included only the most common part (actually there are more than 240 operators ). The operator is loaded into two static lists when an application is started:

    Public static opcode [] multibyteopcodes;

    Public static opcode [] singlebyteopcodes; public static void loadopcodes ()
    {
    Singlebyteopcodes = new opcode [0x100];
    Multibyteopcodes = new opcode [0x100];
    Fieldinfo [] infoarray1 = typeof (Opcodes). getfields ();
    For (INT num1 = 0; num1 <infoarray1.length; num1 ++)
    {
    Fieldinfo info1 = infoarray1 [num1];
    If (info1.fieldtype = typeof (opcode ))
    {
    Opcode code1 = (opcode) info1.getvalue (null );
    Ushort num2 = (ushort) code1.value;
    If (num2 <0x100)
    {
    Singlebyteopcodes [(INT) num2] = code1;
    }
    Else
    {
    If (num2 & 0xff00 )! = 0xfe00)
    {
    Throw new exception ("invalid opcode .");
    }
    Multibyteopcodes [num2 & 0xff] = code1;
    }
    }
    }
    }

    After constructing a methodbodyreader instance, we can use it to parse the command list to obtain its string representation. It is an interesting decompilation.

  • Netken

    Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.