in src/BinaryParsers/ElfBinary/Dwarf/DwarfCompilationUnit.cs [60:401]
private void ReadData(IDwarfBinary dwarfBinary, DwarfMemoryReader debugData, DwarfMemoryReader debugDataDescription, DwarfMemoryReader debugStrings, NormalizeAddressDelegate addressNormalizer)
{
// Read header
int beginPosition = debugData.Position;
ulong length = debugData.ReadLength(out bool is64bit);
int endPosition = debugData.Position + (int)length;
NextOffset = endPosition;
ushort version = debugData.ReadUshort();
byte addressSize;
int debugDataDescriptionOffset;
dwarfBinary.DwarfVersion = version;
if (version == 5)
{
dwarfBinary.DwarfUnitType = (DwarfUnitType)(debugData.ReadByte());
addressSize = debugData.ReadByte();
debugDataDescriptionOffset = debugData.ReadOffset(is64bit);
if (dwarfBinary.DwarfUnitType == DwarfUnitType.Skeleton || dwarfBinary.DwarfUnitType == DwarfUnitType.SplitCompile)
{
debugData.ReadUlong();
}
}
else if (version > 0 && version < 5)
{
debugDataDescriptionOffset = debugData.ReadOffset(is64bit);
addressSize = debugData.ReadByte();
}
else
{
return;
}
DataDescriptionReader dataDescriptionReader = new DataDescriptionReader(debugDataDescription, debugDataDescriptionOffset);
// Read data
List<DwarfSymbol> symbols = new List<DwarfSymbol>();
Stack<DwarfSymbol> parents = new Stack<DwarfSymbol>();
while (debugData.Position < endPosition)
{
int dataPosition = debugData.Position;
uint code = debugData.LEB128();
if (code == 0)
{
if (parents.Count > 0)
{
parents.Pop();
}
continue;
}
DataDescription description = dataDescriptionReader.GetDebugDataDescription(code);
Dictionary<DwarfAttribute, DwarfAttributeValue> attributes = new Dictionary<DwarfAttribute, DwarfAttributeValue>();
if (description.Attributes.Any(a => a.Attribute == DwarfAttribute.LinkageName && a.Format == DwarfFormat.Strp))
{
description.Attributes.RemoveAll(a => a.Attribute == DwarfAttribute.Name);
}
foreach (DataDescriptionAttribute descriptionAttribute in description.Attributes)
{
DwarfAttribute attribute = descriptionAttribute.Attribute;
DwarfFormat format = descriptionAttribute.Format;
DwarfAttributeValue attributeValue = new DwarfAttributeValue();
switch (format)
{
case DwarfFormat.Address:
attributeValue.Type = DwarfAttributeValueType.Address;
attributeValue.Value = debugData.ReadUlong(addressSize);
break;
case DwarfFormat.Block:
attributeValue.Type = DwarfAttributeValueType.Block;
attributeValue.Value = debugData.ReadBlock(debugData.LEB128());
break;
case DwarfFormat.Block1:
attributeValue.Type = DwarfAttributeValueType.Block;
attributeValue.Value = debugData.ReadBlock(debugData.ReadByte());
break;
case DwarfFormat.Block2:
attributeValue.Type = DwarfAttributeValueType.Block;
attributeValue.Value = debugData.ReadBlock(debugData.ReadUshort());
break;
case DwarfFormat.Block4:
attributeValue.Type = DwarfAttributeValueType.Block;
attributeValue.Value = debugData.ReadBlock(debugData.ReadUint());
break;
case DwarfFormat.Data1:
attributeValue.Type = DwarfAttributeValueType.Constant;
attributeValue.Value = (ulong)debugData.ReadByte();
break;
case DwarfFormat.Data2:
attributeValue.Type = DwarfAttributeValueType.Constant;
attributeValue.Value = (ulong)debugData.ReadUshort();
break;
case DwarfFormat.Data4:
attributeValue.Type = DwarfAttributeValueType.Constant;
attributeValue.Value = (ulong)debugData.ReadUint();
break;
case DwarfFormat.Data8:
attributeValue.Type = DwarfAttributeValueType.Constant;
attributeValue.Value = (ulong)debugData.ReadUlong();
break;
case DwarfFormat.SData:
attributeValue.Type = DwarfAttributeValueType.Constant;
attributeValue.Value = (ulong)debugData.SLEB128();
break;
case DwarfFormat.UData:
attributeValue.Type = DwarfAttributeValueType.Constant;
attributeValue.Value = (ulong)debugData.LEB128();
break;
case DwarfFormat.String:
attributeValue.Type = DwarfAttributeValueType.String;
attributeValue.Value = debugData.ReadString();
break;
case DwarfFormat.Strp:
attributeValue.Type = DwarfAttributeValueType.String;
int offsetStrp = debugData.ReadOffset(is64bit);
attributeValue.Value = debugStrings.ReadString(offsetStrp);
break;
case DwarfFormat.Flag:
attributeValue.Type = DwarfAttributeValueType.Flag;
attributeValue.Value = debugData.ReadByte() != 0;
break;
case DwarfFormat.FlagPresent:
attributeValue.Type = DwarfAttributeValueType.Flag;
attributeValue.Value = true;
break;
case DwarfFormat.Ref1:
attributeValue.Type = DwarfAttributeValueType.Reference;
attributeValue.Value = (ulong)debugData.ReadByte() + (ulong)beginPosition;
break;
case DwarfFormat.Ref2:
attributeValue.Type = DwarfAttributeValueType.Reference;
attributeValue.Value = (ulong)debugData.ReadUshort() + (ulong)beginPosition;
break;
case DwarfFormat.Ref4:
attributeValue.Type = DwarfAttributeValueType.Reference;
attributeValue.Value = (ulong)debugData.ReadUint() + (ulong)beginPosition;
break;
case DwarfFormat.Ref8:
attributeValue.Type = DwarfAttributeValueType.Reference;
attributeValue.Value = (ulong)debugData.ReadUlong() + (ulong)beginPosition;
break;
case DwarfFormat.RefUData:
attributeValue.Type = DwarfAttributeValueType.Reference;
attributeValue.Value = (ulong)debugData.LEB128() + (ulong)beginPosition;
break;
case DwarfFormat.RefAddr:
attributeValue.Type = DwarfAttributeValueType.Reference;
attributeValue.Value = (ulong)debugData.ReadOffset(is64bit);
break;
case DwarfFormat.RefSig8:
attributeValue.Type = DwarfAttributeValueType.Invalid;
debugData.Position += 8;
break;
case DwarfFormat.ExpressionLocation:
attributeValue.Type = DwarfAttributeValueType.ExpressionLocation;
attributeValue.Value = debugData.ReadBlock(debugData.LEB128());
break;
case DwarfFormat.SecOffset:
attributeValue.Type = DwarfAttributeValueType.SecOffset;
attributeValue.Value = (ulong)debugData.ReadOffset(is64bit);
break;
case DwarfFormat.ImplicitConst:
break;
case DwarfFormat.Strx:
case DwarfFormat.GNUStrIndex:
attributeValue.Type = DwarfAttributeValueType.String;
attributeValue.Value = (ulong)debugData.LEB128() + (ulong)beginPosition;
break;
case DwarfFormat.Addrx:
attributeValue.Type = DwarfAttributeValueType.String;
attributeValue.Value = (ulong)debugData.LEB128() + (ulong)beginPosition;
break;
case DwarfFormat.Indirect:
break;
case DwarfFormat.GNUAddrIndex:
break;
default:
break;
}
if (attributes.ContainsKey(attribute))
{
if (attributes[attribute] != attributeValue)
{
attributes[attribute] = attributeValue;
}
}
else
{
attributes.Add(attribute, attributeValue);
}
}
DwarfSymbol symbol = new DwarfSymbol()
{
Tag = description.Tag,
Attributes = attributes,
Offset = dataPosition,
};
symbolsByOffset.Add(symbol.Offset, symbol);
if (parents.Count > 0)
{
parents.Peek().Children.Add(symbol);
symbol.Parent = parents.Peek();
}
else
{
symbols.Add(symbol);
}
if (description.HasChildren)
{
symbol.Children = new List<DwarfSymbol>();
parents.Push(symbol);
}
break;
}
SymbolsTree = symbols.ToArray();
if (SymbolsTree.Length > 0)
{
// Add void type symbol
DwarfSymbol voidSymbol = new DwarfSymbol()
{
Tag = DwarfTag.BaseType,
Offset = -1,
Parent = SymbolsTree[0],
Attributes = new Dictionary<DwarfAttribute, DwarfAttributeValue>()
{
{ DwarfAttribute.Name, new DwarfAttributeValue() { Type = DwarfAttributeValueType.String, Value = "void" } },
{ DwarfAttribute.ByteSize, new DwarfAttributeValue() { Type = DwarfAttributeValueType.Constant, Value = (ulong)0 } },
},
};
if (SymbolsTree[0].Children == null)
{
SymbolsTree[0].Children = new List<DwarfSymbol>();
}
SymbolsTree[0].Children.Insert(0, voidSymbol);
symbolsByOffset.Add(voidSymbol.Offset, voidSymbol);
// Post process all symbols
foreach (DwarfSymbol symbol in Symbols)
{
Dictionary<DwarfAttribute, DwarfAttributeValue> attributes = symbol.Attributes as Dictionary<DwarfAttribute, DwarfAttributeValue>;
if (attributes != null)
{
foreach (DwarfAttributeValue value in attributes.Values)
{
if (value.Type == DwarfAttributeValueType.Reference)
{
if (symbolsByOffset.TryGetValue((int)value.Address, out DwarfSymbol reference))
{
value.Type = DwarfAttributeValueType.ResolvedReference;
value.Value = reference;
}
}
else if (value.Type == DwarfAttributeValueType.Address)
{
value.Value = addressNormalizer(value.Address);
}
}
if ((symbol.Tag == DwarfTag.PointerType && !attributes.ContainsKey(DwarfAttribute.Type))
|| (symbol.Tag == DwarfTag.Typedef && !attributes.ContainsKey(DwarfAttribute.Type)))
{
attributes.Add(DwarfAttribute.Type, new DwarfAttributeValue()
{
Type = DwarfAttributeValueType.ResolvedReference,
Value = voidSymbol,
});
}
}
}
// Merge specifications
foreach (DwarfSymbol symbol in Symbols)
{
Dictionary<DwarfAttribute, DwarfAttributeValue> attributes = symbol.Attributes as Dictionary<DwarfAttribute, DwarfAttributeValue>;
if (attributes != null)
{
if (attributes.TryGetValue(DwarfAttribute.Specification, out DwarfAttributeValue specificationValue) && specificationValue.Type == DwarfAttributeValueType.ResolvedReference)
{
DwarfSymbol reference = specificationValue.Reference;
Dictionary<DwarfAttribute, DwarfAttributeValue> referenceAttributes = reference.Attributes as Dictionary<DwarfAttribute, DwarfAttributeValue>;
if (referenceAttributes != null)
{
foreach (KeyValuePair<DwarfAttribute, DwarfAttributeValue> kvp in attributes)
{
if (kvp.Key != DwarfAttribute.Specification)
{
referenceAttributes[kvp.Key] = kvp.Value;
}
}
}
}
}
}
}
}