Exemple #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));
            }
        }
Exemple #2
0
        public override void Render(ImageSegment segment, Program program, Formatter formatter)
        {
            var entries = shdr.Size / shdr.EntrySize;
            var symtab  = shdr.LinkedSection;
            var rdr     = loader.CreateReader(shdr.FileOffset);

            for (ulong 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 = loader.GetSymbolName(symtab, sym);
                formatter.Write("{0:X8} {1,3} {2:X8} {3:X8} {4} ({5})", offset, info & 0xFF, sym, addend, symStr, sym);
                formatter.WriteLine();
            }
        }
 public override void Render(ImageSegment segment, Program program, Formatter formatter)
 {
     var entries = shdr.EntryCount();
     var symtab = shdr.LinkedSection;
     var rdr = loader.CreateReader(shdr.FileOffset);
     for (int i = 0; i < entries; ++i)
     {
         uint iName;
         if (!rdr.TryReadUInt32(out iName))
             return;
         uint value;
         if (!rdr.TryReadUInt32(out value))
             return;
         uint size;
         if (!rdr.TryReadUInt32(out size))
             return;
         byte info;
         if (!rdr.TryReadByte(out info))
             return;
         byte other;
         if (!rdr.TryReadByte(out other))
             return;
         ushort shIndex;
         if (!rdr.TryReadUInt16(out shIndex))
             return;
         string symStr = loader.GetStrPtr(symtab, iName);
         string segName = loader.GetSectionName(shIndex);
         formatter.Write("{0:X4} {1,-40} {2:X8} {3:X8} {4:X2} {5}", i, symStr, value, size, info & 0xFF, segName);
         formatter.WriteLine();
     }
 }
Exemple #4
0
        public override void Render(ImageSegment segment, Program program, Formatter formatter)
        {
            var entries = shdr.sh_size / shdr.sh_entsize;
            var symtab  = (int)shdr.sh_link;
            var rdr     = loader.CreateReader(shdr.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;
                }

                uint   sym    = info >> 8;
                string symStr = loader.GetSymbolName(symtab, sym);
                formatter.Write("{0:X8} {1,3} {2:X8} {3}", offset, info & 0xFF, sym, symStr);
                formatter.WriteLine();
            }
        }
Exemple #5
0
 public override void Relocate(Program program)
 {
     DumpRela32(loader);
     foreach (var relSection in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA))
     {
         var symbols          = 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  = symbols[(int)(rela.r_info >> 8)];
             RelocateEntry(program, sym, referringSection, rela);
         }
     }
 }
Exemple #6
0
        public override void Render(ImageSegment segment, Program program, Formatter formatter)
        {
            var entries = shdr.sh_size / shdr.sh_entsize;
            var symtab  = (int)shdr.sh_link;
            var rdr     = loader.CreateReader(shdr.sh_offset);

            for (int i = 0; i < entries; ++i)
            {
                uint iName;
                if (!rdr.TryReadUInt32(out iName))
                {
                    return;
                }
                uint value;
                if (!rdr.TryReadUInt32(out value))
                {
                    return;
                }
                uint size;
                if (!rdr.TryReadUInt32(out size))
                {
                    return;
                }
                byte info;
                if (!rdr.TryReadByte(out info))
                {
                    return;
                }
                byte other;
                if (!rdr.TryReadByte(out other))
                {
                    return;
                }
                ushort shIndex;
                if (!rdr.TryReadUInt16(out shIndex))
                {
                    return;
                }
                string symStr  = loader.GetStrPtr(symtab, iName);
                string segName = loader.GetSectionName(shIndex);
                formatter.Write("{0,-40} {1:X8} {2:X8} {3:X2} {4}", symStr, value, size, info & 0xFF, segName);
                formatter.WriteLine();
            }
        }
Exemple #7
0
        protected void DumpRela32(ElfLoader32 loader)
        {
            foreach (var section in loader.Sections.Where(s => s.Type == SectionHeaderType.SHT_RELA))
            {
                Debug.Print("RELA: offset {0:X} link section {1}",
                            section.FileOffset,
                            section.LinkedSection.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,
                                (SparcRt)(rela.r_info & 0xFF),
                                symbols[(int)(rela.r_info >> 8)].Name,
                                rela.r_addend,
                                (int)(rela.r_info >> 8));
                }
            }
        }
Exemple #8
0
        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));
                }
            }
        }
Exemple #9
0
        public void RelocateOld(Program program)
        {
            uint nextFakeLibAddr = ~1u; // See R_386_PC32 below; -1 sometimes used for main

            for (int i = 1; i < loader.Sections.Count; ++i)
            {
                var ps = loader.Sections[i];
                if (ps.Type == SectionHeaderType.SHT_REL)
                {
                    // A section such as .rel.dyn or .rel.plt (without an addend field).
                    // Each entry has 2 words: r_offset and r_info. The r_offset is just the offset from the beginning
                    // of the section (section given by the section header's sh_info) to the word to be modified.
                    // r_info has the type in the bottom byte, and a symbol table index in the top 3 bytes.
                    // A symbol table offset of 0 (STN_UNDEF) means use value 0. The symbol table involved comes from
                    // the section header's sh_link field.
                    var   pReloc = loader.CreateReader(ps.FileOffset);
                    ulong size   = ps.Size;
                    // NOTE: the r_offset is different for .o files (ET_REL in the e_type header field) than for exe's
                    // and shared objects!
                    uint destNatOrigin  = 0;
                    uint destHostOrigin = 0;
                    if (loader.Header.e_type == ElfImageLoader.ET_REL)
                    {
                        var destSection = loader.Sections[i].RelocatedSection;
                        destNatOrigin  = destSection.Address.ToUInt32();
                        destHostOrigin = (uint)destSection.FileOffset;
                    }
                    var symSection  = loader.Sections[i].LinkedSection; // associated symbol table
                    var strSection  = symSection.LinkedSection;         // Section index for the string section assoc with this
                    var pStrSection = strSection.FileOffset;
                    var symOrigin   = symSection.FileOffset;
                    var relocR      = loader.CreateReader(0);
                    var relocW      = loader.CreateWriter(0);
                    for (uint u = 0; u < size; u += 2 * sizeof(uint))
                    {
                        uint r_offset = pReloc.ReadUInt32();
                        uint info     = pReloc.ReadUInt32();

                        byte relType     = (byte)info;
                        uint symTabIndex = info >> 8;
                        uint pRelWord; // Pointer to the word to be relocated
                        if (loader.Header.e_type == ElfImageLoader.ET_REL)
                        {
                            pRelWord = destHostOrigin + r_offset;
                        }
                        else
                        {
                            if (r_offset == 0)
                            {
                                continue;
                            }
                            var destSec = loader.GetSectionInfoByAddr(r_offset);
                            pRelWord      = ~0u; // destSec.uHostAddr - destSec.uNativeAddr + r_offset;
                            destNatOrigin = 0;
                        }
                        uint A, S = 0, P;
                        int  nsec;
                        var  sym = Elf32_Sym.Load(loader.CreateReader(symOrigin + symTabIndex * Elf32_Sym.Size));
                        switch (relType)
                        {
                        case 0: // R_386_NONE: just ignore (common)
                            break;

                        case 1: // R_386_32: S + A
                            // Read the symTabIndex'th symbol.
                            S = sym.st_value;
                            if (loader.Header.e_type == ElfImageLoader.ET_REL)
                            {
                                nsec = sym.st_shndx;
                                if (nsec >= 0 && nsec < loader.Sections.Count)
                                {
                                    S += loader.Sections[nsec].Address.ToUInt32();
                                }
                            }
                            A = relocR.ReadUInt32(pRelWord);
                            relocW.WriteUInt32(pRelWord, S + A);
                            break;

                        case 2: // R_386_PC32: S + A - P
                            if (ElfLoader32.ELF32_ST_TYPE(sym.st_info) == ElfLoader.STT_SECTION)
                            {
                                nsec = sym.st_shndx;
                                if (nsec >= 0 && nsec < loader.Sections.Count)
                                {
                                    S = loader.Sections[nsec].Address.ToUInt32();
                                }
                            }
                            else
                            {
                                S = sym.st_value;
                                if (S == 0)
                                {
                                    // This means that the symbol doesn't exist in this module, and is not accessed
                                    // through the PLT, i.e. it will be statically linked, e.g. strcmp. We have the
                                    // name of the symbol right here in the symbol table entry, but the only way
                                    // to communicate with the loader is through the target address of the call.
                                    // So we use some very improbable addresses (e.g. -1, -2, etc) and give them entries
                                    // in the symbol table
                                    uint   nameOffset = sym.st_name;
                                    string pName      = loader.ReadAsciiString(pStrSection + nameOffset);
                                    // this is too slow, I'm just going to assume it is 0
                                    //S = GetAddressByName(pName);
                                    //if (S == (e_type == E_REL ? 0x8000000 : 0)) {
                                    S = nextFakeLibAddr--; // Allocate a new fake address
                                    loader.AddSymbol(S, pName);
                                    //}
                                }
                                else if (loader.Header.e_type == ElfImageLoader.ET_REL)
                                {
                                    nsec = sym.st_shndx;
                                    if (nsec >= 0 && nsec < loader.Sections.Count)
                                    {
                                        S += loader.Sections[nsec].Address.ToUInt32();
                                    }
                                }
                            }
                            A = relocR.ReadUInt32(pRelWord);
                            P = destNatOrigin + r_offset;
                            relocW.WriteUInt32(pRelWord, S + A - P);
                            break;

                        case 6: // R_386_GLOB_DAT
                            // This relocation type is used to set a global offset table entry to the address of the
                            // specified symbol. The special relocation type allows one to determine the
                            // correspondence between symbols and global offset table entries.
                            S = sym.st_value;
                            relocW.WriteUInt32(pRelWord, S);
                            break;

                        case 7:
                        case 8:    // R_386_RELATIVE
                            break; // No need to do anything with these, if a shared object

                        default:
                            throw new NotSupportedException("Relocation type " + (int)relType + " not handled yet");
                        }
                    }
                }
            }
        }