VirtualBox

Changeset 2278 in kBuild


Ignore:
Timestamp:
Feb 24, 2009 2:19:35 AM (16 years ago)
Author:
bird
Message:

kObjDep: HLL source file table parser.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/kmk/kmkbuiltin/kDepObj.c

    r2267 r2278  
    3434#include <errno.h>
    3535#include <ctype.h>
     36#include <stdarg.h>
    3637#ifdef HAVE_ALLOCA_H
    3738# include <alloca.h>
     
    6667#define KDEPOMF_THEADR          0x80
    6768#define KDEPOMF_LHEADR          0x82
    68 #define KDEPOMF_COMMENT         0x88
    69 #define KDEPOMF_CMTCLS_DEPENDENCY  0xe9
     69#define KDEPOMF_COMENT          0x88
     70#define KDEPOMF_CMTCLS_DEPENDENCY   0xe9
     71#define KDEPOMF_CMTCLS_DBGTYPE      0xa1
     72#define KDEPOMF_LINNUM          0x94
     73#define KDEPOMF_LINNUM32        0x95
    7074/** @} */
    7175
     
    170174/** the executable name. */
    171175static const char *argv0 = "";
     176static const char *g_pszFile = NULL;
     177
     178
     179/**
     180 * Prints an error message.
     181 *
     182 * @returns rc.
     183 * @param   rc          The return code, for making one line return statements.
     184 * @param   pszFormat   The message format string.
     185 * @param   ...         Format arguments.
     186 * @todo    Promote this to kDep.c.
     187 */
     188static int kDepErr(int rc, const char *pszFormat, ...)
     189{
     190    va_list va;
     191    const char *psz;
     192    const char *pszName = argv0;
     193
     194    fflush(stdout);
     195
     196    /* The message prefix. */
     197    while ((psz = strpbrk(pszName, "/\\:")) != NULL)
     198        pszName = psz + 1;
     199
     200    if (g_pszFile)
     201        fprintf(stderr, "%s: %s: error: ", pszName, g_pszFile);
     202    else
     203        fprintf(stderr, "%s: error: ", pszName);
     204
     205    /* The message. */
     206    va_start(va, pszFormat);
     207    vfprintf(stderr, pszFormat, va);
     208    va_end(va);
     209
     210    return rc;
     211}
     212
     213
     214/**
     215 * Gets an index from the data.
     216 *
     217 * @returns The index, KU16_MAX on buffer underflow.
     218 * @param   puData      The current data stream position (in/out).
     219 * @param   pcbLeft     Number of bytes left (in/out).
     220 */
     221static KU16 kDepObjOMFGetIndex(KPCUINT *puData, KU16 *pcbLeft)
     222{
     223    KU16 u16;
     224
     225    if (*pcbLeft >= 1 && *pcbLeft != KU16_MAX)
     226    {
     227        *pcbLeft -= 1;
     228        u16 = *puData->pb++;
     229        if (u16 & KU16_C(0x80))
     230        {
     231            if (*pcbLeft >= 1)
     232            {
     233                *pcbLeft -= 1;
     234                u16 = ((u16 & KU16_C(0x7f)) << 8) | *puData->pb++;
     235            }
     236            else
     237                u16 = KU16_MAX;
     238        }
     239    }
     240    else
     241        u16 = KU16_MAX;
     242    return u16;
     243}
    172244
    173245
     
    175247 * Parses the OMF file.
    176248 *
    177  * @returns 0 on success, 1 on failure.
     249 * @returns 0 on success, 1 on failure, 2 if no dependencies was found.
    178250 * @param   pbFile      The start of the file.
    179251 * @param   cbFile      The file size.
     
    181253int kDepObjOMFParse(const KU8 *pbFile, KSIZE cbFile)
    182254{
    183     PCKDEPOMFHDR    pHdr = (PCKDEPOMFHDR)pbFile;
    184     KSIZE           cbLeft = cbFile;
    185 
     255    PCKDEPOMFHDR    pHdr        = (PCKDEPOMFHDR)pbFile;
     256    KSIZE           cbLeft      = cbFile;
     257    char            uDbgType    = 0; /* H or C */
     258    KU8             uDbgVer     = KU8_MAX;
     259    KU32            iSrc        = 0;
     260    KU32            iMaybeSrc   = 0;
     261    KU8             uLinNumType = KU8_MAX;
     262    KU16            cLinNums    = 0;
     263    KU32            cLinFiles   = 0;
     264    KU32            iLinFile    = 0;
    186265
    187266    /*
     
    191270           && cbLeft >= pHdr->cbRec + sizeof(*pHdr))
    192271    {
     272        KPCUINT     uData;
     273        uData.pv = pHdr + 1;
     274
    193275        /* process selected record types. */
    194276        dprintf(("%#07x: %#04x %#05x\n", (const KU8*)pHdr - pbFile, pHdr->bType, pHdr->cbRec));
     
    205287                PCKDEPOMFTHEADR pTHeadr = (PCKDEPOMFTHEADR)pHdr;
    206288                if (1 + pTHeadr->Name.cch + 1 != pHdr->cbRec)
     289                    return kDepErr(1, "%#07x - Bad %cHEADR record, length mismatch.\n",
     290                                   (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L');
     291                if (    (   pTHeadr->Name.cch > 2
     292                         && pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == '.'
     293                         && (   pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'o'
     294                             || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'O'))
     295                    ||  (   pTHeadr->Name.cch > 4
     296                         && pTHeadr->Name.ach[pTHeadr->Name.cch - 4] == '.'
     297                         && (   pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'o'
     298                             || pTHeadr->Name.ach[pTHeadr->Name.cch - 3] == 'O')
     299                         && (   pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'b'
     300                             || pTHeadr->Name.ach[pTHeadr->Name.cch - 2] == 'B')
     301                         && (   pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'j'
     302                             || pTHeadr->Name.ach[pTHeadr->Name.cch - 1] == 'J'))
     303                   )
     304                    dprintf(("%cHEADR: %.*s [ignored]\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach));
     305                else
    207306                {
    208                     fprintf(stderr, "%s: error: %#07x - Bad %cHEADR record, length mismatch.\n",
    209                             argv0, (const KU8*)pHdr - pbFile, pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L');
    210                     return 1;
     307                    dprintf(("%cHEADR: %.*s\n", pHdr->bType == KDEPOMF_THEADR ? 'T' : 'L', pTHeadr->Name.cch, pTHeadr->Name.ach));
     308                    depAdd(pTHeadr->Name.ach, pTHeadr->Name.cch);
     309                    iMaybeSrc++;
    211310                }
    212                 depAdd(pTHeadr->Name.ach, pTHeadr->Name.cch);
     311                uLinNumType = KU8_MAX;
    213312                break;
    214313            }
    215314
    216             case KDEPOMF_COMMENT:
    217                 if (pHdr->cbRec < 2)
    218                 {
    219                     fprintf(stderr, "%s: error: %#07x - Bad COMMENT record, too small.\n",
    220                             argv0, (const KU8*)pHdr - pbFile);
    221                     return 1;
    222                 }
    223                 if (((const KU8 *)(pHdr+1))[0] & 0x3f)
    224                 {
    225                     fprintf(stderr, "%s: error: %#07x - Bad COMMENT record, reserved flags set.\n",
    226                             argv0, (const KU8*)pHdr - pbFile);
    227                     return 1;
    228                 }
    229                 switch (((const KU8 *)(pHdr+1))[1])
     315            case KDEPOMF_COMENT:
     316            {
     317                KU8 uClass;
     318
     319                if (pHdr->cbRec < 2 + 1)
     320                    return kDepErr(1, "%#07x - Bad COMMENT record, too small.\n", (const KU8*)pHdr - pbFile);
     321                if (uData.pb[0] & 0x3f)
     322                    return kDepErr(1, "%#07x - Bad COMMENT record, reserved flags set.\n", (const KU8*)pHdr - pbFile);
     323                uClass = uData.pb[1];
     324                uData.pb += 2;
     325                switch (uClass)
    230326                {
    231327                    /*
     
    241337                            if (pHdr->cbRec == 2 + 1)
    242338                                return 0;
    243 
    244                             fprintf(stderr, "%s: error: %#07x - Bad DEPENDENCY FILE record, length mismatch. (%d/%d)\n",
    245                                     argv0, (const KU8*)pHdr - pbFile,
    246                                     K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1,
    247                                     pHdr->cbRec + sizeof(*pHdr));
    248                             return 1;
    249 
     339                            return kDepErr(1, "%#07lx - Bad DEPENDENCY FILE record, length mismatch. (%u/%u)\n",
     340                                           (long)((const KU8 *)pHdr - pbFile),
     341                                           K_OFFSETOF(KDEPOMFDEPFILE, Name.ach[pDep->Name.cch]) + 1,
     342                                           (unsigned)(pHdr->cbRec + sizeof(*pHdr)));
    250343                        }
    251344                        depAdd(pDep->Name.ach, pDep->Name.cch);
     345                        iSrc++;
    252346                        break;
    253347                    }
    254348
    255                     /** @todo Check for class A1 and pick up the debug info type (HL/CV(/DX)). */
     349                    /*
     350                     * Pick up the debug type so we can parse the LINNUM records.
     351                     */
     352                    case KDEPOMF_CMTCLS_DBGTYPE:
     353                        if (pHdr->cbRec < 2 + 3 + 1)
     354                            break; /* ignore, Borland used this for something else apparently. */
     355                        if (    !(uData.pb[1] == 'C' && uData.pb[2] == 'V')
     356                            &&  !(uData.pb[1] == 'H' && uData.pb[2] == 'L'))
     357                        {
     358                            dprintf(("Unknown debug type: %c%c (%u)\n", uData.pb[1], uData.pb[2], uData.pb[0]));
     359                            break;
     360                        }
     361                        uDbgType = uData.pb[1];
     362                        uDbgVer  = uData.pb[0];
     363                        dprintf(("Debug Type %s ver %u\n", uDbgType == 'H' ? "HLL" : "CodeView", uDbgVer));
     364                        break;
     365
    256366                }
     367                break; /* COMENT */
     368            }
     369
     370            /*
     371             * LINNUM + THEADR == sigar.
     372             */
     373            case KDEPOMF_LINNUM:
     374                if (uDbgType == 'C')
     375                    iMaybeSrc |= KU32_C(0x80000000);
     376                dprintf(("LINNUM:\n"));
    257377                break;
    258             /** @todo add support for HLL line number segments and stuff. */
     378
     379            /*
     380             * The HLL v4 and v6 file names table will include all files when present, which
     381             * is perfect for generating dependencies.
     382             */
     383            case KDEPOMF_LINNUM32:
     384                if (    uDbgType == 'H'
     385                    &&  uDbgVer >= 3
     386                    &&  uDbgVer <= 6)
     387                {
     388                    /* skip two indexes (group & segment) */
     389                    KU16 cbRecLeft = pHdr->cbRec - 1;
     390                    KU16 uGrp = kDepObjOMFGetIndex(&uData, &cbRecLeft);
     391                    KU16 uSeg = kDepObjOMFGetIndex(&uData, &cbRecLeft);
     392                    if (uSeg == KU16_MAX)
     393                        return kDepErr(1, "%#07lx - Bad LINNUM32 record\n", (long)((const KU8 *)pHdr - pbFile));
     394
     395                    if (uLinNumType == KU8_MAX)
     396                    {
     397                        static const char * const s_apsz[5] =
     398                        {
     399                            "source file", "listing file", "source & listing file", "file names table", "path table"
     400                        };
     401                        KU16 uLine;
     402                        KU8  uReserved;
     403                        KU16 uSeg2;
     404                        KU32 cbLinNames;
     405
     406                        if (cbRecLeft < 2+1+1+2+2+4)
     407                            return kDepErr(1, "%#07lx - Bad LINNUM32 record, too short\n", (long)((const KU8 *)pHdr - pbFile));
     408                        cbRecLeft  -= 2+1+1+2+2+4;
     409                        uLine       = *uData.pu16++;
     410                        uLinNumType = *uData.pu8++;
     411                        uReserved   = *uData.pu8++;
     412                        cLinNums    = *uData.pu16++;
     413                        uSeg2       = *uData.pu16++;
     414                        cbLinNames  = *uData.pu32++;
     415
     416                        dprintf(("LINNUM32: uGrp=%#x uSeg=%#x uSeg2=%#x uLine=%#x (MBZ) uReserved=%#x\n",
     417                                 uGrp, uSeg, uSeg2, uLine, uReserved));
     418                        dprintf(("LINNUM32: cLinNums=%#x (%u) cbLinNames=%#x (%u) uLinNumType=%#x (%s)\n",
     419                                 cLinNums, cLinNums, cbLinNames, cbLinNames, uLinNumType,
     420                                 uLinNumType < K_ELEMENTS(s_apsz) ? s_apsz[uLinNumType] : "??"));
     421                        if (uLine != 0)
     422                            return kDepErr(1, "%#07lx - Bad LINNUM32 record, line %#x (MBZ)\n", (long)((const KU8 *)pHdr - pbFile), uLine);
     423                        cLinFiles = iLinFile = KU32_MAX;
     424                        if (   uLinNumType == 3 /* file names table */
     425                            || uLinNumType == 4 /* path table */)
     426                            cLinNums = 0; /* no line numbers */
     427                        else if (uLinNumType > 4)
     428                            return kDepErr(1, "%#07lx - Bad LINNUM32 record, type %#x unknown\n", (long)((const KU8 *)pHdr - pbFile), uLinNumType);
     429                    }
     430                    else
     431                        dprintf(("LINNUM32: uGrp=%#x uSeg=%#x\n", uGrp, uSeg));
     432
     433
     434                    /* Skip file numbers (we parse them to follow the stream correctly). */
     435                    if (uLinNumType != 3 && uLinNumType != 4)
     436                    {
     437                        static const unsigned s_acbTypes[3] = { 2+2+4, 4+4+4, 2+2+4+4+4 };
     438                        unsigned              cbEntry = s_acbTypes[uLinNumType];
     439
     440                        while (cLinNums && cbRecLeft)
     441                        {
     442                            if (cbRecLeft < cbEntry)
     443                                return kDepErr(1, "%#07lx - Bad LINNUM32 record, incomplete line entry\n", (long)((const KU8 *)pHdr - pbFile));
     444
     445                            switch (uLinNumType)
     446                            {
     447                                case 0: /* source file */
     448                                    dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI " at %#010" KX32_PRI "\n",
     449                                             uData.pu16[0], uData.pu16[1], uData.pu32[1]));
     450                                    break;
     451                                case 1: /* listing file */
     452                                    dprintf((" Line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n",
     453                                             uData.pu32[0], uData.pu32[1], uData.pu32[2]));
     454                                    break;
     455                                case 2: /* source & listing file */
     456                                    dprintf((" Line %6" KU16_PRI " of file %2" KU16_PRI ", listning line %6" KU32_PRI ", statement %6" KU32_PRI " at %#010" KX32_PRI "\n",
     457                                             uData.pu16[0], uData.pu16[1], uData.pu32[1], uData.pu32[2], uData.pu32[3]));
     458                                    break;
     459                            }
     460                            uData.pb += cbEntry;
     461                            cbRecLeft -= cbEntry;
     462                            cLinNums--;
     463                        }
     464
     465                        /* If at end of the announced line number entiries, we may find a file names table
     466                           here (who is actually emitting this?). */
     467                        if (!cLinNums)
     468                        {
     469                            uLinNumType = cbRecLeft > 0 ? 3 : KU8_MAX;
     470                            dprintf(("End-of-line-numbers; uLinNumType=%u cbRecLeft=%#x\n", uLinNumType, cbRecLeft));
     471                        }
     472                    }
     473
     474                    if (uLinNumType == 3 || uLinNumType == 4)
     475                    {
     476                        /* Read the file/path table header (first time only). */
     477                        if (cLinFiles == KU32_MAX && iLinFile == KU32_MAX)
     478                        {
     479                            KU32 iFirstCol;
     480                            KU32 cCols;
     481
     482                            if (cbRecLeft < 4+4+4)
     483                                return kDepErr(1, "%#07lx - Bad LINNUM32 record, incomplete file/path table header\n", (long)((const KU8 *)pHdr - pbFile));
     484                            cbRecLeft -= 4+4+4;
     485
     486                            iFirstCol = *uData.pu32++;
     487                            cCols     = *uData.pu32++;
     488                            cLinFiles = *uData.pu32++;
     489                            dprintf(("%s table header: cLinFiles=%#" KX32_PRI " (%" KU32_PRI ") iFirstCol=%" KU32_PRI " cCols=%" KU32_PRI"\n",
     490                                     uLinNumType == 3 ? "file names" : "path", cLinFiles, cLinFiles, iFirstCol, cCols));
     491                            if (cLinFiles == KU32_MAX)
     492                                return kDepErr(1, "%#07lx - Bad LINNUM32 record, too many file/path table entries.\n", (long)((const KU8 *)pHdr - pbFile));
     493                            iLinFile = 0;
     494                        }
     495
     496                        /* Parse the file names / path table. */
     497                        while (iLinFile < cLinFiles && cbRecLeft)
     498                        {
     499                            int cbName = *uData.pb++;
     500                            if (cbRecLeft < 1 + cbName)
     501                                return kDepErr(1, "%#07lx - Bad LINNUM32 record, file/path table entry too long.\n", (long)((const KU8 *)pHdr - pbFile));
     502                            iLinFile++;
     503                            dprintf(("#%" KU32_PRI": %.*s\n", iLinFile, cbName, uData.pch));
     504                            if (uLinNumType == 3)
     505                            {
     506                                depAdd(uData.pch, cbName);
     507                                iSrc++;
     508                            }
     509                            cbRecLeft -= 1 + cbName;
     510                            uData.pb += cbName;
     511                        }
     512
     513                        /* The end? */
     514                        if (iLinFile == cLinFiles)
     515                        {
     516                            uLinNumType = KU8_MAX;
     517                            dprintf(("End-of-file/path-table; cbRecLeft=%#x\n", cbRecLeft));
     518                        }
     519                    }
     520                }
     521                else
     522                    dprintf(("LINNUM32: Unknown or unsupported format\n"));
     523                break;
     524
    259525        }
    260526
     
    265531
    266532    if (cbLeft)
    267     {
    268         fprintf(stderr, "%s: error: %#07x - Unexpected EOF. cbLeft=%#x\n",
    269                 argv0, (const KU8*)pHdr - pbFile, cbLeft);
    270         return 1;
    271     }
     533        return kDepErr(1, "%#07x - Unexpected EOF. cbLeft=%#x\n", (const KU8*)pHdr - pbFile, cbLeft);
     534
     535    if (iSrc == 0 && iMaybeSrc <= 1)
     536    {
     537        dprintf(("kDepObjOMFParse: No cylindrical smoking thing: iSrc=0 iMaybeSrc=%#" KX32_PRI"\n", iMaybeSrc));
     538        return 2;
     539    }
     540    dprintf(("kDepObjOMFParse: iSrc=%" KU32_PRI " iMaybeSrc=%#" KX32_PRI "\n", iSrc, iMaybeSrc));
    272541    return 0;
    273542}
     
    303572 * Parses a CodeView 8 symbol section.
    304573 *
    305  * @returns 0 on success, 1 on failure.
     574 * @returns 0 on success, 1 on failure, 2 if no dependencies was found.
    306575 * @param   pbSyms      Pointer to the start of the symbol section.
    307576 * @param   cbSyms      Size of the symbol section.
     
    364633                dprintf(("%06" KX32_PRI " %06" KX32_PRI ": String table\n", off, cbData));
    365634                if (pchStrTab)
    366                     fprintf(stderr, "%s: warning: Found yet another string table!\n");
     635                    fprintf(stderr, "%s: warning: Found yet another string table!\n", argv0);
    367636                pchStrTab = uData.pch;
    368637                cbStrTab = cbData;
     
    373642                dprintf(("%06" KX32_PRI " %06" KX32_PRI ": Source files\n", off, cbData));
    374643                if (uSrcFiles.pb)
    375                     fprintf(stderr, "%s: warning: Found yet another source files table!\n");
     644                    fprintf(stderr, "%s: warning: Found yet another source files table!\n", argv0);
    376645                uSrcFiles = uData;
    377646                cbSrcFiles = cbData;
     
    401670    if (!pchStrTab || !uSrcFiles.pv)
    402671    {
    403         dprintf(("No cylindrical smoking thing: pchStrTab=%p uSrcFiles.pv=%p\n", pchStrTab, uSrcFiles.pv));
     672        dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: pchStrTab=%p uSrcFiles.pv=%p\n", pchStrTab, uSrcFiles.pv));
    404673        return 2;
    405674    }
     
    471740    if (iSrc == 0)
    472741    {
    473         dprintf(("No cylindrical smoking thing: iSrc=0\n"));
     742        dprintf(("kDepObjCOFFParseCV8SymbolSection: No cylindrical smoking thing: iSrc=0\n"));
    474743        return 2;
    475744    }
    476     dprintf(("iSrc=%" KU32_PRI "\n", iSrc));
     745    dprintf(("kDepObjCOFFParseCV8SymbolSection: iSrc=%" KU32_PRI "\n", iSrc));
    477746    return 0;
    478747}
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette