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); }
protected ELF32() { Header = new Elf32_Ehdr(); SectionHeader = null; SectionName = null; NameMaxLength = 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] = ""; } } }
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]); }
/// <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; }
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); }
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; }
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); }