Ignore:
Timestamp:
Jul 9, 2013, 6:16:31 PM (12 years ago)
Author:
bird
Message:

mach_kernel doesn't have segments sorted by link address, but rather file offset, so counter that by sorting the segment array. Fixed RVA calc.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModMachO.c

    r49 r51  
    103103typedef struct KLDRMODMACHOSEG
    104104{
     105    /** The orignal segment number (in case we had to resort it). */
     106    KU32                    iOrgSegNo;
    105107    /** The number of sections in the segment. */
    106108    KU32                    cSections;
     
    188190static int  kldrModMachODoCreate(PKRDR pRdr, KLDRFOFF offImage, PKLDRMODMACHO *ppMod);
    189191static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage,
    190                                              KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, PKBOOL pfCanLoad);
     192                                             KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, PKBOOL pfCanLoad,
     193                                             PKLDRADDR pLinkAddress);
    191194static int  kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, KU32 cbStringPool);
    192195static int  kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress);
     
    292295    KBOOL fMakeGot;
    293296    KBOOL fCanLoad = K_TRUE;
     297    KLDRADDR LinkAddress;
    294298    KU8 cbJmpStub;
    295299    int rc;
     
    352356    if (!rc)
    353357        rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, offImage,
    354                                               &cSegments, &cSections, &cbStringPool, &fCanLoad);
     358                                              &cSegments, &cSections, &cbStringPool, &fCanLoad, &LinkAddress);
    355359    if (rc)
    356360    {
     
    456460        ||  s.Hdr32.magic == IMAGE_MACHO32_SIGNATURE_OE)
    457461        pModMachO->Hdr.reserved = 0;
    458     pModMachO->LinkAddress = 0;
     462    pModMachO->LinkAddress = LinkAddress;
    459463    pModMachO->cbImage = 0;
    460464    pModMachO->fCanLoad = fCanLoad;
     
    504508 * @param   pcbStringPool   Where to store the string pool size.
    505509 * @param   pfCanLoad       Where to store the can-load-image indicator.
     510 * @param   pLinkAddress    Where to store the image link address (i.e. the
     511 *                          lowest segment address).
    506512 */
    507513static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage,
    508                                              KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, PKBOOL pfCanLoad)
     514                                             KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool, PKBOOL pfCanLoad,
     515                                             PKLDRADDR pLinkAddress)
    509516{
    510517    union
     
    534541    *pcbStringPool = 0;
    535542    *pfCanLoad = K_TRUE;
     543    *pLinkAddress = ~(KLDRADDR)0;
    536544
    537545    while (cLeft-- > 0)
     
    696704
    697705
    698                     /* count segments and strings */
     706                    /* count segments and strings, calculate image link address. */
    699707                    switch (pHdr->filetype)
    700708                    {
     
    712720
    713721                            /* a new segment? */
    714                             if (    !cSegments
     722                            if (    cSections == 1
    715723                                ||  kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
    716724                            {
     
    729737                                cSegments++;
    730738                                cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1;
     739
     740                                /* Link address lower? */
     741                                if (*pLinkAddress > u.pSeg32->vmaddr)
     742                                    *pLinkAddress = u.pSeg32->vmaddr;
    731743                            }
    732744                            break;
     
    888900
    889901
    890                     /* count segments and strings */
     902                    /* count segments and strings, calculate image link address. */
    891903                    switch (pHdr->filetype)
    892904                    {
     
    904916
    905917                            /* a new segment? */
    906                             if (    !cSegments
     918                            if (    !cSections == 1
    907919                                ||  kHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
    908920                            {
     
    921933                                cSegments++;
    922934                                cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1;
     935
     936                                /* Link address lower? */
     937                                if (*pLinkAddress > u.pSeg64->vmaddr)
     938                                    *pLinkAddress = u.pSeg64->vmaddr;
    923939                            }
    924940                            break;
     
    11001116    PKLDRMODMACHOSECT pSectExtra = pModMachO->paSections;
    11011117    const KU32 cSegments = pModMachO->pMod->cSegments;
    1102     KU32 i;
     1118    KU32 i, c;
    11031119
    11041120    while (cLeft-- > 0)
     
    11191135                KU32 cSectionsLeft;
    11201136
    1121                 pModMachO->LinkAddress = u.pSeg32->vmaddr;
     1137                kHlpAssert(u.pSeg32->vmaddr >= pModMachO->LinkAddress);
    11221138
    11231139                /*
     
    12541270                KU32 cSectionsLeft;
    12551271
    1256                 pModMachO->LinkAddress = u.pSeg64->vmaddr;
     1272                kHlpAssert(u.pSeg64->vmaddr >= pModMachO->LinkAddress);
    12571273
    12581274                /*
     
    13321348                                pSeg->MapAddress = 0;
    13331349
     1350                                pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0];
    13341351                                pSegExtra->cSections = 0;
    13351352                                pSegExtra->paSections = pSectExtra;
     
    14081425    if (pSegExtra != &pModMachO->aSegments[0])
    14091426        pSegExtra[-1].cSections = pSectExtra - pSegExtra[-1].paSections;
     1427
     1428    /*
     1429     * Make sure the segments are sorted, or we'll get screwed further down.
     1430     */
     1431    c = pSeg - &pModMachO->pMod->aSegments[0];
     1432    pSeg = &pModMachO->pMod->aSegments[0];
     1433    for (i = 0; i < c - 1; i++)
     1434    {
     1435        KLDRADDR LinkAddress = pSeg[i + 1].LinkAddress;
     1436        if (LinkAddress < pSeg[i].LinkAddress)
     1437        {
     1438            /* Gotta move the next segment, find the correct location. */
     1439            KLDRMODMACHOSEG TmpSegExtra;
     1440            KLDRSEG TmpSeg;
     1441            KU32 j = i;
     1442            KU32 cShift = 1;
     1443
     1444            while (j > 0 && LinkAddress < pSeg[j - 1].LinkAddress)
     1445                j--, cShift++;
     1446
     1447            TmpSegExtra = pModMachO->aSegments[i + 1];
     1448            kHlpMemMove(&pModMachO->aSegments[j + 1], &pModMachO->aSegments[j],
     1449                        cShift * sizeof(pModMachO->aSegments[0]));
     1450            pModMachO->aSegments[j] = TmpSegExtra;
     1451
     1452            TmpSeg = pSeg[i + 1];
     1453            kHlpMemMove(&pSeg[j + 1], &pSeg[j], cShift * sizeof(pSeg[0]));
     1454            pSeg[j] = TmpSeg;
     1455        }
     1456    }
     1457    pSeg = &pModMachO->pMod->aSegments[c];
    14101458
    14111459    /*
     
    14541502        pSeg->MapAddress = 0;
    14551503
     1504        pSegExtra->iOrgSegNo = KU32_MAX;
    14561505        pSegExtra->cSections = 0;
    14571506        pSegExtra->paSections = NULL;
Note: See TracChangeset for help on using the changeset viewer.