示例#1
0
        /// <summary>
        /// Parse a single instruction and return the RVA of the next instruction.
        /// </summary>
        /// <param name="rtf">Runtime function to parse</param>
        /// <param name="imageOffset">Offset within the PE image byte array</param>
        /// <param name="rtfOffset">Instruction offset within the runtime function</param>
        /// <param name="instruction">Output text representation of the instruction</param>
        /// <returns>Instruction size in bytes - i.o.w. the next instruction starts at rtfOffset + (the return value)</returns>
        public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, out string instruction)
        {
            if (_disasm == IntPtr.Zero)
            {
                instruction = "";
                return(rtf.Size);
            }

            int instrSize = CoreDisTools.GetInstruction(_disasm, rtf, imageOffset, rtfOffset, _reader.Image, out instruction);

            instruction = instruction.Replace('\t', ' ');

            switch (_reader.Machine)
            {
            case Machine.Amd64:
            case Machine.IA64:
                ProbeX64Quirks(rtf, imageOffset, rtfOffset, instrSize, ref instruction);
                break;

            case Machine.I386:
                break;

            case Machine.ArmThumb2:
            case Machine.Thumb:
                break;

            case Machine.Arm64:
                break;

            default:
                throw new NotImplementedException();
            }

            return(instrSize);
        }
示例#2
0
 /// <summary>
 /// Store the R2R reader and construct the disassembler for the appropriate architecture.
 /// </summary>
 /// <param name="reader"></param>
 public Disassembler(ReadyToRunReader reader, DumpOptions options)
 {
     _reader  = reader;
     _options = options;
     _disasm  = CoreDisTools.GetDisasm(_reader.Machine);
     SetIndentations();
 }
示例#3
0
        public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, out string instruction)
        {
            int instrSize = CoreDisTools.GetInstruction(_disasm, rtf, imageOffset, rtfOffset, _image, out instruction);

            switch (_machine)
            {
            case Machine.Amd64:
            case Machine.IA64:
                ProbeX64Quirks(rtf, imageOffset, rtfOffset, instrSize, ref instruction);
                break;

            case Machine.I386:
                break;

            case Machine.ArmThumb2:
            case Machine.Thumb:
                break;

            case Machine.Arm64:
                break;

            default:
                throw new NotImplementedException();
            }

            return(instrSize);
        }
示例#4
0
 /// <summary>
 /// Shut down the native disassembler interface.
 /// </summary>
 public void Dispose()
 {
     if (_disasm != IntPtr.Zero)
     {
         CoreDisTools.FinishDisasm(_disasm);
     }
 }
示例#5
0
文件: R2RDump.cs 项目: kerwon/coreclr
 /// <summary>
 /// Dumps one runtime function.
 /// </summary>
 private void DumpRuntimeFunction(R2RReader r2r, RuntimeFunction rtf)
 {
     if (_disasm)
     {
         _writer.WriteLine($"Id: {rtf.Id}");
         _writer.Write(CoreDisTools.GetCodeBlock(_disassembler, rtf.StartAddress, r2r.GetOffset(rtf.StartAddress), r2r.Image, rtf.Size));
     }
     else
     {
         _writer.Write($"{rtf}");
     }
     if (_raw)
     {
         _writer.WriteLine("Raw Bytes:");
         DumpBytes(r2r, rtf.StartAddress, (uint)rtf.Size);
     }
     if (_unwind)
     {
         _writer.WriteLine("UnwindInfo:");
         _writer.Write(rtf.UnwindInfo);
         if (_raw)
         {
             DumpBytes(r2r, rtf.UnwindRVA, (uint)rtf.UnwindInfo.Size);
         }
     }
     _writer.WriteLine();
 }
示例#6
0
        /// <summary>
        /// Dumps disassembly and register liveness
        /// </summary>
        internal override void DumpDisasm(RuntimeFunction rtf, int imageOffset, XmlNode parentNode)
        {
            int rtfOffset  = 0;
            int codeOffset = rtf.CodeOffset;

            while (rtfOffset < rtf.Size)
            {
                string instr;
                int    instrSize = _disassembler.GetInstruction(rtf, imageOffset, rtfOffset, out instr);

                AddXMLNode("offset" + codeOffset, instr, parentNode, $"{codeOffset}");

                if (rtf.Method.GcInfo != null && rtf.Method.GcInfo.Transitions.ContainsKey(codeOffset))
                {
                    foreach (BaseGcTransition transition in rtf.Method.GcInfo.Transitions[codeOffset])
                    {
                        AddXMLNode("Transition", transition.ToString(), parentNode, $"{codeOffset}");
                    }
                }

                CoreDisTools.ClearOutputBuffer();
                rtfOffset  += instrSize;
                codeOffset += instrSize;
            }
        }
示例#7
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

            if (_help)
            {
                _writer.WriteLine(syntax.GetHelpText());
                return(0);
            }

            if (_inputFilenames.Count == 0)
            {
                throw new ArgumentException("Input filename must be specified (--in <file>)");
            }

            // open output stream
            if (_outputFilename != null)
            {
                _writer = File.CreateText(_outputFilename);
            }
            else
            {
                _writer = Console.Out;
            }

            try
            {
                foreach (string filename in _inputFilenames)
                {
                    R2RReader r2r = new R2RReader(filename);
                    if (_disasm)
                    {
                        _disassembler = CoreDisTools.GetDisasm(r2r.Machine);
                    }

                    Dump(r2r);

                    if (_disasm)
                    {
                        CoreDisTools.FinishDisasm(_disassembler);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.ToString());
                return(1);
            }
            finally
            {
                // close output stream
                _writer.Close();
            }

            return(0);
        }
示例#8
0
 /// <summary>
 /// Dumps one runtime function.
 /// </summary>
 private void DumpRuntimeFunction(R2RReader r2r, RuntimeFunction rtf)
 {
     if (_disasm)
     {
         _writer.WriteLine($"Id: {rtf.Id}");
         CoreDisTools.DumpCodeBlock(_disassembler, rtf.StartAddress, r2r.GetOffset(rtf.StartAddress), r2r.Image, rtf.Size);
     }
     else
     {
         _writer.Write($"{rtf}");
     }
     if (_raw)
     {
         DumpBytes(r2r, rtf.StartAddress, (uint)rtf.Size);
     }
     _writer.WriteLine();
 }
示例#9
0
        /// <summary>
        /// Dumps disassembly and register liveness
        /// </summary>
        internal override void DumpDisasm(RuntimeFunction rtf, int imageOffset)
        {
            int    indent       = (_options.Naked ? 11 : 32);
            string indentString = new string(' ', indent);
            int    rtfOffset    = 0;
            int    codeOffset   = rtf.CodeOffset;

            while (rtfOffset < rtf.Size)
            {
                string instr;
                int    instrSize = _disassembler.GetInstruction(rtf, imageOffset, rtfOffset, out instr);

                if (_r2r.Machine == Machine.Amd64 && ((ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo)rtf.UnwindInfo).UnwindCodes.ContainsKey(codeOffset))
                {
                    List <ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode> codes = ((ILCompiler.Reflection.ReadyToRun.Amd64.UnwindInfo)rtf.UnwindInfo).UnwindCodes[codeOffset];
                    foreach (ILCompiler.Reflection.ReadyToRun.Amd64.UnwindCode code in codes)
                    {
                        _writer.Write($"{indentString}{code.UnwindOp} {code.OpInfoStr}");
                        if (code.NextFrameOffset != -1)
                        {
                            _writer.WriteLine($"{indentString}{code.NextFrameOffset}");
                        }
                        _writer.WriteLine();
                    }
                }

                if (rtf.Method.GcInfo?.Transitions != null && rtf.Method.GcInfo.Transitions.ContainsKey(codeOffset))
                {
                    foreach (BaseGcTransition transition in rtf.Method.GcInfo.Transitions[codeOffset])
                    {
                        _writer.WriteLine($"{indentString}{transition}");
                    }
                }

                /* According to https://msdn.microsoft.com/en-us/library/ck9asaa9.aspx and src/vm/gcinfodecoder.cpp
                 * UnwindCode and GcTransition CodeOffsets are encoded with a -1 adjustment (that is, it's the offset of the start of the next instruction)
                 */
                _writer.Write(instr);

                CoreDisTools.ClearOutputBuffer();
                rtfOffset  += instrSize;
                codeOffset += instrSize;
            }
        }
示例#10
0
        internal unsafe override void DumpDisasm(IntPtr Disasm, RuntimeFunction rtf, int imageOffset, byte[] image, XmlNode parentNode = null)
        {
            int rtfOffset  = 0;
            int codeOffset = rtf.CodeOffset;

            while (rtfOffset < rtf.Size)
            {
                string instr;
                int    instrSize = CoreDisTools.GetInstruction(Disasm, rtf, imageOffset, rtfOffset, image, out instr);

                _writer.Write(instr);
                if (rtf.Method.GcInfo != null && rtf.Method.GcInfo.Transitions.ContainsKey(codeOffset))
                {
                    _writer.WriteLine($"\t\t\t\t{rtf.Method.GcInfo.Transitions[codeOffset].GetSlotState(rtf.Method.GcInfo.SlotTable)}");
                }

                CoreDisTools.ClearOutputBuffer();
                rtfOffset  += instrSize;
                codeOffset += instrSize;
            }
        }
示例#11
0
        /// <summary>
        /// Dumps disassembly and register liveness
        /// </summary>
        internal override void DumpDisasm(RuntimeFunction rtf, int imageOffset, XmlNode parentNode = null)
        {
            int rtfOffset  = 0;
            int codeOffset = rtf.CodeOffset;

            while (rtfOffset < rtf.Size)
            {
                string instr;
                int    instrSize = _disassembler.GetInstruction(rtf, imageOffset, rtfOffset, out instr);

                _writer.Write(instr);

                if (_r2r.Machine == Machine.Amd64 && ((Amd64.UnwindInfo)rtf.UnwindInfo).UnwindCodes.ContainsKey(codeOffset))
                {
                    List <Amd64.UnwindCode> codes = ((Amd64.UnwindInfo)rtf.UnwindInfo).UnwindCodes[codeOffset];
                    foreach (Amd64.UnwindCode code in codes)
                    {
                        _writer.Write($"\t\t\t\t{code.UnwindOp} {code.OpInfoStr}");
                        if (code.NextFrameOffset != -1)
                        {
                            _writer.WriteLine($" - {code.NextFrameOffset}");
                        }
                        _writer.WriteLine();
                    }
                }

                if (rtf.Method.GcInfo != null && rtf.Method.GcInfo.Transitions.ContainsKey(codeOffset))
                {
                    foreach (BaseGcTransition transition in rtf.Method.GcInfo.Transitions[codeOffset])
                    {
                        _writer.WriteLine($"\t\t\t\t{transition.ToString()}");
                    }
                }

                CoreDisTools.ClearOutputBuffer();
                rtfOffset  += instrSize;
                codeOffset += instrSize;
            }
        }
示例#12
0
文件: XmlDumper.cs 项目: htyu/coreclr
        internal unsafe override void DumpDisasm(IntPtr Disasm, RuntimeFunction rtf, int imageOffset, byte[] image, XmlNode parentNode)
        {
            int rtfOffset  = 0;
            int codeOffset = rtf.CodeOffset;
            Dictionary <int, GcInfo.GcTransition> transitions = rtf.Method.GcInfo.Transitions;
            GcSlotTable slotTable = rtf.Method.GcInfo.SlotTable;

            while (rtfOffset < rtf.Size)
            {
                string instr;
                int    instrSize = CoreDisTools.GetInstruction(Disasm, rtf, imageOffset, rtfOffset, image, out instr);

                AddXMLNode("offset" + codeOffset, instr, parentNode, $"{codeOffset}");
                if (transitions.ContainsKey(codeOffset))
                {
                    AddXMLNode("Transition", transitions[codeOffset].GetSlotState(slotTable), parentNode, $"{codeOffset}");
                }

                CoreDisTools.ClearOutputBuffer();
                rtfOffset  += instrSize;
                codeOffset += instrSize;
            }
        }
示例#13
0
        /// <summary>
        /// Dumps disassembly and register liveness
        /// </summary>
        internal override void DumpDisasm(RuntimeFunction rtf, int imageOffset, XmlNode parentNode = null)
        {
            int rtfOffset  = 0;
            int codeOffset = rtf.CodeOffset;

            while (rtfOffset < rtf.Size)
            {
                string instr;
                int    instrSize = _disassembler.GetInstruction(rtf, imageOffset, rtfOffset, out instr);

                _writer.Write(instr);
                if (rtf.Method.GcInfo != null && rtf.Method.GcInfo.Transitions.ContainsKey(codeOffset))
                {
                    foreach (BaseGcTransition transition in rtf.Method.GcInfo.Transitions[codeOffset])
                    {
                        _writer.WriteLine($"\t\t\t\t{transition.ToString()}");
                    }
                }

                CoreDisTools.ClearOutputBuffer();
                rtfOffset  += instrSize;
                codeOffset += instrSize;
            }
        }
示例#14
0
 public Disassembler(byte[] image, Machine machine)
 {
     _disasm  = CoreDisTools.GetDisasm(machine);
     _image   = image;
     _machine = machine;
 }
示例#15
0
        /// <summary>
        /// Parse a single instruction and return the RVA of the next instruction.
        /// </summary>
        /// <param name="rtf">Runtime function to parse</param>
        /// <param name="imageOffset">Offset within the PE image byte array</param>
        /// <param name="rtfOffset">Instruction offset within the runtime function</param>
        /// <param name="instruction">Output text representation of the instruction</param>
        /// <returns>Instruction size in bytes - i.o.w. the next instruction starts at rtfOffset + (the return value)</returns>
        public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, out string instruction)
        {
            if (_disasm == IntPtr.Zero)
            {
                instruction = "";
                return(rtf.Size);
            }

            int instrSize = CoreDisTools.GetInstruction(_disasm, rtf, imageOffset, rtfOffset, _reader.Image, out instruction);

            CoreDisTools.ClearOutputBuffer();

            instruction = instruction.Replace('\t', ' ');

            if (_options.Naked)
            {
                StringBuilder nakedInstruction = new StringBuilder();
                foreach (string line in instruction.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
                {
                    int colon = line.IndexOf(':');
                    if (colon >= 0)
                    {
                        colon += 2;
                        while (colon + 3 <= line.Length &&
                               IsXDigit(line[colon]) &&
                               IsXDigit(line[colon + 1]) &&
                               line[colon + 2] == ' ')
                        {
                            colon += 3;
                        }

                        if (!_options.HideOffsets)
                        {
                            nakedInstruction.Append($"{(rtfOffset + rtf.CodeOffset),8:x4}:");
                            nakedInstruction.Append("  ");
                        }
                        else
                        {
                            nakedInstruction.Append("    ");
                        }
                        nakedInstruction.Append(line.Substring(colon).TrimStart());
                        nakedInstruction.Append('\n');
                    }
                    else
                    {
                        nakedInstruction.Append(' ', 7);
                        nakedInstruction.Append(line.TrimStart());
                        nakedInstruction.Append('\n');
                    }
                }
                instruction = nakedInstruction.ToString();
            }

            switch (_reader.Machine)
            {
            case Machine.Amd64:
                ProbeX64Quirks(rtf, imageOffset, rtfOffset, instrSize, ref instruction);
                break;

            case Machine.I386:
                ProbeX86Quirks(rtf, imageOffset, rtfOffset, instrSize, ref instruction);
                break;

            case Machine.ArmThumb2:
            case Machine.Thumb:
                break;

            case Machine.Arm64:
                break;

            default:
                throw new NotImplementedException();
            }

            instruction = instruction.Replace("\n", Environment.NewLine);
            return(instrSize);
        }
示例#16
0
 /// <summary>
 /// Store the R2R reader and construct the disassembler for the appropriate architecture.
 /// </summary>
 /// <param name="reader"></param>
 public Disassembler(R2RReader reader)
 {
     _reader = reader;
     _disasm = CoreDisTools.GetDisasm(_reader.Machine);
 }
示例#17
0
        /// <summary>
        /// Parse and dump a single instruction and return its size in bytes.
        /// </summary>
        /// <param name="rtf">Runtime function to parse</param>
        /// <param name="imageOffset">Offset within the PE image byte array</param>
        /// <param name="rtfOffset">Instruction offset within the runtime function</param>
        /// <param name="instruction">Output text representation of the instruction</param>
        /// <returns>Instruction size in bytes - i.o.w. the next instruction starts at rtfOffset + (the return value)</returns>
        public int GetInstruction(RuntimeFunction rtf, int imageOffset, int rtfOffset, out string instruction)
        {
            if (_disasm == IntPtr.Zero)
            {
                instruction = "";
                return(rtf.Size);
            }

            int instrSize = CoreDisTools.GetInstruction(_disasm, rtf, imageOffset, rtfOffset, _reader.Image, out instruction);

            // CoreDisTools dumps instructions in the following format:
            //
            //      address: bytes [padding] \t mnemonic [\t operands] \n
            //
            // However, due to an LLVM issue regarding instruction prefixes (https://bugs.llvm.org/show_bug.cgi?id=7709),
            // multiple lines may be returned for a single x86/x64 instruction.

            var builder = new StringBuilder();
            int lineNum = 0;
            // The start index of the last line in builder
            int lineStartIndex = 0;

            // Remove this foreach wrapper and line* variables after the aforementioned LLVM issue is fixed
            foreach (string line in instruction.Split(new char[] { '\n' }, StringSplitOptions.RemoveEmptyEntries))
            {
                int colonIndex = line.IndexOf(':');
                int tab1Index  = line.IndexOf('\t');

                if ((0 < colonIndex) && (colonIndex < tab1Index))
                {
                    // First handle the address and the byte dump
                    if (_options.Naked)
                    {
                        if (!_options.HideOffsets)
                        {
                            // All lines but the last one must represent single-byte prefixes, so add lineNum to the offset
                            builder.Append($"{rtf.CodeOffset + rtfOffset + lineNum,8:x4}:");
                        }
                    }
                    else
                    {
                        if (_reader.Machine == Machine.Arm64)
                        {
                            // Replace " hh hh hh hh " byte dump with " hhhhhhhh ".
                            // CoreDisTools should be fixed to dump bytes this way for ARM64.
                            uint instructionBytes = BitConverter.ToUInt32(_reader.Image, imageOffset + rtfOffset);
                            builder.Append(line, 0, colonIndex + 1);
                            builder.Append(' ');
                            builder.Append(instructionBytes.ToString("x8"));
                        }
                        else
                        {
                            // Copy the offset and the byte dump
                            int byteDumpEndIndex = tab1Index;
                            do
                            {
                                byteDumpEndIndex--;
                            }while (line[byteDumpEndIndex] == ' ');
                            builder.Append(line, 0, byteDumpEndIndex + 1);
                        }
                        builder.Append(' ');
                    }

                    // Now handle the mnemonic and operands. Ensure proper indentation for the mnemonic.
                    EnsureIndentation(builder, lineStartIndex, MnemonicIndentation);

                    int tab2Index = line.IndexOf('\t', tab1Index + 1);
                    if (tab2Index >= 0)
                    {
                        // Copy everything between the first and the second tabs
                        builder.Append(line, tab1Index + 1, tab2Index - tab1Index - 1);
                        // Ensure proper indentation for the operands
                        EnsureIndentation(builder, lineStartIndex, OperandsIndentation);
                        int afterTab2Index = tab2Index + 1;

                        // Work around an LLVM issue causing an extra space to be output before operands;
                        // see https://reviews.llvm.org/D35946.
                        if ((afterTab2Index < line.Length) &&
                            ((line[afterTab2Index] == ' ') || (line[afterTab2Index] == '\t')))
                        {
                            afterTab2Index++;
                        }

                        // Copy everything after the second tab
                        int savedLength = builder.Length;
                        builder.Append(line, afterTab2Index, line.Length - afterTab2Index);
                        // There should be no extra tabs. Should we encounter them, replace them with a single space.
                        if (line.IndexOf('\t', afterTab2Index) >= 0)
                        {
                            builder.Replace('\t', ' ', savedLength, builder.Length - savedLength);
                        }
                    }
                    else
                    {
                        // Copy everything after the first tab
                        builder.Append(line, tab1Index + 1, line.Length - tab1Index - 1);
                    }
                }
                else
                {
                    // Should not happen. Just replace tabs with spaces.
                    builder.Append(line.Replace('\t', ' '));
                }

                string translatedLine      = builder.ToString(lineStartIndex, builder.Length - lineStartIndex);
                string fixedTranslatedLine = translatedLine;

                switch (_reader.Machine)
                {
                case Machine.Amd64:
                    ProbeX64Quirks(rtf, imageOffset, rtfOffset, instrSize, ref fixedTranslatedLine);
                    break;

                case Machine.I386:
                    ProbeX86Quirks(rtf, imageOffset, rtfOffset, instrSize, ref fixedTranslatedLine);
                    break;

                case Machine.Arm64:
                    ProbeArm64Quirks(rtf, imageOffset, rtfOffset, ref fixedTranslatedLine);
                    break;

                case Machine.ArmThumb2:
                    break;

                default:
                    break;
                }

                // If the translated line has been changed, replace it in the builder
                if (!object.ReferenceEquals(fixedTranslatedLine, translatedLine))
                {
                    builder.Length = lineStartIndex;
                    builder.Append(fixedTranslatedLine);
                }

                builder.Append(Environment.NewLine);
                lineNum++;
                lineStartIndex = builder.Length;
            }

            instruction = builder.ToString();
            return(instrSize);
        }
示例#18
0
 /// <summary>
 /// Store the R2R reader and construct the disassembler for the appropriate architecture.
 /// </summary>
 /// <param name="reader"></param>
 public Disassembler(R2RReader reader, DumpOptions options)
 {
     _reader  = reader;
     _options = options;
     _disasm  = CoreDisTools.GetDisasm(_reader.Machine);
 }
示例#19
0
        private int Run(string[] args)
        {
            ArgumentSyntax syntax = ParseCommandLine(args);

            // open output stream
            if (_outputFilename != null)
            {
                _writer = File.CreateText(_outputFilename);
            }
            else
            {
                _writer = Console.Out;
            }

            if (_help)
            {
                _writer.WriteLine(syntax.GetHelpText());
                return(0);
            }

            try
            {
                if (_inputFilenames.Count == 0)
                {
                    throw new ArgumentException("Input filename must be specified (--in <file>)");
                }

                foreach (string filename in _inputFilenames)
                {
                    R2RReader r2r = new R2RReader(filename);

                    if (_disasm)
                    {
                        _disassembler = CoreDisTools.GetDisasm(r2r.Machine);
                    }

                    if (_xml)
                    {
                        _dumper = new XmlDumper(_ignoreSensitive, r2r, _writer, _raw, _header, _disasm, _disassembler, _unwind, _gc, _sectionContents);
                    }
                    else
                    {
                        _dumper = new TextDumper(r2r, _writer, _raw, _header, _disasm, _disassembler, _unwind, _gc, _sectionContents);
                    }

                    Dump(r2r);

                    if (_disasm)
                    {
                        CoreDisTools.FinishDisasm(_disassembler);
                    }
                }
            }
            catch (Exception e)
            {
                Console.WriteLine("Error: " + e.ToString());
                if (e is ArgumentException)
                {
                    Console.WriteLine();
                    Console.WriteLine(syntax.GetHelpText());
                }
                if (_xml)
                {
                    XmlDocument document = new XmlDocument();
                    XmlNode     node     = document.CreateNode("element", "Error", "");
                    node.InnerText = e.Message;
                    document.AppendChild(node);
                    if (_writer != null)
                    {
                        document.Save(_writer);
                    }
                }
                return(1);
            }
            finally
            {
                // close output stream
                _writer.Close();
            }

            return(0);
        }