void ReadNamedArguments(StringBuilder sb, ByteReader br, int named, int level, bool securityCompatHack) { for (int i = 0; i < named; i++) { if (i != 0) { AppendNewLine(sb, level); } byte fieldOrProperty = br.ReadByte(); switch (fieldOrProperty) { case 0x53: sb.Append("field "); break; case 0x54: sb.Append("property "); break; default: throw new Managed.Reflection.BadImageFormatException(); } string typeName; Type fieldOrPropertyType = ReadFieldOrPropType(sb, br, out typeName); AppendCATypeName(sb, fieldOrPropertyType, typeName, securityCompatHack); sb.Append(' ').Append(QuoteIdentifier(br.ReadString(), true)).Append(" = "); ReadFixedArg(sb, br, fieldOrPropertyType); } }
void WriteInlineType(LineWriter lw, int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments) { CustomModifiers mods = new CustomModifiers(); if (metadataToken >> 24 == 0x1B) { mods = module.__ResolveTypeSpecCustomModifiers(metadataToken, genericTypeArguments, genericMethodArguments); } if (!mods.IsEmpty) { lw.Write("class "); } Type type = ResolveType(metadataToken, genericTypeArguments, genericMethodArguments); if (type.HasElementType) { WriteSignatureType(lw, type); } else if (!type.__IsMissing && type.IsGenericType) { WriteSignatureType(lw, type, TypeLocation.General); } else { WriteTypeDefOrRef(lw, type); } if (!mods.IsEmpty) { WriteCustomModifiers(lw, mods); } }
void AppendTypeNameNoOuter(StringBuilder sb, Type type) { if (type.__Namespace != null) { sb.Append(QuoteIdentifier(type.__Namespace)); sb.Append('.'); } sb.Append(QuoteIdentifier(type.__Name)); }
void AppendTypeName(StringBuilder sb, Type type) { if (type.IsNested) { AppendTypeName(sb, type.DeclaringType); sb.Append('/'); } AppendTypeNameNoOuter(sb, type); }
static bool IsNestedTypeWithNamespace(Type type) { if (!type.IsNested) { return(false); } if (type.IsConstructedGenericType) { type = type.GetGenericTypeDefinition(); } return(type.__Namespace != null); }
static bool IsArrayOfGenericParameter(Type type) { if (type != null && type.IsArray) { while (type.IsArray) { type = type.GetElementType(); } return(!type.__IsMissing && type.IsGenericParameter); } return(false); }
static bool IsNestedTypeWithNamespace(Type type) { if (!type.IsNested) { return false; } if (type.IsConstructedGenericType) { type = type.GetGenericTypeDefinition(); } return type.__Namespace != null; }
void AppendTypeName(StringBuilder sb, Type type, string typeName, bool noself = false, bool securityCompatHack = false) { if (type.Assembly == assembly && !type.__IsMissing && !noself && (!type.IsGenericType || type.IsGenericTypeDefinition) && !type.HasElementType) { AppendTypeName(sb, type); } else if (typerefs.Contains(type)) { sb.Append('[').Append(QuoteIdentifier(FindReferencedAssembly(type.Assembly))).Append(']'); AppendTypeName(sb, type); } else { if (securityCompatHack) { throw new Managed.Reflection.BadImageFormatException(); } sb.Append("class ").Append(QuoteIdentifier(typeName, true)); } }
void AppendCATypeName(StringBuilder sb, Type type, string typeName, bool securityCompatHack = false) { if (type.IsArray) { AppendCATypeName(sb, type.GetElementType(), null); sb.Append("[]"); } else if (type == typeofSystemBoolean) { sb.Append("bool"); } else if (type == typeofSystemSByte) { sb.Append("int8"); } else if (type == typeofSystemByte) { sb.Append("uint8"); } else if (type == typeofSystemChar) { sb.Append("char"); } else if (type == typeofSystemInt16) { sb.Append("int16"); } else if (type == typeofSystemUInt16) { sb.Append("uint16"); } else if (type == typeofSystemInt32) { sb.Append("int32"); } else if (type == typeofSystemUInt32) { sb.Append("uint32"); } else if (type == typeofSystemInt64) { sb.Append("int64"); } else if (type == typeofSystemUInt64) { sb.Append("uint64"); } else if (type == typeofSystemSingle) { sb.Append("float32"); } else if (type == typeofSystemDouble) { sb.Append("float64"); } else if (type == typeofSystemString) { sb.Append("string"); } else if (type == typeofSystemObject) { sb.Append("object"); } else if (type.FullName == "System.Type" && type.Assembly.GetName().Name == "mscorlib") { sb.Append("type"); } else { sb.Append("enum "); AppendTypeName(sb, type, typeName, false, securityCompatHack); } }
void ReadFixedArg(StringBuilder sb, ByteReader br, Type type, bool arrayElement = false) { if (type.IsArray) { int length = br.ReadInt32(); if (length == -1 && compat == CompatLevel.None) { sb.Append("nullref"); } else if (length == 0 && compat != CompatLevel.None) { throw new Managed.Reflection.BadImageFormatException(); } else { Type elementType = type.GetElementType(); AppendCATypeName(sb, elementType, null); sb.AppendFormat("[{0}](", length); for (int i = 0; i < length; i++) { if (i != 0) { sb.Append(' '); } if (elementType == typeofSystemObject) { string typeName; ReadFixedArg(sb, br, ReadFieldOrPropType(sb, br, out typeName), false); } else { ReadFixedArg(sb, br, elementType, true); } } sb.Append(')'); } } else if (type.FullName == "System.Type" && type.Assembly.GetName().Name == "mscorlib") { if (!arrayElement) { AppendCATypeName(sb, type, null); sb.Append('('); } string typeName; var type1 = ReadType(br, out typeName); if (type1 == null) { if (typeName == null) { sb.Append("nullref"); } else { sb.Append("class ").Append(QuoteIdentifier(typeName, true)); } } else { AppendTypeName(sb, type1, typeName, compat != CompatLevel.None && IsNestedTypeWithNamespace(type1)); } if (!arrayElement) { sb.Append(')'); } } else if (type.Assembly == mscorlib) { if (!arrayElement) { AppendCATypeName(sb, type, null); sb.Append('('); } if (type == typeofSystemBoolean) { sb.Append(br.ReadByte() == 0 ? "false" : "true"); } else if (type == typeofSystemByte) { sb.Append(br.ReadByte()); } else if (type == typeofSystemSByte) { sb.Append(br.ReadSByte()); } else if (type == typeofSystemChar) { sb.AppendFormat("0x{0:X4}", (int)br.ReadChar()); } else if (type == typeofSystemInt16) { sb.Append(br.ReadInt16()); } else if (type == typeofSystemUInt16) { sb.Append(br.ReadUInt16()); } else if (type == typeofSystemInt32) { sb.Append(br.ReadInt32()); } else if (type == typeofSystemUInt32) { sb.Append(br.ReadInt32()); } else if (type == typeofSystemInt64) { sb.Append(br.ReadInt64()); } else if (type == typeofSystemUInt64) { sb.Append(br.ReadInt64()); } else if (type == typeofSystemSingle) { sb.Append(ToString(br.ReadSingle(), true)); } else if (type == typeofSystemDouble) { sb.Append(ToString(br.ReadDouble(), true)); } else if (type == typeofSystemString) { var str = br.ReadString(); if (str == null) { sb.Append("nullref"); } else { if (compat != CompatLevel.None) { int pos = str.IndexOf((char)0); if (pos != -1) { str = str.Substring(0, pos); } } sb.Append(QuoteIdentifier(str, true)); } } else if (type == typeofSystemObject) { string typeName; ReadFixedArg(sb, br, ReadFieldOrPropType(sb, br, out typeName)); } else { throw new NotImplementedException(type.FullName); } if (!arrayElement) { sb.Append(')'); } } else if (type.__IsMissing || (compat != CompatLevel.None && typerefs.Contains(type))) { // ildasm actually tries to load the assembly, but we can't do that, so we cheat by having // a list of 'known' enum types if (type.Assembly.GetName().Name == "mscorlib") { switch (type.FullName) { case "System.AttributeTargets": case "System.Runtime.ConstrainedExecution.Consistency": case "System.Runtime.ConstrainedExecution.Cer": case "System.Security.Permissions.SecurityAction": case "System.Security.Permissions.SecurityPermissionFlag": case "System.Runtime.Versioning.ResourceScope": case "System.Runtime.InteropServices.CallingConvention": case "System.Runtime.InteropServices.CharSet": ReadFixedArg(sb, br, typeofSystemInt32); return; case "System.Security.SecurityRuleSet": if (compat != CompatLevel.V20) { ReadFixedArg(sb, br, typeofSystemByte); return; } break; case "System.Diagnostics.Tracing.EventLevel": case "System.Diagnostics.Tracing.EventTask": case "System.Diagnostics.Tracing.EventOpcode": if (compat != CompatLevel.V20 && compat != CompatLevel.V40) { ReadFixedArg(sb, br, typeofSystemInt32); return; } break; case "System.Type": sb.Append("type("); string typeName; AppendTypeName(sb, ReadType(br, out typeName), typeName); sb.Append(")"); return; } } switch (br.Length) { case 1: if (compat != CompatLevel.None) { // ildasm uses bool (???) as the underlying type in this case sb.AppendFormat("bool({0})", br.ReadByte() == 0 ? "false" : "true"); } else { // just guess that the enum has int8 as the underlying type sb.AppendFormat("int8({0})", br.ReadSByte()); } break; case 2: // just guess that the enum has int16 as the underlying type sb.AppendFormat("int16({0})", br.ReadInt16()); break; case 4: // just guess that the enum has int32 as the underlying type sb.AppendFormat("int32({0})", br.ReadInt32()); break; case 8: // just guess that the enum has int64 as the underlying type sb.AppendFormat("int64({0})", br.ReadInt64()); break; default: throw new Managed.Reflection.BadImageFormatException(); } } else if (type.IsEnum) { ReadFixedArg(sb, br, type.GetEnumUnderlyingType(), arrayElement); } else { throw new NotImplementedException(type.FullName); } }
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 Managed.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; } } } }
void AppendTypeName(StringBuilder sb, Type type, string typeName, bool noself = false, bool securityCompatHack = false) { if (type.Assembly == assembly && !type.__IsMissing && !noself && (!type.IsGenericType || type.IsGenericTypeDefinition) && !type.HasElementType) { AppendTypeName(sb, type); } else if (typerefs.Contains(type)) { sb.Append('[').Append(QuoteIdentifier(referencedAssemblies[type.Assembly])).Append(']'); AppendTypeName(sb, type); } else { if (securityCompatHack) { throw new Managed.Reflection.BadImageFormatException(); } sb.Append("class ").Append(QuoteIdentifier(typeName, true)); } }