Пример #1
0
        private unsafe void WriteSectionHeader32()
        {
            var hdr = new Elf32_Ehdr();

            ObjectFile.CopyIdentTo(new Span <byte>(hdr.e_ident, EI_NIDENT));

            _encoder.Encode(out hdr.e_type, (ushort)ObjectFile.FileType);
            _encoder.Encode(out hdr.e_machine, ObjectFile.Arch.Value);
            _encoder.Encode(out hdr.e_version, EV_CURRENT);
            _encoder.Encode(out hdr.e_entry, (uint)ObjectFile.EntryPointAddress);
            _encoder.Encode(out hdr.e_ehsize, Layout.SizeOfElfHeader);
            _encoder.Encode(out hdr.e_flags, (uint)ObjectFile.Flags);

            // program headers
            _encoder.Encode(out hdr.e_phoff, (uint)Layout.OffsetOfProgramHeaderTable);
            _encoder.Encode(out hdr.e_phentsize, Layout.SizeOfProgramHeaderEntry);
            _encoder.Encode(out hdr.e_phnum, (ushort)ObjectFile.Segments.Count);

            // entries for sections
            _encoder.Encode(out hdr.e_shoff, (uint)Layout.OffsetOfSectionHeaderTable);
            _encoder.Encode(out hdr.e_shentsize, Layout.SizeOfSectionHeaderEntry);
            _encoder.Encode(out hdr.e_shnum, (ushort)ObjectFile.VisibleSectionCount);
            _encoder.Encode(out hdr.e_shstrndx, (ushort)(ObjectFile.SectionHeaderStringTable?.SectionIndex ?? (ushort)0));

            Write(hdr);
        }
Пример #2
0
 protected ELF32()
 {
     Header        = new Elf32_Ehdr();
     SectionHeader = null;
     SectionName   = null;
     NameMaxLength = 0;
 }
Пример #3
0
        public ELF32(string filename, bool readSectionHeaders)
            : this()
        {
            FileStream fs = File.Open(filename, FileMode.Open);

            byte[] ehdrBytes = new byte[52];
            fs.Read(ehdrBytes, 0, ehdrBytes.Length);
            fs.Close();

            if (!(ehdrBytes[(byte)EI.MagicNumber0] == 0x7F &&
                  ehdrBytes[(byte)EI.MagicNumber1] == 'E' &&
                  ehdrBytes[(byte)EI.MagicNumber2] == 'L' &&
                  ehdrBytes[(byte)EI.MagicNumber3] == 'F'))
            {
                throw new FormatException("It is not an ELF file.");
            }

            if (ehdrBytes[(byte)EI.FileClass] == (byte)EC.ELF64)
            {
                throw new FormatException("It is an ELF64 file.");
            }
            else if (ehdrBytes[(byte)EI.FileClass] != (byte)EC.ELF32)
            {
                throw new FormatException("It is an invalid ELF class.");
            }

            ValueRead read = new ValueRead(ehdrBytes[(byte)EI.DataEncoding]);

            Header = new Elf32_Ehdr(ehdrBytes, read);

            SectionHeader = new Elf32_Shdr[Header.e_shnum];
            SectionName   = new string[Header.e_shnum];

            if (readSectionHeaders && SectionHeader.Length != 0)
            {
                fs = File.Open(filename, FileMode.Open);
                byte[] shdrBytes = new byte[Header.e_shnum * Header.e_shentsize];
                fs.Position = Header.e_shoff;
                fs.Read(shdrBytes, 0, shdrBytes.Length);
                fs.Close();

                for (int i = 0; i < Header.e_shnum; i++)
                {
                    SectionHeader[i] = new Elf32_Shdr(shdrBytes, (uint)(Header.e_shentsize * i), read);
                    SectionName[i]   = "";
                }
            }
        }
Пример #4
0
        public override ProgramImage Load(Address addrLoad)
        {
            int i;

            m_lImageSize = RawImage.Length;

            m_pImage = RawImage;
            pHeader = ReadElfHeaderStart();
            arch = GetProcessorArchitecture();
            platform = GetPlatform();

            if (pHeader.e_ident != ELF_MAGIC)   
                throw new BadImageFormatException("Incorrect ELF header.");

            if (pHeader.e_phoff != 0)
                m_pPhdrs = LoadProgramHeaders(pHeader.e_phnum, pHeader.e_phoff);

            if (pHeader.e_shoff != 0)
                m_pShdrs = LoadSectionHeaders(pHeader.e_shnum, pHeader.e_shoff);

            // Set up section header string table pointer
            if (pHeader.e_shstrndx != 0)
                stringTableOffset = m_pShdrs[pHeader.e_shstrndx].sh_offset;

            i = 1; // counter - # sects. Start @ 1, total m_iNumSections

            // Number of sections
            m_iNumSections = pHeader.e_shnum;

            // Allocate room for all the Elf sections (including the silly first one)
            m_pSections = new SectionInfo[m_iNumSections];

            // Set up the m_sh_link and m_sh_info arrays
            m_sh_link = new int[m_iNumSections];
            m_sh_info = new int[m_iNumSections];

            // Number of elf sections
            bool bGotCode = false; // True when have seen a code sect

            Address arbitaryLoadAddr = Address.Ptr32(addrLoad.Linear);
            var rdr = CreateImageReader(pHeader.e_shoff);
            for (i = 0; i < m_iNumSections; i++)
            {
                var pShdr = m_pShdrs[i];
                string pName = ReadAsciiString(m_pShdrs[pHeader.e_shstrndx].sh_offset + pShdr.sh_name);
                var sect = new SectionInfo();
                m_pSections[i] = sect;
                m_pSections[i].pSectionName = pName;
                var off = pShdr.sh_offset;
                if (pShdr.sh_offset != 0)
                    sect.uHostAddr = off;
                sect.uNativeAddr = pShdr.sh_addr;
                sect.uSectionSize = pShdr.sh_size;
                if (sect.uNativeAddr == 0 && pName.StartsWith(".rel"))
                {
                    int align = pShdr.sh_addralign;
                    if (align > 1)
                    {
                        if ((arbitaryLoadAddr.Linear % align) != 0)
                            arbitaryLoadAddr += (int)(align - (arbitaryLoadAddr.Linear % align));
                    }
                    sect.uNativeAddr = arbitaryLoadAddr.Offset;
                    arbitaryLoadAddr += sect.uSectionSize;
                }
                sect.uType = pShdr.sh_type;
                m_sh_link[i] = pShdr.sh_link;
                m_sh_info[i] = pShdr.sh_info;
                sect.uSectionEntrySize = pShdr.sh_entsize;
                if (sect.uNativeAddr + sect.uSectionSize > next_extern)
                    first_extern = next_extern = sect.uNativeAddr + sect.uSectionSize;
                if ((pShdr.sh_flags & SectionFlags.SHF_WRITE) == 0)
                    sect.IsReadOnly = true;
                // Can't use the SHF_ALLOC bit to determine bss section; the bss section has SHF_ALLOC but also SHT_NOBITS.
                // (But many other sections, such as .comment, also have SHT_NOBITS). So for now, just use the name
                //      if ((elfRead4(&pShdr.sh_flags) & SHF_ALLOC) == 0)
                if (pName == ".bss")
                    sect.IsBss = true;
                if ((pShdr.sh_flags & SectionFlags.SHF_EXECINSTR) != 0)
                {
                    sect.IsCode = true;
                    bGotCode = true; // We've got to a code section
                }
                // Deciding what is data and what is not is actually quite tricky but important.
                // For example, it's crucial to flag the .exception_ranges section as data, otherwise there is a "hole" in the
                // allocation map, that means that there is more than one "delta" from a read-only section to a page, and in the
                // end using -C results in a file that looks OK but when run just says "Killed".
                // So we use the Elf designations; it seems that ALLOC.!EXEC -> data
                // But we don't want sections before the .text section, like .interp, .hash, etc etc. Hence bGotCode.
                // NOTE: this ASSUMES that sections appear in a sensible order in the input binary file:
                // junk, code, rodata, data, bss
                if (bGotCode &&
                    (pShdr.sh_flags & (SectionFlags.SHF_EXECINSTR | SectionFlags.SHF_ALLOC)) == SectionFlags.SHF_ALLOC &&
                       pShdr.sh_type != SectionType.SHT_NOBITS)
                    sect.bData = true;
                
                sect.Dump();
                Debug.WriteLine("");

            } // for each section

            // assign arbitary addresses to .rel.* sections too
            for (i = 0; i < m_iNumSections; i++)
            {
                if (m_pSections[i].uNativeAddr == 0 && m_pSections[i].pSectionName.StartsWith(".rel"))
                {
                    m_pSections[i].uNativeAddr = arbitaryLoadAddr.Offset;
                    arbitaryLoadAddr += m_pSections[i].uSectionSize;
                }
            }

            // Add symbol info. Note that some symbols will be in the main table only, and others in the dynamic table only.
            // So the best idea is to add symbols for all sections of the appropriate type
            for (i = 1; i < m_iNumSections; ++i)
            {
                var uType = m_pSections[i].uType;
                if (uType == SectionType.SHT_SYMTAB || uType == SectionType.SHT_DYNSYM)
                    AddSyms(i);
            }

            // Save the relocation to symbol table info
            SectionInfo pRel = GetSectionInfoByName(".rela.text");
            if (pRel != null)
            {
                m_bAddend = true; // Remember its a relA table
                m_pReloc =   (Elf32_Rel*)pRel.uHostAddr; // Save pointer to reloc table
            }
            else
            {
                m_bAddend = false;
                pRel = GetSectionInfoByName(".rel.text");
                if (pRel != null)
                {
                    SetRelocInfo(pRel);
                    m_pReloc = (Elf32_Rel*)pRel.uHostAddr; // Save pointer to reloc table
                }
            }

            // Find the PLT limits. Required for IsDynamicLinkedProc(), e.g.
            SectionInfo pPlt = GetSectionInfoByName(".plt");
            if (pPlt != null)
            {
                m_uPltMin = pPlt.uNativeAddr;
                m_uPltMax = pPlt.uNativeAddr + pPlt.uSectionSize;
            }
            return new ProgramImage(addrLoad, new byte[arbitaryLoadAddr - addrLoad]);
        }
Пример #5
0
        /// <summary>
        /// Reads the ELF header.
        /// </summary>
        /// <returns></returns>
        private Elf32_Ehdr ReadElfHeaderStart()
        {
            var rdr = new ImageReader(RawImage, 0);
            var h = new Elf32_Ehdr();

            h.e_ident = rdr.ReadBeUInt32();
            
            h.e_class = rdr.ReadByte();
            h.endianness = rdr.ReadByte();
            h.version = rdr.ReadByte();
            h.osAbi = rdr.ReadByte();

            rdr.Seek(8);             // 8 bytes of padding.

            // Now that we know the endianness, read the remaining fields in endian mode.
            rdr = CreateImageReader(h.endianness, rdr.Offset);
            h.e_type = rdr.ReadInt16();
            h.e_machine = rdr.ReadInt16();
            h.e_version = rdr.ReadInt32();
            h.e_entry = rdr.ReadUInt32();
            h.e_phoff = rdr.ReadUInt32();
            h.e_shoff = rdr.ReadUInt32();
            h.e_flags = rdr.ReadInt32();
            h.e_ehsize = rdr.ReadInt16();
            h.e_phentsize = rdr.ReadInt16();
            h.e_phnum = rdr.ReadInt16();
            h.e_shentsize = rdr.ReadInt16();
            h.e_shnum = rdr.ReadInt16();
            h.e_shstrndx = rdr.ReadInt16();

            Dump("e_type: {0}", h.e_type);
            Dump("e_machine: {0}", (MachineType) h.e_machine);
            Dump("e_version: {0}", h.e_version);
            Dump("e_entry: {0:X}", h.e_entry);
            Dump("e_phoff: {0:X}", h.e_phoff);
            Dump("e_shoff: {0:X}", h.e_shoff);
            Dump("e_flags: {0:X}", h.e_flags);
            Dump("e_ehsize: {0}", h.e_ehsize);
            Dump("e_phentsize: {0}", h.e_phentsize);
            Dump("e_phnum: {0}", h.e_phnum);
            Dump("e_shentsize: {0}", h.e_shentsize);
            Dump("e_shnum: {0}", h.e_shnum);
            Dump("e_shstrndx: {0}", h.e_shstrndx);
            
            return h;
        }
Пример #6
0
        private static void GetEmbeddedModule32(ModuleReader reader, byte[] ident)
        {
            // Read the endiannes.
            bool big = ident[(int)ElfIdent.EI_DATA] == (int)ElfData.ELFDATA2MSB;

            // Read the header.
            Elf32_Ehdr header = new Elf32_Ehdr();

            header.Read(reader, big);

            // Reject files without section names.
            if (header.e_shstrndex == (int)ElfSectionNumber.SHN_UNDEF)
            {
                throw new ModuleException("Unsupported elfs without section names");
            }

            // Read the "section names" section.
            reader.SetPosition((uint)(header.e_shoff + header.e_shstrndex * header.e_shentsize));
            Elf32_Shdr namesHeader = new Elf32_Shdr();

            namesHeader.Read(reader, big);

            // Reject files without real section names.
            if (namesHeader.sh_size == 0)
            {
                throw new ModuleException("This elf doesn't have section names.");
            }

            // Read the name table.
            byte[] nameTable;
            reader.SetPosition(namesHeader.sh_offset);
            reader.Read(out nameTable, (int)namesHeader.sh_size);

            // Move to the section header table.
            reader.SetPosition(header.e_shoff);

            // Read the section until hit '.cbm'.
            Elf32_Shdr    sectionHeader = new Elf32_Shdr();
            bool          found         = false;
            StringBuilder builder       = new StringBuilder();

            for (int i = 0; i < header.e_shnum; ++i)
            {
                // Read the section header.
                sectionHeader.Read(reader, big);

                // Check the section name.
                if (sectionHeader.sh_name >= nameTable.Length)
                {
                    throw new ModuleException("Invalid section name.");
                }

                // Build the section name.
                builder.Length = 0;
                int pos = (int)sectionHeader.sh_name;
                while (nameTable[pos] != 0)
                {
                    builder.Append((char)nameTable[pos++]);
                }
                string sectionName = builder.ToString();

                // Compare the section name.
                if (sectionName == ".cbm")
                {
                    found = true;
                    break;
                }

                // Skip the extra data.
                reader.Skip(header.e_shentsize - Elf32_Shdr.Size);
            }

            // Make sure the section was found.
            if (!found)
            {
                throw new ModuleException("The elf doesn't have a chela module.");
            }

            // Make sure the section type is PROGBITS.
            if (sectionHeader.sh_type != (int)ElfSectionType.SHT_PROGBITS)
            {
                throw new ModuleException("The elf section that can have the module is not supported.");
            }

            // Move to the section offset.
            reader.SetPosition(sectionHeader.sh_offset);
        }
Пример #7
0
        public RPX(string filename)
        {
            FileStream fs = File.Open(filename, FileMode.Open);

            byte[] ehdrBytes = new byte[52];
            fs.Read(ehdrBytes, 0, ehdrBytes.Length);
            fs.Close();

            if (!(ehdrBytes[0] == 0x7F &&
                  ehdrBytes[1] == 'E' &&
                  ehdrBytes[2] == 'L' &&
                  ehdrBytes[3] == 'F'))
            {
                throw new FormatException("It is not an ELF file.");
            }

            if (ehdrBytes[4] != 1 ||
                ehdrBytes[6] != 1)
            {
                throw new FormatException("It is not an ELF32 file.");
            }

            Header = new Elf32_Ehdr(ehdrBytes);

            if (Header.e_ident[5] != 2 ||
                Header.e_ident[7] != 0xCA ||
                Header.e_ident[8] != 0xFE ||
                Header.e_type != 0xFE01)
            {
                throw new FormatException("It is not an RPL/RPX file.");
            }

            if (Header.e_shnum == 0)
            {
                throw new FormatException("This RPL/RPX file has 0 sections.");
            }

            fs = File.Open(filename, FileMode.Open);
            byte[] shdrBytes = new byte[Header.e_shnum * Header.e_shentsize];
            fs.Position = Header.e_shoff;
            fs.Read(shdrBytes, 0, shdrBytes.Length);
            fs.Close();

            SectionHeader = new Elf32_Shdr[Header.e_shnum];

            int sectionCRCsIndex = 0;

            for (int i = 0; i < Header.e_shnum; i++)
            {
                SectionHeader[i] = new Elf32_Shdr(shdrBytes, Header.e_shentsize * i);
                if ((SectionHeader[i].sh_type & 0x80000003) == 0x80000003)//Section Header Type RPL CRCS
                {
                    sectionCRCsIndex = i;
                }
            }

            if (sectionCRCsIndex == 0)
            {
                throw new FormatException("Does not contain CRCs section.");
            }

            fs = File.Open(filename, FileMode.Open);
            byte[] sectionStrBytes = new byte[SectionHeader[Header.e_shstrndx].sh_size];
            fs.Position = SectionHeader[Header.e_shstrndx].sh_offset;
            fs.Read(sectionStrBytes, 0, sectionStrBytes.Length);
            byte[] sectionCRCsBytes = new byte[SectionHeader[sectionCRCsIndex].sh_size];
            fs.Position = SectionHeader[sectionCRCsIndex].sh_offset;
            fs.Read(sectionCRCsBytes, 0, sectionCRCsBytes.Length);
            fs.Close();

            if ((SectionHeader[Header.e_shstrndx].sh_flags & 0x08000000) == 0x08000000)//Section Header Flag RPL ZLIB
            {
                sectionStrBytes = Decompress(sectionStrBytes);
            }

            foreach (byte b in sectionStrBytes)
            {
                if (b > 127)
                {
                    throw new FormatException("Section Strings are not ASCII.");
                }
            }

            SectionName = new string[Header.e_shnum];
            CRC         = new uint[Header.e_shnum];

            long sum = 0;

            for (int i = 0; i < Header.e_shnum; i++)
            {
                uint stringLength = 0;
                while (sectionStrBytes[SectionHeader[i].sh_name + stringLength] != 0)
                {
                    stringLength++;
                }
                SectionName[i] = Encoding.ASCII.GetString(sectionStrBytes, (int)SectionHeader[i].sh_name, (int)stringLength);

                CRC[i] = ReadUInt32Reverse(sectionCRCsBytes, i * 4);
                sum   += CRC[i];//Add all the CRCs

                if (SectionHeader[i].sh_offset != 0)
                {
                    if (SectionName[i] == ".text")
                    {
                        TextSectionIndex = i;//Always 2
                    }
                    else if (SectionName[i] == ".rodata")
                    {
                        RodataSectionIndex = i;//Always 3
                    }
                }
            }
            sum    -= (long)CRC[TextSectionIndex] + CRC[RodataSectionIndex] + CRC[CRC.Length - 1]; //Subtract ".text" CRC, ".rodata" CRC and "RPL Info" CRC
            CRCsSum = (uint)(sum >> 4);                                                            //Discard the least significant 4 bits

            FileName = filename;
        }
Пример #8
0
        private static void GetEmbeddedModule32(ModuleReader reader, byte[] ident)
        {
            // Read the endiannes.
            bool big = ident[(int)ElfIdent.EI_DATA] == (int)ElfData.ELFDATA2MSB;

            // Read the header.
            Elf32_Ehdr header = new Elf32_Ehdr();
            header.Read(reader, big);

            // Reject files without section names.
            if(header.e_shstrndex == (int)ElfSectionNumber.SHN_UNDEF)
                throw new ModuleException("Unsupported elfs without section names");

            // Read the "section names" section.
            reader.SetPosition((uint) (header.e_shoff + header.e_shstrndex*header.e_shentsize));
            Elf32_Shdr namesHeader = new Elf32_Shdr();
            namesHeader.Read(reader, big);

            // Reject files without real section names.
            if(namesHeader.sh_size == 0)
                throw new ModuleException("This elf doesn't have section names.");

            // Read the name table.
            byte[] nameTable;
            reader.SetPosition(namesHeader.sh_offset);
            reader.Read(out nameTable, (int)namesHeader.sh_size);

            // Move to the section header table.
            reader.SetPosition(header.e_shoff);

            // Read the section until hit '.cbm'.
            Elf32_Shdr sectionHeader = new Elf32_Shdr();
            bool found = false;
            StringBuilder builder = new StringBuilder();
            for(int i = 0; i < header.e_shnum; ++i)
            {
                // Read the section header.
                sectionHeader.Read(reader, big);

                // Check the section name.
                if(sectionHeader.sh_name >= nameTable.Length)
                    throw new ModuleException("Invalid section name.");

                // Build the section name.
                builder.Length = 0;
                int pos = (int)sectionHeader.sh_name;
                while(nameTable[pos] != 0)
                    builder.Append((char)nameTable[pos++]);
                string sectionName = builder.ToString();

                // Compare the section name.
                if(sectionName == ".cbm")
                {
                    found = true;
                    break;
                }

                // Skip the extra data.
                reader.Skip(header.e_shentsize - Elf32_Shdr.Size);
            }

            // Make sure the section was found.
            if(!found)
                throw new ModuleException("The elf doesn't have a chela module.");

            // Make sure the section type is PROGBITS.
            if(sectionHeader.sh_type != (int)ElfSectionType.SHT_PROGBITS)
                throw new ModuleException("The elf section that can have the module is not supported.");

            // Move to the section offset.
            reader.SetPosition(sectionHeader.sh_offset);
        }