Пример #1
0
 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);
     }
 }
Пример #2
0
        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);
        }
Пример #3
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;
            }
        }
Пример #5
0
        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);
        }
Пример #6
0
 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);
         }
     }
 }
Пример #7
0
        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);
                    }
                }
            }
        }
Пример #8
0
        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);
        }