diff --git a/Directory.Build.props b/Directory.Build.props index a81ed07..33cea46 100644 --- a/Directory.Build.props +++ b/Directory.Build.props @@ -5,7 +5,7 @@ True - - + + diff --git a/ELFSharp/ELF/Class.cs b/ELFSharp/ELF/Class.cs index 9c12096..bfcd808 100644 --- a/ELFSharp/ELF/Class.cs +++ b/ELFSharp/ELF/Class.cs @@ -4,6 +4,6 @@ public enum Class { Bit32, Bit64, - NotELF + NotELF } } \ No newline at end of file diff --git a/ELFSharp/ELF/Consts.cs b/ELFSharp/ELF/Consts.cs index 22c0a95..4ac4211 100644 --- a/ELFSharp/ELF/Consts.cs +++ b/ELFSharp/ELF/Consts.cs @@ -8,5 +8,4 @@ public static class Consts public const int SymbolEntrySize64 = 24; public const int MinimalELFSize = 16; } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/ELF.cs b/ELFSharp/ELF/ELF.cs index 9333bdc..ff6e861 100644 --- a/ELFSharp/ELF/ELF.cs +++ b/ELFSharp/ELF/ELF.cs @@ -10,6 +10,25 @@ namespace ELFSharp.ELF { public sealed class ELF : IELF where T : struct { + private const int SectionNameNotUniqueMarker = -1; + private readonly bool ownsStream; + + private readonly SimpleEndianessAwareReader reader; + private Stage currentStage; + private StringTable dynamicStringTable; + private StringTable objectsStringTable; + private uint sectionHeaderEntryCount; + private ushort sectionHeaderEntrySize; + private long sectionHeaderOffset; + private List sectionHeaders; + private Dictionary sectionIndicesByName; + private List> sections; + private ushort segmentHeaderEntryCount; + private ushort segmentHeaderEntrySize; + private long segmentHeaderOffset; + private List> segments; + private uint stringTableIndex; + internal ELF(Stream stream, bool ownsStream) { this.ownsStream = ownsStream; @@ -20,6 +39,14 @@ internal ELF(Stream stream, bool ownsStream) ReadSegmentHeaders(); } + public T EntryPoint { get; private set; } + + public T MachineFlags { get; private set; } + + public IReadOnlyList> Segments => segments.AsReadOnly(); + + public IReadOnlyList> Sections => sections.AsReadOnly(); + public Endianess Endianess { get; private set; } public Class Class { get; private set; } @@ -28,42 +55,50 @@ internal ELF(Stream stream, bool ownsStream) public Machine Machine { get; private set; } - public T EntryPoint { get; private set; } + public bool HasSegmentHeader => segmentHeaderOffset != 0; - public T MachineFlags { get; private set; } - - public bool HasSegmentHeader + public bool HasSectionHeader => sectionHeaderOffset != 0; + + public bool HasSectionsStringTable => stringTableIndex != 0; + + IReadOnlyList IELF.Segments => Segments; + + public IStringTable SectionsStringTable { get; private set; } + + IEnumerable IELF.GetSections() { - get { return segmentHeaderOffset != 0; } + return Sections.Where(x => x is TSectionType).Cast(); } - - public bool HasSectionHeader + + IReadOnlyList IELF.Sections => Sections; + + bool IELF.TryGetSection(string name, out ISection section) { - get { return sectionHeaderOffset != 0; } + var result = TryGetSection(name, out var concreteSection); + section = concreteSection; + return result; } - public bool HasSectionsStringTable + ISection IELF.GetSection(string name) { - get { return stringTableIndex != 0; } + return GetSection(name); } - - public IReadOnlyList> Segments + + bool IELF.TryGetSection(int index, out ISection section) { - get => segments.AsReadOnly(); + var result = TryGetSection(index, out var sectionConcrete); + section = sectionConcrete; + return result; } - IReadOnlyList IELF.Segments + ISection IELF.GetSection(int index) { - get => Segments; + return GetSection(index); } - public IStringTable SectionsStringTable { get; private set; } - - public IReadOnlyList> Sections => sections.AsReadOnly(); - - IEnumerable IELF.GetSections() + public void Dispose() { - return Sections.Where(x => x is TSectionType).Cast(); + if (ownsStream) reader.BaseStream.Dispose(); } public IEnumerable GetSections() where TSection : Section @@ -71,8 +106,6 @@ public IEnumerable GetSections() where TSection : Section return Sections.Where(x => x is TSection).Cast(); } - IReadOnlyList IELF.Sections => Sections; - public bool TryGetSection(string name, out Section section) { return TryGetSectionInner(name, out section) == GetSectionResult.Success; @@ -80,73 +113,45 @@ public bool TryGetSection(string name, out Section section) public Section GetSection(string name) { - var result = TryGetSectionInner(name, out Section section); + var result = TryGetSectionInner(name, out var section); - switch(result) + switch (result) { - case GetSectionResult.Success: - return section; - case GetSectionResult.SectionNameNotUnique: - throw new InvalidOperationException("Given section name is not unique, order is ambigous."); - case GetSectionResult.NoSectionsStringTable: - throw new InvalidOperationException("Given ELF does not contain section header string table, therefore names of sections cannot be obtained."); - case GetSectionResult.NoSuchSection: - throw new KeyNotFoundException(string.Format("Given section {0} could not be found in the file.", name)); - default: - throw new InvalidOperationException("Unhandled error."); + case GetSectionResult.Success: + return section; + case GetSectionResult.SectionNameNotUnique: + throw new InvalidOperationException("Given section name is not unique, order is ambigous."); + case GetSectionResult.NoSectionsStringTable: + throw new InvalidOperationException( + "Given ELF does not contain section header string table, therefore names of sections cannot be obtained."); + case GetSectionResult.NoSuchSection: + throw new KeyNotFoundException(string.Format("Given section {0} could not be found in the file.", + name)); + default: + throw new InvalidOperationException("Unhandled error."); } } - bool IELF.TryGetSection(string name, out ISection section) - { - var result = TryGetSection(name, out Section concreteSection); - section = concreteSection; - return result; - } - - ISection IELF.GetSection(string name) - { - return GetSection(name); - } - public Section GetSection(int index) { - GetSectionResult result = TryGetSectionInner(index, out Section section); - switch(result) + var result = TryGetSectionInner(index, out var section); + switch (result) { - case GetSectionResult.Success: - return section; - case GetSectionResult.NoSuchSection: - throw new IndexOutOfRangeException(string.Format("Given section index {0} is out of range.", index)); - default: - throw new ArgumentOutOfRangeException(); + case GetSectionResult.Success: + return section; + case GetSectionResult.NoSuchSection: + throw new IndexOutOfRangeException(string.Format("Given section index {0} is out of range.", + index)); + default: + throw new ArgumentOutOfRangeException(); } } - public override string ToString() - { - return string.Format("[ELF: Endianess={0}, Class={1}, Type={2}, Machine={3}, EntryPoint=0x{4:X}, " + - "NumberOfSections={5}, NumberOfSegments={6}]", Endianess, Class, Type, Machine, EntryPoint, sections.Count, segments.Count); - } - - bool IELF.TryGetSection(int index, out ISection section) - { - var result = TryGetSection(index, out Section sectionConcrete); - section = sectionConcrete; - return result; - } - - ISection IELF.GetSection(int index) - { - return GetSection(index); - } - - public void Dispose() + public override string ToString() { - if(ownsStream) - { - reader.BaseStream.Dispose(); - } + return string.Format("[ELF: Endianess={0}, Class={1}, Type={2}, Machine={3}, EntryPoint=0x{4:X}, " + + "NumberOfSections={5}, NumberOfSegments={6}]", Endianess, Class, Type, Machine, + EntryPoint, sections.Count, segments.Count); } private bool TryGetSection(int index, out Section section) @@ -157,7 +162,7 @@ private bool TryGetSection(int index, out Section section) private Section GetSectionFromSectionHeader(SectionHeader header) { Section returned; - switch(header.Type) + switch (header.Type) { case SectionType.Null: goto default; @@ -193,28 +198,25 @@ private Section GetSectionFromSectionHeader(SectionHeader header) returned = new Section(header, reader); break; } + return returned; } - + private void ReadSegmentHeaders() { - segments = new List>(segmentHeaderEntryCount); + segments = new List>(segmentHeaderEntryCount); - for(var i = 0u; i < segmentHeaderEntryCount; i++) + for (var i = 0u; i < segmentHeaderEntryCount; i++) { var seekTo = segmentHeaderOffset + i * segmentHeaderEntrySize; reader.BaseStream.Seek(seekTo, SeekOrigin.Begin); var segmentType = Segment.ProbeType(reader); Segment segment; - if(segmentType == SegmentType.Note) - { + if (segmentType == SegmentType.Note) segment = new NoteSegment(segmentHeaderOffset + i * segmentHeaderEntrySize, Class, reader); - } else - { segment = new Segment(segmentHeaderOffset + i * segmentHeaderEntrySize, Class, reader); - } segments.Add(segment); } @@ -223,57 +225,44 @@ private void ReadSegmentHeaders() private void ReadSections() { sectionHeaders = new List(); - if(HasSectionsStringTable) - { - sectionIndicesByName = new Dictionary(); - } + if (HasSectionsStringTable) sectionIndicesByName = new Dictionary(); for (var i = 0; i < sectionHeaderEntryCount; i++) { var header = ReadSectionHeader(i); sectionHeaders.Add(header); - if(HasSectionsStringTable) + if (HasSectionsStringTable) { var name = header.Name; - if(!sectionIndicesByName.ContainsKey(name)) - { + if (!sectionIndicesByName.ContainsKey(name)) sectionIndicesByName.Add(name, i); - } else - { + else sectionIndicesByName[name] = SectionNameNotUniqueMarker; - } } } + sections = new List>(Enumerable.Repeat>( null, sectionHeaders.Count )); FindStringTables(); - for(var i = 0; i < sectionHeaders.Count; i++) - { - TouchSection(i); - } + for (var i = 0; i < sectionHeaders.Count; i++) TouchSection(i); sectionHeaders = null; currentStage = Stage.AfterSectionsAreRead; } private void TouchSection(int index) { - if(currentStage != Stage.Initalizing) - { + if (currentStage != Stage.Initalizing) throw new InvalidOperationException("TouchSection invoked in improper state."); - } - if(sections[index] != null) - { - return; - } + if (sections[index] != null) return; var section = GetSectionFromSectionHeader(sectionHeaders[index]); sections[index] = section; } private void FindStringTables() { - TryGetSection(Consts.ObjectsStringTableName, out Section section); + TryGetSection(Consts.ObjectsStringTableName, out var section); objectsStringTable = (StringTable)section; TryGetSection(Consts.DynamicStringTableName, out section); @@ -283,29 +272,23 @@ private void FindStringTables() private void ReadStringTable() { - if(!HasSectionHeader || !HasSectionsStringTable) - { - return; - } + if (!HasSectionHeader || !HasSectionsStringTable) return; var header = ReadSectionHeader(checked((int)stringTableIndex)); - if(header.Type != SectionType.StringTable) - { - throw new InvalidOperationException("Given index of section header does not point at string table which was expected."); - } + if (header.Type != SectionType.StringTable) + throw new InvalidOperationException( + "Given index of section header does not point at string table which was expected."); SectionsStringTable = new StringTable(header, reader); } private SectionHeader ReadSectionHeader(int index, bool ignoreUpperLimit = false) { - if(index < 0 || (!ignoreUpperLimit && index >= sectionHeaderEntryCount)) - { + if (index < 0 || (!ignoreUpperLimit && index >= sectionHeaderEntryCount)) throw new ArgumentOutOfRangeException(nameof(index)); - } reader.BaseStream.Seek( - sectionHeaderOffset + index*sectionHeaderEntrySize, + sectionHeaderOffset + index * sectionHeaderEntrySize, SeekOrigin.Begin ); @@ -322,7 +305,7 @@ private SimpleEndianessAwareReader ObtainEndianessAwareReader(Stream stream) { 1 => Class.Bit32, 2 => Class.Bit64, - _ => throw new ArgumentException($"Given ELF file is of unknown class {classByte}."), + _ => throw new ArgumentException($"Given ELF file is of unknown class {classByte}.") }; var endianessByte = reader.ReadByte(); @@ -331,7 +314,7 @@ private SimpleEndianessAwareReader ObtainEndianessAwareReader(Stream stream) { 1 => Endianess.LittleEndian, 2 => Endianess.BigEndian, - _ => throw new ArgumentException($"Given ELF file uses unknown endianess {endianessByte}."), + _ => throw new ArgumentException($"Given ELF file uses unknown endianess {endianessByte}.") }; reader.ReadBytes(10); // padding bytes of section e_ident @@ -343,13 +326,11 @@ private void ReadFields() Type = (FileType)reader.ReadUInt16(); Machine = (Machine)reader.ReadUInt16(); var version = reader.ReadUInt32(); - if(version != 1) - { + if (version != 1) throw new ArgumentException(string.Format( "Given ELF file is of unknown version {0}.", version )); - } EntryPoint = (Class == Class.Bit32 ? reader.ReadUInt32() : reader.ReadUInt64()).To(); // TODO: assertions for (u)longs segmentHeaderOffset = Class == Class.Bit32 ? reader.ReadUInt32() : reader.ReadInt64(); @@ -373,71 +354,37 @@ private void ReadFields() // If the index of the string table is larger than or equal to SHN_LORESERVE (0xff00), this member holds SHN_XINDEX (0xffff) // and the real index of the section name string table section is held in the sh_link member of the initial entry in section // header table. Otherwise, the sh_link member of the initial entry in section header table contains the value zero. - if (stringTableIndex == 0xffff) - { - stringTableIndex = checked((uint)firstSectionHeader.Link); - } + if (stringTableIndex == 0xffff) stringTableIndex = checked(firstSectionHeader.Link); } } private GetSectionResult TryGetSectionInner(string name, out Section section) { - section = default(Section); - if(!HasSectionsStringTable) - { - return GetSectionResult.NoSectionsStringTable; - } - if(!sectionIndicesByName.TryGetValue(name, out int index)) - { - return GetSectionResult.NoSuchSection; - } - if(index == SectionNameNotUniqueMarker) - { - return GetSectionResult.SectionNameNotUnique; - } + section = default; + if (!HasSectionsStringTable) return GetSectionResult.NoSectionsStringTable; + if (!sectionIndicesByName.TryGetValue(name, out var index)) return GetSectionResult.NoSuchSection; + if (index == SectionNameNotUniqueMarker) return GetSectionResult.SectionNameNotUnique; return TryGetSectionInner(index, out section); } private GetSectionResult TryGetSectionInner(int index, out Section section) { - section = default(Section); - if(index >= sections.Count) - { - return GetSectionResult.NoSuchSection; - } - if(sections[index] != null) + section = default; + if (index >= sections.Count) return GetSectionResult.NoSuchSection; + if (sections[index] != null) { section = sections[index]; return GetSectionResult.Success; } - if(currentStage != Stage.Initalizing) - { - throw new InvalidOperationException("Assert not met: null section by proper index in not initializing stage."); - } + + if (currentStage != Stage.Initalizing) + throw new InvalidOperationException( + "Assert not met: null section by proper index in not initializing stage."); TouchSection(index); section = sections[index]; return GetSectionResult.Success; } - private readonly SimpleEndianessAwareReader reader; - private readonly bool ownsStream; - private long segmentHeaderOffset; - private long sectionHeaderOffset; - private ushort segmentHeaderEntrySize; - private ushort segmentHeaderEntryCount; - private ushort sectionHeaderEntrySize; - private uint sectionHeaderEntryCount; - private uint stringTableIndex; - private List> segments; - private List> sections; - private Dictionary sectionIndicesByName; - private List sectionHeaders; - private StringTable objectsStringTable; - private StringTable dynamicStringTable; - private Stage currentStage; - - private const int SectionNameNotUniqueMarker = -1; - private enum Stage { Initalizing, @@ -452,5 +399,4 @@ private enum GetSectionResult NoSuchSection } } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/ELFReader.cs b/ELFSharp/ELF/ELFReader.cs index a4d1514..697ca6b 100644 --- a/ELFSharp/ELF/ELFReader.cs +++ b/ELFSharp/ELF/ELFReader.cs @@ -4,120 +4,108 @@ namespace ELFSharp.ELF { - public static class ELFReader - { + public static class ELFReader + { + private const string NotELFMessage = "Given stream is not a proper ELF file."; + + private static readonly byte[] Magic = + { + 0x7F, + 0x45, + 0x4C, + 0x46 + }; // 0x7F 'E' 'L' 'F' + public static IELF Load(Stream stream, bool shouldOwnStream) - { - if(!TryLoad(stream, shouldOwnStream, out IELF elf)) - { - throw new ArgumentException(NotELFMessage); - } + { + if (!TryLoad(stream, shouldOwnStream, out var elf)) throw new ArgumentException(NotELFMessage); return elf; - } + } public static IELF Load(string fileName) { - return Load(File.OpenRead(fileName), true); + return Load(File.OpenRead(fileName), true); } - public static bool TryLoad(Stream stream, bool shouldOwnStream, out IELF elf) - { - switch(CheckELFType(stream)) - { - case Class.Bit32: - elf = new ELF(stream, shouldOwnStream); - return true; - case Class.Bit64: - elf = new ELF(stream, shouldOwnStream); - return true; - default: - elf = null; - stream.Close(); - return false; - } - } + public static bool TryLoad(Stream stream, bool shouldOwnStream, out IELF elf) + { + switch (CheckELFType(stream)) + { + case Class.Bit32: + elf = new ELF(stream, shouldOwnStream); + return true; + case Class.Bit64: + elf = new ELF(stream, shouldOwnStream); + return true; + default: + elf = null; + stream.Close(); + return false; + } + } public static bool TryLoad(string fileName, out IELF elf) { - return TryLoad(File.OpenRead(fileName), true, out elf); + return TryLoad(File.OpenRead(fileName), true, out elf); } - public static Class CheckELFType(Stream stream) - { - var currentStreamPosition = stream.Position; - - if(stream.Length < Consts.MinimalELFSize) - { - return Class.NotELF; - } - - using(var reader = new BinaryReader(stream, Encoding.UTF8, true)) - { - var magic = reader.ReadBytes(4); - for(var i = 0; i < 4; i++) - { - if(magic[i] != Magic[i]) - { - return Class.NotELF; - } - } - var value = reader.ReadByte(); - stream.Position = currentStreamPosition; - return value == 1 ? Class.Bit32 : Class.Bit64; - } - } + public static Class CheckELFType(Stream stream) + { + var currentStreamPosition = stream.Position; + + if (stream.Length < Consts.MinimalELFSize) return Class.NotELF; + + using (var reader = new BinaryReader(stream, Encoding.UTF8, true)) + { + var magic = reader.ReadBytes(4); + for (var i = 0; i < 4; i++) + if (magic[i] != Magic[i]) + return Class.NotELF; + + var value = reader.ReadByte(); + stream.Position = currentStreamPosition; + return value == 1 ? Class.Bit32 : Class.Bit64; + } + } public static Class CheckELFType(string fileName) { - using(var stream = File.OpenRead(fileName)) + using (var stream = File.OpenRead(fileName)) { - return CheckELFType(stream); + return CheckELFType(stream); } } - - public static ELF Load(Stream stream, bool shouldOwnStream) where T : struct - { - if(CheckELFType(stream) == Class.NotELF) - { - throw new ArgumentException(NotELFMessage); - } - return new ELF(stream, shouldOwnStream); - } + public static ELF Load(Stream stream, bool shouldOwnStream) where T : struct + { + if (CheckELFType(stream) == Class.NotELF) throw new ArgumentException(NotELFMessage); + + return new ELF(stream, shouldOwnStream); + } public static ELF Load(string fileName) where T : struct { - return Load(File.OpenRead(fileName), true); + return Load(File.OpenRead(fileName), true); } - public static bool TryLoad(Stream stream, bool shouldOwnStream, out ELF elf) where T : struct - { - switch(CheckELFType(stream)) - { - case Class.Bit32: - case Class.Bit64: - elf = new ELF(stream, shouldOwnStream); - return true; - default: - elf = null; - return false; - } - } - - public static bool TryLoad(string fileName, out ELF elf) where T : struct + public static bool TryLoad(Stream stream, bool shouldOwnStream, out ELF elf) where T : struct { - return TryLoad(File.OpenRead(fileName), true, out elf); + switch (CheckELFType(stream)) + { + case Class.Bit32: + case Class.Bit64: + elf = new ELF(stream, shouldOwnStream); + return true; + default: + elf = null; + return false; + } } - private static readonly byte[] Magic = + public static bool TryLoad(string fileName, out ELF elf) where T : struct { - 0x7F, - 0x45, - 0x4C, - 0x46 - }; // 0x7F 'E' 'L' 'F' - - private const string NotELFMessage = "Given stream is not a proper ELF file."; - } + return TryLoad(File.OpenRead(fileName), true, out elf); + } + } } \ No newline at end of file diff --git a/ELFSharp/ELF/FileType.cs b/ELFSharp/ELF/FileType.cs index 99ef333..b50c7e6 100644 --- a/ELFSharp/ELF/FileType.cs +++ b/ELFSharp/ELF/FileType.cs @@ -1,11 +1,11 @@ namespace ELFSharp.ELF { - public enum FileType : ushort - { - None = 0, - Relocatable, - Executable, - SharedObject, - Core - } + public enum FileType : ushort + { + None = 0, + Relocatable, + Executable, + SharedObject, + Core + } } \ No newline at end of file diff --git a/ELFSharp/ELF/IELF.cs b/ELFSharp/ELF/IELF.cs index 58aa921..1013d52 100644 --- a/ELFSharp/ELF/IELF.cs +++ b/ELFSharp/ELF/IELF.cs @@ -1,5 +1,5 @@ -using System.Collections.Generic; using System; +using System.Collections.Generic; using ELFSharp.ELF.Sections; using ELFSharp.ELF.Segments; @@ -23,5 +23,4 @@ public interface IELF : IDisposable bool TryGetSection(int index, out ISection section); ISection GetSection(int index); } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Machine.cs b/ELFSharp/ELF/Machine.cs index dba4eb8..11c12d9 100644 --- a/ELFSharp/ELF/Machine.cs +++ b/ELFSharp/ELF/Machine.cs @@ -1,168 +1,169 @@ /* * This file is based on LLVM's elf.h file. You can find its license * in the LICENSE file. - * + * */ namespace ELFSharp.ELF { - public enum Machine : ushort - { - None = 0, // No machine - M32 = 1, // AT&T WE 32100 - SPARC = 2, // SPARC - Intel386 = 3, // Intel 386 - M68K = 4, // Motorola 68000 - M88K = 5, // Motorola 88000 - Intel486 = 6, // Intel 486 (deprecated) - Intel860 = 7, // Intel 80860 - MIPS = 8, // MIPS R3000 - S370 = 9, // IBM System/370 - MIPSRS3LE = 10, // MIPS RS3000 Little-endian - PARISC = 15, // Hewlett-Packard PA-RISC - VPP500 = 17, // Fujitsu VPP500 - SPARC32Plus = 18, // Enhanced instruction set SPARC - Intel960 = 19, // Intel 80960 - PPC = 20, // PowerPC - PPC64 = 21, // PowerPC64 - S390 = 22, // IBM System/390 - SPU = 23, // IBM SPU/SPC - V800 = 36, // NEC V800 - FR20 = 37, // Fujitsu FR20 - RH32 = 38, // TRW RH-32 - RCE = 39, // Motorola RCE - ARM = 40, // ARM - Alpha = 41, // DEC Alpha - SuperH = 42, // Hitachi SH - SPARCv9 = 43, // SPARC V9 - TriCore = 44, // Siemens TriCore - ARC = 45, // Argonaut RISC Core - H8300 = 46, // Hitachi H8/300 - H8300H = 47, // Hitachi H8/300H - H8S = 48, // Hitachi H8S - H8500 = 49, // Hitachi H8/500 - IA64 = 50, // Intel IA-64 processor architecture - MIPSX = 51, // Stanford MIPS-X - ColdFire = 52, // Motorola ColdFire - M68HC12 = 53, // Motorola M68HC12 - MMA = 54, // Fujitsu MMA Multimedia Accelerator - PCP = 55, // Siemens PCP - NCPU = 56, // Sony nCPU embedded RISC processor - NDR1 = 57, // Denso NDR1 microprocessor - StarCore = 58, // Motorola Star*Core processor - ME16 = 59, // Toyota ME16 processor - ST100 = 60, // STMicroelectronics ST100 processor - TinyJ = 61, // Advanced Logic Corp. TinyJ embedded processor family - AMD64 = 62, // AMD x86-64 architecture - PDSP = 63, // Sony DSP Processor - PDP10 = 64, // Digital Equipment Corp. PDP-10 - PDP11 = 65, // Digital Equipment Corp. PDP-11 - FX66 = 66, // Siemens FX66 microcontroller - ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller - ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller - M68HC16 = 69, // Motorola MC68HC16 Microcontroller - M68HC11 = 70, // Motorola MC68HC11 Microcontroller - M68HC08 = 71, // Motorola MC68HC08 Microcontroller - M68HC05 = 72, // Motorola MC68HC05 Microcontroller - SVX = 73, // Silicon Graphics SVx - ST19 = 74, // STMicroelectronics ST19 8-bit microcontroller - VAX = 75, // Digital VAX - CRIS = 76, // Axis Communications 32-bit embedded processor - Javelin = 77, // Infineon Technologies 32-bit embedded processor - FirePath = 78, // Element 14 64-bit DSP Processor - ZSP = 79, // LSI Logic 16-bit DSP Processor - MMIX = 80, // Donald Knuth's educational 64-bit processor - HUANY = 81, // Harvard University machine-independent object files - PRISM = 82, // SiTera Prism - AVR = 83, // Atmel AVR 8-bit microcontroller - FR30 = 84, // Fujitsu FR30 - D10V = 85, // Mitsubishi D10V - D30V = 86, // Mitsubishi D30V - V850 = 87, // NEC v850 - M32R = 88, // Mitsubishi M32R - MN10300 = 89, // Matsushita MN10300 - MN10200 = 90, // Matsushita MN10200 - PicoJava = 91, // picoJava - OpenRISC = 92, // OpenRISC 32-bit embedded processor - ARCompact = 93, // ARC International ARCompact processo - Xtensa = 94, // Tensilica Xtensa Architecture - VideoCore = 95, // Alphamosaic VideoCore processor - TMMGPP = 96, // Thompson Multimedia General Purpose Processor - NS32K = 97, // National Semiconductor 32000 series - TPC = 98, // Tenor Network TPC processor - SNP1k = 99, // Trebia SNP 1000 processor - ST200 = 100, // STMicroelectronics (www.st.com) ST200 - IP2K = 101, // Ubicom IP2xxx microcontroller family - MAX = 102, // MAX Processor - CompactRISC = 103, // National Semiconductor CompactRISC microprocessor - F2MC16 = 104, // Fujitsu F2MC16 - MSP430 = 105, // Texas Instruments embedded microcontroller msp430 - Blackfin = 106, // Analog Devices Blackfin (DSP) processor - S1C33 = 107, // S1C33 Family of Seiko Epson processors - SEP = 108, // Sharp embedded microprocessor - ArcaRISC = 109, // Arca RISC Microprocessor - UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University - Excess = 111, // eXcess: 16/32/64-bit configurable embedded CPU - DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor - AlteraNios2 = 113, // Altera Nios II soft-core processor - CRX = 114, // National Semiconductor CompactRISC CRX - XGATE = 115, // Motorola XGATE embedded processor - C166 = 116, // Infineon C16x/XC16x processor - M16C = 117, // Renesas M16C series microprocessors - DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal - // Controller - EngineRISC = 119, // Freescale Communication Engine RISC core - M32C = 120, // Renesas M32C series microprocessors - TSK3000 = 131, // Altium TSK3000 core - RS08 = 132, // Freescale RS08 embedded processor - SHARC = 133, // Analog Devices SHARC family of 32-bit DSP processors - ECOG2 = 134, // Cyan Technology eCOG2 microprocessor - Score7 = 135, // Sunplus S+core7 RISC processor - DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor - VideoCore3 = 137, // Broadcom VideoCore III processor - LatticeMico32 = 138, // RISC processor for Lattice FPGA architecture - SeikoEpsonC17 = 139, // Seiko Epson C17 family - TIC6000 = 140, // The Texas Instruments TMS320C6000 DSP family - TIC2000 = 141, // The Texas Instruments TMS320C2000 DSP family - TIC5500 = 142, // The Texas Instruments TMS320C55x DSP family - MMDSPPlus = 160, // STMicroelectronics 64bit VLIW Data Signal Processor - CypressM8C = 161, // Cypress M8C microprocessor - R32C = 162, // Renesas R32C series microprocessors - TriMedia = 163, // NXP Semiconductors TriMedia architecture family - Hexagon = 164, // Qualcomm Hexagon processor - Intel8051 = 165, // Intel 8051 and variants - STxP7x = 166, // STMicroelectronics STxP7x family of configurable and extensible RISC processors - NDS32 = 167, // Andes Technology compact code size embedded RISC processor family - ECOG1 = 168, // Cyan Technology eCOG1X family - ECOG1X = 168, // Cyan Technology eCOG1X family - MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers - XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor - MANIK = 171, // M2000 Reconfigurable RISC Microprocessor - CrayNV2 = 172, // Cray Inc. NV2 vector architecture - RX = 173, // Renesas RX family - METAG = 174, // Imagination Technologies META processor architecture - MCSTElbrus = 175, // MCST Elbrus general purpose hardware architecture - ECOG16 = 176, // Cyan Technology eCOG16 family - CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit microprocessor - ETPU = 178, // Freescale Extended Time Processing Unit - SLE9X = 179, // Infineon Technologies SLE9X core - L10M = 180, // Intel L10M - K10M = 181, // Intel K10M - AArch64 = 183, // ARM AArch64 - AVR32 = 185, // Atmel Corporation 32-bit microprocessor family - STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller - TILE64 = 187, // Tilera TILE64 multicore architecture family - TILEPro = 188, // Tilera TILEPro multicore architecture family - CUDA = 190, // NVIDIA CUDA architecture - TILEGx = 191, // Tilera TILE-Gx multicore architecture family - CloudShield = 192, // CloudShield architecture family - CoreA1st = 193, // KIPO-KAIST Core-A 1st generation processor family - CoreA2nd = 194, // KIPO-KAIST Core-A 2nd generation processor family - ARCompact2 = 195, // Synopsys ARCompact V2 - Open8 = 196, // Open8 8-bit RISC soft processor core - RL78 = 197, // Renesas RL78 family - VideoCore5 = 198, // Broadcom VideoCore V processor - R78KOR = 199, // Renesas 78KOR family - F56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC) - } -} + public enum Machine : ushort + { + None = 0, // No machine + M32 = 1, // AT&T WE 32100 + SPARC = 2, // SPARC + Intel386 = 3, // Intel 386 + M68K = 4, // Motorola 68000 + M88K = 5, // Motorola 88000 + Intel486 = 6, // Intel 486 (deprecated) + Intel860 = 7, // Intel 80860 + MIPS = 8, // MIPS R3000 + S370 = 9, // IBM System/370 + MIPSRS3LE = 10, // MIPS RS3000 Little-endian + PARISC = 15, // Hewlett-Packard PA-RISC + VPP500 = 17, // Fujitsu VPP500 + SPARC32Plus = 18, // Enhanced instruction set SPARC + Intel960 = 19, // Intel 80960 + PPC = 20, // PowerPC + PPC64 = 21, // PowerPC64 + S390 = 22, // IBM System/390 + SPU = 23, // IBM SPU/SPC + V800 = 36, // NEC V800 + FR20 = 37, // Fujitsu FR20 + RH32 = 38, // TRW RH-32 + RCE = 39, // Motorola RCE + ARM = 40, // ARM + Alpha = 41, // DEC Alpha + SuperH = 42, // Hitachi SH + SPARCv9 = 43, // SPARC V9 + TriCore = 44, // Siemens TriCore + ARC = 45, // Argonaut RISC Core + H8300 = 46, // Hitachi H8/300 + H8300H = 47, // Hitachi H8/300H + H8S = 48, // Hitachi H8S + H8500 = 49, // Hitachi H8/500 + IA64 = 50, // Intel IA-64 processor architecture + MIPSX = 51, // Stanford MIPS-X + ColdFire = 52, // Motorola ColdFire + M68HC12 = 53, // Motorola M68HC12 + MMA = 54, // Fujitsu MMA Multimedia Accelerator + PCP = 55, // Siemens PCP + NCPU = 56, // Sony nCPU embedded RISC processor + NDR1 = 57, // Denso NDR1 microprocessor + StarCore = 58, // Motorola Star*Core processor + ME16 = 59, // Toyota ME16 processor + ST100 = 60, // STMicroelectronics ST100 processor + TinyJ = 61, // Advanced Logic Corp. TinyJ embedded processor family + AMD64 = 62, // AMD x86-64 architecture + PDSP = 63, // Sony DSP Processor + PDP10 = 64, // Digital Equipment Corp. PDP-10 + PDP11 = 65, // Digital Equipment Corp. PDP-11 + FX66 = 66, // Siemens FX66 microcontroller + ST9PLUS = 67, // STMicroelectronics ST9+ 8/16 bit microcontroller + ST7 = 68, // STMicroelectronics ST7 8-bit microcontroller + M68HC16 = 69, // Motorola MC68HC16 Microcontroller + M68HC11 = 70, // Motorola MC68HC11 Microcontroller + M68HC08 = 71, // Motorola MC68HC08 Microcontroller + M68HC05 = 72, // Motorola MC68HC05 Microcontroller + SVX = 73, // Silicon Graphics SVx + ST19 = 74, // STMicroelectronics ST19 8-bit microcontroller + VAX = 75, // Digital VAX + CRIS = 76, // Axis Communications 32-bit embedded processor + Javelin = 77, // Infineon Technologies 32-bit embedded processor + FirePath = 78, // Element 14 64-bit DSP Processor + ZSP = 79, // LSI Logic 16-bit DSP Processor + MMIX = 80, // Donald Knuth's educational 64-bit processor + HUANY = 81, // Harvard University machine-independent object files + PRISM = 82, // SiTera Prism + AVR = 83, // Atmel AVR 8-bit microcontroller + FR30 = 84, // Fujitsu FR30 + D10V = 85, // Mitsubishi D10V + D30V = 86, // Mitsubishi D30V + V850 = 87, // NEC v850 + M32R = 88, // Mitsubishi M32R + MN10300 = 89, // Matsushita MN10300 + MN10200 = 90, // Matsushita MN10200 + PicoJava = 91, // picoJava + OpenRISC = 92, // OpenRISC 32-bit embedded processor + ARCompact = 93, // ARC International ARCompact processo + Xtensa = 94, // Tensilica Xtensa Architecture + VideoCore = 95, // Alphamosaic VideoCore processor + TMMGPP = 96, // Thompson Multimedia General Purpose Processor + NS32K = 97, // National Semiconductor 32000 series + TPC = 98, // Tenor Network TPC processor + SNP1k = 99, // Trebia SNP 1000 processor + ST200 = 100, // STMicroelectronics (www.st.com) ST200 + IP2K = 101, // Ubicom IP2xxx microcontroller family + MAX = 102, // MAX Processor + CompactRISC = 103, // National Semiconductor CompactRISC microprocessor + F2MC16 = 104, // Fujitsu F2MC16 + MSP430 = 105, // Texas Instruments embedded microcontroller msp430 + Blackfin = 106, // Analog Devices Blackfin (DSP) processor + S1C33 = 107, // S1C33 Family of Seiko Epson processors + SEP = 108, // Sharp embedded microprocessor + ArcaRISC = 109, // Arca RISC Microprocessor + UNICORE = 110, // Microprocessor series from PKU-Unity Ltd. and MPRC of Peking University + Excess = 111, // eXcess: 16/32/64-bit configurable embedded CPU + DXP = 112, // Icera Semiconductor Inc. Deep Execution Processor + AlteraNios2 = 113, // Altera Nios II soft-core processor + CRX = 114, // National Semiconductor CompactRISC CRX + XGATE = 115, // Motorola XGATE embedded processor + C166 = 116, // Infineon C16x/XC16x processor + M16C = 117, // Renesas M16C series microprocessors + DSPIC30F = 118, // Microchip Technology dsPIC30F Digital Signal + + // Controller + EngineRISC = 119, // Freescale Communication Engine RISC core + M32C = 120, // Renesas M32C series microprocessors + TSK3000 = 131, // Altium TSK3000 core + RS08 = 132, // Freescale RS08 embedded processor + SHARC = 133, // Analog Devices SHARC family of 32-bit DSP processors + ECOG2 = 134, // Cyan Technology eCOG2 microprocessor + Score7 = 135, // Sunplus S+core7 RISC processor + DSP24 = 136, // New Japan Radio (NJR) 24-bit DSP Processor + VideoCore3 = 137, // Broadcom VideoCore III processor + LatticeMico32 = 138, // RISC processor for Lattice FPGA architecture + SeikoEpsonC17 = 139, // Seiko Epson C17 family + TIC6000 = 140, // The Texas Instruments TMS320C6000 DSP family + TIC2000 = 141, // The Texas Instruments TMS320C2000 DSP family + TIC5500 = 142, // The Texas Instruments TMS320C55x DSP family + MMDSPPlus = 160, // STMicroelectronics 64bit VLIW Data Signal Processor + CypressM8C = 161, // Cypress M8C microprocessor + R32C = 162, // Renesas R32C series microprocessors + TriMedia = 163, // NXP Semiconductors TriMedia architecture family + Hexagon = 164, // Qualcomm Hexagon processor + Intel8051 = 165, // Intel 8051 and variants + STxP7x = 166, // STMicroelectronics STxP7x family of configurable and extensible RISC processors + NDS32 = 167, // Andes Technology compact code size embedded RISC processor family + ECOG1 = 168, // Cyan Technology eCOG1X family + ECOG1X = 168, // Cyan Technology eCOG1X family + MAXQ30 = 169, // Dallas Semiconductor MAXQ30 Core Micro-controllers + XIMO16 = 170, // New Japan Radio (NJR) 16-bit DSP Processor + MANIK = 171, // M2000 Reconfigurable RISC Microprocessor + CrayNV2 = 172, // Cray Inc. NV2 vector architecture + RX = 173, // Renesas RX family + METAG = 174, // Imagination Technologies META processor architecture + MCSTElbrus = 175, // MCST Elbrus general purpose hardware architecture + ECOG16 = 176, // Cyan Technology eCOG16 family + CR16 = 177, // National Semiconductor CompactRISC CR16 16-bit microprocessor + ETPU = 178, // Freescale Extended Time Processing Unit + SLE9X = 179, // Infineon Technologies SLE9X core + L10M = 180, // Intel L10M + K10M = 181, // Intel K10M + AArch64 = 183, // ARM AArch64 + AVR32 = 185, // Atmel Corporation 32-bit microprocessor family + STM8 = 186, // STMicroeletronics STM8 8-bit microcontroller + TILE64 = 187, // Tilera TILE64 multicore architecture family + TILEPro = 188, // Tilera TILEPro multicore architecture family + CUDA = 190, // NVIDIA CUDA architecture + TILEGx = 191, // Tilera TILE-Gx multicore architecture family + CloudShield = 192, // CloudShield architecture family + CoreA1st = 193, // KIPO-KAIST Core-A 1st generation processor family + CoreA2nd = 194, // KIPO-KAIST Core-A 2nd generation processor family + ARCompact2 = 195, // Synopsys ARCompact V2 + Open8 = 196, // Open8 8-bit RISC soft processor core + RL78 = 197, // Renesas RL78 family + VideoCore5 = 198, // Broadcom VideoCore V processor + R78KOR = 199, // Renesas 78KOR family + F56800EX = 200 // Freescale 56800EX Digital Signal Controller (DSC) + } +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/DynamicEntry.cs b/ELFSharp/ELF/Sections/DynamicEntry.cs index d2c989e..67bae46 100644 --- a/ELFSharp/ELF/Sections/DynamicEntry.cs +++ b/ELFSharp/ELF/Sections/DynamicEntry.cs @@ -1,10 +1,9 @@ namespace ELFSharp.ELF.Sections { /// - /// Dynamic table entries are made up of a 32 bit or 64 bit "tag" - /// and a 32 bit or 64 bit union (val/pointer in 64 bit, val/pointer/offset in 32 bit). - /// - /// See LLVM elf.h file for the C/C++ version. + /// Dynamic table entries are made up of a 32 bit or 64 bit "tag" + /// and a 32 bit or 64 bit union (val/pointer in 64 bit, val/pointer/offset in 32 bit). + /// See LLVM elf.h file for the C/C++ version. /// public class DynamicEntry : IDynamicEntry { @@ -14,9 +13,9 @@ public DynamicEntry(T tagValue, T value) Value = value; } - public DynamicTag Tag { get; private set; } + public T Value { get; } - public T Value { get; private set; } + public DynamicTag Tag { get; } public override string ToString() { diff --git a/ELFSharp/ELF/Sections/DynamicSection.cs b/ELFSharp/ELF/Sections/DynamicSection.cs index 8e5d055..483de65 100644 --- a/ELFSharp/ELF/Sections/DynamicSection.cs +++ b/ELFSharp/ELF/Sections/DynamicSection.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Linq; @@ -8,25 +7,25 @@ namespace ELFSharp.ELF.Sections { public sealed class DynamicSection : Section, IDynamicSection where T : struct { - internal DynamicSection(SectionHeader header, SimpleEndianessAwareReader reader, ELF elf) : base(header, reader) + private readonly ELF elf; + + private List> entries; + + internal DynamicSection(SectionHeader header, SimpleEndianessAwareReader reader, ELF elf) : base(header, + reader) { this.elf = elf; ReadEntries(); } - public IEnumerable> Entries - { - get { return new ReadOnlyCollection>(entries); } - } + public IEnumerable> Entries => new ReadOnlyCollection>(entries); - IEnumerable IDynamicSection.Entries - { - get { return entries.Cast(); } - } + IEnumerable IDynamicSection.Entries => entries; public override string ToString() { - return string.Format("{0}: {2}, load @0x{4:X}, {5} entries", Name, NameIndex, Type, RawFlags, LoadAddress, Entries.Count()); + return string.Format("{0}: {2}, load @0x{4:X}, {5} entries", Name, NameIndex, Type, RawFlags, LoadAddress, + Entries.Count()); } private void ReadEntries() @@ -43,19 +42,10 @@ private void ReadEntries() entries = new List>(); for (ulong i = 0; i < entryCount; i++) - { if (elf.Class == Class.Bit32) - { entries.Add(new DynamicEntry(Reader.ReadUInt32().To(), Reader.ReadUInt32().To())); - } else if (elf.Class == Class.Bit64) - { entries.Add(new DynamicEntry(Reader.ReadUInt64().To(), Reader.ReadUInt64().To())); - } - } } - - private List> entries; - private readonly ELF elf; } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/DynamicTag.cs b/ELFSharp/ELF/Sections/DynamicTag.cs index d12ef34..aee4fc4 100644 --- a/ELFSharp/ELF/Sections/DynamicTag.cs +++ b/ELFSharp/ELF/Sections/DynamicTag.cs @@ -1,67 +1,64 @@ namespace ELFSharp.ELF.Sections { /// - /// This enum holds some of the possible values for the DynamicTag value (dropping platform - /// specific contents, such as MIPS flags.) - /// - /// Values are coming from LLVM's elf.h headers. - /// - /// File can be found in LLVM 3.8.1 source at: - /// ../include/llvm/support/elf.h - /// - /// License of the original C code is LLVM license. + /// This enum holds some of the possible values for the DynamicTag value (dropping platform + /// specific contents, such as MIPS flags.) + /// Values are coming from LLVM's elf.h headers. + /// File can be found in LLVM 3.8.1 source at: + /// ../include/llvm/support/elf.h + /// License of the original C code is LLVM license. /// public enum DynamicTag : ulong { - Null = 0, // Marks end of dynamic array. - Needed = 1, // String table offset of needed library. - PLTRelSz = 2, // Size of relocation entries in PLT. - PLTGOT = 3, // Address associated with linkage table. - Hash = 4, // Address of symbolic hash table. - StrTab = 5, // Address of dynamic string table. - SymTab = 6, // Address of dynamic symbol table. - RelA = 7, // Address of relocation table (Rela entries). - RelASz = 8, // Size of Rela relocation table. - RelAEnt = 9, // Size of a Rela relocation entry. - StrSz = 10, // Total size of the string table. - SymEnt = 11, // Size of a symbol table entry. - Init = 12, // Address of initialization function. - Fini = 13, // Address of termination function. - SoName = 14, // String table offset of a shared objects name. - RPath = 15, // String table offset of library search path. - Symbolic = 16, // Changes symbol resolution algorithm. - Rel = 17, // Address of relocation table (Rel entries). - RelSz = 18, // Size of Rel relocation table. - RelEnt = 19, // Size of a Rel relocation entry. - PLTRel = 20, // Type of relocation entry used for linking. - Debug = 21, // Reserved for debugger. - TextRel = 22, // Relocations exist for non-writable segments. - JmpRel = 23, // Address of relocations associated with PLT. - BindNow = 24, // Process all relocations before execution. - InitArray = 25, // Pointer to array of initialization functions. - FiniArray = 26, // Pointer to array of termination functions. - InitArraySz = 27, // Size of DT_INIT_ARRAY. - FiniArraySz = 28, // Size of DT_FINI_ARRAY. - RunPath = 29, // String table offset of lib search path. - Flags = 30, // Flags. - Encoding = 32, // Values from here to DT_LOOS follow the rules for the interpretation of the d_un union. + Null = 0, // Marks end of dynamic array. + Needed = 1, // String table offset of needed library. + PLTRelSz = 2, // Size of relocation entries in PLT. + PLTGOT = 3, // Address associated with linkage table. + Hash = 4, // Address of symbolic hash table. + StrTab = 5, // Address of dynamic string table. + SymTab = 6, // Address of dynamic symbol table. + RelA = 7, // Address of relocation table (Rela entries). + RelASz = 8, // Size of Rela relocation table. + RelAEnt = 9, // Size of a Rela relocation entry. + StrSz = 10, // Total size of the string table. + SymEnt = 11, // Size of a symbol table entry. + Init = 12, // Address of initialization function. + Fini = 13, // Address of termination function. + SoName = 14, // String table offset of a shared objects name. + RPath = 15, // String table offset of library search path. + Symbolic = 16, // Changes symbol resolution algorithm. + Rel = 17, // Address of relocation table (Rel entries). + RelSz = 18, // Size of Rel relocation table. + RelEnt = 19, // Size of a Rel relocation entry. + PLTRel = 20, // Type of relocation entry used for linking. + Debug = 21, // Reserved for debugger. + TextRel = 22, // Relocations exist for non-writable segments. + JmpRel = 23, // Address of relocations associated with PLT. + BindNow = 24, // Process all relocations before execution. + InitArray = 25, // Pointer to array of initialization functions. + FiniArray = 26, // Pointer to array of termination functions. + InitArraySz = 27, // Size of DT_INIT_ARRAY. + FiniArraySz = 28, // Size of DT_FINI_ARRAY. + RunPath = 29, // String table offset of lib search path. + Flags = 30, // Flags. + Encoding = 32, // Values from here to DT_LOOS follow the rules for the interpretation of the d_un union. - PreInitArray = 32, // Pointer to array of preinit functions. - PreInitArraySz = 33, // Size of the DT_PREINIT_ARRAY array. - LoOS = 0x60000000, // Start of environment specific tags. - HiOS = 0x6FFFFFFF, // End of environment specific tags. - LoProc = 0x70000000, // Start of processor specific tags. - HiProc = 0x7FFFFFFF, // End of processor specific tags. - GNUHash = 0x6FFFFEF5, // Reference to the GNU hash table. + PreInitArray = 32, // Pointer to array of preinit functions. + PreInitArraySz = 33, // Size of the DT_PREINIT_ARRAY array. + LoOS = 0x60000000, // Start of environment specific tags. + HiOS = 0x6FFFFFFF, // End of environment specific tags. + LoProc = 0x70000000, // Start of processor specific tags. + HiProc = 0x7FFFFFFF, // End of processor specific tags. + GNUHash = 0x6FFFFEF5, // Reference to the GNU hash table. TLSDescPLT = 0x6FFFFEF6, // Location of PLT entry for TLS descriptor resolver calls. TLSDescGOT = 0x6FFFFEF7, // Location of GOT entry used by TLS descriptor resolver PLT entry. - RelACount = 0x6FFFFFF9, // ELF32_Rela count. - RelCount = 0x6FFFFFFA, // ELF32_Rel count. - Flags1 = 0X6FFFFFFB, // Flags_1. - VerSym = 0x6FFFFFF0, // The address of .gnu.version section. - VerDef = 0X6FFFFFFC, // The address of the version definition table. - VerDefNum = 0X6FFFFFFD, // The number of entries in DT_VERDEF. - VerNeed = 0X6FFFFFFE, // The address of the version Dependency table. - VerNeedNum = 0X6FFFFFFF // The number of entries in DT_VERNEED. + RelACount = 0x6FFFFFF9, // ELF32_Rela count. + RelCount = 0x6FFFFFFA, // ELF32_Rel count. + Flags1 = 0X6FFFFFFB, // Flags_1. + VerSym = 0x6FFFFFF0, // The address of .gnu.version section. + VerDef = 0X6FFFFFFC, // The address of the version definition table. + VerDefNum = 0X6FFFFFFD, // The number of entries in DT_VERDEF. + VerNeed = 0X6FFFFFFE, // The address of the version Dependency table. + VerNeedNum = 0X6FFFFFFF // The number of entries in DT_VERNEED. } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/IDynamicEntry.cs b/ELFSharp/ELF/Sections/IDynamicEntry.cs index c63f838..2549dc7 100644 --- a/ELFSharp/ELF/Sections/IDynamicEntry.cs +++ b/ELFSharp/ELF/Sections/IDynamicEntry.cs @@ -1,9 +1,9 @@ namespace ELFSharp.ELF.Sections { /// - /// Represents an entry in the dynamic table. - /// Interface--because this is a union type in C, if we want more detail at some point on the values in the Union type, - /// we can have separate classes. + /// Represents an entry in the dynamic table. + /// Interface--because this is a union type in C, if we want more detail at some point on the values in the Union type, + /// we can have separate classes. /// public interface IDynamicEntry { diff --git a/ELFSharp/ELF/Sections/IDynamicSection.cs b/ELFSharp/ELF/Sections/IDynamicSection.cs index 15a4bc6..b998cfb 100644 --- a/ELFSharp/ELF/Sections/IDynamicSection.cs +++ b/ELFSharp/ELF/Sections/IDynamicSection.cs @@ -1,4 +1,3 @@ -using System; using System.Collections.Generic; namespace ELFSharp.ELF.Sections diff --git a/ELFSharp/ELF/Sections/INoteSection.cs b/ELFSharp/ELF/Sections/INoteSection.cs index d73f4c4..e62ad30 100644 --- a/ELFSharp/ELF/Sections/INoteSection.cs +++ b/ELFSharp/ELF/Sections/INoteSection.cs @@ -5,5 +5,4 @@ public interface INoteSection : ISection string NoteName { get; } byte[] Description { get; } } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/IProgBitsSection.cs b/ELFSharp/ELF/Sections/IProgBitsSection.cs index d87d3ae..a8afc9b 100644 --- a/ELFSharp/ELF/Sections/IProgBitsSection.cs +++ b/ELFSharp/ELF/Sections/IProgBitsSection.cs @@ -4,5 +4,4 @@ public interface IProgBitsSection : ISection { void WriteContents(byte[] destination, int offset, int length = 0); } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/ISection.cs b/ELFSharp/ELF/Sections/ISection.cs index f3b0b5f..6731631 100644 --- a/ELFSharp/ELF/Sections/ISection.cs +++ b/ELFSharp/ELF/Sections/ISection.cs @@ -2,11 +2,10 @@ namespace ELFSharp.ELF.Sections { public interface ISection { - byte[] GetContents(); string Name { get; } uint NameIndex { get; } SectionType Type { get; } SectionFlags Flags { get; } + byte[] GetContents(); } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/IStringTable.cs b/ELFSharp/ELF/Sections/IStringTable.cs index fe5a880..cdfbd4b 100644 --- a/ELFSharp/ELF/Sections/IStringTable.cs +++ b/ELFSharp/ELF/Sections/IStringTable.cs @@ -7,5 +7,4 @@ public interface IStringTable : ISection string this[long index] { get; } IEnumerable Strings { get; } } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/ISymbolEntry.cs b/ELFSharp/ELF/Sections/ISymbolEntry.cs index 21a61e0..d245d4d 100644 --- a/ELFSharp/ELF/Sections/ISymbolEntry.cs +++ b/ELFSharp/ELF/Sections/ISymbolEntry.cs @@ -10,5 +10,4 @@ public interface ISymbolEntry ISection PointedSection { get; } ushort PointedSectionIndex { get; } } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/ISymbolTable.cs b/ELFSharp/ELF/Sections/ISymbolTable.cs index 6bf6b3a..db99feb 100644 --- a/ELFSharp/ELF/Sections/ISymbolTable.cs +++ b/ELFSharp/ELF/Sections/ISymbolTable.cs @@ -6,5 +6,4 @@ public interface ISymbolTable : ISection { IEnumerable Entries { get; } } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/NoteData.cs b/ELFSharp/ELF/Sections/NoteData.cs index 0f1620d..9f336af 100644 --- a/ELFSharp/ELF/Sections/NoteData.cs +++ b/ELFSharp/ELF/Sections/NoteData.cs @@ -1,10 +1,9 @@ using System; +using System.Collections.ObjectModel; using System.IO; -using ELFSharp; using System.Text; -using ELFSharp.Utilities; using ELFSharp.ELF.Segments; -using System.Collections.ObjectModel; +using ELFSharp.Utilities; namespace ELFSharp.ELF.Sections { @@ -12,28 +11,7 @@ public class NoteData : INoteData { public const ulong NoteDataHeaderSize = 12; // name size + description size + field - public string Name { get; private set; } - - public ReadOnlyCollection Description - { - get - { - return new ReadOnlyCollection(DescriptionBytes); - } - } - - internal byte[] DescriptionBytes { get; private set; } - - public ulong Type { get; private set; } - - internal ulong NoteOffset { get; private set; } - internal ulong NoteFileSize { get; private set; } - internal ulong NoteFileEnd { get { return NoteOffset + NoteFileSize; } } - - public override string ToString() - { - return $"Name={Name} DataSize=0x{DescriptionBytes.Length.ToString("x8")}"; - } + private readonly SimpleEndianessAwareReader reader; internal NoteData(ulong sectionOffset, ulong sectionSize, SimpleEndianessAwareReader reader) { @@ -58,13 +36,9 @@ internal NoteData(ulong sectionOffset, ulong sectionSize, SimpleEndianessAwareRe { var name = reader.ReadBytes(alignedNameSize); if (nameSize > 0) - { Name = Encoding.UTF8.GetString(name, 0, nameSize - 1); // minus one to omit terminating NUL - } if (reader.BaseStream.Position + descriptionSize <= sectionEnd) - { DescriptionBytes = descriptionSize > 0 ? reader.ReadBytes(descriptionSize) : new byte[0]; - } } // If there are multiple notes inside one segment, keep track of the end position so we can read them @@ -73,11 +47,30 @@ internal NoteData(ulong sectionOffset, ulong sectionSize, SimpleEndianessAwareRe NoteFileSize = (ulong)alignedNameSize + (ulong)alignedDescriptionSize + NoteDataHeaderSize; } + internal byte[] DescriptionBytes { get; } + + internal ulong NoteOffset { get; } + internal ulong NoteFileSize { get; } + internal ulong NoteFileEnd => NoteOffset + NoteFileSize; + + private int FieldSize => 4; + + public string Name { get; } + + public ReadOnlyCollection Description => new ReadOnlyCollection(DescriptionBytes); + + public ulong Type { get; } + public Stream ToStream() { return new MemoryStream(DescriptionBytes); } + public override string ToString() + { + return $"Name={Name} DataSize=0x{DescriptionBytes.Length.ToString("x8")}"; + } + private int ReadSize() { /* @@ -99,15 +92,5 @@ private ulong ReadField() // see comment above return reader.ReadUInt32(); } - - private int FieldSize - { - get - { - return 4; - } - } - - private readonly SimpleEndianessAwareReader reader; } -} +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/NoteSection.cs b/ELFSharp/ELF/Sections/NoteSection.cs index 19efeb7..404e220 100644 --- a/ELFSharp/ELF/Sections/NoteSection.cs +++ b/ELFSharp/ELF/Sections/NoteSection.cs @@ -1,46 +1,25 @@ -using System; -using ELFSharp; using ELFSharp.Utilities; namespace ELFSharp.ELF.Sections { public sealed class NoteSection : Section, INoteSection where T : struct { - public string NoteName - { - get - { - return data.Name; - } - } - - public byte[] Description - { - get - { - return data.DescriptionBytes; - } - } + private readonly NoteData data; - public override string ToString() - { - return string.Format("{0}: {2}, Type={1}", Name, NoteType, Type); - } - - public T NoteType - { - get - { - return data.Type.To(); - } - } - internal NoteSection(SectionHeader header, SimpleEndianessAwareReader reader) : base(header, reader) { data = new NoteData(header.Offset, header.Size, reader); } - - private readonly NoteData data; - } + public T NoteType => data.Type.To(); + + public string NoteName => data.Name; + + public byte[] Description => data.DescriptionBytes; + + public override string ToString() + { + return string.Format("{0}: {2}, Type={1}", Name, NoteType, Type); + } + } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/ProgBitsSection.cs b/ELFSharp/ELF/Sections/ProgBitsSection.cs index 8a56527..7dc2b87 100644 --- a/ELFSharp/ELF/Sections/ProgBitsSection.cs +++ b/ELFSharp/ELF/Sections/ProgBitsSection.cs @@ -5,18 +5,17 @@ namespace ELFSharp.ELF.Sections { public sealed class ProgBitsSection : Section, IProgBitsSection where T : struct { + private const int BufferSize = 10 * 1024; + internal ProgBitsSection(SectionHeader header, SimpleEndianessAwareReader reader) : base(header, reader) { } - + public void WriteContents(byte[] destination, int offset, int length = 0) { SeekToSectionBeginning(); - if (length == 0 || (ulong)length > Header.Size) - { - length = Convert.ToInt32(Header.Size); - } + if (length == 0 || (ulong)length > Header.Size) length = Convert.ToInt32(Header.Size); var remaining = length; while (remaining > 0) { @@ -25,7 +24,5 @@ public void WriteContents(byte[] destination, int offset, int length = 0) remaining -= buffer.Length; } } - - private const int BufferSize = 10 * 1024; } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/Section.cs b/ELFSharp/ELF/Sections/Section.cs index babfcc5..ff22f52 100644 --- a/ELFSharp/ELF/Sections/Section.cs +++ b/ELFSharp/ELF/Sections/Section.cs @@ -6,116 +6,52 @@ namespace ELFSharp.ELF.Sections { public class Section : ISection where T : struct { + protected readonly SimpleEndianessAwareReader Reader; + internal Section(SectionHeader header, SimpleEndianessAwareReader reader) { Header = header; - this.Reader = reader; + Reader = reader; } - public virtual byte[] GetContents() - { - if (Type == SectionType.NoBits) - { - return Array.Empty(); - } - - Reader.BaseStream.Seek((long)Header.Offset, SeekOrigin.Begin); - return Reader.ReadBytes(Convert.ToInt32(Header.Size)); - } + public T RawFlags => Header.RawFlags.To(); - public string Name - { - get - { - return Header.Name; - } - } + public T LoadAddress => Header.LoadAddress.To(); - public uint NameIndex - { - get - { - return Header.NameIndex; - } - } + public T Alignment => Header.Alignment.To(); - public SectionType Type - { - get - { - return Header.Type; - } - } + public T EntrySize => Header.EntrySize.To(); - public SectionFlags Flags - { - get - { - return Header.Flags; - } - } + public T Size => Header.Size.To(); - public T RawFlags - { - get - { - return Header.RawFlags.To(); - } - } - - public T LoadAddress - { - get - { - return Header.LoadAddress.To(); - } - } + public T Offset => Header.Offset.To(); - public T Alignment - { - get - { - return Header.Alignment.To(); - } - } + internal SectionHeader Header { get; } - public T EntrySize - { - get - { - return Header.EntrySize.To(); - } - } - - public T Size + public virtual byte[] GetContents() { - get - { - return Header.Size.To(); - } - } + if (Type == SectionType.NoBits) return Array.Empty(); - public T Offset - { - get - { - return Header.Offset.To(); - } + Reader.BaseStream.Seek((long)Header.Offset, SeekOrigin.Begin); + return Reader.ReadBytes(Convert.ToInt32(Header.Size)); } - public override string ToString() - { - return Header.ToString(); - } + public string Name => Header.Name; + + public uint NameIndex => Header.NameIndex; + + public SectionType Type => Header.Type; - internal SectionHeader Header { get; private set; } + public SectionFlags Flags => Header.Flags; + + public override string ToString() + { + return Header.ToString(); + } protected void SeekToSectionBeginning() { Reader.BaseStream.Seek((long)Header.Offset, SeekOrigin.Begin); } - - protected readonly SimpleEndianessAwareReader Reader; } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SectionFlags.cs b/ELFSharp/ELF/Sections/SectionFlags.cs index 1dd2efb..fcf3ddc 100644 --- a/ELFSharp/ELF/Sections/SectionFlags.cs +++ b/ELFSharp/ELF/Sections/SectionFlags.cs @@ -9,5 +9,4 @@ public enum SectionFlags Allocatable = 2, Executable = 4 } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SectionHeader.cs b/ELFSharp/ELF/Sections/SectionHeader.cs index 9645cf0..f5ebf8a 100644 --- a/ELFSharp/ELF/Sections/SectionHeader.cs +++ b/ELFSharp/ELF/Sections/SectionHeader.cs @@ -4,12 +4,18 @@ namespace ELFSharp.ELF.Sections { internal sealed class SectionHeader { + private readonly Class elfClass; + + private readonly SimpleEndianessAwareReader reader; + + private readonly IStringTable table; + // TODO: make elf consts file with things like SHT_LOUSER internal SectionHeader(SimpleEndianessAwareReader reader, Class elfClass, IStringTable table = null) { this.reader = reader; this.table = table; - this.elfClass = elfClass; + this.elfClass = elfClass; ReadSectionHeader(); } @@ -22,22 +28,20 @@ internal SectionHeader(SimpleEndianessAwareReader reader, Class elfClass, IStrin internal ulong Alignment { get; private set; } internal ulong EntrySize { get; private set; } internal ulong Size { get; private set; } - internal ulong Offset { get; private set; } + internal ulong Offset { get; private set; } internal uint Link { get; private set; } internal uint Info { get; private set; } - - public override string ToString() - { - return string.Format("{0}: {2}, load @0x{4:X}, {5} bytes long", Name, NameIndex, Type, RawFlags, LoadAddress, Size); - } + + public override string ToString() + { + return string.Format("{0}: {2}, load @0x{4:X}, {5} bytes long", Name, NameIndex, Type, RawFlags, + LoadAddress, Size); + } private void ReadSectionHeader() { NameIndex = reader.ReadUInt32(); - if(table != null) - { - Name = table[NameIndex]; - } + if (table != null) Name = table[NameIndex]; Type = (SectionType)reader.ReadUInt32(); RawFlags = ReadAddress(); Flags = unchecked((SectionFlags)RawFlags); @@ -59,10 +63,5 @@ private ulong ReadOffset() { return elfClass == Class.Bit32 ? reader.ReadUInt32() : reader.ReadUInt64(); } - - private readonly SimpleEndianessAwareReader reader; - private IStringTable table; - private readonly Class elfClass; } - -} +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SectionType.cs b/ELFSharp/ELF/Sections/SectionType.cs index b02c898..592a27d 100644 --- a/ELFSharp/ELF/Sections/SectionType.cs +++ b/ELFSharp/ELF/Sections/SectionType.cs @@ -1,18 +1,18 @@ namespace ELFSharp.ELF.Sections { - public enum SectionType : uint - { - Null = 0, - ProgBits, - SymbolTable, - StringTable, - RelocationAddends, - HashTable, - Dynamic, - Note, - NoBits, - Relocation, - Shlib, - DynamicSymbolTable, - } + public enum SectionType : uint + { + Null = 0, + ProgBits, + SymbolTable, + StringTable, + RelocationAddends, + HashTable, + Dynamic, + Note, + NoBits, + Relocation, + Shlib, + DynamicSymbolTable + } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SpecialSectionIndex.cs b/ELFSharp/ELF/Sections/SpecialSectionIndex.cs index 8f79f7d..64587b4 100644 --- a/ELFSharp/ELF/Sections/SpecialSectionIndex.cs +++ b/ELFSharp/ELF/Sections/SpecialSectionIndex.cs @@ -1,9 +1,9 @@ namespace ELFSharp.ELF.Sections { - public enum SpecialSectionIndex : ushort - { - Absolute = 0, - Common = 0xFFF1, - Undefined = 0xFFF2 - } + public enum SpecialSectionIndex : ushort + { + Absolute = 0, + Common = 0xFFF1, + Undefined = 0xFFF2 + } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SpecialSectionType.cs b/ELFSharp/ELF/Sections/SpecialSectionType.cs index b93c18b..1db6837 100644 --- a/ELFSharp/ELF/Sections/SpecialSectionType.cs +++ b/ELFSharp/ELF/Sections/SpecialSectionType.cs @@ -1,12 +1,12 @@ namespace ELFSharp.ELF.Sections { - public enum SpecialSectionType - { - Null, - ProgBits, - NoBits, - Shlib, - ProcessorSpecific, - UserSpecific - } + public enum SpecialSectionType + { + Null, + ProgBits, + NoBits, + Shlib, + ProcessorSpecific, + UserSpecific + } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/StringTable.cs b/ELFSharp/ELF/Sections/StringTable.cs index 72d8ad1..dbe8902 100644 --- a/ELFSharp/ELF/Sections/StringTable.cs +++ b/ELFSharp/ELF/Sections/StringTable.cs @@ -2,88 +2,79 @@ using System.Collections.Generic; using System.Diagnostics; using System.Text; -using ELFSharp.Utilities; - +using ELFSharp.Utilities; + namespace ELFSharp.ELF.Sections -{ +{ public sealed class StringTable : Section, IStringTable where T : struct - { + { + private readonly byte[] stringBlob; + + private readonly Dictionary stringCache; + private bool cachePopulated; + internal StringTable(SectionHeader header, SimpleEndianessAwareReader reader) : base(header, reader) - { - stringCache = new Dictionary - { - { 0, string.Empty } - }; - stringBlob = ReadStringData(); - } - + { + stringCache = new Dictionary + { + { 0, string.Empty } + }; + stringBlob = ReadStringData(); + } + public IEnumerable Strings - { + { get { - if(!cachePopulated) - { - PrepopulateCache(); - } - return stringCache.Values; - } - } - + if (!cachePopulated) PrepopulateCache(); + return stringCache.Values; + } + } + public string this[long index] - { + { get { - if(stringCache.TryGetValue(index, out string result)) - { - return result; - } - return HandleUnexpectedIndex(index); - } - } - + if (stringCache.TryGetValue(index, out var result)) return result; + return HandleUnexpectedIndex(index); + } + } + private string HandleUnexpectedIndex(long index) - { - var stringStart = (int)index; - for(var i = stringStart; i < stringBlob.Length; ++i) - { - if(stringBlob[i] == 0) + { + var stringStart = (int)index; + for (var i = stringStart; i < stringBlob.Length; ++i) + if (stringBlob[i] == 0) { var str = Encoding.UTF8.GetString(stringBlob, stringStart, i - stringStart); stringCache.Add(stringStart, str); return str; } - } - throw new IndexOutOfRangeException(); - } - + + throw new IndexOutOfRangeException(); + } + private void PrepopulateCache() { cachePopulated = true; var stringStart = 1; - for(var i = 1; i < stringBlob.Length; ++i) - { - if(stringBlob[i] == 0) + for (var i = 1; i < stringBlob.Length; ++i) + if (stringBlob[i] == 0) { - if(!stringCache.ContainsKey(stringStart)) - { + if (!stringCache.ContainsKey(stringStart)) stringCache.Add(stringStart, Encoding.UTF8.GetString(stringBlob, stringStart, i - stringStart)); - } stringStart = i + 1; } - } - } - + } + private byte[] ReadStringData() { SeekToSectionBeginning(); var blob = Reader.ReadBytes((int)Header.Size); - Debug.Assert(blob.Length == 0 || (blob[0] == 0 && blob[blob.Length - 1] == 0), "First and last bytes must be the null character (except for empty string tables)"); + Debug.Assert(blob.Length == 0 || (blob[0] == 0 && blob[blob.Length - 1] == 0), + "First and last bytes must be the null character (except for empty string tables)"); return blob; } - - private readonly Dictionary stringCache; - private readonly byte[] stringBlob; - private bool cachePopulated; - } -} + } +} \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SymbolBinding.cs b/ELFSharp/ELF/Sections/SymbolBinding.cs index 9f2a5da..a5a977b 100644 --- a/ELFSharp/ELF/Sections/SymbolBinding.cs +++ b/ELFSharp/ELF/Sections/SymbolBinding.cs @@ -1,10 +1,10 @@ namespace ELFSharp.ELF.Sections { - public enum SymbolBinding - { - Local, - Global, - Weak, - ProcessorSpecific - } + public enum SymbolBinding + { + Local, + Global, + Weak, + ProcessorSpecific + } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SymbolEntry.cs b/ELFSharp/ELF/Sections/SymbolEntry.cs index afcddaa..eddac18 100644 --- a/ELFSharp/ELF/Sections/SymbolEntry.cs +++ b/ELFSharp/ELF/Sections/SymbolEntry.cs @@ -4,57 +4,54 @@ namespace ELFSharp.ELF.Sections { public class SymbolEntry : ISymbolEntry where T : struct { - public string Name { get; } - - public SymbolBinding Binding { get; } + private readonly ELF elf; - public SymbolType Type { get; } + public SymbolEntry(string name, T value, T size, SymbolVisibility visibility, + SymbolBinding binding, SymbolType type, ELF elf, ushort sectionIdx) + { + Name = name; + Value = value; + Size = size; + Binding = binding; + Type = type; + Visibility = visibility; + this.elf = elf; + PointedSectionIndex = sectionIdx; + } public T Value { get; } public T Size { get; } - public SymbolVisibility Visibility { get; } - - public bool IsPointedIndexSpecial => Enum.IsDefined(typeof(SpecialSectionIndex), PointedSectionIndex); - public Section PointedSection => IsPointedIndexSpecial ? null : elf.GetSection(PointedSectionIndex); - ISection ISymbolEntry.PointedSection => PointedSection; - - public ushort PointedSectionIndex { get; } - public SpecialSectionIndex SpecialPointedSectionIndex { get { - if(IsPointedIndexSpecial) - { - return (SpecialSectionIndex)PointedSectionIndex; - } + if (IsPointedIndexSpecial) return (SpecialSectionIndex)PointedSectionIndex; throw new InvalidOperationException("Given pointed section index does not have special meaning."); } } + public string Name { get; } + + public SymbolBinding Binding { get; } + + public SymbolType Type { get; } + + public SymbolVisibility Visibility { get; } + + public bool IsPointedIndexSpecial => Enum.IsDefined(typeof(SpecialSectionIndex), PointedSectionIndex); + + ISection ISymbolEntry.PointedSection => PointedSection; + + public ushort PointedSectionIndex { get; } + public override string ToString() { return string.Format("[{3} {4} {0}: 0x{1:X}, size: {2}, section idx: {5}]", - Name, Value, Size, Binding, Type, (SpecialSectionIndex)PointedSectionIndex); + Name, Value, Size, Binding, Type, (SpecialSectionIndex)PointedSectionIndex); } - - public SymbolEntry(string name, T value, T size, SymbolVisibility visibility, - SymbolBinding binding, SymbolType type, ELF elf, ushort sectionIdx) - { - Name = name; - Value = value; - Size = size; - Binding = binding; - Type = type; - Visibility = visibility; - this.elf = elf; - PointedSectionIndex = sectionIdx; - } - - private readonly ELF elf; } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SymbolTable.cs b/ELFSharp/ELF/Sections/SymbolTable.cs index 8c1b2dc..052a3bc 100644 --- a/ELFSharp/ELF/Sections/SymbolTable.cs +++ b/ELFSharp/ELF/Sections/SymbolTable.cs @@ -1,6 +1,4 @@ -using System; using System.Collections.Generic; -using System.Linq; using System.Collections.ObjectModel; using ELFSharp.Utilities; @@ -8,35 +6,35 @@ namespace ELFSharp.ELF.Sections { public sealed class SymbolTable : Section, ISymbolTable where T : struct { - internal SymbolTable(SectionHeader header, SimpleEndianessAwareReader Reader, IStringTable table, ELF elf) : base(header, Reader) + private readonly ELF elf; + private readonly IStringTable table; + + private List> entries; + + internal SymbolTable(SectionHeader header, SimpleEndianessAwareReader Reader, IStringTable table, ELF elf) : + base(header, Reader) { this.table = table; this.elf = elf; ReadSymbols(); } - public IEnumerable> Entries - { - get { return new ReadOnlyCollection>(entries); } - } + public IEnumerable> Entries => new ReadOnlyCollection>(entries); - IEnumerable ISymbolTable.Entries - { - get { return Entries.Cast(); } - } + IEnumerable ISymbolTable.Entries => Entries; private void ReadSymbols() { SeekToSectionBeginning(); entries = new List>(); var adder = (ulong)(elf.Class == Class.Bit32 ? Consts.SymbolEntrySize32 : Consts.SymbolEntrySize64); - for(var i = 0UL; i < Header.Size; i += adder) + for (var i = 0UL; i < Header.Size; i += adder) { var value = 0UL; var size = 0UL; var nameIdx = Reader.ReadUInt32(); - if(elf.Class == Class.Bit32) + if (elf.Class == Class.Bit32) { value = Reader.ReadUInt32(); size = Reader.ReadUInt32(); @@ -47,7 +45,7 @@ private void ReadSymbols() var visibility = (SymbolVisibility)(other & 3); // Only three lowest bits are meaningful. var sectionIdx = Reader.ReadUInt16(); - if(elf.Class == Class.Bit64) + if (elf.Class == Class.Bit64) { value = Reader.ReadUInt64(); size = Reader.ReadUInt64(); @@ -56,12 +54,9 @@ private void ReadSymbols() var name = table == null ? "" : table[nameIdx]; var binding = (SymbolBinding)(info >> 4); var type = (SymbolType)(info & 0x0F); - entries.Add(new SymbolEntry(name, value.To(), size.To(), visibility, binding, type, elf, sectionIdx)); + entries.Add(new SymbolEntry(name, value.To(), size.To(), visibility, binding, type, elf, + sectionIdx)); } } - - private List> entries; - private readonly IStringTable table; - private readonly ELF elf; } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SymbolType.cs b/ELFSharp/ELF/Sections/SymbolType.cs index ecf1a5c..6d7f6a7 100644 --- a/ELFSharp/ELF/Sections/SymbolType.cs +++ b/ELFSharp/ELF/Sections/SymbolType.cs @@ -1,12 +1,12 @@ namespace ELFSharp.ELF.Sections { - public enum SymbolType - { - NotSpecified, - Object, - Function, - Section, - File, - ProcessorSpecific - } + public enum SymbolType + { + NotSpecified, + Object, + Function, + Section, + File, + ProcessorSpecific + } } \ No newline at end of file diff --git a/ELFSharp/ELF/Sections/SymbolVisibility.cs b/ELFSharp/ELF/Sections/SymbolVisibility.cs index 55099a1..aa7c061 100644 --- a/ELFSharp/ELF/Sections/SymbolVisibility.cs +++ b/ELFSharp/ELF/Sections/SymbolVisibility.cs @@ -7,4 +7,4 @@ public enum SymbolVisibility : byte Hidden = 2, Protected = 3 } -} +} \ No newline at end of file diff --git a/ELFSharp/ELF/Segments/INoteData.cs b/ELFSharp/ELF/Segments/INoteData.cs index 0c049f9..f683f04 100644 --- a/ELFSharp/ELF/Segments/INoteData.cs +++ b/ELFSharp/ELF/Segments/INoteData.cs @@ -6,27 +6,26 @@ namespace ELFSharp.ELF.Segments public interface INoteData { /// - /// Owner of the note. + /// Owner of the note. /// string Name { get; } /// - /// Data contents of the note. The format of this depends on the combination of the Name and Type properties and often - /// corresponds to a struct. - /// - /// For example, see elf.h in the Linux kernel source tree. + /// Data contents of the note. The format of this depends on the combination of the Name and Type properties and often + /// corresponds to a struct. + /// For example, see elf.h in the Linux kernel source tree. /// ReadOnlyCollection Description { get; } /// - /// Data type + /// Data type /// ulong Type { get; } /// - /// Returns the Description byte[] as a Stream + /// Returns the Description byte[] as a Stream /// /// Stream ToStream(); } -} +} \ No newline at end of file diff --git a/ELFSharp/ELF/Segments/INoteSegment.cs b/ELFSharp/ELF/Segments/INoteSegment.cs index 3d9288a..d6e5131 100644 --- a/ELFSharp/ELF/Segments/INoteSegment.cs +++ b/ELFSharp/ELF/Segments/INoteSegment.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; namespace ELFSharp.ELF.Segments { @@ -10,8 +9,8 @@ public interface INoteSegment : ISegment byte[] NoteDescription { get; } /// - /// Returns all notes within the segment + /// Returns all notes within the segment /// IReadOnlyList Notes { get; } } -} +} \ No newline at end of file diff --git a/ELFSharp/ELF/Segments/ISegment.cs b/ELFSharp/ELF/Segments/ISegment.cs index 9bc52ff..4ad2a43 100644 --- a/ELFSharp/ELF/Segments/ISegment.cs +++ b/ELFSharp/ELF/Segments/ISegment.cs @@ -8,5 +8,4 @@ public interface ISegment byte[] GetFileContents(); byte[] GetMemoryContents(); } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Segments/NoteSegment.cs b/ELFSharp/ELF/Segments/NoteSegment.cs index 4199b9a..3e4c3df 100644 --- a/ELFSharp/ELF/Segments/NoteSegment.cs +++ b/ELFSharp/ELF/Segments/NoteSegment.cs @@ -7,13 +7,16 @@ namespace ELFSharp.ELF.Segments { public sealed class NoteSegment : Segment, INoteSegment { + private readonly NoteData data; + + private readonly List notes = new List(); internal NoteSegment(long headerOffset, Class elfClass, SimpleEndianessAwareReader reader) : base(headerOffset, elfClass, reader) { - ulong offset = (ulong)base.Offset; - ulong fileSize = (ulong)base.FileSize; - ulong remainingSize = fileSize; + var offset = (ulong)Offset; + var fileSize = (ulong)FileSize; + var remainingSize = fileSize; // Keep the first NoteData as a property for backwards compatibility data = new NoteData(offset, remainingSize, reader); @@ -33,14 +36,10 @@ internal NoteSegment(long headerOffset, Class elfClass, SimpleEndianessAwareRead notes.Add(note); offset += note.NoteFileSize; if (note.NoteFileSize <= remainingSize) - { remainingSize -= note.NoteFileSize; - } else - { // File is damaged throw new IndexOutOfRangeException("NoteSegment internal note-data is out of bounds"); - } } } } @@ -50,10 +49,6 @@ internal NoteSegment(long headerOffset, Class elfClass, SimpleEndianessAwareRead public ulong NoteType => data.Type; public byte[] NoteDescription => data.DescriptionBytes; - public IReadOnlyList Notes { get => notes.AsReadOnly(); } - - private List notes = new List(); - - private readonly NoteData data; + public IReadOnlyList Notes => notes.AsReadOnly(); } -} +} \ No newline at end of file diff --git a/ELFSharp/ELF/Segments/Segment.cs b/ELFSharp/ELF/Segments/Segment.cs index 414da53..2a64659 100644 --- a/ELFSharp/ELF/Segments/Segment.cs +++ b/ELFSharp/ELF/Segments/Segment.cs @@ -6,18 +6,19 @@ namespace ELFSharp.ELF.Segments { public class Segment : ISegment { + private readonly Class elfClass; + + private readonly long headerOffset; + private readonly SimpleEndianessAwareReader reader; + internal Segment(long headerOffset, Class elfClass, SimpleEndianessAwareReader reader) - { - this.reader = reader; + { + this.reader = reader; this.headerOffset = headerOffset; this.elfClass = elfClass; ReadHeader(); } - public SegmentType Type { get; private set; } - - public SegmentFlags Flags { get; private set; } - public T Address { get; private set; } public T PhysicalAddress { get; private set; } @@ -30,22 +31,18 @@ internal Segment(long headerOffset, Class elfClass, SimpleEndianessAwareReader r public long Offset { get; private set; } - public static SegmentType ProbeType(SimpleEndianessAwareReader reader) - { - return (SegmentType)reader.ReadUInt32(); - } + public SegmentType Type { get; private set; } + + public SegmentFlags Flags { get; private set; } /// - /// Returns content of the section as it is given in the file. - /// Note that it may be an array of length 0. + /// Returns content of the section as it is given in the file. + /// Note that it may be an array of length 0. /// /// Segment contents as byte array. public byte[] GetFileContents() { - if(FileSize == 0) - { - return new byte[0]; - } + if (FileSize == 0) return new byte[0]; SeekTo(Offset); var result = new byte[checked((int)FileSize)]; @@ -55,23 +52,20 @@ public byte[] GetFileContents() } /// - /// Returns content of the section, possibly padded or truncated to the memory size. - /// Note that it may be an array of length 0. + /// Returns content of the section, possibly padded or truncated to the memory size. + /// Note that it may be an array of length 0. /// /// Segment image as a byte array. public byte[] GetMemoryContents() { var sizeAsInt = Size.To(); - if(sizeAsInt == 0) - { - return new byte[0]; - } + if (sizeAsInt == 0) return new byte[0]; SeekTo(Offset); var result = new byte[sizeAsInt]; var fileImage = reader.ReadBytes(Math.Min(result.Length, checked((int)FileSize))); fileImage.CopyTo(result, 0); - return result; + return result; } public byte[] GetRawHeader() @@ -80,6 +74,11 @@ public byte[] GetRawHeader() return reader.ReadBytes(elfClass == Class.Bit32 ? 32 : 56); } + public static SegmentType ProbeType(SimpleEndianessAwareReader reader) + { + return (SegmentType)reader.ReadUInt32(); + } + public override string ToString() { return string.Format("{2}: size {3}, @ 0x{0:X}", Address, PhysicalAddress, Type, Size); @@ -89,20 +88,14 @@ private void ReadHeader() { SeekTo(headerOffset); Type = (SegmentType)reader.ReadUInt32(); - if(elfClass == Class.Bit64) - { - Flags = (SegmentFlags)reader.ReadUInt32(); - } + if (elfClass == Class.Bit64) Flags = (SegmentFlags)reader.ReadUInt32(); // TODO: some functions?s Offset = elfClass == Class.Bit32 ? reader.ReadUInt32() : reader.ReadInt64(); Address = (elfClass == Class.Bit32 ? reader.ReadUInt32() : reader.ReadUInt64()).To(); PhysicalAddress = (elfClass == Class.Bit32 ? reader.ReadUInt32() : reader.ReadUInt64()).To(); FileSize = elfClass == Class.Bit32 ? reader.ReadInt32() : reader.ReadInt64(); Size = (elfClass == Class.Bit32 ? reader.ReadUInt32() : reader.ReadUInt64()).To(); - if(elfClass == Class.Bit32) - { - Flags = (SegmentFlags)reader.ReadUInt32(); - } + if (elfClass == Class.Bit32) Flags = (SegmentFlags)reader.ReadUInt32(); Alignment = (elfClass == Class.Bit32 ? reader.ReadUInt32() : reader.ReadUInt64()).To(); } @@ -111,10 +104,5 @@ private void SeekTo(long givenOffset) { reader.BaseStream.Seek(givenOffset, SeekOrigin.Begin); } - - private long headerOffset; - private Class elfClass; - private SimpleEndianessAwareReader reader; } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Segments/SegmentFlags.cs b/ELFSharp/ELF/Segments/SegmentFlags.cs index 998803b..6dd8a4b 100644 --- a/ELFSharp/ELF/Segments/SegmentFlags.cs +++ b/ELFSharp/ELF/Segments/SegmentFlags.cs @@ -9,5 +9,4 @@ public enum SegmentFlags : uint Write = 2, Read = 4 } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELF/Segments/SegmentType.cs b/ELFSharp/ELF/Segments/SegmentType.cs index 563eab4..438c421 100644 --- a/ELFSharp/ELF/Segments/SegmentType.cs +++ b/ELFSharp/ELF/Segments/SegmentType.cs @@ -1,14 +1,13 @@ namespace ELFSharp.ELF.Segments { - public enum SegmentType : uint - { - Null = 0, - Load, - Dynamic, - Interpreter, - Note, - SharedLibrary, - ProgramHeader - } -} - + public enum SegmentType : uint + { + Null = 0, + Load, + Dynamic, + Interpreter, + Note, + SharedLibrary, + ProgramHeader + } +} \ No newline at end of file diff --git a/ELFSharp/ELF/Utilities.cs b/ELFSharp/ELF/Utilities.cs index 9920d65..5fff916 100644 --- a/ELFSharp/ELF/Utilities.cs +++ b/ELFSharp/ELF/Utilities.cs @@ -9,5 +9,4 @@ internal static T To(this object source) return (T)Convert.ChangeType(source, typeof(T)); } } -} - +} \ No newline at end of file diff --git a/ELFSharp/ELFSharp.csproj b/ELFSharp/ELFSharp.csproj index 8952595..0cadb2c 100644 --- a/ELFSharp/ELFSharp.csproj +++ b/ELFSharp/ELFSharp.csproj @@ -1,25 +1,25 @@  - - netstandard2.0 - True - sgKey.snk - 2.17.3.0 - 2.0 - Konrad Kruczyński, Piotr Zierhoffer, Łukasz Kucharski, Bastian Eicher, Cameron, Everett Maus, Fox, Reuben Olinsky, Connor Christie, Rollrat, Ulysses Wu, Cédric Luthi, Yong Yan, Filip Navara, Dedmen Miller, Murat Ocaktürk, Grivus, Alex E., Pavel Vorozheykin - Konrad Kruczyński - http://elfsharp.it/ - Fixed magic value for the x64 Big Endian Mach-O binaries. Detailed changelog available at: https://github.com/konrad-kruczynski/elfsharp/blob/master/CHANGELOG.md - C# library for reading binary ELF, UImage, Mach-O files - ELF UImage Mach-O - ELFSharp - C# library for reading binary ELF, UImage, Mach-O files - ELFSharp - icon.png - MIT - - - - - + + netstandard2.0 + True + sgKey.snk + 2.17.3.0 + 2.0 + Konrad Kruczyński, Piotr Zierhoffer, Łukasz Kucharski, Bastian Eicher, Cameron, Everett Maus, Fox, Reuben Olinsky, Connor Christie, Rollrat, Ulysses Wu, Cédric Luthi, Yong Yan, Filip Navara, Dedmen Miller, Murat Ocaktürk, Grivus, Alex E., Pavel Vorozheykin + Konrad Kruczyński + http://elfsharp.it/ + Fixed magic value for the x64 Big Endian Mach-O binaries. Detailed changelog available at: https://github.com/konrad-kruczynski/elfsharp/blob/master/CHANGELOG.md + C# library for reading binary ELF, UImage, Mach-O files + ELF UImage Mach-O + ELFSharp + C# library for reading binary ELF, UImage, Mach-O files + ELFSharp + icon.png + MIT + + + + + diff --git a/ELFSharp/Endianess.cs b/ELFSharp/Endianess.cs index 1f25152..d53993f 100644 --- a/ELFSharp/Endianess.cs +++ b/ELFSharp/Endianess.cs @@ -1,8 +1,8 @@ namespace ELFSharp { - public enum Endianess - { - LittleEndian, - BigEndian - } + public enum Endianess + { + LittleEndian, + BigEndian + } } \ No newline at end of file diff --git a/ELFSharp/MachO/Command.cs b/ELFSharp/MachO/Command.cs index 9f9ef6f..cdc45c1 100644 --- a/ELFSharp/MachO/Command.cs +++ b/ELFSharp/MachO/Command.cs @@ -5,14 +5,13 @@ namespace ELFSharp.MachO { public class Command { + protected readonly SimpleEndianessAwareReader Reader; + protected readonly Stream Stream; + internal Command(SimpleEndianessAwareReader reader, Stream stream) { Stream = stream; Reader = reader; } - - protected readonly SimpleEndianessAwareReader Reader; - protected readonly Stream Stream; } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/CommandType.cs b/ELFSharp/MachO/CommandType.cs index 7534639..5c1c391 100644 --- a/ELFSharp/MachO/CommandType.cs +++ b/ELFSharp/MachO/CommandType.cs @@ -10,7 +10,6 @@ public enum CommandType : uint Segment64 = 0x19, ReexportDylib = 0x8000001fu, Main = 0x80000028u, - UUID = 0x1b, + UUID = 0x1b } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/Dylib.cs b/ELFSharp/MachO/Dylib.cs index 0901488..ef0e36a 100644 --- a/ELFSharp/MachO/Dylib.cs +++ b/ELFSharp/MachO/Dylib.cs @@ -24,12 +24,15 @@ internal Dylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSiz public Version CurrentVersion { get; } public Version CompatibilityVersion { get; } - private static Version GetVersion(uint version) => new Version((int)(version >> 16), (int)((version >> 8) & 0xff), (int)(version & 0xff)); + private static Version GetVersion(uint version) + { + return new Version((int)(version >> 16), (int)((version >> 8) & 0xff), (int)(version & 0xff)); + } private static string GetString(byte[] bytes) { var nullTerminatorIndex = Array.FindIndex(bytes, e => e == '\0'); - return Encoding.ASCII.GetString(bytes, index: 0, nullTerminatorIndex >= 0 ? nullTerminatorIndex : bytes.Length); + return Encoding.ASCII.GetString(bytes, 0, nullTerminatorIndex >= 0 ? nullTerminatorIndex : bytes.Length); } } } \ No newline at end of file diff --git a/ELFSharp/MachO/EntryPoint.cs b/ELFSharp/MachO/EntryPoint.cs index 512f687..06e6e3c 100644 --- a/ELFSharp/MachO/EntryPoint.cs +++ b/ELFSharp/MachO/EntryPoint.cs @@ -14,7 +14,5 @@ public EntryPoint(SimpleEndianessAwareReader reader, Stream stream) : base(reade public long Value { get; private set; } public long StackSize { get; private set; } - } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/FatArchiveReader.cs b/ELFSharp/MachO/FatArchiveReader.cs index e82b2ab..1e0cd7c 100644 --- a/ELFSharp/MachO/FatArchiveReader.cs +++ b/ELFSharp/MachO/FatArchiveReader.cs @@ -1,5 +1,4 @@ -using System; -using System.Collections.Generic; +using System.Collections.Generic; using System.IO; using ELFSharp.Utilities; @@ -17,7 +16,7 @@ public static IEnumerable Enumerate(Stream stream, bool shouldOwnStream) var alreadyRead = 0; var fatEntriesBegin = stream.Position; - while(alreadyRead < machOCount) + while (alreadyRead < machOCount) { // We're only interested in offset and size. stream.Seek(fatEntriesBegin + 20 * alreadyRead + 8, SeekOrigin.Begin); @@ -30,4 +29,4 @@ public static IEnumerable Enumerate(Stream stream, bool shouldOwnStream) } } } -} +} \ No newline at end of file diff --git a/ELFSharp/MachO/FileType.cs b/ELFSharp/MachO/FileType.cs index e71caf6..0c306b3 100644 --- a/ELFSharp/MachO/FileType.cs +++ b/ELFSharp/MachO/FileType.cs @@ -14,5 +14,4 @@ public enum FileType : uint Debug = 0xA, Kext = 0xB } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/HeaderFlags.cs b/ELFSharp/MachO/HeaderFlags.cs index 52f52b0..636456c 100644 --- a/ELFSharp/MachO/HeaderFlags.cs +++ b/ELFSharp/MachO/HeaderFlags.cs @@ -49,9 +49,11 @@ public enum HeaderFlags : uint AllowStackExecution = 0x20000, /* When this bit is set, all stacks in the task will be given stack * execution privilege. Only used in MH_EXECUTE filetypes. */ - RootSafe = 0x40000, /* When this bit is set, the binary declares it is safe for use in processes with uid zero */ + RootSafe = + 0x40000, /* When this bit is set, the binary declares it is safe for use in processes with uid zero */ - SetuidSafe = 0x80000, /* When this bit is set, the binary declares it is safe for use in processes when issetugid() is true */ + SetuidSafe = + 0x80000, /* When this bit is set, the binary declares it is safe for use in processes when issetugid() is true */ NoReexportedDylibs = 0x100000, /* When this bit is set on a dylib, the static linker does not need to * examine dependent dylibs to see if any are re-exported */ diff --git a/ELFSharp/MachO/IdDylib.cs b/ELFSharp/MachO/IdDylib.cs index bf4a25c..978cfa3 100644 --- a/ELFSharp/MachO/IdDylib.cs +++ b/ELFSharp/MachO/IdDylib.cs @@ -5,7 +5,8 @@ namespace ELFSharp.MachO { public class IdDylib : Dylib { - public IdDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, commandSize) + public IdDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, + commandSize) { } } diff --git a/ELFSharp/MachO/LoadDylib.cs b/ELFSharp/MachO/LoadDylib.cs index ae58d60..865206b 100644 --- a/ELFSharp/MachO/LoadDylib.cs +++ b/ELFSharp/MachO/LoadDylib.cs @@ -5,7 +5,8 @@ namespace ELFSharp.MachO { public class LoadDylib : Dylib { - public LoadDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, commandSize) + public LoadDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, + commandSize) { } } diff --git a/ELFSharp/MachO/LoadWeakDylib.cs b/ELFSharp/MachO/LoadWeakDylib.cs index 3f11039..64feac8 100644 --- a/ELFSharp/MachO/LoadWeakDylib.cs +++ b/ELFSharp/MachO/LoadWeakDylib.cs @@ -5,7 +5,8 @@ namespace ELFSharp.MachO { public class LoadWeakDylib : Dylib { - public LoadWeakDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, commandSize) + public LoadWeakDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, + commandSize) { } } diff --git a/ELFSharp/MachO/MachO.cs b/ELFSharp/MachO/MachO.cs index 1f0862c..e1368d5 100644 --- a/ELFSharp/MachO/MachO.cs +++ b/ELFSharp/MachO/MachO.cs @@ -1,5 +1,5 @@ -using System.IO; using System.Collections.Generic; +using System.IO; using System.Linq; using ELFSharp.Utilities; @@ -7,9 +7,12 @@ namespace ELFSharp.MachO { public sealed class MachO { + internal const int Architecture64 = 0x1000000; + private readonly Command[] commands; + internal MachO(Stream stream, bool is64, Endianess endianess, bool ownsStream) { - this.is64 = is64; + this.Is64 = is64; using var reader = new SimpleEndianessAwareReader(stream, endianess, !ownsStream); @@ -19,71 +22,63 @@ internal MachO(Stream stream, bool is64, Endianess endianess, bool ownsStream) var noOfCommands = reader.ReadInt32(); reader.ReadInt32(); // size of commands Flags = (HeaderFlags)reader.ReadUInt32(); - if(is64) - { - reader.ReadBytes(4); // reserved - } + if (is64) reader.ReadBytes(4); // reserved commands = new Command[noOfCommands]; ReadCommands(noOfCommands, stream, reader); } - public IEnumerable GetCommandsOfType() where T : Command - { - return commands.Where(x => x != null).OfType(); - } - public Machine Machine { get; private set; } public FileType FileType { get; private set; } public HeaderFlags Flags { get; private set; } - public bool Is64 => is64; + public bool Is64 { get; } + + public IEnumerable GetCommandsOfType() where T : Command + { + return commands.Where(x => x != null).OfType(); + } private void ReadCommands(int noOfCommands, Stream stream, SimpleEndianessAwareReader reader) { - for(var i = 0; i < noOfCommands; i++) + for (var i = 0; i < noOfCommands; i++) { var loadCommandType = reader.ReadUInt32(); var commandSize = reader.ReadUInt32(); - switch((CommandType)loadCommandType) + switch ((CommandType)loadCommandType) { - case CommandType.SymbolTable: - commands[i] = new SymbolTable(reader, stream, is64, commands.OfType().SelectMany(e => e.Sections).ToList()); - break; - case CommandType.IdDylib: - commands[i] = new IdDylib(reader, stream, commandSize); - break; - case CommandType.LoadDylib: - commands[i] = new LoadDylib(reader, stream, commandSize); - break; - case CommandType.LoadWeakDylib: - commands[i] = new LoadWeakDylib(reader, stream, commandSize); - break; - case CommandType.ReexportDylib: - commands[i] = new ReexportDylib(reader, stream, commandSize); - break; - case CommandType.Main: - commands[i] = new EntryPoint(reader, stream); - break; - case CommandType.Segment: - case CommandType.Segment64: - commands[i] = new Segment(reader, stream, this); - break; - case CommandType.UUID: - commands[i] = new UUID(reader, stream); - break; - default: - reader.ReadBytes((int)commandSize - 8); // 8 bytes is the size of the common command header - break; + case CommandType.SymbolTable: + commands[i] = new SymbolTable(reader, stream, Is64, + commands.OfType().SelectMany(e => e.Sections).ToList()); + break; + case CommandType.IdDylib: + commands[i] = new IdDylib(reader, stream, commandSize); + break; + case CommandType.LoadDylib: + commands[i] = new LoadDylib(reader, stream, commandSize); + break; + case CommandType.LoadWeakDylib: + commands[i] = new LoadWeakDylib(reader, stream, commandSize); + break; + case CommandType.ReexportDylib: + commands[i] = new ReexportDylib(reader, stream, commandSize); + break; + case CommandType.Main: + commands[i] = new EntryPoint(reader, stream); + break; + case CommandType.Segment: + case CommandType.Segment64: + commands[i] = new Segment(reader, stream, this); + break; + case CommandType.UUID: + commands[i] = new UUID(reader, stream); + break; + default: + reader.ReadBytes((int)commandSize - 8); // 8 bytes is the size of the common command header + break; } } } - - private readonly bool is64; - private readonly Command[] commands; - - internal const int Architecture64 = 0x1000000; } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/MachOReader.cs b/ELFSharp/MachO/MachOReader.cs index 3c0a057..41e2bab 100644 --- a/ELFSharp/MachO/MachOReader.cs +++ b/ELFSharp/MachO/MachOReader.cs @@ -8,6 +8,22 @@ namespace ELFSharp.MachO { public static class MachOReader { + private const uint FatMagic = 0xBEBAFECA; + + private const string FatArchiveErrorMessage = + "Given file is a fat archive, contains more than one MachO binary. Use (Try)LoadFat to handle it."; + + private const string NotMachOErrorMessage = "Given file is not a Mach-O file."; + + private static readonly IReadOnlyDictionary MagicToMachOType = + new Dictionary + { + { 0xFEEDFACE, (false, Endianess.LittleEndian) }, + { 0xFEEDFACF, (true, Endianess.LittleEndian) }, + { 0xCEFAEDFE, (false, Endianess.BigEndian) }, + { 0xCFFAEDFE, (true, Endianess.BigEndian) } + }; + public static MachO Load(string fileName) { return Load(File.OpenRead(fileName), true); @@ -15,22 +31,19 @@ public static MachO Load(string fileName) public static MachO Load(Stream stream, bool shouldOwnStream) { - return (TryLoad(stream, shouldOwnStream, out MachO result)) switch + return TryLoad(stream, shouldOwnStream, out var result) switch { MachOResult.OK => result, MachOResult.NotMachO => throw new InvalidOperationException(NotMachOErrorMessage), MachOResult.FatMachO => throw new InvalidOperationException(FatArchiveErrorMessage), - _ => throw new ArgumentOutOfRangeException(), + _ => throw new ArgumentOutOfRangeException() }; } public static IReadOnlyList LoadFat(Stream stream, bool shouldOwnStream) { var result = TryLoadFat(stream, shouldOwnStream, out var machOs); - if(result == MachOResult.OK || result == MachOResult.FatMachO) - { - return machOs; - } + if (result == MachOResult.OK || result == MachOResult.FatMachO) return machOs; throw new InvalidOperationException(NotMachOErrorMessage); } @@ -44,14 +57,10 @@ public static MachOResult TryLoad(Stream stream, bool shouldOwnStream, out MachO { var result = TryLoadFat(stream, shouldOwnStream, out var machOs); - if(result == MachOResult.OK) - { + if (result == MachOResult.OK) machO = machOs.SingleOrDefault(); - } else - { machO = null; - } return result; } @@ -63,33 +72,17 @@ public static MachOResult TryLoadFat(Stream stream, bool shouldOwnStream, out IR using var reader = new BinaryReader(stream, Encoding.UTF8, true); var magic = reader.ReadUInt32(); - if(magic == FatMagic) + if (magic == FatMagic) { machOs = FatArchiveReader.Enumerate(stream, shouldOwnStream).ToArray(); return MachOResult.FatMachO; } - if(!MagicToMachOType.TryGetValue(magic, out var machOType)) - { - return MachOResult.NotMachO; - } + if (!MagicToMachOType.TryGetValue(magic, out var machOType)) return MachOResult.NotMachO; var machO = new MachO(stream, machOType.Is64Bit, machOType.Endianess, shouldOwnStream); machOs = new[] { machO }; return MachOResult.OK; } - - private static readonly IReadOnlyDictionary MagicToMachOType = new Dictionary - { - { 0xFEEDFACE, (false, Endianess.LittleEndian) }, - { 0xFEEDFACF, (true, Endianess.LittleEndian) }, - { 0xCEFAEDFE, (false, Endianess.BigEndian) }, - { 0xCFFAEDFE, (true, Endianess.BigEndian) } - }; - - private const uint FatMagic = 0xBEBAFECA; - private const string FatArchiveErrorMessage = "Given file is a fat archive, contains more than one MachO binary. Use (Try)LoadFat to handle it."; - private const string NotMachOErrorMessage = "Given file is not a Mach-O file."; } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/MachOResult.cs b/ELFSharp/MachO/MachOResult.cs index 3dcb9cd..e877f56 100644 --- a/ELFSharp/MachO/MachOResult.cs +++ b/ELFSharp/MachO/MachOResult.cs @@ -2,9 +2,8 @@ { public enum MachOResult { - OK, + OK, NotMachO, FatMachO } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/Machine.cs b/ELFSharp/MachO/Machine.cs index ab89148..acf70df 100644 --- a/ELFSharp/MachO/Machine.cs +++ b/ELFSharp/MachO/Machine.cs @@ -1,6 +1,6 @@ namespace ELFSharp.MachO { - public enum Machine : int + public enum Machine { Any = -1, Vax = 1, @@ -17,7 +17,4 @@ public enum Machine : int PowerPc = 18, PowerPc64 = PowerPc | MachO.Architecture64 } - - -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/Protection.cs b/ELFSharp/MachO/Protection.cs index 6006077..fa3c2d1 100644 --- a/ELFSharp/MachO/Protection.cs +++ b/ELFSharp/MachO/Protection.cs @@ -9,5 +9,4 @@ public enum Protection Write = 2, Execute = 4 } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/ReexportDylib.cs b/ELFSharp/MachO/ReexportDylib.cs index d882fe0..1f86b59 100644 --- a/ELFSharp/MachO/ReexportDylib.cs +++ b/ELFSharp/MachO/ReexportDylib.cs @@ -5,7 +5,8 @@ namespace ELFSharp.MachO { public class ReexportDylib : Dylib { - public ReexportDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, commandSize) + public ReexportDylib(SimpleEndianessAwareReader reader, Stream stream, uint commandSize) : base(reader, stream, + commandSize) { } } diff --git a/ELFSharp/MachO/Section.cs b/ELFSharp/MachO/Section.cs index 018b0e8..43e0575 100644 --- a/ELFSharp/MachO/Section.cs +++ b/ELFSharp/MachO/Section.cs @@ -6,7 +6,10 @@ namespace ELFSharp.MachO [DebuggerDisplay("Section({segment.Name,nq},{Name,nq})")] public sealed class Section { - public Section(string name, string segmentName, ulong address, ulong size, uint offset, uint alignExponent, uint relocOffset, uint numberOfReloc, uint flags, Segment segment) + private readonly Segment segment; + + public Section(string name, string segmentName, ulong address, ulong size, uint offset, uint alignExponent, + uint relocOffset, uint numberOfReloc, uint flags, Segment segment) { Name = name; SegmentName = segmentName; @@ -23,8 +26,8 @@ public Section(string name, string segmentName, ulong address, ulong size, uint public string Name { get; private set; } public string SegmentName { get; private set; } public ulong Address { get; private set; } - public ulong Size { get; private set; } - public uint Offset { get; private set; } + public ulong Size { get; } + public uint Offset { get; } public uint AlignExponent { get; private set; } public uint RelocOffset { get; private set; } public uint RelocCount { get; private set; } @@ -32,16 +35,10 @@ public Section(string name, string segmentName, ulong address, ulong size, uint public byte[] GetData() { - if (Offset < segment.FileOffset || Offset + Size > segment.FileOffset + segment.Size) - { - return new byte[0]; - } + if (Offset < segment.FileOffset || Offset + Size > segment.FileOffset + segment.Size) return new byte[0]; var result = new byte[Size]; Array.Copy(segment.GetData(), (int)(Offset - segment.FileOffset), result, 0, (int)Size); return result; } - - private readonly Segment segment; } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/Segment.cs b/ELFSharp/MachO/Segment.cs index bf20945..68fe47d 100644 --- a/ELFSharp/MachO/Segment.cs +++ b/ELFSharp/MachO/Segment.cs @@ -1,10 +1,10 @@ using System; -using System.IO; -using System.Linq; -using System.Text; using System.Collections.Generic; using System.Collections.ObjectModel; using System.Diagnostics; +using System.IO; +using System.Linq; +using System.Text; using ELFSharp.Utilities; namespace ELFSharp.MachO @@ -12,9 +12,13 @@ namespace ELFSharp.MachO [DebuggerDisplay("{Type}({Name,nq})")] public sealed class Segment : Command { + private readonly byte[] data; + + private readonly bool is64; + public Segment(SimpleEndianessAwareReader reader, Stream stream, MachO machO) : base(reader, stream) { - this.is64 = machO.Is64; + is64 = machO.Is64; Name = ReadSectionOrSegmentName(); Address = ReadUInt32OrUInt64(); Size = ReadUInt32OrUInt64(); @@ -25,18 +29,18 @@ public Segment(SimpleEndianessAwareReader reader, Stream stream, MachO machO) : var numberOfSections = Reader.ReadInt32(); Reader.ReadInt32(); // we ignore flags for now - if(fileSize > 0) + if (fileSize > 0) { var streamPosition = Stream.Position; Stream.Seek((long)FileOffset, SeekOrigin.Begin); - data = new byte[Size]; + data = new byte[Size]; var buffer = stream.ReadBytesOrThrow(checked((int)fileSize)); Array.Copy(buffer, data, buffer.Length); Stream.Position = streamPosition; } var sections = new List
(); - for(var i = 0; i < numberOfSections; i++) + for (var i = 0; i < numberOfSections; i++) { var sectionName = ReadSectionOrSegmentName(); var segmentName = ReadSectionOrSegmentName(); @@ -44,9 +48,7 @@ public Segment(SimpleEndianessAwareReader reader, Stream stream, MachO machO) : // An intermediate object file contains only one segment. // This segment name is empty, its sections segment names are not empty. if (machO.FileType != FileType.Object && segmentName != Name) - { throw new InvalidOperationException("Unexpected name of the section's segment."); - } var sectionAddress = ReadUInt32OrUInt64(); var sectionSize = ReadUInt32OrUInt64(); @@ -59,7 +61,8 @@ public Segment(SimpleEndianessAwareReader reader, Stream stream, MachO machO) : _ = Reader.ReadUInt32(); // reserved2 _ = is64 ? Reader.ReadUInt32() : 0; // reserved3 - var section = new Section(sectionName, segmentName, sectionAddress, sectionSize, offset, alignExponent, relocOffset, numberOfReloc, flags, this); + var section = new Section(sectionName, segmentName, sectionAddress, sectionSize, offset, alignExponent, + relocOffset, numberOfReloc, flags, this); sections.Add(section); } @@ -68,8 +71,8 @@ public Segment(SimpleEndianessAwareReader reader, Stream stream, MachO machO) : public string Name { get; private set; } public ulong Address { get; private set; } - public ulong Size { get; private set; } - public ulong FileOffset { get; private set; } + public ulong Size { get; } + public ulong FileOffset { get; } public Protection InitialProtection { get; private set; } public Protection MaximalProtection { get; private set; } public ReadOnlyCollection
Sections { get; private set; } @@ -77,10 +80,7 @@ public Segment(SimpleEndianessAwareReader reader, Stream stream, MachO machO) : public byte[] GetData() { - if(data == null) - { - return new byte[Size]; - } + if (data == null) return new byte[Size]; return data.ToArray(); } @@ -99,9 +99,5 @@ private string ReadSectionOrSegmentName() var nameAsBytes = Reader.ReadBytes(16).TakeWhile(x => x != 0).ToArray(); return Encoding.UTF8.GetString(nameAsBytes); } - - private readonly bool is64; - private readonly byte[] data; } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/Symbol.cs b/ELFSharp/MachO/Symbol.cs index a63421c..8d9213a 100644 --- a/ELFSharp/MachO/Symbol.cs +++ b/ELFSharp/MachO/Symbol.cs @@ -1,5 +1,4 @@ -using System; -using System.Diagnostics; +using System.Diagnostics; namespace ELFSharp.MachO { @@ -14,8 +13,7 @@ public Symbol(string name, long value, Section section) : this() } public string Name { get; private set; } - public Int64 Value { get; private set; } + public long Value { get; private set; } public Section Section { get; private set; } } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/SymbolTable.cs b/ELFSharp/MachO/SymbolTable.cs index 87a625b..6f869b9 100644 --- a/ELFSharp/MachO/SymbolTable.cs +++ b/ELFSharp/MachO/SymbolTable.cs @@ -1,5 +1,5 @@ -using System.IO; -using System.Collections.Generic; +using System.Collections.Generic; +using System.IO; using System.Linq; using System.Text; using ELFSharp.Utilities; @@ -8,7 +8,12 @@ namespace ELFSharp.MachO { public class SymbolTable : Command { - public SymbolTable(SimpleEndianessAwareReader reader, Stream stream, bool is64, IReadOnlyList
sections) : base(reader, stream) + private readonly bool is64; + + private Symbol[] symbols; + + public SymbolTable(SimpleEndianessAwareReader reader, Stream stream, bool is64, IReadOnlyList
sections) + : base(reader, stream) { this.is64 = is64; ReadSymbols(sections); @@ -16,10 +21,7 @@ public SymbolTable(SimpleEndianessAwareReader reader, Stream stream, bool is64, public IEnumerable Symbols { - get - { - return symbols.Select(x => x); - } + get { return symbols.Select(x => x); } } private void ReadSymbols(IReadOnlyList
sections) @@ -35,15 +37,16 @@ private void ReadSymbols(IReadOnlyList
sections) try { - for(var i = 0; i < numberOfSymbols; i++) + for (var i = 0; i < numberOfSymbols; i++) { var nameOffset = Reader.ReadInt32(); var name = ReadStringFromOffset(stringTableOffset + nameOffset); var type = Reader.ReadByte(); var sect = Reader.ReadByte(); var desc = Reader.ReadInt16(); - long value = is64 ? Reader.ReadInt64() : Reader.ReadInt32(); - var symbol = new Symbol(name, value, sect > 0 && sect <= sections.Count ? sections[sect - 1] : null); + var value = is64 ? Reader.ReadInt64() : Reader.ReadInt32(); + var symbol = new Symbol(name, value, + sect > 0 && sect <= sections.Count ? sections[sect - 1] : null); symbols[i] = symbol; } } @@ -61,14 +64,13 @@ private string ReadStringFromOffset(int offset) { var asBytes = new List(); int readByte; - while((readByte = Stream.ReadByte()) != 0) + while ((readByte = Stream.ReadByte()) != 0) { - if(readByte == -1) - { + if (readByte == -1) throw new EndOfStreamException("Premature end of the stream while reading string."); - } asBytes.Add((byte)readByte); } + return Encoding.UTF8.GetString(asBytes.ToArray()); } finally @@ -76,9 +78,5 @@ private string ReadStringFromOffset(int offset) Stream.Position = streamPosition; } } - - private Symbol[] symbols; - private readonly bool is64; } -} - +} \ No newline at end of file diff --git a/ELFSharp/MachO/UUID.cs b/ELFSharp/MachO/UUID.cs index 82eb6d8..a5ab263 100644 --- a/ELFSharp/MachO/UUID.cs +++ b/ELFSharp/MachO/UUID.cs @@ -1,15 +1,12 @@ using System; -using System.Collections.Generic; using System.IO; using System.Linq; -using System.Net; -using System.Text; using ELFSharp.Utilities; namespace ELFSharp.MachO { - public class UUID : Command - { + public class UUID : Command + { internal UUID(SimpleEndianessAwareReader reader, Stream stream) : base(reader, stream) { ID = ReadUUID(); @@ -31,5 +28,4 @@ private Guid ReadUUID() return guid; } } -} - +} \ No newline at end of file diff --git a/ELFSharp/UImage/Architecture.cs b/ELFSharp/UImage/Architecture.cs index b0c3be7..cea1ae2 100644 --- a/ELFSharp/UImage/Architecture.cs +++ b/ELFSharp/UImage/Architecture.cs @@ -1,30 +1,27 @@ -using System; - namespace ELFSharp.UImage { - public enum Architecture : byte - { - Invalid = 0, - Alpha = 1, - ARM = 2, - Ix86 = 3, - Itanium = 4, - MIPS = 5, - MIPS64 = 6, - PowerPC = 7, - S390 = 8, - SuperH = 9, - SPARC = 10, - SPARC64 = 11, - M68k = 12, - MicroBlaze = 14, - Nios2 = 15, - Blackfin = 16, - AVR32 = 17, - ST200 = 18, - Sandbox = 19, - NDS32 = 20, - OpenRISC = 21 - } -} - + public enum Architecture : byte + { + Invalid = 0, + Alpha = 1, + ARM = 2, + Ix86 = 3, + Itanium = 4, + MIPS = 5, + MIPS64 = 6, + PowerPC = 7, + S390 = 8, + SuperH = 9, + SPARC = 10, + SPARC64 = 11, + M68k = 12, + MicroBlaze = 14, + Nios2 = 15, + Blackfin = 16, + AVR32 = 17, + ST200 = 18, + Sandbox = 19, + NDS32 = 20, + OpenRISC = 21 + } +} \ No newline at end of file diff --git a/ELFSharp/UImage/CompressionType.cs b/ELFSharp/UImage/CompressionType.cs index aa2ec15..0e90517 100644 --- a/ELFSharp/UImage/CompressionType.cs +++ b/ELFSharp/UImage/CompressionType.cs @@ -1,14 +1,11 @@ -using System; - namespace ELFSharp.UImage { - public enum CompressionType : byte - { - None = 0, - Gzip = 1, - Bzip2 = 2, - Lzma = 3, - Lzo = 4 - } -} - + public enum CompressionType : byte + { + None = 0, + Gzip = 1, + Bzip2 = 2, + Lzma = 3, + Lzo = 4 + } +} \ No newline at end of file diff --git a/ELFSharp/UImage/ImageDataResult.cs b/ELFSharp/UImage/ImageDataResult.cs index f811ceb..4878e59 100644 --- a/ELFSharp/UImage/ImageDataResult.cs +++ b/ELFSharp/UImage/ImageDataResult.cs @@ -1,13 +1,10 @@ -using System; - namespace ELFSharp.UImage { - public enum ImageDataResult - { - OK, - BadChecksum, - UnsupportedCompressionFormat, - InvalidIndex - } -} - + public enum ImageDataResult + { + OK, + BadChecksum, + UnsupportedCompressionFormat, + InvalidIndex + } +} \ No newline at end of file diff --git a/ELFSharp/UImage/ImageType.cs b/ELFSharp/UImage/ImageType.cs index 323811f..20fb5e9 100644 --- a/ELFSharp/UImage/ImageType.cs +++ b/ELFSharp/UImage/ImageType.cs @@ -1,13 +1,10 @@ -using System; - namespace ELFSharp.UImage { - // here only supported image types are listed - public enum ImageType : byte - { - Standalone = 1, - Kernel = 2, - MultiFileImage = 4 - } -} - + // here only supported image types are listed + public enum ImageType : byte + { + Standalone = 1, + Kernel = 2, + MultiFileImage = 4 + } +} \ No newline at end of file diff --git a/ELFSharp/UImage/OS.cs b/ELFSharp/UImage/OS.cs index 56bd8fa..9f52b31 100644 --- a/ELFSharp/UImage/OS.cs +++ b/ELFSharp/UImage/OS.cs @@ -1,33 +1,30 @@ -using System; - namespace ELFSharp.UImage { - public enum OS : byte - { - Invalid = 0, - OpenBSD = 1, - NetBSD = 2, - FreeBSD = 3, - BSD44 = 4, - Linux = 5, - SVR4 = 6, - Esix = 7, - Solaris = 8, - Irix = 9, - SCO = 10, - Dell = 11, - NCR = 12, - LynxOS = 13, - VxWorks = 14, - PSOS = 15, - QNX = 16, - Firmware = 17, - RTEMS = 18, - ARTOS = 19, - UnityOS = 20, - INTEGRITY = 21, - OSE = 22, - Plan9 = 23 - } -} - + public enum OS : byte + { + Invalid = 0, + OpenBSD = 1, + NetBSD = 2, + FreeBSD = 3, + BSD44 = 4, + Linux = 5, + SVR4 = 6, + Esix = 7, + Solaris = 8, + Irix = 9, + SCO = 10, + Dell = 11, + NCR = 12, + LynxOS = 13, + VxWorks = 14, + PSOS = 15, + QNX = 16, + Firmware = 17, + RTEMS = 18, + ARTOS = 19, + UnityOS = 20, + INTEGRITY = 21, + OSE = 22, + Plan9 = 23 + } +} \ No newline at end of file diff --git a/ELFSharp/UImage/UImage.cs b/ELFSharp/UImage/UImage.cs index 33b45db..00b4636 100644 --- a/ELFSharp/UImage/UImage.cs +++ b/ELFSharp/UImage/UImage.cs @@ -1,23 +1,29 @@ using System; +using System.Collections.Generic; using System.IO; -using System.Text; -using System.Linq; using System.IO.Compression; -using System.Collections.Generic; +using System.Linq; +using System.Text; namespace ELFSharp.UImage { - public sealed class UImage - { - internal UImage(Stream stream, bool multiFileImage, bool ownsStream) - { - this.shouldOwnStream = ownsStream; - imageSizes = new List(); + public sealed class UImage + { + private const int MaximumNameLength = 32; + private readonly List imageSizes; + private readonly byte[] rawImage; + private readonly bool shouldOwnStream; + + internal UImage(Stream stream, bool multiFileImage, bool ownsStream) + { + shouldOwnStream = ownsStream; + imageSizes = new List(); using var reader = new BinaryReader(stream, Encoding.UTF8, !ownsStream); reader.ReadBytes(8); // magic and CRC, already checked - Timestamp = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) + TimeSpan.FromSeconds(reader.ReadInt32BigEndian())).ToLocalTime(); + Timestamp = (new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc) + + TimeSpan.FromSeconds(reader.ReadInt32BigEndian())).ToLocalTime(); Size = reader.ReadUInt32BigEndian(); LoadAddress = reader.ReadUInt32BigEndian(); EntryPoint = reader.ReadUInt32BigEndian(); @@ -29,111 +35,90 @@ internal UImage(Stream stream, bool multiFileImage, bool ownsStream) var nameAsBytes = reader.ReadBytes(32); Name = Encoding.UTF8.GetString(nameAsBytes.Reverse().SkipWhile(x => x == 0).Reverse().ToArray()); - if (multiFileImage) - { - var startingPosition = stream.Position; - - int nextImageSize; - do - { - nextImageSize = reader.ReadInt32BigEndian(); - imageSizes.Add(nextImageSize); - } - while (nextImageSize != 0); - - // Last image size is actually a terminator. - imageSizes.RemoveAt(imageSizes.Count - 1); - ImageCount = imageSizes.Count; - stream.Position = startingPosition; - } + if (multiFileImage) + { + var startingPosition = stream.Position; + + int nextImageSize; + do + { + nextImageSize = reader.ReadInt32BigEndian(); + imageSizes.Add(nextImageSize); + } while (nextImageSize != 0); + + // Last image size is actually a terminator. + imageSizes.RemoveAt(imageSizes.Count - 1); + ImageCount = imageSizes.Count; + stream.Position = startingPosition; + } rawImage = reader.ReadBytes((int)Size); } - public uint CRC { get; private set; } - public bool IsChecksumOK { get; private set; } - public uint Size { get; private set; } - public uint LoadAddress { get; private set; } - public uint EntryPoint { get; private set; } - public string Name { get; private set; } - public DateTime Timestamp { get; private set; } - public CompressionType Compression { get; private set; } - public ImageType Type { get; private set; } - public OS OperatingSystem { get; private set; } - public Architecture Architecture { get; private set; } - public int ImageCount { get; private set; } - - public ImageDataResult TryGetImageData(int imageIndex, out byte[] result) - { - result = null; - - if (imageIndex > ImageCount - 1 || imageIndex < 0) - { - return ImageDataResult.InvalidIndex; - } - - if (ImageCount == 1) - { - return TryGetImageData(out result); - } + public uint CRC { get; } + public bool IsChecksumOK { get; private set; } + public uint Size { get; } + public uint LoadAddress { get; private set; } + public uint EntryPoint { get; private set; } + public string Name { get; private set; } + public DateTime Timestamp { get; private set; } + public CompressionType Compression { get; } + public ImageType Type { get; private set; } + public OS OperatingSystem { get; private set; } + public Architecture Architecture { get; private set; } + public int ImageCount { get; } + + public ImageDataResult TryGetImageData(int imageIndex, out byte[] result) + { + result = null; + + if (imageIndex > ImageCount - 1 || imageIndex < 0) return ImageDataResult.InvalidIndex; + + if (ImageCount == 1) return TryGetImageData(out result); if (Compression != CompressionType.None) - { // We only support multi file images without compression return ImageDataResult.UnsupportedCompressionFormat; - } - if (CRC != UImageReader.GzipCrc32(rawImage)) - { - return ImageDataResult.BadChecksum; - } + if (CRC != UImageReader.GzipCrc32(rawImage)) return ImageDataResult.BadChecksum; - // Images sizes * 4 + terminator (which also takes 4 bytes). + // Images sizes * 4 + terminator (which also takes 4 bytes). var startingOffset = 4 * (ImageCount + 1) + imageSizes.Take(imageIndex).Sum(); - result = new byte[imageSizes[imageIndex]]; - Array.Copy(rawImage, startingOffset, result, 0, result.Length); + result = new byte[imageSizes[imageIndex]]; + Array.Copy(rawImage, startingOffset, result, 0, result.Length); - return ImageDataResult.OK; - } + return ImageDataResult.OK; + } - public ImageDataResult TryGetImageData(out byte[] result) - { - result = null; + public ImageDataResult TryGetImageData(out byte[] result) + { + result = null; - if (ImageCount > 1) - { - return TryGetImageData(0, out result); - } + if (ImageCount > 1) return TryGetImageData(0, out result); if (Compression != CompressionType.None && Compression != CompressionType.Gzip) - { return ImageDataResult.UnsupportedCompressionFormat; - } - if (CRC != UImageReader.GzipCrc32(rawImage)) - { - return ImageDataResult.BadChecksum; - } - - result = new byte[rawImage.Length]; - Array.Copy(rawImage, result, result.Length); - if(Compression == CompressionType.Gzip) - { - using(var stream = new GZipStream(new MemoryStream(result), CompressionMode.Decompress)) - { - using(var decompressed = new MemoryStream()) - { - stream.CopyTo(decompressed); - result = decompressed.ToArray(); - } - } - } - return ImageDataResult.OK; - } + if (CRC != UImageReader.GzipCrc32(rawImage)) return ImageDataResult.BadChecksum; + + result = new byte[rawImage.Length]; + Array.Copy(rawImage, result, result.Length); + if (Compression == CompressionType.Gzip) + using (var stream = new GZipStream(new MemoryStream(result), CompressionMode.Decompress)) + { + using (var decompressed = new MemoryStream()) + { + stream.CopyTo(decompressed); + result = decompressed.ToArray(); + } + } + + return ImageDataResult.OK; + } public byte[] GetImageData(int imageIndex) { - byte[] result; + byte[] result; var imageDataResult = TryGetImageData(imageIndex, out result); return InterpretImageResult(result, imageDataResult); } @@ -147,26 +132,23 @@ public byte[] GetImageData() private byte[] InterpretImageResult(byte[] result, ImageDataResult imageDataResult) { - return imageDataResult switch - { - ImageDataResult.OK => result, - ImageDataResult.BadChecksum => throw new InvalidOperationException("Bad checksum of the image, probably corrupted image."), - ImageDataResult.UnsupportedCompressionFormat => throw new InvalidOperationException(string.Format("Unsupported compression format '{0}'.", Compression)), - ImageDataResult.InvalidIndex => throw new ArgumentException("Invalid image index."), - _ => throw new ArgumentOutOfRangeException() - }; + return imageDataResult switch + { + ImageDataResult.OK => result, + ImageDataResult.BadChecksum => throw new InvalidOperationException( + "Bad checksum of the image, probably corrupted image."), + ImageDataResult.UnsupportedCompressionFormat => throw new InvalidOperationException( + string.Format("Unsupported compression format '{0}'.", Compression)), + ImageDataResult.InvalidIndex => throw new ArgumentException("Invalid image index."), + _ => throw new ArgumentOutOfRangeException() + }; } public byte[] GetRawImageData() - { - var result = new byte[rawImage.Length]; - Array.Copy(rawImage, result, result.Length); - return result; - } - - private const int MaximumNameLength = 32; - private readonly byte[] rawImage; - private readonly List imageSizes; - private readonly bool shouldOwnStream; - } -} + { + var result = new byte[rawImage.Length]; + Array.Copy(rawImage, result, result.Length); + return result; + } + } +} \ No newline at end of file diff --git a/ELFSharp/UImage/UImageReader.cs b/ELFSharp/UImage/UImageReader.cs index f9d8747..e56d93b 100644 --- a/ELFSharp/UImage/UImageReader.cs +++ b/ELFSharp/UImage/UImageReader.cs @@ -5,110 +5,91 @@ namespace ELFSharp.UImage { - public static class UImageReader - { + public static class UImageReader + { + private const uint Magic = 0x27051956; + private const uint Polynomial = 0xEDB88320; + private const uint Seed = 0xFFFFFFFF; + public static UImage Load(string fileName) { - return Load(File.OpenRead(fileName), true); + return Load(File.OpenRead(fileName), true); } - public static UImage Load(Stream stream, bool shouldOwnStream) - { - return (TryLoad(stream, shouldOwnStream, out UImage result)) switch + public static UImage Load(Stream stream, bool shouldOwnStream) + { + return TryLoad(stream, shouldOwnStream, out var result) switch { UImageResult.OK => result, UImageResult.NotUImage => throw new InvalidOperationException("Given file is not an UBoot image."), - UImageResult.BadChecksum => throw new InvalidOperationException("Wrong header checksum of the given UImage file."), - UImageResult.NotSupportedImageType => throw new InvalidOperationException("Given image type is not supported."), - _ => throw new ArgumentOutOfRangeException(), + UImageResult.BadChecksum => throw new InvalidOperationException( + "Wrong header checksum of the given UImage file."), + UImageResult.NotSupportedImageType => throw new InvalidOperationException( + "Given image type is not supported."), + _ => throw new ArgumentOutOfRangeException() }; } public static UImageResult TryLoad(string fileName, out UImage uImage) { - return TryLoad(File.OpenRead(fileName), true, out uImage); + return TryLoad(File.OpenRead(fileName), true, out uImage); } - public static UImageResult TryLoad(Stream stream, bool shouldOwnStream, out UImage uImage) - { - var startingStreamPosition = stream.Position; + public static UImageResult TryLoad(Stream stream, bool shouldOwnStream, out UImage uImage) + { + var startingStreamPosition = stream.Position; + + uImage = null; + if (stream.Length < 64) return UImageResult.NotUImage; - uImage = null; - if(stream.Length < 64) - { - return UImageResult.NotUImage; - } - using var reader = new BinaryReader(stream, Encoding.UTF8, true); var headerForCrc = reader.ReadBytes(64); // we need to zero crc part - for(var i = 4; i < 8; i++) - { - headerForCrc[i] = 0; - } + for (var i = 4; i < 8; i++) headerForCrc[i] = 0; stream.Position = startingStreamPosition; var magic = reader.ReadUInt32BigEndian(); - if(magic != Magic) - { - return UImageResult.NotUImage; - } + if (magic != Magic) return UImageResult.NotUImage; var crc = reader.ReadUInt32BigEndian(); - if(crc != GzipCrc32(headerForCrc)) - { - return UImageResult.BadChecksum; - } + if (crc != GzipCrc32(headerForCrc)) return UImageResult.BadChecksum; reader.ReadBytes(22); var imageType = (ImageType)reader.ReadByte(); - if(!Enum.IsDefined(typeof(ImageType), imageType)) - { - return UImageResult.NotSupportedImageType; - } + if (!Enum.IsDefined(typeof(ImageType), imageType)) return UImageResult.NotSupportedImageType; - var multiFileImage = imageType == ImageType.MultiFileImage; + var multiFileImage = imageType == ImageType.MultiFileImage; stream.Position = startingStreamPosition; uImage = new UImage(stream, multiFileImage, shouldOwnStream); return UImageResult.OK; } - internal static uint GzipCrc32(byte[] data) - { - var remainder = Seed; - for(var i = 0; i < data.Length; i++) - { - remainder ^= data[i]; - for(var j = 0; j < 8; j++) - { - if((remainder & 1) != 0) - { - remainder = (remainder >> 1) ^ Polynomial; - } - else - { - remainder >>= 1; - } - } - } - return remainder ^ Seed; - } - - internal static uint ReadUInt32BigEndian(this BinaryReader reader) - { - return (uint)IPAddress.HostToNetworkOrder(reader.ReadInt32()); - } - - internal static int ReadInt32BigEndian(this BinaryReader reader) - { - return IPAddress.HostToNetworkOrder(reader.ReadInt32()); - } - - private const uint Magic = 0x27051956; - private const uint Polynomial = 0xEDB88320; - private const uint Seed = 0xFFFFFFFF; - } -} + internal static uint GzipCrc32(byte[] data) + { + var remainder = Seed; + for (var i = 0; i < data.Length; i++) + { + remainder ^= data[i]; + for (var j = 0; j < 8; j++) + if ((remainder & 1) != 0) + remainder = (remainder >> 1) ^ Polynomial; + else + remainder >>= 1; + } + + return remainder ^ Seed; + } + internal static uint ReadUInt32BigEndian(this BinaryReader reader) + { + return (uint)IPAddress.HostToNetworkOrder(reader.ReadInt32()); + } + + internal static int ReadInt32BigEndian(this BinaryReader reader) + { + return IPAddress.HostToNetworkOrder(reader.ReadInt32()); + } + } +} \ No newline at end of file diff --git a/ELFSharp/UImage/UImageResult.cs b/ELFSharp/UImage/UImageResult.cs index 5478ae1..ed695ce 100644 --- a/ELFSharp/UImage/UImageResult.cs +++ b/ELFSharp/UImage/UImageResult.cs @@ -1,13 +1,10 @@ -using System; - namespace ELFSharp.UImage { - public enum UImageResult - { - OK, - NotUImage, - BadChecksum, - NotSupportedImageType - } -} - + public enum UImageResult + { + OK, + NotUImage, + BadChecksum, + NotSupportedImageType + } +} \ No newline at end of file diff --git a/ELFSharp/Utilities/Extensions.cs b/ELFSharp/Utilities/Extensions.cs index 6268ee9..ad4c5cd 100644 --- a/ELFSharp/Utilities/Extensions.cs +++ b/ELFSharp/Utilities/Extensions.cs @@ -1,5 +1,4 @@ -using System; -using System.IO; +using System.IO; namespace ELFSharp.Utilities { @@ -8,16 +7,15 @@ internal static class Extensions public static byte[] ReadBytesOrThrow(this Stream stream, int count) { var result = new byte[count]; - while(count > 0) + while (count > 0) { var readThisTurn = stream.Read(result, result.Length - count, count); - if(readThisTurn == 0) - { + if (readThisTurn == 0) throw new EndOfStreamException($"End of stream reached while {count} bytes more expected."); - } count -= readThisTurn; } + return result; } } -} +} \ No newline at end of file diff --git a/ELFSharp/Utilities/SimpleEndianessAwareReader.cs b/ELFSharp/Utilities/SimpleEndianessAwareReader.cs index 79b4dc9..19b8bcf 100644 --- a/ELFSharp/Utilities/SimpleEndianessAwareReader.cs +++ b/ELFSharp/Utilities/SimpleEndianessAwareReader.cs @@ -1,50 +1,46 @@ using System; using System.IO; using System.Net; -using ELFSharp.ELF; namespace ELFSharp.Utilities { public sealed class SimpleEndianessAwareReader : IDisposable { + private readonly bool beNonClosing; + + private readonly bool needsAdjusting; + public SimpleEndianessAwareReader(Stream stream, Endianess endianess, bool beNonClosing = false) { this.beNonClosing = beNonClosing; - this.stream = stream; - needsAdjusting = endianess == Endianess.LittleEndian ^ BitConverter.IsLittleEndian; + this.BaseStream = stream; + needsAdjusting = (endianess == Endianess.LittleEndian) ^ BitConverter.IsLittleEndian; } + public Stream BaseStream { get; } + public void Dispose() { - if(beNonClosing) - { - return; - } - stream.Dispose(); + if (beNonClosing) return; + BaseStream.Dispose(); } public byte[] ReadBytes(int count) { - return stream.ReadBytesOrThrow(count); + return BaseStream.ReadBytesOrThrow(count); } public byte ReadByte() { - var result = stream.ReadByte(); - if(result == -1) - { - throw new EndOfStreamException("End of stream reached while trying to read one byte."); - } + var result = BaseStream.ReadByte(); + if (result == -1) throw new EndOfStreamException("End of stream reached while trying to read one byte."); return (byte)result; } public short ReadInt16() { var value = BitConverter.ToInt16(ReadBytes(2), 0); - if(needsAdjusting) - { - value = IPAddress.NetworkToHostOrder(value); - } + if (needsAdjusting) value = IPAddress.NetworkToHostOrder(value); return value; } @@ -56,10 +52,7 @@ public ushort ReadUInt16() public int ReadInt32() { var value = BitConverter.ToInt32(ReadBytes(4), 0); - if(needsAdjusting) - { - value = IPAddress.NetworkToHostOrder(value); - } + if (needsAdjusting) value = IPAddress.NetworkToHostOrder(value); return value; } @@ -71,10 +64,7 @@ public uint ReadUInt32() public long ReadInt64() { var value = BitConverter.ToInt64(ReadBytes(8), 0); - if(needsAdjusting) - { - value = IPAddress.NetworkToHostOrder(value); - } + if (needsAdjusting) value = IPAddress.NetworkToHostOrder(value); return value; } @@ -82,11 +72,5 @@ public ulong ReadUInt64() { return (ulong)ReadInt64(); } - - public Stream BaseStream => stream; - - private readonly bool needsAdjusting; - private readonly bool beNonClosing; - private readonly Stream stream; } -} +} \ No newline at end of file diff --git a/ELFSharp/Utilities/SubStream.cs b/ELFSharp/Utilities/SubStream.cs index 3b84e94..c13c08c 100644 --- a/ELFSharp/Utilities/SubStream.cs +++ b/ELFSharp/Utilities/SubStream.cs @@ -5,36 +5,30 @@ namespace ELFSharp.Utilities { internal sealed class SubStream : Stream { + private const string NegativeArgumentMessage = "The argument cannot be negative."; + private const string OutsideStreamMessage = "The argument must be within the wrapped stream."; + private readonly long startingPosition; + + private readonly Stream wrappedStream; + public SubStream(Stream wrappedStream, long startingPosition, long length) { - if(startingPosition < 0) - { - throw new ArgumentException(nameof(startingPosition), NegativeArgumentMessage); - } + if (startingPosition < 0) throw new ArgumentException(nameof(startingPosition), NegativeArgumentMessage); - if(startingPosition > wrappedStream.Length) - { + if (startingPosition > wrappedStream.Length) throw new ArgumentException(nameof(startingPosition), OutsideStreamMessage); - } - if(length < 0) - { - throw new ArgumentException(nameof(length), NegativeArgumentMessage); - } + if (length < 0) throw new ArgumentException(nameof(length), NegativeArgumentMessage); - if(startingPosition + length > wrappedStream.Length) - { + if (startingPosition + length > wrappedStream.Length) throw new ArgumentException(nameof(startingPosition), OutsideStreamMessage); - } - if(!wrappedStream.CanSeek) - { + if (!wrappedStream.CanSeek) throw new ArgumentException(nameof(wrappedStream), "Wrapped streem has to be seekable."); - } -; + ; this.wrappedStream = wrappedStream; this.startingPosition = startingPosition; - this.length = length; + this.Length = length; wrappedStream.Seek(startingPosition, SeekOrigin.Begin); } @@ -45,16 +39,13 @@ public SubStream(Stream wrappedStream, long startingPosition, long length) public override bool CanWrite => false; - public override long Length => length; + public override long Length { get; } public override long Position { get => wrappedStream.Position - startingPosition; - set - { - wrappedStream.Position = value + startingPosition; - } + set => wrappedStream.Position = value + startingPosition; } public override void Flush() @@ -64,7 +55,7 @@ public override void Flush() public override int Read(byte[] buffer, int offset, int count) { - count = (int)Math.Min(count, length - Position); + count = (int)Math.Min(count, Length - Position); return wrappedStream.Read(buffer, offset, count); } @@ -81,10 +72,8 @@ public override long Seek(long offset, SeekOrigin origin) _ => throw new InvalidOperationException("Should never reach here.") }; - if(adjustedOffset < startingPosition || adjustedOffset > startingPosition + length) - { + if (adjustedOffset < startingPosition || adjustedOffset > startingPosition + Length) throw new ArgumentException(nameof(offset), "Effective offset cannot move outside of the substream."); - } return wrappedStream.Seek(adjustedOffset, SeekOrigin.Begin) - startingPosition; } @@ -98,12 +87,5 @@ public override void Write(byte[] buffer, int offset, int count) { throw new NotSupportedException($"Writing is not available for {nameof(SubStream)}."); } - - private readonly Stream wrappedStream; - private readonly long startingPosition; - private readonly long length; - - private const string NegativeArgumentMessage = "The argument cannot be negative."; - private const string OutsideStreamMessage = "The argument must be within the wrapped stream."; } -} +} \ No newline at end of file diff --git a/Tests/ELF/DynamicSectionTests.cs b/Tests/ELF/DynamicSectionTests.cs index 8934fef..d5e2a5b 100644 --- a/Tests/ELF/DynamicSectionTests.cs +++ b/Tests/ELF/DynamicSectionTests.cs @@ -1,11 +1,7 @@ -using ELFSharp.ELF; +using System.Linq; +using ELFSharp.ELF; using ELFSharp.ELF.Sections; using NUnit.Framework; -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; namespace Tests.ELF { @@ -43,6 +39,5 @@ public void ShouldHaveCorrectDynamicEntryCount64() var dynamicSection = (IDynamicSection)elf.GetSection(".dynamic"); Assert.AreEqual(29, dynamicSection.Entries.Count()); } - } -} +} \ No newline at end of file diff --git a/Tests/ELF/NoteSectionTests.cs b/Tests/ELF/NoteSectionTests.cs index db8b7df..2c5bf51 100644 --- a/Tests/ELF/NoteSectionTests.cs +++ b/Tests/ELF/NoteSectionTests.cs @@ -1,8 +1,8 @@ -using NUnit.Framework; -using ELFSharp.ELF.Sections; -using ELFSharp.ELF; using System.Linq; +using ELFSharp.ELF; +using ELFSharp.ELF.Sections; using ELFSharp.ELF.Segments; +using NUnit.Framework; namespace Tests.ELF { @@ -81,5 +81,4 @@ public void ShouldReadMultipleNoteDataType() Assert.AreEqual(1024ul, noteSegment.Notes[6].Type); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/OpeningTests.cs b/Tests/ELF/OpeningTests.cs index 6571c0a..85d8554 100644 --- a/Tests/ELF/OpeningTests.cs +++ b/Tests/ELF/OpeningTests.cs @@ -1,7 +1,8 @@ -using NUnit.Framework; +using System.IO; +using ELFSharp; using ELFSharp.ELF; using ELFSharp.ELF.Sections; -using ELFSharp; +using NUnit.Framework; namespace Tests.ELF { @@ -14,49 +15,49 @@ public void ShouldChooseGoodClass32() using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); Assert.AreEqual(Class.Bit32, elf.Class); } - + [Test] public void ShouldChooseGoodClass64() { using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); Assert.AreEqual(Class.Bit64, elf.Class); } - + [Test] public void ShouldOpenHelloWorld32() { - ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); + ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); } - + [Test] public void ShouldOpenHelloWorld64() - { + { ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); } - + [Test] public void ShouldProperlyParseClass32() { var elf32 = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); - Assert.AreEqual(Class.Bit32, elf32.Class); + Assert.AreEqual(Class.Bit32, elf32.Class); } [Test] public void ShouldProperlyParseClass64() - { + { var elf64 = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); Assert.AreEqual(Class.Bit64, elf64.Class); } - + [Test] public void ShouldProperlyParseEndianess() { - using var elfLittleEndian = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); + using var elfLittleEndian = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); Assert.AreEqual(Endianess.LittleEndian, elfLittleEndian.Endianess); - using var elfBigEndian = ELFReader.Load(Utilities.GetBinaryStream("vmlinuxOpenRisc"), true); + using var elfBigEndian = ELFReader.Load(Utilities.GetBinaryStream("vmlinuxOpenRisc"), true); Assert.AreEqual(Endianess.BigEndian, elfBigEndian.Endianess); } - + [Test] public void ShouldOpenBigEndian() { @@ -71,16 +72,16 @@ public void ShouldOpenElfWithNonUniqueSectionNames() } // Github issue no 3 - [Test] - public void ShouldLoadSharedObjectElfWithProgramHeaders() - { - ELFReader.Load(Utilities.GetBinaryStream("issue3"), true); - } + [Test] + public void ShouldLoadSharedObjectElfWithProgramHeaders() + { + ELFReader.Load(Utilities.GetBinaryStream("issue3"), true); + } - [Test] - public void ShouldNotOpenNonELFFile() - { - Assert.IsFalse(ELFReader.TryLoad(Utilities.GetBinaryStream("notelf"), true, out var _)); + [Test] + public void ShouldNotOpenNonELFFile() + { + Assert.IsFalse(ELFReader.TryLoad(Utilities.GetBinaryStream("notelf"), true, out _)); } // Github issue no 9 @@ -110,7 +111,7 @@ public void ShouldOpenEmptyStringTableElf() [Test] public void ShouldCloseOwnedStreamOnNonElf() { - var stream = new System.IO.MemoryStream(new byte[] { 0, 1, 2, 3 }); + var stream = new MemoryStream(new byte[] { 0, 1, 2, 3 }); Assert.IsFalse(ELFReader.TryLoad(stream, true, out _)); Assert.IsFalse(stream.CanRead); } @@ -120,7 +121,7 @@ public void ShouldDisposeStream() { var isDisposed = false; var stream = new StreamWrapper(Utilities.GetBinaryStream("hello32le"), () => isDisposed = true); - ELFReader.Load(stream, shouldOwnStream: true).Dispose(); + ELFReader.Load(stream, true).Dispose(); Assert.True(isDisposed); } @@ -129,9 +130,8 @@ public void ShouldNotDisposeStream() { var isDisposed = false; var stream = new StreamWrapper(Utilities.GetBinaryStream("hello32le"), () => isDisposed = true); - ELFReader.Load(stream, shouldOwnStream: false).Dispose(); + ELFReader.Load(stream, false).Dispose(); Assert.False(isDisposed); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/ProgBitsSectionTests.cs b/Tests/ELF/ProgBitsSectionTests.cs index c680133..82b4039 100644 --- a/Tests/ELF/ProgBitsSectionTests.cs +++ b/Tests/ELF/ProgBitsSectionTests.cs @@ -1,7 +1,7 @@ using System.Linq; -using NUnit.Framework; -using ELFSharp.ELF.Sections; using ELFSharp.ELF; +using ELFSharp.ELF.Sections; +using NUnit.Framework; namespace Tests.ELF { @@ -15,7 +15,7 @@ public void ShouldGetLoadAddress32() var sectionsToLoad = elf.GetSections>().Where(x => x.LoadAddress != 0); Assert.AreEqual(13, sectionsToLoad.Count()); } - + [Test] public void ShouldGetLoadAddress64() { @@ -24,5 +24,4 @@ public void ShouldGetLoadAddress64() Assert.AreEqual(12, sectionsToLoad.Count()); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/SectionGettingTests.cs b/Tests/ELF/SectionGettingTests.cs index d5976dd..33b6fd6 100644 --- a/Tests/ELF/SectionGettingTests.cs +++ b/Tests/ELF/SectionGettingTests.cs @@ -1,8 +1,6 @@ -using System; -using NUnit.Framework; -using ELFSharp.ELF; +using ELFSharp.ELF; using ELFSharp.ELF.Sections; -using System.Linq; +using NUnit.Framework; namespace Tests.ELF { @@ -20,7 +18,8 @@ public void ShouldGetSection() public void ShouldHandleNonExistingSection() { ISection section; - Assert.IsFalse(ELFReader.Load(Utilities.GetBinaryStream("issue3"), true).TryGetSection(".nonexisting", out section)); + Assert.IsFalse(ELFReader.Load(Utilities.GetBinaryStream("issue3"), true) + .TryGetSection(".nonexisting", out section)); } [Test] @@ -48,5 +47,4 @@ public void ShouldGetSectionContents() Assert.AreEqual(0xE14DEBA1, Utilities.ComputeCrc32(sectionContents)); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/SectionHeadersParsingTests.cs b/Tests/ELF/SectionHeadersParsingTests.cs index d209a56..cfae910 100644 --- a/Tests/ELF/SectionHeadersParsingTests.cs +++ b/Tests/ELF/SectionHeadersParsingTests.cs @@ -1,7 +1,7 @@ using System.Linq; -using NUnit.Framework; -using ELFSharp.ELF.Sections; using ELFSharp.ELF; +using ELFSharp.ELF.Sections; +using NUnit.Framework; namespace Tests.ELF { @@ -14,7 +14,7 @@ public void ShouldFindProperNumberOfSections32() using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); Assert.AreEqual(29, elf.Sections.Count()); } - + [Test] public void ShouldFindProperNumberOfSections64() { @@ -86,5 +86,4 @@ public void ShouldFindSizeInFirstEntry() Assert.AreEqual(0x10ace, elf.Sections[0].Size); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/SegmentsTests.cs b/Tests/ELF/SegmentsTests.cs index ee139a6..4c6afb4 100644 --- a/Tests/ELF/SegmentsTests.cs +++ b/Tests/ELF/SegmentsTests.cs @@ -1,7 +1,7 @@ using System.Linq; -using NUnit.Framework; -using ELFSharp.ELF.Segments; using ELFSharp.ELF; +using ELFSharp.ELF.Segments; +using NUnit.Framework; namespace Tests.ELF { @@ -14,7 +14,7 @@ public void ShouldFindAllSegmentsH32LE() using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); Assert.AreEqual(8, elf.Segments.Count()); } - + [Test] public void ShouldFindAllSegmentsOR32BE() { @@ -81,7 +81,7 @@ public void ShouldHaveNullAdditionalBytes() var elf = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); var segment = elf.Segments.Single(x => x.Address == 0x8049F14 && x.Type == SegmentType.Load); - byte[] memoryContents = segment.GetMemoryContents(); + var memoryContents = segment.GetMemoryContents(); var endingZeroes = memoryContents.Skip((int)segment.FileSize); Assert.IsTrue(endingZeroes.All(x => x == 0), "Not all additional bytes were zero."); } @@ -105,5 +105,4 @@ public void ShouldHandleNoteSegment() Assert.AreEqual(1, noteSegment.NoteType); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/StringTableTests.cs b/Tests/ELF/StringTableTests.cs index fbbf2b9..41f848b 100644 --- a/Tests/ELF/StringTableTests.cs +++ b/Tests/ELF/StringTableTests.cs @@ -1,6 +1,6 @@ using System.Linq; -using NUnit.Framework; using ELFSharp.ELF; +using NUnit.Framework; namespace Tests.ELF { @@ -11,20 +11,20 @@ public class StringTableTests public void ShouldFindAllStrings() { using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); - Assert.IsTrue(elf.HasSectionsStringTable, - "Sections string table was not found in 32 bit ELF."); + Assert.IsTrue(elf.HasSectionsStringTable, + "Sections string table was not found in 32 bit ELF."); Assert.AreEqual(29, elf.SectionsStringTable.Strings.Count()); } - + [Test] public void ShouldFindAllStrings64() { using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); - Assert.IsTrue(elf.HasSectionsStringTable, - "Sections string table was not found in 64 bit ELF."); + Assert.IsTrue(elf.HasSectionsStringTable, + "Sections string table was not found in 64 bit ELF."); Assert.AreEqual(30, elf.SectionsStringTable.Strings.Count()); } - + [Test] public void ShouldFindAllStringsBigEndian() { @@ -36,5 +36,4 @@ public void ShouldFindAllStringsBigEndian() Assert.AreEqual(28, elf.SectionsStringTable.Strings.Count()); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/SymbolTableTests.cs b/Tests/ELF/SymbolTableTests.cs index 1a5b792..76d9c2d 100644 --- a/Tests/ELF/SymbolTableTests.cs +++ b/Tests/ELF/SymbolTableTests.cs @@ -1,7 +1,7 @@ using System.Linq; -using NUnit.Framework; -using ELFSharp.ELF.Sections; using ELFSharp.ELF; +using ELFSharp.ELF.Sections; +using NUnit.Framework; namespace Tests.ELF { @@ -13,15 +13,15 @@ public void ShouldFindAllSymbols32() { using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello32le"), true); var symtab = (ISymbolTable)elf.GetSection(".symtab"); - Assert.AreEqual(64, symtab.Entries.Count()); + Assert.AreEqual(64, symtab.Entries.Count()); } - + [Test] public void ShouldFindAllSymbols64() { - using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); - var symtab = (ISymbolTable)elf.GetSection(".symtab"); - Assert.AreEqual(64, symtab.Entries.Count()); + using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); + var symtab = (ISymbolTable)elf.GetSection(".symtab"); + Assert.AreEqual(64, symtab.Entries.Count()); } // Github issue no 24 @@ -43,5 +43,4 @@ public void SymbolsShouldHaveCorrectVisibility() Assert.AreEqual(3, visibilites[SymbolVisibility.Hidden]); } } -} - +} \ No newline at end of file diff --git a/Tests/ELF/WebTests.cs b/Tests/ELF/WebTests.cs index 63a69a7..464e09d 100644 --- a/Tests/ELF/WebTests.cs +++ b/Tests/ELF/WebTests.cs @@ -1,26 +1,23 @@ using System; -using NUnit.Framework; using System.Collections.Generic; -using ELFSharp.ELF.Sections; using System.Linq; using ELFSharp.ELF; +using ELFSharp.ELF.Sections; +using NUnit.Framework; namespace Tests.ELF { - [TestFixture] - public class WebTests - { - [Test] - public void ListELFSectionHeaders() - { - using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); - var output = new List(); + [TestFixture] + public class WebTests + { + [Test] + public void ListELFSectionHeaders() + { + using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); + var output = new List(); - foreach(var header in elf.Sections) - { - output.Add(header.ToString()); - } - var expectedOutput = @": Null, load @0x0, 0 bytes long + foreach (var header in elf.Sections) output.Add(header.ToString()); + var expectedOutput = @": Null, load @0x0, 0 bytes long .interp: ProgBits, load @0x400200, 28 bytes long .note.ABI-tag: Note, Type=1 .note.gnu.build-id: Note, Type=3 @@ -50,23 +47,20 @@ public void ListELFSectionHeaders() .shstrtab: StringTable, load @0x0, 264 bytes long .symtab: SymbolTable, load @0x0, 1536 bytes long .strtab: StringTable, load @0x0, 566 bytes long"; - var expectedOutputAsLines = expectedOutput.Split(new [] { "\n", "\r\n" }, StringSplitOptions.None); - CollectionAssert.AreEqual(expectedOutputAsLines, output); - } + var expectedOutputAsLines = expectedOutput.Split(new[] { "\n", "\r\n" }, StringSplitOptions.None); + CollectionAssert.AreEqual(expectedOutputAsLines, output); + } - [Test] - public void GetNamesOfFunctionSymbols() - { - using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); - var output = new List(); + [Test] + public void GetNamesOfFunctionSymbols() + { + using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); + var output = new List(); - var functions = ((ISymbolTable)elf.GetSection(".symtab")).Entries.Where(x => x.Type == SymbolType.Function); - foreach(var f in functions) - { - output.Add(f.Name); - } + var functions = ((ISymbolTable)elf.GetSection(".symtab")).Entries.Where(x => x.Type == SymbolType.Function); + foreach (var f in functions) output.Add(f.Name); - var expectedOutput = @"deregister_tm_clones + var expectedOutput = @"deregister_tm_clones register_tm_clones __do_global_dtors_aux frame_dummy @@ -78,23 +72,22 @@ public void GetNamesOfFunctionSymbols() _start main _init"; - var expectedOutputAsLines = expectedOutput.Split(new [] { "\n", "\r\n" }, StringSplitOptions.None); - CollectionAssert.AreEqual(expectedOutputAsLines, output); - } - - [Test] - public void WriteAllLoadableProgBitsToArray() - { - using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); + var expectedOutputAsLines = expectedOutput.Split(new[] { "\n", "\r\n" }, StringSplitOptions.None); + CollectionAssert.AreEqual(expectedOutputAsLines, output); + } - var sectionsToLoad = elf.GetSections>() - .Where(x => x.LoadAddress != 0); - foreach (var s in sectionsToLoad) - { - var array = new byte[s.Size]; - s.GetContents().CopyTo(array, 0); - } - } - } -} + [Test] + public void WriteAllLoadableProgBitsToArray() + { + using var elf = ELFReader.Load(Utilities.GetBinaryStream("hello64le"), true); + var sectionsToLoad = elf.GetSections>() + .Where(x => x.LoadAddress != 0); + foreach (var s in sectionsToLoad) + { + var array = new byte[s.Size]; + s.GetContents().CopyTo(array, 0); + } + } + } +} \ No newline at end of file diff --git a/Tests/MachO/EntryPointTests.cs b/Tests/MachO/EntryPointTests.cs index 817b206..2447cb2 100644 --- a/Tests/MachO/EntryPointTests.cs +++ b/Tests/MachO/EntryPointTests.cs @@ -1,7 +1,6 @@ -using System; -using NUnit.Framework; +using System.Linq; using ELFSharp.MachO; -using System.Linq; +using NUnit.Framework; namespace Tests.MachO { @@ -26,5 +25,4 @@ public void ShouldFind64BitEntryPoint() Assert.AreEqual(0, entryPoint.StackSize); } } -} - +} \ No newline at end of file diff --git a/Tests/MachO/FileHeaderTests.cs b/Tests/MachO/FileHeaderTests.cs index f040445..b2b8313 100644 --- a/Tests/MachO/FileHeaderTests.cs +++ b/Tests/MachO/FileHeaderTests.cs @@ -1,6 +1,5 @@ using ELFSharp.MachO; using NUnit.Framework; -using System.Linq; namespace Tests.MachO { @@ -26,5 +25,4 @@ public void ShouldLoadFileHasNoHeaderFlags() Assert.AreEqual(flags, (HeaderFlags)0); } } -} - +} \ No newline at end of file diff --git a/Tests/MachO/OpeningTests.cs b/Tests/MachO/OpeningTests.cs index 50c2a7d..b633d8e 100644 --- a/Tests/MachO/OpeningTests.cs +++ b/Tests/MachO/OpeningTests.cs @@ -1,7 +1,7 @@ -using NUnit.Framework; -using ELFSharp.MachO; -using System; +using System; using System.Linq; +using ELFSharp.MachO; +using NUnit.Framework; namespace Tests.MachO { @@ -48,7 +48,8 @@ public void ShouldOpenFatMachO() [Test] public void ShouldThrowOnFatMachOWhenOpenedAsNotFat() { - Assert.Throws(() => MachOReader.Load(Utilities.GetBinaryStream("Undecimus"), true)); + Assert.Throws(() => + MachOReader.Load(Utilities.GetBinaryStream("Undecimus"), true)); } [Test] @@ -70,7 +71,7 @@ public void ShouldOpenNotFatMachOUsingFatMethod() public void ShouldOpenMachOObjectFile() { // intermediate object file has only 1 segment. - var result = MachOReader.TryLoad(Utilities.GetBinaryStream("simple-mach-o-object.o"), true, out ELFSharp.MachO.MachO machO); + var result = MachOReader.TryLoad(Utilities.GetBinaryStream("simple-mach-o-object.o"), true, out var machO); Assert.AreEqual(MachOResult.OK, result); Assert.AreEqual(machO.FileType, FileType.Object); Assert.AreEqual(machO.GetCommandsOfType().Count(), 1); @@ -81,7 +82,7 @@ public void ShouldDisposeStream() { var isDisposed = false; var stream = new StreamWrapper(Utilities.GetBinaryStream("simple-mach-o"), () => isDisposed = true); - MachOReader.Load(stream, shouldOwnStream: true); + MachOReader.Load(stream, true); Assert.True(isDisposed); } @@ -90,9 +91,8 @@ public void ShouldNotDisposeStream() { var isDisposed = false; var stream = new StreamWrapper(Utilities.GetBinaryStream("simple-mach-o"), () => isDisposed = true); - MachOReader.Load(stream, shouldOwnStream: false); + MachOReader.Load(stream, false); Assert.False(isDisposed); } } -} - +} \ No newline at end of file diff --git a/Tests/MachO/SegmentTests.cs b/Tests/MachO/SegmentTests.cs index 73b8a06..8016ea8 100644 --- a/Tests/MachO/SegmentTests.cs +++ b/Tests/MachO/SegmentTests.cs @@ -1,8 +1,7 @@ -using System; -using NUnit.Framework; -using ELFSharp.MachO; -using System.Linq; +using System.Linq; using System.Text; +using ELFSharp.MachO; +using NUnit.Framework; namespace Tests.MachO { @@ -37,5 +36,4 @@ public static void ShouldFindSectionWithDataAndNoDataArm64(string segmentName, s section.GetData(); } } -} - +} \ No newline at end of file diff --git a/Tests/MachO/SymbolTableTests.cs b/Tests/MachO/SymbolTableTests.cs index 73ed5be..99f861a 100644 --- a/Tests/MachO/SymbolTableTests.cs +++ b/Tests/MachO/SymbolTableTests.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; -using NUnit.Framework; -using ELFSharp.MachO; using System.Linq; +using ELFSharp.MachO; +using NUnit.Framework; namespace Tests.MachO { @@ -20,7 +20,8 @@ public void ShouldListSymbols() { var machO = MachOReader.Load(Utilities.GetBinaryStream("shared-32-mach-o"), true); var symbolTable = machO.GetCommandsOfType().Single(); - CollectionAssert.IsSubsetOf(new [] { "_funkcja", "_inna_funkcja", "_jeszcze_inna_funkcja" }, symbolTable.Symbols.Select(x => x.Name).ToArray()); + CollectionAssert.IsSubsetOf(new[] { "_funkcja", "_inna_funkcja", "_jeszcze_inna_funkcja" }, + symbolTable.Symbols.Select(x => x.Name).ToArray()); } // picked a few symbols with `nm -m 3dengine_libretro_ios.dylib` @@ -34,10 +35,10 @@ public void ShouldListSymbols() public void ShouldHaveCorrectSection(string symbolName, string section) { var symbol = symbols.First(e => e.Name == symbolName); - Assert.AreEqual(section, symbol.Section == null ? null : $"{symbol.Section.SegmentName},{symbol.Section.Name}"); + Assert.AreEqual(section, + symbol.Section == null ? null : $"{symbol.Section.SegmentName},{symbol.Section.Name}"); } private IEnumerable symbols; } -} - +} \ No newline at end of file diff --git a/Tests/MachO/UUIDTests.cs b/Tests/MachO/UUIDTests.cs index a05991b..611c281 100644 --- a/Tests/MachO/UUIDTests.cs +++ b/Tests/MachO/UUIDTests.cs @@ -1,33 +1,28 @@ -using System; -using NUnit.Framework; +using System.Linq; using ELFSharp.MachO; -using System.IO; -using System.Linq; +using NUnit.Framework; namespace Tests.MachO { [TestFixture] public class UUIDTests - { + { [Test] public void ReadsUUID() { var archs = MachOReader.LoadFat(Utilities.GetBinaryStream("3dengine_libretro_ios.dylib"), true); - foreach(var arch in archs) + foreach (var arch in archs) { var ids = arch.GetCommandsOfType(); // a valid macho can't have 0 LC_UUIDs Assert.AreNotEqual(ids.Count(), 0); - foreach(var id in ids) - { + foreach (var id in ids) // for each arch the uuid must be specified Assert.AreNotEqual(id.ID, null); - } } } } -} - +} \ No newline at end of file diff --git a/Tests/StreamWrapper.cs b/Tests/StreamWrapper.cs index 057a3ee..f9d9322 100644 --- a/Tests/StreamWrapper.cs +++ b/Tests/StreamWrapper.cs @@ -5,8 +5,8 @@ namespace Tests { public class StreamWrapper : Stream { - private readonly Stream stream; private readonly Action onDispose; + private readonly Stream stream; public StreamWrapper(Stream stream, Action onDispose) { @@ -14,16 +14,6 @@ public StreamWrapper(Stream stream, Action onDispose) this.onDispose = onDispose; } - public override void Flush() => stream.Flush(); - - public override int Read(byte[] buffer, int offset, int count) => stream.Read(buffer, offset, count); - - public override long Seek(long offset, SeekOrigin origin) => stream.Seek(offset, origin); - - public override void SetLength(long value) => stream.SetLength(value); - - public override void Write(byte[] buffer, int offset, int count) => stream.Write(buffer, offset, count); - public override bool CanRead => stream.CanRead; public override bool CanSeek => stream.CanSeek; @@ -38,6 +28,31 @@ public override long Position set => stream.Position = value; } + public override void Flush() + { + stream.Flush(); + } + + public override int Read(byte[] buffer, int offset, int count) + { + return stream.Read(buffer, offset, count); + } + + public override long Seek(long offset, SeekOrigin origin) + { + return stream.Seek(offset, origin); + } + + public override void SetLength(long value) + { + stream.SetLength(value); + } + + public override void Write(byte[] buffer, int offset, int count) + { + stream.Write(buffer, offset, count); + } + protected override void Dispose(bool disposing) { onDispose(); diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index bfbe506..c85a0e6 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,26 +1,26 @@ - - net6.0 - Tests - + + net6.0 + Tests + - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + + + diff --git a/Tests/UImage/GzipTests.cs b/Tests/UImage/GzipTests.cs index 97a8e1c..c7b5710 100644 --- a/Tests/UImage/GzipTests.cs +++ b/Tests/UImage/GzipTests.cs @@ -1,21 +1,21 @@ -using NUnit.Framework; using ELFSharp.UImage; +using NUnit.Framework; namespace Tests.UImage { [TestFixture] - public class GzipTests - { - [Test] - public void ShouldExtractGzipCompressedUImage() - { - Assert.AreEqual(UImageResult.OK, UImageReader.TryLoad(Utilities.GetBinaryStream("uImage-gzip"), true, out var image)); + public class GzipTests + { + [Test] + public void ShouldExtractGzipCompressedUImage() + { + Assert.AreEqual(UImageResult.OK, + UImageReader.TryLoad(Utilities.GetBinaryStream("uImage-gzip"), true, out var image)); Assert.AreEqual(CompressionType.Gzip, image.Compression); - CollectionAssert.AreEqual( - Utilities.ReadWholeStream(Utilities.GetBinaryStream("uImage-gzip-extracted")), - image.GetImageData()); - } - } -} - + CollectionAssert.AreEqual( + Utilities.ReadWholeStream(Utilities.GetBinaryStream("uImage-gzip-extracted")), + image.GetImageData()); + } + } +} \ No newline at end of file diff --git a/Tests/UImage/MultiFileImageTests.cs b/Tests/UImage/MultiFileImageTests.cs index 4b08a1c..2311669 100644 --- a/Tests/UImage/MultiFileImageTests.cs +++ b/Tests/UImage/MultiFileImageTests.cs @@ -1,13 +1,11 @@ -using System; -using System.Linq; -using ELFSharp.UImage; +using ELFSharp.UImage; using NUnit.Framework; namespace Tests.UImage { - [TestFixture] - public sealed class MultiFileTests - { + [TestFixture] + public sealed class MultiFileTests + { [Test] public void ShouldOpenMultiFileImage() { @@ -22,7 +20,7 @@ public void ShouldGetFirstImageFromMultiFileImage() UImageReader.TryLoad(Utilities.GetBinaryStream("mImage"), true, out var uImage)); var imageData = uImage.GetImageData(); - CollectionAssert.AreEqual(new byte[] { 0x7F, (byte)'E', (byte)'L', (byte)'F' }, imageData[0..4]); + CollectionAssert.AreEqual(new byte[] { 0x7F, (byte)'E', (byte)'L', (byte)'F' }, imageData[..4]); } [Test] @@ -32,7 +30,7 @@ public void ShouldGetFirstImageFromMultiFileImageOnZeroIndex() UImageReader.TryLoad(Utilities.GetBinaryStream("mImage"), true, out var uImage)); var imageData = uImage.GetImageData(0); - CollectionAssert.AreEqual(new byte[] { 0x7F, (byte)'E', (byte)'L', (byte)'F' }, imageData[0..4]); + CollectionAssert.AreEqual(new byte[] { 0x7F, (byte)'E', (byte)'L', (byte)'F' }, imageData[..4]); } [Test] @@ -42,8 +40,7 @@ public void ShouldGetSecondImageFromMultiFileImage() UImageReader.TryLoad(Utilities.GetBinaryStream("mImage"), true, out var uImage)); var imageData = uImage.GetImageData(1); - CollectionAssert.AreEqual(new byte[] { 0xD0, 0x0D, 0xFE, 0xED }, imageData[0..4]); + CollectionAssert.AreEqual(new byte[] { 0xD0, 0x0D, 0xFE, 0xED }, imageData[..4]); } } -} - +} \ No newline at end of file diff --git a/Tests/UImage/SimpleTests.cs b/Tests/UImage/SimpleTests.cs index 12c4b47..9d33610 100644 --- a/Tests/UImage/SimpleTests.cs +++ b/Tests/UImage/SimpleTests.cs @@ -1,81 +1,80 @@ using System; -using NUnit.Framework; using ELFSharp.UImage; -using System.IO; +using NUnit.Framework; namespace Tests.UImage { - [TestFixture] - public class SimpleTests - { - [Test] - public void ShouldOpenUImage() - { + [TestFixture] + public class SimpleTests + { + [Test] + public void ShouldOpenUImage() + { Assert.AreEqual(UImageResult.OK, UImageReader.TryLoad(Utilities.GetBinaryStream("uImage-panda"), true, out _)); } - [Test] - public void ShouldNotOpenNotUImageFile() - { + [Test] + public void ShouldNotOpenNotUImageFile() + { // not elf, nor uImage - Assert.AreEqual(UImageResult.NotUImage, UImageReader.TryLoad(Utilities.GetBinaryStream("notelf"), true, out _)); - } + Assert.AreEqual(UImageResult.NotUImage, + UImageReader.TryLoad(Utilities.GetBinaryStream("notelf"), true, out _)); + } - [Test] - public void ShouldProperlyReadHeader() - { - var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-panda"), true); - Assert.AreEqual(3120712, uImage.Size); - Assert.AreEqual(0x80008000, uImage.EntryPoint); - Assert.AreEqual(0x80008000, uImage.LoadAddress); - Assert.AreEqual(0x6C77B32E, uImage.CRC); - Assert.AreEqual("Linux-3.2.0", uImage.Name); - } + [Test] + public void ShouldProperlyReadHeader() + { + var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-panda"), true); + Assert.AreEqual(3120712, uImage.Size); + Assert.AreEqual(0x80008000, uImage.EntryPoint); + Assert.AreEqual(0x80008000, uImage.LoadAddress); + Assert.AreEqual(0x6C77B32E, uImage.CRC); + Assert.AreEqual("Linux-3.2.0", uImage.Name); + } - [Test] - public void ShouldProperlyReadTimestamp() - { - var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-panda"), true); - Assert.AreEqual(new DateTime(2012, 4, 10, 19, 11, 06, DateTimeKind.Utc).ToLocalTime(), uImage.Timestamp); - } + [Test] + public void ShouldProperlyReadTimestamp() + { + var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-panda"), true); + Assert.AreEqual(new DateTime(2012, 4, 10, 19, 11, 06, DateTimeKind.Utc).ToLocalTime(), uImage.Timestamp); + } - [Test] - public void ShouldFailOnImageWithWrongChecksum() - { + [Test] + public void ShouldFailOnImageWithWrongChecksum() + { Assert.AreEqual(UImageResult.BadChecksum, UImageReader.TryLoad(Utilities.GetBinaryStream("uImage-panda-wrng-cksm"), true, out _)); - } + } - [Test] - public void ShouldFindCorrectImageType() - { - var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-panda"), true); - Assert.AreEqual(ImageType.Kernel, uImage.Type); - } + [Test] + public void ShouldFindCorrectImageType() + { + var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-panda"), true); + Assert.AreEqual(ImageType.Kernel, uImage.Type); + } - [Test] - public void ShouldExtractCorrectImage() - { - var extracted = Utilities.ReadWholeStream(Utilities.GetBinaryStream("vexpress-image-extracted")); + [Test] + public void ShouldExtractCorrectImage() + { + var extracted = Utilities.ReadWholeStream(Utilities.GetBinaryStream("vexpress-image-extracted")); - CollectionAssert.AreEqual(extracted, + CollectionAssert.AreEqual(extracted, UImageReader.Load(Utilities.GetBinaryStream("uImage-vexpress"), true).GetImageData()); - } - - [Test] - public void ShouldGetProperOSValue() - { - var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-vexpress"), true); - Assert.AreEqual(OS.Linux, uImage.OperatingSystem); - } + } - [Test] - public void ShouldGetProperArchitecture() - { - var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-vexpress"), true); - Assert.AreEqual(Architecture.ARM, uImage.Architecture); - } - } -} + [Test] + public void ShouldGetProperOSValue() + { + var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-vexpress"), true); + Assert.AreEqual(OS.Linux, uImage.OperatingSystem); + } + [Test] + public void ShouldGetProperArchitecture() + { + var uImage = UImageReader.Load(Utilities.GetBinaryStream("uImage-vexpress"), true); + Assert.AreEqual(Architecture.ARM, uImage.Architecture); + } + } +} \ No newline at end of file diff --git a/Tests/Utilities.cs b/Tests/Utilities.cs index 623c4c4..07ce0d5 100644 --- a/Tests/Utilities.cs +++ b/Tests/Utilities.cs @@ -1,5 +1,4 @@ using System; -using System.Collections.Generic; using System.IO; using Force.Crc32; using NUnit.Framework; @@ -7,15 +6,14 @@ namespace Tests { [SetUpFixture] - public class Utilities - { - public static Stream GetBinaryStream(string name) - { + public class Utilities + { + private const string ResourcesPrefix = "Tests.Binaries."; + + public static Stream GetBinaryStream(string name) + { var result = typeof(Utilities).Assembly.GetManifestResourceStream(ResourcesPrefix + name); - if(result == null) - { - throw new FileNotFoundException($"Could not find resource '{name}'."); - } + if (result == null) throw new FileNotFoundException($"Could not find resource '{name}'."); return result; } @@ -33,8 +31,5 @@ public static byte[] ReadWholeStream(Stream stream) stream.CopyTo(memoryStream); return memoryStream.ToArray(); } - - private const string ResourcesPrefix = "Tests.Binaries."; - } -} - + } +} \ No newline at end of file