Пример #1
0
        void WriteVTableFixups(LineWriter lw)
        {
            int ptrsize = GetPointerSize();

            VTableFixups[] fixups = GetVTableFixups();
            if (fixups.Length != 0)
            {
                for (int i = 0; i < fixups.Length; i++)
                {
                    lw.Write(".vtfixup [{0}] {1}{2} at D_{3:X8} //",
                             fixups[i].Count,
                             (fixups[i].Type & COR_VTABLE_32BIT) != 0 ? "int32" : "int64",
                             (fixups[i].Type & COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN) != 0
                            ? " retainappdomain"
                            : (fixups[i].Type & COR_VTABLE_FROM_UNMANAGED) != 0
                                ? " fromunmanaged"
                                : "",
                             fixups[i].RVA);
                    foreach (var method in GetVTableMethods(fixups[i]))
                    {
                        if (ptrsize == 4)
                        {
                            lw.Write(" {0:X8}", method.MetadataToken);
                        }
                        else
                        {
                            lw.Write(" {0:X16}", method.MetadataToken);
                        }
                    }
                    lw.WriteLine();
                }
            }
        }
Пример #2
0
        void WriteVTableFixupComment(LineWriter lw)
        {
            int ptrsize = GetPointerSize();

            VTableFixups[] fixups = GetVTableFixups();
            if (fixups.Length != 0)
            {
                lw.WriteLine("// VTableFixup Directory:");
                for (int i = 0; i < fixups.Length; i++)
                {
                    lw.WriteLine("//   IMAGE_COR_VTABLEFIXUP[{0}]:", i);
                    lw.WriteLine("//       RVA:               0x{0:x8}", fixups[i].RVA);
                    lw.WriteLine("//       Count:             0x{0:x4}", fixups[i].Count);
                    lw.WriteLine("//       Type:              0x{0:x4}", fixups[i].Type);
                    var methods = GetVTableMethods(fixups[i]);
                    for (int j = 0; j < methods.Length; j++)
                    {
                        var method = methods[j];
                        List <KeyValuePair <int, int> > list;
                        if (!vtentryMap.TryGetValue(method, out list))
                        {
                            list = new List <KeyValuePair <int, int> >();
                            vtentryMap.Add(method, list);
                        }
                        list.Add(new KeyValuePair <int, int>(i + 1, j + 1));
                        if (ptrsize == 4)
                        {
                            lw.WriteLine("//         [0x{0:x4}]            (0x{1:x8})", j, method.MetadataToken);
                        }
                        else
                        {
                            lw.WriteLine("//         [0x{0:x4}]            (0x         {1:x})", j, method.MetadataToken);
                        }
                    }
                }
                lw.WriteLine();
            }
            lw.WriteLine();
        }
 void WriteVTableFixupComment(LineWriter lw)
 {
     int ptrsize = GetPointerSize();
     VTableFixups[] fixups = GetVTableFixups();
     if (fixups.Length != 0)
     {
         lw.WriteLine("// VTableFixup Directory:");
         for (int i = 0; i < fixups.Length; i++)
         {
             lw.WriteLine("//   IMAGE_COR_VTABLEFIXUP[{0}]:", i);
             lw.WriteLine("//       RVA:               0x{0:x8}", fixups[i].RVA);
             lw.WriteLine("//       Count:             0x{0:x4}", fixups[i].Count);
             lw.WriteLine("//       Type:              0x{0:x4}", fixups[i].Type);
             var methods = GetVTableMethods(fixups[i]);
             for (int j = 0; j < methods.Length; j++)
             {
                 var method = methods[j];
                 List<KeyValuePair<int,int>> list;
                 if (!vtentryMap.TryGetValue(method, out list))
                 {
                     list = new List<KeyValuePair<int, int>>();
                     vtentryMap.Add(method, list);
                 }
                 list.Add(new KeyValuePair<int,int>(i + 1, j + 1));
                 if (ptrsize == 4)
                 {
                     lw.WriteLine("//         [0x{0:x4}]            (0x{1:x8})", j, method.MetadataToken);
                 }
                 else
                 {
                     lw.WriteLine("//         [0x{0:x4}]            (0x         {1:x})", j, method.MetadataToken);
                 }
             }
         }
         lw.WriteLine();
     }
     lw.WriteLine();
 }
Пример #4
0
 void WriteVTableFixups(LineWriter lw)
 {
     int ptrsize = GetPointerSize();
     VTableFixups[] fixups = GetVTableFixups();
     if (fixups.Length != 0)
     {
         for (int i = 0; i < fixups.Length; i++)
         {
             lw.Write(".vtfixup [{0}] {1}{2} at D_{3:X8} //",
                 fixups[i].Count,
                 (fixups[i].Type & COR_VTABLE_32BIT) != 0 ? "int32" : "int64",
                 (fixups[i].Type & COR_VTABLE_FROM_UNMANAGED_RETAIN_APPDOMAIN) != 0
                     ? " retainappdomain"
                     : (fixups[i].Type & COR_VTABLE_FROM_UNMANAGED) != 0
                         ? " fromunmanaged"
                         : "",
                 fixups[i].RVA);
             foreach (var method in GetVTableMethods(fixups[i]))
             {
                 if (ptrsize == 4)
                 {
                     lw.Write(" {0:X8}", method.MetadataToken);
                 }
                 else
                 {
                     lw.Write(" {0:X16}", method.MetadataToken);
                 }
             }
             lw.WriteLine();
         }
     }
 }
Пример #5
0
        void WriteInlineMethod(LineWriter lw, MethodBase mb, Type[] optionalParameterTypes, CustomModifiers[] customModifiers, MethodInfo methodimpl = null)
        {
            WriteCallingConvention(lw, mb.CallingConvention);
            if (mb is ConstructorInfo)
            {
                WriteSignatureType(lw, ((ConstructorInfo)mb).__ReturnParameter.ParameterType);
                WriteCustomModifiers(lw, ((ConstructorInfo)mb).__ReturnParameter.__GetCustomModifiers());
                lw.Write(" ");
            }
            else
            {
                WriteSignatureType(lw, ((MethodInfo)mb.__GetMethodOnTypeDefinition()).ReturnType, IsArrayOfGenericParameter(mb.DeclaringType) ? TypeLocation.General : TypeLocation.MemberRefNoWrap);
                WriteCustomModifiers(lw, ((MethodInfo)mb).ReturnParameter.__GetCustomModifiers());
                lw.Write(" ");
            }
            bool generic;

            if (mb.DeclaringType == null)
            {
                generic = false;
                lw.Write("{0}", QuoteIdentifier(GetMethodName(mb)));
            }
            else
            {
                if (mb.DeclaringType.__IsMissing || !mb.DeclaringType.IsGenericType)
                {
                    generic = false;
                    WriteTypeDefOrRef(lw, mb.DeclaringType);
                }
                else
                {
                    generic = true;
                    WriteSignatureType(lw, mb.DeclaringType, mb.IsGenericMethod ? TypeLocation.DeclaringType : TypeLocation.General);
                }
                lw.Write("::{0}", QuoteIdentifier(GetMethodName(mb)));
            }
            if (mb.IsGenericMethod)
            {
                if (methodimpl != null)
                {
                    lw.Write("<[{0}]>", mb.GetGenericArguments().Length);
                }
                else
                {
                    lw.Write("<");
                    string sep = "";
                    foreach (var par in mb.GetGenericArguments())
                    {
                        lw.Write(sep);
                        sep = ",";
                        WriteSignatureType(lw, par, generic ? TypeLocation.MemberRefNoWrap : TypeLocation.MethodGenericParameter);
                    }
                    lw.Write(">");
                }
            }
            if (mb.IsGenericMethodDefinition && methodimpl != null)
            {
                mb = ((MethodInfo)mb).MakeGenericMethod(methodimpl.GetGenericArguments());
            }
            else
            {
                mb = mb.__GetMethodOnTypeDefinition();
            }
            lw.Write("(");
            TypeLocation loc = (methodimpl != null && mb.IsGenericMethod)
                ? TypeLocation.GenericMethodImpl
                : IsArrayOfGenericParameter(mb.DeclaringType) ? TypeLocation.General : TypeLocation.MemberRefNoWrap;
            int level = lw.Column;

            if (compat != CompatLevel.None && loc == TypeLocation.GenericMethodImpl)
            {
                // ildasm doesn't take the length of the arity ("<[1]>") into account
                level -= 5 + (int)Math.Log10(mb.GetGenericArguments().Length);
            }
            bool first            = true;
            bool noLineWrapCompat = false;

            foreach (var parameter in mb.GetParameters())
            {
                if (!first)
                {
                    if (noLineWrapCompat)
                    {
                        lw.Write(",");
                    }
                    else
                    {
                        if (loc == TypeLocation.MemberRefNoWrap)
                        {
                            loc = TypeLocation.MemberRef;
                        }
                        lw.WriteLine(",");
                        lw.GoToColumn(level);
                    }
                }
                first = false;
                lw.ClearWrappedFlag();
                WriteSignatureType(lw, parameter.ParameterType, loc);
                noLineWrapCompat |= lw.Wrapped;
                WriteCustomModifiers(lw, parameter.__GetCustomModifiers());
            }
            if (optionalParameterTypes.Length != 0)
            {
                if (!first)
                {
                    lw.WriteLine(",");
                    lw.GoToColumn(level);
                }
                first = false;
                lw.Write("...");
                for (int i = 0; i < optionalParameterTypes.Length; i++)
                {
                    if (!first)
                    {
                        lw.WriteLine(",");
                        lw.GoToColumn(level);
                    }
                    first = false;
                    WriteSignatureType(lw, optionalParameterTypes[i], TypeLocation.MemberRef);
                    WriteCustomModifiers(lw, customModifiers[i]);
                }
            }
            lw.Write(")");
        }
Пример #6
0
        void WriteIL(LineWriter lw, MethodBase mb, MethodBody body, Type[] genericTypeArguments, Type[] genericMethodArguments)
        {
            ParameterInfo[] parameters = mb.GetParameters();
            int             level      = lw.Column;

            byte[] code = body.GetILAsByteArray();
            lw.GoToColumn(level);
            lw.WriteLine("// Code size       {0} (0x{0:x})", code.Length);
            lw.GoToColumn(level);
            lw.WriteLine(".maxstack  {0}", body.MaxStackSize);

            IList <LocalVariableInfo> locals = body.LocalVariables;

            if (locals.Count != 0)
            {
                lw.GoToColumn(level);
                lw.Write(".locals ");
                if (body.InitLocals)
                {
                    lw.Write("init ");
                }
                lw.Write("(");
                bool first = true;
                foreach (var local in locals)
                {
                    if (!first)
                    {
                        lw.WriteLine(",");
                        lw.GoToColumn(level + 9);
                    }
                    first = false;
                    WriteSignatureType(lw, local.LocalType, TypeLocation.Local);
                    if (local.IsPinned)
                    {
                        lw.Write(" pinned");
                    }
                    WriteCustomModifiers(lw, local.__GetCustomModifiers());
                    lw.Write(" V_{0}", local.LocalIndex);
                }
                lw.WriteLine(")");
            }

            var exceptions  = new List <ExceptionHandlingClause>();
            var exceptions2 = new List <ExceptionHandlingClause>();

            SortExceptions(body.ExceptionHandlingClauses, exceptions, exceptions2);

            Stack <ExceptionHandlingClause> activeExceptions = new Stack <ExceptionHandlingClause>();
            ExceptionHandlingClause         currentException = null;
            bool extraNewLine      = false;
            int  nextFlatException = 0;
            int  nextException     = 0;
            bool handler           = false;
            int  pos = 0;

            while (pos < code.Length)
            {
                if (extraNewLine)
                {
                    lw.WriteLine();
                    extraNewLine = false;
                }
                if (currentException != null)
                {
                    if (currentException.HandlerOffset == pos)
                    {
                        switch (currentException.Flags)
                        {
                        case ExceptionHandlingClauseOptions.Clause:
                            lw.GoToColumn(level - 2);
                            if (currentException.TryOffset + currentException.TryLength == pos)
                            {
                                lw.WriteLine("}  // end .try");
                            }
                            else
                            {
                                lw.WriteLine("}  // end handler");
                            }
                            lw.GoToColumn(level - 2);
                            lw.Write("catch ");
                            if (currentException.CatchType.__IsMissing || !currentException.CatchType.IsGenericType)
                            {
                                WriteTypeDefOrRef(lw, currentException.CatchType);
                            }
                            else
                            {
                                WriteSignatureType(lw, currentException.CatchType);
                            }
                            lw.WriteLine(" ");
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("{");
                            handler = true;
                            break;

                        case ExceptionHandlingClauseOptions.Finally:
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("}  // end .try");
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("finally");
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("{");
                            break;

                        case ExceptionHandlingClauseOptions.Fault:
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("}  // end .try");
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("fault");
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("{");
                            break;

                        case ExceptionHandlingClauseOptions.Filter:
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("}  // end filter");
                            lw.GoToColumn(level - 2);
                            lw.WriteLine("{  // handler");
                            handler = true;
                            break;

                        default:
                            throw new IKVM.Reflection.BadImageFormatException();
                        }
                    }
                    else if (currentException.FilterOffset == pos && pos != 0)
                    {
                        lw.GoToColumn(level - 2);
                        if (handler)
                        {
                            lw.WriteLine("}  // end handler");
                        }
                        else
                        {
                            lw.WriteLine("}  // end .try");
                        }
                        lw.GoToColumn(level - 2);
                        lw.WriteLine("filter");
                        lw.GoToColumn(level - 2);
                        lw.WriteLine("{");
                    }
                }
                while (nextException < exceptions.Count &&
                       exceptions[nextException].TryOffset == pos)
                {
                    activeExceptions.Push(currentException);
                    ExceptionHandlingClause prevException = currentException;
                    currentException = exceptions[nextException++];
                    if (prevException != null && currentException.TryOffset == prevException.TryOffset && currentException.TryLength == prevException.TryLength)
                    {
                        // another handler for the same block
                        continue;
                    }
                    handler = false;
                    lw.GoToColumn(level);
                    lw.WriteLine(".try");
                    lw.GoToColumn(level);
                    lw.WriteLine("{");
                    level += 2;
                }
                lw.GoToColumn(level);
                int currPos = pos;
                lw.Write("IL_{0:x4}:  ", pos);
                int   level1      = lw.Column;
                short opcodeValue = code[pos++];
                if (opcodeValue == 0xFE)
                {
                    opcodeValue = (short)(0xFE00 + code[pos++]);
                }
                OpCode opcode = opcodes[opcodeValue + 512];
                lw.Write("{0}", opcode.Name);
                switch (opcode.OperandType)
                {
                case OperandType.InlineNone:
                    break;

                case OperandType.InlineBrTarget:
                    lw.GoToColumn(level1 + 11);
                    lw.Write("IL_{0:x4}", ReadInt32(code, ref pos) + pos);
                    break;

                case OperandType.ShortInlineBrTarget:
                    lw.GoToColumn(level1 + 11);
                    lw.Write("IL_{0:x4}", (sbyte)code[pos++] + pos);
                    break;

                case OperandType.InlineMethod:
                {
                    lw.GoToColumn(level1 + 11);
                    int        token = ReadInt32(code, ref pos);
                    MethodBase methodOrConstructor = ResolveMethod(token, genericTypeArguments, genericMethodArguments);
                    if ((methodOrConstructor.CallingConvention & CallingConventions.Any) == CallingConventions.VarArgs)
                    {
                        CustomModifiers[] customModifiers;
                        Type[]            optionalParameterTypes = ResolveOptionalParameterTypes(token, genericTypeArguments, genericMethodArguments, out customModifiers);
                        WriteInlineMethod(lw, methodOrConstructor, optionalParameterTypes, customModifiers);
                    }
                    else
                    {
                        WriteInlineMethod(lw, methodOrConstructor, Type.EmptyTypes, null);
                    }
                }
                break;

                case OperandType.InlineField:
                    lw.GoToColumn(level1 + 11);
                    WriteInlineField(lw, ResolveField(ReadInt32(code, ref pos), genericTypeArguments, genericMethodArguments));
                    break;

                case OperandType.InlineI:
                    lw.GoToColumn(level1 + 11);
                    WriteInlineI(lw, ReadInt32(code, ref pos));
                    break;

                case OperandType.InlineI8:
                    lw.GoToColumn(level1 + 11);
                    WriteInlineI8(lw, ReadInt64(code, ref pos));
                    break;

                case OperandType.ShortInlineI:
                    lw.GoToColumn(level1 + 11);
                    lw.Write("{0}", (sbyte)code[pos++]);
                    break;

                case OperandType.InlineR:
                    lw.GoToColumn(level1 + 11);
                    WriteInlineR(lw, ReadDouble(code, ref pos), false);
                    break;

                case OperandType.ShortInlineR:
                    lw.GoToColumn(level1 + 11);
                    WriteShortInlineR(lw, ReadSingle(code, ref pos), false);
                    break;

                case OperandType.InlineType:
                    if (opcode == OpCodes.Constrained)
                    {
                        // "constrained." is too long to fit in the opcode column
                        lw.Write(" ");
                    }
                    else
                    {
                        lw.GoToColumn(level1 + 11);
                    }
                    WriteInlineType(lw, ReadInt32(code, ref pos), genericTypeArguments, genericMethodArguments);
                    break;

                case OperandType.InlineTok:
                {
                    int token = ReadInt32(code, ref pos);
                    switch (token >> 24)
                    {
                    case 0x01:
                    case 0x02:
                        lw.GoToColumn(level1 + 11);
                        WriteTypeDefOrRef(lw, ResolveType(token, genericTypeArguments, genericMethodArguments));
                        break;

                    case 0x1B:
                    {
                        Type type = ResolveType(token, genericTypeArguments, genericMethodArguments);
                        if (type.IsGenericTypeDefinition)
                        {
                            // HACK because typeof(Foo<>).MakeGenericType(typeof(Foo<>).GetGenericArguments()) == typeof(Foo<>)
                            // we need to inflate the builder here
                            type = type.MakeGenericType(type.GetGenericArguments());
                        }
                        lw.GoToColumn(level1 + 11);
                        WriteSignatureType(lw, type);
                        break;
                    }

                    case 0x04:
                    case 0x06:
                    case 0x0A:
                    case 0x2B:
                    {
                        MemberInfo member = ResolveMember(token, genericTypeArguments, genericMethodArguments);
                        if (member is FieldInfo)
                        {
                            lw.GoToColumn(level1 + 11);
                            lw.Write("field ");
                            WriteInlineField(lw, (FieldInfo)member);
                        }
                        else
                        {
                            var mb1 = (MethodBase)member;
                            lw.GoToColumn(level1 + 11);
                            if (mb1.__IsMissing || !mb1.IsGenericMethod || compat != CompatLevel.V20)
                            {
                                lw.Write("method ");
                            }
                            WriteInlineMethod(lw, mb1, Type.EmptyTypes, null);
                        }
                        break;
                    }

                    default:
                        throw new NotImplementedException("token type = " + (token >> 24));
                    }
                }
                break;

                case OperandType.InlineVar:
                    lw.GoToColumn(level1 + 11);
                    WriteInlineVar(lw, mb, opcode, parameters, ReadInt16(code, ref pos));
                    break;

                case OperandType.ShortInlineVar:
                    lw.GoToColumn(level1 + 11);
                    WriteInlineVar(lw, mb, opcode, parameters, code[pos++]);
                    break;

                case OperandType.InlineString:
                    lw.GoToColumn(level1 + 11);
                    WriteInlineString(lw, module.ResolveString(ReadInt32(code, ref pos)), level);
                    break;

                case OperandType.InlineSwitch:
                {
                    lw.GoToColumn(level1 + 11);
                    lw.WriteLine("( ");
                    int count  = ReadInt32(code, ref pos);
                    int offset = pos + 4 * count;
                    for (int i = 0; i < count - 1; i++)
                    {
                        lw.GoToColumn(level + 22);
                        lw.WriteLine("IL_{0:x4},", offset + ReadInt32(code, ref pos));
                    }
                    lw.GoToColumn(level + 22);
                    lw.Write("IL_{0:x4})", offset + ReadInt32(code, ref pos));
                }
                break;

                case OperandType.InlineSig:
                    lw.GoToColumn(level1 + 11);
                    WriteStandAloneMethodSig(lw, module.__ResolveStandAloneMethodSig(ReadInt32(code, ref pos), genericTypeArguments, genericMethodArguments), false, false);
                    break;

                default:
                    throw new InvalidOperationException();
                }
                lw.WriteLine();

                if (opcode == OpCodes.Leave || opcode == OpCodes.Leave_S)
                {
                    if (pos < code.Length)
                    {
                        lw.WriteLine();
                    }
                }
                else if (opcode != OpCodes.Switch && opcode != OpCodes.Rethrow && opcode != OpCodes.Endfilter && opcode != OpCodes.Endfinally)
                {
                    switch (opcode.FlowControl)
                    {
                    case FlowControl.Branch:
                    case FlowControl.Cond_Branch:
                    case FlowControl.Throw:
                    case FlowControl.Return:
                        extraNewLine = true;
                        break;
                    }
                }
                if (nextFlatException < exceptions2.Count && exceptions2[nextFlatException].HandlerOffset + exceptions2[nextFlatException].HandlerLength == currPos)
                {
                    if (extraNewLine && pos < code.Length)
                    {
                        extraNewLine = false;
                        lw.WriteLine();
                    }
                    lw.GoToColumn(level);
                    if (exceptions2[nextFlatException].FilterOffset == 0)
                    {
                        lw.Write(".try IL_{0:x4} to IL_{1:x4} catch ", exceptions2[nextFlatException].TryOffset, exceptions2[nextFlatException].TryOffset + exceptions2[nextFlatException].TryLength);
                        if (exceptions2[nextFlatException].CatchType.__IsMissing || !exceptions2[nextFlatException].CatchType.IsGenericType)
                        {
                            WriteTypeDefOrRef(lw, exceptions2[nextFlatException].CatchType);
                        }
                        else
                        {
                            WriteSignatureType(lw, exceptions2[nextFlatException].CatchType);
                        }
                        lw.WriteLine(" handler IL_{0:x4} to IL_{1:x4}", exceptions2[nextFlatException].HandlerOffset, exceptions2[nextFlatException].HandlerOffset + exceptions2[nextFlatException].HandlerLength);
                    }
                    else
                    {
                        lw.WriteLine(".try IL_{0:x4} to IL_{1:x4} filter IL_{2:x4} handler IL_{3:x4} to IL_{4:x4}",
                                     exceptions2[nextFlatException].TryOffset, exceptions2[nextFlatException].TryOffset + exceptions2[nextFlatException].TryLength,
                                     exceptions2[nextFlatException].FilterOffset,
                                     exceptions2[nextFlatException].HandlerOffset, exceptions2[nextFlatException].HandlerOffset + exceptions2[nextFlatException].HandlerLength);
                    }
                    nextFlatException++;
                }

                while (currentException != null && currentException.HandlerOffset + currentException.HandlerLength == pos)
                {
                    ExceptionHandlingClause prevException = currentException;
                    currentException = activeExceptions.Pop();
                    if (currentException == null || currentException.TryOffset != prevException.TryOffset || currentException.TryLength != prevException.TryLength)
                    {
                        if (extraNewLine && pos < code.Length)
                        {
                            extraNewLine = false;
                            lw.WriteLine();
                        }
                        level -= 2;
                        lw.GoToColumn(level);
                        lw.WriteLine("}  // end handler");
                        handler = false;
                    }
                    else
                    {
                        handler = true;
                    }
                }
            }
        }