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;
        }
Exemple #4
0
        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);
        }
Exemple #5
0
        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;
        }
Exemple #7
0
        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);
        }
Exemple #9
0
        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;
        }