private void LoadImportReferencesFromRelPlt(Dictionary <Address, ImportReference> importReferences) { var rel_plt = loader.GetSectionInfoByName(".rel.plt"); var symtab = rel_plt.LinkedSection; var plt = loader.GetSectionInfoByName(".plt"); var relRdr = loader.CreateReader(rel_plt.FileOffset); uint entries = rel_plt.EntryCount(); for (uint i = 0; i < entries; ++i) { uint offset; if (!relRdr.TryReadUInt32(out offset)) { return; } uint info; if (!relRdr.TryReadUInt32(out info)) { return; } uint sym = info >> 8; string symStr = loader.GetSymbolName(symtab, sym); var addr = plt.Address + (i + 1) * plt.EntrySize; importReferences[addr] = new NamedImportReference( addr, null, symStr); } }
public override void Relocate(Program program) { DumpRel32(loader); DumpRela32(loader); foreach (var relSection in loader.Sections) { if (relSection.Type == SectionHeaderType.SHT_REL) { var sectionSymbols = loader.Symbols[relSection.LinkedSection]; var referringSection = relSection.RelocatedSection; var rdr = loader.CreateReader(relSection.FileOffset); for (uint i = 0; i < relSection.EntryCount(); ++i) { var rel = Elf32_Rel.Read(rdr); var sym = sectionSymbols[(int)(rel.r_info >> 8)]; RelocateEntry(program, sym, referringSection, rel); } } else if (relSection.Type == SectionHeaderType.SHT_RELA) { var sectionSymbols = loader.Symbols[relSection.LinkedSection]; var referringSection = relSection.RelocatedSection; var rdr = loader.CreateReader(relSection.FileOffset); for (uint i = 0; i < relSection.EntryCount(); ++i) { var rela = Elf32_Rela.Read(rdr); var sym = sectionSymbols[(int)(rela.r_info >> 8)]; RelocateEntry(program, sym, referringSection, rela); } } } }
/// <remarks> /// According to the ELF PPC32 documentation, the .rela.plt and .plt tables /// should contain the same number of entries, even if the individual entry /// sizes are distinct. The entries in .real.plt refer to symbols while the /// entries in .plt are (writeable) pointers. Any caller that jumps to one /// of pointers in the .plt table is a "trampoline", and should be replaced /// in the decompiled code with just a call to the symbol obtained from the /// .real.plt section. /// </remarks> public override void Relocate(Program program) { base.Relocate(program); var rela_plt = loader.GetSectionInfoByName(".rela.plt"); if (rela_plt == null) { return; } var plt = loader.GetSectionInfoByName(".plt"); var relaRdr = loader.CreateReader(rela_plt.FileOffset); var pltRdr = loader.CreateReader(plt.FileOffset); for (int i = 0; i < rela_plt.EntryCount(); ++i) { // Read the .rela.plt entry uint offset; if (!relaRdr.TryReadUInt32(out offset)) { return; } uint info; if (!relaRdr.TryReadUInt32(out info)) { return; } int addend; if (!relaRdr.TryReadInt32(out addend)) { return; } // Read the .plt entry. We don't care about its contents, // only its address. Anyone accessing that address is // trying to access the symbol. uint thunkAddress; if (!pltRdr.TryReadUInt32(out thunkAddress)) { break; } uint sym = info >> 8; string symStr = loader.GetSymbolName(rela_plt.LinkedSection, sym); var addr = plt.Address + (uint)i * 4; program.ImportReferences.Add( addr, new NamedImportReference(addr, null, symStr)); } }
protected void DumpRela32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA)) { ElfImageLoader.trace.Inform( "RELA: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); var symbols = loader.Symbols[section.LinkedSection.FileOffset]; var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rela = Elf32_Rela.Read(rdr); ElfImageLoader.trace.Verbose( " off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2}", rela.r_offset, RelocationTypeToString(rela.r_info & 0xFF), symbols[(int)(rela.r_info >> 8)].Name, rela.r_addend, (int)(rela.r_info >> 8)); } } }
public override void Relocate(Program program) { // Get all relocations from PT_DYNAMIC segments first; these are the relocations actually // carried out by the operating system. var symbols = RelocateDynamicSymbols(program); if (symbols.Count > 0) { return; } DumpRel32(loader); DumpRela32(loader); foreach (var relSection in loader.Sections) { if (relSection.Type == SectionHeaderType.SHT_REL) { loader.Symbols.TryGetValue(relSection.LinkedSection.FileOffset, out var sectionSymbols); var referringSection = relSection.RelocatedSection; var rdr = loader.CreateReader(relSection.FileOffset); for (uint i = 0; i < relSection.EntryCount(); ++i) { var rel = loader.LoadRelEntry(rdr); var sym = sectionSymbols?[rel.SymbolIndex]; RelocateEntry(program, sym, referringSection, rel); } } else if (relSection.Type == SectionHeaderType.SHT_RELA) { loader.Symbols.TryGetValue(relSection.LinkedSection.FileOffset, out var sectionSymbols); var referringSection = relSection.RelocatedSection; var rdr = loader.CreateReader(relSection.FileOffset); for (uint i = 0; i < relSection.EntryCount(); ++i) { var rela = loader.LoadRelaEntry(rdr); var sym = sectionSymbols?[rela.SymbolIndex]; RelocateEntry(program, sym, referringSection, rela); } } } }
protected void DumpRel32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_REL)) { Debug.Print("REL: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); var symbols = loader.Symbols[section.LinkedSection.FileOffset]; var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rel = Elf32_Rel.Read(rdr); Debug.Print(" off:{0:X8} type:{1,-16} {3,3} {2}", rel.r_offset, RelocationTypeToString(rel.r_info & 0xFF), symbols[(int)(rel.r_info >> 8)].Name, (int)(rel.r_info >> 8)); } } }
protected void DumpRel32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_REL)) { ElfImageLoader.trace.Inform("REL: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); loader.Symbols.TryGetValue(section.LinkedSection.FileOffset, out var symbols); var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rel = Elf32_Rel.Read(rdr); ElfImageLoader.trace.Verbose( " off:{0:X8} type:{1,-16} {3,3} {2}", rel.r_offset, RelocationTypeToString(rel.r_info & 0xFF), symbols != null ? symbols[(int)(rel.r_info >> 8)].Name : "<nosym>", (int)(rel.r_info >> 8)); } } }
protected void DumpRela32(ElfLoader32 loader) { foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA)) { Debug.Print("RELA: offset {0:X} symbol section {1}, relocating in section {2}", section.FileOffset, section.LinkedSection.Name, section.RelocatedSection.Name); var symbols = loader.Symbols[section.LinkedSection]; var rdr = loader.CreateReader(section.FileOffset); for (uint i = 0; i < section.EntryCount(); ++i) { var rela = Elf32_Rela.Read(rdr); Debug.Print(" off:{0:X8} type:{1,-16} add:{3,-20} {4,3} {2}", rela.r_offset, RelocationTypeToString(rela.r_info & 0xFF), symbols[(int)(rela.r_info >> 8)].Name, rela.r_addend, (int)(rela.r_info >> 8)); } } }