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); }
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"); } }
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"); } }
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); }