From 3dbeed1554626e944c1f69cd78040bce3db7a304 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Wed, 8 May 2024 10:21:43 +0200 Subject: [PATCH 1/4] Improve Reko disassembly speed Signed-off-by: AnErrupTion --- .../Stages/DisassemblyStage.cs | 16 +- .../Stages/DisassemblyStage.cs | 18 +- .../DecodedInstruction.cs | 10 +- .../Mosa.Utility.Disassembler/Disassembler.cs | 155 +++++++----------- Source/Mosa.Utility.Launcher/Builder.cs | 8 +- 5 files changed, 78 insertions(+), 129 deletions(-) diff --git a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs b/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs index d59150f209..521c6a09cd 100755 --- a/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs +++ b/Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs @@ -33,19 +33,13 @@ protected void TraceDisassembly() stream.Read(memory, 0, length); stream.Position = oldPosition; - var disassembler = new Disassembler(Architecture.PlatformName); - disassembler.SetMemory(memory, 0); + var disassembler = new Disassembler(Architecture.PlatformName, memory, 0); + var instruction = disassembler.DecodeNext(); - var list = disassembler.Decode(); - - if (list != null) - { - foreach (var instr in list) - trace.Log(instr.Full); - } - else + while (instruction != null) { - PostEvent(CompilerEvent.Error, $"Failed disassembly for method {MethodCompiler.Method}"); + trace.Log(instruction.Full); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs b/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs index a83e83f25a..4571ab33b4 100644 --- a/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs +++ b/Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs @@ -34,21 +34,13 @@ protected void TraceDisassembly() stream.Read(memory, 0, length); stream.Position = oldPosition; - var disassembler = new Disassembler(Architecture.PlatformName); - disassembler.SetMemory(memory, 0); + var disassembler = new Disassembler(Architecture.PlatformName, memory, 0); + var instruction = disassembler.DecodeNext(); - var list = disassembler.Decode(); - - if (list != null) - { - foreach (var instr in list) - { - trace.Log(instr.Full); - } - } - else + while (instruction != null) { - PostEvent(CompilerEvent.Error, $"Failed disassembly for method {MethodCompiler.Method}"); + trace.Log(instruction.Full); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs b/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs index 0dc54452d0..ce1f0102c3 100644 --- a/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs +++ b/Source/Mosa.Utility.Disassembler/DecodedInstruction.cs @@ -2,13 +2,13 @@ namespace Mosa.Utility.Disassembler; -public partial class DecodedInstruction +public class DecodedInstruction { - public ulong Address { get; set; } + public ulong Address { get; init; } - public int Length { get; set; } + public uint Length { get; init; } - public string Instruction { get; set; } + public string Instruction { get; init; } - public string Full { get; set; } + public string Full { get; init; } } diff --git a/Source/Mosa.Utility.Disassembler/Disassembler.cs b/Source/Mosa.Utility.Disassembler/Disassembler.cs index 78d6b562e1..6d1995136d 100644 --- a/Source/Mosa.Utility.Disassembler/Disassembler.cs +++ b/Source/Mosa.Utility.Disassembler/Disassembler.cs @@ -5,127 +5,91 @@ using Reko.Arch.Arm; using Reko.Arch.X86; using Reko.Core; +using Reko.Core.Machine; using Reko.Core.Memory; namespace Mosa.Utility.Disassembler; -public partial class Disassembler +public class Disassembler { - private byte[] memory; - public ulong Offset { get; set; } - private readonly ProcessorArchitecture arch; - private MemoryArea memoryArea; + private readonly byte[] memory; + private readonly IEnumerator instructions; + private readonly StringBuilder sb = new StringBuilder(100); - public Disassembler(string platform) + public Disassembler(string platform, byte[] bytes, ulong address) { var services = new ServiceContainer(); var options = new Dictionary(); + var memoryArea = new ByteMemoryArea(Address.Ptr32((uint)address), bytes); - arch = platform.ToLowerInvariant() switch + ProcessorArchitecture arch = platform.ToLowerInvariant() switch { "arm32" => new Arm32Architecture(services, "arm32", options), "arm64" => new Arm64Architecture(services, "arm64", options), "x86" => new X86ArchitectureFlat32(services, "x86-protected-32", options), "x64" => new X86ArchitectureFlat64(services, "x86-protected-64", options), - _ => arch + _ => throw new PlatformNotSupportedException(platform) }; - } - public void SetMemory(byte[] memory, ulong address) - { - this.memory = memory; - memoryArea = new ByteMemoryArea(Address.Ptr32((uint)address), memory); + memory = bytes; + instructions = arch.CreateDisassembler(memoryArea.CreateLeReader((long)Offset)).GetEnumerator(); } - public List Decode(int count = int.MaxValue) + public DecodedInstruction DecodeNext() { - var decoded = new List(); + if (!instructions.MoveNext()) + return null; - var sb = new StringBuilder(100); + var machineInstruction = instructions.Current; + if (machineInstruction == null) + return null; - try + var length = (uint)machineInstruction.Length; + var address = machineInstruction.Address.Offset; + var instruction = machineInstruction.ToString() + .Replace('\t', ' ') + .Replace(",", ", ") + .Replace("+", " + ") + .Replace("-", " - ") + .Replace("*", " * "); + + // FIXME + //instruction = ChangeHex(instruction); + + sb.Append(address.ToString("X8")); + sb.Append(' '); + for (var i = 0U; i < length; i++) { - var dasm = arch.CreateDisassembler(memoryArea.CreateLeReader((long)Offset)); - - foreach (var instr in dasm) - { - var len = instr.Length; - var address = instr.Address.Offset; - var instruction = instr.ToString().Replace('\t', ' '); - - // preference - instruction = instruction.Replace(",", ", "); - - // fix up - //instruction = ChangeHex(instruction); - - sb.AppendFormat("{0:x8}", address); - sb.Append(' '); - var bytes = BytesToHex(memory, (uint)Offset, len); - sb.Append(bytes == null ? string.Empty : bytes.ToString()); - sb.Append(string.Empty.PadRight(41 - sb.Length, ' ')); - sb.Append(instruction); - - decoded.Add(new DecodedInstruction - { - Address = address, - Length = len, - Instruction = instruction, - Full = sb.ToString() - }); - - sb.Clear(); - - count--; - - if (count == 0) - break; - - Offset += (uint)len; - } - - return decoded; + var b = memory[i + Offset]; + sb.Append(b.ToString("X2")); + sb.Append(' '); } - catch - { - return decoded; - } - } - - private static StringBuilder BytesToHex(byte[] memory, uint offset, int length) - { - if (length == 0) - return null; + for (var i = 0; i < 41 - sb.Length; i++) + sb.Append(' '); + sb.Append(instruction); - var sb = new StringBuilder(); - - for (uint i = 0; i < length; i++) + var decodedInstruction = new DecodedInstruction { - var b = memory[i + offset]; + Address = address, + Length = length, + Instruction = instruction, + Full = sb.ToString() + }; - sb.AppendFormat("{0:x2} ", b); - } + sb.Clear(); - sb.Length--; + Offset += length; - return sb; + return decodedInstruction; } - private static bool IsHex(char c) + private static bool IsHex(char c) => c switch { - if (c >= '0' && c <= '9') - return true; - - if (c >= 'a' && c <= 'f') - return true; - - if (c >= 'A' && c <= 'F') - return true; - - return false; - } + >= '0' and <= '9' or >= 'a' and <= 'f' or >= 'A' and <= 'F' => true, + _ => false + }; private static int IsNextWordHex(string s, int start) { @@ -150,7 +114,6 @@ private static string ChangeHex(string s) for (var i = 0; i < s.Length; i++) { var c = s[i]; - var l = IsNextWordHex(s, i); if (l == 0) @@ -158,17 +121,15 @@ private static string ChangeHex(string s) sb.Append(c); continue; } - else - { - var hex = s.Substring(i, l); - var value = long.Parse(hex, System.Globalization.NumberStyles.HexNumber); - var hex2 = Convert.ToString(value, 16).ToUpper(); - sb.Append("0x"); - sb.Append(hex2); + var hex = s.Substring(i, l); + var value = long.Parse(hex, System.Globalization.NumberStyles.HexNumber); + var hex2 = Convert.ToString(value, 16).ToUpper(); - i += l; - } + sb.Append("0x"); + sb.Append(hex2); + + i += l; } return sb.ToString(); diff --git a/Source/Mosa.Utility.Launcher/Builder.cs b/Source/Mosa.Utility.Launcher/Builder.cs index 6933287cb7..5857a10547 100644 --- a/Source/Mosa.Utility.Launcher/Builder.cs +++ b/Source/Mosa.Utility.Launcher/Builder.cs @@ -241,12 +241,12 @@ private void GenerateASMFile() for (ulong i = fileOffset; i < (ulong)code2.Length; i++) code[i - fileOffset] = code2[i]; - var disassembler = new Disassembler.Disassembler(MosaSettings.Platform); - disassembler.SetMemory(code, startingAddress); + var disassembler = new Disassembler.Disassembler(MosaSettings.Platform, code, startingAddress); using var dest = File.CreateText(MosaSettings.AsmFile); - foreach (var instruction in disassembler.Decode()) + var instruction = disassembler.DecodeNext(); + while (instruction != null) { if (map.TryGetValue(instruction.Address, out List list)) foreach (var entry in list) @@ -256,6 +256,8 @@ private void GenerateASMFile() if (instruction.Address > startingAddress + length) break; + + instruction = disassembler.DecodeNext(); } } From 1a6edc9019123b02cd0d505a8914686f90e39945 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Wed, 8 May 2024 10:35:29 +0200 Subject: [PATCH 2/4] Fix debugger Signed-off-by: AnErrupTion --- Source/Mosa.Tool.Debugger/Views/InstructionView.cs | 9 +++++---- Source/Mosa.Tool.Debugger/Views/MethodView.cs | 7 ++++--- Source/Mosa.Tool.Debugger/Views/StatusView.cs | 8 ++++---- Source/Mosa.Tool.Debugger/Views/TraceView.cs | 8 ++++---- 4 files changed, 17 insertions(+), 15 deletions(-) diff --git a/Source/Mosa.Tool.Debugger/Views/InstructionView.cs b/Source/Mosa.Tool.Debugger/Views/InstructionView.cs index 10b7c73c8a..112a44176d 100644 --- a/Source/Mosa.Tool.Debugger/Views/InstructionView.cs +++ b/Source/Mosa.Tool.Debugger/Views/InstructionView.cs @@ -57,19 +57,20 @@ private void UpdateDisplay(ulong address, byte[] memory) { instructions.Clear(); - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); + var instruction = disassembler.DecodeNext(); - foreach (var instruction in disassembler.Decode()) + while (instruction != null) { var entry = new InstructionEntry() { IP = instruction.Address, - Length = instruction.Length, + Length = (int)instruction.Length, Instruction = instruction.Instruction.ToString() }; instructions.Add(entry); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Tool.Debugger/Views/MethodView.cs b/Source/Mosa.Tool.Debugger/Views/MethodView.cs index cc88d84e29..35c2b34e29 100644 --- a/Source/Mosa.Tool.Debugger/Views/MethodView.cs +++ b/Source/Mosa.Tool.Debugger/Views/MethodView.cs @@ -148,10 +148,10 @@ private void UpdateDisplay(ulong address, byte[] memory) { instructions.Clear(); - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); + var instruction = disassembler.DecodeNext(); - foreach (var instruction in disassembler.Decode()) + while (instruction != null) { var addr = MainForm.ParseAddress(instruction.Instruction); @@ -166,6 +166,7 @@ private void UpdateDisplay(ulong address, byte[] memory) }; instructions.Add(entry); + instruction = disassembler.DecodeNext(); } } diff --git a/Source/Mosa.Tool.Debugger/Views/StatusView.cs b/Source/Mosa.Tool.Debugger/Views/StatusView.cs index 09329ce091..f60039afae 100644 --- a/Source/Mosa.Tool.Debugger/Views/StatusView.cs +++ b/Source/Mosa.Tool.Debugger/Views/StatusView.cs @@ -44,15 +44,15 @@ private void UpdateDisplay(ulong address, byte[] memory) if (address != InstructionPointer) return; - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); tbInstruction.Text = "Unable to decode!"; - foreach (var instruction in disassembler.Decode()) + var instruction = disassembler.DecodeNext(); + while (instruction != null) { tbInstruction.Text = instruction.Instruction; - break; + instruction = disassembler.DecodeNext(); } } } diff --git a/Source/Mosa.Tool.Debugger/Views/TraceView.cs b/Source/Mosa.Tool.Debugger/Views/TraceView.cs index 236e1a3d8a..f746d5d0d7 100644 --- a/Source/Mosa.Tool.Debugger/Views/TraceView.cs +++ b/Source/Mosa.Tool.Debugger/Views/TraceView.cs @@ -68,13 +68,13 @@ private void UpdateDisplay(ulong address, byte[] memory) if (address == InstructionPointer) { - var disassembler = new Disassembler("x86"); - disassembler.SetMemory(memory, address); + var disassembler = new Disassembler("x86", memory, address); + var instruction = disassembler.DecodeNext(); - foreach (var instruction in disassembler.Decode()) + while (instruction != null) { opinstruction = instruction.Instruction; - break; + instruction = disassembler.DecodeNext(); } } From 5ad4c70cf657668f7cd84613d71a45e82af2b032 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Wed, 8 May 2024 10:41:57 +0200 Subject: [PATCH 3/4] Forgot to cast in debugger Signed-off-by: AnErrupTion --- Source/Mosa.Tool.Debugger/Views/MethodView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Mosa.Tool.Debugger/Views/MethodView.cs b/Source/Mosa.Tool.Debugger/Views/MethodView.cs index 35c2b34e29..dc705c87f7 100644 --- a/Source/Mosa.Tool.Debugger/Views/MethodView.cs +++ b/Source/Mosa.Tool.Debugger/Views/MethodView.cs @@ -160,7 +160,7 @@ private void UpdateDisplay(ulong address, byte[] memory) var entry = new MethodInstructionEntry() { IP = instruction.Address, // Offset? - Length = instruction.Length, + Length = (int)instruction.Length, Instruction = instruction.Instruction, Info = info }; From 7dc8b526896286d534f397c0d678b22142466fd4 Mon Sep 17 00:00:00 2001 From: AnErrupTion Date: Wed, 8 May 2024 11:10:07 +0200 Subject: [PATCH 4/4] Make text output identical Signed-off-by: AnErrupTion --- Source/Mosa.Utility.Disassembler/Disassembler.cs | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Source/Mosa.Utility.Disassembler/Disassembler.cs b/Source/Mosa.Utility.Disassembler/Disassembler.cs index 6d1995136d..4b3c7223b9 100644 --- a/Source/Mosa.Utility.Disassembler/Disassembler.cs +++ b/Source/Mosa.Utility.Disassembler/Disassembler.cs @@ -50,23 +50,20 @@ public DecodedInstruction DecodeNext() var address = machineInstruction.Address.Offset; var instruction = machineInstruction.ToString() .Replace('\t', ' ') - .Replace(",", ", ") - .Replace("+", " + ") - .Replace("-", " - ") - .Replace("*", " * "); + .Replace(",", ", "); // FIXME //instruction = ChangeHex(instruction); - sb.Append(address.ToString("X8")); + sb.Append(address.ToString("x8")); sb.Append(' '); for (var i = 0U; i < length; i++) { var b = memory[i + Offset]; - sb.Append(b.ToString("X2")); + sb.Append(b.ToString("x2")); sb.Append(' '); } - for (var i = 0; i < 41 - sb.Length; i++) + for (var i = sb.Length; i < 41; i++) sb.Append(' '); sb.Append(instruction);