Skip to content

Commit

Permalink
Improve Reko disassembly speed (#1227)
Browse files Browse the repository at this point in the history
* Improve Reko disassembly speed

Signed-off-by: AnErrupTion <anerruption@disroot.org>

* Fix debugger

Signed-off-by: AnErrupTion <anerruption@disroot.org>

* Forgot to cast in debugger

Signed-off-by: AnErrupTion <anerruption@disroot.org>

* Make text output identical

Signed-off-by: AnErrupTion <anerruption@disroot.org>

---------

Signed-off-by: AnErrupTion <anerruption@disroot.org>
  • Loading branch information
AnErrupTion committed May 8, 2024
1 parent 1ddbccd commit 279a4c1
Show file tree
Hide file tree
Showing 9 changed files with 91 additions and 143 deletions.
9 changes: 5 additions & 4 deletions Source/Mosa.Tool.Debugger/Views/InstructionView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
9 changes: 5 additions & 4 deletions Source/Mosa.Tool.Debugger/Views/MethodView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand All @@ -160,12 +160,13 @@ 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
};

instructions.Add(entry);
instruction = disassembler.DecodeNext();
}
}

Expand Down
8 changes: 4 additions & 4 deletions Source/Mosa.Tool.Debugger/Views/StatusView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}
}
8 changes: 4 additions & 4 deletions Source/Mosa.Tool.Debugger/Views/TraceView.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
16 changes: 5 additions & 11 deletions Source/Mosa.Tool.Explorer.Avalonia/Stages/DisassemblyStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
18 changes: 5 additions & 13 deletions Source/Mosa.Tool.Explorer/Stages/DisassemblyStage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
}

Expand Down
10 changes: 5 additions & 5 deletions Source/Mosa.Utility.Disassembler/DecodedInstruction.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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; }
}
148 changes: 53 additions & 95 deletions Source/Mosa.Utility.Disassembler/Disassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,127 +5,88 @@
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<MachineInstruction> 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<string, object>();
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<DecodedInstruction> Decode(int count = int.MaxValue)
public DecodedInstruction DecodeNext()
{
var decoded = new List<DecodedInstruction>();

var sb = new StringBuilder(100);

try
{
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();
if (!instructions.MoveNext())
return null;

count--;
var machineInstruction = instructions.Current;
if (machineInstruction == null)
return null;

if (count == 0)
break;
var length = (uint)machineInstruction.Length;
var address = machineInstruction.Address.Offset;
var instruction = machineInstruction.ToString()
.Replace('\t', ' ')
.Replace(",", ", ");

Offset += (uint)len;
}
// FIXME
//instruction = ChangeHex(instruction);

return decoded;
}
catch
sb.Append(address.ToString("x8"));
sb.Append(' ');
for (var i = 0U; i < length; i++)
{
return decoded;
var b = memory[i + Offset];
sb.Append(b.ToString("x2"));
sb.Append(' ');
}
}

private static StringBuilder BytesToHex(byte[] memory, uint offset, int length)
{
if (length == 0)
return null;
for (var i = sb.Length; i < 41; 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)
{
Expand All @@ -150,25 +111,22 @@ 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)
{
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();
Expand Down
8 changes: 5 additions & 3 deletions Source/Mosa.Utility.Launcher/Builder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<string> list))
foreach (var entry in list)
Expand All @@ -256,6 +256,8 @@ private void GenerateASMFile()

if (instruction.Address > startingAddress + length)
break;

instruction = disassembler.DecodeNext();
}
}

Expand Down

0 comments on commit 279a4c1

Please sign in to comment.