Ignore:
Timestamp:
Feb 13, 2007, 9:40:28 AM (19 years ago)
Author:
bird
Message:

Implemented generic fixups for 32-bit symbol tables.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModMachO.c

    r2962 r2963  
    6464    /** The RVA of this section. */
    6565    KLDRADDR                RVA;
    66     /** The file offset of this section. 
     66    /** The file offset of this section.
    6767     * This is -1 if the section doesn't have a file backing. */
    6868    off_t                   offFile;
     
    7171    /** The array of fixups. (lazy loaded) */
    7272    macho_relocation_info_t *paFixups;
    73     /** The file offset of the fixups for this section. 
     73    /** The file offset of the fixups for this section.
    7474     * This is -1 if the section doesn't have any fixups. */
    7575    off_t                   offFixups;
     
    7979    uint32_t                iSegment;
    8080    /** Pointer to the Mach-O section structure. */
    81     void                   *pvMachoSection;                                     
     81    void                   *pvMachoSection;
    8282} KLDRMODMACHOSECT, *PKLDRMODMACHOSECT;
    8383
    8484/**
    8585 * Extra per-segment info.
    86  * 
     86 *
    8787 * This is corresponds to a kLdr segment, not a Mach-O segment!
    8888 */
     
    9191    /** The number of sections in the segment. */
    9292    uint32_t                cSections;
    93     /** Pointer to the sections belonging to this segment. 
    94      * The array resides in the big memory chunk allocated for 
     93    /** Pointer to the sections belonging to this segment.
     94     * The array resides in the big memory chunk allocated for
    9595     * the module handle, so it doesn't need freeing. */
    9696    PKLDRMODMACHOSECT       paSections;
     
    167167static int  kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO);
    168168static int  kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, off_t offFixups, uint32_t cFixups, void **pvFixups);
     169static int  kldrModMachOMapVirginBits(PKLDRMODMACHO pModMachO);
    169170
    170171static int  kldrModMachODoQuerySymbol32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, const char *pchStrings,
    171                                            uint32_t cchStrings, KLDRADDR BaseAddress, uint32_t iSymbol, const char *pchSymbol, 
     172                                           uint32_t cchStrings, KLDRADDR BaseAddress, uint32_t iSymbol, const char *pchSymbol,
    172173                                           size_t cchSymbol, PKLDRADDR puValue, uint32_t *pfKind);
    173 static int  kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 
     174static int  kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms,
    174175                                           const char *pchStrings, uint32_t cchStrings, KLDRADDR BaseAddress,
    175176                                           uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser);
    176177static int  kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
    177178static int  kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress);
    178 static int  kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits,
    179                                                off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs,
    180                                                KLDRADDR NewBaseAddress);
     179static int  kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
     180                                                 macho_nlist_32_t *paSyms, uint32_t cSyms, KLDRADDR NewBaseAddress);
    181181
    182182/*static int  kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
     
    297297     */
    298298    cchFilename = kLdrHlpStrLen(kLdrRdrName(pRdr));
    299     cb = KLDR_ALIGN_Z(  KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments]) 
     299    cb = KLDR_ALIGN_Z(  KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments])
    300300                      + sizeof(KLDRMODMACHOSECT) * cSections, 16)
    301301       + KLDR_OFFSETOF(KLDRMOD, aSegments[cSegments])
     
    524524                cSegmentCommands++;
    525525
    526                 /* 
    527                  * convert, validate and parse the sections. 
     526                /*
     527                 * convert, validate and parse the sections.
    528528                 */
    529529                cSectionsLeft = u.pSeg32->nsects;
     
    556556                        case S_REGULAR:
    557557                        case S_CSTRING_LITERALS:
     558                        case S_COALESCED:
    558559                            if (pSect->reserved1 || pSect->reserved2)
    559560                                return KLDR_ERR_MACHO_BAD_SECTION;
     
    570571                        case S_16BYTE_LITERALS:
    571572                        case S_SYMBOL_STUBS:
    572                         case S_COALESCED:
    573573                        case S_MOD_INIT_FUNC_POINTERS:
    574574                        case S_MOD_TERM_FUNC_POINTERS:
     
    583583                                         | S_ATTR_LOC_RELOC | SECTION_TYPE))
    584584                        return KLDR_ERR_MACHO_BAD_SECTION;
    585                     if (!pSect->size)
    586                         return KLDR_ERR_MACHO_BAD_SECTION;
    587585                    if (    pSect->addr - u.pSeg32->vmaddr > u.pSeg32->vmsize
    588586                        ||  pSect->addr - u.pSeg32->vmaddr + pSect->size > u.pSeg32->vmsize)
     
    592590                        ||  (((1 << pSect->align) - 1) & u.pSeg32->vmaddr))
    593591                        return KLDR_ERR_MACHO_BAD_SECTION;
    594                     if (    fFileBits 
     592                    if (    fFileBits
    595593                        &&  (   pSect->offset > cbFile
    596594                             || (uint64_t)pSect->offset + pSect->size > cbFile))
     
    600598                    if (!pSect->nreloc && pSect->reloff)
    601599                        return KLDR_ERR_MACHO_BAD_SECTION;
    602                     if (    pSect->nreloc 
     600                    if (    pSect->nreloc
    603601                        &&  (   pSect->reloff > cbFile
    604602                             || (uint64_t)pSect->reloff + (off_t)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile)
     
    647645
    648646            /*case LC_SEGMENT_64:
    649                  copy 32-bit code 
     647                 copy 32-bit code
    650648                break;
    651649            */
     
    665663                cbSym = pHdr->magic == IMAGE_MACHO32_SIGNATURE
    666664                     || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
    667                       ? sizeof(macho_nlist_32_t) 
     665                      ? sizeof(macho_nlist_32_t)
    668666                      : sizeof(macho_nlist_64_t);
    669667                if (    u.pSymTab->symoff >= cbFile
     
    681679                break;
    682680            }
     681
     682            case LC_DYSYMTAB:
     683                /** @todo deal with this! */
     684                break;
    683685
    684686            case LC_THREAD:
     
    727729            case LC_FVMFILE:
    728730            case LC_PREPAGE:
    729             case LC_DYSYMTAB:
    730731            case LC_LOAD_DYLIB:
    731732            case LC_ID_DYLIB:
     
    820821                pModMachO->LinkAddress = u.pSeg32->vmaddr;
    821822
    822                 /* 
    823                  * convert, validate and parse the sections. 
     823                /*
     824                 * convert, validate and parse the sections.
    824825                 */
    825826                cSectionsLeft = u.pSeg32->nsects;
     
    888889                                    return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */
    889890
    890                                 /* If there are file bits, ensure they are in the current flow. 
     891                                /* If there are file bits, ensure they are in the current flow.
    891892                                   (yes, we are very very careful here, I know.) */
    892                                 if (    pSect->offset 
     893                                if (    pSect->offset
    893894                                    &&  pSeg[-1].cbFile == pSeg[-1].cb)
    894895                                {
     
    899900                                    if (fOk)
    900901                                        pSeg[-1].cbFile = (off_t)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size;
    901                                     else 
     902                                    else
    902903                                    {
    903                                        
     904
    904905                                        pSeg[-1].cbFile = pSeg[-1].offFile = -1;
    905906                                        pModMachO->fMapUsingLoadCommandSections = 1;
     
    947948        pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections;
    948949
    949     /* 
     950    /*
    950951     * Adjust mapping addresses calculating the image size.
    951952     */
     
    10551056     * Refuse segmented requests for now.
    10561057     */
    1057     if (    pfKind 
     1058    if (    pfKind
    10581059        &&  (*pfKind & KLDRSYMKIND_REQ_TYPE_MASK) != KLDRSYMKIND_REQ_FLAT)
    10591060        return KLDR_ERR_TODO;
     
    10691070            if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
    10701071                ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
    1071                 rc = kldrModMachODoQuerySymbol32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 
    1072                                                     pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol, 
     1072                rc = kldrModMachODoQuerySymbol32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
     1073                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol,
    10731074                                                    cchSymbol, puValue, pfKind);
    10741075            else
    10751076                rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */
    1076                 /*rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 
    1077                                                     pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol, 
     1077                /*rc = kldrModMachODoQuerySymbol64Bit(pModMachO, (macho_nlist_64_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
     1078                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, iSymbol, pchSymbol,
    10781079                                                    cchSymbol, puValue, pfKind);*/
    10791080
     
    10901091/**
    10911092 * Lookup a symbol in a 32-bit symbol table.
    1092  * 
     1093 *
    10931094 * @returns See kLdrModQuerySymbol.
    1094  * @param   pModMachO   
     1095 * @param   pModMachO
    10951096 * @param   paSyms      Pointer to the symbol table.
    10961097 * @param   cSyms       Number of symbols in the table.
    10971098 * @param   pchStrings  Pointer to the string table.
    10981099 * @param   cchStrings  Size of the string table.
    1099  * @param   BaseAddress Adjusted base address, see kLdrModQuerySymbol. 
     1100 * @param   BaseAddress Adjusted base address, see kLdrModQuerySymbol.
    11001101 * @param   iSymbol     See kLdrModQuerySymbol.
    11011102 * @param   pchSymbol   See kLdrModQuerySymbol.
     
    11181119        cchStrings -= cchSymbol;
    11191120
    1120         for (iSymbol = 0; iSymbol < cSyms; iSymbol++)
     1121        /* external symbols are usually at the end, so search the other way. */
     1122        for (iSymbol = cSyms - 1; iSymbol != UINT32_MAX; iSymbol--)
    11211123        {
    11221124            const char *psz;
     
    11311133            if (paSyms[iSymbol].n_type & MACHO_N_PEXT) /*??*/
    11321134                continue;
    1133            
     1135
    11341136            /* get name */
    1135             if (!paSyms[iSymbol].n_un.n_strx) 
     1137            if (!paSyms[iSymbol].n_un.n_strx)
    11361138                continue;
    11371139            if ((uint32_t)paSyms[iSymbol].n_un.n_strx >= cchStrings)
     
    11461148            break;
    11471149        }
    1148         if (iSymbol >= cSyms)
     1150        if (iSymbol == UINT32_MAX)
    11491151            return KLDR_ERR_SYMBOL_NOT_FOUND;
    11501152    }
     
    11591161    }
    11601162
    1161     /* 
     1163    /*
    11621164     * Calc the return values.
    11631165     */
    11641166    if (pfKind)
    11651167    {
    1166         if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 
     1168        if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
    11671169            ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
    11681170            *pfKind = KLDRSYMKIND_32BIT | KLDRSYMKIND_NO_TYPE;
     
    11891191                *puValue = RVA + BaseAddress;
    11901192
    1191             if (    pfKind 
     1193            if (    pfKind
    11921194                &&  (pSect->fFlags & (S_ATTR_PURE_INSTRUCTIONS | S_ATTR_SELF_MODIFYING_CODE)))
    11931195                *pfKind = (*pfKind & ~KLDRSYMKIND_TYPE_MASK) | KLDRSYMKIND_CODE;
     
    12381240            if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
    12391241                ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
    1240                 rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 
    1241                                                     pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, 
     1242                rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
     1243                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress,
    12421244                                                    fFlags, pfnCallback, pvUser);
    12431245            else
    12441246                rc = KLDR_ERR_TODO; /** @todo duplicate kldrModMachOQuerySymbol32 for parsing 64-bit symbols when everything is working. */
    1245                 /*rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols, 
     1247                /*rc = kldrModMachODoEnumSymbols32Bit(pModMachO, (macho_nlist_32_t *)pModMachO->pvaSymbols, pModMachO->cSymbols,
    12461248                                                    pModMachO->pchStrings, pModMachO->cchStrings, BaseAddress, pfnCallback, pvUser);*/
    12471249        }
     
    12561258/**
    12571259 * Enum a 32-bit symbol table.
    1258  * 
     1260 *
    12591261 * @returns See kLdrModQuerySymbol.
    1260  * @param   pModMachO   
     1262 * @param   pModMachO
    12611263 * @param   paSyms      Pointer to the symbol table.
    12621264 * @param   cSyms       Number of symbols in the table.
    12631265 * @param   pchStrings  Pointer to the string table.
    12641266 * @param   cchStrings  Size of the string table.
    1265  * @param   BaseAddress Adjusted base address, see kLdrModEnumSymbols. 
     1267 * @param   BaseAddress Adjusted base address, see kLdrModEnumSymbols.
    12661268 * @param   fFlags      See kLdrModEnumSymbols.
    12671269 * @param   pfnCallback See kLdrModEnumSymbols.
    12681270 * @param   pvUser      See kLdrModEnumSymbols.
    12691271 */
    1270 static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms, 
     1272static int kldrModMachODoEnumSymbols32Bit(PKLDRMODMACHO pModMachO, const macho_nlist_32_t *paSyms, uint32_t cSyms,
    12711273                                          const char *pchStrings, uint32_t cchStrings, KLDRADDR BaseAddress,
    12721274                                          uint32_t fFlags, PFNKLDRMODENUMSYMS pfnCallback, void *pvUser)
     
    13011303            if (paSyms[iSym].n_type & MACHO_N_PEXT) /*??*/
    13021304                continue;
    1303             if (!paSyms[iSym].n_un.n_strx) 
     1305            if (!paSyms[iSym].n_un.n_strx)
    13041306                continue;
    13051307        }
    13061308
    1307         /* 
    1308          * Gather symbol info 
     1309        /*
     1310         * Gather symbol info
    13091311         */
    13101312
     
    16791681     * Resolve imports and apply base relocations.
    16801682     */
    1681     rc = kldrModMachORelocateBits(pMod, pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping, pModMachO->LinkAddress, 
     1683    rc = kldrModMachORelocateBits(pMod, pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping, pModMachO->LinkAddress,
    16821684                                  pfnGetImport, pvUser);
    16831685
     
    17201722     * We currently ignore REFERENCE_TYPE.
    17211723     */
    1722     if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE 
     1724    if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
    17231725        ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
    17241726    {
     
    17351737                size_t cchSymbol;
    17361738                uint32_t fKind = KLDRSYMKIND_REQ_FLAT;
    1737                 KLDRADDR Value; 
     1739                KLDRADDR Value;
    17381740
    17391741                /** @todo Implement N_REF_TO_WEAK. */
     
    17831785                size_t cchSymbol;
    17841786                uint32_t fKind = KLDRSYMKIND_REQ_FLAT;
    1785                 KLDRADDR Value; 
     1787                KLDRADDR Value;
    17861788
    17871789                /** @todo Implement N_REF_TO_WEAK. */
     
    18341836    uint32_t iSeg;
    18351837    int rc;
    1836     int (*pfnFixupSection)(PKLDRMODMACHO, uint8_t *, size_t, off_t, const macho_relocation_info_t *, uint32_t, KLDRADDR);
    18371838
    18381839
     
    18471848     * Iterate over the segments and their sections and apply fixups.
    18481849     */
    1849     pfnFixupSection = NULL;
    18501850    for (iSeg = rc = 0; !rc && iSeg < pModMachO->pMod->cSegments; iSeg++)
    18511851    {
     
    18731873             * Apply the fixups.
    18741874             */
    1875             if (!pfnFixupSection)
    1876             {
    1877                 /* determin the function for applying fixups. */
    1878                 if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
    1879                     ||  pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE)
    1880                     pfnFixupSection = kldrModMachOObjFixupSectionGeneric;
    1881                 else
    1882                 {
    1883                     rc = KLDR_ERR_TODO; /* save space for now. */
    1884                     break;
    1885                 }
    1886             }
    1887 
    18881875            pbSectBits = (uint8_t *)pvMapping + (uintptr_t)pSect->RVA;
    1889             rc = pfnFixupSection(pModMachO, pbSectBits, (size_t)pSect->cb, pSect->offFile,
    1890                                  pSect->paFixups, pSect->cFixups, NewBaseAddress);
     1876            if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE) /** @todo this aint right. */
     1877                rc = kldrModMachOFixupSectionGeneric32Bit(pModMachO, pbSectBits, pSect,
     1878                                                          (macho_nlist_32_t *)pModMachO->pvaSymbols,
     1879                                                          pModMachO->cSymbols, NewBaseAddress);
     1880            else
     1881                rc = KLDR_ERR_TODO; /* save space for now. */
    18911882            if (rc)
    18921883                break;
     
    18981889
    18991890
    1900 static int  kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits,
    1901                                                off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs,
    1902                                                KLDRADDR NewBaseAddress)
    1903 {
     1891/**
     1892 * Applies generic fixups to a section in an image of the same endian-ness
     1893 * as the host CPU.
     1894 *
     1895 * @returns 0 on success, non-zero kLdr status code on failure.
     1896 * @param   pModMachO       The Mach-O module interpreter instance.
     1897 * @param   pbSectBits      Pointer to the section bits.
     1898 * @param   pFixupSect      The section being fixed up.
     1899 * @param   NewBaseAddress  The new base image address.
     1900 */
     1901static int  kldrModMachOFixupSectionGeneric32Bit(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, PKLDRMODMACHOSECT pFixupSect,
     1902                                                 macho_nlist_32_t *paSyms, uint32_t cSyms, KLDRADDR NewBaseAddress)
     1903{
     1904    const macho_relocation_info_t *paFixups = pFixupSect->paFixups;
     1905    const uint32_t cFixups = pFixupSect->cFixups;
     1906    size_t cbSectBits = (size_t)pFixupSect->cb;
     1907    const uint8_t *pbSectVirginBits;
     1908    uint32_t iFixup;
     1909    KLDRPU uFixVirgin;
     1910    KLDRPU uFix;
     1911    KLDRADDR SymAddr;
     1912    int rc;
     1913
     1914    /*
     1915     * Find the virgin bits.
     1916     */
     1917    if (pFixupSect->offFile != -1)
     1918    {
     1919        rc = kldrModMachOMapVirginBits(pModMachO);
     1920        if (rc)
     1921            return rc;
     1922        pbSectVirginBits = (const uint8_t *)pModMachO->pvBits + pFixupSect->offFile;
     1923    }
     1924    else
     1925        pbSectVirginBits = NULL;
     1926
     1927    /*
     1928     * Iterate the fixups and apply them.
     1929     */
     1930    for (iFixup = 0; iFixup < cFixups; iFixup++)
     1931    {
     1932        union
     1933        {
     1934            macho_relocation_info_t     r;
     1935            scattered_relocation_info_t s;
     1936        } Fixup;
     1937        Fixup.r = paFixups[iFixup];
     1938
     1939        if (!(Fixup.r.r_address & R_SCATTERED))
     1940        {
     1941            /* sanity */
     1942            if ((uint32_t)Fixup.r.r_address >= cbSectBits)
     1943                return KLDR_ERR_BAD_FIXUP;
     1944
     1945            /* calc fixup addresses. */
     1946            uFix.pv = pbSectBits + Fixup.r.r_address;
     1947            uFixVirgin.pv = pbSectVirginBits ? (uint8_t *)pbSectVirginBits + Fixup.r.r_address : 0;
     1948
     1949            /*
     1950             * Calc the symbol value.
     1951             */
     1952            /* The addend is stored in the code. */
     1953            /** @todo Deal with unaligned accesses on non x86 platforms. */
     1954            switch (Fixup.r.r_length)
     1955            {
     1956                case 0: SymAddr = *uFixVirgin.pi8; break;
     1957                case 1: SymAddr = *uFixVirgin.pi16; break;
     1958                case 2: SymAddr = *uFixVirgin.pi32; break;
     1959                case 3: SymAddr = *uFixVirgin.pi64; break;
     1960            }
     1961
     1962            /* Add symbol / section address. */
     1963            if (Fixup.r.r_extern)
     1964            {
     1965                const macho_nlist_32_t *pSym;
     1966                if (Fixup.r.r_symbolnum >= cSyms)
     1967                    return KLDR_ERR_BAD_FIXUP;
     1968                pSym = &paSyms[Fixup.r.r_symbolnum];
     1969
     1970                if (pSym->n_type & MACHO_N_STAB)
     1971                    return KLDR_ERR_BAD_FIXUP;
     1972
     1973                switch (pSym->n_type & MACHO_N_TYPE)
     1974                {
     1975                    case MACHO_N_SECT:
     1976                    {
     1977                        PKLDRMODMACHOSECT pSymSect;
     1978                        if ((uint32_t)pSym->n_sect - 1 > pModMachO->cSections)
     1979                            return KLDR_ERR_MACHO_BAD_SYMBOL;
     1980                        pSymSect = &pModMachO->paSections[pSym->n_sect - 1];
     1981
     1982                        SymAddr += pSym->n_value - pModMachO->LinkAddress + pSymSect->RVA;
     1983                        break;
     1984                    }
     1985
     1986                    case MACHO_N_UNDF:
     1987                    case MACHO_N_ABS:
     1988                        SymAddr += pSym->n_value;
     1989                        break;
     1990
     1991                    case MACHO_N_INDR:
     1992                    case MACHO_N_PBUD:
     1993                        return KLDR_ERR_TODO;
     1994                    default:
     1995                        return KLDR_ERR_MACHO_BAD_SYMBOL;
     1996                }
     1997            }
     1998            else if (Fixup.r.r_symbolnum != R_ABS)
     1999            {
     2000                PKLDRMODMACHOSECT pSymSect;
     2001                if (Fixup.r.r_symbolnum > pModMachO->cSections)
     2002                    return KLDR_ERR_BAD_FIXUP;
     2003                pSymSect = &pModMachO->paSections[Fixup.r.r_symbolnum - 1];
     2004                SymAddr += NewBaseAddress + pSymSect->RVA;
     2005            }
     2006
     2007            /* adjust for PC relative */
     2008            if (Fixup.r.r_pcrel)
     2009                SymAddr -= Fixup.r.r_address + pFixupSect->RVA + NewBaseAddress;
     2010        }
     2011        else
     2012        {
     2013            PKLDRMODMACHOSECT pSymSect;
     2014            uint32_t iSymSect;
     2015            KLDRADDR Value;
     2016
     2017            /* sanity */
     2018            KLDRMODMACHO_ASSERT(Fixup.s.r_scattered);
     2019            if ((uint32_t)Fixup.s.r_address >= cbSectBits)
     2020                return KLDR_ERR_BAD_FIXUP;
     2021
     2022            /* calc fixup addresses. */
     2023            uFix.pv = pbSectBits + Fixup.s.r_address;
     2024            uFixVirgin.pv = pbSectVirginBits ? (uint8_t *)pbSectVirginBits + Fixup.s.r_address : 0;
     2025
     2026            /*
     2027             * Calc the symbol value.
     2028             */
     2029            /* The addend is stored in the code. */
     2030            switch (Fixup.s.r_length)
     2031            {
     2032                case 0: SymAddr = *uFixVirgin.pi8; break;
     2033                case 1: SymAddr = *uFixVirgin.pi16; break;
     2034                case 2: SymAddr = *uFixVirgin.pi32; break;
     2035                case 3: SymAddr = *uFixVirgin.pi64; break;
     2036            }
     2037
     2038            /* Calc the section number from the r_value and adjust the value. */
     2039            pSymSect = NULL;
     2040            Value = Fixup.s.r_value - pModMachO->LinkAddress;
     2041            for (iSymSect = 0; iSymSect < pModMachO->cSections; iSymSect++)
     2042            {
     2043                KLDRADDR off = Value - pModMachO->paSections[iSymSect].RVA;
     2044                if (off < pModMachO->paSections[iSymSect].cb)
     2045                {
     2046                    pSymSect = &pModMachO->paSections[iSymSect];
     2047                    break;
     2048                }
     2049                else if (off == pModMachO->paSections[iSymSect].cb) /* edge case */
     2050                    pSymSect = &pModMachO->paSections[iSymSect];
     2051            }
     2052            if (!pSymSect)
     2053                return KLDR_ERR_BAD_FIXUP;
     2054
     2055            /** @todo this looking up of the r_value section isn't strictly required unless we're going to remove sections from the link. */
     2056            SymAddr += NewBaseAddress + pSymSect->RVA + (Value - pSymSect->RVA);
     2057
     2058            /* adjust for PC relative */
     2059            if (Fixup.s.r_pcrel)
     2060                SymAddr -= Fixup.s.r_address + pFixupSect->RVA + NewBaseAddress;
     2061
     2062            Fixup.r.r_length = ((scattered_relocation_info_t *)&paFixups[iFixup])->r_length;
     2063            Fixup.r.r_type   = ((scattered_relocation_info_t *)&paFixups[iFixup])->r_type;
     2064        }
     2065
     2066        /*
     2067         * Write back the fixed up value.
     2068         */
     2069        if (Fixup.r.r_type == GENERIC_RELOC_VANILLA)
     2070        {
     2071            switch (Fixup.r.r_length)
     2072            {
     2073                case 0: *uFix.pu8  = (uint8_t)SymAddr; break;
     2074                case 1: *uFix.pu16 = (uint16_t)SymAddr; break;
     2075                case 2: *uFix.pu32 = (uint32_t)SymAddr; break;
     2076                case 3: *uFix.pu64 = (uint64_t)SymAddr; break;
     2077            }
     2078        }
     2079        else if (Fixup.r.r_type <= GENERIC_RELOC_LOCAL_SECTDIFF)
     2080            return KLDR_ERR_TODO;
     2081        else
     2082            return KLDR_ERR_BAD_FIXUP;
     2083    }
    19042084
    19052085    return 0;
     
    19092089/**
    19102090 * Loads the symbol table for a MH_OBJECT file.
    1911  * 
     2091 *
    19122092 * The symbol table is pointed to by KLDRMODMACHO::pvaSymbols.
    1913  * 
     2093 *
    19142094 * @returns 0 on success, non-zero kLdr status code on failure.
    1915  * @param   pModMachO       The Mach-O module interpret instance.
     2095 * @param   pModMachO       The Mach-O module interpreter instance.
    19162096 */
    19172097static int  kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO)
     
    19192099    int rc = 0;
    19202100
    1921     if (    !pModMachO->pvaSymbols 
     2101    if (    !pModMachO->pvaSymbols
    19222102        &&  pModMachO->cSymbols)
    19232103    {
     
    19582138                    pModMachO->pvaSymbols = pvSyms;
    19592139                    pModMachO->pchStrings = (char *)pvStrings;
    1960    
     2140
    19612141                    /* perform endian conversion? */
    19622142                    if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
     
    19712151                            pSym++;
    19722152                        }
    1973                     } 
     2153                    }
    19742154                    else if (pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE)
    19752155                    {
     
    20002180
    20012181/**
    2002  * Loads the fixups at the given address and performs endian 
     2182 * Loads the fixups at the given address and performs endian
    20032183 * conversion if necessary.
    2004  * 
     2184 *
    20052185 * @returns 0 on success, non-zero kLdr status code on failure.
    2006  * @param   pModMachO       The Mach-O module interpret instance.
     2186 * @param   pModMachO       The Mach-O module interpreter instance.
    20072187 * @param   offFixups       The file offset of the fixups.
    20082188 * @param   cFixups         The number of fixups to load.
     
    20302210
    20312211        /* do endian conversion if necessary. */
    2032         if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE 
     2212        if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
    20332213            ||  pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE)
    20342214        {
     
    20442224    else
    20452225        kldrHlpFree(paFixups);
     2226    return rc;
     2227}
     2228
     2229
     2230/**
     2231 * Maps the virgin file bits into memory if not already done.
     2232 *
     2233 * @returns 0 on success, non-zero kLdr status code on failure.
     2234 * @param   pModMachO       The Mach-O module interpreter instance.
     2235 */
     2236static int kldrModMachOMapVirginBits(PKLDRMODMACHO pModMachO)
     2237{
     2238    int rc = 0;
     2239    if (!pModMachO->pvBits)
     2240        rc = kLdrRdrAllMap(pModMachO->pMod->pRdr, &pModMachO->pvBits);
    20462241    return rc;
    20472242}
Note: See TracChangeset for help on using the changeset viewer.