Changeset 59


Ignore:
Timestamp:
Oct 13, 2013, 12:53:10 AM (12 years ago)
Author:
bird
Message:

Mach-O: Object files only have one LC_SEGMENTxx, one kLdr segment for each Mach-O section (sans debug).

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModMachO.c

    r58 r59  
    515515 * out the module instance.
    516516 *
    517  * The conversion that's preformed is format endian to host endian.
    518  * The preparsing has to do with segment counting, section counting and string pool sizing.
     517 * The conversion that's preformed is format endian to host endian.  The
     518 * preparsing has to do with segment counting, section counting and string pool
     519 * sizing.
     520 *
     521 * Segment are created in two different ways, depending on the file type.
     522 *
     523 * For object files there is only one segment command without a given segment
     524 * name. The sections inside that segment have different segment names and are
     525 * not sorted by their segname attribute.  We create one segment for each
     526 * section, with the segment name being 'segname.sectname' in order to hopefully
     527 * keep the names unique.  Debug sections does not get segments.
     528 *
     529 * For non-object files, one kLdr segment is created for each Mach-O segment.
     530 * Debug segments is not exposed by kLdr via the kLdr segment table, but via the
     531 * debug enumeration callback API.
    519532 *
    520533 * @returns 0 on success.
     
    592605                KU32            cSectionsLeft = pSrcSeg->nsects;
    593606                KU64            offSect       = 0;
    594                 KBOOL           fSkipSeg      = !kHlpStrComp(pSrcSeg->segname, "__DWARF")
    595                                              || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG));
    596607
    597608                /* Convert and verify the segment. */
     
    614625                #define VALIDATE_AND_ADD_SEGMENT(a_cBits) \
    615626                do { \
     627                    KBOOL fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") /* Note: Not for non-object files. */ \
     628                                  || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \
     629                    \
    616630                    KLDRMODMACHO_CHECK_RETURN(   pSrcSeg->filesize == 0 \
    617631                                              || (   pSrcSeg->fileoff <= cbFile \
     
    632646                    cSegmentCommands++; \
    633647                    \
    634                     /* add the segment. */ \
    635                     if (!fSkipSeg) \
     648                    /* Add the segment, if not object file. */ \
     649                    if (!fSkipSeg && pHdr->filetype != MH_OBJECT) \
    636650                    { \
    637651                        cbStringPool += kHlpStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)) + 1; \
     
    672686                        \
    673687                        /* validate */ \
    674                         KLDRMODMACHO_CHECK_RETURN(!kHlpStrComp(pSect->segname, pSrcSeg->segname),\
    675                                                   KLDR_ERR_MACHO_BAD_SECTION); \
     688                        if (pHdr->filetype != MH_OBJECT) \
     689                            KLDRMODMACHO_CHECK_RETURN(!kHlpStrComp(pSect->segname, pSrcSeg->segname),\
     690                                                      KLDR_ERR_MACHO_BAD_SECTION); \
    676691                        \
    677692                        switch (pSect->flags & SECTION_TYPE) \
     
    786801                        } \
    787802                        \
    788                         /* validate against file type (pointless?) and count the section. */ \
     803                        /* Validate against file type (pointless?) and count the section, for object files add segment. */ \
    789804                        switch (pHdr->filetype) \
    790805                        { \
    791806                            case MH_OBJECT: \
     807                                if (   !(pSect->flags & S_ATTR_DEBUG) \
     808                                    && kHlpStrComp(pSect->segname, "__DWARF")) \
     809                                { \
     810                                    cbStringPool += kHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1; \
     811                                    cbStringPool += kHlpStrNLen(&pSect->sectname[0], sizeof(pSect->sectname)) + 1; \
     812                                    cSegments++; \
     813                                    \
     814                                    /* Link address lower? Very unlikely. */ \
     815                                    if (*pLinkAddress > pSect->addr) \
     816                                        *pLinkAddress = pSect->addr; \
     817                                } \
     818                                /* fall thru */ \
    792819                            case MH_EXECUTE: \
    793820                            case MH_DYLIB: \
     
    819846                KU32            cSectionsLeft = pSrcSeg->nsects;
    820847                KU64            offSect       = 0;
    821                 KBOOL           fSkipSeg      = !kHlpStrComp(pSrcSeg->segname, "__DWARF")
    822                                              || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG));
    823848
    824849                /* Convert and verify the segment. */
     
    10721097                KU32            cSectionsLeft = pSrcSeg->nsects;
    10731098
     1099                /* Adds a segment, used by the macro below and thus shared with the 64-bit segment variant. */
     1100                #define NEW_SEGMENT(a_cBits, a_achName1, a_fObjFile, a_achName2, a_SegAddr, a_cbSeg, a_fFileBits, a_offFile, a_cbFile) \
     1101                do { \
     1102                    pDstSeg->pvUser = NULL; \
     1103                    pDstSeg->pchName = pbStringPool; \
     1104                    pDstSeg->cchName = (KU32)kHlpStrNLen(a_achName1, sizeof(a_achName1)); \
     1105                    kHlpMemCopy(pbStringPool, a_achName1, pDstSeg->cchName); \
     1106                    pbStringPool += pDstSeg->cchName; \
     1107                    if (a_fObjFile) \
     1108                    {   /* MH_OBJECT: Add '.sectname' - sections aren't sorted by segments. */ \
     1109                        KSIZE cchName2 = kHlpStrNLen(a_achName2, sizeof(a_achName2)); \
     1110                        *pbStringPool++ = '.'; \
     1111                        kHlpMemCopy(pbStringPool, a_achName2, cchName2); \
     1112                        pbStringPool += cchName2; \
     1113                        pDstSeg->cchName += cchName2; \
     1114                    } \
     1115                    *pbStringPool++ = '\0'; \
     1116                    pDstSeg->SelFlat = 0; \
     1117                    pDstSeg->Sel16bit = 0; \
     1118                    pDstSeg->fFlags = 0; \
     1119                    pDstSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */ \
     1120                    pDstSeg->cb = (a_cbSeg); \
     1121                    pDstSeg->Alignment = 1; /* updated while parsing sections. */ \
     1122                    pDstSeg->LinkAddress = (a_SegAddr); \
     1123                    if (a_fFileBits) \
     1124                    { \
     1125                        pDstSeg->offFile = (a_offFile) + pModMachO->offImage; \
     1126                        pDstSeg->cbFile  = (a_cbFile); \
     1127                    } \
     1128                    else \
     1129                    { \
     1130                        pDstSeg->offFile = -1; \
     1131                        pDstSeg->cbFile  = -1; \
     1132                    } \
     1133                    pDstSeg->RVA = (a_SegAddr) - pModMachO->LinkAddress; \
     1134                    pDstSeg->cbMapped = 0; \
     1135                    pDstSeg->MapAddress = 0; \
     1136                    \
     1137                    pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; \
     1138                    pSegExtra->cSections = 0; \
     1139                    pSegExtra->paSections = pSectExtra; \
     1140                } while (0)
     1141
     1142                /* Closes the new segment - parter of NEW_SEGMENT. */
     1143                #define CLOSE_SEGMENT() \
     1144                do { \
     1145                    pSegExtra->cSections = pSectExtra - pSegExtra->paSections; \
     1146                    pSegExtra++; \
     1147                    pDstSeg++; \
     1148                } while (0)
     1149
     1150
    10741151                /* Shared with the 64-bit variant. */
    10751152                #define ADD_SEGMENT_AND_ITS_SECTIONS(a_cBits) \
    10761153                do { \
    1077                     KBOOL   fSkipSeg = !kHlpStrComp(pSrcSeg->segname, "__DWARF") \
    1078                                     || (cSectionsLeft > 0 && (pFirstSect->flags & S_ATTR_DEBUG)); \
     1154                    KBOOL fAddSegOuter = K_FALSE; \
    10791155                    \
    10801156                    kHlpAssert(pSrcSeg->vmaddr >= pModMachO->LinkAddress); \
     
    10841160                     * in the preparsing stage. \
    10851161                     */ \
    1086                     for (pSegItr = &pModMachO->pMod->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \
    1087                         if (!kHlpStrNComp(pSegItr->pchName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \
    1088                             KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_DUPLICATE_SEGMENT_NAME); \
     1162                    if (pModMachO->Hdr.filetype != MH_OBJECT) \
     1163                        for (pSegItr = &pModMachO->pMod->aSegments[0]; pSegItr != pDstSeg; pSegItr++) \
     1164                            if (!kHlpStrNComp(pSegItr->pchName, pSrcSeg->segname, sizeof(pSrcSeg->segname))) \
     1165                                KLDRMODMACHO_FAILED_RETURN(KLDR_ERR_DUPLICATE_SEGMENT_NAME); \
    10891166                    \
    10901167                    /* \
    10911168                     * Create a new segment, unless we're supposed to skip this one. \
    10921169                     */ \
    1093                     if (!fSkipSeg) \
     1170                    if (   pModMachO->Hdr.filetype != MH_OBJECT \
     1171                        && (cSectionsLeft == 0 || !(pFirstSect->flags & S_ATTR_DEBUG)) \
     1172                        && kHlpStrComp(pSrcSeg->segname, "__DWARF") ) \
    10941173                    { \
    1095                         pDstSeg->pvUser = NULL; \
    1096                         pDstSeg->pchName = pbStringPool; \
    1097                         pDstSeg->cchName = (KU32)kHlpStrNLen(&pSrcSeg->segname[0], sizeof(pSrcSeg->segname)); \
    1098                         kHlpMemCopy(pbStringPool, &pSrcSeg->segname[0], pDstSeg->cchName); \
    1099                         pbStringPool += pDstSeg->cchName; \
    1100                         *pbStringPool++ = '\0'; \
    1101                         pDstSeg->SelFlat = 0; \
    1102                         pDstSeg->Sel16bit = 0; \
    1103                         pDstSeg->fFlags = 0; \
    1104                         pDstSeg->enmProt = KPROT_EXECUTE_WRITECOPY; /** @todo fixme! */ \
    1105                         pDstSeg->cb = pSrcSeg->vmsize; \
    1106                         pDstSeg->Alignment = 1; /* updated while parsing sections. */ \
    1107                         pDstSeg->LinkAddress = pSrcSeg->vmaddr; \
    1108                         if (pSrcSeg->filesize > 0) \
    1109                         { \
    1110                             pDstSeg->offFile = pSrcSeg->fileoff + pModMachO->offImage; \
    1111                             pDstSeg->cbFile  = pSrcSeg->filesize; \
    1112                         } \
    1113                         else \
    1114                         { \
    1115                             pDstSeg->offFile = -1; \
    1116                             pDstSeg->cbFile  = -1; \
    1117                         } \
    1118                         pDstSeg->RVA = pSrcSeg->vmaddr - pModMachO->LinkAddress; \
    1119                         pDstSeg->cbMapped = 0; \
    1120                         pDstSeg->MapAddress = 0; \
    1121                         \
    1122                         pSegExtra->iOrgSegNo = pSegExtra - &pModMachO->aSegments[0]; \
    1123                         pSegExtra->cSections = 0; \
    1124                         pSegExtra->paSections = pSectExtra; \
     1174                        NEW_SEGMENT(a_cBits, pSrcSeg->segname, K_FALSE /*a_fObjFile*/, 0 /*a_achName2*/, \
     1175                                    pSrcSeg->vmaddr, pSrcSeg->vmsize, \
     1176                                    pSrcSeg->filesize != 0, pSrcSeg->fileoff, pSrcSeg->filesize); \
     1177                        fAddSegOuter = K_TRUE; \
    11251178                    } \
    11261179                    \
     
    11301183                    while (cSectionsLeft-- > 0) \
    11311184                    { \
     1185                        /* New segment if object file. */ \
     1186                        KBOOL fAddSegInner = K_FALSE; \
     1187                        if (   pModMachO->Hdr.filetype == MH_OBJECT \
     1188                            && !(pSect->flags & S_ATTR_DEBUG) \
     1189                            && kHlpStrComp(pSrcSeg->segname, "__DWARF") ) \
     1190                        { \
     1191                            kHlpAssert(!fAddSegOuter); \
     1192                            NEW_SEGMENT(a_cBits, pSect->segname, K_TRUE /*a_fObjFile*/, pSect->sectname, \
     1193                                        pSect->addr, pSect->size, \
     1194                                        pSect->offset != 0, pSect->offset, pSect->size); \
     1195                            fAddSegInner = K_TRUE; \
     1196                        } \
     1197                        \
    11321198                        /* Section data extract. */ \
    11331199                        pSectExtra->cb = pSect->size; \
     
    11491215                        \
    11501216                        /* Update the segment alignment, if we're not skipping it. */ \
    1151                         if (!fSkipSeg && pDstSeg->Alignment < ((KLDRADDR)1 << pSect->align)) \
     1217                        if (   (fAddSegOuter || fAddSegInner) \
     1218                            && pDstSeg->Alignment < ((KLDRADDR)1 << pSect->align)) \
    11521219                            pDstSeg->Alignment = (KLDRADDR)1 << pSect->align; \
    11531220                        \
    1154                         /* Next section. */ \
     1221                        /* Next section, and if object file next segment. */ \
    11551222                        pSectExtra++; \
    11561223                        pSect++; \
     1224                        if (fAddSegInner) \
     1225                            CLOSE_SEGMENT(); \
    11571226                    } \
    11581227                    \
    11591228                    /* Close the segment and advance. */ \
    1160                     if (!fSkipSeg) \
    1161                     { \
    1162                         pSegExtra->cSections = pSectExtra - pSegExtra->paSections; \
    1163                         pSegExtra++; \
    1164                         pDstSeg++; \
    1165                     } \
     1229                    if (fAddSegOuter) \
     1230                        CLOSE_SEGMENT(); \
    11661231                } while (0) /* ADD_SEGMENT_AND_ITS_SECTIONS */
    11671232
Note: See TracChangeset for help on using the changeset viewer.