Esempio n. 1
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ElfFile"/> class.
        /// </summary>
        ///
        /// <param name="header">
        /// The ELF file header.
        /// </param>
        ///
        /// <param name="segments">
        /// The program header table.
        /// </param>
        ///
        /// <param name="sections">
        /// The section header table.
        /// </param>
        internal ElfFile(ElfHeader header, ElfProgramHeaderTable segments, ElfSectionHeaderTable sections)
        {
            Header = header;

            Segments = segments;
            Sections = sections;
        }
Esempio n. 2
0
        /// <summary>
        /// Initializes a new instance of the <see cref="ElfProgramHeaderTable"/> class by examining an ELF header.
        /// </summary>
        ///
        /// <param name="reader">
        /// The reader used to extract the data needed to parse the ELF file.
        /// </param>
        ///
        /// <param name="header">
        /// The ELF header used to extract the metadata about this program header table.
        /// </param>
        ///
        /// <param name="sections">
        /// The list of sections which will be parsed to extract the sections corresponding to this segment.
        /// </param>
        internal ElfProgramHeaderTable(BinaryReader reader, ElfHeader header, ElfSectionHeaderTable sections)
        {
            // Initialize all segments
            for (var i = 0; i < header.ProgramHeaderEntryCount; i++)
            {
                ElfSegment segment;

                switch (header.Class)
                {
                case ElfClass.Elf32:
                {
                    segment = new Bit32.ElfSegment(reader, (long)(header.ProgramHeaderOffset + (ulong)(i * header.ProgramHeaderSize)));
                    break;
                }

                case ElfClass.Elf64:
                {
                    segment = new Bit64.ElfSegment(reader, (long)(header.ProgramHeaderOffset + (ulong)(i * header.ProgramHeaderSize)));
                    break;
                }

                default:
                {
                    throw new InvalidOperationException("Unreachable case reached");
                }
                }

                segment.Sections = sections.Where(s => s.Address >= segment.VirtualAddress && s.Address < segment.VirtualAddress + segment.MemorySize).ToList().AsReadOnly();

                segments.Add(segment);
            }
        }
Esempio n. 3
0
        /// <summary>
        /// Reads an ELF file from a binary reader.
        /// </summary>
        ///
        /// <param name="reader">
        /// The reader used to extract the data needed to parse the ELF file.
        /// </param>
        ///
        /// <returns>
        /// The ELF file parsed from the binary reader.
        /// </returns>
        ///
        /// <exception cref="FileFormatException">
        /// <paramref name="reader"/> base stream does not represent a valid ELF file.
        /// </exception>
        public static ElfFile ReadElfFile(BinaryReader reader)
        {
            try
            {
                long savedPosition = reader.BaseStream.Position;

                byte magic0 = reader.ReadByte();
                byte magic1 = reader.ReadByte();
                byte magic2 = reader.ReadByte();
                byte magic3 = reader.ReadByte();

                if (magic0 != ElfHeader.ELFMAG0 || magic1 != ElfHeader.ELFMAG1 || magic2 != ElfHeader.ELFMAG2 || magic3 != ElfHeader.ELFMAG3)
                {
                    throw new FileFormatException($"Invalid ELF magic bytes: 0x{magic0,0:X2} 0x{magic1,0:X2} 0x{magic2,0:X2} 0x{magic3,0:X2}");
                }

                byte @class = reader.ReadByte();

                if (@class != ElfHeader.ELFCLASS32 && @class != ElfHeader.ELFCLASS64)
                {
                    throw new FileFormatException($"Invalid ELF class: 0x{@class,0:X2}");
                }

                byte endianness = reader.ReadByte();

                if (endianness != ElfHeader.ELFDATA2LSB && endianness != ElfHeader.ELFDATA2MSB)
                {
                    throw new FileFormatException($"Invalid ELF endianness: 0x{endianness,0:X2}");
                }

                // Re-materialize the reader with the parsed endianness
                reader = new EndianBinaryReader(reader.BaseStream, endianness == ElfHeader.ELFDATA2MSB ? Endianness.BigEndian : Endianness.LittleEndian, Encoding.UTF8, true);

                ElfHeader header;

                switch (@class)
                {
                case ElfHeader.ELFCLASS32:
                {
                    header = new Bit32.ElfHeader(reader, savedPosition);
                    break;
                }

                case ElfHeader.ELFCLASS64:
                {
                    header = new Bit64.ElfHeader(reader, savedPosition);
                    break;
                }

                default:
                {
                    throw new InvalidOperationException("Unreachable case reached");
                }
                }

                var sections = new ElfSectionHeaderTable(reader, header);
                var segments = new ElfProgramHeaderTable(reader, header, sections);

                reader.BaseStream.Position = savedPosition;

                return(new ElfFile(header, segments, sections));
            }
            catch (InaccessibleAddressException exception)
            {
                throw new FileFormatException(exception.Message, exception);
            }
        }