Beispiel #1
0
        private void Disassemble(ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address)
        {
            WriteCommentLine(output, readyToRunMethod.SignatureString);
            byte[] codeBytes = new byte[runtimeFunction.Size];
            for (int i = 0; i < runtimeFunction.Size; i++)
            {
                codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
            }

            // TODO: Decorate the disassembly with Unwind, GC and debug info
            var codeReader = new ByteArrayCodeReader(codeBytes);
            var decoder    = Decoder.Create(bitness, codeReader);

            decoder.IP = address;
            ulong endRip = decoder.IP + (uint)codeBytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            string    disassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(null);
            Formatter formatter         = null;

            if (disassemblyFormat.Equals(ReadyToRunOptions.intel))
            {
                formatter = new NasmFormatter();
            }
            else
            {
                Debug.Assert(disassemblyFormat.Equals(ReadyToRunOptions.gas));
                formatter = new GasFormatter();
            }
            formatter.Options.DigitSeparator        = "`";
            formatter.Options.FirstOperandCharIndex = 10;
            var tempOutput = new StringOutput();

            foreach (var instr in instructions)
            {
                int byteBaseIndex = (int)(instr.IP - address);
                foreach (var bound in runtimeFunction.DebugInfo.BoundsList)
                {
                    if (bound.NativeOffset == byteBaseIndex)
                    {
                        if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog)
                        {
                            WriteCommentLine(output, "Prolog");
                        }
                        else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog)
                        {
                            WriteCommentLine(output, "Epilog");
                        }
                        else
                        {
                            WriteCommentLine(output, $"IL_{bound.ILOffset:x4}");
                        }
                    }
                }
                formatter.Format(instr, tempOutput);
                output.Write(instr.IP.ToString("X16"));
                output.Write(" ");
                int instrLen = instr.Length;
                for (int i = 0; i < instrLen; i++)
                {
                    output.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
                }
                int missingBytes = 10 - instrLen;
                for (int i = 0; i < missingBytes; i++)
                {
                    output.Write("  ");
                }
                output.Write(" ");
                output.WriteLine(tempOutput.ToStringAndReset());
            }
            output.WriteLine();
        }
Beispiel #2
0
 abstract internal void DumpMethod(ReadyToRunMethod method);
        private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10)
        {
            // TODO: Decorate the disassembly with GCInfo
            WriteCommentLine(output, readyToRunMethod.SignatureString);

            Dictionary <ulong, UnwindCode> unwindInfo = null;

            if (ReadyToRunOptions.GetIsShowUnwindInfo(null) && bitness == 64)
            {
                unwindInfo = WriteUnwindInfo(runtimeFunction, output);
            }

            bool isShowDebugInfo = ReadyToRunOptions.GetIsShowDebugInfo(null);
            Dictionary <VarLocType, HashSet <ValueTuple <DebugInfo, NativeVarInfo> > > debugInfo = null;

            if (isShowDebugInfo)
            {
                debugInfo = WriteDebugInfo(readyToRunMethod, output);
            }

            byte[] codeBytes = new byte[runtimeFunction.Size];
            for (int i = 0; i < runtimeFunction.Size; i++)
            {
                codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
            }

            var codeReader = new ByteArrayCodeReader(codeBytes);
            var decoder    = Decoder.Create(bitness, codeReader);

            decoder.IP = address;
            ulong endRip = decoder.IP + (uint)codeBytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            string    disassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(null);
            Formatter formatter         = null;

            if (disassemblyFormat.Equals(ReadyToRunOptions.intel))
            {
                formatter = new NasmFormatter();
            }
            else
            {
                Debug.Assert(disassemblyFormat.Equals(ReadyToRunOptions.gas));
                formatter = new GasFormatter();
            }
            formatter.Options.DigitSeparator        = "`";
            formatter.Options.FirstOperandCharIndex = 10;
            var   tempOutput  = new StringOutput();
            ulong baseInstrIP = instructions[0].IP;

            foreach (var instr in instructions)
            {
                int byteBaseIndex = (int)(instr.IP - address);
                if (isShowDebugInfo && runtimeFunction.DebugInfo != null)
                {
                    foreach (var bound in runtimeFunction.DebugInfo.BoundsList)
                    {
                        if (bound.NativeOffset == byteBaseIndex)
                        {
                            if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog)
                            {
                                WriteCommentLine(output, "Prolog");
                            }
                            else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog)
                            {
                                WriteCommentLine(output, "Epilog");
                            }
                            else
                            {
                                WriteCommentLine(output, $"IL_{bound.ILOffset:x4}");
                            }
                        }
                    }
                }
                formatter.Format(instr, tempOutput);
                output.Write(instr.IP.ToString("X16"));
                output.Write(" ");
                int instrLen = instr.Length;
                for (int i = 0; i < instrLen; i++)
                {
                    output.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
                }
                int missingBytes = 10 - instrLen;
                for (int i = 0; i < missingBytes; i++)
                {
                    output.Write("  ");
                }
                output.Write(" ");
                output.Write(tempOutput.ToStringAndReset());
                DecorateUnwindInfo(output, unwindInfo, baseInstrIP, instr);
                DecorateDebugInfo(output, instr, debugInfo, baseInstrIP);
                DecorateCallSite(currentFile, output, reader, showMetadataTokens, showMetadataTokensInBase10, instr);
            }
            output.WriteLine();
        }
        private Dictionary <VarLocType, HashSet <(DebugInfo debugInfo, NativeVarInfo varLoc)> > WriteDebugInfo(ReadyToRunMethod readyToRunMethod, ITextOutput output)
        {
            Dictionary <VarLocType, HashSet <(DebugInfo debugInfo, NativeVarInfo varLoc)> > debugInfoDict = new Dictionary <VarLocType, HashSet <(DebugInfo debugInfo, NativeVarInfo varLoc)> >();
            IReadOnlyList <RuntimeFunction> runTimeList = readyToRunMethod.RuntimeFunctions;

            foreach (RuntimeFunction runtimeFunction in runTimeList)
            {
                DebugInfo debugInfo = runtimeFunction.DebugInfo;
                if (debugInfo != null && debugInfo.BoundsList.Count > 0)
                {
                    for (int i = 0; i < debugInfo.VariablesList.Count; ++i)
                    {
                        var varLoc = debugInfo.VariablesList[i];
                        try {
                            var  typeSet = new HashSet <ValueTuple <DebugInfo, NativeVarInfo> >();
                            bool found   = debugInfoDict.TryGetValue(varLoc.VariableLocation.VarLocType, out typeSet);
                            if (found)
                            {
                                (DebugInfo debugInfo, NativeVarInfo varLoc)newTuple = (debugInfo, varLoc);
                                typeSet.Add(newTuple);
                            }
                            else
                            {
                                typeSet = new HashSet <ValueTuple <DebugInfo, NativeVarInfo> >();
                                debugInfoDict.Add(varLoc.VariableLocation.VarLocType, typeSet);
                                (DebugInfo debugInfo, NativeVarInfo varLoc)newTuple = (debugInfo, varLoc);
                                typeSet.Add(newTuple);
                            }
                        } catch (ArgumentNullException) {
                            output.WriteLine("Failed to find hash set of Debug info type");
                        }

                        if (varLoc.VariableLocation.VarLocType != VarLocType.VLT_REG && varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK &&
                            varLoc.VariableLocation.VarLocType != VarLocType.VLT_STK_BYREF)
                        {
                            output.WriteLine($"    Variable Number: {varLoc.VariableNumber}");
                            output.WriteLine($"    Start Offset: 0x{varLoc.StartOffset:X}");
                            output.WriteLine($"    End Offset: 0x{varLoc.EndOffset:X}");
                            output.WriteLine($"    Loc Type: {varLoc.VariableLocation.VarLocType}");
                            switch (varLoc.VariableLocation.VarLocType)
                            {
                            case VarLocType.VLT_REG:
                            case VarLocType.VLT_REG_FP:
                            case VarLocType.VLT_REG_BYREF:
                                output.WriteLine($"    Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}");
                                break;

                            case VarLocType.VLT_STK:
                            case VarLocType.VLT_STK_BYREF:
                                output.WriteLine($"    Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}");
                                output.WriteLine($"    Stack Offset: {varLoc.VariableLocation.Data2}");
                                break;

                            case VarLocType.VLT_REG_REG:
                                output.WriteLine($"    Register 1: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}");
                                output.WriteLine($"    Register 2: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}");
                                break;

                            case VarLocType.VLT_REG_STK:
                                output.WriteLine($"    Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}");
                                output.WriteLine($"    Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}");
                                output.WriteLine($"    Stack Offset: {varLoc.VariableLocation.Data3}");
                                break;

                            case VarLocType.VLT_STK_REG:
                                output.WriteLine($"    Stack Offset: {varLoc.VariableLocation.Data1}");
                                output.WriteLine($"    Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data2)}");
                                output.WriteLine($"    Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data3)}");
                                break;

                            case VarLocType.VLT_STK2:
                                output.WriteLine($"    Base Register: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}");
                                output.WriteLine($"    Stack Offset: {varLoc.VariableLocation.Data2}");
                                break;

                            case VarLocType.VLT_FPSTK:
                                output.WriteLine($"    Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}");
                                break;

                            case VarLocType.VLT_FIXED_VA:
                                output.WriteLine($"    Offset: {DebugInfo.GetPlatformSpecificRegister(debugInfo.Machine, varLoc.VariableLocation.Data1)}");
                                break;

                            default:
                                output.WriteLine("WRN: Unexpected variable location type");
                                break;
                            }
                            output.WriteLine("");
                        }
                    }
                }
            }
            return(debugInfoDict);
        }
Beispiel #5
0
 public MethodPair(ReadyToRunMethod leftMethod, ReadyToRunMethod rightMethod)
 {
     LeftMethod  = leftMethod;
     RightMethod = rightMethod;
 }
        private void Disassemble(PEFile currentFile, ITextOutput output, ReadyToRunReader reader, ReadyToRunMethod readyToRunMethod, RuntimeFunction runtimeFunction, int bitness, ulong address, bool showMetadataTokens, bool showMetadataTokensInBase10)
        {
            WriteCommentLine(output, readyToRunMethod.SignatureString);
            byte[] codeBytes = new byte[runtimeFunction.Size];
            for (int i = 0; i < runtimeFunction.Size; i++)
            {
                codeBytes[i] = reader.Image[reader.GetOffset(runtimeFunction.StartAddress) + i];
            }

            // TODO: Decorate the disassembly with Unwind, GC and debug info
            var codeReader = new ByteArrayCodeReader(codeBytes);
            var decoder    = Decoder.Create(bitness, codeReader);

            decoder.IP = address;
            ulong endRip = decoder.IP + (uint)codeBytes.Length;

            var instructions = new InstructionList();

            while (decoder.IP < endRip)
            {
                decoder.Decode(out instructions.AllocUninitializedElement());
            }

            string    disassemblyFormat = ReadyToRunOptions.GetDisassemblyFormat(null);
            Formatter formatter         = null;

            if (disassemblyFormat.Equals(ReadyToRunOptions.intel))
            {
                formatter = new NasmFormatter();
            }
            else
            {
                Debug.Assert(disassemblyFormat.Equals(ReadyToRunOptions.gas));
                formatter = new GasFormatter();
            }
            formatter.Options.DigitSeparator        = "`";
            formatter.Options.FirstOperandCharIndex = 10;
            var tempOutput = new StringOutput();

            foreach (var instr in instructions)
            {
                int byteBaseIndex = (int)(instr.IP - address);
                if (runtimeFunction.DebugInfo != null)
                {
                    foreach (var bound in runtimeFunction.DebugInfo.BoundsList)
                    {
                        if (bound.NativeOffset == byteBaseIndex)
                        {
                            if (bound.ILOffset == (uint)DebugInfoBoundsType.Prolog)
                            {
                                WriteCommentLine(output, "Prolog");
                            }
                            else if (bound.ILOffset == (uint)DebugInfoBoundsType.Epilog)
                            {
                                WriteCommentLine(output, "Epilog");
                            }
                            else
                            {
                                WriteCommentLine(output, $"IL_{bound.ILOffset:x4}");
                            }
                        }
                    }
                }
                formatter.Format(instr, tempOutput);
                output.Write(instr.IP.ToString("X16"));
                output.Write(" ");
                int instrLen = instr.Length;
                for (int i = 0; i < instrLen; i++)
                {
                    output.Write(codeBytes[byteBaseIndex + i].ToString("X2"));
                }
                int missingBytes = 10 - instrLen;
                for (int i = 0; i < missingBytes; i++)
                {
                    output.Write("  ");
                }
                output.Write(" ");
                output.Write(tempOutput.ToStringAndReset());
                int importCellAddress = (int)instr.IPRelativeMemoryAddress;
                if (instr.IsCallNearIndirect && reader.ImportCellNames.ContainsKey(importCellAddress))
                {
                    output.Write(" ; ");
                    ReadyToRunSignature signature = reader.ImportSignatures[(int)instr.IPRelativeMemoryAddress];
                    switch (signature)
                    {
                    case MethodDefEntrySignature methodDefSignature:
                        var methodDefToken = MetadataTokens.EntityHandle(unchecked ((int)methodDefSignature.MethodDefToken));
                        if (showMetadataTokens)
                        {
                            if (showMetadataTokensInBase10)
                            {
                                output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken)}) ", "metadata");
                            }
                            else
                            {
                                output.WriteReference(currentFile, methodDefToken, $"({MetadataTokens.GetToken(methodDefToken):X8}) ", "metadata");
                            }
                        }
                        methodDefToken.WriteTo(currentFile, output, Decompiler.Metadata.GenericContext.Empty);
                        break;

                    case MethodRefEntrySignature methodRefSignature:
                        var methodRefToken = MetadataTokens.EntityHandle(unchecked ((int)methodRefSignature.MethodRefToken));
                        if (showMetadataTokens)
                        {
                            if (showMetadataTokensInBase10)
                            {
                                output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken)}) ", "metadata");
                            }
                            else
                            {
                                output.WriteReference(currentFile, methodRefToken, $"({MetadataTokens.GetToken(methodRefToken):X8}) ", "metadata");
                            }
                        }
                        methodRefToken.WriteTo(currentFile, output, Decompiler.Metadata.GenericContext.Empty);
                        break;

                    default:
                        output.WriteLine(reader.ImportCellNames[importCellAddress]);
                        break;
                    }
                    output.WriteLine();
                }
                else
                {
                    output.WriteLine();
                }
            }
            output.WriteLine();
        }