Skip to content

Commit c678e7c

Browse files
committed
Add support for multiple line program table
1 parent 5d8f7db commit c678e7c

File tree

14 files changed

+1613
-1362
lines changed

14 files changed

+1613
-1362
lines changed

src/LibObjectFile.CodeGen/Program.Dwarf.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -180,7 +180,7 @@ private static void GenerateDwarfAttributes(CSharpNamespace ns)
180180
break;
181181

182182
case "lineptr":
183-
attrType = "DwarfLineSequence";
183+
attrType = "DwarfLineProgramTable";
184184
break;
185185

186186
case "exprloc":

src/LibObjectFile.Tests/Dwarf/DwarfTests.cs

Lines changed: 111 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,65 @@ public void TestDebugLineHelloWorld()
134134
Assert.AreEqual(inputDebugLineBuffer, outputDebugLineBuffer);
135135
}
136136

137+
[Test]
138+
public void TestDebugLineLibMultipleObjs()
139+
{
140+
var cppName = "lib";
141+
var libShared = $"{cppName}_debug.so";
142+
LinuxUtil.RunLinuxExe("gcc", $"{cppName}_*.cpp -g -shared -o {libShared}");
143+
144+
ElfObjectFile elf;
145+
using (var inStream = File.OpenRead(libShared))
146+
{
147+
Console.WriteLine($"ReadBack from {libShared}");
148+
elf = ElfObjectFile.Read(inStream);
149+
elf.Print(Console.Out);
150+
}
151+
152+
var elfContext = new DwarfElfContext(elf);
153+
var inputContext = new DwarfReaderContext(elfContext);
154+
inputContext.DebugLinePrinter = Console.Out;
155+
var dwarf = DwarfFile.Read(inputContext);
156+
157+
inputContext.DebugLineStream.Position = 0;
158+
159+
var copyInputDebugLineStream = new MemoryStream();
160+
inputContext.DebugLineStream.CopyTo(copyInputDebugLineStream);
161+
inputContext.DebugLineStream.Position = 0;
162+
163+
var outputContext = new DwarfWriterContext
164+
{
165+
IsLittleEndian = inputContext.IsLittleEndian,
166+
EnableRelocation = false,
167+
AddressSize = inputContext.AddressSize,
168+
DebugLineStream = new MemoryStream()
169+
};
170+
dwarf.Write(outputContext);
171+
172+
Console.WriteLine();
173+
Console.WriteLine("=====================================================");
174+
Console.WriteLine("Readback");
175+
Console.WriteLine("=====================================================");
176+
Console.WriteLine();
177+
178+
var reloadContext = new DwarfReaderContext()
179+
{
180+
IsLittleEndian = outputContext.IsLittleEndian,
181+
AddressSize = outputContext.AddressSize,
182+
DebugLineStream = outputContext.DebugLineStream
183+
};
184+
185+
reloadContext.DebugLineStream.Position = 0;
186+
reloadContext.DebugLineStream = outputContext.DebugLineStream;
187+
reloadContext.DebugLinePrinter = Console.Out;
188+
189+
var dwarf2 = DwarfFile.Read(reloadContext);
190+
191+
var inputDebugLineBuffer = copyInputDebugLineStream.ToArray();
192+
var outputDebugLineBuffer = ((MemoryStream)reloadContext.DebugLineStream).ToArray();
193+
Assert.AreEqual(inputDebugLineBuffer, outputDebugLineBuffer);
194+
}
195+
137196
[Test]
138197
public void TestDebugLineSmall()
139198
{
@@ -274,30 +333,56 @@ public void CreateDwarf()
274333
// Create .debug_line information
275334
var fileName = new DwarfFileName()
276335
{
277-
Name = "check.cpp",
336+
Name = "check1.cpp",
337+
Directory = Environment.CurrentDirectory,
338+
};
339+
var fileName2 = new DwarfFileName()
340+
{
341+
Name = "check2.cpp",
278342
Directory = Environment.CurrentDirectory,
279343
};
280-
dwarfFile.LineTable.AddressSize = DwarfAddressSize.Bit64;
281-
dwarfFile.LineTable.FileNames.Add(fileName);
282-
dwarfFile.LineTable.AddLineSequence(new DwarfLineSequence()
283-
{
284344

285-
new DwarfLine()
345+
// First line table
346+
for (int i = 0; i < 2; i++)
347+
{
348+
var lineTable = new DwarfLineProgramTable();
349+
dwarfFile.LineSection.AddLineProgramTable(lineTable);
350+
351+
lineTable.AddressSize = DwarfAddressSize.Bit64;
352+
lineTable.FileNames.Add(fileName);
353+
lineTable.FileNames.Add(fileName2);
354+
lineTable.AddLineSequence(new DwarfLineSequence()
286355
{
287-
File = fileName,
288-
Address = 0,
289-
Column = 1,
290-
Line = 1,
291-
},
292-
new DwarfLine()
356+
357+
new DwarfLine()
358+
{
359+
File = fileName,
360+
Address = 0,
361+
Column = 1,
362+
Line = 1,
363+
},
364+
new DwarfLine()
365+
{
366+
File = fileName,
367+
Address = 1,
368+
Column = 1,
369+
Line = 2,
370+
}
371+
}
372+
);
373+
lineTable.AddLineSequence(new DwarfLineSequence()
293374
{
294-
File = fileName,
295-
Address = 0,
296-
Column = 1,
297-
Line = 1,
375+
376+
new DwarfLine()
377+
{
378+
File = fileName2,
379+
Address = 0,
380+
Column = 1,
381+
Line = 1,
382+
},
298383
}
299-
}
300-
);
384+
);
385+
}
301386

302387
// Create .debug_info
303388
var rootDIE = new DwarfDIECompileUnit()
@@ -306,11 +391,11 @@ public void CreateDwarf()
306391
LowPC = 0, // 0 relative to base virtual address
307392
HighPC = (int)codeSection.Size, // default is offset/length after LowPC
308393
CompDir = fileName.Directory,
309-
StmtList = dwarfFile.LineTable.LineSequences[0],
394+
StmtList = dwarfFile.LineSection.LineTables[0],
310395
};
311396
var subProgram = new DwarfDIESubprogram()
312397
{
313-
Name = "MyFunction"
398+
Name = "MyFunction",
314399
};
315400
rootDIE.AddChild(subProgram);
316401

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

333-
using (var output = new FileStream("check.o", FileMode.Create))
418+
var outputFileName = "create_dwarf.o";
419+
using (var output = new FileStream(outputFileName, FileMode.Create))
334420
{
335421
elf.Write(output);
336422
}
@@ -342,6 +428,10 @@ public void CreateDwarf()
342428
dwarfFile.AddressRangeTable.Print(Console.Out);
343429
Console.WriteLine();
344430
dwarfFile.InfoSection.Print(Console.Out);
431+
432+
Console.WriteLine("ReadBack --debug-dump=rawline");
433+
var readelf = LinuxUtil.ReadElf(outputFileName, "--debug-dump=rawline").TrimEnd();
434+
Console.WriteLine(readelf);
345435
}
346436

347437
private static void PrintStreamLength(DwarfReaderWriterContext context)

src/LibObjectFile.Tests/LibObjectFile.Tests.csproj

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,18 @@
99

1010
<ItemGroup>
1111
<None Remove="helloworld.cpp" />
12+
<None Remove="lib_a.cpp" />
13+
<None Remove="lib_b.cpp" />
1214
<None Remove="small.cpp" />
1315
</ItemGroup>
1416

1517
<ItemGroup>
18+
<Content Include="lib_b.cpp">
19+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
20+
</Content>
21+
<Content Include="lib_a.cpp">
22+
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
23+
</Content>
1624
<Content Include="small.cpp">
1725
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
1826
</Content>

src/LibObjectFile.Tests/LinuxUtil.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ public static class LinuxUtil
1414
{
1515
public static string ReadElf(string file, string arguments = "-W -a")
1616
{
17-
return RunLinuxExe("readelf", $"{file} -W -a");
17+
return RunLinuxExe("readelf", $"{file} {arguments}");
1818
}
1919

2020
public static string RunLinuxExe(string exe, string arguments, string distribution = "Ubuntu-18.04")

src/LibObjectFile.Tests/lib_a.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
int process_add(int a, int b)
2+
{
3+
return a + b;
4+
}

src/LibObjectFile.Tests/lib_b.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
float process_add2(float a, float b)
2+
{
3+
return a + b;
4+
}

src/LibObjectFile/Dwarf/DwarfAttribute.cs

Lines changed: 15 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -283,22 +283,31 @@ private void ResolveAttributeValue(DwarfReader reader)
283283
{
284284
case DwarfAttributeKind.DeclFile:
285285
{
286-
var file = reader.File.LineTable.FileNames[ValueAsI32 - 1];
287-
ValueAsU64 = 0;
288-
ValueAsObject = file;
286+
var currentLineProgramTable = reader.CurrentLineProgramTable;
287+
if (currentLineProgramTable == null)
288+
{
289+
// Log and error
290+
}
291+
else
292+
{
293+
var file = currentLineProgramTable.FileNames[ValueAsI32 - 1];
294+
ValueAsU64 = 0;
295+
ValueAsObject = file;
296+
}
289297
break;
290298
}
291299

292300
case DwarfAttributeKind.StmtList:
293301
{
294302
if (ValueAsU64 == 0) return;
295303

296-
if (reader.File.LineTable != null)
304+
if (reader.File.LineSection != null)
297305
{
298-
if (reader.OffsetToDebugLineSequence.TryGetValue(ValueAsU64, out var debugLine))
306+
if (reader.OffsetToLineProgramTable.TryGetValue(ValueAsU64, out var lineProgramTable))
299307
{
300308
ValueAsU64 = 0;
301-
ValueAsObject = debugLine;
309+
ValueAsObject = lineProgramTable;
310+
reader.PushLineProgramTable(lineProgramTable);
302311
}
303312
else
304313
{

src/LibObjectFile/Dwarf/DwarfDIE.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,11 @@ public class DwarfDIE : DwarfContainer
1717
[DebuggerBrowsable(DebuggerBrowsableState.Never)]
1818
private DwarfTagEx _tag;
1919

20+
/// <summary>
21+
/// The current line program table when reading.
22+
/// </summary>
23+
internal DwarfLineProgramTable CurrentLineProgramTable;
24+
2025
public DwarfDIE()
2126
{
2227
_attributes = new List<DwarfAttribute>();
@@ -391,7 +396,7 @@ protected override void UpdateLayout(DwarfLayoutContext layoutContext)
391396
protected override void Read(DwarfReader reader)
392397
{
393398
// Store map offset to DIE to resolve references
394-
reader.RegisterDIE(this);
399+
reader.PushDIE(this);
395400

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

@@ -426,6 +431,8 @@ protected override void Read(DwarfReader reader)
426431
}
427432
}
428433

434+
reader.PopDIE();
435+
429436
Size = reader.Offset - Offset;
430437
}
431438

src/LibObjectFile/Dwarf/DwarfFile.cs

Lines changed: 20 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,15 @@ public class DwarfFile : DwarfContainer
1111
{
1212
private DwarfAbbreviationTable _abbreviationTable;
1313
private DwarfStringTable _stringTable;
14-
private DwarfLineSection _lineTable;
14+
private DwarfLineSection _lineSection;
1515
private DwarfInfoSection _infoSection;
1616
private DwarfAddressRangeTable _addressRangeTable;
1717

1818
public DwarfFile()
1919
{
2020
AbbreviationTable = new DwarfAbbreviationTable();
2121
StringTable = new DwarfStringTable();
22-
LineTable = new DwarfLineSection();
22+
LineSection = new DwarfLineSection();
2323
InfoSection = new DwarfInfoSection();
2424
AddressRangeTable = new DwarfAddressRangeTable();
2525
}
@@ -36,10 +36,10 @@ public DwarfStringTable StringTable
3636
set => AttachChild(this, value, ref _stringTable, false);
3737
}
3838

39-
public DwarfLineSection LineTable
39+
public DwarfLineSection LineSection
4040
{
41-
get => _lineTable;
42-
set => AttachChild(this, value, ref _lineTable, false);
41+
get => _lineSection;
42+
set => AttachChild(this, value, ref _lineSection, false);
4343
}
4444

4545
public DwarfAddressRangeTable AddressRangeTable
@@ -63,7 +63,7 @@ public override void Verify(DiagnosticBag diagnostics)
6363
{
6464
base.Verify(diagnostics);
6565

66-
LineTable.Verify(diagnostics);
66+
LineSection.Verify(diagnostics);
6767
AbbreviationTable.Verify(diagnostics);
6868
AddressRangeTable.Verify(diagnostics);
6969
StringTable.Verify(diagnostics);
@@ -77,8 +77,8 @@ public void UpdateLayout(DwarfLayoutConfig config, DiagnosticBag diagnostics)
7777

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

80-
LineTable.Offset = 0;
81-
LineTable.UpdateLayoutInternal(layoutContext);
80+
LineSection.Offset = 0;
81+
LineSection.UpdateLayoutInternal(layoutContext);
8282
if (layoutContext.HasErrors)
8383
{
8484
return;
@@ -142,9 +142,9 @@ public void Write(DwarfWriterContext writerContext)
142142
{
143143
writer.Stream.Position = 0;
144144
writer.Stream.SetLength(0);
145-
writer.CurrentSection = LineTable;
146-
LineTable.Relocations.Clear();
147-
LineTable.WriteInternal(writer);
145+
writer.CurrentSection = LineSection;
146+
LineSection.Relocations.Clear();
147+
LineSection.WriteInternal(writer);
148148
}
149149

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

@@ -248,17 +248,17 @@ public void WriteToElf(DwarfElfContext elfContext, DwarfLayoutConfig layoutConfi
248248
}
249249

250250
// Line table
251-
if (LineTable.Size > 0)
251+
if (LineSection.Size > 0)
252252
{
253253
writer.Stream = elfContext.GetOrCreateLineSection().Stream;
254254
writer.Stream.Position = 0;
255255
writer.Stream.SetLength(0);
256-
writer.CurrentSection = LineTable;
257-
LineTable.Relocations.Clear();
258-
LineTable.WriteInternal(writer);
259-
if (writer.EnableRelocation && LineTable.Relocations.Count > 0)
256+
writer.CurrentSection = LineSection;
257+
LineSection.Relocations.Clear();
258+
LineSection.WriteInternal(writer);
259+
if (writer.EnableRelocation && LineSection.Relocations.Count > 0)
260260
{
261-
LineTable.CopyRelocationsTo(elfContext, elfContext.GetOrCreateRelocLineSection());
261+
LineSection.CopyRelocationsTo(elfContext, elfContext.GetOrCreateRelocLineSection());
262262
}
263263
else
264264
{
@@ -347,8 +347,8 @@ public static DwarfFile Read(DwarfReaderContext readerContext)
347347
reader.Stream = readerContext.DebugLineStream;
348348
if (reader.Stream != null)
349349
{
350-
reader.CurrentSection = dwarf.LineTable;
351-
dwarf.LineTable.ReadInternal(reader);
350+
reader.CurrentSection = dwarf.LineSection;
351+
dwarf.LineSection.ReadInternal(reader);
352352
}
353353

354354
reader.Log = null;

0 commit comments

Comments
 (0)