Changeset 62 for trunk


Ignore:
Timestamp:
Oct 16, 2013, 7:30:36 PM (12 years ago)
Author:
bird
Message:

Mach-O: More MH_OBJECT fixes.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModMachO.c

    r61 r62  
    55
    66/*
    7  * Copyright (c) 2006-2007 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
     7 * Copyright (c) 2006-2013 Knut St. Osmundsen <bird-kStuff-spamix@anduin.net>
    88 *
    99 * Permission is hereby granted, free of charge, to any person
     
    153153     * This is 0 if not needed. */
    154154    KU8                     cbJmpStub;
    155     /** When set the sections in the load command segments must be used when
    156      * mapping or loading the image. */
    157     KBOOL                   fMapUsingLoadCommandSections;
     155    /** Effective file type.  If the original was a MH_OBJECT file, the
     156     * corresponding MH_DSYM needs the segment translation of a MH_OBJECT too.
     157     * The MH_DSYM normally has a separate __DWARF segment, but this is
     158     * automatically skipped during the transation. */
     159    KU8                     uEffFileType;
    158160    /** Pointer to the load commands. (endian converted) */
    159161    KU8                    *pbLoadCommands;
     
    206208static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage,
    207209                                             KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool,
    208                                              PKBOOL pfCanLoad, PKLDRADDR pLinkAddress);
     210                                             PKBOOL pfCanLoad, PKLDRADDR pLinkAddress, KU8 *puEffFileType);
    209211static int  kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, KU32 cbStringPool);
    210212static int  kldrModMachOAdjustBaseAddress(PKLDRMODMACHO pModMachO, PKLDRADDR pBaseAddress);
     
    312314    KLDRADDR LinkAddress;
    313315    KU8 cbJmpStub;
     316    KU8 uEffFileType;
    314317    int rc;
    315318    *ppModMachO = NULL;
     
    373376    if (!rc)
    374377        rc = kldrModMachOPreParseLoadCommands(pbLoadCommands, &s.Hdr32, pRdr, offImage, fOpenFlags,
    375                                               &cSegments, &cSections, &cbStringPool, &fCanLoad, &LinkAddress);
     378                                              &cSegments, &cSections, &cbStringPool, &fCanLoad, &LinkAddress, &uEffFileType);
    376379    if (rc)
    377380    {
     
    438441                case CPU_SUBTYPE_XEON_MP:           pMod->enmCpu = KCPU_P4; break;
    439442                    break;
     443
    440444                default:
     445                    /* Hack for kextutil output. */
     446                    if (   s.Hdr32.cpusubtype == 0
     447                        && s.Hdr32.filetype   == MH_OBJECT)
     448                        break;
    441449                    return KLDR_ERR_MACHO_UNSUPPORTED_MACHINE;
    442450            }
     
    486494    pModMachO->fMakeGot = fMakeGot;
    487495    pModMachO->cbJmpStub = cbJmpStub;
    488     pModMachO->fMapUsingLoadCommandSections = K_FALSE;
     496    pModMachO->uEffFileType = uEffFileType;
    489497    pModMachO->offSymbols = 0;
    490498    pModMachO->cSymbols = 0;
     
    548556static int  kldrModMachOPreParseLoadCommands(KU8 *pbLoadCommands, const mach_header_32_t *pHdr, PKRDR pRdr, KLDRFOFF offImage,
    549557                                             KU32 fOpenFlags, KU32 *pcSegments, KU32 *pcSections, KU32 *pcbStringPool,
    550                                              PKBOOL pfCanLoad, PKLDRADDR pLinkAddress)
     558                                             PKBOOL pfCanLoad, PKLDRADDR pLinkAddress, KU8 *puEffFileType)
    551559{
    552560    union
     
    571579    int fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
    572580                      || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE;
     581    KU8 uEffFileType = *puEffFileType = pHdr->filetype;
    573582
    574583    *pcSegments = 0;
     
    627636                #define VALIDATE_AND_ADD_SEGMENT(a_cBits) \
    628637                do { \
    629                     KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") /* Note: Not for non-object files. */ \
     638                    KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF")   /* Note: Not for non-object files. */ \
     639                                  || (   !kHlpStrComp(pSrcSeg->segname, "__CTF") /* Their CTF tool did/does weird things, */ \
     640                                      && pSrcSeg->vmsize == 0)                   /* overlapping vmaddr and zero vmsize. */ \
    630641                                  || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \
     642                    \
     643                    /* MH_DSYM files for MH_OBJECT files must have MH_OBJECT segment translation. */ \
     644                    if (   uEffFileType == MH_DSYM \
     645                        && cSegmentCommands == 0 \
     646                        && pSrcSeg->segname[0] == '\0') \
     647                        *puEffFileType = uEffFileType = MH_OBJECT; \
    631648                    \
    632649                    KLDRMODMACHO_CHECK_RETURN(   pSrcSeg->filesize == 0 \
     
    634651                                                  && (KU64)pSrcSeg->fileoff + pSrcSeg->filesize <= cbFile), \
    635652                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
    636                     KLDRMODMACHO_CHECK_RETURN(pSrcSeg->filesize <= pSrcSeg->vmsize, \
     653                    KLDRMODMACHO_CHECK_RETURN(   pSrcSeg->filesize <= pSrcSeg->vmsize \
     654                                              || (fSkipSeg && !kHlpStrComp(pSrcSeg->segname, "__CTF") /* see above */), \
    637655                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
    638656                    KLDRMODMACHO_CHECK_RETURN((pSrcSeg->maxprot & pSrcSeg->initprot) == pSrcSeg->initprot, \
     
    643661                                              <= u.pLoadCmd->cmdsize - sizeof(segment_command_##a_cBits##_t), \
    644662                                              KLDR_ERR_MACHO_BAD_LOAD_COMMAND); \
    645                     KLDRMODMACHO_CHECK_RETURN(    pHdr->filetype != MH_OBJECT \
    646                                               ||  cSegmentCommands == 0,\
     663                    KLDRMODMACHO_CHECK_RETURN(   uEffFileType != MH_OBJECT \
     664                                              || cSegmentCommands == 0 \
     665                                              || (   cSegmentCommands == 1 \
     666                                                  && uEffFileType == MH_OBJECT \
     667                                                  && pHdr->filetype == MH_DSYM \
     668                                                  && fSkipSeg), \
    647669                                              KLDR_ERR_MACHO_BAD_OBJECT_FILE); \
    648670                    cSegmentCommands++; \
    649671                    \
    650672                    /* Add the segment, if not object file. */ \
    651                     if (!fSkipSeg && pHdr->filetype != MH_OBJECT) \
     673                    if (!fSkipSeg && uEffFileType != MH_OBJECT) \
    652674                    { \
    653675                        cbStringPool += kHlpStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)) + 1; \
     
    686708                        \
    687709                        /* validate */ \
    688                         if (pHdr->filetype != MH_OBJECT) \
     710                        if (uEffFileType != MH_OBJECT) \
    689711                            KLDRMODMACHO_CHECK_RETURN(!kHlpStrComp(pSect->segname, pSrcSeg->segname),\
    690712                                                      KLDR_ERR_MACHO_BAD_SECTION); \
     
    776798                        if (fFileBits) \
    777799                        { \
    778                             KLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \
    779                                                       KLDR_ERR_MACHO_NON_CONT_SEG_BITS); \
    780                             KLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \
    781                                                       KLDR_ERR_MACHO_BAD_SECTION); \
     800                            if (uEffFileType != MH_OBJECT) \
     801                            { \
     802                                KLDRMODMACHO_CHECK_RETURN(pSect->offset == pSrcSeg->fileoff + offSect, \
     803                                                          KLDR_ERR_MACHO_NON_CONT_SEG_BITS); \
     804                                KLDRMODMACHO_CHECK_RETURN(pSect->offset - pSrcSeg->fileoff <= pSrcSeg->filesize, \
     805                                                          KLDR_ERR_MACHO_BAD_SECTION); \
     806                            } \
    782807                            KLDRMODMACHO_CHECK_RETURN(pSect->offset <= cbFile, \
    783808                                                      KLDR_ERR_MACHO_BAD_SECTION); \
     
    802827                        \
    803828                        /* Validate against file type (pointless?) and count the section, for object files add segment. */ \
    804                         switch (pHdr->filetype) \
     829                        switch (uEffFileType) \
    805830                        { \
    806831                            case MH_OBJECT: \
     
    916941                /* only one string in objects, please. */
    917942                cSymbolTabs++;
    918                 if (    pHdr->filetype == MH_OBJECT
     943                if (    uEffFileType == MH_OBJECT
    919944                    &&  cSymbolTabs != 1)
    920945                    KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_OBJECT_FILE);
     
    10271052        KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_MACHO_BAD_LOAD_COMMAND);
    10281053
    1029     switch (pHdr->filetype)
     1054    switch (uEffFileType)
    10301055    {
    10311056        case MH_OBJECT:
     
    11581183                     * in the preparsing stage. \
    11591184                     */ \
    1160                     if (pModMachO->Hdr.filetype != MH_OBJECT) \
     1185                    if (pModMachO->uEffFileType != MH_OBJECT) \
    11611186                        for (pSegItr = &pModMachO->pMod->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \
    11621187                            if (!kHlpStrNComp(pSegItr->pchName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \
     
    11661191                     * Create a new segment, unless we're supposed to skip this one. \
    11671192                     */ \
    1168                     if (   pModMachO->Hdr.filetype != MH_OBJECT \
     1193                    if (   pModMachO->uEffFileType != MH_OBJECT \
    11691194                        && (cSectionsLeft == 0 || !(pFirstSect->flags & S_ATTR_DEBUG)) \
    11701195                        && kHlpStrComp(pSrcSeg->segname, "__DWARF") ) \
     
    11831208                        /* New segment if object file. */ \
    11841209                        KBOOL fAddSegInner = K_FALSE; \
    1185                         if (   pModMachO->Hdr.filetype == MH_OBJECT \
     1210                        if (   pModMachO->uEffFileType == MH_OBJECT \
    11861211                            && !(pSect->flags & S_ATTR_DEBUG) \
    11871212                            && kHlpStrComp(pSrcSeg->segname, "__DWARF") ) \
     
    12451270
    12461271            case LC_SYMTAB:
    1247                 switch (pModMachO->Hdr.filetype)
     1272                switch (pModMachO->uEffFileType)
    12481273                {
    12491274                    case MH_OBJECT:
     
    15121537     * Locate the segment.
    15131538     */
    1514     iSeg = pMod->cSegments;
    1515     if (!iSeg)
     1539    if (!pMod->cSegments)
    15161540        return KLDR_ERR_SYMBOL_NOT_FOUND;
    1517     while (   pMod->aSegments[iSeg].cchName != cchSegName
    1518            || kHlpMemComp(pMod->aSegments[iSeg].pchName, pchSegName, cchSegName) != 0)
    1519     {
    1520         if (!iSeg)
    1521             return KLDR_ERR_SYMBOL_NOT_FOUND;
    1522         iSeg--;
    1523     }
     1541    for (iSeg = 0; iSeg < pMod->cSegments; iSeg++)
     1542    {
     1543        if (   pMod->aSegments[iSeg].cchName >= cchSegName
     1544            && kHlpMemComp(pMod->aSegments[iSeg].pchName, pchSegName, cchSegName) == 0)
     1545        {
     1546            section_32_t const *pSect;
     1547            if (   pMod->aSegments[iSeg].cchName == cchSegName
     1548                && pModMachO->Hdr.filetype != MH_OBJECT /* Good enough for __DWARF segs in MH_DHSYM, I hope. */)
     1549                break;
     1550
     1551            pSect = (section_32_t *)pModMachO->aSegments[iSeg].paSections[0].pvMachoSection;
     1552            if (   pModMachO->uEffFileType == MH_OBJECT
     1553                && pMod->aSegments[iSeg].cchName > cchSegName + 1
     1554                && pMod->aSegments[iSeg].pchName[cchSegName] == '.'
     1555                && kHlpStrNComp(&pMod->aSegments[iSeg].pchName[cchSegName + 1], pSect->sectname, sizeof(pSect->sectname)) == 0
     1556                && pMod->aSegments[iSeg].cchName - cchSegName - 1 <= sizeof(pSect->sectname) )
     1557                break;
     1558        }
     1559    }
     1560    if (iSeg >= pMod->cSegments)
     1561        return KLDR_ERR_SYMBOL_NOT_FOUND;
    15241562
    15251563    if (!s_aPrefixes[iPrefix].fSection)
     
    15281566         * Calculate the segment start/end address.
    15291567         */
    1530         uValue = pMod->aSegments[iSeg].LinkAddress;
     1568        uValue = pMod->aSegments[iSeg].RVA;
    15311569        if (!s_aPrefixes[iPrefix].fStart)
    15321570            uValue += pMod->aSegments[iSeg].cb;
     
    15541592        }
    15551593
    1556         if (   pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE
    1557             || pModMachO->Hdr.magic == IMAGE_MACHO32_SIGNATURE_OE)
    1558         {
    1559             section_32_t *pSect = (section_32_t *)pModMachO->aSegments[iSeg].paSections[iSect].pvMachoSection;
    1560             uValue = pSect->addr;
    1561             if (!s_aPrefixes[iPrefix].fStart)
    1562                 uValue += pSect->size;
    1563         }
    1564         else
    1565         {
    1566             section_64_t *pSect = (section_64_t *)pModMachO->aSegments[iSeg].paSections[iSect].pvMachoSection;
    1567             uValue = pSect->addr;
    1568             if (!s_aPrefixes[iPrefix].fStart)
    1569                 uValue += pSect->size;
    1570         }
    1571     }
    1572 
    1573     /*
    1574      * Adjust the value from link to rva + base.
    1575      */
    1576     uValue -= pMod->aSegments[iSeg].LinkAddress - pMod->aSegments[iSeg].RVA;
     1594        uValue = pModMachO->aSegments[iSeg].paSections[iSect].RVA;
     1595        if (!s_aPrefixes[iPrefix].fStart)
     1596            uValue += pModMachO->aSegments[iSeg].paSections[iSect].cb;
     1597    }
     1598
     1599    /*
     1600     * Convert from RVA to load address.
     1601     */
    15771602    uValue += BaseAddress;
    15781603    if (puValue)
     
    17531778                                      || (   paSyms[iSymbol].n_sect == 1 /* special hack for __mh_execute_header */
    17541779                                          && offSect == 0U - pSect->RVA
    1755                                           && pModMachO->Hdr.filetype != MH_OBJECT),
     1780                                          && pModMachO->uEffFileType != MH_OBJECT),
    17561781                                      KLDR_ERR_MACHO_BAD_SYMBOL);
    17571782            if (puValue)
     
    18811906                                      || (   paSyms[iSymbol].n_sect == 1 /* special hack for __mh_execute_header */
    18821907                                          && offSect == 0U - pSect->RVA
    1883                                           && pModMachO->Hdr.filetype != MH_OBJECT),
     1908                                          && pModMachO->uEffFileType != MH_OBJECT),
    18841909                                      KLDR_ERR_MACHO_BAD_SYMBOL);
    18851910            if (puValue)
     
    20332058                                          || (   paSyms[iSym].n_sect == 1 /* special hack for __mh_execute_header */
    20342059                                              && uValue == 0U - pSect->RVA
    2035                                               && pModMachO->Hdr.filetype != MH_OBJECT),
     2060                                              && pModMachO->uEffFileType != MH_OBJECT),
    20362061                                          KLDR_ERR_MACHO_BAD_SYMBOL);
    20372062                uValue += BaseAddress + pSect->RVA;
     
    21452170                                          || (   paSyms[iSym].n_sect == 1 /* special hack for __mh_execute_header */
    21462171                                              && uValue == 0U - pSect->RVA
    2147                                               && pModMachO->Hdr.filetype != MH_OBJECT),
     2172                                              && pModMachO->uEffFileType != MH_OBJECT),
    21482173                                          KLDR_ERR_MACHO_BAD_SYMBOL);
    21492174                uValue += BaseAddress + pSect->RVA;
     
    23412366
    23422367    /* try do the prepare */
    2343     if (pModMachO->fMapUsingLoadCommandSections)
    2344         KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    2345     else
    2346     {
    2347         rc = kRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed);
    2348         if (rc)
    2349             return rc;
    2350     }
     2368    rc = kRdrMap(pMod->pRdr, &pvBase, pMod->cSegments, pMod->aSegments, fFixed);
     2369    if (rc)
     2370        return rc;
    23512371
    23522372    /*
     
    23802400     * Try unmap the image.
    23812401     */
    2382     if (pModMachO->fMapUsingLoadCommandSections)
    2383         KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    2384     else
    2385     {
    2386         rc = kRdrUnmap(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments);
    2387         if (rc)
    2388             return rc;
    2389     }
     2402    rc = kRdrUnmap(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments);
     2403    if (rc)
     2404        return rc;
    23902405
    23912406    /*
     
    24512466     * Before doing anything we'll have to make all pages writable.
    24522467     */
    2453     if (pModMachO->fMapUsingLoadCommandSections)
    2454         KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    2455     else
    2456     {
    2457         rc = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
    2458         if (rc)
    2459             return rc;
    2460     }
     2468    rc = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 1 /* unprotect */);
     2469    if (rc)
     2470        return rc;
    24612471
    24622472    /*
     
    24692479     * Restore protection.
    24702480     */
    2471     if (pModMachO->fMapUsingLoadCommandSections)
    2472         rc2 = KLDR_ERR_TODO; /* deal with this if it ever occurs. */
    2473     else
    2474         rc2 = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
     2481    rc2 = kRdrProtect(pMod->pRdr, pModMachO->pvMapping, pMod->cSegments, pMod->aSegments, 0 /* protect */);
    24752482    if (!rc && rc2)
    24762483        rc = rc2;
     
    33983405    /*
    33993406     * When possible use the segment table to load the data.
    3400      * If not iterate the load commands and execute the segment / section loads.
    3401      */
    3402     if (pModMachO->fMapUsingLoadCommandSections)
    3403         KLDRMODMACHO_CHECK_RETURN(0, KLDR_ERR_TODO); /* deal with this if it ever occurs. */
    3404     else
    3405     {
    3406         for (i = 0; i < pMod->cSegments; i++)
    3407         {
    3408             /* skip it? */
    3409             if (    pMod->aSegments[i].cbFile == -1
    3410                 ||  pMod->aSegments[i].offFile == -1
    3411                 ||  pMod->aSegments[i].LinkAddress == NIL_KLDRADDR
    3412                 ||  !pMod->aSegments[i].Alignment)
    3413                 continue;
    3414             rc = kRdrRead(pMod->pRdr,
    3415                           (KU8 *)pvBits + (pMod->aSegments[i].LinkAddress - pModMachO->LinkAddress),
    3416                           pMod->aSegments[i].cbFile,
    3417                           pMod->aSegments[i].offFile);
    3418             if (rc)
    3419                 return rc;
    3420         }
     3407     */
     3408    for (i = 0; i < pMod->cSegments; i++)
     3409    {
     3410        /* skip it? */
     3411        if (    pMod->aSegments[i].cbFile == -1
     3412            ||  pMod->aSegments[i].offFile == -1
     3413            ||  pMod->aSegments[i].LinkAddress == NIL_KLDRADDR
     3414            ||  !pMod->aSegments[i].Alignment)
     3415            continue;
     3416        rc = kRdrRead(pMod->pRdr,
     3417                      (KU8 *)pvBits + pMod->aSegments[i].RVA,
     3418                      pMod->aSegments[i].cbFile,
     3419                      pMod->aSegments[i].offFile);
     3420        if (rc)
     3421            return rc;
    34213422    }
    34223423
Note: See TracChangeset for help on using the changeset viewer.