Skip to content

Commit

Permalink
Source code view added to GDB Debugger (#479)
Browse files Browse the repository at this point in the history
* - dnlib cleanup

* - Extracting PDB source information for debugger

* - Added PDB information into debug files

* - Added SourceView to GDBDebugger

* - Added SourceDataView to GDBDebugger

* - Added SourceDataView to GDBDebugger

* - Added SourceDataView to GDBDebugger

* - Added SourceDataView to GDBDebugger
  • Loading branch information
tgiphil committed Jun 24, 2018
1 parent 49d345f commit de99fdd
Show file tree
Hide file tree
Showing 57 changed files with 1,558 additions and 221 deletions.
2 changes: 1 addition & 1 deletion Demos/Run-CoolWorld.bat
Original file line number Diff line number Diff line change
@@ -1 +1 @@
start ..\bin\Mosa.Tool.Launcher.exe --q --a --map --asm --debuginfo ..\bin\Mosa.CoolWorld.x86.exe
start ..\bin\Mosa.Tool.Launcher.exe --q --a --output-map --output-asm --output-debuginfo ..\bin\Mosa.CoolWorld.x86.exe
2 changes: 1 addition & 1 deletion Demos/Run-HelloWorld.bat
Original file line number Diff line number Diff line change
@@ -1 +1 @@
start ..\bin\Mosa.Tool.Launcher.exe --q --a --qemu --asm --threading-off ..\bin\Mosa.HelloWorld.x86.exe
start ..\bin\Mosa.Tool.Launcher.exe --q --a --qemu --output-asm --threading-off ..\bin\Mosa.HelloWorld.x86.exe
2 changes: 1 addition & 1 deletion Demos/Run-TestWorld.bat
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
start ..\bin\Mosa.Tool.Launcher.exe --q --a --qemu --map --asm --debuginfo --all-optimization-off --threading-off ..\bin\Mosa.TestWorld.x86.exe
start ..\bin\Mosa.Tool.Launcher.exe --q --a --qemu --output-map --output-asm --output-debug --all-optimizations-off --threading-off ..\bin\Mosa.TestWorld.x86.exe

12 changes: 3 additions & 9 deletions Source/Mosa.Compiler.Common/KeyedList.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,7 @@ public KeyedList()

public void Add(T key, V value)
{
List<V> list;

if (!Collection.TryGetValue(key, out list))
if (!Collection.TryGetValue(key, out List<V> list))
{
list = new List<V>();
Collection.Add(key, list);
Expand All @@ -32,9 +30,7 @@ public void Add(T key, V value)

public void AddIfNew(T key, V value)
{
List<V> list;

if (!Collection.TryGetValue(key, out list))
if (!Collection.TryGetValue(key, out List<V> list))
{
list = new List<V>();

Expand All @@ -49,9 +45,7 @@ public void AddIfNew(T key, V value)

public List<V> Get(T key)
{
List<V> list = null;

Collection.TryGetValue(key, out list);
Collection.TryGetValue(key, out List<V> list);

return list;
}
Expand Down
2 changes: 1 addition & 1 deletion Source/Mosa.Compiler.Common/StringExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ namespace Mosa.Compiler.Common
{
public static class StringExtension
{
public static ulong ParseHexOrDecimal(this string value)
public static ulong ParseHexOrInteger(this string value)
{
string nbr = value.ToUpper().Trim();
int digits = 10;
Expand Down
3 changes: 3 additions & 0 deletions Source/Mosa.Compiler.Framework/BasicBlock.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public sealed class BasicBlock
public const int StartLabel = 0;
public const int EpilogueLabel = 0xFFFFF;
public const int CompilerBlockStartLabel = 0x10001;
public const int ReservedLabel = StartLabel - 1;

#region Data Fields

Expand Down Expand Up @@ -111,6 +112,8 @@ public sealed class BasicBlock

internal BasicBlock(int sequence, int blockLabel, int instructionLabel)
{
Debug.Assert(blockLabel != ReservedLabel);

NextBlocks = new List<BasicBlock>(2);
PreviousBlocks = new List<BasicBlock>(1);
Label = blockLabel;
Expand Down
13 changes: 13 additions & 0 deletions Source/Mosa.Compiler.Framework/CompilerMethodData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,8 @@ public sealed class CompilerMethodData

public int LocalMethodStackSize { get; set; }

public List<LabelRegion> LabelRegions { get; }

#endregion Properties

public CompilerMethodData(MosaMethod mosaMethod)
Expand All @@ -72,6 +74,7 @@ public CompilerMethodData(MosaMethod mosaMethod)

Calls = new List<MosaMethod>();
CalledBy = new List<MosaMethod>();
LabelRegions = new List<LabelRegion>();
Counters = new Counters();
CompileCount = 0;
}
Expand All @@ -86,6 +89,16 @@ public void AddCalledBy(MosaMethod method)
}
}

public void AddLabelRegion(int label, int start, int length)
{
LabelRegions.Add(new LabelRegion()
{
Label = label,
Start = start,
Length = length
});
}

#endregion Methods
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
// Copyright (c) MOSA Project. Licensed under the New BSD License.

using Mosa.Compiler.Framework.Linker;
using System.Collections.Generic;
using System.IO;

namespace Mosa.Compiler.Framework.CompilerStages
Expand All @@ -20,6 +21,8 @@ public sealed class DebugFileGenerationStage : BaseCompilerStage
/// </summary>
private TextWriter writer;

private Dictionary<string, int> SourceFiles = new Dictionary<string, int>();

#endregion Data Members

protected override void Setup()
Expand All @@ -41,6 +44,9 @@ protected override void RunPostCompile()
EmitMethods();
EmitParameters();
EmitFields();
EmitSourceLabels();
EmitSourceFileInformation();
EmitSourceInformation();
}
}

Expand Down Expand Up @@ -95,28 +101,29 @@ private void EmitEntryPoint()
private void EmitTypes()
{
writer.WriteLine("[Types]");
writer.WriteLine("TypeDef\tSize\tFullName\tParent Type\tDeclaring Type\tElement Type");
writer.WriteLine("TypeID\tTypeDef\tSize\tFullName\tBaseTypeID\tDeclaringTypeID\tElementTypeID");
foreach (var type in TypeSystem.AllTypes)
{
if (type.IsModule)
continue;

writer.WriteLine(
"{0:x8}\t{1}\t{2}\t{3}\t{4}\t{5}",
"{0}\t{1:x8}\t{2}\t{3}\t{4}\t{5}\t{6}",
type.ID,
Linker.GetSymbol(type.FullName + Metadata.TypeDefinition, SectionKind.ROData).VirtualAddress,
TypeLayout.GetTypeSize(type),
type.FullName,
(type.BaseType != null) ? type.BaseType.FullName : string.Empty,
(type.DeclaringType != null) ? type.DeclaringType.FullName : string.Empty,
(type.ElementType != null) ? type.ElementType.FullName : string.Empty
(type.BaseType != null) ? type.BaseType.ID : 0,
(type.DeclaringType != null) ? type.DeclaringType.ID : 0,
(type.ElementType != null) ? type.ElementType.ID : 0
);
}
}

private void EmitMethods()
{
writer.WriteLine("[Methods]");
writer.WriteLine("Address\tSize\tMethodDef\tFullName\tType\tReturnType\tStackSize\tParameterStackSize\tAttributes");
writer.WriteLine("MethodID\tAddress\tSize\tMethodDef\tFullName\tTypeID\tReturnTypeID\tStackSize\tParameterStackSize\tAttributes");

foreach (var type in TypeSystem.AllTypes)
{
Expand All @@ -126,19 +133,20 @@ private void EmitMethods()
foreach (var method in type.Methods)
{
var symbol = Linker.GetSymbol(method.FullName, SectionKind.Text);
var methodData = this.Compiler.CompilerData.GetCompilerMethodData(method);
var methodData = Compiler.CompilerData.GetCompilerMethodData(method);

writer.WriteLine(
"{0:x8}\t{1}\t{2:x8}\t{3}\t{4}\t{5}\t{6}\t{7}\t{8}",
"{0}\t{1:x8}\t{2}\t{3:x8}\t{4}\t{5}\t{6}\t{7}\t{8}\t{9}",
method.ID,
symbol.VirtualAddress,
symbol.Size,
Linker.GetSymbol(method.FullName + Metadata.MethodDefinition, SectionKind.ROData).VirtualAddress,
method.FullName,
method.Signature.ReturnType.FullName,
method.Signature.ReturnType.ID,
methodData.LocalMethodStackSize,
methodData.ParameterStackSize,
(int)method.MethodAttributes,
type.FullName
type.ID
);
}
}
Expand All @@ -147,7 +155,7 @@ private void EmitMethods()
private void EmitParameters()
{
writer.WriteLine("[Parameters]");
writer.WriteLine("Index\tOffset\tFullName\tName\tType\tMethod\tAttributes");
writer.WriteLine("MethodID\tIndex\tOffset\tName\tFullName\tParameterTypeID\tAttributes");

foreach (var type in TypeSystem.AllTypes)
{
Expand All @@ -162,13 +170,13 @@ private void EmitParameters()
{
writer.WriteLine(
"{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}",
method.ID,
index++,
0, // todo: offset to parameter
parameter.FullName,
parameter.Name,
parameter.ParameterType.FullName,
(int)parameter.ParameterAttributes,
method.FullName
parameter.FullName,
parameter.ParameterType.ID,
(int)parameter.ParameterAttributes
);
}
}
Expand All @@ -178,7 +186,7 @@ private void EmitParameters()
private void EmitFields()
{
writer.WriteLine("[Fields]");
writer.WriteLine("Index\tFullName\tName\tFieldType\tAddress\tAttributes\tOffset\tDataLength\tDataAddress\tType");
writer.WriteLine("TypeID\tIndex\tFullName\tName\tFieldTypeID\tAddress\tAttributes\tOffset\tDataLength\tDataAddress");

foreach (var type in TypeSystem.AllTypes)
{
Expand All @@ -194,22 +202,153 @@ private void EmitFields()
//var datasection = (field.Data != null) ? SectionKind.ROData : SectionKind.BSS; // not used yet

writer.WriteLine(
"{0}\t{1}\t{2}\t{3}\t{4:x8}\t{5}\t{6}\t{7}\t{8:x8}\t{9}",
"{0}\t{1}\t{2}\t{3}\t{4}\t{5:x8}\t{6}\t{7}\t{8}\t{9:x8}",
type.ID,
index++,
field.FullName,
field.Name,
field.FieldType.FullName,
field.FieldType.ID,
symbol?.VirtualAddress ?? 0,
(int)field.FieldAttributes,
field.IsStatic && !field.IsLiteral ? 0 : TypeLayout.GetFieldOffset(field), // todo: missing first offset
field.Data?.Length ?? 0,
0, // todo: DataAddress
type.FullName
0 // todo: DataAddress
);
}
}
}

private void EmitSourceLabels()
{
writer.WriteLine("[SourceLabels]");
writer.WriteLine("MethodID\tLabel\tStart\tLength");

foreach (var methodData in Compiler.CompilerData.MethodData)
{
if (methodData == null || methodData.LabelRegions.Count == 0)
continue;

var first = methodData.LabelRegions[0];

if (first.Start != 0)
{
// special case which maps any prologue instructions to the first label
writer.WriteLine(
"{0}\t{1}\t{2}\t{3}",
methodData.Method.ID,
0,
0,
first.Start
);
}

foreach (var labelRegion in methodData.LabelRegions)
{
writer.WriteLine(
"{0}\t{1}\t{2}\t{3}",
methodData.Method.ID,
labelRegion.Label,
labelRegion.Start,
labelRegion.Length
);
}
}
}

private void EmitSourceFileInformation()
{
var filenames = new List<string>();
var hashset = new HashSet<string>();

string last = string.Empty;

foreach (var type in TypeSystem.AllTypes)
{
if (type.IsModule)
continue;

foreach (var method in type.Methods)
{
if (method.Code == null)
continue;

foreach (var instruction in method.Code)
{
var filename = instruction.Document;

if (filename == null)
continue;

if (last == filename)
continue;

if (!hashset.Contains(filename))
{
filenames.Add(filename);
hashset.Add(filename);
last = filename;
}
}
}
}

writer.WriteLine("[SourceFile]");
writer.WriteLine("SourceFileID\tFileName");

int index = 0;

foreach (var filename in filenames)
{
writer.WriteLine(
"{0}\t{1}",
++index,
filename
);

SourceFiles.Add(filename, index);
}
}

private void EmitSourceInformation()
{
writer.WriteLine("[Source]");
writer.WriteLine("MethodID\tLabel\tStartLine\tStartColumn\tEndLine\tEndColumn\tSourceFileID");

foreach (var type in TypeSystem.AllTypes)
{
if (type.IsModule)
continue;

foreach (var method in type.Methods)
{
int index = 0;

if (method.Code == null)
continue;

foreach (var instruction in method.Code)
{
if (instruction.Document == null)
continue;

if (instruction.StartLine == 0xFEEFEE)
continue;

writer.WriteLine(
"{0}\t{1}\t{2}\t{3}\t{4}\t{5}\t{6}",
method.ID,
instruction.Offset,
instruction.StartLine,
instruction.StartColumn,
instruction.EndLine,
instruction.EndColumn,
SourceFiles[instruction.Document]
);
}
}
}
}

#endregion Internals
}
}
Loading

0 comments on commit de99fdd

Please sign in to comment.