VirtualBox

Changeset 46259 in vbox for trunk/src/VBox/Runtime


Ignore:
Timestamp:
May 24, 2013 7:20:19 PM (12 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
85993
Message:

ldrELFRelocatable.cpp.h: Made ET_EXEC and ET_DYN partially work so the DWARF code can get its job done.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/ldr/ldrELFRelocatable.cpp.h

    r46180 r46259  
    9999    /** The ELF header. */
    100100    Elf_Ehdr                Ehdr;
    101     /** Pointer to our copy of the section headers.
     101    /** Pointer to our copy of the section headers with sh_addr as RVAs.
    102102     * The virtual addresses in this array is the 0 based assignments we've given the image.
    103103     * Not valid if the image is DONE. */
     
    108108    /** The size of the loaded image. */
    109109    size_t                  cbImage;
     110
     111    /** The image base address if it's an EXEC or DYN image. */
     112    Elf_Addr                LinkAddress;
    110113
    111114    /** The symbol section index. */
     
    156159}
    157160
     161
     162/*
     163 *
     164 * EXEC & DYN.
     165 * EXEC & DYN.
     166 * EXEC & DYN.
     167 * EXEC & DYN.
     168 * EXEC & DYN.
     169 *
     170 */
     171
     172
     173/**
     174 * Applies the fixups for a section in an executable image.
     175 *
     176 * @returns iprt status code.
     177 * @param   pModElf         The ELF loader module instance data.
     178 * @param   BaseAddr        The base address which the module is being fixedup to.
     179 * @param   pfnGetImport    The callback function to use to resolve imports (aka unresolved externals).
     180 * @param   pvUser          User argument to pass to the callback.
     181 * @param   SecAddr         The section address. This is the address the relocations are relative to.
     182 * @param   cbSec           The section size. The relocations must be inside this.
     183 * @param   pu8SecBaseR     Where we read section bits from.
     184 * @param   pu8SecBaseW     Where we write section bits to.
     185 * @param   pvRelocs        Pointer to where we read the relocations from.
     186 * @param   cbRelocs        Size of the relocations.
     187 */
     188static int RTLDRELF_NAME(RelocateSectionExecDyn)(PRTLDRMODELF pModElf, Elf_Addr BaseAddr,
     189                                                 PFNRTLDRIMPORT pfnGetImport, void *pvUser,
     190                                                 const Elf_Addr SecAddr, Elf_Size cbSec,
     191                                                 const uint8_t *pu8SecBaseR, uint8_t *pu8SecBaseW,
     192                                                 const void *pvRelocs, Elf_Size cbRelocs)
     193{
     194#if ELF_MODE != 32
     195    NOREF(pu8SecBaseR);
     196#endif
     197
     198    /*
     199     * Iterate the relocations.
     200     * The relocations are stored in an array of Elf32_Rel records and covers the entire relocation section.
     201     */
     202    const Elf_Addr    offDelta = BaseAddr - pModElf->LinkAddress;
     203    const Elf_Reloc  *paRels   = (const Elf_Reloc *)pvRelocs;
     204    const unsigned    iRelMax   = (unsigned)(cbRelocs / sizeof(paRels[0]));
     205    AssertMsgReturn(iRelMax == cbRelocs / sizeof(paRels[0]), (FMT_ELF_SIZE "\n", cbRelocs / sizeof(paRels[0])),
     206                    VERR_IMAGE_TOO_BIG);
     207    for (unsigned iRel = 0; iRel < iRelMax; iRel++)
     208    {
     209        /*
     210         * Skip R_XXX_NONE entries early to avoid confusion in the symbol
     211         * getter code.
     212         */
     213#if   ELF_MODE == 32
     214        if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE)
     215            continue;
     216#elif ELF_MODE == 64
     217        if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE)
     218            continue;
     219#endif
     220
     221        /*
     222         * Validate and find the symbol, resolve undefined ones.
     223         */
     224        Elf_Size iSym = ELF_R_SYM(paRels[iRel].r_info);
     225        if (iSym >= pModElf->cSyms)
     226        {
     227            AssertMsgFailed(("iSym=%d is an invalid symbol index!\n", iSym));
     228            return VERR_LDRELF_INVALID_SYMBOL_INDEX;
     229        }
     230        const Elf_Sym *pSym = &pModElf->paSyms[iSym];
     231        if (pSym->st_name >= pModElf->cbStr)
     232        {
     233            AssertMsgFailed(("iSym=%d st_name=%d str sh_size=%d\n", iSym, pSym->st_name, pModElf->cbStr));
     234            return VERR_LDRELF_INVALID_SYMBOL_NAME_OFFSET;
     235        }
     236
     237        Elf_Addr SymValue = 0;
     238        if (pSym->st_shndx == SHN_UNDEF)
     239        {
     240            /* Try to resolve the symbol. */
     241            const char *pszName = ELF_STR(pModElf, pSym->st_name);
     242            RTUINTPTR   ExtValue;
     243            int rc = pfnGetImport(&pModElf->Core, "", pszName, ~0, &ExtValue, pvUser);
     244            AssertMsgRCReturn(rc, ("Failed to resolve '%s' rc=%Rrc\n", pszName, rc), rc);
     245            SymValue = (Elf_Addr)ExtValue;
     246            AssertMsgReturn((RTUINTPTR)SymValue == ExtValue, ("Symbol value overflowed! '%s'\n", pszName),
     247                            VERR_SYMBOL_VALUE_TOO_BIG);
     248            Log2(("rtldrELF: #%-3d - UNDEF " FMT_ELF_ADDR " '%s'\n", iSym, SymValue, pszName));
     249        }
     250        else
     251        {
     252            AssertReturn(pSym->st_shndx < pModElf->cSyms || pSym->st_shndx == SHN_ABS, ("%#x\n", pSym->st_shndx));
     253#if   ELF_MODE == 64
     254            SymValue = pSym->st_value;
     255#endif
     256        }
     257
     258#if   ELF_MODE == 64
     259        /* Calc the value. */
     260        Elf_Addr Value;
     261        if (pSym->st_shndx < pModElf->cSyms)
     262            Value = SymValue + offDelta;
     263        else
     264            Value = SymValue + paRels[iRel].r_addend;
     265#endif
     266
     267        /*
     268         * Apply the fixup.
     269         */
     270        AssertMsgReturn(paRels[iRel].r_offset < cbSec, (FMT_ELF_ADDR " " FMT_ELF_SIZE "\n", paRels[iRel].r_offset, cbSec), VERR_LDRELF_INVALID_RELOCATION_OFFSET);
     271#if   ELF_MODE == 32
     272        const Elf_Addr *pAddrR = (const Elf_Addr *)(pu8SecBaseR + paRels[iRel].r_offset);    /* Where to read the addend. */
     273#endif
     274        Elf_Addr       *pAddrW =       (Elf_Addr *)(pu8SecBaseW + paRels[iRel].r_offset);    /* Where to write the fixup. */
     275        switch (ELF_R_TYPE(paRels[iRel].r_info))
     276        {
     277#if   ELF_MODE == 32
     278            /*
     279             * Absolute addressing.
     280             */
     281            case R_386_32:
     282            {
     283                Elf_Addr Value;
     284                if (pSym->st_shndx < pModElf->Ehdr.e_shnum)
     285                    Value = *pAddrR + offDelta;         /* Simplified. */
     286                else if (pSym->st_shndx == SHN_ABS)
     287                    continue;                           /* Internal fixup, no need to apply it. */
     288                else if (pSym->st_shndx == SHN_UNDEF)
     289                    Value = SymValue + *pAddrR;
     290                else
     291                    AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */
     292                *(uint32_t *)pAddrW = Value;
     293                Log4((FMT_ELF_ADDR": R_386_32   Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value));
     294                break;
     295            }
     296
     297            /*
     298             * PC relative addressing.
     299             */
     300            case R_386_PC32:
     301            {
     302                Elf_Addr Value;
     303                if (pSym->st_shndx < pModElf->Ehdr.e_shnum)
     304                    continue;                           /* Internal fixup, no need to apply it. */
     305                else if (pSym->st_shndx == SHN_ABS)
     306                    Value = *pAddrR + offDelta;         /* Simplified. */
     307                else if (pSym->st_shndx == SHN_UNDEF)
     308                {
     309                    const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
     310                    Value = SymValue + *(uint32_t *)pAddrR - SourceAddr;
     311                    *(uint32_t *)pAddrW = Value;
     312                }
     313                else
     314                    AssertFailedReturn(VERR_LDR_GENERAL_FAILURE); /** @todo SHN_COMMON */
     315                Log4((FMT_ELF_ADDR": R_386_PC32 Value=" FMT_ELF_ADDR "\n", SecAddr + paRels[iRel].r_offset + BaseAddr, Value));
     316                break;
     317            }
     318
     319#elif ELF_MODE == 64
     320
     321            /*
     322             * Absolute addressing
     323             */
     324            case R_X86_64_64:
     325            {
     326                *(uint64_t *)pAddrW = Value;
     327                Log4((FMT_ELF_ADDR": R_X86_64_64   Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     328                      SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
     329                break;
     330            }
     331
     332            /*
     333             * Truncated 32-bit value (zero-extendedable to the 64-bit value).
     334             */
     335            case R_X86_64_32:
     336            {
     337                *(uint32_t *)pAddrW = (uint32_t)Value;
     338                Log4((FMT_ELF_ADDR": R_X86_64_32   Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     339                      SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
     340                AssertMsgReturn((Elf_Addr)*(uint32_t *)pAddrW == SymValue, ("Value=" FMT_ELF_ADDR "\n", SymValue),
     341                                VERR_SYMBOL_VALUE_TOO_BIG);
     342                break;
     343            }
     344
     345            /*
     346             * Truncated 32-bit value (sign-extendedable to the 64-bit value).
     347             */
     348            case R_X86_64_32S:
     349            {
     350                *(int32_t *)pAddrW = (int32_t)Value;
     351                Log4((FMT_ELF_ADDR": R_X86_64_32S  Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     352                      SecAddr + paRels[iRel].r_offset + BaseAddr, Value, SymValue));
     353                AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
     354                break;
     355            }
     356
     357            /*
     358             * PC relative addressing.
     359             */
     360            case R_X86_64_PC32:
     361            {
     362                const Elf_Addr SourceAddr = SecAddr + paRels[iRel].r_offset + BaseAddr; /* Where the source really is. */
     363                Value -= SourceAddr;
     364                *(int32_t *)pAddrW = (int32_t)Value;
     365                Log4((FMT_ELF_ADDR": R_X86_64_PC32 Value=" FMT_ELF_ADDR " SymValue=" FMT_ELF_ADDR "\n",
     366                      SourceAddr, Value, SymValue));
     367                AssertMsgReturn((Elf_Addr)*(int32_t *)pAddrW == Value, ("Value=" FMT_ELF_ADDR "\n", Value), VERR_SYMBOL_VALUE_TOO_BIG); /** @todo check the sign-extending here. */
     368                break;
     369            }
     370#endif
     371
     372            default:
     373                AssertMsgFailed(("Unknown relocation type: %d (iRel=%d iRelMax=%d)\n",
     374                                 ELF_R_TYPE(paRels[iRel].r_info), iRel, iRelMax));
     375                return VERR_LDRELF_RELOCATION_NOT_SUPPORTED;
     376        }
     377    }
     378
     379    return VINF_SUCCESS;
     380}
     381
     382
     383
     384/*
     385 *
     386 * REL
     387 * REL
     388 * REL
     389 * REL
     390 * REL
     391 *
     392 */
    158393
    159394/**
     
    287522    {
    288523        /*
     524         * Skip R_XXX_NONE entries early to avoid confusion in the symbol
     525         * getter code.
     526         */
     527#if   ELF_MODE == 32
     528        if (ELF_R_TYPE(paRels[iRel].r_info) == R_386_NONE)
     529            continue;
     530#elif ELF_MODE == 64
     531        if (ELF_R_TYPE(paRels[iRel].r_info) == R_X86_64_NONE)
     532            continue;
     533#endif
     534
     535
     536        /*
    289537         * Get the symbol.
    290538         */
     
    476724                Value = paSyms[iSym].st_value;
    477725            else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum)
    478                 /* relative to the section. */
    479                 Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
     726            {
     727                if (pModElf->Ehdr.e_type == ET_REL)
     728                    /* relative to the section. */
     729                    Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
     730                else /* Fixed up for link address. */
     731                    Value = BaseAddr + paSyms[iSym].st_value - pModElf->LinkAddress;
     732            }
    480733            else
    481734            {
     
    646899
    647900        /** @todo Make RelocateSection a function pointer so we can select the one corresponding to the machine when opening the image. */
    648         rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser,
    649                                             pShdr->sh_addr,
    650                                             pShdr->sh_size,
    651                                             (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
    652                                             (uint8_t *)pvBits + pShdr->sh_addr,
    653                                             (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
    654                                             pShdrRel->sh_size);
     901        if (pModElf->Ehdr.e_type == ET_REL)
     902            rc = RTLDRELF_NAME(RelocateSection)(pModElf, BaseAddr, pfnGetImport, pvUser,
     903                                                pShdr->sh_addr,
     904                                                pShdr->sh_size,
     905                                                (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
     906                                                (uint8_t *)pvBits + pShdr->sh_addr,
     907                                                (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
     908                                                pShdrRel->sh_size);
     909        else
     910            rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pModElf, BaseAddr, pfnGetImport, pvUser,
     911                                                       pShdr->sh_addr,
     912                                                       pShdr->sh_size,
     913                                                       (const uint8_t *)pModElf->pvBits + pShdr->sh_offset,
     914                                                       (uint8_t *)pvBits + pShdr->sh_addr,
     915                                                       (const uint8_t *)pModElf->pvBits + pShdrRel->sh_offset,
     916                                                       pShdrRel->sh_size);
    655917        if (RT_FAILURE(rc))
    656918            return rc;
     
    703965                        Value = paSyms[iSym].st_value;
    704966                    else if (paSyms[iSym].st_shndx < pModElf->Ehdr.e_shnum)
    705                         /* relative to the section. */
    706                         Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
     967                    {
     968                        if (pModElf->Ehdr.e_type == ET_REL)
     969                            /* relative to the section. */
     970                            Value = BaseAddr + paSyms[iSym].st_value + pModElf->paShdrs[paSyms[iSym].st_shndx].sh_addr;
     971                        else /* Fixed up for link address. */
     972                            Value = BaseAddr + paSyms[iSym].st_value - pModElf->LinkAddress;
     973                    }
    707974                    else
    708975                    {
     
    9981265{
    9991266    PRTLDRMODELF pThis = (PRTLDRMODELF)pMod;
     1267    LogFlow(("%s: iDbgInfo=%#x off=%RTfoff cb=%#zu\n", __FUNCTION__, iDbgInfo, off, cb));
    10001268
    10011269    /*
     
    10661334         * Apply the relocations.
    10671335         */
    1068         rc = RTLDRELF_NAME(RelocateSection)(pThis, 0 /*BaseAddress*/,
    1069                                             RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
    1070                                             pThis->paShdrs[iDbgInfo].sh_addr,
    1071                                             pThis->paShdrs[iDbgInfo].sh_size,
    1072                                             (const uint8_t *)pvBuf,
    1073                                             (uint8_t *)pvBuf,
    1074                                             pbRelocs,
    1075                                             pThis->paShdrs[iRelocs].sh_size);
     1336        if (pThis->Ehdr.e_type == ET_REL)
     1337            rc = RTLDRELF_NAME(RelocateSection)(pThis, pThis->LinkAddress,
     1338                                                RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
     1339                                                pThis->paShdrs[iDbgInfo].sh_addr,
     1340                                                pThis->paShdrs[iDbgInfo].sh_size,
     1341                                                (const uint8_t *)pvBuf,
     1342                                                (uint8_t *)pvBuf,
     1343                                                pbRelocs,
     1344                                                pThis->paShdrs[iRelocs].sh_size);
     1345        else
     1346            rc = RTLDRELF_NAME(RelocateSectionExecDyn)(pThis, pThis->LinkAddress,
     1347                                                       RTLDRELF_NAME(GetImportStubCallback), NULL /*pvUser*/,
     1348                                                       pThis->paShdrs[iDbgInfo].sh_addr,
     1349                                                       pThis->paShdrs[iDbgInfo].sh_size,
     1350                                                       (const uint8_t *)pvBuf,
     1351                                                       (uint8_t *)pvBuf,
     1352                                                       pbRelocs,
     1353                                                       pThis->paShdrs[iRelocs].sh_size);
     1354
    10761355        RTMemTmpFree(pbRelocsBuf);
    10771356    }
     
    14551734    //pModElf->cbStr          = 0;
    14561735    //pModElf->cbImage        = 0;
     1736    //pModElf->LinkAddress    = 0;
    14571737    //pModElf->pStr           = NULL;
    14581738    //pModElf->cbShStr        = 0;
     
    14941774
    14951775                /*
    1496                  * Validate the section headers, allocate memory for the sections (determine the image size),
    1497                  * and find relevant sections.
     1776                 * Validate the section headers and find relevant sections.
    14981777                 */
    14991778                for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
     
    15021781                    if (RT_FAILURE(rc))
    15031782                        break;
    1504 
    1505                     /* Allocate memory addresses for the section. */
    1506                     if (paShdrs[i].sh_flags & SHF_ALLOC)
    1507                     {
    1508                         paShdrs[i].sh_addr = paShdrs[i].sh_addralign
    1509                             ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
    1510                             : (Elf_Addr)pModElf->cbImage;
    1511                         pModElf->cbImage = (size_t)paShdrs[i].sh_addr + (size_t)paShdrs[i].sh_size;
    1512                         AssertMsgReturn(pModElf->cbImage == paShdrs[i].sh_addr + paShdrs[i].sh_size,
    1513                                         (FMT_ELF_ADDR "\n", paShdrs[i].sh_addr + paShdrs[i].sh_size),
    1514                                         VERR_IMAGE_TOO_BIG);
    1515                         Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
    1516                     }
    15171783
    15181784                    /* We're looking for symbol tables. */
     
    15521818                } /* for each section header */
    15531819
    1554                 Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx\n",
    1555                       pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc, pModElf->cbImage));
     1820                /*
     1821                 * Calculate the image base address if the image isn't relocatable.
     1822                 */
     1823                if (RT_SUCCESS(rc) && pModElf->Ehdr.e_type != ET_REL)
     1824                {
     1825                    pModElf->LinkAddress = ~(Elf_Addr)0;
     1826                    for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
     1827                        if (   (paShdrs[i].sh_flags & SHF_ALLOC)
     1828                            && paShdrs[i].sh_addr < pModElf->LinkAddress)
     1829                            pModElf->LinkAddress = paShdrs[i].sh_addr;
     1830                    if (pModElf->LinkAddress == ~(Elf_Addr)0)
     1831                    {
     1832                        AssertFailed();
     1833                        rc = VERR_LDR_GENERAL_FAILURE;
     1834                    }
     1835                }
     1836
     1837                /*
     1838                 * Perform allocations / RVA calculations, determine the image size.
     1839                 */
     1840                if (RT_SUCCESS(rc))
     1841                    for (unsigned i = 0; i < pModElf->Ehdr.e_shnum; i++)
     1842                        if (paShdrs[i].sh_flags & SHF_ALLOC)
     1843                        {
     1844                            if (pModElf->Ehdr.e_type == ET_REL)
     1845                                paShdrs[i].sh_addr = paShdrs[i].sh_addralign
     1846                                                   ? RT_ALIGN_T(pModElf->cbImage, paShdrs[i].sh_addralign, Elf_Addr)
     1847                                                   : (Elf_Addr)pModElf->cbImage;
     1848                            else
     1849                                paShdrs[i].sh_addr -= pModElf->LinkAddress;
     1850                            Elf_Addr EndAddr = paShdrs[i].sh_addr + paShdrs[i].sh_size;
     1851                            if (pModElf->cbImage < EndAddr)
     1852                            {
     1853                                pModElf->cbImage = (size_t)EndAddr;
     1854                                AssertMsgReturn(pModElf->cbImage == EndAddr, (FMT_ELF_ADDR "\n", EndAddr), VERR_IMAGE_TOO_BIG);
     1855                            }
     1856                            Log2(("RTLdrElf: %s: Assigned " FMT_ELF_ADDR " to section #%d\n", pszLogName, paShdrs[i].sh_addr, i));
     1857                        }
     1858
     1859                Log2(("RTLdrElf: iSymSh=%u cSyms=%u iStrSh=%u cbStr=%u rc=%Rrc cbImage=%#zx LinkAddress=" FMT_ELF_ADDR "\n",
     1860                      pModElf->iSymSh, pModElf->cSyms, pModElf->iStrSh, pModElf->cbStr, rc,
     1861                      pModElf->cbImage, pModElf->LinkAddress));
    15561862                if (RT_SUCCESS(rc))
    15571863                {
Note: See TracChangeset for help on using the changeset viewer.

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette