public void Decompile(CompilationStreamPair streams, TextWriter codeWriter) { Argument.NotNull(nameof(streams), streams); Argument.NotNull(nameof(codeWriter), codeWriter); using (var resultScope = JitCompileAndGetMethods(streams.AssemblyStream)) using (var dataTarget = DataTarget.AttachToProcess(Current.ProcessId, uint.MaxValue, AttachFlag.Passive)) { var currentMethodAddressRef = new Reference <ulong>(); var runtime = dataTarget.ClrVersions.Single(v => v.Flavor == ClrFlavor).CreateRuntime(); var translator = new IntelTranslator { SymbolResolver = (Instruction instruction, long addr, ref long offset) => ResolveSymbol(runtime, instruction, addr, currentMethodAddressRef.Value) }; WriteJitInfo(runtime.ClrInfo, codeWriter); WriteProfilerState(codeWriter); codeWriter.WriteLine(); var architecture = MapArchitecture(runtime.ClrInfo.DacInfo.TargetArchitecture); foreach (var result in resultScope.Results) { DisassembleAndWrite(result, runtime, architecture, translator, currentMethodAddressRef, codeWriter); codeWriter.WriteLine(); } } }
public void Decompile(CompilationStreamPair streams, TextWriter codeWriter) { Argument.NotNull(nameof(streams), streams); Argument.NotNull(nameof(codeWriter), codeWriter); var currentSetup = AppDomain.CurrentDomain.SetupInformation; using (var dataTarget = DataTarget.AttachToProcess(CurrentProcess.Id, UInt32.MaxValue, AttachFlag.Passive)) using (var context = AppDomainContext.Create(new AppDomainSetup { ApplicationBase = currentSetup.ApplicationBase, PrivateBinPath = currentSetup.PrivateBinPath })) { context.LoadAssembly(LoadMethod.LoadFrom, Assembly.GetExecutingAssembly().GetAssemblyFile().FullName); var results = RemoteFunc.Invoke(context.Domain, streams.AssemblyStream, Remote.GetCompiledMethods); var currentMethodAddressRef = new Reference <ulong>(); var runtime = dataTarget.ClrVersions.Single().CreateRuntime(); var translator = new IntelTranslator { SymbolResolver = (Instruction instruction, long addr, ref long offset) => ResolveSymbol(runtime, instruction, addr, currentMethodAddressRef.Value) }; WriteJitInfo(runtime.ClrInfo, codeWriter); var architecture = MapArchitecture(runtime.ClrInfo.DacInfo.TargetArchitecture); foreach (var result in results) { DisassembleAndWrite(result, runtime, architecture, translator, currentMethodAddressRef, codeWriter); codeWriter.WriteLine(); } } }
public string DumpASM() { TextWriter asmWriter = new StringWriter(); using (DataTarget target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive)) { foreach (ClrInfo clrInfo in target.ClrVersions) { this.engine.UpdateLog("Found CLR Version:" + clrInfo.Version.ToString()); // This is the data needed to request the dac from the symbol server: ModuleInfo dacInfo = clrInfo.DacInfo; this.engine.UpdateLog($"Filesize: {dacInfo.FileSize:X}"); this.engine.UpdateLog($"Timestamp: {dacInfo.TimeStamp:X}"); this.engine.UpdateLog($"Dac File: {dacInfo.FileName}"); ClrRuntime runtime = target.ClrVersions.Single().CreateRuntime(); var appDomain = runtime.AppDomains[0]; var module = appDomain.Modules.LastOrDefault(m => m.AssemblyName != null && m.AssemblyName.StartsWith(assemblyName)); asmWriter.WriteLine( $"; {clrInfo.ModuleInfo.ToString()} ({clrInfo.Flavor} {clrInfo.Version})"); asmWriter.WriteLine( $"; {clrInfo.DacInfo.FileName} ({clrInfo.DacInfo.TargetArchitecture} {clrInfo.DacInfo.Version})"); asmWriter.WriteLine(); foreach (var typeClr in module.EnumerateTypes()) { asmWriter.WriteLine($"; Type {typeClr.Name}"); ClrHeap heap = runtime.Heap; ClrType @object = heap.GetTypeByMethodTable(typeClr.MethodTable); foreach (ClrMethod method in @object.Methods) { MethodCompilationType compileType = method.CompilationType; ArchitectureMode mode = clrInfo.DacInfo.TargetArchitecture == Architecture.X86 ? ArchitectureMode.x86_32 : ArchitectureMode.x86_64; this.currentMethodAddress = 0; var translator = new IntelTranslator { SymbolResolver = (Instruction instruction, long addr, ref long offset) => ResolveSymbol(runtime, instruction, addr, ref currentMethodAddress) }; // This not work even ClrMd says opposite... //ulong startAddress = method.NativeCode; //ulong endAddress = method.ILOffsetMap.Select(entry => entry.EndAddress).Max(); DisassembleAndWrite(method, mode, translator, ref currentMethodAddress, asmWriter); this.engine.UpdateLog($"Method {method.Name} disassembled to ASM."); asmWriter.WriteLine(); } } break; } } return(asmWriter.ToString()); }
private static int Main(string[] args) { Console.WriteLine(); Console.WriteLine("Mosa.Tool.Disassembler.Intel.Disassembler [www.mosa-project.org]"); Console.WriteLine("Copyright 2016. New BSD License."); Console.WriteLine("Written by Phil Garcia ([email protected])"); Console.WriteLine(); try { var options = ParseOptions(args); if (options == null) { return(-1); //Commandline errors will be printed by the commandline lib } // Need a new instance of translator every time as they aren't thread safe var translator = new IntelTranslator() { // Configure the translator to output instruction addresses and instruction binary as hex IncludeAddress = true, IncludeBinary = true }; var code2 = File.ReadAllBytes(options.InputFile); var code = new byte[code2.Length]; for (ulong i = options.FileOffset; i < (ulong)code2.Length; i++) { code[i - options.FileOffset] = code2[i]; } //using (var disasm = new SharpDisasm.Disassembler(code, ArchitectureMode.x86_32, options.StartingAddress, true, Vendor.Any, options.FileOffset)) using (var disasm = new SharpDisasm.Disassembler(code, ArchitectureMode.x86_32, options.StartingAddress, true, Vendor.Any)) { using (var dest = File.CreateText(options.OutputFile)) { foreach (var instruction in disasm.Disassemble()) { var inst = translator.Translate(instruction); dest.WriteLine(inst); if (options.Length != 0 && instruction.PC > options.StartingAddress + options.Length) { break; } } } } return(0); } catch (Exception e) { Console.Error.WriteLine("Exception: {0}", e.ToString()); return(-1); } }
/// <summary> /// Initializes a new instance of the <see cref="Disassembler" /> class. The instructions can then be disassembled with a call to <see cref="Disassemble"/>. The base address used to resolve relative addresses should be provided in <paramref name="address"/>. /// </summary> /// <param name="codePtr">A pointer to memory to be disassembled.</param> /// <param name="codeLength">The maximum length to be disassembled.</param> /// <param name="architecture">The architecture of the code (e.g. 64-bit, 32-bit or 16-bit).</param> /// <param name="address">The address of the first byte of code. This value is used to resolve relative addresses into absolute addresses while disassembling.</param> /// <param name="copyBinaryToInstruction">Keeps a copy of the binary code for the instruction. This will increase the memory usage for each instruction. This is necessary if planning on using the <see cref="Translators.Translator.IncludeBinary"/> option.</param> /// <param name="vendor">What vendors to support for disassembly, default is Any. Other options are AMD or Intel.</param> public Disassembler(IntPtr codePtr, int codeLength, ArchitectureMode architecture, ulong address = 0x0, bool copyBinaryToInstruction = false, Vendor vendor = Vendor.Any) : this(null, architecture, address, copyBinaryToInstruction, vendor) { if (codePtr == IntPtr.Zero) { throw new ArgumentOutOfRangeException("codePtr"); } if (codeLength <= 0) { throw new ArgumentOutOfRangeException("codeLength", "Code length must be larger than 0."); } this.codePtr = codePtr; this.codeLength = codeLength; Translator = new IntelTranslator(); }
/// <summary> /// Initializes a new instance of the <see cref="Disassembler" /> class. Prepares a new disassembler instance for the code provided. The instructions can then be disassembled with a call to <see cref="Disassemble"/>. The base address used to resolve relative addresses should be provided in <paramref name="address"/>. /// </summary> /// <param name="code">The code to be disassembled</param> /// <param name="architecture">The target x86 instruction set architecture of the code (e.g. 64-bit, 32-bit or 16-bit).</param> /// <param name="address">The address of the first byte of code. This value is used to resolve relative addresses into absolute addresses while disassembling.</param> /// <param name="copyBinaryToInstruction">Keeps a copy of the binary code for the instruction. This will increase the memory usage for each instruction. This is necessary if planning on using the <see cref="Translators.Translator.IncludeBinary"/> option.</param> /// <param name="vendor">What vendor instructions to support during disassembly, default is Any. Other options are AMD or Intel.</param> public Disassembler(Byte[] code, ArchitectureMode architecture, ulong address = 0x0, bool copyBinaryToInstruction = true, Vendor vendor = Vendor.Any) { this.code = code; this.Architecture = architecture; this.Address = address; this.CopyBinaryToInstruction = copyBinaryToInstruction; this.Vendor = vendor; if (code != null) { this.pinnedCodeArray = new AutoPinner(this.code); this.codePtr = this.pinnedCodeArray; this.codeLength = this.code.Length; } Translator = new IntelTranslator(); this.InitUdis86(); }
public void Decompile(Stream assemblyStream, TextWriter codeWriter) { var currentSetup = AppDomain.CurrentDomain.SetupInformation; using (var dataTarget = DataTarget.AttachToProcess(CurrentProcess.Id, UInt32.MaxValue, AttachFlag.Passive)) using (var context = AppDomainContext.Create(new AppDomainSetup { ApplicationBase = currentSetup.ApplicationBase, PrivateBinPath = currentSetup.PrivateBinPath })) { context.LoadAssembly(LoadMethod.LoadFrom, Assembly.GetExecutingAssembly().GetAssemblyFile().FullName); var results = RemoteFunc.Invoke(context.Domain, assemblyStream, Remote.GetCompiledMethods); var currentMethodAddressRef = new Reference <ulong>(); var runtime = dataTarget.ClrVersions.Single().CreateRuntime(); var translator = new IntelTranslator { SymbolResolver = (Instruction instruction, long addr, ref long offset) => ResolveSymbol(runtime, instruction, addr, currentMethodAddressRef.Value) }; codeWriter.WriteLine("; This is an experimental implementation."); codeWriter.WriteLine("; Please report any bugs to https://github.com/ashmind/TryRoslyn/issues."); codeWriter.WriteLine(); WriteJitInfo(runtime.ClrInfo, codeWriter); var architecture = MapArchitecture(runtime.ClrInfo.DacInfo.TargetArchitecture); foreach (var result in results) { var methodHandle = (ulong)result.Handle.ToInt64(); var method = runtime.GetMethodByHandle(methodHandle); if (method == null) { codeWriter.WriteLine(" ; Method with handle 0x{0:X} was somehow not found by CLRMD.", methodHandle); codeWriter.WriteLine(" ; See https://github.com/ashmind/TryRoslyn/issues/84."); continue; } DisassembleAndWrite(method, result.Message, architecture, translator, currentMethodAddressRef, codeWriter); codeWriter.WriteLine(); } } }
public string DumpASM() { TextWriter asmWriter = new StringWriter(); using (DataTarget target = DataTarget.AttachToProcess(Process.GetCurrentProcess().Id, 5000, AttachFlag.Passive)) { foreach (ClrInfo clrInfo in target.ClrVersions) { this.engine.UpdateLog("Found CLR Version:" + clrInfo.Version.ToString()); // This is the data needed to request the dac from the symbol server: ModuleInfo dacInfo = clrInfo.DacInfo; this.engine.UpdateLog($"Filesize: {dacInfo.FileSize:X}"); this.engine.UpdateLog($"Timestamp: {dacInfo.TimeStamp:X}"); this.engine.UpdateLog($"Dac File: {dacInfo.FileName}"); ClrRuntime runtime = target.ClrVersions.Single().CreateRuntime(); var appDomain = runtime.AppDomains[0]; var module = appDomain.Modules.LastOrDefault(m => m.AssemblyName != null && m.AssemblyName.StartsWith(assemblyName)); asmWriter.WriteLine( $"; {clrInfo.ModuleInfo.ToString()} ({clrInfo.Flavor} {clrInfo.Version})"); asmWriter.WriteLine( $"; {clrInfo.DacInfo.FileName} ({clrInfo.DacInfo.TargetArchitecture} {clrInfo.DacInfo.Version})"); asmWriter.WriteLine(); foreach (var typeClr in module.EnumerateTypes()) { // Note: Accroding to https://github.com/dotnet/coreclr/blob/master/src/vm/methodtable.h: // "(...) for value types GetBaseSize returns the size of instance fields for // a boxed value, and GetNumInstanceFieldsBytes for an unboxed value." // but mentioned method implementation is trivial: // inline DWORD MethodTable::GetNumInstanceFieldBytes() //{ // LIMITED_METHOD_DAC_CONTRACT; // return (GetBaseSize() - GetClass()->GetBaseSizePadding()); //} asmWriter.WriteLine($"; Type {typeClr.Name}"); asmWriter.WriteLine($"; MethodTable: 0x{typeClr.MethodTable:x16}"); asmWriter.WriteLine($"; Size: {typeClr.BaseSize}{(typeClr.IsValueClass ? string.Format(" (when boxed)") : string.Empty)}"); asmWriter.WriteLine($"; IsValueType: {typeClr.IsValueClass}"); asmWriter.WriteLine($"; IsArray: {typeClr.IsArray}"); asmWriter.WriteLine($"; IsEnum: {typeClr.IsEnum}"); asmWriter.WriteLine($"; IsPrimitive: {typeClr.IsPrivate}"); asmWriter.WriteLine("; Fields:"); asmWriter.WriteLine("; {0,6} {1,16} {2,20} {3,4}", "Offset", "Name", "Type", "Size"); var orderedFields = typeClr.Fields.ToList().OrderBy(x => x.Offset); foreach (var field in orderedFields) { asmWriter.WriteLine($"; {field.Offset,6} {field.Name,16} {field.Type.Name,20} {field.Size,4}"); } ClrHeap heap = runtime.Heap; foreach (ClrMethod method in typeClr.Methods) { MethodCompilationType compileType = method.CompilationType; ArchitectureMode mode = clrInfo.DacInfo.TargetArchitecture == Architecture.X86 ? ArchitectureMode.x86_32 : ArchitectureMode.x86_64; this.currentMethodAddress = 0; var translator = new IntelTranslator { SymbolResolver = (Instruction instruction, long addr, ref long offset) => ResolveSymbol(runtime, instruction, addr, ref currentMethodAddress) }; // This not work even ClrMd says opposite... //ulong startAddress = method.NativeCode; //ulong endAddress = method.ILOffsetMap.Select(entry => entry.EndAddress).Max(); DisassembleAndWrite(method, mode, translator, ref currentMethodAddress, asmWriter); this.engine.UpdateLog($"Method {method.Name} disassembled to ASM."); asmWriter.WriteLine(); } } break; } } return(asmWriter.ToString()); }
private void GenerateASMFile() { var translator = new IntelTranslator() { IncludeAddress = true, IncludeBinary = true }; var map = new Dictionary <ulong, List <string> >(); foreach (var symbol in Linker.Symbols) { if (!map.TryGetValue(symbol.VirtualAddress, out List <string> list)) { list = new List <string>(); map.Add(symbol.VirtualAddress, list); } list.Add(symbol.Name); } var textSection = Linker.Sections[(int)SectionKind.Text]; var startingAddress = textSection.VirtualAddress + MultibootHeaderLength; var fileOffset = Linker.BaseFileOffset + MultibootHeaderLength; var length = textSection.Size; var code2 = File.ReadAllBytes(LauncherSettings.OutputFile); var code = new byte[code2.Length]; for (ulong i = fileOffset; i < (ulong)code2.Length; i++) { code[i - fileOffset] = code2[i]; } var mode = ArchitectureMode.x86_32; switch (LauncherSettings.Platform) { case "x86": mode = ArchitectureMode.x86_32; break; case "x64": mode = ArchitectureMode.x86_64; break; } using (var disasm = new Disassembler(code, mode, startingAddress, true, Vendor.Any)) { using (var dest = File.CreateText(LauncherSettings.AsmFile)) { if (map.TryGetValue(startingAddress, out List <string> list)) { foreach (var entry in list) { dest.WriteLine($"; {entry}"); } } foreach (var instruction in disasm.Disassemble()) { var inst = translator.Translate(instruction); dest.WriteLine(inst); if (map.TryGetValue(instruction.PC, out List <string> list2)) { foreach (var entry in list2) { dest.WriteLine($"; {entry}"); } } if (instruction.PC > startingAddress + length) { break; } } } } }
private void GenerateASMFile() { var translator = new IntelTranslator() { IncludeAddress = true, IncludeBinary = true }; var asmfile = Path.Combine(LauncherOptions.DestinationDirectory, Path.GetFileNameWithoutExtension(LauncherOptions.SourceFile) + ".asm"); var textSection = Linker.Sections[(int)SectionKind.Text]; var map = new Dictionary <ulong, List <string> >(); foreach (var symbol in Linker.Symbols) { if (!map.TryGetValue(symbol.VirtualAddress, out List <string> list)) { list = new List <string>(); map.Add(symbol.VirtualAddress, list); } list.Add(symbol.Name); } const uint multibootHeaderLength = MultibootHeaderLength; ulong startingAddress = textSection.VirtualAddress + multibootHeaderLength; uint fileOffset = textSection.FileOffset + multibootHeaderLength; uint length = textSection.Size; var code2 = File.ReadAllBytes(CompiledFile); var code = new byte[code2.Length]; for (ulong i = fileOffset; i < (ulong)code2.Length; i++) { code[i - fileOffset] = code2[i]; } using (var disasm = new Disassembler(code, ArchitectureMode.x86_32, startingAddress, true, Vendor.Any)) { using (var dest = File.CreateText(asmfile)) { if (map.TryGetValue(startingAddress, out List <string> list)) { foreach (var entry in list) { dest.WriteLine($"; {entry}"); } } foreach (var instruction in disasm.Disassemble()) { var inst = translator.Translate(instruction); dest.WriteLine(inst); if (map.TryGetValue(instruction.PC, out List <string> list2)) { foreach (var entry in list2) { dest.WriteLine($"; {entry}"); } } if (instruction.PC > startingAddress + length) { break; } } } } }
private void GenerateASMFile() { // Need a new instance of translator every time as they aren't thread safe var translator = new IntelTranslator(); // Configure the translator to output instruction addresses and instruction binary as hex translator.IncludeAddress = true; translator.IncludeBinary = true; var asmfile = Path.Combine(Options.DestinationDirectory, Path.GetFileNameWithoutExtension(Options.SourceFile) + ".asm"); var textSection = Linker.LinkerSections[(int)SectionKind.Text]; var map = new Dictionary <ulong, string>(); foreach (var symbol in Linker.Symbols) { if (map.ContainsKey(symbol.VirtualAddress)) { continue; } map.Add(symbol.VirtualAddress, symbol.Name); } uint multibootHeaderLength = MultibootHeaderLength; ulong startingAddress = textSection.VirtualAddress + multibootHeaderLength; uint fileOffset = textSection.FileOffset + multibootHeaderLength; uint length = textSection.Size; var code2 = File.ReadAllBytes(CompiledFile); var code = new byte[code2.Length]; for (ulong i = fileOffset; i < (ulong)code2.Length; i++) { code[i - fileOffset] = code2[i]; } using (var disasm = new SharpDisasm.Disassembler(code, ArchitectureMode.x86_32, startingAddress, true, Vendor.Any)) { using (var dest = File.CreateText(asmfile)) { if (map.ContainsKey(startingAddress)) { dest.WriteLine("; " + map[startingAddress]); } foreach (var instruction in disasm.Disassemble()) { var inst = translator.Translate(instruction); dest.WriteLine(inst); if (map.ContainsKey(instruction.PC)) { dest.WriteLine("; " + map[instruction.PC]); } if (instruction.PC > startingAddress + length) { break; } } } } }