Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improve Reko disassembly speed #1227

Merged
merged 4 commits into from
May 8, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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
Loading