Changeset 2961 for trunk


Ignore:
Timestamp:
Feb 11, 2007, 4:15:35 PM (19 years ago)
Author:
bird
Message:

Some more work in the GetBits and Relocate area.

Location:
trunk/kLdr
Files:
3 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdr.h

    r2958 r2961  
    5050   typedef int64_t              intmax_t;
    5151   typedef uint64_t             uintmax_t;
    52 #  define UINT16_C(c)           (c ## U)
     52#  define UINT8_C(c)            (c)
     53#  define UINT16_C(c)           (c)
    5354#  define UINT32_C(c)           (c ## U)
    5455#  define UINT64_C(c)           (c ## ULL)
     56#  define INT8_C(c)             (c)
    5557#  define INT16_C(c)            (c)
    5658#  define INT32_C(c)            (c)
     
    11901192/** Couldn't fit the address value into the field. Typically a relocation kind of error. */
    11911193#define KLDR_ERR_ADDRESS_OVERFLOW                           (KLDR_ERR_BASE + 56)
     1194/** Couldn't fit a calculated size value into the native size type of the host. */
     1195#define KLDR_ERR_SIZE_OVERFLOW                              (KLDR_ERR_BASE + 57)
    11921196/** Thread attach failed. */
    1193 #define KLDR_ERR_THREAD_ATTACH_FAILED                       (KLDR_ERR_BASE + 57)
     1197#define KLDR_ERR_THREAD_ATTACH_FAILED                       (KLDR_ERR_BASE + 58)
    11941198/** The file reader can't take more concurrent mappings. */
    1195 #define KLDR_ERR_TOO_MANY_MAPPINGS                          (KLDR_ERR_BASE + 58)
     1199#define KLDR_ERR_TOO_MANY_MAPPINGS                          (KLDR_ERR_BASE + 59)
    11961200/** The module wasn't a DLL or object file. */
    1197 #define KLDR_ERR_NOT_DLL                                    (KLDR_ERR_BASE + 59)
     1201#define KLDR_ERR_NOT_DLL                                    (KLDR_ERR_BASE + 60)
    11981202/** The module wasn't an EXE. */
    1199 #define KLDR_ERR_NOT_EXE                                    (KLDR_ERR_BASE + 60)
     1203#define KLDR_ERR_NOT_EXE                                    (KLDR_ERR_BASE + 61)
    12001204/** Not implemented yet. */
    1201 #define KLDR_ERR_TODO                                       (KLDR_ERR_BASE + 61)
     1205#define KLDR_ERR_TODO                                       (KLDR_ERR_BASE + 62)
    12021206
    12031207
    12041208/** @name kLdrModPE status codes
    12051209 * @{ */
    1206 #define KLDR_ERR_PE_BASE                                    (KLDR_ERR_BASE + 62)
     1210#define KLDR_ERR_PE_BASE                                    (KLDR_ERR_BASE + 63)
    12071211/** The machine isn't supported by the interpreter. */
    12081212#define KLDR_ERR_PE_UNSUPPORTED_MACHINE                     (KLDR_ERR_PE_BASE + 0)
     
    12811285/** The image is 32-bit and contains 64-bit load commands or vise versa. */
    12821286#define KLDR_ERR_MACHO_BIT_MIX                              (KLDR_ERR_MACHO_BASE + 12)
    1283 /** The bad MH_OBJECT file. */
     1287/** Bad MH_OBJECT file. */
    12841288#define KLDR_ERR_MACHO_BAD_OBJECT_FILE                      (KLDR_ERR_MACHO_BASE + 13)
     1289/** Bad symbol table entry. */
     1290#define KLDR_ERR_MACHO_BAD_SYMBOL                           (KLDR_ERR_MACHO_BASE + 14)
    12851291/** @} */
    12861292
    12871293/** End of the valid kLdr status codes. */
    1288 #define KLDR_ERR_END                                        (KLDR_ERR_MACHO_BASE + 14)
     1294#define KLDR_ERR_END                                        (KLDR_ERR_MACHO_BASE + 15)
    12891295
    12901296const char *kLdrErrStr(int rc);
  • trunk/kLdr/kLdrModMachO.c

    r2956 r2961  
    3434#include "kLdrModMachO.h"
    3535
    36 /* quick hack for now. */
    37 typedef struct nlist
    38 {
    39     uint32_t    n_strx;
    40     uint8_t     n_type;
    41     int8_t      n_other;
    42     int16_t     n_desc;
    43     uint32_t    n_value;
    44 } nlist_t;
    45 
    4636
    4737/*******************************************************************************
     
    6151#endif
    6252
    63 /** @def KLDRMODMACHO_RVA2TYPE
    64  * Converts a RVA to a pointer of the specified type.
    65  * @param   pvBits      The bits (image base).
    66  * @param   uRVA        The image relative virtual address.
    67  * @param   type        The type to cast to.
    68  */
    69 #define KLDRMODMACHO_RVA2TYPE(pvBits, uRVA, type) \
    70         ( (type) ((uintptr_t)(pvBits) + (uintptr_t)(uRVA)) )
    71 
    72 /** @def KLDRMODMACHO_VALID_RVA
    73  * Checks that the specified RVA value is non-zero and within the bounds of the image.
    74  * @returns true/false.
    75  * @param   pModPE      The PE module interpreter instance.
    76  * @param   uRVA        The RVA to validate.
    77  */
    78 #define KLDRMODMACHO_VALID_RVA(pModPE, uRVA) \
    79         ( (uRVA) && (uRVA) < (pModPE)->Hdrs.OptionalHeader.SizeOfImage )
    80 
    81 
    8253
    8354/*******************************************************************************
    8455*   Structures and Typedefs                                                    *
    8556*******************************************************************************/
     57/**
     58 * Mach-O section details.
     59 */
     60typedef struct KLDRMODMACHOSECT
     61{
     62    /** The size of the section (in bytes). */
     63    KLDRSIZE                cb;
     64    /** The RVA of this section. */
     65    KLDRADDR                RVA;
     66    /** The file offset of this section.
     67     * This is -1 if the section doesn't have a file backing. */
     68    off_t                   offFile;
     69    /** The number of fixups. */
     70    uint32_t                cFixups;
     71    /** The array of fixups. (lazy loaded) */
     72    macho_relocation_info_t *paFixups;
     73    /** The file offset of the fixups for this section.
     74     * This is -1 if the section doesn't have any fixups. */
     75    off_t                   offFixups;
     76    /** Pointer to the Mach-O section structure. */
     77    void                   *pvMachoSection;
     78                                     
     79} KLDRMODMACHOSECT, *PKLDRMODMACHOSECT;
     80
     81/**
     82 * Extra per-segment info.
     83 *
     84 * This is corresponds to a kLdr segment, not a Mach-O segment!
     85 */
     86typedef struct KLDRMODMACHOSEG
     87{
     88    /** The number of sections in the segment. */
     89    uint32_t                cSections;
     90    /** Pointer to the sections belonging to this segment.
     91     * The array resides in the big memory chunk allocated for
     92     * the module handle, so it doesn't need freeing. */
     93    PKLDRMODMACHOSECT       paSections;
     94
     95} KLDRMODMACHOSEG, *PKLDRMODMACHOSEG;
     96
    8697/**
    8798 * Instance data for the Mach-O MH_OBJECT module interpreter.
     
    116127    uint32_t                cSymbols;
    117128    /** The pointer to the loaded symbol table. */
    118     void                   *paSymbols;
     129    void                   *pvaSymbols;
    119130    /** The offset of the string table. */
    120131    off_t                   offStrings;
     
    122133    uint32_t                cbStrings;
    123134    /** Pointer to the loaded string table. */
    124     char                   *pbStrings;
     135    char                   *pchStrings;
     136    /** Array of segments parallel to the one in KLDRMOD. */
     137    KLDRMODMACHOSEG         aSegments[1];
    125138} KLDRMODMACHO, *PKLDRMODMACHO;
     139
    126140
    127141
     
    137151static int  kldrModMachODoCreate(PKLDRRDR pRdr, PKLDRMODMACHO *ppMod);
    138152static int  kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, PKLDRRDR pRdr,
    139                                              uint32_t *pcSegments, uint32_t *pcbStringPool);
     153                                             uint32_t *pcSegments, uint32_t *pcSections, uint32_t *pcbStringPool);
    140154static int  kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool);
     155/*static int  kldrModMachOLoadLoadCommands(PKLDRMODMACHO pModMachO);*/
    141156static int  kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO);
    142 static int  kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
    143 static int  kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     157static int  kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, off_t offFixups, uint32_t cFixups, void **pvFixups);
     158
     159static int  kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);
     160static int  kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress);
     161static int  kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits,
     162                                               off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs,
     163                                               KLDRADDR NewBaseAddress);
     164
     165/*static int  kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress);
     166static int  kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser);*/
    144167
    145168
     
    195218    uint8_t *pbLoadCommands;
    196219    uint32_t cSegments;
     220    uint32_t cSections;
    197221    uint32_t cbStringPool;
    198222    size_t cchFilename;
     
    244268                     ? sizeof(mach_header_32_t) : sizeof(mach_header_64_t));
    245269    if (!rc)
    246         rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, &cSegments, &cbStringPool);
     270        rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, &cSegments, &cSections, &cbStringPool);
    247271    if (rc)
    248272    {
     
    256280     */
    257281    cchFilename = kLdrHlpStrLen(kLdrRdrName(pRdr));
    258     cb = KLDR_ALIGN_Z(sizeof(KLDRMODMACHO), 16)
     282    cb = KLDR_ALIGN_Z(  KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments])
     283                      + sizeof(KLDRMODMACHOSECT) * cSections, 16)
    259284       + KLDR_OFFSETOF(KLDRMOD, aSegments[cSegments])
    260285       + cchFilename + 1
     
    267292
    268293    /* KLDRMOD */
    269     pMod = (PKLDRMOD)((uint8_t *)pModMachO + KLDR_ALIGN_Z(sizeof(KLDRMODMACHO), 16));
     294    pMod = (PKLDRMOD)((uint8_t *)pModMachO + KLDR_ALIGN_Z(  KLDR_OFFSETOF(KLDRMODMACHO, aSegments[cSegments])
     295                                                          + sizeof(KLDRMODMACHOSECT) * cSections, 16));
    270296    pMod->pvData = pModMachO;
    271297    pMod->pRdr = pRdr;
     
    348374    pModMachO->offSymbols = 0;
    349375    pModMachO->cSymbols = 0;
    350     pModMachO->paSymbols = NULL;
     376    pModMachO->pvaSymbols = NULL;
    351377    pModMachO->offStrings = 0;
    352378    pModMachO->cbStrings = 0;
    353     pModMachO->pbStrings = NULL;
     379    pModMachO->pchStrings = NULL;
    354380
    355381    /*
     
    372398 *
    373399 * The conversion that's preformed is format endian to host endian.
    374  * The preparsing has to do with segment counting and string pool sizing.
     400 * The preparsing has to do with segment counting, section counting and string pool sizing.
    375401 *
    376402 * @returns 0 on success.
     
    380406 * @param   pRdr            The file reader.
    381407 * @param   pcSegments      Where to store the segment count.
     408 * @param   pcSegments      Where to store the section count.
    382409 * @param   pcbStringPool   Where to store the string pool size.
    383410 */
    384411static int  kldrModMachOPreParseLoadCommands(uint8_t *pbLoadCommands, const mach_header_32_t *pHdr, PKLDRRDR pRdr,
    385                                              uint32_t *pcSegments, uint32_t *pcbStringPool)
     412                                             uint32_t *pcSegments, uint32_t *pcSections, uint32_t *pcbStringPool)
    386413{
    387414    union
     
    397424    const uint64_t cbFile = kLdrRdrSize(pRdr);
    398425    uint32_t cSegments = 0;
     426    uint32_t cSections = 0;
    399427    uint32_t cbStringPool = 0;
    400428    uint32_t cLeft = pHdr->ncmds;
     
    407435
    408436    *pcSegments = 0;
     437    *pcSections = 0;
    409438    *pcbStringPool = 0;
    410439
     
    554583                    if (    pSect->nreloc
    555584                        &&  (   pSect->reloff > cbFile
    556                              || (uint64_t)pSect->reloff + (off_t)pSect->nreloc * sizeof(nlist_t)) > cbFile)
     585                             || (uint64_t)pSect->reloff + (off_t)pSect->nreloc * sizeof(macho_relocation_info_t)) > cbFile)
    557586                        return KLDR_ERR_MACHO_BAD_SECTION;
    558587
     
    584613                                cbStringPool += kLdrHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1;
    585614                            }
     615                            cSections++;
    586616                            break;
    587617                        }
     
    603633
    604634            case LC_SYMTAB:
     635            {
     636                size_t cbSym;
    605637                if (fConvertEndian)
    606638                {
     
    612644
    613645                /* verify */
     646                cbSym = pHdr->magic == IMAGE_MACHO32_SIGNATURE
     647                     || pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
     648                      ? sizeof(macho_nlist_32_t)
     649                      : sizeof(macho_nlist_64_t);
    614650                if (    u.pSymTab->symoff >= cbFile
    615                     ||  (uint64_t)u.pSymTab->symoff + u.pSymTab->nsyms * sizeof(nlist_t) > kLdrRdrSize(pRdr))
     651                    ||  (uint64_t)u.pSymTab->symoff + u.pSymTab->nsyms * cbSym > kLdrRdrSize(pRdr))
    616652                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
    617653                if (    u.pSymTab->stroff >= cbFile
     
    625661                    return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
    626662                break;
     663            }
    627664
    628665            case LC_THREAD:
     
    707744
    708745    *pcSegments = cSegments;
     746    *pcSections = cSections;
    709747    *pcbStringPool = cbStringPool;
    710748
     
    739777    int fFirstSegment = 1;
    740778    PKLDRSEG pSeg = &pModMachO->pMod->aSegments[0];
     779    PKLDRMODMACHOSEG pSegExtra = &pModMachO->aSegments[0];
     780    PKLDRMODMACHOSECT pSectExtra = (PKLDRMODMACHOSECT)&pModMachO->aSegments[pModMachO->pMod->cSegments];
    741781    const uint32_t cSegments = pModMachO->pMod->cSegments;
    742782    uint32_t i;
     
    779819                                ||  kLdrHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
    780820                            {
     821                                /* close the previous segment */
     822                                if (pSegExtra != &pModMachO->aSegments[1])
     823                                    pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections;
     824
    781825                                /* new segment. */
    782826                                pSeg->pvUser = NULL;
     
    799843                                pSeg->MapAddress = 0;
    800844
     845                                pSegExtra->cSections = 0;
     846                                pSegExtra->paSections = pSectExtra;
     847
    801848                                pSeg++;
     849                                pSegExtra++;
    802850                                fFirstSegment = 0;
    803851                            }
    804                             else if (!fFirstSegment)
     852                            else
    805853                            {
    806854                                /* update exiting segment */
     
    832880                                /** @todo update the protection... */
    833881                            }
     882
     883                            /* Section info. */
     884                            pSectExtra->cb = pSect->size;
     885                            pSectExtra->RVA = pSect->addr;
     886                            pSectExtra->offFile = pSect->offset ? pSect->offset : -1;
     887                            pSectExtra->cFixups = pSect->nreloc;
     888                            pSectExtra->paFixups = NULL;
     889                            pSectExtra->offFixups = pSect->nreloc ? pSect->reloff : -1;
     890                            pSectExtra->pvMachoSection = pSect;
     891                            pSectExtra++;
    834892                            break;
    835893                        }
     
    862920    } /* while more commands */
    863921
     922    /*
     923     * Close the last segment (if any).
     924     */
     925    if (pSegExtra != &pModMachO->aSegments[1])
     926        pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections;
     927
    864928    /*
    865929     * Adjust mapping addresses calculating the image size.
     
    897961    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
    898962    int rc = 0;
     963    uint32_t i, j;
    899964    KLDRMODMACHO_ASSERT(!pModMachO->pvMapping);
     965
     966    i = pMod->cSegments;
     967    while (i-- > 0)
     968    {
     969        j = pModMachO->aSegments[i].cSections;
     970        while (j-- > 0)
     971        {
     972            kldrHlpFree(pModMachO->aSegments[i].paSections[j].paFixups);
     973            pModMachO->aSegments[i].paSections[j].paFixups = NULL;
     974        }
     975    }
    900976
    901977    if (pMod->pRdr)
     
    908984    kldrHlpFree(pModMachO->pbLoadCommands);
    909985    pModMachO->pbLoadCommands = NULL;
    910     kldrHlpFree(pModMachO->pbStrings);
    911     pModMachO->pbStrings = NULL;
    912     kldrHlpFree(pModMachO->paSymbols);
    913     pModMachO->paSymbols = NULL;
     986    kldrHlpFree(pModMachO->pchStrings);
     987    pModMachO->pchStrings = NULL;
     988    kldrHlpFree(pModMachO->pvaSymbols);
     989    pModMachO->pvaSymbols = NULL;
    914990    kldrHlpFree(pModMachO);
    915991    return rc;
     
    15311607     */
    15321608    rc = kldrModMachODoFixups(pModMachO, (void *)pModMachO->pvMapping, (uintptr_t)pModMachO->pvMapping,
    1533                            pModMachO->Hdrs.OptionalHeader.ImageBase);
     1609                              pModMachO->Hdrs.OptionalHeader.ImageBase);
    15341610
    15351611    /*
     
    15511627
    15521628/**
    1553  * Applies base relocations to a (unprotected) image mapping.
     1629 * MH_OBJECT: Resolves undefined symbols (imports).
    15541630 *
    15551631 * @returns 0 on success, non-zero kLdr status code on failure.
    1556  * @param   pModMachO          The PE module interpreter instance.
     1632 * @param   pModMachO       The Mach-O module interpreter instance.
     1633 * @param   pfnGetImport    The callback for resolving an imported symbol.
     1634 * @param   pvUser          User argument to the callback.
     1635 */
     1636static int  kldrModMachOObjDoImports(PKLDRMODMACHO pModMachO, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
     1637{
     1638    const uint32_t cSyms = pModMachO->cSymbols;
     1639    uint32_t iSym;
     1640    int rc;
     1641
     1642    /*
     1643     * Ensure that we've got the symbol table and section fixups handy.
     1644     */
     1645    rc = kldrModMachOLoadObjSymTab(pModMachO);
     1646    if (rc)
     1647        return rc;
     1648
     1649    /*
     1650     * Iterate the symbol table and resolve undefined symbols.
     1651     * We currently ignore REFERENCE_TYPE.
     1652     */
     1653    if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
     1654        ||  pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
     1655    {
     1656        macho_nlist_32_t *paSyms = (macho_nlist_32_t *)pModMachO->pvaSymbols;
     1657        for (iSym = 0; iSym < cSyms; iSym++)
     1658        {
     1659            /* skip stabs */
     1660            if (paSyms[iSym].n_type & MACHO_N_STAB)
     1661                continue;
     1662
     1663            if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
     1664            {
     1665                const char *pszSymbol;
     1666                size_t cchSymbol;
     1667                uint32_t fKind = KLDRSYMKIND_REQ_FLAT;
     1668                KLDRADDR Value;
     1669
     1670                /** @todo Implement N_REF_TO_WEAK. */
     1671                if (paSyms[iSym].n_desc & N_REF_TO_WEAK)
     1672                    return KLDR_ERR_TODO;
     1673
     1674                /* Get the symbol name and try resolve it. */
     1675                if ((uint32_t)paSyms[iSym].n_un.n_strx >= pModMachO->cbStrings)
     1676                    return KLDR_ERR_MACHO_BAD_SYMBOL;
     1677                pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx];
     1678                cchSymbol = kLdrHlpStrLen(pszSymbol);
     1679                rc = pfnGetImport(pModMachO->pMod, NIL_KLDRMOD_IMPORT, iSym, pszSymbol, cchSymbol, NULL,
     1680                                  &Value, &fKind, pvUser);
     1681                if (rc)
     1682                {
     1683                    /* weak reference? */
     1684                    if (!(paSyms[iSym].n_desc & N_WEAK_REF))
     1685                        break;
     1686                    Value = 0;
     1687                }
     1688
     1689                /* Update the symbol. */
     1690                paSyms[iSym].n_value = (uint32_t)Value;
     1691                if (paSyms[iSym].n_value != Value)
     1692                {
     1693                    rc = KLDR_ERR_ADDRESS_OVERFLOW;
     1694                    break;
     1695                }
     1696            }
     1697            else if (paSyms[iSym].n_desc & N_WEAK_DEF)
     1698                return KLDR_ERR_TODO; /** @todo implement weak symbols. */
     1699        }
     1700    }
     1701    else
     1702    {
     1703        /* (Identical to the 32-bit code, just different paSym type. (and n_strx is unsigned)) */
     1704        macho_nlist_64_t *paSyms = (macho_nlist_64_t *)pModMachO->pvaSymbols;
     1705        for (iSym = 0; iSym < cSyms; iSym++)
     1706        {
     1707            /* skip stabs */
     1708            if (paSyms[iSym].n_type & MACHO_N_STAB)
     1709                continue;
     1710
     1711            if ((paSyms[iSym].n_type & MACHO_N_TYPE) == MACHO_N_UNDF)
     1712            {
     1713                const char *pszSymbol;
     1714                size_t cchSymbol;
     1715                uint32_t fKind = KLDRSYMKIND_REQ_FLAT;
     1716                KLDRADDR Value;
     1717
     1718                /** @todo Implement N_REF_TO_WEAK. */
     1719                if (paSyms[iSym].n_desc & N_REF_TO_WEAK)
     1720                    return KLDR_ERR_TODO;
     1721
     1722                /* Get the symbol name and try resolve it. */
     1723                if (paSyms[iSym].n_un.n_strx >= pModMachO->cbStrings)
     1724                    return KLDR_ERR_MACHO_BAD_SYMBOL;
     1725                pszSymbol = &pModMachO->pchStrings[paSyms[iSym].n_un.n_strx];
     1726                cchSymbol = kLdrHlpStrLen(pszSymbol);
     1727                rc = pfnGetImport(pModMachO->pMod, NIL_KLDRMOD_IMPORT, iSym, pszSymbol, cchSymbol, NULL,
     1728                                  &Value, &fKind, pvUser);
     1729                if (rc)
     1730                {
     1731                    /* weak reference? */
     1732                    if (!(paSyms[iSym].n_desc & N_WEAK_REF))
     1733                        break;
     1734                    Value = 0;
     1735                }
     1736
     1737                /* Update the symbol. */
     1738                paSyms[iSym].n_value = Value;
     1739                if (paSyms[iSym].n_value != Value)
     1740                {
     1741                    rc = KLDR_ERR_ADDRESS_OVERFLOW;
     1742                    break;
     1743                }
     1744            }
     1745            else if (paSyms[iSym].n_desc & N_WEAK_DEF)
     1746                return KLDR_ERR_TODO; /** @todo implement weak symbols. */
     1747        }
     1748    }
     1749
     1750    return rc;
     1751}
     1752
     1753
     1754/**
     1755 * MH_OBJECT: Applies base relocations to a (unprotected) image mapping.
     1756 *
     1757 * @returns 0 on success, non-zero kLdr status code on failure.
     1758 * @param   pModMachO       The Mach-O module interpreter instance.
    15571759 * @param   pvMapping       The mapping to fixup.
    15581760 * @param   NewBaseAddress  The address to fixup the mapping to.
    15591761 * @param   OldBaseAddress  The address the mapping is currently fixed up to.
    15601762 */
    1561 static int  kldrModMachODoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress, KLDRADDR OldBaseAddress)
    1562 {
    1563 #if 0
    1564     const KLDRADDR                  Delta = NewBaseAddress - OldBaseAddress;
    1565     uint32_t                        cbLeft = pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].Size;
    1566     const IMAGE_BASE_RELOCATION    *pBR, *pFirstBR;
    1567 
    1568     /*
    1569      * Don't don anything if the delta is 0 or there aren't any relocations.
    1570      */
    1571     if (    !Delta
    1572         ||  !cbLeft
    1573         ||  !pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress)
    1574         return 0;
    1575 
    1576     /*
    1577      * Process the fixups block by block.
    1578      * (These blocks appears to be 4KB on all archs despite the native page size.)
    1579      */
    1580     pBR = pFirstBR = KLDRMODMACHO_RVA2TYPE(pvMapping,
    1581                                         pModMachO->Hdrs.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_BASERELOC].VirtualAddress,
    1582                                         const IMAGE_BASE_RELOCATION *);
    1583     while (     cbLeft > sizeof(IMAGE_BASE_RELOCATION)
    1584            &&   pBR->SizeOfBlock >= sizeof(IMAGE_BASE_RELOCATION) /* paranoia */)
    1585     {
    1586         union
     1763static int  kldrModMachOObjDoFixups(PKLDRMODMACHO pModMachO, void *pvMapping, KLDRADDR NewBaseAddress)
     1764{
     1765    uint32_t iSeg;
     1766    int rc;
     1767    int (*pfnFixupSection)(PKLDRMODMACHO, uint8_t *, size_t, off_t, const macho_relocation_info_t *, uint32_t, KLDRADDR);
     1768
     1769
     1770    /*
     1771     * Ensure that we've got the symbol table and section fixups handy.
     1772     */
     1773    rc = kldrModMachOLoadObjSymTab(pModMachO);
     1774    if (rc)
     1775        return rc;
     1776
     1777    /*
     1778     * Iterate over the segments and their sections and apply fixups.
     1779     */
     1780    pfnFixupSection = NULL;
     1781    for (iSeg = rc = 0; !rc && iSeg < pModMachO->pMod->cSegments; iSeg++)
     1782    {
     1783        PKLDRMODMACHOSEG pSeg = &pModMachO->aSegments[iSeg];
     1784        uint32_t iSect;
     1785
     1786        for (iSect = 0; iSect < pSeg->cSections; iSect++)
    15871787        {
    1588             uint8_t    *pu8;
    1589             uint16_t   *pu16;
    1590             uint32_t   *pu32;
    1591             uint64_t   *pu64;
    1592         }               uChunk,
    1593                         u;
    1594         const uint16_t *poffFixup = (const uint16_t *)(pBR + 1);
    1595         const uint32_t  cbBlock = KLDR_MIN(cbLeft, pBR->SizeOfBlock) - sizeof(IMAGE_BASE_RELOCATION); /* more caution... */
    1596         uint32_t        cFixups = cbBlock / sizeof(poffFixup[0]);
    1597         uChunk.pu8 = KLDRMODMACHO_RVA2TYPE(pvMapping, pBR->VirtualAddress, uint8_t *);
    1598 
    1599         /*
    1600          * Loop thru the fixups in this chunk.
    1601          */
    1602         while (cFixups > 0)
    1603         {
    1604             u.pu8 = uChunk.pu8 + (*poffFixup & 0xfff);
    1605             switch (*poffFixup >> 12) /* ordered by value. */
     1788            PKLDRMODMACHOSECT pSect = &pSeg->paSections[iSect];
     1789            uint8_t *pbSectBits;
     1790
     1791            /* skip sections without fixups. */
     1792            if (!pSect->cFixups)
     1793                continue;
     1794
     1795            /* lazy load (and endian convert) the fixups. */
     1796            if (!pSect->paFixups)
    16061797            {
    1607                 /* 0 - Alignment placeholder. */
    1608                 case IMAGE_REL_BASED_ABSOLUTE:
     1798                rc = kldrModMachOLoadFixups(pModMachO, pSect->offFixups, pSect->cFixups, &pSect->paFixups);
     1799                if (rc)
    16091800                    break;
    1610 
    1611                 /* 1 - 16-bit, add 2nd 16-bit part of the delta. (rare) */
    1612                 case IMAGE_REL_BASED_HIGH:
    1613                     *u.pu16 += (uint16_t)(Delta >> 16);
    1614                     break;
    1615 
    1616                 /* 2 - 16-bit, add 1st 16-bit part of the delta. (rare) */
    1617                 case IMAGE_REL_BASED_LOW:
    1618                     *u.pu16 += (uint16_t)Delta;
    1619                     break;
    1620 
    1621                 /* 3 - 32-bit, add delta. (frequent in 32-bit images) */
    1622                 case IMAGE_REL_BASED_HIGHLOW:
    1623                     *u.pu32 += (uint32_t)Delta;
    1624                     break;
    1625 
    1626                 /* 4 - 16-bit, add 2nd 16-bit of the delta, sign adjust for the lower 16-bit. one arg. (rare)  */
    1627                 case IMAGE_REL_BASED_HIGHADJ:
     1801            }
     1802
     1803            /*
     1804             * Apply the fixups.
     1805             */
     1806            if (!pfnFixupSection)
     1807            {
     1808                /* determin the function for applying fixups. */
     1809                if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
     1810                    ||  pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE)
     1811                    pfnFixupSection = kldrModMachOObjFixupSectionGeneric;
     1812                else
    16281813                {
    1629                     int32_t i32;
    1630                     if (cFixups <= 1)
    1631                         return KLDR_ERR_PE_BAD_FIXUP;
    1632 
    1633                     i32 = (uint32_t)*u.pu16 << 16;
    1634                     i32 |= *++poffFixup; cFixups--; /* the addend argument */
    1635                     i32 += (uint32_t)Delta;
    1636                     i32 += 0x8000;
    1637                     *u.pu16 = (uint16_t)(i32 >> 16);
     1814                    rc = KLDR_ERR_TODO; /* save space for now. */
    16381815                    break;
    16391816                }
    1640 
    1641                 /* 5 - 32-bit MIPS JMPADDR, no implemented. */
    1642                 case IMAGE_REL_BASED_MIPS_JMPADDR:
    1643                     *u.pu32 = (*u.pu32 & 0xc0000000)
    1644                             | ((uint32_t)((*u.pu32 << 2) + (uint32_t)Delta) >> 2);
    1645                     break;
    1646 
    1647                 /* 6 - Intra section? Reserved value in later specs. Not implemented. */
    1648                 case IMAGE_REL_BASED_SECTION:
    1649                     KLDRMODMACHO_ASSERT(!"SECTION");
    1650                     return KLDR_ERR_PE_BAD_FIXUP;
    1651 
    1652                 /* 7 - Relative intra section? Reserved value in later specs. Not implemented. */
    1653                 case IMAGE_REL_BASED_REL32:
    1654                     KLDRMODMACHO_ASSERT(!"SECTION");
    1655                     return KLDR_ERR_PE_BAD_FIXUP;
    1656 
    1657                 /* 8 - reserved according to binutils... */
    1658                 case 8:
    1659                     KLDRMODMACHO_ASSERT(!"RESERVERED8");
    1660                     return KLDR_ERR_PE_BAD_FIXUP;
    1661 
    1662                 /* 9 - IA64_IMM64 (/ MIPS_JMPADDR16), no specs nor need to support the platform yet.
    1663                  * Bet this requires more code than all the other fixups put together in good IA64 spirit :-) */
    1664                 case IMAGE_REL_BASED_IA64_IMM64:
    1665                     KLDRMODMACHO_ASSERT(!"IA64_IMM64 / MIPS_JMPADDR16");
    1666                     return KLDR_ERR_PE_BAD_FIXUP;
    1667 
    1668                 /* 10 - 64-bit, add delta. (frequently in 64-bit images) */
    1669                 case IMAGE_REL_BASED_DIR64:
    1670                     *u.pu64 += (uint64_t)Delta;
    1671                     break;
    1672 
    1673                 /* 11 - 16-bit, add 3rd 16-bit of the delta, sign adjust for the lower 32-bit. two args. (rare) */
    1674                 case IMAGE_REL_BASED_HIGH3ADJ:
     1817            }
     1818
     1819            pbSectBits = (uint8_t *)pvMapping + (uintptr_t)pSect->RVA;
     1820            rc = pfnFixupSection(pModMachO, pbSectBits, (size_t)pSect->cb, pSect->offFile,
     1821                                 pSect->paFixups, pSect->cFixups, NewBaseAddress);
     1822            if (rc)
     1823                break;
     1824        }
     1825    }
     1826
     1827    return rc;
     1828}
     1829
     1830
     1831static int  kldrModMachOObjFixupSectionGeneric(PKLDRMODMACHO pModMachO, uint8_t *pbSectBits, size_t cbSectBits,
     1832                                               off_t offFile, const macho_relocation_info_t *paRelocs, uint32_t cRelocs,
     1833                                               KLDRADDR NewBaseAddress)
     1834{
     1835
     1836    return 0;
     1837}
     1838
     1839
     1840/**
     1841 * Loads the symbol table for a MH_OBJECT file.
     1842 *
     1843 * The symbol table is pointed to by KLDRMODMACHO::pvaSymbols.
     1844 *
     1845 * @returns 0 on success, non-zero kLdr status code on failure.
     1846 * @param   pModMachO       The Mach-O module interpret instance.
     1847 */
     1848static int  kldrModMachOLoadObjSymTab(PKLDRMODMACHO pModMachO)
     1849{
     1850    int rc = 0;
     1851
     1852    if (    !pModMachO->pvaSymbols
     1853        &&  pModMachO->cSymbols)
     1854    {
     1855        size_t cbSyms;
     1856        size_t cbSym;
     1857        void *pvSyms;
     1858        void *pvStrings;
     1859
     1860        /* sanity */
     1861        if (    !pModMachO->offSymbols
     1862            ||  (pModMachO->cbStrings && !pModMachO->offStrings))
     1863            return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
     1864
     1865        /* allocate */
     1866        cbSym = pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
     1867             || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
     1868             ? sizeof(macho_nlist_32_t)
     1869             : sizeof(macho_nlist_64_t);
     1870        cbSyms = pModMachO->cSymbols * cbSym;
     1871        if (cbSyms / cbSym != pModMachO->cSymbols)
     1872            return KLDR_ERR_SIZE_OVERFLOW;
     1873        rc = KLDR_ERR_NO_MEMORY;
     1874        pvSyms = kldrHlpAlloc(cbSyms);
     1875        if (pvSyms)
     1876        {
     1877            if (pModMachO->cbStrings)
     1878                pvStrings = kldrHlpAlloc(pModMachO->cbStrings);
     1879            else
     1880                pvStrings = kldrHlpAllocZ(4);
     1881            if (pvStrings)
     1882            {
     1883                /* read */
     1884                rc = kLdrRdrRead(pModMachO->pMod->pRdr, pvSyms, cbSyms, pModMachO->offSymbols);
     1885                if (!rc && pModMachO->cbStrings)
     1886                    rc = kLdrRdrRead(pModMachO->pMod->pRdr, pvStrings, pModMachO->cbStrings, pModMachO->offStrings);
     1887                if (!rc)
    16751888                {
    1676                     int64_t i64;
    1677                     if (cFixups <= 2)
    1678                         return KLDR_ERR_PE_BAD_FIXUP;
    1679 
    1680                     i64 = (uint64_t)*u.pu16 << 32
    1681                         | ((uint32_t)poffFixup[2] << 16)
    1682                         | poffFixup[1];
    1683                     i64 += Delta;
    1684                     i64 += 0x80008000UL;
    1685                     *u.pu16 = (uint16_t)(i64 >> 32);
    1686                     /* skip the addends arguments */
    1687                     poffFixup += 2;
    1688                     cFixups -= 2;
    1689                     break;
     1889                    pModMachO->pvaSymbols = pvSyms;
     1890                    pModMachO->pchStrings = (char *)pvStrings;
     1891   
     1892                    /* perform endian conversion? */
     1893                    if (pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
     1894                    {
     1895                        uint32_t cLeft = pModMachO->cSymbols;
     1896                        macho_nlist_32_t *pSym = (macho_nlist_32_t *)pvSyms;
     1897                        while (cLeft-- > 0)
     1898                        {
     1899                            pSym->n_un.n_strx = KLDRHLP_E2E_U32(pSym->n_un.n_strx);
     1900                            pSym->n_desc = (int16_t)KLDRHLP_E2E_U16(pSym->n_desc);
     1901                            pSym->n_value = KLDRHLP_E2E_U32(pSym->n_value);
     1902                            pSym++;
     1903                        }
     1904                    }
     1905                    else if (pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE)
     1906                    {
     1907                        uint32_t cLeft = pModMachO->cSymbols;
     1908                        macho_nlist_64_t *pSym = (macho_nlist_64_t *)pvSyms;
     1909                        while (cLeft-- > 0)
     1910                        {
     1911                            pSym->n_un.n_strx = KLDRHLP_E2E_U32(pSym->n_un.n_strx);
     1912                            pSym->n_desc = (int16_t)KLDRHLP_E2E_U16(pSym->n_desc);
     1913                            pSym->n_value = KLDRHLP_E2E_U64(pSym->n_value);
     1914                            pSym++;
     1915                        }
     1916                    }
     1917
     1918                    return 0;
    16901919                }
    1691 
    1692                 /* the rest are yet to be defined.*/
    1693                 default:
    1694                     return KLDR_ERR_PE_BAD_FIXUP;
     1920                kldrHlpFree(pvStrings);
    16951921            }
    1696 
    1697             /*
    1698              * Next relocation.
    1699              */
    1700             poffFixup++;
    1701             cFixups--;
     1922            kldrHlpFree(pvSyms);
    17021923        }
    1703 
    1704 
    1705         /*
    1706          * Next block.
    1707          */
    1708         cbLeft -= pBR->SizeOfBlock;
    1709         pBR = (PIMAGE_BASE_RELOCATION)((uintptr_t)pBR + pBR->SizeOfBlock);
    1710     }
    1711 
    1712 #endif
    1713     return 0;
    1714 }
    1715 
     1924    }
     1925    else
     1926        KLDRMODMACHO_ASSERT(pModMachO->pchStrings);
     1927
     1928    return rc;
     1929}
    17161930
    17171931
    17181932/**
    1719  * Resolves imports.
    1720  *
     1933 * Loads the fixups at the given address and performs endian
     1934 * conversion if necessary.
     1935 *
    17211936 * @returns 0 on success, non-zero kLdr status code on failure.
    1722  * @param   pModMachO          The PE module interpreter instance.
    1723  * @param   pvMapping       The mapping which imports should be resolved.
    1724  * @param   pfnGetImport    The callback for resolving an imported symbol.
    1725  * @param   pvUser          User argument to the callback.
     1937 * @param   pModMachO       The Mach-O module interpret instance.
     1938 * @param   offFixups       The file offset of the fixups.
     1939 * @param   cFixups         The number of fixups to load.
     1940 * @param   ppaFixups       Where to put the pointer to the allocated fixup array.
    17261941 */
    1727 static int  kldrModMachODoImports(PKLDRMODMACHO pModMachO, void *pvMapping, PFNKLDRMODGETIMPORT pfnGetImport, void *pvUser)
    1728 {
    1729     /* for when loading non-objects. */
    1730     return 0;
     1942static int  kldrModMachOLoadFixups(PKLDRMODMACHO pModMachO, off_t offFixups, uint32_t cFixups, macho_relocation_info_t **ppaFixups)
     1943{
     1944    macho_relocation_info_t *paFixups;
     1945    size_t cbFixups;
     1946    int rc;
     1947
     1948    /* allocate the memory. */
     1949    cbFixups = cFixups * sizeof(*paFixups);
     1950    if (cbFixups / sizeof(*paFixups) != cFixups)
     1951        return KLDR_ERR_SIZE_OVERFLOW;
     1952    paFixups = (macho_relocation_info_t *)kldrHlpAlloc(cbFixups);
     1953    if (!paFixups)
     1954        return KLDR_ERR_NO_MEMORY;
     1955
     1956    /* read the fixups. */
     1957    rc = kLdrRdrRead(pModMachO->pMod->pRdr, paFixups, cbFixups, offFixups);
     1958    if (!rc)
     1959    {
     1960        *ppaFixups = paFixups;
     1961
     1962        /* do endian conversion if necessary. */
     1963        if (    pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE
     1964            ||  pModMachO->Hdr.magic == IMAGE_MACHO64_SIGNATURE_OE)
     1965        {
     1966            uint32_t iFixup;
     1967            for (iFixup = 0; iFixup < cFixups; iFixup++)
     1968            {
     1969                uint32_t *pu32 = (uint32_t *)&paFixups[iFixup];
     1970                pu32[0] = KLDRHLP_E2E_U32(pu32[0]);
     1971                pu32[1] = KLDRHLP_E2E_U32(pu32[1]);
     1972            }
     1973        }
     1974    }
     1975    else
     1976        kldrHlpFree(paFixups);
     1977    return rc;
    17311978}
    17321979
     
    18212068     * Call workers to do the jobs.
    18222069     */
    1823     rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress);
    1824     if (pModMachO->Hdr.filetype != MH_OBJECT)
    1825         rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser);
     2070    if (pModMachO->Hdr.filetype == MH_OBJECT)
     2071    {
     2072        rc = kldrModMachOObjDoImports(pModMachO, pfnGetImport, pvUser);
     2073        if (!rc)
     2074            rc = kldrModMachOObjDoFixups(pModMachO, pvBits, NewBaseAddress);
     2075
     2076    }
     2077    else
     2078        rc = KLDR_ERR_TODO;
     2079    /*{
     2080        rc = kldrModMachODoFixups(pModMachO, pvBits, NewBaseAddress, OldBaseAddress, pfnGetImport, pvUser);
     2081        if (!rc)
     2082            rc = kldrModMachODoImports(pModMachO, pvBits, pfnGetImport, pvUser);
     2083    }*/
    18262084
    18272085    return rc;
  • trunk/kLdr/kLdrModMachO.h

    r2958 r2961  
    667667    union
    668668    {
    669         int32_t n_strx;         /**< Offset (index) into the string table. 0 means "". */
     669        uint32_t n_strx;        /**< Offset (index) into the string table. 0 means "". */
    670670    }           n_un;
    671671    uint8_t     n_type;         /**< Symbol type. */
Note: See TracChangeset for help on using the changeset viewer.