Ignore:
Timestamp:
Feb 7, 2007, 8:07:16 AM (19 years ago)
Author:
bird
Message:

Completed kldrModMachOParseLoadCommands and kldrModMachOSize. Added an kLdrErrStr API.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/kLdr/kLdrModMachO.c

    r2954 r2955  
    9999    /** The link address. */
    100100    KLDRADDR                LinkAddress;
     101    /** The size of the mapped image. */
     102    KLDRADDR                cbImage;
     103    /** When set the load commands will be used when mapping / loading the bits.
     104     * This is the case when segments are made up of sections that doesn't have
     105     * proper ordering and/or aligning in the file alignment. */
     106    int                     fMapUsingLoadCommands;
    101107
    102108    /** Pointer to the load commands. (endian converted) */
     
    353359        pModMachO->Hdr.reserved = 0;
    354360    pModMachO->LinkAddress = 0;
     361    pModMachO->cbImage = 0;
     362    pModMachO->fMapUsingLoadCommands = 0;
    355363    pModMachO->offSymbols = 0;
    356364    pModMachO->cSymbols = 0;
     
    408416    uint32_t cbLeft = pHdr->sizeofcmds;
    409417    uint8_t *pb = pbLoadCommands;
     418    int      cSegmentCommands = 0;
    410419    int      fConvertEndian = pHdr->magic == IMAGE_MACHO32_SIGNATURE_OE
    411420                           || pHdr->magic == IMAGE_MACHO64_SIGNATURE_OE;
     
    447456                if (u.pLoadCmd->cmdsize < sizeof(segment_command_32_t))
    448457                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     458                if (    pHdr->magic != IMAGE_MACHO32_SIGNATURE_OE
     459                    &&  pHdr->magic != IMAGE_MACHO32_SIGNATURE)
     460                    return KLDR_ERR_MACHO_BIT_MIX;
    449461                if (fConvertEndian)
    450462                {
     
    473485                if (u.pSeg32->nsects * sizeof(section_32_t) > u.pLoadCmd->cmdsize - sizeof(segment_command_32_t))
    474486                    return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
     487                if (    pHdr->filetype == MH_OBJECT
     488                    &&  cSegmentCommands > 0)
     489                    return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
     490                cSegmentCommands++;
    475491
    476492                /*
     
    566582
    567583                            /* a new segment? */
    568                             if (    pSect == pFirstSect
     584                            if (    !cSegments
    569585                                ||  kLdrHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
    570586                            {
     
    580596                                /* ok. count it and the string. */
    581597                                cSegments++;
    582                                 cbStringPool += kLdrHlpStrLen(pSect->segname) + 1;
     598                                cbStringPool += kLdrHlpStrNLen(&pSect->segname[0], sizeof(pSect->segname)) + 1;
    583599                            }
    584600                            break;
     
    595611            }
    596612
    597             case LC_SEGMENT_64:
    598                 /* copy 32-bit code */
     613            /*case LC_SEGMENT_64:
     614                 copy 32-bit code
    599615                break;
     616            */
    600617
    601618            case LC_SYMTAB:
     
    656673                break;
    657674
     675            case LC_SEGMENT_64:
    658676            case LC_LOADFVMLIB:
    659677            case LC_IDFVMLIB:
     
    684702    }
    685703
    686     /* be strict (for now). */
     704    /* be strict. */
    687705    if (cbLeft)
    688706        return KLDR_ERR_MACHO_BAD_LOAD_COMMAND;
    689707
     708    switch (pHdr->filetype)
     709    {
     710        case MH_OBJECT:
     711            if (!cSegments)
     712                return KLDR_ERR_MACHO_BAD_OBJECT_FILE;
     713            break;
     714    }
     715
    690716    *pcSegments = cSegments;
    691     *pcbStringPool = cLeft;
     717    *pcbStringPool = cbStringPool;
    692718
    693719    return 0;
     
    708734static int  kldrModMachOParseLoadCommands(PKLDRMODMACHO pModMachO, char *pbStringPool, uint32_t cbStringPool)
    709735{
     736    union
     737    {
     738        const uint8_t              *pb;
     739        const load_command_t       *pLoadCmd;
     740        const segment_command_32_t *pSeg32;
     741        const segment_command_64_t *pSeg64;
     742        const symtab_command_t     *pSymTab;
     743    } u;
     744    uint32_t cLeft = pModMachO->Hdr.ncmds;
     745    uint32_t cbLeft = pModMachO->Hdr.sizeofcmds;
     746    const uint8_t *pb = pModMachO->pbLoadCommands;
     747    int fFirstSegment = 1;
     748    PKLDRSEG pSeg = &pModMachO->pMod->aSegments[0];
     749    const uint32_t cSegments = pModMachO->pMod->cSegments;
     750    uint32_t i;
     751
     752    while (cLeft-- > 0)
     753    {
     754        u.pb = pb;
     755        cbLeft -= u.pLoadCmd->cmdsize;
     756        pb += u.pLoadCmd->cmdsize;
     757
     758        /*
     759         * Convert endian if needed, parse and validate the command.
     760         */
     761        switch (u.pLoadCmd->cmd)
     762        {
     763            case LC_SEGMENT_32:
     764            {
     765                section_32_t *pSect;
     766                section_32_t *pFirstSect;
     767                uint32_t cSectionsLeft;
     768
     769                pModMachO->LinkAddress = u.pSeg32->vmaddr;
     770
     771                /*
     772                 * convert, validate and parse the sections.
     773                 */
     774                cSectionsLeft = u.pSeg32->nsects;
     775                pFirstSect = pSect = (section_32_t *)(u.pSeg32 + 1);
     776                while (cSectionsLeft-- > 0)
     777                {
     778                    switch (pModMachO->Hdr.filetype)
     779                    {
     780                        case MH_OBJECT:
     781                        {
     782                            /* Don't load debug symbols. (test this) */
     783                            if (pSect->flags & S_ATTR_DEBUG)
     784                                break;
     785
     786                            if (    fFirstSegment
     787                                ||  kLdrHlpStrNComp(pSect->segname, (pSect - 1)->segname, sizeof(pSect->segname)))
     788                            {
     789                                /* new segment. */
     790                                pSeg->pvUser = NULL;
     791                                pSeg->pchName = pbStringPool;
     792                                pSeg->cchName = (uint32_t)kLdrHlpStrNLen(&pSect->segname[0], sizeof(pSect->sectname));
     793                                kLdrHlpMemCopy(pbStringPool, &pSect->segname[0], pSeg->cchName);
     794                                pbStringPool += pSeg->cchName;
     795                                *pbStringPool++ = '\0';
     796                                pSeg->SelFlat = 0;
     797                                pSeg->Sel16bit = 0;
     798                                pSeg->fFlags = 0;
     799                                pSeg->enmProt = KLDRPROT_EXECUTE_WRITECOPY; /** @todo fixme! */
     800                                pSeg->cb = pSect->size;
     801                                pSeg->Alignment = (1 << pSect->align);
     802                                pSeg->LinkAddress = pSect->addr;
     803                                pSeg->offFile = pSect->offset ? pSect->offset : -1;
     804                                pSeg->cbFile  = pSect->offset ? pSect->size : -1;
     805                                pSeg->RVA = pSect->addr - pModMachO->LinkAddress;
     806                                pSeg->cbMapped = 0;
     807                                pSeg->MapAddress = 0;
     808
     809                                pSeg++;
     810                                fFirstSegment = 0;
     811                            }
     812                            else if (!fFirstSegment)
     813                            {
     814                                /* update exiting segment */
     815                                if (pSeg[-1].Alignment < (1 << pSect->align))
     816                                    pSeg[-1].Alignment = (1 << pSect->align);
     817                                if (pSect->addr < pSeg[-1].LinkAddress)
     818                                    return KLDR_ERR_MACHO_BAD_SECTION; /** @todo move up! */
     819
     820                                if (    pSect->offset
     821                                    &&  pSeg[-1].cbFile == pSeg[-1].cb)
     822                                {
     823                                    if (    pSeg[-1].offFile + pSeg[-1].cbFile == pSect->offset
     824                                        &&  pSeg[-1].cbFile == pSect->addr - pSeg[-1].LinkAddress)
     825                                        pSeg[-1].cbFile = (off_t)(pSect->addr - pSeg[-1].LinkAddress) + pSect->size;
     826                                    else
     827                                    {
     828                                        pSeg[-1].cbFile = pSeg[-1].offFile = -1;
     829                                        pModMachO->fMapUsingLoadCommands = 1;
     830                                    }
     831                                }
     832                                pSeg[-1].cb = pSect->addr - pSeg[-1].LinkAddress + pSect->size;
     833
     834                                /** @todo update the protection... */
     835                            }
     836                            break;
     837                        }
     838
     839                        default:
     840                            return KLDR_ERR_INVALID_PARAMETER;
     841                    }
     842
     843                    /* next */
     844                    pSect++;
     845                }
     846                break;
     847            }
     848
     849            default:
     850                break;
     851        }
     852    }
     853
     854    /*
     855     * Adjust mapping addresses calculating the image size.
     856     */
     857    pSeg = &pModMachO->pMod->aSegments[0];
     858    switch (pModMachO->Hdr.filetype)
     859    {
     860        case MH_OBJECT:
     861        {
     862            KLDRADDR cb1;
     863            size_t cb2;
     864
     865            for (i = 0; i < cSegments - 1; i++)
     866            {
     867                cb1 = pSeg[i + 1].LinkAddress - pSeg[i].LinkAddress;
     868                cb2 = (size_t)cb1;
     869                pSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(size_t)0;
     870            }
     871            cb1 = KLDR_ALIGN_ADDR(pSeg[i].cb, pSeg[i].Alignment);
     872            cb2 = (size_t)cb1;
     873            pSeg[i].cbMapped = cb2 == cb1 ? cb2 : ~(size_t)0;
     874
     875            pModMachO->cbImage = pSeg[i].RVA + cb1;
     876            break;
     877        }
     878    }
     879
    710880    return 0;
    711881}
     
    19782148static KLDRADDR kldrModMachOSize(PKLDRMOD pMod)
    19792149{
    1980 #if 0
    19812150    PKLDRMODMACHO pModMachO = (PKLDRMODMACHO)pMod->pvData;
    1982     return pModMachO->Hdrs.OptionalHeader.SizeOfImage;
    1983 #else
    1984     return 0;
    1985 #endif
     2151    return pModMachO->cbImage;
    19862152}
    19872153
Note: See TracChangeset for help on using the changeset viewer.