Skip to content

Commit

Permalink
Improve Reko disassembly speed
Browse files Browse the repository at this point in the history
Signed-off-by: AnErrupTion <[email protected]>
  • Loading branch information
AnErrupTion committed May 8, 2024
1 parent 1ddbccd commit 3dbeed1
Show file tree
Hide file tree
Showing 5 changed files with 78 additions and 129 deletions.
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; }
}
155 changes: 58 additions & 97 deletions Source/Mosa.Utility.Disassembler/Disassembler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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<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>();
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)
{
Expand All @@ -150,25 +114,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 3dbeed1

Please sign in to comment.