예제 #1
0
        protected void processRelocationTable(byte[] htentry, bool abs)
        {
            uint off = getInt32(htentry, 16);
            // uint type = getInt32(htentry, 4);
            int  size      = (int)getInt32(htentry, 20);
            uint symtabNum = getInt32(htentry, 24);
            uint whichSect = getInt32(htentry, 28);

            if (trace > 0)
            {
                Debug.WriteLine(String.Format(
                                    "Relocation Table Entries (symtab=0x{0:X}, section=0x{1:X})",
                                    symtabNum, whichSect));
            }
            if (!loadSectionTable(whichSect, SHT.PROGBITS))
            {
                return;
            }
            string name = getSectionName((int)whichSect, SHT.PROGBITS);

            if (name == null)
            {
                return;
            }
            byte[] targetSection = sectionTable[whichSect];
            int    sectStart     = 0;

            switch (name)
            {
            case ".text":
                sectStart = TextStart;
                break;

            case ".data":
                sectStart = DataStart + roDataSize + roStrlDataSize;
                break;

            case ".rodata":
                sectStart = DataStart;
                break;

            case ".rodata.str1.4":
                sectStart = DataStart + roDataSize;
                break;

            case ".debug_line":
            case ".debug_info":
            case ".debug_abbrev":
                break;

            default:
                Debug.WriteLine(String.Format(
                                    "  relocation for {0} ignored", name));
                return;
            }
            int relEntryLen = abs? 12 : 8;

            byte[] relEntry = new byte[relEntryLen];
            fs.Seek((long)off + fsOrigin, SeekOrigin.Begin);
            while (size > 0)
            {
                int len = fs.Read(relEntry, 0, relEntryLen);
                if (len < relEntryLen)
                {
                    throw new AsmException("Read error (rel entry)");   // read error
                }
                int  offset = (int)getInt32(relEntry, 0);
                uint info   = getInt32(relEntry, 4);
                uint addend = abs? getInt32(relEntry, 8) : 0;
                size -= relEntryLen;
                uint sym    = info >> 8;
                uint rtype  = info & 0xFF;
                ST   symbol = symbolTable[symtabNum][sym];
                if (trace > 0)
                {
                    Debug.WriteLine(String.Format(
                                        "  offset=0x{0:X}, sym#=0x{1:X}, symName={2}, type#={3}, addend=0x{4:X}",
                                        offset, sym, symbol.name, rtype, addend));
                }
                performRelocation((uint)(sectStart + offset), offset, targetSection, addend, symbol, rtype);
            }
        }
예제 #2
0
        // apply relocation to the in-memory copy of the code section
        //    addr:    the run-time address of the location being relocated
        //    offset:  the offset within the object code section of the
        //             location being relocated
        //    section: an in-memory copy of the object code section
        //    addend:  a constant to add to the value of the relocation symbol
        //    symbol:  the relocation symbol whose value is to be added to
        //             the location specified by addr and offset.
        //    type:    the type of relocation to be performed, as specified
        //             in the Elf documentation (and as discovered by
        //             inspection of Arm object code files).
        protected void performRelocation(
            uint addr, int offset, byte[] section, uint addend, ST symbol, uint type)
        {
            uint        word    = getInt32(section, offset);
            uint        newWord = 0;
            string      name    = symbol.name;
            int         val;    // value of the symbol
            string      symbolKind = "??";
            SectionType st         = SectionType.Unknown;

            if (!String.IsNullOrEmpty(name))
            {
                bool    isNewUnknown = false;
                SyEntry sym          = af.LookupSymbol(name, out isNewUnknown);
                if (sym == null)
                {
                    if (name == "__cs3_heap_start" || name == "_end")
                    { // This is a temporary fixup; the proper solution would involve
                      // reading  loader script which defined __cs3_heap_start = _end.
                        val = DataEnd;
                        //af.DefineSymbol(name, -1, val-bssStart, SectionType.Bss);
                    }
                    //else if (name == "__cs3_heap_limit")
                    //    val = dataEnd + heapSize;
                    else
                    {
                        if (isNewUnknown)
                        {
                            af.ParseError("reference to undefined external symbol {0}", name);
                        }
                        return;
                    }
                }
                else
                {
                    val = sym.SymValue;
                }
            }
            else
            {
                bool local = true;
                val = getSymbolValue(symbol, ref symbolKind, ref st, ref local);
                switch (st)
                {
                case SectionType.Text:
                    val += TextStart;  break;

                case SectionType.Data:
                    val += DataStart;  break;

                case SectionType.Bss:
                    val += BssStart;  break;

                default:
                    Debug.WriteLine(String.Format(
                                        "- anon symbol, kind={0}, section type {1} ignored",
                                        symbolKind, st.ToString()));
                    return;
                }
            }
            uint opnd;
            bool supported = true;

            switch (type)
            {
            case 0:
                return;

            case 2:                             // R_ARM_ABS32
                newWord = (uint)(word + val + addend);
                break;

            case 1:                           // R_ARM_PC24   (used by gcc from Australia)
            case 27:                          // R_ARM_PLT32  (deprecated but used by CodeSourcery)
            case 28:                          // R_ARM_CALL   (used by CodeSourcery)
            case 29:                          // R_ARM_JUMP24 (used by CodeSourcery)
                opnd = (uint)((word & 0x00ffffff) << 2);
                if ((opnd & 0x02000000) != 0) // sign extend?
                {
                    opnd |= 0xFC000000;
                }
                opnd   += (uint)(val + addend - addr);
                opnd    = (uint)((opnd >> 2) & 0xFFFFFF);
                newWord = (uint)((word & 0xFF000000) | opnd);
                break;

            default:
                supported = false;
                break;
            }
            if (!supported || trace > 0)
            {
                Debug.WriteLine(String.Format(
                                    "  Relocation: old=0x{0:X}, new=0x{1:X}, val=0x{2:X}, add=0x{3:X}, type={4}",
                                    word, newWord, val, addend, type));
            }
            if (!supported)
            {
                throw new AsmException("unhandled relocation type: {0}", type);
            }
            putInt32(section, offset, newWord);
        }
예제 #3
0
        protected int getSymbolValue(
            ST symbol, ref string symbolKind, ref SectionType st, ref bool local)
        {
            string s = "none";

            st = SectionType.None;
            STB binding = (STB)((symbol.info >> 4) & 0x0f);

            if (binding == STB.WEAK)
            {
                Debug.WriteLine(String.Format(
                                    "weak binding for symbol ({0}) unsupported", symbol.name));
                symbolKind = s;
                return(0);
            }
            local = (binding != STB.GLOBAL);
            SHN sectNum = (SHN)symbol.shndx;

            if (sectNum == SHN.UNDEF)
            {
                s = "external";
            }
            else if ((uint)sectNum < (uint)SHN.LOPROC)
            {
                byte[] htentry    = sectionHeaderTable[(uint)sectNum];
                uint   sectNameIx = getInt32(htentry, 0);
                s = getString(sectNameIx);
            }
            else if (sectNum == SHN.ABS)
            {
                s = "absolute"; // for symbols with absolute addresses
            }
            else if (sectNum == SHN.COMMON)
            {
                s = "common";          // for COMM symbols
            }
            else
            {
                Debug.WriteLine(String.Format(
                                    "Unhandled symbol type (shndx=0x{0:X})", (uint)sectNum));
                symbolKind = s;
                return(0);
            }
            if (trace > 0)
            {
                Debug.WriteLine(String.Format(
                                    " symbol {0}: kind = {1} value=0x{2:X} size=0x{3:X}",
                                    symbol.name, s, symbol.value, symbol.size));
            }
            switch (s)
            {
            case ".text":
                st = SectionType.Text;  break;

            case ".data":
                st = SectionType.Data;  break;

            case ".rodata":
                st = SectionType.Data;  break;

            case ".rodata.str1.4":
                st = SectionType.Data;  break;

            case ".bss":
            case "common":
                st = SectionType.Bss;  break;

            case "absolute":
                st = SectionType.Abs;  break;

            case "external":
                af.DefineExternal(symbol.name);
                break;

            case "none":
            case ".debug_abbrev":
            case ".debug_line":
                break;

            default:
                Debug.WriteLine(String.Format(
                                    "Unsupported section type {0}", s));
                break;
            }
            symbolKind = s;
            int offset = (int)symbol.value;

            if (s == ".rodata.str1.4")
            {
                offset += roDataSize;
            }
            if (s == ".data")
            {
                offset += roDataSize + roStrlDataSize;
            }
            return(offset);
        }