Changeset 2963 for trunk


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

Implemented generic fixups for 32-bit symbol tables.

Location:
trunk/kLdr
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdr.h

    r2962 r2963  
    5858#  define INT32_C(c)            (c)
    5959#  define INT64_C(c)            (c ## LL)
     60#  define INT8_MIN              (INT8_C(-0x7f) - 1)
     61#  define INT16_MIN             (INT16_C(-0x7fff) - 1)
     62#  define INT32_MIN             (INT32_C(-0x7fffffff) - 1)
     63#  define INT64_MIN             (INT64_C(-0x7fffffffffffffff) - 1)
     64#  define INT8_MAX              INT8_C(0x7f)
     65#  define INT16_MAX             INT16_C(0x7fff)
     66#  define INT32_MAX             INT32_C(0x7fffffff)
     67#  define INT64_MAX             INT64_C(0x7fffffffffffffff)
     68#  define UINT8_MAX             UINT8_C(0xff)
     69#  define UINT16_MAX            UINT16_C(0xffff)
     70#  define UINT32_MAX            UINT32_C(0xffffffff)
     71#  define UINT64_MAX            UINT64_C(0xffffffffffffffff)
    6072# else
    6173#  include <stdint.h>
     
    6476
    6577
    66 /** @defgroup grp_kLdrRdr   kLdrRdr - The file provider
     78/** @defgroup grp_kLdrBasic     kLdr Basic Types
    6779 * @{ */
    6880
     
    101113#endif
    102114
    103 /** Pointer to a loader segment. */
    104 typedef struct KLDRSEG *PKLDRSEG;
    105 /** Pointer to a loader segment. */
    106 typedef const struct KLDRSEG *PCKLDRSEG;
    107 
    108 
     115
     116/**
     117 * Union of all the integer types.
     118 */
     119typedef union KLDRU
     120{
     121    int8_t          i8;     /**< int8_t view. */
     122    uint8_t         u8;     /**< uint8_t view. */
     123    int16_t         i16;    /**< int16_t view. */
     124    uint16_t        u16;    /**< uint16_t view. */
     125    int32_t         i32;    /**< int32_t view. */
     126    uint32_t        u32;    /**< uint32_t view. */
     127    int64_t         i64;    /**< int64_t view. */
     128    uint64_t        u64;    /**< uint64_t view. */
     129
     130    int8_t          ai8[8]; /**< int8_t array view . */
     131    uint8_t         au8[8]; /**< uint8_t array view. */
     132    int16_t         ai16[4];/**< int16_t array view . */
     133    uint16_t        au16[4];/**< uint16_t array view. */
     134    int32_t         ai32[2];/**< int32_t array view . */
     135    uint32_t        au32[2];/**< uint32_t array view. */
     136
     137    signed char     ch;     /**< signed char view. */
     138    unsigned char   uch;    /**< unsigned char view. */
     139    signed short    s;      /**< signed short view. */
     140    unsigned short  us;     /**< unsigned short view. */
     141    signed int      i;      /**< signed int view. */
     142    unsigned int    u;      /**< unsigned int view. */
     143    signed long     l;      /**< signed long view. */
     144    unsigned long   ul;     /**< unsigned long view. */
     145    void           *pv;     /**< void pointer view. */
     146
     147    KLDRADDR        Addr;   /**< kLdr address view. */
     148    KLDRSIZE        Size;   /**< kLdr size view. */
     149} KLDRU;
     150/** Pointer to an integer union. */
     151typedef KLDRU *PKLDRU;
     152/** Pointer to a const integer union. */
     153typedef const KLDRU *PCKLDRU;
     154
     155
     156/**
     157 * Union of pointers to all the integer types.
     158 */
     159typedef union KLDRPU
     160{
     161    int8_t         *pi8;    /**< int8_t view. */
     162    uint8_t        *pu8;    /**< uint8_t view. */
     163    int16_t        *pi16;   /**< int16_t view. */
     164    uint16_t       *pu16;   /**< uint16_t view. */
     165    int32_t        *pi32;   /**< int32_t view. */
     166    uint32_t       *pu32;   /**< uint32_t view. */
     167    int64_t        *pi64;   /**< int64_t view. */
     168    uint64_t       *pu64;   /**< uint64_t view. */
     169
     170    signed char    *pch;    /**< signed char view. */
     171    unsigned char  *puch;   /**< unsigned char view. */
     172    signed short   *ps;     /**< signed short view. */
     173    unsigned short *pus;    /**< unsigned short view. */
     174    signed int     *pi;     /**< signed int view. */
     175    unsigned int   *pu;     /**< unsigned int view. */
     176    signed long    *pl;     /**< signed long view. */
     177    unsigned long  *pul;    /**< unsigned long view. */
     178    void           *pv;     /**< void pointer view. */
     179} KLDRPU;
     180/** Pointer to an integer pointer union. */
     181typedef KLDRPU *PKLDRPU;
     182/** Pointer to a const integer pointer union. */
     183typedef const KLDRPU *PCKLDRPU;
    109184
    110185
     
    142217} KLDRPROT;
    143218
     219/** Pointer to a loader segment. */
     220typedef struct KLDRSEG *PKLDRSEG;
     221/** Pointer to a loader segment. */
     222typedef const struct KLDRSEG *PCKLDRSEG;
     223
     224/** @} */
     225
     226
     227/** @defgroup grp_kLdrRdr   kLdrRdr - The file provider
     228 * @{ */
    144229
    145230/** Pointer to a file provider instance core. */
  • 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}
  • trunk/kLdr/kLdrModMachO.h

    r2962 r2963  
    641641/**
    642642 * The 32-bit Mach-O version of the nlist structure.
    643  * 
    644  * This differs from the a.out nlist struct in that the unused n_other field 
     643 *
     644 * This differs from the a.out nlist struct in that the unused n_other field
    645645 * was renamed to n_sect and used for keeping the relevant section number.
    646646 * @remark  This structure is not name mach_nlist_32 in the Apple headers, but nlist.
     
    648648typedef struct macho_nlist_32
    649649{
    650     union 
     650    union
    651651    {
    652652        int32_t n_strx;         /**< Offset (index) into the string table. 0 means "". */
     
    665665typedef struct macho_nlist_64
    666666{
    667     union 
     667    union
    668668    {
    669669        uint32_t n_strx;        /**< Offset (index) into the string table. 0 means "". */
     
    676676
    677677
    678 /** @name Symbol Type Constants (macho_nlist_32_t::n_type, macho_nlist_64_t::n_type) 
    679  * 
     678/** @name Symbol Type Constants (macho_nlist_32_t::n_type, macho_nlist_64_t::n_type)
     679 *
    680680 * In the Mach-O world n_type is somewhat similar to a.out, meaning N_EXT, N_UNDF, N_ABS
    681681 * and the debug symbols are essentially the same, but the remaining stuff is different.
    682  * The main reason for this is that the encoding of section has been moved to n_sect 
    683  * to permit up to 255 sections instead of the fixed 3 a.out sections (not counting 
     682 * The main reason for this is that the encoding of section has been moved to n_sect
     683 * to permit up to 255 sections instead of the fixed 3 a.out sections (not counting
    684684 * the abs symbols and set vectors).
    685  * 
    686  * To avoid confusion with a.out the Mach-O constants has been fitted with a MACHO_ 
     685 *
     686 * To avoid confusion with a.out the Mach-O constants has been fitted with a MACHO_
    687687 * prefix here.
    688  * 
    689  * Common symbols (aka communal symbols and comdefs) are represented by 
    690  * n_type = MACHO_N_EXT | MACHO_N_UNDF, n_sect = NO_SECT and n_value giving 
     688 *
     689 * Common symbols (aka communal symbols and comdefs) are represented by
     690 * n_type = MACHO_N_EXT | MACHO_N_UNDF, n_sect = NO_SECT and n_value giving
    691691 * the size.
    692  * 
    693  * 
     692 *
     693 *
    694694 * Symbol table entries can be inserted directly in the assembly code using
    695695 * this notation:
     
    697697 *      .stabs "n_name", n_type, n_sect, n_desc, n_value
    698698 * @endcode
    699  * 
     699 *
    700700 * (1) The line number is optional, GCC doesn't set it.
    701701 * (2) The type is optional, GCC doesn't set it.
     
    729729#define MACHO_N_PC      UINT8_C(0x30)   /**< Global pascal symbol.  "name",, NO_SECT, subtype?, line (3) */
    730730    /* omits N_NSYMS, N_NOMAP and N_OBJ. */
    731 #define MACHO_N_OPT     UINT8_C(0x3c)   /**< Options for the debugger related to the language of the 
     731#define MACHO_N_OPT     UINT8_C(0x3c)   /**< Options for the debugger related to the language of the
    732732                                             source file.           "options?",,,, */
    733733#define MACHO_N_RSYM    UINT8_C(0x40)   /**< Register variable.     "name",, NO_SECT, type, register */
     
    758758#define MACHO_N_ECOMM   UINT8_C(0xe4)   /**< End common.            "name",, section, 0, 0 */
    759759#define MACHO_N_ECOML   UINT8_C(0xe8)   /**< End local common.           0,, section, 0, address */
    760 #define MACHO_N_LENG    UINT8_C(0xfe)   /**< Length-value of the preceding entry. 
     760#define MACHO_N_LENG    UINT8_C(0xfe)   /**< Length-value of the preceding entry.
    761761                                                                    "name",, NO_SECT, 0, length */
    762762
    763763/** @} */
    764764
    765 /** @name Symbol Description Bits (macho_nlist_32_t::n_desc, macho_nlist_64_t::n_desc) 
    766  * 
    767  * Mach-O puts the n_desc field to a number of uses, like lazy binding , library 
     765/** @name Symbol Description Bits (macho_nlist_32_t::n_desc, macho_nlist_64_t::n_desc)
     766 *
     767 * Mach-O puts the n_desc field to a number of uses, like lazy binding , library
    768768 * ordinal numbers for -twolevel_namespace, stripping and weak symbol handling.
    769  * 
    770  * @remark The REFERENCE_FLAGS_* are really not flags in the normal sense (bit), 
     769 *
     770 * @remark The REFERENCE_FLAGS_* are really not flags in the normal sense (bit),
    771771 *         they are more like enum values.
    772772 * @{
     
    802802/** Weak external symbol. Symbol can be missing, in which case it's will have the value 0. */
    803803#define N_WEAK_REF                      UINT16_C(0x0040)
    804 /** Weak symbol definition. The symbol can be overridden by another weak 
    805  * symbol already present or by a non-weak (strong) symbol definition. 
    806  * Currently only supported for coalesed symbols. 
     804/** Weak symbol definition. The symbol can be overridden by another weak
     805 * symbol already present or by a non-weak (strong) symbol definition.
     806 * Currently only supported for coalesed symbols.
    807807 * @remark This bit means something differently for undefined symbols, see N_REF_TO_WEAK.
    808808 */
     
    822822/**
    823823 * Relocation entry.
    824  * 
    825  * Differs from a.out in the meaning of r_symbolnum when r_extern=0 and 
    826  * that r_pad is made into r_type. 
    827  * 
     824 *
     825 * Differs from a.out in the meaning of r_symbolnum when r_extern=0 and
     826 * that r_pad is made into r_type.
     827 *
    828828 * @remark  This structure and type has been prefixed with macho_ to avoid
    829829 *          confusion with the original a.out type.
    830830 */
    831 typedef struct macho_relocation_info 
    832 {
    833     int32_t     r_address;          /**< Section relative address of the fixup. 
    834                                          The top bit (signed) indicates that this is a scattered 
     831typedef struct macho_relocation_info
     832{
     833    int32_t     r_address;          /**< Section relative address of the fixup.
     834                                         The top bit (signed) indicates that this is a scattered
    835835                                         relocation if set, see scattered_relocation_info_t. */
    836836    uint32_t    r_symbolnum : 24,   /**< r_extern=1: Symbol table index, relocate with the address of this symbol.
     
    845845#define R_ABS           0
    846846
    847 /** Flag in r_address indicating that the relocation is of the 
     847/** Flag in r_address indicating that the relocation is of the
    848848 * scattered_relocation_info_t kind and not macho_relocation_info_t. */
    849849#define R_SCATTERED     UINT32_C(0x80000000)
     
    851851/**
    852852 * Scattered relocation.
    853  * 
    854  * This is a hack mainly for RISC machines which restricts section size 
     853 *
     854 * This is a hack mainly for RISC machines which restricts section size
    855855 * to 16MB among other things.
    856  * 
     856 *
    857857 * The reason for the big/little endian differences here is of course because
    858  * of the R_SCATTERED mask and the way bitfields are implemented by the 
     858 * of the R_SCATTERED mask and the way bitfields are implemented by the
    859859 * C/C++ compilers.
    860860 */
     
    876876# error "Neither KLDR_LITTLE_ENDIAN nor KLDR_BIG_ENDIAN is defined!"
    877877#endif
    878     int32_t     r_value;            /**< The value the fixup is refering to (Without offset added). */
     878    int32_t     r_value;            /**< The value the fixup is refering to (without offset added). */
    879879} scattered_relocation_info_t;
    880880
     
    884884typedef enum reloc_type_generic
    885885{
    886     GENERIC_RELOC_VANILLA = 0,      /**< Standard relocation. */ 
     886    GENERIC_RELOC_VANILLA = 0,      /**< Standard relocation. */
    887887    GENERIC_RELOC_PAIR,             /**< Follows GENERIC_RELOC_SECTDIFF. */
    888888    GENERIC_RELOC_SECTDIFF,         /**< ??? */
  • trunk/kLdr/kLdrRdrFile.c

    r2893 r2963  
    934934    }
    935935
     936    *ppvBits = pRdrFile->pvMapping;
    936937    pRdrFile->cMappings++;
    937938    return 0;
Note: See TracChangeset for help on using the changeset viewer.