/// <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)); } }