private static void Disasm(Stream stream, uint size, TextWriter writer, Formatter formatter = null) { var buffer = ArrayPool <byte> .Shared.Rent((int)size); var startPosition = stream.Position; stream.Read(buffer, 0, (int)size); stream.Position = startPosition; // You can also pass in a hex string, eg. "90 91 929394", or you can use your own CodeReader // reading data from a file or memory etc var codeReader = new StreamCodeReader(stream, size); var decoder = Decoder.Create(IntPtr.Size * 8, codeReader); decoder.IP = (ulong)0; ulong endRip = decoder.IP + (uint)size; // This list is faster than List<Instruction> since it uses refs to the Instructions // instead of copying them (each Instruction is 32 bytes in size). It has a ref indexer, // and a ref iterator. Add() uses 'in' (ref readonly). var instructions = new InstructionList(); while (decoder.IP < endRip) { // The method allocates an uninitialized element at the end of the list and // returns a reference to it which is initialized by Decode(). decoder.Decode(out instructions.AllocUninitializedElement()); } // Formatters: Masm*, Nasm* and Gas* (AT&T) if (formatter == null) { formatter = new NasmFormatter(); formatter.Options.DigitSeparator = ""; formatter.Options.FirstOperandCharIndex = 10; } var output = new StringBuilderFormatterOutput(); // Use InstructionList's ref iterator (C# 7.3) to prevent copying 32 bytes every iteration foreach (ref var instr in instructions) { // Don't use instr.ToString(), it allocates more, uses masm syntax and default options formatter.Format(instr, output); writer.Write($"{instr.IP:X16} "); for (int i = 0; i < instr.ByteLength; i++) { writer.Write(buffer[(int)instr.IP + i].ToString("X2")); } writer.Write(new string(' ', 16 * 2 - instr.ByteLength * 2)); writer.WriteLine($"{output.ToStringAndReset()}"); } }
public unsafe XrefScanner(IntPtr codeStart, int lengthLimit = 1000) { if (codeStart == IntPtr.Zero) { throw new NullReferenceException(nameof(codeStart)); } myUnmanagedMemoryStream = new UnmanagedMemoryStream((byte *)codeStart, lengthLimit, lengthLimit, FileAccess.Read); var codeReader = new StreamCodeReader(myUnmanagedMemoryStream); myDecoder = Decoder.Create(IntPtr.Size * 8, codeReader); myDecoder.IP = (ulong)codeStart; }
private static int CalcAsmLength(Assembler asm) { var stream = new MemoryStream(); asm.Assemble(new StreamCodeWriter(stream), 0); // Disassemble the result stream.Position = 0; var reader = new StreamCodeReader(stream); var decoder = Decoder.Create(64, reader); return(decoder.Select(i => i.Length).Sum()); }
internal static unsafe Decoder DecoderForAddress(IntPtr codeStart, int lengthLimit = 1000) { if (codeStart == IntPtr.Zero) { throw new NullReferenceException(nameof(codeStart)); } var stream = new UnmanagedMemoryStream((byte *)codeStart, lengthLimit, lengthLimit, FileAccess.Read); var codeReader = new StreamCodeReader(stream); var decoder = Decoder.Create(IntPtr.Size * 8, codeReader); decoder.IP = (ulong)codeStart; return(decoder); }
private byte[] Assemble(Assembler assembler) { using var stream = new MemoryStream(); assembler.Assemble(new StreamCodeWriter(stream), 0); stream.Position = 0; var reader = new StreamCodeReader(stream); int next; var bytes = new byte[stream.Length]; while ((next = reader.ReadByte()) >= 0) { bytes[stream.Position - 1] = (byte)next; } return(bytes); }