Skip to content

Commit

Permalink
Add support for multiple line program table
Browse files Browse the repository at this point in the history
  • Loading branch information
xoofx committed Mar 27, 2020
1 parent 5d8f7db commit c678e7c
Show file tree
Hide file tree
Showing 14 changed files with 1,613 additions and 1,362 deletions.
2 changes: 1 addition & 1 deletion src/LibObjectFile.CodeGen/Program.Dwarf.cs
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ private static void GenerateDwarfAttributes(CSharpNamespace ns)
break;

case "lineptr":
attrType = "DwarfLineSequence";
attrType = "DwarfLineProgramTable";
break;

case "exprloc":
Expand Down
132 changes: 111 additions & 21 deletions src/LibObjectFile.Tests/Dwarf/DwarfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,65 @@ public void TestDebugLineHelloWorld()
Assert.AreEqual(inputDebugLineBuffer, outputDebugLineBuffer);
}

[Test]
public void TestDebugLineLibMultipleObjs()
{
var cppName = "lib";
var libShared = $"{cppName}_debug.so";
LinuxUtil.RunLinuxExe("gcc", $"{cppName}_*.cpp -g -shared -o {libShared}");

ElfObjectFile elf;
using (var inStream = File.OpenRead(libShared))
{
Console.WriteLine($"ReadBack from {libShared}");
elf = ElfObjectFile.Read(inStream);
elf.Print(Console.Out);
}

var elfContext = new DwarfElfContext(elf);
var inputContext = new DwarfReaderContext(elfContext);
inputContext.DebugLinePrinter = Console.Out;
var dwarf = DwarfFile.Read(inputContext);

inputContext.DebugLineStream.Position = 0;

var copyInputDebugLineStream = new MemoryStream();
inputContext.DebugLineStream.CopyTo(copyInputDebugLineStream);
inputContext.DebugLineStream.Position = 0;

var outputContext = new DwarfWriterContext
{
IsLittleEndian = inputContext.IsLittleEndian,
EnableRelocation = false,
AddressSize = inputContext.AddressSize,
DebugLineStream = new MemoryStream()
};
dwarf.Write(outputContext);

Console.WriteLine();
Console.WriteLine("=====================================================");
Console.WriteLine("Readback");
Console.WriteLine("=====================================================");
Console.WriteLine();

var reloadContext = new DwarfReaderContext()
{
IsLittleEndian = outputContext.IsLittleEndian,
AddressSize = outputContext.AddressSize,
DebugLineStream = outputContext.DebugLineStream
};

reloadContext.DebugLineStream.Position = 0;
reloadContext.DebugLineStream = outputContext.DebugLineStream;
reloadContext.DebugLinePrinter = Console.Out;

var dwarf2 = DwarfFile.Read(reloadContext);

var inputDebugLineBuffer = copyInputDebugLineStream.ToArray();
var outputDebugLineBuffer = ((MemoryStream)reloadContext.DebugLineStream).ToArray();
Assert.AreEqual(inputDebugLineBuffer, outputDebugLineBuffer);
}

[Test]
public void TestDebugLineSmall()
{
Expand Down Expand Up @@ -274,30 +333,56 @@ public void CreateDwarf()
// Create .debug_line information
var fileName = new DwarfFileName()
{
Name = "check.cpp",
Name = "check1.cpp",
Directory = Environment.CurrentDirectory,
};
var fileName2 = new DwarfFileName()
{
Name = "check2.cpp",
Directory = Environment.CurrentDirectory,
};
dwarfFile.LineTable.AddressSize = DwarfAddressSize.Bit64;
dwarfFile.LineTable.FileNames.Add(fileName);
dwarfFile.LineTable.AddLineSequence(new DwarfLineSequence()
{

new DwarfLine()
// First line table
for (int i = 0; i < 2; i++)
{
var lineTable = new DwarfLineProgramTable();
dwarfFile.LineSection.AddLineProgramTable(lineTable);

lineTable.AddressSize = DwarfAddressSize.Bit64;
lineTable.FileNames.Add(fileName);
lineTable.FileNames.Add(fileName2);
lineTable.AddLineSequence(new DwarfLineSequence()
{
File = fileName,
Address = 0,
Column = 1,
Line = 1,
},
new DwarfLine()

new DwarfLine()
{
File = fileName,
Address = 0,
Column = 1,
Line = 1,
},
new DwarfLine()
{
File = fileName,
Address = 1,
Column = 1,
Line = 2,
}
}
);
lineTable.AddLineSequence(new DwarfLineSequence()
{
File = fileName,
Address = 0,
Column = 1,
Line = 1,

new DwarfLine()
{
File = fileName2,
Address = 0,
Column = 1,
Line = 1,
},
}
}
);
);
}

// Create .debug_info
var rootDIE = new DwarfDIECompileUnit()
Expand All @@ -306,11 +391,11 @@ public void CreateDwarf()
LowPC = 0, // 0 relative to base virtual address
HighPC = (int)codeSection.Size, // default is offset/length after LowPC
CompDir = fileName.Directory,
StmtList = dwarfFile.LineTable.LineSequences[0],
StmtList = dwarfFile.LineSection.LineTables[0],
};
var subProgram = new DwarfDIESubprogram()
{
Name = "MyFunction"
Name = "MyFunction",
};
rootDIE.AddChild(subProgram);

Expand All @@ -330,7 +415,8 @@ public void CreateDwarf()
var dwarfElfContext = new DwarfElfContext(elf);
dwarfFile.WriteToElf(dwarfElfContext);

using (var output = new FileStream("check.o", FileMode.Create))
var outputFileName = "create_dwarf.o";
using (var output = new FileStream(outputFileName, FileMode.Create))
{
elf.Write(output);
}
Expand All @@ -342,6 +428,10 @@ public void CreateDwarf()
dwarfFile.AddressRangeTable.Print(Console.Out);
Console.WriteLine();
dwarfFile.InfoSection.Print(Console.Out);

Console.WriteLine("ReadBack --debug-dump=rawline");
var readelf = LinuxUtil.ReadElf(outputFileName, "--debug-dump=rawline").TrimEnd();
Console.WriteLine(readelf);
}

private static void PrintStreamLength(DwarfReaderWriterContext context)
Expand Down
8 changes: 8 additions & 0 deletions src/LibObjectFile.Tests/LibObjectFile.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,18 @@

<ItemGroup>
<None Remove="helloworld.cpp" />
<None Remove="lib_a.cpp" />
<None Remove="lib_b.cpp" />
<None Remove="small.cpp" />
</ItemGroup>

<ItemGroup>
<Content Include="lib_b.cpp">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="lib_a.cpp">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<Content Include="small.cpp">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
Expand Down
2 changes: 1 addition & 1 deletion src/LibObjectFile.Tests/LinuxUtil.cs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public static class LinuxUtil
{
public static string ReadElf(string file, string arguments = "-W -a")
{
return RunLinuxExe("readelf", $"{file} -W -a");
return RunLinuxExe("readelf", $"{file} {arguments}");
}

public static string RunLinuxExe(string exe, string arguments, string distribution = "Ubuntu-18.04")
Expand Down
4 changes: 4 additions & 0 deletions src/LibObjectFile.Tests/lib_a.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
int process_add(int a, int b)
{
return a + b;
}
4 changes: 4 additions & 0 deletions src/LibObjectFile.Tests/lib_b.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
float process_add2(float a, float b)
{
return a + b;
}
21 changes: 15 additions & 6 deletions src/LibObjectFile/Dwarf/DwarfAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -283,22 +283,31 @@ private void ResolveAttributeValue(DwarfReader reader)
{
case DwarfAttributeKind.DeclFile:
{
var file = reader.File.LineTable.FileNames[ValueAsI32 - 1];
ValueAsU64 = 0;
ValueAsObject = file;
var currentLineProgramTable = reader.CurrentLineProgramTable;
if (currentLineProgramTable == null)
{
// Log and error
}
else
{
var file = currentLineProgramTable.FileNames[ValueAsI32 - 1];
ValueAsU64 = 0;
ValueAsObject = file;
}
break;
}

case DwarfAttributeKind.StmtList:
{
if (ValueAsU64 == 0) return;

if (reader.File.LineTable != null)
if (reader.File.LineSection != null)
{
if (reader.OffsetToDebugLineSequence.TryGetValue(ValueAsU64, out var debugLine))
if (reader.OffsetToLineProgramTable.TryGetValue(ValueAsU64, out var lineProgramTable))
{
ValueAsU64 = 0;
ValueAsObject = debugLine;
ValueAsObject = lineProgramTable;
reader.PushLineProgramTable(lineProgramTable);
}
else
{
Expand Down
9 changes: 8 additions & 1 deletion src/LibObjectFile/Dwarf/DwarfDIE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,11 @@ public class DwarfDIE : DwarfContainer
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private DwarfTagEx _tag;

/// <summary>
/// The current line program table when reading.
/// </summary>
internal DwarfLineProgramTable CurrentLineProgramTable;

public DwarfDIE()
{
_attributes = new List<DwarfAttribute>();
Expand Down Expand Up @@ -391,7 +396,7 @@ protected override void UpdateLayout(DwarfLayoutContext layoutContext)
protected override void Read(DwarfReader reader)
{
// Store map offset to DIE to resolve references
reader.RegisterDIE(this);
reader.PushDIE(this);

// Console.WriteLine($" <{level}><{die.Offset:x}> Abbrev Number: {abbreviationCode} ({die.Tag})");

Expand Down Expand Up @@ -426,6 +431,8 @@ protected override void Read(DwarfReader reader)
}
}

reader.PopDIE();

Size = reader.Offset - Offset;
}

Expand Down
40 changes: 20 additions & 20 deletions src/LibObjectFile/Dwarf/DwarfFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,15 +11,15 @@ public class DwarfFile : DwarfContainer
{
private DwarfAbbreviationTable _abbreviationTable;
private DwarfStringTable _stringTable;
private DwarfLineSection _lineTable;
private DwarfLineSection _lineSection;
private DwarfInfoSection _infoSection;
private DwarfAddressRangeTable _addressRangeTable;

public DwarfFile()
{
AbbreviationTable = new DwarfAbbreviationTable();
StringTable = new DwarfStringTable();
LineTable = new DwarfLineSection();
LineSection = new DwarfLineSection();
InfoSection = new DwarfInfoSection();
AddressRangeTable = new DwarfAddressRangeTable();
}
Expand All @@ -36,10 +36,10 @@ public DwarfStringTable StringTable
set => AttachChild(this, value, ref _stringTable, false);
}

public DwarfLineSection LineTable
public DwarfLineSection LineSection
{
get => _lineTable;
set => AttachChild(this, value, ref _lineTable, false);
get => _lineSection;
set => AttachChild(this, value, ref _lineSection, false);
}

public DwarfAddressRangeTable AddressRangeTable
Expand All @@ -63,7 +63,7 @@ public override void Verify(DiagnosticBag diagnostics)
{
base.Verify(diagnostics);

LineTable.Verify(diagnostics);
LineSection.Verify(diagnostics);
AbbreviationTable.Verify(diagnostics);
AddressRangeTable.Verify(diagnostics);
StringTable.Verify(diagnostics);
Expand All @@ -77,8 +77,8 @@ public void UpdateLayout(DwarfLayoutConfig config, DiagnosticBag diagnostics)

var layoutContext = new DwarfLayoutContext(this, config, diagnostics);

LineTable.Offset = 0;
LineTable.UpdateLayoutInternal(layoutContext);
LineSection.Offset = 0;
LineSection.UpdateLayoutInternal(layoutContext);
if (layoutContext.HasErrors)
{
return;
Expand Down Expand Up @@ -142,9 +142,9 @@ public void Write(DwarfWriterContext writerContext)
{
writer.Stream.Position = 0;
writer.Stream.SetLength(0);
writer.CurrentSection = LineTable;
LineTable.Relocations.Clear();
LineTable.WriteInternal(writer);
writer.CurrentSection = LineSection;
LineSection.Relocations.Clear();
LineSection.WriteInternal(writer);
}

writer.Log = null;
Expand Down Expand Up @@ -215,7 +215,7 @@ public void WriteToElf(DwarfElfContext elfContext, DwarfLayoutConfig layoutConfi
// Pre-create table/sections to create symbols as well
if (StringTable.Size > 0) elfContext.GetOrCreateStringTable();
if (AbbreviationTable.Size > 0) elfContext.GetOrCreateAbbreviationTable();
if (LineTable.Size > 0) elfContext.GetOrCreateLineSection();
if (LineSection.Size > 0) elfContext.GetOrCreateLineSection();
if (AddressRangeTable.Size > 0) elfContext.GetOrCreateAddressRangeTable();
if (InfoSection.Size > 0) elfContext.GetOrCreateInfoSection();

Expand Down Expand Up @@ -248,17 +248,17 @@ public void WriteToElf(DwarfElfContext elfContext, DwarfLayoutConfig layoutConfi
}

// Line table
if (LineTable.Size > 0)
if (LineSection.Size > 0)
{
writer.Stream = elfContext.GetOrCreateLineSection().Stream;
writer.Stream.Position = 0;
writer.Stream.SetLength(0);
writer.CurrentSection = LineTable;
LineTable.Relocations.Clear();
LineTable.WriteInternal(writer);
if (writer.EnableRelocation && LineTable.Relocations.Count > 0)
writer.CurrentSection = LineSection;
LineSection.Relocations.Clear();
LineSection.WriteInternal(writer);
if (writer.EnableRelocation && LineSection.Relocations.Count > 0)
{
LineTable.CopyRelocationsTo(elfContext, elfContext.GetOrCreateRelocLineSection());
LineSection.CopyRelocationsTo(elfContext, elfContext.GetOrCreateRelocLineSection());
}
else
{
Expand Down Expand Up @@ -347,8 +347,8 @@ public static DwarfFile Read(DwarfReaderContext readerContext)
reader.Stream = readerContext.DebugLineStream;
if (reader.Stream != null)
{
reader.CurrentSection = dwarf.LineTable;
dwarf.LineTable.ReadInternal(reader);
reader.CurrentSection = dwarf.LineSection;
dwarf.LineSection.ReadInternal(reader);
}

reader.Log = null;
Expand Down
Loading

0 comments on commit c678e7c

Please sign in to comment.