internal static bool IsAr(Stream stream, DiagnosticBag diagnostics)
        {
            Span <byte> magic       = stackalloc byte[ArArchiveFile.Magic.Length];
            int         magicLength = stream.Read(magic);

            if (magicLength != magic.Length)
            {
                if (diagnostics != null)
                {
                    diagnostics.Error(DiagnosticId.AR_ERR_InvalidMagicLength, $"Invalid length {magicLength} while trying to read !<arch> from stream while expecting at least {magic.Length} bytes");
                }
                return(false);
            }

            if (!magic.SequenceEqual(ArArchiveFile.Magic))
            {
                if (diagnostics != null)
                {
                    diagnostics.Error(DiagnosticId.AR_ERR_MagicNotFound, $"Magic !<arch>\\n not found");
                }
                return(false);
            }

            return(true);
        }
        public bool TryGetSectionSafe <TSection>(string className, string propertyName, object context, DiagnosticBag diagnostics, out TSection section, params ElfSectionType[] sectionTypes) where TSection : ElfSection
        {
            section = null;

            if (Section == null)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_LinkOrInfoSectionNull, $"`{className}.{propertyName}` cannot be null for this instance", context);
                return(false);
            }

            bool foundValid = false;

            foreach (var elfSectionType in sectionTypes)
            {
                if (Section.Type == elfSectionType)
                {
                    foundValid = true;
                    break;
                }
            }

            if (!foundValid)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_LinkOrInfoInvalidSectionType, $"The type `{Section.Type}` of `{className}.{propertyName}` must be a {string.Join(" or ", sectionTypes)}", context);
                return(false);
            }
            section = Section as TSection;

            if (section == null)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_LinkOrInfoInvalidSectionInstance, $"The `{className}.{propertyName}` must be an instance of {typeof(TSection).Name}");
                return(false);
            }
            return(true);
        }
Beispiel #3
0
        public override void Verify(DiagnosticBag diagnostics)
        {
            if (diagnostics == null)
            {
                throw new ArgumentNullException(nameof(diagnostics));
            }

            for (var i = 0; i < Files.Count; i++)
            {
                var item = Files[i];
                if (item.Name == null)
                {
                    diagnostics.Error(DiagnosticId.AR_ERR_InvalidNullFileEntryName, $"Invalid null FileName for file entry [{i}] in {this}");
                }
                else if (Kind == ArArchiveKind.Common)
                {
                    var count = Encoding.UTF8.GetByteCount(item.Name);
                    if (count > ArFile.FieldNameLength)
                    {
                        diagnostics.Error(DiagnosticId.AR_ERR_InvalidFileEntryNameTooLong, $"Invalid length ({count} bytes) for file entry [{i}] {item.Name} in {this}. Must be <= {ArFile.FieldNameLength} for {Kind} ar file");
                    }
                }

                item.Verify(diagnostics);
            }
        }
        /// <summary>
        /// Tries to copy from an ident array as found in ELF header <see cref="Elf32_Ehdr.e_ident"/> to this ELF object file instance.
        /// or <see cref="Elf64_Ehdr.e_ident"/>.
        /// </summary>
        /// <param name="objectFile">The object file to receive the ident from.</param>
        /// <param name="ident">A span to read from. Must be >= 16 bytes length</param>
        /// <param name="diagnostics">The diagnostics</param>
        /// <returns><c>true</c> if copying the ident was successful. <c>false</c> otherwise</returns>
        public static bool TryCopyIdentFrom(this ElfObjectFile objectFile, ReadOnlySpan <byte> ident, DiagnosticBag diagnostics)
        {
            if (objectFile == null)
            {
                throw new ArgumentNullException(nameof(objectFile));
            }
            if (ident.Length < EI_NIDENT)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_InvalidHeaderIdentLength, $"Invalid ELF Ident length found. Must be >= {EI_NIDENT}");
                return(false);
            }

            if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_InvalidHeaderMagic, "Invalid ELF Magic found");
                return(false);
            }

            objectFile.FileClass  = (ElfFileClass)ident[EI_CLASS];
            objectFile.Encoding   = (ElfEncoding)ident[EI_DATA];
            objectFile.Version    = ident[EI_VERSION];
            objectFile.OSABI      = new ElfOSABI(ident[EI_OSABI]);
            objectFile.AbiVersion = ident[EI_ABIVERSION];
            return(true);
        }
        /// <summary>
        /// Tries to copy from an ident array as found in ELF header <see cref="Elf32_Ehdr.e_ident"/> to this ELF object file instance.
        /// or <see cref="Elf64_Ehdr.e_ident"/>.
        /// </summary>
        /// <param name="objectFile">The object file to receive the ident from.</param>
        /// <param name="ident">A span to read from. Must be >= 16 bytes length</param>
        /// <param name="diagnostics">The diagnostics</param>
        /// <returns><c>true</c> if copying the ident was successful. <c>false</c> otherwise</returns>
        public static bool TryCopyIdentFrom(this ElfObjectFile objectFile, ReadOnlySpan <byte> ident, DiagnosticBag diagnostics)
        {
            if (objectFile == null)
            {
                throw new ArgumentNullException(nameof(objectFile));
            }
            if (ident.Length < EI_NIDENT)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_InvalidHeaderIdentLength, $"Invalid ELF Ident length found. Must be >= {EI_NIDENT}");
                return(false);
            }

            if (ident[EI_MAG0] != ELFMAG0 || ident[EI_MAG1] != ELFMAG1 || ident[EI_MAG2] != ELFMAG2 || ident[EI_MAG3] != ELFMAG3)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_InvalidHeaderMagic, "Invalid ELF Magic found");
                return(false);
            }

            CopyIndentFrom(objectFile, ident);
            return(true);
        }
        public override void Verify(DiagnosticBag diagnostics)
        {
            base.Verify(diagnostics);

            if (Version != 2)
            {
                diagnostics.Error(DiagnosticId.DWARF_ERR_VersionNotSupported, $"Non supported version {Version} for .debug_aranges");
            }

            if (Unit == null)
            {
                diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidNullUnitForAddressRangeTable, $"Invalid {nameof(Unit)} for .debug_aranges that cannot be null");
            }
            else
            {
                var parentFile = Unit.GetParentFile();
                if (this.Parent != parentFile)
                {
                    diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidParentUnitForAddressRangeTable, $"Invalid parent {nameof(DwarfFile)} of {nameof(Unit)} for .debug_aranges that doesn't match the parent of instance");
                }
            }
        }
        public override void UpdateLayout(DiagnosticBag diagnostics)
        {
            if (diagnostics == null)
            {
                throw new ArgumentNullException(nameof(diagnostics));
            }

            var nextSectionOffset = AlignHelper.AlignToUpper(Offset, UpperAlignment);

            Size = nextSectionOffset - Offset;
            if (Size >= int.MaxValue)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_InvalidAlignmentOutOfRange, $"Invalid alignment 0x{UpperAlignment:x} resulting in an offset beyond int.MaxValue");
            }
        }
Beispiel #8
0
        public override void Verify(DiagnosticBag diagnostics)
        {
            base.Verify(diagnostics);

            if (Type != ElfSectionType.Null ||
                Flags != ElfSectionFlags.None ||
                !Name.IsEmpty ||
                VirtualAddress != 0 ||
                Alignment != 0 ||
                !Link.IsEmpty ||
                !Info.IsEmpty ||
                Offset != 0 ||
                Size != 0)
            {
                diagnostics.Error(DiagnosticId.ELF_ERR_InvalidNullSection, "Invalid Null section. This section should not be modified and all properties must be null");
            }
        }
Beispiel #9
0
        public override void Verify(DiagnosticBag diagnostics)
        {
            base.Verify(diagnostics);

            if (Range.IsEmpty)
            {
                //diagnostics.Error($"Invalid empty {nameof(Range)} in {this}. An {nameof(ElfSegment)} requires to be attached to a section or a range of section or a {nameof(ElfShadowSection)}");
            }
            else
            {
                // TODO: Add checks that Alignment is Power Of 2
                var alignment = Alignment == 0 ? Alignment = 1 : Alignment;
                if (!AlignHelper.IsPowerOfTwo(alignment))
                {
                    diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentAlignmentForLoad, $"Invalid segment alignment requirements: Alignment = {alignment} must be a power of 2");
                }

                if (Range.BeginSection.Parent == null)
                {
                    diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentRangeBeginSectionParent, $"Invalid null parent {nameof(Range)}.{nameof(Range.BeginSection)} in {this}. The section must be attached to the same {nameof(ElfObjectFile)} than this instance");
                }

                if (Range.EndSection.Parent == null)
                {
                    diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentRangeEndSectionParent, $"Invalid null parent {nameof(Range)}.{nameof(Range.EndSection)} in {this}. The section must be attached to the same {nameof(ElfObjectFile)} than this instance");
                }

                if (Range.BeginOffset >= Range.BeginSection.Size)
                {
                    diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentRangeBeginOffset, $"Invalid {nameof(Range)}.{nameof(Range.BeginOffset)}: {Range.BeginOffset} cannot be >= {nameof(Range.BeginSection)}.{nameof(ElfSection.Size)}: {Range.BeginSection.Size} in {this}. The offset must be within the section");
                }
                else
                {
                    if (Type == ElfSegmentTypeCore.Load)
                    {
                        // Specs:
                        // As ‘‘Program Loading’’ later in this part describes, loadable process segments must have congruent values for p_vaddr and p_offset, modulo the page size.
                        // TODO: how to make this configurable?
                        if ((alignment % 4096) != 0)
                        {
                            diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentAlignmentForLoad, $"Invalid {nameof(ElfNative.PT_LOAD)} segment alignment requirements: {alignment} must be multiple of the Page Size {4096}");
                        }

                        var mod = (VirtualAddress - Range.Offset) & (alignment - 1);
                        if (mod != 0)
                        {
                            diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentVirtualAddressOrOffset, $"Invalid {nameof(ElfNative.PT_LOAD)} segment alignment requirements: (VirtualAddress - Range.Offset) & (Alignment - 1) == {mod}  while it must be == 0");
                        }
                    }
                }

                if ((Range.EndOffset >= 0 && (ulong)Range.EndOffset >= Range.EndSection.Size))
                {
                    diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentRangeEndOffset, $"Invalid {nameof(Range)}.{nameof(Range.EndOffset)}: {Range.EndOffset} cannot be >= {nameof(Range)}.{nameof(ElfSegmentRange.EndSection)}.{nameof(ElfSection.Size)}: {Range.EndSection.Size} in {this}. The offset must be within the section");
                }
                else if (Range.EndOffset < 0)
                {
                    var endOffset = (long)Range.EndSection.Size + Range.EndOffset;
                    if (endOffset < 0)
                    {
                        diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentRangeEndOffset, $"Invalid relative {nameof(Range)}.{nameof(Range.EndOffset)}: {Range.EndOffset}. The resulting end offset {endOffset} with {nameof(Range)}.{nameof(ElfSegmentRange.EndSection)}.{nameof(ElfSection.Size)}: {Range.EndSection.Size} cannot be < 0 in {this}. The offset must be within the section");
                    }
                }

                if (Range.BeginSection.Parent != null && Range.EndSection.Parent != null)
                {
                    if (Range.BeginSection.Index > Range.EndSection.Index)
                    {
                        diagnostics.Error(DiagnosticId.ELF_ERR_InvalidSegmentRangeIndices, $"Invalid index order between {nameof(Range)}.{nameof(ElfSegmentRange.BeginSection)}.{nameof(ElfSegment.Index)}: {Range.BeginSection.Index} and {nameof(Range)}.{nameof(ElfSegmentRange.EndSection)}.{nameof(ElfSegment.Index)}: {Range.EndSection.Index} in {this}. The from index must be <= to the end index.");
                    }
                }
            }
        }
        private bool TryReadNext(DwarfReaderWriter reader, DiagnosticBag diagnostics)
        {
            var code = reader.ReadLEB128();

            if (code == 0)
            {
                return(false);
            }

            var item = new DwarfAbbreviationItem();

            var  index        = code - 1;
            bool canAddToList = _mapItems == null && index < int.MaxValue && _items.Count == (int)index;

            item.Tag = reader.ReadLEB128As <DwarfTag>();
            var  hasChildrenRaw = reader.ReadU8();
            bool hasChildren    = false;

            if (hasChildrenRaw == DwarfNative.DW_CHILDREN_yes)
            {
                hasChildren = true;
            }
            else if (hasChildrenRaw != DwarfNative.DW_CHILDREN_no)
            {
                diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"Invalid children {hasChildrenRaw}. Must be either {DwarfNative.DW_CHILDREN_yes} or {DwarfNative.DW_CHILDREN_no}");
                return(false);
            }

            item.Code = code;

            item.HasChildren = hasChildren;

            if (canAddToList)
            {
                _items.Add(item);
            }
            else
            {
                if (_mapItems == null)
                {
                    _mapItems = new Dictionary <ulong, DwarfAbbreviationItem>();
                    for (var i = 0; i < _items.Count; i++)
                    {
                        var previousItem = _items[i];
                        _mapItems.Add((ulong)i + 1, previousItem);
                    }
                    _items.Clear();
                }

                // TODO: check collisions
                if (_mapItems.ContainsKey(code))
                {
                    diagnostics.Error(DiagnosticId.DWARF_ERR_InvalidData, $"Invalid code {code} found while another code already exists in this abbreviation.");
                    return(false);
                }
                _mapItems.Add(code, item);
            }

            List <DwarfAttributeDescriptor> descriptors = null;

            while (true)
            {
                var attributeName = reader.ReadLEB128As <DwarfAttributeName>();
                var attributeForm = reader.ReadLEB128As <DwarfAttributeForm>();

                if (attributeForm.Value == 0 && attributeForm.Value == 0)
                {
                    break;
                }

                if (descriptors == null)
                {
                    descriptors = new List <DwarfAttributeDescriptor>(1);
                }
                descriptors.Add(new DwarfAttributeDescriptor(attributeName, attributeForm));
            }

            if (descriptors != null)
            {
                item.Descriptors = descriptors;
            }

            return(true);
        }