.NET Decompiler with support for PDB generation, ReadyToRun, Metadata (&more) - cross-platform!
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

266 lines
8.4 KiB

// Copyright (c) 2011 AlphaSierraPapa for the SharpDevelop Team
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this
// software and associated documentation files (the "Software"), to deal in the Software
// without restriction, including without limitation the rights to use, copy, modify, merge,
// publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
// to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or
// substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
// INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
// PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE
// FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
// OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
// DEALINGS IN THE SOFTWARE.
using System;
using Mono.Cecil;
using Mono.Cecil.Cil;
namespace ICSharpCode.Decompiler.Disassembler
{
public static class DisassemblerHelpers
{
public static void WriteOffsetReference(ITextOutput writer, Instruction instruction)
{
writer.WriteReference(CecilExtensions.OffsetToString(instruction.Offset), instruction);
}
public static void WriteTo(this ExceptionHandler exceptionHandler, ITextOutput writer)
{
writer.Write("Try ");
WriteOffsetReference(writer, exceptionHandler.TryStart);
writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.TryEnd);
writer.Write(exceptionHandler.HandlerType.ToString());
if (exceptionHandler.FilterStart != null) {
writer.Write(' ');
WriteOffsetReference(writer, exceptionHandler.FilterStart);
writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.FilterEnd);
writer.Write(" handler ");
}
if (exceptionHandler.CatchType != null) {
writer.Write(' ');
exceptionHandler.CatchType.WriteTo(writer);
}
writer.Write(' ');
WriteOffsetReference(writer, exceptionHandler.HandlerStart);
writer.Write('-');
WriteOffsetReference(writer, exceptionHandler.HandlerEnd);
}
public static void WriteTo(this Instruction instruction, ITextOutput writer)
{
writer.WriteDefinition(CecilExtensions.OffsetToString(instruction.Offset), instruction);
writer.Write(": ");
writer.Write(instruction.OpCode.Name);
if(null != instruction.Operand) {
writer.Write(' ');
WriteOperand(writer, instruction.Operand);
}
}
static void WriteLabelList(ITextOutput writer, Instruction[] instructions)
{
writer.Write("(");
for(int i = 0; i < instructions.Length; i++) {
if(i != 0) writer.Write(", ");
WriteOffsetReference(writer, instructions[i]);
}
writer.Write(")");
}
static string ToInvariantCultureString(object value)
{
IConvertible convertible = value as IConvertible;
return(null != convertible)
? convertible.ToString(System.Globalization.CultureInfo.InvariantCulture)
: value.ToString();
}
public static void WriteTo(this MethodReference method, ITextOutput writer)
{
if (method.HasThis)
writer.Write("instance ");
method.ReturnType.WriteTo(writer);
writer.Write(' ');
method.DeclaringType.WriteTo(writer, true);
writer.Write("::");
writer.WriteReference(method.Name, method);
writer.Write("(");
var parameters = method.Parameters;
for(int i = 0; i < parameters.Count; ++i) {
if (i > 0) writer.Write(", ");
parameters[i].ParameterType.WriteTo(writer);
}
writer.Write(")");
}
static void WriteTo(this FieldReference field, ITextOutput writer)
{
field.FieldType.WriteTo(writer);
writer.Write(' ');
field.DeclaringType.WriteTo(writer);
writer.Write("::");
writer.WriteReference(field.Name, field);
}
public static string Escape(string identifier)
{
return identifier;
}
public static void WriteTo(this TypeReference type, ITextOutput writer, bool onlyName = false, bool shortName = false)
{
if (type is PinnedType) {
writer.Write("pinned ");
type.GetElementType().WriteTo(writer, onlyName, shortName);
} else if (type is ArrayType) {
ArrayType at = (ArrayType)type;
at.ElementType.WriteTo(writer, onlyName, shortName);
writer.Write('[');
writer.Write(string.Join(", ", at.Dimensions));
writer.Write(']');
} else if (type is GenericParameter) {
writer.WriteReference(type.Name, type);
} else if (type is ByReferenceType) {
type.GetElementType().WriteTo(writer, onlyName, shortName);
writer.Write('&');
} else if (type is PointerType) {
type.GetElementType().WriteTo(writer, onlyName, shortName);
writer.Write('*');
} else if (type is GenericInstanceType) {
type.GetElementType().WriteTo(writer, onlyName, shortName);
writer.Write('<');
var arguments = ((GenericInstanceType)type).GenericArguments;
for (int i = 0; i < arguments.Count; i++) {
if (i > 0)
writer.Write(", ");
arguments[i].WriteTo(writer, onlyName, shortName);
}
writer.Write('>');
} else if (type is OptionalModifierType) {
writer.Write("modopt(");
((OptionalModifierType)type).ModifierType.WriteTo(writer, true, shortName);
writer.Write(") ");
type.GetElementType().WriteTo(writer, onlyName, shortName);
} else if (type is RequiredModifierType) {
writer.Write("modreq(");
((RequiredModifierType)type).ModifierType.WriteTo(writer, true, shortName);
writer.Write(") ");
type.GetElementType().WriteTo(writer, onlyName, shortName);
} else {
string name = PrimitiveTypeName(type);
if (name != null) {
writer.Write(name);
} else {
if (!onlyName)
writer.Write(type.IsValueType ? "valuetype " : "class ");
if (type.DeclaringType != null) {
type.DeclaringType.WriteTo(writer, true, shortName);
writer.Write('/');
writer.WriteReference(Escape(type.Name), type);
} else {
if (!type.IsDefinition && type.Scope != null && !shortName && !(type is TypeSpecification))
writer.Write("[{0}]", Escape(type.Scope.Name));
writer.WriteReference(shortName ? type.Name : type.FullName, type);
}
}
}
}
public static void WriteOperand(ITextOutput writer, object operand)
{
if (operand == null)
throw new ArgumentNullException("operand");
Instruction targetInstruction = operand as Instruction;
if (targetInstruction != null) {
WriteOffsetReference(writer, targetInstruction);
return;
}
Instruction[] targetInstructions = operand as Instruction[];
if (targetInstructions != null) {
WriteLabelList(writer, targetInstructions);
return;
}
VariableReference variableRef = operand as VariableReference;
if (variableRef != null) {
writer.WriteReference(variableRef.Index.ToString(), variableRef);
return;
}
MethodReference methodRef = operand as MethodReference;
if (methodRef != null) {
methodRef.WriteTo(writer);
return;
}
TypeReference typeRef = operand as TypeReference;
if (typeRef != null) {
typeRef.WriteTo(writer);
return;
}
FieldReference fieldRef = operand as FieldReference;
if (fieldRef != null) {
fieldRef.WriteTo(writer);
return;
}
string s = operand as string;
if (s != null) {
writer.Write("\"" + s.Replace("\\", "\\\\").Replace("\"", "\\\"") + "\"");
return;
}
s = ToInvariantCultureString(operand);
writer.Write(s);
}
public static string PrimitiveTypeName(this TypeReference type)
{
switch (type.FullName) {
case "System.SByte":
return "int8";
case "System.Int16":
return "int16";
case "System.Int32":
return "int32";
case "System.Int64":
return "int64";
case "System.Byte":
return "uint8";
case "System.UInt16":
return "uint16";
case "System.UInt32":
return "uint32";
case "System.UInt64":
return "uint64";
case "System.Single":
return "float32";
case "System.Double":
return "float64";
case "System.Void":
return "void";
case "System.Boolean":
return "bool";
case "System.String":
return "string";
case "System.Char":
return "char";
case "System.Object":
return "object";
default:
return null;
}
}
}
}