public Disassembler(int bitness, string commentPrefix, SourceCodeProvider sourceCodeProvider, KnownSymbols knownSymbols, DisassemblerOptions disassemblerOptions) { this.bitness = bitness; this.commentPrefix = commentPrefix; this.sourceCodeProvider = sourceCodeProvider; if (bitness == 64) { diffableSymAddrLo = DIFFABLE_SYM_ADDR64_LO; diffableSymAddrHi = DIFFABLE_SYM_ADDR64_HI; } else { diffableSymAddrLo = DIFFABLE_SYM_ADDR32_LO; diffableSymAddrHi = DIFFABLE_SYM_ADDR32_HI; } targets = new Dictionary <ulong, AddressInfo>(); sortedTargets = new List <KeyValuePair <ulong, AddressInfo> >(); formatterOutput = new FormatterOutputImpl(); charBuf = new char[100]; this.knownSymbols = knownSymbols; this.disassemblerOptions = disassemblerOptions; if ((disassemblerOptions & DisassemblerOptions.Diffable) != 0) { this.disassemblerOptions = (disassemblerOptions & ~(DisassemblerOptions.ShowAddresses | DisassemblerOptions.ShowHexBytes)); } }
/// <summary> /// Task for disassembling one individual file. /// </summary> /// <param name="logger">The logging implementation to log errors/info to.</param> /// <param name="options">The options to use while disassembling.</param> /// <returns>True if the disassembler could successfully disassemble the file; otherwise returns false.</returns> public bool DisassembleFile(ILogger logger, DisassemblerOptions options) { bool success = true; logger.Log(LogLevel.Info, "Invoking disassembler for file " + options.InputFileName); try { ICompiledFileReader fileParser = m_FileParserFac.GetFileParser(options.InputFileName); DisassembledFileBase fileBase = fileParser.ParseFile(options.InputFileName, logger); IAssemblyFileWriter fileWriter = fileBase.AssemblyTextFileWriter; fileWriter.GenerateOutputFile(options.OutputFileName); } catch (IOException ex) { logger.Log(LogLevel.Critical, ex.Message); success = false; } catch (Exception ex) { logger.Log(LogLevel.Critical, "In file " + options.InputFileName + ":"); logger.Log(LogLevel.Critical, ex.Message); success = false; } return(success); }
public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, DisassemblerOptions options) { if (output == null) throw new ArgumentNullException("output"); this.output = output; this.detectControlStructure = detectControlStructure; this.options = options; }
/// <summary> /// Creates a new managed disassembler /// </summary> /// <param name="compilationData">The compilation data</param> /// <param name="createDisassembler">Function to create the disassembler</param> /// <param name="options">The options</param> public Disassembler( AbstractCompilationData compilationData, Func<AbstractCompilationData, INativeDisassembler> createDisassembler, DisassemblerOptions options = DisassemblerOptions.None) { this.compilationData = compilationData; this.nativeDisassembler = createDisassembler(compilationData); this.options = options; }
/// <summary> /// Creates a new managed disassembler /// </summary> /// <param name="compilationData">The compilation data</param> /// <param name="createDisassembler">Function to create the disassembler</param> /// <param name="options">The options</param> public Disassembler( AbstractCompilationData compilationData, Func <AbstractCompilationData, INativeDisassembler> createDisassembler, DisassemblerOptions options = DisassemblerOptions.None) { this.compilationData = compilationData; this.nativeDisassembler = createDisassembler(compilationData); this.options = options; }
private static ValueTask <EInputBlockResult> DisassembleRomAsync(IRomData romData) { Console.WriteLine("Disassembling ROM."); Console.WriteLine(); Console.WriteLine("HEADER"); var romBuild = romData.GetRomBuild(); Console.WriteLine($"{romData.Header.Title}"); Console.WriteLine($"Build: {romBuild.Version} ({romBuild.BuildNumber})"); Console.WriteLine($"Size: {romData.Size.Size.Mebibits}Mib (0x{romData.Length:X})"); Console.WriteLine($"Destination Code: {romData.Header.DestinationCode}"); Console.WriteLine($"Game Code: {romData.Header.GameCode}"); Console.WriteLine($"Format: {romData.Header.Format}"); Console.WriteLine($"Mask Rom Version: {romData.Header.Version}"); Console.WriteLine($"Entry Address: 0x{romData.Header.EntryAddress:X}"); Console.WriteLine($"Return Address: 0x{romData.Header.ReturnAddress:X}"); Console.WriteLine(); using var decompressedRomData = romData.Decompress(); var disassembler = new Disassembler(); var options = new DisassemblerOptions { OutputDir = new DirectoryInfo(@"C:\Users\shira\Desktop\OoTDecomp"), SplitFiles = false, KnownFiles = { new FileEntry("INTERNAL_HEADER", 0xA4000000, romData.GetHeaderData()), new FileEntry("IPL3", 0xA4000040, romData.GetIPL3Data()), // We don't know what this is, but we can figure this out // when we start disassembling correctly and getting a bunch of opcode errors. // For reference, we know that Mario ends at 0x0B6A40. We'll go a bit higher then // work our way down. new FileEntry("CODE", romData.Header.EntryAddress, decompressedRomData.GetCodeData(0x0C3500)) }, Regions = { new DataRegion("INTERNAL_HEADER", 0xA4000000, 0xA400003F) }, KnownFunctions = { { 0x80000400, "Main" } } }; //disassembler.AddRegion(new DataRegion("INTERNAL_HEADER", 0xA4000000, 0xA400003F)); Console.WriteLine(); if (!PerformChecklistOperation("Disassembling ROM to MIPS.", () => disassembler.Disassemble(options), r => r.Exception)) { return(new ValueTask <EInputBlockResult>(EInputBlockResult.Failed)); } return(new ValueTask <EInputBlockResult>(EInputBlockResult.Success)); }
public MethodBodyDisassembler(ITextOutput output, bool detectControlStructure, DisassemblerOptions options) { if (output == null) { throw new ArgumentNullException("output"); } this.output = output; this.detectControlStructure = detectControlStructure; this.options = options; }
ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationOptions options, ModuleDef ownerModule) { var disOpts = new DisassemblerOptions(options.CancellationToken, ownerModule); if (options.DecompilerSettings.ShowILComments) disOpts.GetOpCodeDocumentation = GetOpCodeDocumentation; if (options.DecompilerSettings.ShowXmlDocumentation) disOpts.GetXmlDocComments = GetXmlDocComments; disOpts.CreateInstructionBytesReader = InstructionBytesReader.Create; disOpts.ShowTokenAndRvaComments = options.DecompilerSettings.ShowTokenAndRvaComments; disOpts.ShowILBytes = options.DecompilerSettings.ShowILBytes; disOpts.SortMembers = options.DecompilerSettings.SortMembers; return new ReflectionDisassembler(output, detectControlStructure, disOpts); }
ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationOptions options, ModuleDef ownerModule) { var disOpts = new DisassemblerOptions(options.CancellationToken, ownerModule); if (options.DecompilerSettings.AddILComments) { disOpts.GetOpCodeDocumentation = GetOpCodeDocumentation; } if (options.DecompilerSettings.ShowXmlDocumentation) { disOpts.GetXmlDocComments = GetXmlDocComments; } return(new ReflectionDisassembler(output, detectControlStructure, disOpts)); }
ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationContext ctx, ModuleDef ownerModule) { var disOpts = new DisassemblerOptions(ctx.CancellationToken, ownerModule); if (langSettings.Settings.ShowILComments) { disOpts.GetOpCodeDocumentation = ILLanguageHelper.GetOpCodeDocumentation; } if (langSettings.Settings.ShowXmlDocumentation) { disOpts.GetXmlDocComments = GetXmlDocComments; } disOpts.CreateInstructionBytesReader = m => InstructionBytesReader.Create(m, ctx.IsBodyModified != null && ctx.IsBodyModified(m)); disOpts.ShowTokenAndRvaComments = langSettings.Settings.ShowTokenAndRvaComments; disOpts.ShowILBytes = langSettings.Settings.ShowILBytes; disOpts.SortMembers = langSettings.Settings.SortMembers; return(new ReflectionDisassembler(output, detectControlStructure, disOpts)); }
/// <summary> /// Disassembles a .JEF file into instructions and data. /// </summary> /// <param name="options">The options used to disassemble the file</param> /// <param name="logger">A logging implementation to log errors to.</param> public void Disassemble(DisassemblerOptions options, ILogger logger) { var stopwatch = new Stopwatch(); var tasks = new List <Task <bool> >(); stopwatch.Start(); DisassembleFile(logger, options); stopwatch.Stop(); if (tasks.Any(t => !t.Result)) { logger.Log(LogLevel.Info, "Disassembly completed (with errors) in " + stopwatch.Elapsed.ToString()); } else { logger.Log(LogLevel.Info, "Disassembly completed in " + stopwatch.Elapsed.ToString()); } }
/// <summary> /// Runs the disassembler with the provided set of arguments. /// </summary> /// <param name="options">The options provided by the user.</param> private static int RunDisassembler(DisassemblerOptions options) { ILogger logger = null; string logFileName = options.LogFile; if (!string.IsNullOrEmpty(logFileName) && !string.IsNullOrWhiteSpace(logFileName)) { logger = new HybridLogger(logFileName.Trim()); } else { logger = new ConsoleLogger(); } var disassembler = new Disassembler(); disassembler.Disassemble(options, logger); return(0); }
ReflectionDisassembler CreateReflectionDisassembler(IDecompilerOutput output, DecompilationContext ctx, ModuleDef ownerModule) { var disOpts = new DisassemblerOptions(langSettings.Settings.SettingsVersion, ctx.CancellationToken, ownerModule); if (langSettings.Settings.ShowILComments) { disOpts.GetOpCodeDocumentation = ILLanguageHelper.GetOpCodeDocumentation; } var sb = new StringBuilder(); if (langSettings.Settings.ShowXmlDocumentation) { disOpts.GetXmlDocComments = a => GetXmlDocComments(a, sb); } disOpts.CreateInstructionBytesReader = m => InstructionBytesReader.Create(m, !(ctx.IsBodyModified is null) && ctx.IsBodyModified(m)); disOpts.ShowTokenAndRvaComments = langSettings.Settings.ShowTokenAndRvaComments; disOpts.ShowILBytes = langSettings.Settings.ShowILBytes; disOpts.SortMembers = langSettings.Settings.SortMembers; disOpts.ShowPdbInfo = langSettings.Settings.ShowPdbInfo; disOpts.MaxStringLength = langSettings.Settings.MaxStringLength; return(new ReflectionDisassembler(output, detectControlStructure, disOpts)); }
private void BlocksListView_OnSelectionChanged(object sender, SelectionChangedEventArgs e) { ILView.Document.Blocks.Clear(); var options = new DisassemblerOptions(new System.Threading.CancellationToken(), null); uint rva = (uint)method.RVA; uint baseRva = rva == 0 ? 0 : rva + method.Body.HeaderSize; long baseOffs = baseRva == 0 ? 0 : method.Module.ToFileOffset(baseRva) ?? 0; int startLocation; foreach (var instr in cflowDeobfuscator.UnsolvedBlocks[BlocksListView.SelectedIndex].Block.Instructions) { instr.Instruction.WriteTo(ilOutput, options, baseRva, baseOffs, null, method, out startLocation); ilOutput.Write("\r", BoxedTextColor.Text); } ExprView.Document.Blocks.Clear(); var expr = cflowDeobfuscator.UnsolvedBlocks[BlocksListView.SelectedIndex].Expression; exprOutput.Write(TextColor.String, expr.ToString()); Consts.Items.Clear(); GetConsts(expr); Consts.IsEnabled = true; if (Consts.Items.Count > 0) { Consts.SelectedIndex = 0; } else { Consts.IsEnabled = false; } }
public static void WriteTo(this Instruction instruction, ITextOutput writer, DisassemblerOptions options, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method) { if (options != null && (options.ShowTokenAndRvaComments || options.ShowILBytes)) { writer.Write("/* ", TextTokenType.Comment); bool needSpace = false; if (options.ShowTokenAndRvaComments) { ulong fileOffset = (ulong)baseOffs + instruction.Offset; writer.WriteReference(string.Format("0x{0:X8}", fileOffset), new AddressReference(options.OwnerModule == null ? null : options.OwnerModule.Location, false, fileOffset, (ulong)instruction.GetSize()), TextTokenType.Comment, false); needSpace = true; } if (options.ShowILBytes) { if (needSpace) writer.Write(' ', TextTokenType.Comment); if (byteReader == null) writer.Write("??", TextTokenType.Comment); else { int size = instruction.GetSize(); for (int i = 0; i < size; i++) { var b = byteReader.ReadByte(); if (b < 0) writer.Write("??", TextTokenType.Comment); else writer.Write(string.Format("{0:X2}", b), TextTokenType.Comment); } // Most instructions should be at most 5 bytes in length, but use 6 since // ldftn/ldvirtftn are 6 bytes long. The longest instructions are those with // 8 byte operands, ldc.i8 and ldc.r8: 9 bytes. const int MIN_BYTES = 6; for (int i = size; i < MIN_BYTES; i++) writer.Write(" ", TextTokenType.Comment); } } writer.Write(" */", TextTokenType.Comment); writer.WriteSpace(); } writer.WriteDefinition(DnlibExtensions.OffsetToString(instruction.GetOffset()), new InstructionReference(method, instruction), TextTokenType.Label, false); writer.Write(':', TextTokenType.Operator); writer.WriteSpace(); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, TextTokenType.OpCode); if (instruction.Operand != null) { int count = OPERAND_ALIGNMENT - instruction.OpCode.Name.Length; if (count <= 0) count = 1; writer.Write(spaces[count], TextTokenType.Text); if (instruction.OpCode == OpCodes.Ldtoken) { var member = instruction.Operand as IMemberRef; if (member != null && member.IsMethod) { writer.Write("method", TextTokenType.Keyword); writer.WriteSpace(); } else if (member != null && member.IsField) { writer.Write("field", TextTokenType.Keyword); writer.WriteSpace(); } } WriteOperand(writer, instruction.Operand, method); } if (options != null && options.GetOpCodeDocumentation != null) { var doc = options.GetOpCodeDocumentation(instruction.OpCode); if (doc != null) { writer.Write("\t", TextTokenType.Text); writer.Write("// " + doc, TextTokenType.Comment); } } }
ReflectionDisassembler CreateReflectionDisassembler(ITextOutput output, DecompilationContext ctx, ModuleDef ownerModule) { var disOpts = new DisassemblerOptions(ctx.CancellationToken, ownerModule); if (langSettings.Settings.ShowILComments) disOpts.GetOpCodeDocumentation = ILLanguageHelper.GetOpCodeDocumentation; if (langSettings.Settings.ShowXmlDocumentation) disOpts.GetXmlDocComments = GetXmlDocComments; disOpts.CreateInstructionBytesReader = m => InstructionBytesReader.Create(m, ctx.IsBodyModified != null && ctx.IsBodyModified(m)); disOpts.ShowTokenAndRvaComments = langSettings.Settings.ShowTokenAndRvaComments; disOpts.ShowILBytes = langSettings.Settings.ShowILBytes; disOpts.SortMembers = langSettings.Settings.SortMembers; return new ReflectionDisassembler(output, detectControlStructure, disOpts); }
public static void WriteTo(this Instruction instruction, ITextOutput writer, DisassemblerOptions options, uint baseRva, long baseOffs, IInstructionBytesReader byteReader, MethodDef method) { if (options != null && (options.ShowTokenAndRvaComments || options.ShowILBytes)) { writer.Write("/* ", TextTokenType.Comment); bool needSpace = false; if (options.ShowTokenAndRvaComments) { ulong fileOffset = (ulong)baseOffs + instruction.Offset; writer.WriteReference(string.Format("0x{0:X8}", fileOffset), new AddressReference(options.OwnerModule == null ? null : options.OwnerModule.Location, false, fileOffset, (ulong)instruction.GetSize()), TextTokenType.Comment, false); needSpace = true; } if (options.ShowILBytes) { if (needSpace) { writer.Write(' ', TextTokenType.Comment); } if (byteReader == null) { writer.Write("??", TextTokenType.Comment); } else { int size = instruction.GetSize(); for (int i = 0; i < size; i++) { var b = byteReader.ReadByte(); if (b < 0) { writer.Write("??", TextTokenType.Comment); } else { writer.Write(string.Format("{0:X2}", b), TextTokenType.Comment); } } // Most instructions should be at most 5 bytes in length, but use 6 since // ldftn/ldvirtftn are 6 bytes long. The longest instructions are those with // 8 byte operands, ldc.i8 and ldc.r8: 9 bytes. const int MIN_BYTES = 6; for (int i = size; i < MIN_BYTES; i++) { writer.Write(" ", TextTokenType.Comment); } } } writer.Write(" */", TextTokenType.Comment); writer.WriteSpace(); } writer.WriteDefinition(DnlibExtensions.OffsetToString(instruction.GetOffset()), new InstructionReference(method, instruction), TextTokenType.Label, false); writer.Write(':', TextTokenType.Operator); writer.WriteSpace(); writer.WriteReference(instruction.OpCode.Name, instruction.OpCode, TextTokenType.OpCode); if (instruction.Operand != null) { int count = OPERAND_ALIGNMENT - instruction.OpCode.Name.Length; if (count <= 0) { count = 1; } writer.Write(spaces[count], TextTokenType.Text); if (instruction.OpCode == OpCodes.Ldtoken) { var member = instruction.Operand as IMemberRef; if (member != null && member.IsMethod) { writer.Write("method", TextTokenType.Keyword); writer.WriteSpace(); } else if (member != null && member.IsField) { writer.Write("field", TextTokenType.Keyword); writer.WriteSpace(); } } WriteOperand(writer, instruction.Operand, method); } if (options != null && options.GetOpCodeDocumentation != null) { var doc = options.GetOpCodeDocumentation(instruction.OpCode); if (doc != null) { writer.Write("\t", TextTokenType.Text); writer.Write("// " + doc, TextTokenType.Comment); } } }
/// <summary>Set the options for the disassembly</summary> /// <param name="options">Options</param> /// <returns><see langword="true"/> if the options are all supported</returns> public bool SetOptions(DisassemblerOptions options) { return(LLVMSetDisasmOptions(DisasmHandle, ( ulong )options)); }