protected override void UpdateLayout(DwarfLayoutContext layoutContext) { ulong sizeOf = 0; // unit_length sizeOf += DwarfHelper.SizeOfUnitLength(Is64BitEncoding); // version sizeOf += 2; // debug_info_offset sizeOf += DwarfHelper.SizeOfUInt(Is64BitEncoding); // Address size sizeOf += 1; // segment selector size sizeOf += 1; var align = (ulong)SegmentSelectorSize + (ulong)AddressSize * 2; // SPECS 7.21: The first tuple following the header in each set begins at an offset that is a multiple of the size of a single tuple sizeOf = AlignHelper.AlignToUpper(sizeOf, align); // SizeOf ranges + 1 (for last 0 entry) sizeOf += ((ulong)Ranges.Count + 1UL) * align; Size = sizeOf; if (Unit != null) { DebugInfoOffset = Unit.Offset; } }
protected override void UpdateLayout(DwarfLayoutContext layoutContext) { var endOffset = Offset; if (_mapItems.Count > 0) { foreach (var itemPair in _mapItems) { var item = itemPair.Value; item.Offset = endOffset; item.UpdateLayoutInternal(layoutContext); endOffset += item.Size; } } else { if (_items.Count > 0) { foreach (var item in _items) { item.Offset = endOffset; item.UpdateLayoutInternal(layoutContext); endOffset += item.Size; } } } endOffset += DwarfHelper.SizeOfULEB128(0); Size = endOffset - Offset; }
protected override void UpdateLayout(DwarfLayoutContext layoutContext) { var endOffset = Offset; // Code endOffset += DwarfHelper.SizeOfULEB128(Code); // Tag endOffset += DwarfHelper.SizeOfULEB128((uint)Tag.Value); // HasChildren endOffset += 1; var descriptors = Descriptors; for (int i = 0; i < descriptors.Length; i++) { var descriptor = descriptors[i]; endOffset += DwarfHelper.SizeOfULEB128((uint)descriptor.Kind.Value); endOffset += DwarfHelper.SizeOfULEB128((uint)descriptor.Form.Value); } // Null Kind and Form endOffset += DwarfHelper.SizeOfULEB128(0) * 2; Size = endOffset - Offset; }
private ulong SizeOfDIEReference(DwarfLayoutContext context) { if (Operand0 == null) { return(DwarfHelper.SizeOfULEB128(0)); } else if (Operand0 is DwarfDIE die) { // TODO: check that die reference is within this section if (die.Offset < Offset) { return(DwarfHelper.SizeOfULEB128(die.Offset)); } else { // TODO: encode depending on Context.DefaultAttributeFormForReference return(DwarfHelper.SizeOfILEB128(uint.MaxValue)); } } else { context.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"The object operand of {Kind} operation {this} must be a {nameof(DwarfDIE)} instead of {Operand0.GetType()}."); } return(0U); }
public static void Print(this DwarfDIE die, TextWriter writer, int level = 0) { if (writer == null) { throw new ArgumentNullException(nameof(writer)); } writer.WriteLine($" <{level}><{die.Offset:x}>: Abbrev Number: {die.Abbrev.Code} ({die.Tag})"); foreach (var attr in die.Attributes) { string attrValue = null; switch (attr.ValueAsObject) { case DwarfDIE dieRef: attrValue = $"<0x{dieRef.Offset:x}>"; break; case string str: attrValue = str; break; case DwarfExpression expr: attrValue = $"{expr.Operations.Count} OpCodes ({string.Join(", ", expr.Operations.Select(x => x.Kind))})"; break; } switch (attr.Kind.Value) { case DwarfAttributeKind.Language: attrValue = $"{attr.ValueAsU64} {GetLanguageKind((DwarfLanguageKind)attr.ValueAsU64)}"; break; } if (attrValue == null) { var encoding = DwarfHelper.GetAttributeEncoding(attr.Kind); if ((encoding & DwarfAttributeEncoding.Address) != 0) { attrValue = $"0x{attr.ValueAsU64:x}"; } else { attrValue = $"{attr.ValueAsU64}"; } } writer.WriteLine($" <{attr.Offset:x}> {attr.Kind,-18} : {attrValue}"); } foreach (var child in die.Children) { Print(child, writer, level + 1); } }
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; }
private ulong SizeOfEncodedValue(DwarfOperationKindEx kind, ulong value, byte size, DwarfAddressSize addressSize) { switch (size) { case 0: return(1 + DwarfHelper.SizeOfUInt(addressSize)); case 1: return(1 + 1); case 2: return(1 + 2); case 4: return(1 + 4); case 8: return(1 + 8); default: // TODO: report via diagnostics in Verify throw new InvalidOperationException($"Invalid Encoded address size {size} for {kind}"); } }
protected override void Write(DwarfWriter writer) { var startOffset = writer.Offset; // unit_length writer.WriteUnitLength(Size - DwarfHelper.SizeOfUnitLength(Is64BitEncoding)); // version writer.WriteU16(Version); // debug_info_offset var debugInfoOffset = DebugInfoOffset; if (writer.EnableRelocation) { writer.RecordRelocation(DwarfRelocationTarget.DebugInfo, writer.SizeOfUIntEncoding(), debugInfoOffset); debugInfoOffset = 0; } writer.WriteUIntFromEncoding(debugInfoOffset); // address_size writer.AddressSize = AddressSize; writer.WriteU8((byte)AddressSize); writer.WriteU8((byte)SegmentSelectorSize); var align = (ulong)SegmentSelectorSize + (ulong)AddressSize * 2; // SPECS 7.21: The first tuple following the header in each set begins at an offset that is a multiple of the size of a single tuple var nextOffset = AlignHelper.AlignToUpper(writer.Offset, align); for (ulong offset = writer.Offset; offset < nextOffset; offset++) { writer.WriteU8(0); } Debug.Assert(writer.Offset == nextOffset); foreach (var range in Ranges) { if (SegmentSelectorSize != 0) { switch (SegmentSelectorSize) { case DwarfAddressSize.Bit8: writer.WriteU8((byte)range.Segment); break; case DwarfAddressSize.Bit16: writer.WriteU16((ushort)range.Segment); break; case DwarfAddressSize.Bit32: writer.WriteU32((uint)range.Segment); break; case DwarfAddressSize.Bit64: writer.WriteU64((ulong)range.Segment); break; } } writer.WriteAddress(DwarfRelocationTarget.Code, range.Address); writer.WriteUInt(range.Length); } if (SegmentSelectorSize != 0) { switch (SegmentSelectorSize) { case DwarfAddressSize.Bit8: writer.WriteU8(0); break; case DwarfAddressSize.Bit16: writer.WriteU16(0); break; case DwarfAddressSize.Bit32: writer.WriteU32(0); break; case DwarfAddressSize.Bit64: writer.WriteU64(0); break; } } switch (AddressSize) { case DwarfAddressSize.Bit8: writer.WriteU16(0); break; case DwarfAddressSize.Bit16: writer.WriteU32(0); break; case DwarfAddressSize.Bit32: writer.WriteU64(0); break; case DwarfAddressSize.Bit64: writer.WriteU64(0); writer.WriteU64(0); break; } Debug.Assert(writer.Offset - startOffset == Size); }
protected override void UpdateLayout(DwarfLayoutContext layoutContext) { var endOffset = Offset; // 1 byte per opcode endOffset += 1; switch (Kind.Value) { case DwarfOperationKind.Addr: endOffset += DwarfHelper.SizeOfUInt(layoutContext.CurrentUnit.AddressSize); break; case DwarfOperationKind.Const1u: case DwarfOperationKind.Const1s: case DwarfOperationKind.Pick: case DwarfOperationKind.DerefSize: case DwarfOperationKind.XderefSize: endOffset += 1; break; case DwarfOperationKind.Const2u: case DwarfOperationKind.Const2s: case DwarfOperationKind.Bra: case DwarfOperationKind.Skip: case DwarfOperationKind.Call2: endOffset += 2; break; case DwarfOperationKind.Const4u: case DwarfOperationKind.Const4s: case DwarfOperationKind.Call4: endOffset += 4; break; case DwarfOperationKind.Const8u: case DwarfOperationKind.Const8s: endOffset += 8; break; case DwarfOperationKind.Constu: case DwarfOperationKind.PlusUconst: case DwarfOperationKind.Regx: case DwarfOperationKind.Piece: case DwarfOperationKind.Addrx: case DwarfOperationKind.GNUAddrIndex: case DwarfOperationKind.Constx: case DwarfOperationKind.GNUConstIndex: endOffset += DwarfHelper.SizeOfULEB128(Operand1.U64); break; case DwarfOperationKind.Consts: case DwarfOperationKind.Fbreg: endOffset += DwarfHelper.SizeOfILEB128(Operand1.I64); break; case DwarfOperationKind.Deref: case DwarfOperationKind.Dup: case DwarfOperationKind.Drop: case DwarfOperationKind.Over: case DwarfOperationKind.Swap: case DwarfOperationKind.Rot: case DwarfOperationKind.Xderef: case DwarfOperationKind.Abs: case DwarfOperationKind.And: case DwarfOperationKind.Div: case DwarfOperationKind.Minus: case DwarfOperationKind.Mod: case DwarfOperationKind.Mul: case DwarfOperationKind.Neg: case DwarfOperationKind.Not: case DwarfOperationKind.Or: case DwarfOperationKind.Plus: case DwarfOperationKind.Shl: case DwarfOperationKind.Shr: case DwarfOperationKind.Shra: case DwarfOperationKind.Xor: case DwarfOperationKind.Eq: case DwarfOperationKind.Ge: case DwarfOperationKind.Gt: case DwarfOperationKind.Le: case DwarfOperationKind.Lt: case DwarfOperationKind.Ne: case DwarfOperationKind.Nop: case DwarfOperationKind.PushObjectAddress: case DwarfOperationKind.FormTlsAddress: case DwarfOperationKind.CallFrameCfa: case DwarfOperationKind.Lit0: case DwarfOperationKind.Lit1: case DwarfOperationKind.Lit2: case DwarfOperationKind.Lit3: case DwarfOperationKind.Lit4: case DwarfOperationKind.Lit5: case DwarfOperationKind.Lit6: case DwarfOperationKind.Lit7: case DwarfOperationKind.Lit8: case DwarfOperationKind.Lit9: case DwarfOperationKind.Lit10: case DwarfOperationKind.Lit11: case DwarfOperationKind.Lit12: case DwarfOperationKind.Lit13: case DwarfOperationKind.Lit14: case DwarfOperationKind.Lit15: case DwarfOperationKind.Lit16: case DwarfOperationKind.Lit17: case DwarfOperationKind.Lit18: case DwarfOperationKind.Lit19: case DwarfOperationKind.Lit20: case DwarfOperationKind.Lit21: case DwarfOperationKind.Lit22: case DwarfOperationKind.Lit23: case DwarfOperationKind.Lit24: case DwarfOperationKind.Lit25: case DwarfOperationKind.Lit26: case DwarfOperationKind.Lit27: case DwarfOperationKind.Lit28: case DwarfOperationKind.Lit29: case DwarfOperationKind.Lit30: case DwarfOperationKind.Lit31: case DwarfOperationKind.Reg0: case DwarfOperationKind.Reg1: case DwarfOperationKind.Reg2: case DwarfOperationKind.Reg3: case DwarfOperationKind.Reg4: case DwarfOperationKind.Reg5: case DwarfOperationKind.Reg6: case DwarfOperationKind.Reg7: case DwarfOperationKind.Reg8: case DwarfOperationKind.Reg9: case DwarfOperationKind.Reg10: case DwarfOperationKind.Reg11: case DwarfOperationKind.Reg12: case DwarfOperationKind.Reg13: case DwarfOperationKind.Reg14: case DwarfOperationKind.Reg15: case DwarfOperationKind.Reg16: case DwarfOperationKind.Reg17: case DwarfOperationKind.Reg18: case DwarfOperationKind.Reg19: case DwarfOperationKind.Reg20: case DwarfOperationKind.Reg21: case DwarfOperationKind.Reg22: case DwarfOperationKind.Reg23: case DwarfOperationKind.Reg24: case DwarfOperationKind.Reg25: case DwarfOperationKind.Reg26: case DwarfOperationKind.Reg27: case DwarfOperationKind.Reg28: case DwarfOperationKind.Reg29: case DwarfOperationKind.Reg30: case DwarfOperationKind.Reg31: case DwarfOperationKind.StackValue: case DwarfOperationKind.GNUPushTlsAddress: case DwarfOperationKind.GNUUninit: break; case DwarfOperationKind.Breg0: case DwarfOperationKind.Breg1: case DwarfOperationKind.Breg2: case DwarfOperationKind.Breg3: case DwarfOperationKind.Breg4: case DwarfOperationKind.Breg5: case DwarfOperationKind.Breg6: case DwarfOperationKind.Breg7: case DwarfOperationKind.Breg8: case DwarfOperationKind.Breg9: case DwarfOperationKind.Breg10: case DwarfOperationKind.Breg11: case DwarfOperationKind.Breg12: case DwarfOperationKind.Breg13: case DwarfOperationKind.Breg14: case DwarfOperationKind.Breg15: case DwarfOperationKind.Breg16: case DwarfOperationKind.Breg17: case DwarfOperationKind.Breg18: case DwarfOperationKind.Breg19: case DwarfOperationKind.Breg20: case DwarfOperationKind.Breg21: case DwarfOperationKind.Breg22: case DwarfOperationKind.Breg23: case DwarfOperationKind.Breg24: case DwarfOperationKind.Breg25: case DwarfOperationKind.Breg26: case DwarfOperationKind.Breg27: case DwarfOperationKind.Breg28: case DwarfOperationKind.Breg29: case DwarfOperationKind.Breg30: case DwarfOperationKind.Breg31: endOffset += DwarfHelper.SizeOfILEB128(Operand2.I64); break; case DwarfOperationKind.Bregx: endOffset += DwarfHelper.SizeOfULEB128(Operand1.U64); endOffset += DwarfHelper.SizeOfILEB128(Operand2.I64); break; case DwarfOperationKind.CallRef: endOffset += DwarfHelper.SizeOfUInt(layoutContext.CurrentUnit.AddressSize); break; case DwarfOperationKind.BitPiece: endOffset += DwarfHelper.SizeOfULEB128(Operand1.U64); endOffset += DwarfHelper.SizeOfULEB128(Operand2.U64); break; case DwarfOperationKind.ImplicitValue: if (Operand0 == null) { layoutContext.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"The object operand of implicit value operation {this} from DIE cannot be null."); } else if (Operand0 is Stream stream) { var streamSize = (ulong)stream.Length; endOffset += DwarfHelper.SizeOfULEB128(streamSize); endOffset += streamSize; } else { layoutContext.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"The object operand of implicit value operation {this} must be a System.IO.Stream."); } break; case DwarfOperationKind.ImplicitPointer: case DwarfOperationKind.GNUImplicitPointer: // a reference to a debugging information entry that describes the dereferenced object’s value if (layoutContext.CurrentUnit.Version == 2) { endOffset += DwarfHelper.SizeOfUInt(layoutContext.CurrentUnit.AddressSize); } else { endOffset += DwarfHelper.SizeOfUInt(layoutContext.CurrentUnit.Is64BitEncoding); } // a signed number that is treated as a byte offset from the start of that value endOffset += DwarfHelper.SizeOfILEB128(Operand1.I64); break; case DwarfOperationKind.EntryValue: case DwarfOperationKind.GNUEntryValue: if (Operand0 == null) { endOffset += DwarfHelper.SizeOfULEB128(0); } else if (Operand0 is DwarfExpression expr) { expr.Offset = endOffset; expr.UpdateLayoutInternal(layoutContext); endOffset += DwarfHelper.SizeOfULEB128(expr.Size); } else { layoutContext.Diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"The object operand of EntryValue operation {this} must be a {nameof(DwarfExpression)} instead of {Operand0.GetType()}."); } break; case DwarfOperationKind.ConstType: case DwarfOperationKind.GNUConstType: { // The DW_OP_const_type operation takes three operands // The first operand is an unsigned LEB128 integer that represents the offset // of a debugging information entry in the current compilation unit, which // must be a DW_TAG_base_type entry that provides the type of the constant provided endOffset += SizeOfDIEReference(layoutContext); endOffset += SizeOfEncodedValue(Kind, Operand1.U64, (byte)Operand2.U64, layoutContext.CurrentUnit.AddressSize); break; } case DwarfOperationKind.RegvalType: case DwarfOperationKind.GNURegvalType: { // The DW_OP_regval_type operation provides the contents of a given register // interpreted as a value of a given type // The first operand is an unsigned LEB128 number, which identifies a register // whose contents is to be pushed onto the stack endOffset += DwarfHelper.SizeOfULEB128(Operand1.U64); // The second operand is an unsigned LEB128 number that represents the offset // of a debugging information entry in the current compilation unit endOffset += SizeOfDIEReference(layoutContext); break; } case DwarfOperationKind.DerefType: case DwarfOperationKind.GNUDerefType: case DwarfOperationKind.XderefType: { // The DW_OP_deref_type operation behaves like the DW_OP_deref_size operation: // it pops the top stack entry and treats it as an address. // This operand is a 1-byte unsigned integral constant whose value which is the // same as the size of the base type referenced by the second operand endOffset += 1; // The second operand is an unsigned LEB128 number that represents the offset // of a debugging information entry in the current compilation unit endOffset += SizeOfDIEReference(layoutContext); break; } case DwarfOperationKind.Convert: case DwarfOperationKind.GNUConvert: case DwarfOperationKind.Reinterpret: case DwarfOperationKind.GNUReinterpret: endOffset += SizeOfDIEReference(layoutContext); break; case DwarfOperationKind.GNUEncodedAddr: endOffset += SizeOfEncodedValue(Kind, Operand1.U64, (byte)Operand2.U64, layoutContext.CurrentUnit.AddressSize); break; case DwarfOperationKind.GNUParameterRef: endOffset += 4; break; default: throw new NotSupportedException($"The {nameof(DwarfOperationKind)} {Kind} is not supported"); } Size = endOffset - Offset; }