private static void WriteEncodedValue(DwarfWriter writer, DwarfOperationKindEx kind, ulong value, byte size) { writer.WriteU8(size); switch (size) { case 0: writer.WriteUInt(value); break; case 1: writer.WriteU8((byte)value); break; case 2: writer.WriteU16((ushort)value); break; case 4: writer.WriteU32((uint)value); break; case 8: writer.WriteU64(value); break; 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 Write(DwarfWriter writer) { var startOpOffset = Offset; Debug.Assert(startOpOffset == Offset); writer.WriteU8((byte)Kind); switch (Kind.Value) { case DwarfOperationKind.Addr: writer.WriteAddress(DwarfRelocationTarget.Code, Operand1.U64); break; case DwarfOperationKind.Const1u: case DwarfOperationKind.Const1s: case DwarfOperationKind.Pick: case DwarfOperationKind.DerefSize: case DwarfOperationKind.XderefSize: writer.WriteU8((byte)Operand1.U64); break; case DwarfOperationKind.Const2u: case DwarfOperationKind.Const2s: writer.WriteU16((ushort)Operand1.U64); break; case DwarfOperationKind.Const4u: case DwarfOperationKind.Const4s: writer.WriteU32((uint)Operand1.U64); break; case DwarfOperationKind.Const8u: case DwarfOperationKind.Const8s: writer.WriteU64(Operand1.U64); 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: writer.WriteULEB128(Operand1.U64); break; case DwarfOperationKind.Consts: case DwarfOperationKind.Fbreg: writer.WriteILEB128(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: break; case DwarfOperationKind.Bra: case DwarfOperationKind.Skip: writer.WriteU16((ushort)((long)Offset + 2 - (long)((DwarfOperation)Operand0).Offset)); break; 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: 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: writer.WriteILEB128(Operand2.I64); break; case DwarfOperationKind.Bregx: writer.WriteULEB128(Operand1.U64); writer.WriteILEB128(Operand2.I64); break; case DwarfOperationKind.Call2: writer.WriteU16((ushort)((DwarfDIE)Operand0).Offset); break; case DwarfOperationKind.Call4: writer.WriteU32((uint)((DwarfDIE)Operand0).Offset); break; case DwarfOperationKind.CallRef: writer.WriteUInt(((DwarfDIE)Operand0).Offset); break; case DwarfOperationKind.BitPiece: writer.WriteULEB128(Operand1.U64); writer.WriteULEB128(Operand2.U64); break; case DwarfOperationKind.ImplicitValue: { var stream = (Stream)Operand0; writer.WriteULEB128((ulong)stream.Position); writer.Write(stream); break; } case DwarfOperationKind.ImplicitPointer: case DwarfOperationKind.GNUImplicitPointer: { ulong offset = ((DwarfDIE)Operand0).Offset; // a reference to a debugging information entry that describes the dereferenced object’s value if (writer.CurrentUnit.Version == 2) { writer.WriteUInt(offset); } else { writer.WriteUIntFromEncoding(offset); } // a signed number that is treated as a byte offset from the start of that value writer.WriteILEB128(Operand1.I64); break; } case DwarfOperationKind.EntryValue: case DwarfOperationKind.GNUEntryValue: { var expression = (DwarfExpression)Operand0; writer.WriteULEB128(expression.Size); expression.WriteInternal(writer); 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 writer.WriteULEB128(((DwarfDIE)Operand0).Offset); WriteEncodedValue(writer, Kind, Operand1.U64, (byte)Operand2.U64); 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 writer.WriteULEB128(Operand1.U64); // The second operand is an unsigned LEB128 number that represents the offset // of a debugging information entry in the current compilation unit writer.WriteULEB128(((DwarfDIE)Operand0).Offset); 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 writer.WriteU8((byte)Operand1.U64); // The second operand is an unsigned LEB128 number that represents the offset // of a debugging information entry in the current compilation unit writer.WriteULEB128(((DwarfDIE)Operand0).Offset); break; } case DwarfOperationKind.Convert: case DwarfOperationKind.GNUConvert: case DwarfOperationKind.Reinterpret: case DwarfOperationKind.GNUReinterpret: writer.WriteULEB128(((DwarfDIE)Operand0).Offset); break; case DwarfOperationKind.GNUPushTlsAddress: case DwarfOperationKind.GNUUninit: break; case DwarfOperationKind.GNUEncodedAddr: WriteEncodedValue(writer, Kind, Operand1.U64, (byte)Operand2.U64); break; case DwarfOperationKind.GNUParameterRef: writer.WriteU32((uint)Operand1.U64); break; default: throw new NotSupportedException($"The {nameof(DwarfOperationKind)} {Kind} is not supported"); } Debug.Assert(writer.Offset - startOpOffset == Size); }