Skip to content

Commit

Permalink
Add support for encoding location lists (#22)
Browse files Browse the repository at this point in the history
* WIP: Add support for encoding location lists

* Emit relocations for location lists

* Fix writing base address with relocations

* Add diagnostics and implement ToString on the new objects
  • Loading branch information
filipnavara authored Oct 21, 2022
1 parent f192089 commit 94a195e
Show file tree
Hide file tree
Showing 15 changed files with 503 additions and 38 deletions.
25 changes: 25 additions & 0 deletions src/LibObjectFile.Tests/Dwarf/DwarfTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,31 @@ public void CreateDwarf()
};
rootDIE.AddChild(subProgram);

var locationList = new DwarfLocationList();
var regExpression = new DwarfExpression();
regExpression.AddOperation(new DwarfOperation { Kind = DwarfOperationKindEx.Reg0 });
var regExpression2 = new DwarfExpression();
regExpression2.AddOperation(new DwarfOperation { Kind = DwarfOperationKindEx.Reg2 });
locationList.AddLocationListEntry(new DwarfLocationListEntry
{
Start = 0,
End = 0x10,
Expression = regExpression,
});
locationList.AddLocationListEntry(new DwarfLocationListEntry
{
Start = 0x10,
End = 0x20,
Expression = regExpression2,
});
var variable = new DwarfDIEVariable()
{
Name = "a",
Location = locationList,
};
dwarfFile.LocationSection.AddLocationList(locationList);
subProgram.AddChild(variable);

var cu = new DwarfCompilationUnit()
{
AddressSize = DwarfAddressSize.Bit64,
Expand Down
1 change: 1 addition & 0 deletions src/LibObjectFile/DiagnosticId.cs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ public enum DiagnosticId
DWARF_ERR_InvalidParentUnitForAddressRangeTable = 2017,
DWARF_ERR_InvalidParentForDIE = 2018,
DWARF_WRN_InvalidExtendedOpCodeLength = 2019,
DWARF_ERR_InvalidParentForLocationList = 2020,

}
}
47 changes: 45 additions & 2 deletions src/LibObjectFile/Dwarf/DwarfAttribute.cs
Original file line number Diff line number Diff line change
Expand Up @@ -88,13 +88,23 @@ public override void Verify(DiagnosticBag diagnostics)

if (thisSection != attrSection)
{
diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidParentForDIE, $"Invalid parent for the DIE {attrDIE} referenced by the attribute {this}. It must be within the same parent {attrSection.GetType()}.");
diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidParentForDIE, $"Invalid parent for the DIE {attrDIE} referenced by the attribute {this}. It must be within the same parent {thisSection.GetType()}.");
}
}
else if (ValueAsObject is DwarfExpression expr)
{
expr.Verify(diagnostics);
}
else if (ValueAsObject is DwarfLocationList locationList)
{
var thisSection = this.GetParentFile();
var locationListSection = locationList.GetParentFile();

if (thisSection != locationListSection)
{
diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidParentForLocationList, $"Invalid parent for the LocationList {locationList} referenced by the attribute {this}. It must be within the same parent {thisSection.GetType()}.");
}
}
}

public int CompareTo(DwarfAttribute other)
Expand Down Expand Up @@ -323,6 +333,23 @@ private void ResolveAttributeValue(DwarfReader reader)
break;

}

case DwarfAttributeKind.Location:
{
if (Form == DwarfAttributeFormEx.SecOffset)
{
if (reader.OffsetToLocationList.TryGetValue(ValueAsU64, out var locationList))
{
ValueAsU64 = 0;
ValueAsObject = locationList;
}
else
{
// Log and error
}
}
break;
}
}
}

Expand Down Expand Up @@ -600,6 +627,15 @@ private DwarfAttributeForm ComputeAttributeForm(DwarfLayoutContext context)

encoding = DwarfAttributeEncoding.ExpressionLocation;
}
else if (this.ValueAsObject is DwarfLocationList)
{
if ((encoding & DwarfAttributeEncoding.LocationList) == 0)
{
context.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"The expression value of attribute {this} from DIE {this.Parent} is not valid for supported attribute encoding {encoding}. Expecting LocationList.");
}

encoding = DwarfAttributeEncoding.LocationList;
}
else if ((encoding & DwarfAttributeEncoding.Address) != 0)
{
if (this.ValueAsObject != null)
Expand Down Expand Up @@ -896,7 +932,14 @@ protected override void Write(DwarfWriter writer)
// stroffsetsptr
case DwarfAttributeForm.SecOffset:
{
writer.WriteUIntFromEncoding(ValueAsU64);
if (ValueAsObject != null)
{
writer.WriteUIntFromEncoding(((DwarfObject) ValueAsObject).Offset);
}
else
{
writer.WriteUIntFromEncoding(ValueAsU64);
}
break;
}

Expand Down
4 changes: 2 additions & 2 deletions src/LibObjectFile/Dwarf/DwarfDIE.cs
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ protected void SetAttributeLocationOpt(DwarfAttributeKind kind, DwarfLocation? c
{
var value = cst.Value;
attr.ValueAsU64 = value.AsValue.U64;
attr.ValueAsObject = value.AsExpression;
attr.ValueAsObject = value.AsObject;
}
return;
}
Expand All @@ -260,7 +260,7 @@ protected void SetAttributeLocationOpt(DwarfAttributeKind kind, DwarfLocation? c
{
Kind = kind,
ValueAsU64 = value.AsValue.U64,
ValueAsObject = value.AsExpression
ValueAsObject = value.AsObject
});
}
}
Expand Down
49 changes: 48 additions & 1 deletion src/LibObjectFile/Dwarf/DwarfElfContext.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ public class DwarfElfContext
private int _abbreviationTableSymbolIndex;
private int _lineTableSymbolIndex;
private int _stringTableSymbolIndex;
private int _locationSectionSymbolIndex;
private readonly ElfSymbolTable _symbolTable;

public DwarfElfContext(ElfObjectFile elf)
Expand Down Expand Up @@ -78,6 +79,10 @@ public DwarfElfContext(ElfObjectFile elf)
LineTable = ((ElfBinarySection)section);
mapSectionToSymbolIndex.TryGetValue(LineTable, out _lineTableSymbolIndex);
break;
case ".debug_loc":
LocationSection = ((ElfBinarySection)section);
mapSectionToSymbolIndex.TryGetValue(LocationSection, out _locationSectionSymbolIndex);
break;

case ".rela.debug_aranges":
case ".rel.debug_aranges":
Expand All @@ -96,6 +101,12 @@ public DwarfElfContext(ElfObjectFile elf)
RelocInfoSection = (ElfRelocationTable)section;
RelocInfoSection.Relocate(relocContext);
break;

case ".rela.debug_loc":
case ".rel.debug_loc":
RelocLocationSection = (ElfRelocationTable)section;
RelocLocationSection.Relocate(relocContext);
break;
}
}
}
Expand All @@ -119,9 +130,13 @@ public DwarfElfContext(ElfObjectFile elf)
public ElfBinarySection StringTable { get; set; }

public ElfBinarySection LineTable { get; set; }

public ElfRelocationTable RelocLineTable { get; set; }

public ElfBinarySection LocationSection { get; private set; }

public ElfRelocationTable RelocLocationSection { get; set; }

public int CodeSectionSymbolIndex => _codeSectionSymbolIndex;

public int InfoSectionSymbolIndex => _infoSectionSymbolIndex;
Expand All @@ -132,6 +147,8 @@ public DwarfElfContext(ElfObjectFile elf)

public int LineTableSymbolIndex => _lineTableSymbolIndex;

public int LocationSectionSymbolIndex => _locationSectionSymbolIndex;

public ElfBinarySection GetOrCreateInfoSection()
{
return InfoSection ??= GetOrCreateDebugSection(".debug_info", true, out _infoSectionSymbolIndex);
Expand Down Expand Up @@ -172,6 +189,16 @@ public ElfBinarySection GetOrCreateStringTable()
return StringTable ??= GetOrCreateDebugSection(".debug_str", true, out _stringTableSymbolIndex);
}

public ElfBinarySection GetOrCreateLocationSection()
{
return LocationSection ??= GetOrCreateDebugSection(".debug_loc", true, out _locationSectionSymbolIndex);
}

public ElfRelocationTable GetOrCreateRelocLocationSection()
{
return RelocLocationSection ??= GetOrCreateRelocationTable(LocationSection);
}

public void RemoveStringTable()
{
if (StringTable != null)
Expand Down Expand Up @@ -250,6 +277,26 @@ public void RemoveRelocInfoSection()
}
}

public void RemoveLocationSection()
{
if (LocationSection != null)
{
Elf.RemoveSection(LocationSection);
LocationSection = null;
}

RemoveRelocLocationSection();
}

public void RemoveRelocLocationSection()
{
if (RelocLocationSection != null)
{
Elf.RemoveSection(RelocLocationSection);
RelocLocationSection = null;
}
}

private ElfBinarySection GetOrCreateDebugSection(string name, bool createSymbol, out int symbolIndex)
{
var newSection = new ElfBinarySection()
Expand Down
76 changes: 50 additions & 26 deletions src/LibObjectFile/Dwarf/DwarfExpression.cs
Original file line number Diff line number Diff line change
Expand Up @@ -51,32 +51,10 @@ public override void Verify(DiagnosticBag diagnostics)
}
}

protected override void UpdateLayout(DwarfLayoutContext layoutContext)
{
var endOffset = Offset;
foreach (var op in _operations)
{
op.Offset = endOffset;
op.UpdateLayoutInternal(layoutContext);
endOffset += op.Size;
}

OperationLengthInBytes = endOffset - Offset;

// We need to shift the expression which is prefixed by its size encoded in LEB128
var deltaLength = DwarfHelper.SizeOfULEB128(Size);
foreach (var op in InternalOperations)
{
op.Offset += deltaLength;
}

Size = OperationLengthInBytes + deltaLength;
}

protected override void Read(DwarfReader reader)
internal void ReadInternal(DwarfReader reader, bool inLocationSection = false)
{
Offset = reader.Offset;
var size = reader.ReadULEB128();
var size = inLocationSection ? reader.ReadU16() : reader.ReadULEB128();
OperationLengthInBytes = size;
var endPosition = reader.Offset + size;

Expand All @@ -90,12 +68,20 @@ protected override void Read(DwarfReader reader)
Size = reader.Offset - Offset;
}

protected override void Write(DwarfWriter writer)
internal void WriteInternal(DwarfWriter writer, bool inLocationSection = false)
{
Debug.Assert(Offset == writer.Offset);
Debug.Assert(!inLocationSection || OperationLengthInBytes <= ushort.MaxValue);

var startExpressionOffset = writer.Offset;
writer.WriteULEB128(OperationLengthInBytes);
if (inLocationSection)
{
writer.WriteU16((ushort)OperationLengthInBytes);
}
else
{
writer.WriteULEB128(OperationLengthInBytes);
}

foreach (var op in Operations)
{
Expand All @@ -104,5 +90,43 @@ protected override void Write(DwarfWriter writer)

Debug.Assert(writer.Offset - startExpressionOffset == Size);
}

internal void UpdateLayoutInternal(DwarfLayoutContext layoutContext, bool inLocationSection = false)
{
var endOffset = Offset;
foreach (var op in _operations)
{
op.Offset = endOffset;
op.UpdateLayoutInternal(layoutContext);
endOffset += op.Size;
}

OperationLengthInBytes = endOffset - Offset;

// We need to shift the expression which is prefixed by its size encoded in LEB128,
// or fixed-size U2 in .debug_loc section
var deltaLength = inLocationSection ? sizeof(ushort) : DwarfHelper.SizeOfULEB128(Size);
foreach (var op in InternalOperations)
{
op.Offset += deltaLength;
}

Size = OperationLengthInBytes + deltaLength;
}

protected override void UpdateLayout(DwarfLayoutContext layoutContext)
{
UpdateLayoutInternal(layoutContext, inLocationSection: false);
}

protected override void Read(DwarfReader reader)
{
ReadInternal(reader, inLocationSection: false);
}

protected override void Write(DwarfWriter writer)
{
WriteInternal(writer, inLocationSection: false);
}
}
}
Loading

0 comments on commit 94a195e

Please sign in to comment.