Example #1
0
        /// <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));
            }
        }