public override void LoadSectionHeaders() { // Create the sections. var inames = new List <uint>(); var links = new List <uint>(); var infos = new List <uint>(); var rdr = imgLoader.CreateReader(Header.e_shoff); for (uint i = 0; i < Header.e_shnum; ++i) { var shdr = Elf32_SHdr.Load(rdr); if (shdr == null) { break; } var section = new ElfSection { Number = i, Type = shdr.sh_type, Flags = shdr.sh_flags, Address = Address.Ptr32(shdr.sh_addr), FileOffset = shdr.sh_offset, Size = shdr.sh_size, Alignment = shdr.sh_addralign, EntrySize = shdr.sh_entsize, }; Sections.Add(section); inames.Add(shdr.sh_name); links.Add(shdr.sh_link); infos.Add(shdr.sh_info); } // Get section names and crosslink sections. for (int i = 0; i < Sections.Count; ++i) { var section = Sections[i]; section.Name = ReadSectionName(inames[i]); ElfSection linkSection = null; ElfSection relSection = null; switch (section.Type) { case SectionHeaderType.SHT_REL: case SectionHeaderType.SHT_RELA: linkSection = GetSectionByIndex(links[i]); relSection = GetSectionByIndex(infos[i]); break; case SectionHeaderType.SHT_DYNAMIC: case SectionHeaderType.SHT_HASH: case SectionHeaderType.SHT_SYMTAB: case SectionHeaderType.SHT_DYNSYM: linkSection = GetSectionByIndex(links[i]); break; } section.LinkedSection = linkSection; section.RelocatedSection = relSection; } }
public SymtabSegmentRenderer(ElfImageLoader loader, Elf32_SHdr shdr) { this.loader = loader; this.shdr = shdr; }
public RelaSegmentRenderer(ElfImageLoader loader, Elf32_SHdr shdr) { this.loader = loader; this.shdr = shdr; }
private void DumpRela(Elf32_SHdr sh) { var entries = sh.sh_size / sh.sh_entsize; var symtab = sh.sh_link; var rdr = CreateReader(sh.sh_offset); for (int i = 0; i < entries; ++i) { uint offset; if (!rdr.TryReadUInt32(out offset)) return; uint info; if (!rdr.TryReadUInt32(out info)) return; int addend; if (!rdr.TryReadInt32(out addend)) return; uint sym = info >> 8; string symStr = GetStrPtr((int)symtab, sym); Debug.Print(" RELA {0:X8} {1,3} {2:X8} {3:X8} {4}", offset, info&0xFF, sym, addend, symStr); } }
private ImageMapSegmentRenderer CreateRenderer(Elf32_SHdr shdr) { switch (shdr.sh_type) { case SectionHeaderType.SHT_DYNAMIC: return new DynamicSectionRenderer(this, shdr); case SectionHeaderType.SHT_RELA: return new RelaSegmentRenderer(this, shdr); default: return null; } }
public string GetStrPtr(Elf32_SHdr sect, uint offset) { if (sect == null) { // Most commonly, this will be an null, because a call to GetSectionByName() failed throw new ArgumentException("GetStrPtr passed null section."); } // Get a pointer to the start of the string table and add the offset return ReadAsciiString( RawImage, sect.sh_offset + offset); }
// Add appropriate symbols to the symbol table. secIndex is the section index of the symbol table. private void AddSyms(Elf32_SHdr pSect) { int e_type = this.Header32.e_type; // Calc number of symbols uint nSyms = pSect.sh_size / pSect.sh_entsize; uint offSym = pSect.sh_offset; //m_pSym = (Elf32_Sym*)pSect.uHostAddr; // Pointer to symbols uint strIdx = pSect.sh_link; // sh_link points to the string table var siPlt = GetSectionInfoByName32(".plt"); uint addrPlt = siPlt!=null ? siPlt.sh_addr : 0; var siRelPlt = GetSectionInfoByName32(".rel.plt"); uint sizeRelPlt = 8; // Size of each entry in the .rel.plt table if (siRelPlt == null) { siRelPlt = GetSectionInfoByName32(".rela.plt"); sizeRelPlt = 12; // Size of each entry in the .rela.plt table is 12 bytes } uint addrRelPlt = 0; uint numRelPlt = 0; if (siRelPlt != null) { addrRelPlt = siRelPlt.sh_addr; numRelPlt = sizeRelPlt != 0 ? siRelPlt.sh_size / sizeRelPlt : 0u; } // Number of entries in the PLT: // int max_i_for_hack = siPlt ? (int)siPlt.uSectionSize / 0x10 : 0; // Index 0 is a dummy entry var symRdr = CreateReader(offSym); for (int i = 1; i < nSyms; i++) { uint name; if (!symRdr.TryReadUInt32(out name)) break; uint val; if (!symRdr.TryReadUInt32(out val)) //= (ADDRESS)elfRead4((int)m_pSym[i].st_value); break; uint size; if (!symRdr.TryReadUInt32(out size)) break; byte info; if (!symRdr.TryReadByte(out info)) break; byte other; if (!symRdr.TryReadByte(out other)) break; ushort shndx; if (!symRdr.TryReadLeUInt16(out shndx)) break; if (name == 0) continue; // Weird: symbol w no name. if (shndx >= SectionHeaders.Count) { } else { var otherSection = SectionHeaders[shndx]; } string str = GetStrPtr((int)strIdx, name); // Hack off the "@@GLIBC_2.0" of Linux, if present int pos; if ((pos = str.IndexOf("@@")) >= 0) str = str.Remove(pos); // Ensure no overwriting (except functions) #if Nilx if (@m_SymTab.ContainsKey(val) || ELF32_ST_TYPE(m_pSym[i].st_info) == STT_FUNC) { if (val == 0 && siPlt != null) { //&& i < max_i_for_hack) { throw new NotImplementedException(); // Special hack for gcc circa 3.3.3: (e.g. test/pentium/settest). The value in the dynamic symbol table // is zero! I was assuming that index i in the dynamic symbol table would always correspond to index i // in the .plt section, but for fedora2_true, this doesn't work. So we have to look in the .rel[a].plt // section. Thanks, gcc! Note that this hack can cause strange symbol names to appear //val = findRelPltOffset(i, addrRelPlt, sizeRelPlt, numRelPlt, addrPlt); } else if (e_type == ET_REL) { throw new NotImplementedException(); #if NYI int nsec = elfRead2(m_pSym[i].st_shndx); if (nsec >= 0 && nsec < m_iNumSections) val += GetSectionInfo(nsec)->uNativeAddr; #endif } m_SymTab[val] = str; } #endif Debug.Print(" Symbol {0} ({0:X}) with address {1:X} (segment {2} {2:X}): {3}", i, val, shndx, str); } #if NYI ADDRESS uMain = GetMainEntryPoint(); if (uMain != NO_ADDRESS && m_SymTab.find(uMain) == m_SymTab.end()) { // Ugh - main mustn't have the STT_FUNC attribute. Add it string sMain = "main"; m_SymTab[uMain] = sMain; } return; #endif }
public DynamicSectionRenderer(ElfImageLoader loader, Elf32_SHdr shdr) { this.loader = loader; this.shdr = shdr; }
public SymtabSegmentRenderer32(ElfLoader32 loader, Elf32_SHdr shdr) { this.loader = loader; this.shdr = shdr; }
public RelSegmentRenderer(ElfLoader32 loader, Elf32_SHdr shdr) { this.loader = loader; this.shdr = shdr; }