private static void PrintOperandValue(StringBuilder sb, object value, DisassemblyOptions options) { if (value is System.Type t) { sb.Append(t.Name); } else if (value is string s) { sb.Append($"\"{s}\""); } else if (value is ObjectReference or) { if (options.HasFlag(DisassemblyOptions.ShowNames) && or.Reference != null && !string.IsNullOrWhiteSpace(or.Reference.Name)) { sb.Append(or.Reference.Name); } else { sb.Append(or); } } else if (value is IBitEnumOperandValue beov) { PrintBitEnumValue(sb, beov, options); } else if (value is IValueEnumOperandValue veov) { PrintValueEnumValue(sb, veov, options); } else { sb.Append(value); } }
private static int TryDisassemble(DisassemblyOptions opts, Func <RomVersion, string, Func <DisassemblyTask, bool> > getFilter) { string path; if (!RomVersion.TryGet(opts.GameId, opts.VersionId, out RomVersion version)) { Console.WriteLine($"Unrecognized version {opts.GameId} {opts.VersionId}"); return(-1); } if (opts.RomPath != null) { path = opts.RomPath; } else if (!PathUtil.TryGetRomLocation(version, out path)) { Console.WriteLine($"Cannot find path for {opts.GameId} {opts.VersionId}"); return(-1); } Disassemble.MipsToC = opts.MipsToCOutput; Disassemble.GccOutput = Disassemble.MipsToC || !opts.ReadableOutput; Disassemble.PrintRelocations = true; Disassemble.SetGprNames(); Func <DisassemblyTask, bool> filter = getFilter(version, path); if (filter == null) { return(-1); } DisassembleRom(version, path, filter); return(0); }
private static int Run(Options options) { string listing = null; long elapsed = 0; Disassembler ds = new Disassembler(); DisassemblyOptions settings = DisassemblyOptions.None; if (options.ShowNames) { settings |= DisassemblyOptions.ShowNames; } if (options.ShowTypes) { settings |= DisassemblyOptions.ShowTypes; } if (options.DebugMode) { byte[] bytes = File.ReadAllBytes(options.InputFile); using (MemoryStream stream = new MemoryStream(bytes)) { // idle run just to compile code Module.ReadFrom(stream); Stopwatch stopwatch = new Stopwatch(); for (int i = 0; i < 5; i++) { stream.Position = 0; stopwatch.Start(); Module module = Module.ReadFrom(stream); listing = ds.Disassemble(module, settings); stopwatch.Stop(); elapsed = stopwatch.ElapsedMilliseconds; Console.WriteLine($"{i + 1}) Time elapsed {elapsed}ms"); stopwatch.Reset(); } Console.WriteLine(); } } else { using (FileStream stream = File.OpenRead(options.InputFile)) { Module module = Module.ReadFrom(stream); listing = ds.Disassemble(module, settings); } } Console.WriteLine(listing); return(0); }
private static void PrintOperandValue(StringBuilder sb, object value, DisassemblyOptions options) { switch (value) { case System.Type t: sb.Append(t.Name); break; case string s: { sb.Append('"'); sb.Append(s); sb.Append('"'); } break; case ObjectReference or: { if (options.HasFlag(DisassemblyOptions.ShowNames) && or.Reference != null && !string.IsNullOrWhiteSpace(or.Reference.Name)) { sb.Append(or.Reference.Name); } else { or.ToString(sb); } } break; case IBitEnumOperandValue beov: PrintBitEnumValue(sb, beov, options); break; case IValueEnumOperandValue veov: PrintValueEnumValue(sb, veov, options); break; case VaryingOperandValue varOpVal: varOpVal.ToString(sb); break; default: sb.Append(value); break; } }
public string Disassemble(Module module, DisassemblyOptions options) { m_sb.AppendFormat("; SPIR-V\n"); m_sb.AppendFormat("; Version: {0}\n", module.Header.Version); if (module.Header.GeneratorName == null) { m_sb.AppendFormat("; Generator: {0}; {1}\n", module.Header.GeneratorName, module.Header.GeneratorVersion); } else { m_sb.AppendFormat("; Generator: {0} {1}; {2}\n", module.Header.GeneratorVendor, module.Header.GeneratorName, module.Header.GeneratorVersion); } m_sb.AppendFormat("; Bound: {0}\n", module.Header.Bound); m_sb.AppendFormat("; Schema: {0}\n", module.Header.Reserved); List <string> lines = new List <string> (); foreach (var i in module.Instructions) { PrintInstruction(m_sb, i, options); lines.Add(m_sb.ToString()); m_sb.Clear(); } int longestPrefix = 0; foreach (var line in lines) { longestPrefix = Math.Max(longestPrefix, line.IndexOf('=')); } foreach (var line in lines) { if (line.StartsWith(";")) { m_sb.AppendLine(line); } else { if (line.Contains("=")) { var parts = line.Split('='); System.Diagnostics.Debug.Assert(parts.Length == 2); m_sb.Append(parts[0].PadLeft(longestPrefix)); m_sb.Append(" = "); m_sb.Append(parts[1]); } else { m_sb.Append("".PadLeft(longestPrefix + 4)); m_sb.Append(line); } m_sb.AppendLine(); } } string result = m_sb.ToString(); m_sb.Clear(); return(result); }
private static void PrintValueEnumValue(StringBuilder sb, IValueEnumOperandValue valueOperandValue, DisassemblyOptions options) { sb.Append(valueOperandValue.Key); if (valueOperandValue.Value is IList <object> valueList && valueList.Count > 0) { sb.Append(" "); foreach (var v in valueList) { PrintOperandValue(sb, v, options); } } }
private static void PrintBitEnumValue(StringBuilder sb, IBitEnumOperandValue enumOperandValue, DisassemblyOptions options) { foreach (var key in enumOperandValue.Values.Keys) { sb.Append(enumOperandValue.EnumerationType.GetEnumName(key)); var value = enumOperandValue.Values[key] as IList <object>; if (value.Count != 0) { sb.Append(" "); foreach (var v in value) { PrintOperandValue(sb, v, options); } } } }
private static void PrintInstruction(StringBuilder sb, ParsedInstruction instruction, DisassemblyOptions options) { if (instruction.Operands.Count == 0) { sb.Append(instruction.Instruction.Name); return; } int currentOperand = 0; if (instruction.Instruction.Operands[currentOperand].Type is IdResultType) { if (options.HasFlag(DisassemblyOptions.ShowTypes)) { sb.Append(instruction.ResultType.ToString()); sb.Append(" "); } ++currentOperand; } if (currentOperand < instruction.Operands.Count && instruction.Instruction.Operands[currentOperand].Type is IdResult) { if (!options.HasFlag(DisassemblyOptions.ShowNames) || string.IsNullOrWhiteSpace(instruction.Name)) { PrintOperandValue(sb, instruction.Operands[currentOperand].Value, options); } else { sb.Append(instruction.Name); } sb.Append(" = "); ++currentOperand; } sb.Append(instruction.Instruction.Name); sb.Append(" "); for (; currentOperand < instruction.Operands.Count; ++currentOperand) { PrintOperandValue(sb, instruction.Operands[currentOperand].Value, options); sb.Append(" "); } }
public string Disassemble(Module module, DisassemblyOptions options) { m_sb.AppendLine("; SPIR-V"); m_sb.Append("; Version: ").Append(module.Header.Version).AppendLine(); if (module.Header.GeneratorName == null) { m_sb.Append("; Generator: unknown; ").Append(module.Header.GeneratorVersion).AppendLine(); } else { m_sb.Append("; Generator: ").Append(module.Header.GeneratorVendor).Append(' '). Append(module.Header.GeneratorName).Append("; ").Append(module.Header.GeneratorVersion).AppendLine(); } m_sb.Append("; Bound: ").Append(module.Header.Bound).AppendLine(); m_sb.Append("; Schema: ").Append(module.Header.Reserved).AppendLine(); var lines = new string[module.Instructions.Count + 1]; lines[0] = m_sb.ToString(); m_sb.Clear(); for (var i = 0; i < module.Instructions.Count; i++) { var instruction = module.Instructions[i]; PrintInstruction(m_sb, instruction, options); lines[i + 1] = m_sb.ToString(); m_sb.Clear(); } var longestPrefix = 0; for (var i = 0; i < lines.Length; i++) { var line = lines[i]; longestPrefix = Math.Max(longestPrefix, line.IndexOf('=')); if (longestPrefix > 50) { longestPrefix = 50; break; } } m_sb.Append(lines[0]); for (var i = 1; i < lines.Length; i++) { var line = lines[i]; var index = line.IndexOf('='); if (index == -1) { m_sb.Append(' ', longestPrefix + 4); m_sb.Append(line); } else { var pad = Math.Max(0, longestPrefix - index); m_sb.Append(' ', pad); m_sb.Append(line, 0, index); m_sb.Append('='); m_sb.Append(line, index + 1, line.Length - index - 1); } m_sb.AppendLine(); } var result = m_sb.ToString(); m_sb.Clear(); return(result); }