VirtualBox

Changeset 60265 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Mar 31, 2016 12:48:14 AM (9 years ago)
Author:
vboxsync
svn:sync-xref-src-repo-rev:
106306
Message:

bs3kit: line number improvments.

Location:
trunk/src/VBox/ValidationKit/bootsectors
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/bootsectors/Config.kmk

    r60231 r60265  
    9090TOOL_VBoxNasm_ASFLAGS ?= $(TOOL_NASM_ASFLAGS)
    9191TOOL_VBoxNasm_COMPILE_AS_OUTPUT = $(outbase).lst
    92 TOOL_VBoxNasm_COMPILE_AS_DEPEND =
     92TOOL_VBoxNasm_COMPILE_AS_DEPEND = $(VBoxBs3ObjConverter_1_TARGET)
    9393TOOL_VBoxNasm_COMPILE_AS_DEPORD =
    9494define TOOL_VBoxNasm_COMPILE_AS_CMDS
     
    9898                -o $(obj)\
    9999                $(abspath $(source))
     100        $(QUIET)$(VBoxBs3ObjConverter_1_TARGET) "$(obj)"
    100101        $(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE) -wo $(dep) -- $(TOOL_VBoxNasm_AS)\
    101102                $(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\
     
    367368# Debug info format depends on what we use for 64-bit.
    368369if1of ($(KBUILD_HOST), win)
    369  BS3_OW_DBG_OPT   = -hc
     370 BS3_OW_DBG_OPT   = -hc -d1+
     371 #BS3_OW_DBG_OPT   = -hd -d1+
    370372 BS3_OW_DBG_LDOPT = codeview
    371373else
    372  BS3_OW_DBG_OPT   = -hd
     374 BS3_OW_DBG_OPT   = -hd -d1+
    373375 BS3_OW_DBG_LDOPT = dwarf
    374376endif
     
    399401# Note! Using -d1 as -d1+ and -d2 causes suboptimal code to be generated (strlen
    400402#       reloading string pointer argument all the time).
     403#       Update! -d1+ is required for line number information in code living in include
     404#               files and any DWARF stuff at all.  So, we'll ignore poor code quality.
    401405# Note! Optimization options should come after debug stuff as -d2 for instance
    402406#       disables all optimziations.
     
    458462TEMPLATE_VBoxBS3KitImg_CXXTOOL      = Bs3Ow16
    459463TEMPLATE_VBoxBS3KitImg_CFLAGS       = \
    460         -nt=BS3TEXT16 -nd=BS3DATA16 -nc=BS3CLASS16CODE -ecc -q -0 -wx -zl -zdp -zu -mc $(BS3_OW_DBG_OPT) -d1 -s -oa -ob -of -oi -ol -or -os -d+
     464        -nt=BS3TEXT16 -nd=BS3DATA16 -nc=BS3CLASS16CODE -ecc -q -0 -wx -zl -zdp -zu -mc $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
    461465TEMPLATE_VBoxBS3KitImg_CXXFLAGS     = \
    462         -nt=BS3TEXT16 -nd=BS3DATA16 -nc=BS3CLASS16CODE -ecc -q -0 -wx -zl -zdp -zu -mc $(BS3_OW_DBG_OPT) -d1 -s -oa -ob -of -oi -ol -or -os -d+
     466        -nt=BS3TEXT16 -nd=BS3DATA16 -nc=BS3CLASS16CODE -ecc -q -0 -wx -zl -zdp -zu -mc $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
    463467TEMPLATE_VBoxBS3KitImg_CDEFS        = ARCH_BITS=16 RT_ARCH_X86
    464468
     
    586590TEMPLATE_VBoxBS3KitImg32_CXXTOOL      = Bs3Ow32
    587591TEMPLATE_VBoxBS3KitImg32_CFLAGS       = \
    588         -nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -wx -zl -mf $(BS3_OW_DBG_OPT) -d1 -s -oa -ob -of -oi -ol -or -os -d+
     592        -nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -wx -zl -mf $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
    589593TEMPLATE_VBoxBS3KitImg32_CXXFLAGS     = \
    590         -nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -wx -zl -mf $(BS3_OW_DBG_OPT) -d1 -s -oa -ob -of -oi -ol -or -os -d+
     594        -nt=BS3TEXT32 -nd=BS3DATA32 -nc=BS3CLASS32CODE -ecc -q -wx -zl -mf $(BS3_OW_DBG_OPT) -s -oa -ob -of -oi -ol -or -os -d+
    591595TEMPLATE_VBoxBS3KitImg32_INCS         = $(VBOX_PATH_BS3KIT_SRC) .
    592596TEMPLATE_VBoxBS3KitImg32_LDTOOL       = VBoxBsUnusedLd
     
    611615 TEMPLATE_VBoxBS3KitImg64_CTOOL      := Bs3Vcc64
    612616 TEMPLATE_VBoxBS3KitImg64_CXXTOOL    := Bs3Vcc64
    613  TEMPLATE_VBoxBS3KitImg64_CFLAGS      = -Zi -O1 -Oi -GF -GS- -Gy -Gs65536
    614  TEMPLATE_VBoxBS3KitImg64_CXXFLAGS    = -Zi -O1 -Oi -GF -GS- -Gy -Gs65536
     617 TEMPLATE_VBoxBS3KitImg64_CFLAGS      = -Z7 -O1 -Oi -GF -GS- -Gy -Gs65536
     618 TEMPLATE_VBoxBS3KitImg64_CXXFLAGS    = -Z7 -O1 -Oi -GF -GS- -Gy -Gs65536
    615619else
    616620 TEMPLATE_VBoxBS3KitImg64_CTOOL      := Bs3Gcc64Elf64
  • trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp

    r60197 r60265  
    4343#include <iprt/formats/pecoff.h>
    4444#include <iprt/formats/omf.h>
     45#include <iprt/formats/codeview.h>
    4546
    4647
     
    258259    FILE           *pDst;
    259260
     261    /** Pointer to the table mapping from source segments/section to segdefs. */
     262    POMFTOSEGDEF    paSegments;
    260263    /** Number of source segments/sections. */
    261264    uint32_t        cSegments;
    262     /** Pointer to the table mapping from source segments/section to segdefs. */
    263     POMFTOSEGDEF    paSegments;
    264265
    265266    /** Number of entries in the source symbol table. */
     
    267268    /** Pointer to the table mapping from source symbols to OMF stuff. */
    268269    POMFSYMBOL      paSymbols;
     270
     271    /** LEDATA segment offset. */
     272    uint32_t        offSeg;
     273    /** Start of the current LEDATA record.   */
     274    uint32_t        offSegRec;
     275    /** The LEDATA end segment offset. */
     276    uint32_t        offSegEnd;
     277    /** The current LEDATA segment. */
     278    uint16_t        idx;
    269279
    270280    /** The index of the next list of names entry. */
     
    277287    /** The record data buffer (too large, but whatever).  */
    278288    uint8_t         abData[_1K + 64];
    279     /** Alignment padding. */
    280     uint8_t         abAlign[2];
    281289
    282290    /** Current FIXUPP entry. */
     
    397405static bool omfWriter_RecAddBytes(POMFWRITER pThis, const void *pvData, size_t cbData)
    398406{
    399     if (cbData + pThis->cbRec <= OMF_MAX_RECORD_PAYLOAD)
     407    const uint16_t cbNasmHack = OMF_MAX_RECORD_PAYLOAD + 1;
     408    if (cbData + pThis->cbRec <= cbNasmHack)
    400409    {
    401410        memcpy(&pThis->abData[pThis->cbRec], pvData, cbData);
     
    403412        return true;
    404413    }
    405     return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x, cbData=%#x)!\n", pThis->bType, (unsigned)cbData);
     414    return error(pThis->pszSrc, "Exceeded max OMF record length (bType=%#x, cbData=%#x, cbRec=%#x, max=%#x)!\n",
     415                 pThis->bType, (unsigned)cbData, pThis->cbRec, OMF_MAX_RECORD_PAYLOAD);
    406416}
    407417
     
    476486}
    477487
    478 static bool omfWriter_LNamesBegin(POMFWRITER pThis)
     488static bool omfWriter_LNamesBegin(POMFWRITER pThis, bool fAddZeroEntry)
    479489{
    480490    /* First entry is an empty string. */
    481491    return omfWriter_RecBegin(pThis, OMF_LNAMES)
    482492        && (   pThis->idxNextName > 1
     493            || !fAddZeroEntry
    483494            || omfWriter_LNamesAddN(pThis, "", 0, NULL));
    484495}
     
    576587 * EXTDEF - Add an entry, split record if necessary.
    577588 */
    578 static bool omfWriter_ExtDefAddN(POMFWRITER pThis, const char *pchString, size_t cchString)
     589static bool omfWriter_ExtDefAddN(POMFWRITER pThis, const char *pchString, size_t cchString, uint16_t idxType)
    579590{
    580591    /* Split? */
     
    590601
    591602    return omfWriter_RecAddStringN(pThis, pchString, cchString)
    592         && omfWriter_RecAddIdx(pThis, 0); /* type */
     603        && omfWriter_RecAddIdx(pThis, idxType); /* type */
    593604}
    594605
     
    598609static bool omfWriter_ExtDefAdd(POMFWRITER pThis, const char *pszString)
    599610{
    600     return omfWriter_ExtDefAddN(pThis, pszString, strlen(pszString));
     611    return omfWriter_ExtDefAddN(pThis, pszString, strlen(pszString), 0);
    601612}
    602613
     
    621632}
    622633
     634
    623635/**
    624636 * LEDATA + FIXUPP - Begin records.
    625637 */
    626 static bool omfWriter_LEDataBegin(POMFWRITER pThis, uint16_t idxSeg, uint32_t offSeg,
    627                                   uint32_t cbData, uint32_t cbRawData, void const *pbRawData, uint8_t **ppbData)
     638static bool omfWriter_LEDataBegin(POMFWRITER pThis, uint16_t idxSeg, uint32_t offSeg)
     639{
     640    if (   omfWriter_RecBegin(pThis, OMF_LEDATA32)
     641        && omfWriter_RecAddIdx(pThis, idxSeg)
     642        && omfWriter_RecAddU32(pThis, offSeg))
     643    {
     644        pThis->idx       = idxSeg;
     645        pThis->offSeg    = offSeg;
     646        pThis->offSegRec = offSeg;
     647        pThis->offSegEnd = offSeg + OMF_MAX_RECORD_PAYLOAD - 1 /*CRC*/ - pThis->cbRec;
     648        pThis->offSegEnd &= ~(uint32_t)7; /* qword align. */
     649
     650        /* Reset the associated FIXUPP records. */
     651        pThis->iFixupp = 0;
     652        for (unsigned i = 0; i < RT_ELEMENTS(pThis->aFixupps); i++)
     653            pThis->aFixupps[i].cbRec = 0;
     654        return true;
     655    }
     656    return false;
     657}
     658
     659/**
     660 * LEDATA + FIXUPP - Begin records.
     661 */
     662static bool omfWriter_LEDataBeginEx(POMFWRITER pThis, uint16_t idxSeg, uint32_t offSeg,
     663                                    uint32_t cbData, uint32_t cbRawData, void const *pbRawData, uint8_t **ppbData)
    628664{
    629665    if (   omfWriter_RecBegin(pThis, OMF_LEDATA32)
     
    643679                memset(&pbDst[cbRawData], 0, cbData - cbRawData);
    644680
    645             pThis->cbRec += cbData;
     681            pThis->cbRec    += cbData;
     682            pThis->idx       = idxSeg;
     683            pThis->offSegRec = offSeg;
     684            pThis->offSeg    = offSeg + cbData;
     685            pThis->offSegEnd = offSeg + cbData;
    646686
    647687            /* Reset the associated FIXUPP records. */
     
    736776
    737777/**
     778 * LEDATA + FIXUPP - Add simple fixup, split if necessary.
     779 */
     780static bool omfWriter_LEDataAddFixupNoDisp(POMFWRITER pThis, uint16_t offDataRec, uint8_t bLocation,
     781                                           uint8_t bFrame, uint16_t idxFrame, uint8_t bTarget, uint16_t idxTarget)
     782{
     783    return omfWriter_LEDataAddFixup(pThis, offDataRec, false /*fSelfRel*/, bLocation, bFrame, idxFrame, bTarget, idxTarget,
     784                                    false /*fTargetDisp*/, 0 /*offTargetDisp*/);
     785}
     786
     787
     788/**
    738789 * LEDATA + FIXUPP - End of records.
    739790 */
     
    755806        }
    756807        pThis->iFixupp = 0;
     808        return true;
     809    }
     810    return false;
     811}
     812
     813/**
     814 * LEDATA + FIXUPP - Splits the LEDATA record.
     815 */
     816static bool omfWriter_LEDataSplit(POMFWRITER pThis)
     817{
     818    return omfWriter_LEDataEnd(pThis)
     819        && omfWriter_LEDataBegin(pThis, pThis->idx, pThis->offSeg);
     820}
     821
     822/**
     823 * LEDATA + FIXUPP - Returns available space in current LEDATA record.
     824 */
     825static uint32_t omfWriter_LEDataAvailable(POMFWRITER pThis)
     826{
     827    if (pThis->offSeg < pThis->offSegEnd)
     828        return pThis->offSegEnd - pThis->offSeg;
     829    return 0;
     830}
     831
     832/**
     833 * LEDATA + FIXUPP - Splits LEDATA record if less than @a cb bytes available.
     834 */
     835static bool omfWriter_LEDataEnsureSpace(POMFWRITER pThis, uint32_t cb)
     836{
     837    if (   omfWriter_LEDataAvailable(pThis) >= cb
     838        || omfWriter_LEDataSplit(pThis))
     839        return true;
     840    return false;
     841}
     842
     843/**
     844 * LEDATA + FIXUPP - Adds data to the LEDATA record, splitting it if needed.
     845 */
     846static bool omfWriter_LEDataAddBytes(POMFWRITER pThis, void const *pvData, size_t cbData)
     847{
     848    while (cbData > 0)
     849    {
     850        uint32_t cbAvail = omfWriter_LEDataAvailable(pThis);
     851        if (cbAvail >= cbData)
     852        {
     853            if (omfWriter_RecAddBytes(pThis, pvData, cbData))
     854            {
     855                pThis->offSeg += (uint32_t)cbData;
     856                break;
     857            }
     858            return false;
     859        }
     860        if (!omfWriter_RecAddBytes(pThis, pvData, cbAvail))
     861            return false;
     862        pThis->offSeg += cbAvail;
     863        pvData         = (uint8_t const *)pvData + cbAvail;
     864        cbData        -= cbAvail;
     865        if (!omfWriter_LEDataSplit(pThis))
     866            return false;
     867    }
     868    return true;
     869}
     870
     871/**
     872 * LEDATA + FIXUPP - Adds a U32 to the LEDATA record, splitting if needed.
     873 */
     874static bool omfWriter_LEDataAddU32(POMFWRITER pThis, uint32_t u32)
     875{
     876    if (   omfWriter_LEDataEnsureSpace(pThis, 4)
     877        && omfWriter_RecAddU32(pThis, u32))
     878    {
     879        pThis->offSeg += 4;
     880        return true;
     881    }
     882    return false;
     883}
     884
     885/**
     886 * LEDATA + FIXUPP - Adds a U16 to the LEDATA record, splitting if needed.
     887 */
     888static bool omfWriter_LEDataAddU16(POMFWRITER pThis, uint16_t u16)
     889{
     890    if (   omfWriter_LEDataEnsureSpace(pThis, 2)
     891        && omfWriter_RecAddU16(pThis, u16))
     892    {
     893        pThis->offSeg += 2;
     894        return true;
     895    }
     896    return false;
     897}
     898
     899/**
     900 * LEDATA + FIXUPP - Adds a byte to the LEDATA record, splitting if needed.
     901 */
     902static bool omfWriter_LEDataAddU8(POMFWRITER pThis, uint8_t b)
     903{
     904    if (   omfWriter_LEDataEnsureSpace(pThis, 1)
     905        && omfWriter_RecAddU8(pThis, b))
     906    {
     907        pThis->offSeg += 1;
    757908        return true;
    758909    }
     
    10471198    uint16_t idxGrpFlat, idxGrpData;
    10481199    uint16_t idxClassCode, idxClassData, idxClassDwarf;
    1049     if (   !omfWriter_LNamesBegin(pThis)
     1200    if (   !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/)
    10501201        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat)
    10511202        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData)
     
    14941645             */
    14951646            uint8_t *pbCopy;
    1496             if (!omfWriter_LEDataBegin(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy))
     1647            if (!omfWriter_LEDataBeginEx(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy))
    14971648                return false;
    14981649
     
    17901941    uint16_t idxGrpFlat, idxGrpData;
    17911942    uint16_t idxClassCode, idxClassData, idxClassDebugSymbols, idxClassDebugTypes;
    1792     if (   !omfWriter_LNamesBegin(pThis)
     1943    if (   !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/)
    17931944        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat)
    17941945        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData)
     
    23232474             */
    23242475            uint8_t *pbCopy;
    2325             if (!omfWriter_LEDataBegin(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy))
     2476            if (!omfWriter_LEDataBeginEx(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy))
    23262477                return false;
    23272478
     
    27822933    uint16_t idxGrpFlat, idxGrpData;
    27832934    uint16_t idxClassCode, idxClassData, idxClassDwarf;
    2784     if (   !omfWriter_LNamesBegin(pThis)
     2935    if (   !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/)
    27852936        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat)
    27862937        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData)
     
    32093360             */
    32103361            uint8_t *pbCopy;
    3211             if (!omfWriter_LEDataBegin(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy))
     3362            if (!omfWriter_LEDataBeginEx(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy))
    32123363                return false;
    32133364
     
    34403591
    34413592/**
    3442  * Renames references to intrinsic helper functions so they won't clash between
    3443  * 32-bit and 16-bit code.
     3593 * Records line number information for a file in a segment (for CV8 debug info).
     3594 */
     3595typedef struct OMFFILELINES
     3596{
     3597    /** The source info offset. */
     3598    uint32_t        offSrcInfo;
     3599    /** Number of line/offset pairs. */
     3600    uint32_t        cPairs;
     3601    /** Number of pairs allocated. */
     3602    uint32_t        cPairsAlloc;
     3603    /** Table with line number and offset pairs, ordered by offset. */
     3604    PRTCV8LINEPAIR  paPairs;
     3605} OMFFILEINES;
     3606typedef OMFFILEINES *POMFFILEINES;
     3607
     3608/**
     3609 * Records line number information for a segment (for CV8 debug info).
     3610 */
     3611typedef struct OMFSEGLINES
     3612{
     3613    /** Number of files.   */
     3614    uint32_t        cFiles;
     3615    /** Number of bytes we need. */
     3616    uint32_t        cb;
     3617    /** The segment index. */
     3618    uint16_t        idxSeg;
     3619    /** File table. */
     3620    POMFFILEINES    paFiles;
     3621} OMFSEGLINES;
     3622typedef OMFSEGLINES *POMFSEGLINES;
     3623
     3624/**
     3625 * OMF conversion details.
    34443626 *
    3445  * @returns true / false.
    3446  * @param   pszFile     File name for complaining.
    3447  * @param   pbFile      Pointer to the file content.
    3448  * @param   cbFile      Size of the file content.
     3627 * Keeps information relevant to the conversion and CV8 debug info.
    34493628 */
    3450 static bool convertomf(const char *pszFile, uint8_t *pbFile, size_t cbFile, const char **papchLNames, uint32_t cLNamesMax)
     3629typedef struct OMFDETAILS
     3630{
     3631    /** Set if it has line numbers. */
     3632    bool            fLineNumbers;
     3633    /** Set if we think this may be a 32-bit OMF file. */
     3634    bool            fProbably32bit;
     3635    /** Set if this module may need mangling. */
     3636    bool            fMayNeedMangling;
     3637    /** Number of SEGDEFs records. */
     3638    uint32_t        cSegDefs;
     3639    /** The LNAME index of '$$SYMBOLS' or UINT16_MAX it not found. */
     3640    uint16_t        iSymbolsNm;
     3641    /** The LNAME index of 'DEBSYM' or UINT16_MAX it not found. */
     3642    uint16_t        iDebSymNm;
     3643    /** The '$$SYMBOLS' segment index. */
     3644    uint16_t        iSymbolsSeg;
     3645
     3646    /** CV8: Filename string table size. */
     3647    uint32_t        cbStrTab;
     3648    /** CV8: Filename string table allocation size (always multiple of dword,
     3649     *  zero initialized). */
     3650    uint32_t        cbStrTabAlloc;
     3651    /** CV8: Filename String table. */
     3652    char           *pchStrTab;
     3653    /** CV8: Elements in the source info table. */
     3654    uint16_t        cSrcInfo;
     3655    /** CV8: Source info table. */
     3656    PRTCV8SRCINFO   paSrcInfo;
     3657
     3658    /** Number of entries in the paSegLines table. */
     3659    uint32_t        cSegLines;
     3660    /** Segment line numbers, indexed by segment number. */
     3661    POMFSEGLINES    paSegLines;
     3662} OMFDETAILS;
     3663typedef OMFDETAILS *POMFDETAILS;
     3664typedef OMFDETAILS const *PCOMFDETAILS;
     3665
     3666
     3667/**
     3668 * Adds a line number to the CV8 debug info.
     3669 *
     3670 * @returns success indicator.
     3671 * @param   pOmfStuff   Where to collect CV8 debug info.
     3672 * @param   cchSrcFile  The length of the source file name.
     3673 * @param   pchSrcFile  The source file name, not terminated.
     3674 * @param   poffFile    Where to return the source file information table
     3675 *                      offset (for use in the line number tables).
     3676 */
     3677static bool collectOmfAddFile(POMFDETAILS pOmfStuff, uint8_t cchSrcFile, const char *pchSrcFile, uint32_t *poffFile)
     3678{
     3679    /*
     3680     * Do lookup first.
     3681     */
     3682    uint32_t i = pOmfStuff->cSrcInfo;
     3683    while (i-- > 0)
     3684    {
     3685        const char *pszCur = &pOmfStuff->pchStrTab[pOmfStuff->paSrcInfo[i].offSourceName];
     3686        if (   strncmp(pszCur, pchSrcFile, cchSrcFile) == 0
     3687            && pszCur[cchSrcFile] == '\0')
     3688        {
     3689            *poffFile = i * sizeof(pOmfStuff->paSrcInfo[0]);
     3690            return true;
     3691        }
     3692    }
     3693
     3694    /*
     3695     * Add it to the string table (dword aligned and zero padded).
     3696     */
     3697    uint32_t offSrcTab = pOmfStuff->cbStrTab;
     3698    if (offSrcTab + cchSrcFile + 1 > pOmfStuff->cbStrTabAlloc)
     3699    {
     3700        uint32_t cbNew = (offSrcTab == 0) + offSrcTab + cchSrcFile + 1;
     3701        cbNew = RT_ALIGN(cbNew, 256);
     3702        void *pvNew = realloc(pOmfStuff->pchStrTab, cbNew);
     3703        if (!pvNew)
     3704            return error("???", "out of memory");
     3705        pOmfStuff->pchStrTab     = (char *)pvNew;
     3706        pOmfStuff->cbStrTabAlloc = cbNew;
     3707        memset(&pOmfStuff->pchStrTab[offSrcTab], 0, cbNew - offSrcTab);
     3708
     3709        if (!offSrcTab)
     3710            offSrcTab++;
     3711    }
     3712
     3713    memcpy(&pOmfStuff->pchStrTab[offSrcTab], pchSrcFile, cchSrcFile);
     3714    pOmfStuff->pchStrTab[offSrcTab + cchSrcFile] = '\0';
     3715    pOmfStuff->cbStrTab = offSrcTab + cchSrcFile + 1;
     3716
     3717    /*
     3718     * Add it to the filename info table.
     3719     */
     3720    if ((pOmfStuff->cSrcInfo % 8) == 0)
     3721    {
     3722        void *pvNew = realloc(pOmfStuff->paSrcInfo, sizeof(pOmfStuff->paSrcInfo[0]) * (pOmfStuff->cSrcInfo + 8));
     3723        if (!pvNew)
     3724            return error("???", "out of memory");
     3725        pOmfStuff->paSrcInfo = (PRTCV8SRCINFO)pvNew;
     3726    }
     3727
     3728    PRTCV8SRCINFO  pSrcInfo = &pOmfStuff->paSrcInfo[pOmfStuff->cSrcInfo++];
     3729    pSrcInfo->offSourceName = offSrcTab;
     3730    pSrcInfo->uDigestType   = RTCV8SRCINFO_DIGEST_TYPE_MD5;
     3731    memset(&pSrcInfo->Digest, 0, sizeof(pSrcInfo->Digest));
     3732
     3733    *poffFile = (uint32_t)((uintptr_t)pSrcInfo - (uintptr_t)pOmfStuff->paSrcInfo);
     3734    return true;
     3735}
     3736
     3737
     3738/**
     3739 * Adds a line number to the CV8 debug info.
     3740 *
     3741 * @returns success indicator.
     3742 * @param   pOmfStuff   Where to collect CV8 debug info.
     3743 * @param   idxSeg      The segment index.
     3744 * @param   off         The segment offset.
     3745 * @param   uLine       The line number.
     3746 * @param   offSrcInfo  The source file info table offset.
     3747 */
     3748static bool collectOmfAddLine(POMFDETAILS pOmfStuff, uint16_t idxSeg, uint32_t off, uint16_t uLine, uint32_t offSrcInfo)
     3749{
     3750    /*
     3751     * Get/add the segment line structure.
     3752     */
     3753    if (idxSeg >= pOmfStuff->cSegLines)
     3754    {
     3755        void *pvNew = realloc(pOmfStuff->paSegLines, (idxSeg + 1) * sizeof(pOmfStuff->paSegLines[0]));
     3756        if (!pvNew)
     3757            return error("???", "out of memory");
     3758        pOmfStuff->paSegLines = (POMFSEGLINES)pvNew;
     3759
     3760        memset(&pOmfStuff->paSegLines[pOmfStuff->cSegLines], 0,
     3761               (idxSeg + 1 - pOmfStuff->cSegLines) * sizeof(pOmfStuff->paSegLines[0]));
     3762        for (uint32_t i = pOmfStuff->cSegLines; i <= idxSeg; i++)
     3763        {
     3764            pOmfStuff->paSegLines[i].idxSeg = i;
     3765            pOmfStuff->paSegLines[i].cb = sizeof(RTCV8LINESHDR);
     3766        }
     3767        pOmfStuff->cSegLines = idxSeg + 1;
     3768    }
     3769    POMFSEGLINES pSegLines = &pOmfStuff->paSegLines[idxSeg];
     3770
     3771    /*
     3772     * Get/add the file structure with the segment.
     3773     */
     3774    POMFFILEINES pFileLines = NULL;
     3775    uint32_t i = pSegLines->cFiles;
     3776    while (i-- > 0)
     3777        if (pSegLines->paFiles[i].offSrcInfo == offSrcInfo)
     3778        {
     3779            pFileLines = &pSegLines->paFiles[i];
     3780            break;
     3781        }
     3782    if (!pFileLines)
     3783    {
     3784        i = pSegLines->cFiles;
     3785        if ((i % 4) == 0)
     3786        {
     3787            void *pvNew = realloc(pSegLines->paFiles, (i + 4) * sizeof(pSegLines->paFiles[0]));
     3788            if (!pvNew)
     3789                return error("???", "out of memory");
     3790            pSegLines->paFiles = (POMFFILEINES)pvNew;
     3791        }
     3792
     3793        pSegLines->cFiles = i + 1;
     3794        pSegLines->cb    += sizeof(RTCV8LINESSRCMAP);
     3795
     3796        pFileLines = &pSegLines->paFiles[i];
     3797        pFileLines->offSrcInfo  = offSrcInfo;
     3798        pFileLines->cPairs      = 0;
     3799        pFileLines->cPairsAlloc = 0;
     3800        pFileLines->paPairs     = NULL;
     3801    }
     3802
     3803    /*
     3804     * Add the line number (sorted, duplicates removed).
     3805     */
     3806    if (pFileLines->cPairs + 1 > pFileLines->cPairsAlloc)
     3807    {
     3808        void *pvNew = realloc(pFileLines->paPairs, (pFileLines->cPairsAlloc + 16) * sizeof(pFileLines->paPairs[0]));
     3809        if (!pvNew)
     3810            return error("???", "out of memory");
     3811        pFileLines->paPairs      = (PRTCV8LINEPAIR)pvNew;
     3812        pFileLines->cPairsAlloc += 16;
     3813    }
     3814
     3815    i = pFileLines->cPairs;
     3816    while (i > 0 && (   off < pFileLines->paPairs[i - 1].offSection
     3817                     || (   off == pFileLines->paPairs[i - 1].offSection
     3818                         && uLine < pFileLines->paPairs[i - 1].uLineNumber)) )
     3819        i--;
     3820    if (   i     == pFileLines->cPairs
     3821        || off   != pFileLines->paPairs[i].offSection
     3822        || uLine != pFileLines->paPairs[i].uLineNumber)
     3823    {
     3824        if (i < pFileLines->cPairs)
     3825            memmove(&pFileLines->paPairs[i + 1], &pFileLines->paPairs[i],
     3826                    (pFileLines->cPairs - i) * sizeof(pFileLines->paPairs));
     3827        pFileLines->paPairs[i].offSection      = off;
     3828        pFileLines->paPairs[i].uLineNumber     = uLine;
     3829        pFileLines->paPairs[i].fEndOfStatement = true;
     3830        pFileLines->cPairs++;
     3831        pSegLines->cb += sizeof(pFileLines->paPairs[0]);
     3832    }
     3833
     3834    return true;
     3835}
     3836
     3837
     3838/**
     3839 * Parses OMF file gathering line numbers (for CV8 debug info) and checking out
     3840 * external defintions for mangling work (compiler instrinsics).
     3841 *
     3842 * @returns success indicator.
     3843 * @param   pszFile     The name of the OMF file.
     3844 * @param   pbFile      The file content.
     3845 * @param   cbFile      The size of the file content.
     3846 * @param   pOmfStuff   Where to collect CV8 debug info and anything else we
     3847 *                      find out about the OMF file.
     3848 */
     3849static bool collectOmfDetails(const char *pszFile, uint8_t const *pbFile, size_t cbFile, POMFDETAILS pOmfStuff)
    34513850{
    34523851    uint32_t        cLNames = 0;
    34533852    uint32_t        cExtDefs = 0;
    34543853    uint32_t        cPubDefs = 0;
    3455     bool            fProbably32bit = false;
    34563854    uint32_t        off = 0;
     3855    uint8_t         cchSrcFile = 0;
     3856    const char     *pchSrcFile = NULL;
     3857    uint32_t        offSrcInfo = UINT32_MAX;
     3858
     3859    memset(pOmfStuff, 0, sizeof(*pOmfStuff));
     3860    pOmfStuff->iDebSymNm   = UINT16_MAX;
     3861    pOmfStuff->iSymbolsNm  = UINT16_MAX;
     3862    pOmfStuff->iSymbolsSeg = UINT16_MAX;
    34573863
    34583864    while (off + 3 < cbFile)
     
    34653871            return error(pszFile, "Invalid record length at %#x: %#x (cbFile=%#lx)\n", off, cbRec, (unsigned long)cbFile);
    34663872
    3467         if (bRecType & OMF_REC32)
    3468             fProbably32bit = true;
    3469 
    3470         uint32_t offRec = 0;
    3471         uint8_t *pbRec  = &pbFile[off + 3];
     3873        uint32_t        offRec = 0;
     3874        uint8_t const  *pbRec  = &pbFile[off + 3];
    34723875#define OMF_CHECK_RET(a_cbReq, a_Name) /* Not taking the checksum into account, so we're good with 1 or 2 byte fields. */ \
    34733876            if (offRec + (a_cbReq) <= cbRec) {/*likely*/} \
    34743877            else return error(pszFile, "Malformed " #a_Name "! off=%#x offRec=%#x cbRec=%#x cbNeeded=%#x line=%d\n", \
    34753878                              off, offRec, cbRec, (a_cbReq), __LINE__)
     3879#define OMF_READ_IDX(a_idx, a_Name) \
     3880            do { \
     3881                OMF_CHECK_RET(2, a_Name); \
     3882                a_idx = pbRec[offRec++]; \
     3883                if ((a_idx) & 0x80) \
     3884                    a_idx = (((a_idx) & 0x7f) << 8) | pbRec[offRec++]; \
     3885            } while (0)
     3886
    34763887        switch (bRecType)
    34773888        {
    34783889            /*
    3479              * Scan external definitions for intrinsics needing mangling.
     3890             * Record LNAME records, scanning for FLAT.
     3891             */
     3892            case OMF_LNAMES:
     3893                while (offRec + 1 < cbRec)
     3894                {
     3895                    uint8_t cch = pbRec[offRec];
     3896                    if (offRec + 1 + cch >= cbRec)
     3897                        return error(pszFile, "Invalid LNAME string length at %#x+3+%#x: %#x (cbFile=%#lx)\n",
     3898                                     off, offRec, cch, (unsigned long)cbFile);
     3899
     3900                    cLNames++;
     3901                    if (g_cVerbose > 2)
     3902                        printf("  LNAME[%u]: %-*.*s\n", cLNames, cch, cch, &pbRec[offRec + 1]);
     3903
     3904                    if (cch == 4 && memcmp(&pbRec[offRec + 1], "FLAT", 4) == 0)
     3905                        pOmfStuff->fProbably32bit = true;
     3906
     3907                    if (   cch == 6
     3908                        && pOmfStuff->iDebSymNm == UINT16_MAX
     3909                        && memcmp(&pbRec[offRec + 1], "DEBSYM", 6) == 0)
     3910                        pOmfStuff->iDebSymNm = cLNames;
     3911                    if (   cch == 9
     3912                        && pOmfStuff->iSymbolsNm == UINT16_MAX
     3913                        && memcmp(&pbRec[offRec + 1], "$$SYMBOLS", 9) == 0)
     3914                        pOmfStuff->iSymbolsNm = cLNames;
     3915
     3916                    offRec += cch + 1;
     3917                }
     3918                break;
     3919
     3920            /*
     3921             * Display external defitions if -v is specified, also check if anything needs mangling.
    34803922             */
    34813923            case OMF_EXTDEF:
    3482             {
    34833924                while (offRec + 1 < cbRec)
    34843925                {
     
    34883929                    offRec += cch;
    34893930
    3490                     OMF_CHECK_RET(2, EXTDEF);
    3491                     uint16_t idxType = pbRec[offRec++];
    3492                     if (idxType & 0x80)
    3493                         idxType = ((idxType & 0x7f) << 8) | pbRec[offRec++];
     3931                    uint16_t idxType;
     3932                    OMF_READ_IDX(idxType, EXTDEF);
    34943933
    34953934                    if (g_cVerbose > 2)
     
    34993938
    35003939                    /* Look for g_apszExtDefRenames entries that requires changing. */
    3501                     if (   cch >= 5
     3940                    if (   !pOmfStuff->fMayNeedMangling
     3941                        && cch >= 5
    35023942                        && cch <= 7
    35033943                        && pchName[0] == '_'
     
    35113951                            || pchName[3] == 'T') )
    35123952                    {
    3513                         uint32_t i = RT_ELEMENTS(g_apszExtDefRenames);
    3514                         while (i-- > 0)
    3515                             if (   cch == (uint8_t)g_apszExtDefRenames[i][0]
    3516                                 && memcmp(&g_apszExtDefRenames[i][1], pchName, cch) == 0)
    3517                             {
    3518                                 pchName[0] = fProbably32bit ? '?' : '_';
    3519                                 pchName[1] = '?';
    3520                                 break;
    3521                             }
     3953                        pOmfStuff->fMayNeedMangling = true;
    35223954                    }
    3523 
    3524                     cExtDefs++;
    35253955                }
    35263956                break;
    3527             }
    3528 
    3529             /*
    3530              * Record LNAME records, scanning for FLAT.
    3531              */
    3532             case OMF_LNAMES:
    3533             {
    3534                 while (offRec + 1 < cbRec)
    3535                 {
    3536                     uint8_t cch = pbRec[offRec];
    3537                     if (offRec + 1 + cch >= cbRec)
    3538                         return error(pszFile, "Invalid LNAME string length at %#x+3+%#x: %#x (cbFile=%#lx)\n",
    3539                                      off, offRec, cch, (unsigned long)cbFile);
    3540                     if (cLNames + 1 >= cLNamesMax)
    3541                         return error(pszFile, "Too many LNAME strings\n");
    3542 
    3543                     if (g_cVerbose > 2)
    3544                         printf("  LNAME[%u]: %-*.*s\n", cLNames, cch, cch, &pbRec[offRec + 1]);
    3545 
    3546                     papchLNames[cLNames++] = (const char *)&pbRec[offRec];
    3547                     if (cch == 4 && memcmp(&pbRec[offRec + 1], "FLAT", 4) == 0)
    3548                         fProbably32bit = true;
    3549 
    3550                     offRec += cch + 1;
    3551                 }
    3552                 break;
    3553             }
    35543957
    35553958            /*
    35563959             * Display public names if -v is specified.
    35573960             */
     3961            case OMF_PUBDEF32:
     3962            case OMF_LPUBDEF32:
     3963                pOmfStuff->fProbably32bit = true;
    35583964            case OMF_PUBDEF16:
    3559             case OMF_PUBDEF32:
    35603965            case OMF_LPUBDEF16:
    3561             case OMF_LPUBDEF32:
    3562             {
    35633966                if (g_cVerbose > 0)
    35643967                {
     
    35683971                        pszRec++;
    35693972
    3570                     OMF_CHECK_RET(2, [L]PUBDEF);
    3571                     uint16_t idxGrp = pbRec[offRec++];
    3572                     if (idxGrp & 0x80)
    3573                         idxGrp = ((idxGrp & 0x7f) << 8) | pbRec[offRec++];
    3574 
    3575                     OMF_CHECK_RET(2, [L]PUBDEF);
    3576                     uint16_t idxSeg = pbRec[offRec++];
    3577                     if (idxSeg & 0x80)
    3578                         idxSeg = ((idxSeg & 0x7f) << 8) | pbRec[offRec++];
     3973                    uint16_t idxGrp;
     3974                    OMF_READ_IDX(idxGrp, [L]PUBDEF);
     3975
     3976                    uint16_t idxSeg;
     3977                    OMF_READ_IDX(idxSeg, [L]PUBDEF);
    35793978
    35803979                    uint16_t uFrameBase = 0;
     
    36104009                        }
    36114010
    3612                         OMF_CHECK_RET(2, [L]PUBDEF);
    3613                         uint16_t idxType = pbRec[offRec++];
    3614                         if (idxType & 0x80)
    3615                             idxType = ((idxType & 0x7f) << 8) | pbRec[offRec++];
     4011                        uint16_t idxType;
     4012                        OMF_READ_IDX(idxType, [L]PUBDEF);
    36164013
    36174014                        if (g_cVerbose > 2)
     
    36194016                        else if (g_cVerbose > 0)
    36204017                            printf("%04x:%08x %c %-*.*s\n", uSeg, offSeg, chType, cch, cch, pchName);
    3621 
    3622                         cPubDefs++;
    36234018                    }
    36244019                }
    36254020                break;
     4021
     4022            /*
     4023             * Must count segment defitions to figure the index of our segment.
     4024             */
     4025            case OMF_SEGDEF16:
     4026            case OMF_SEGDEF32:
     4027                pOmfStuff->cSegDefs++;
     4028                break;
     4029
     4030            /*
     4031             * Gather file names.
     4032             */
     4033            case OMF_THEADR: /* watcom */
     4034                cchSrcFile = pbRec[offRec++];
     4035                OMF_CHECK_RET(cchSrcFile, OMF_THEADR);
     4036                pchSrcFile = (const char *)&pbRec[offRec];
     4037                if (!collectOmfAddFile(pOmfStuff, cchSrcFile, pchSrcFile, &offSrcInfo))
     4038                    return false;
     4039                break;
     4040
     4041            case OMF_COMENT:
     4042            {
     4043                OMF_CHECK_RET(2, COMENT);
     4044                offRec++; /* skip the type (flags) */
     4045                uint8_t bClass = pbRec[offRec++];
     4046                if (bClass == OMF_CCLS_BORLAND_SRC_FILE) /* nasm */
     4047                {
     4048                    OMF_CHECK_RET(1+1+4, BORLAND_SRC_FILE);
     4049                    offRec++; /* skip unknown byte */
     4050                    cchSrcFile = pbRec[offRec++];
     4051                    OMF_CHECK_RET(cchSrcFile + 4, BORLAND_SRC_FILE);
     4052                    pchSrcFile = (const char *)&pbRec[offRec];
     4053                    offRec += cchSrcFile;
     4054                    if (offRec + 4 + 1 != cbRec)
     4055                        return error(pszFile, "BAD BORLAND_SRC_FILE record at %#x: %d bytes left\n",
     4056                                     off, cbRec - offRec - 4 - 1);
     4057                    if (!collectOmfAddFile(pOmfStuff, cchSrcFile, pchSrcFile, &offSrcInfo))
     4058                        return false;
     4059                    break;
     4060                }
     4061                break;
     4062            }
     4063
     4064            /*
     4065             * Line number conversion.
     4066             */
     4067            case OMF_LINNUM16:
     4068            case OMF_LINNUM32:
     4069            {
     4070                uint16_t idxGrp;
     4071                OMF_READ_IDX(idxGrp, LINNUM);
     4072                uint16_t idxSeg;
     4073                OMF_READ_IDX(idxSeg, LINNUM);
     4074
     4075                uint16_t iLine;
     4076                uint32_t off;
     4077                if (bRecType == OMF_LINNUM16)
     4078                    while (offRec + 4 < cbRec)
     4079                    {
     4080                        iLine = RT_MAKE_U16(pbRec[offRec + 0], pbRec[offRec + 1]);
     4081                        off   = RT_MAKE_U16(pbRec[offRec + 2], pbRec[offRec + 3]);
     4082                        if (!collectOmfAddLine(pOmfStuff, idxSeg, off, iLine, offSrcInfo))
     4083                            return false;
     4084                        offRec += 4;
     4085                    }
     4086                else
     4087                    while (offRec + 6 < cbRec)
     4088                    {
     4089                        iLine = RT_MAKE_U16(pbRec[offRec + 0], pbRec[offRec + 1]);
     4090                        off   = RT_MAKE_U32_FROM_U8(pbRec[offRec + 2], pbRec[offRec + 3], pbRec[offRec + 4], pbRec[offRec + 5]);
     4091                        if (!collectOmfAddLine(pOmfStuff, idxSeg, off, iLine, offSrcInfo))
     4092                            return false;
     4093                        offRec += 6;
     4094                    }
     4095                if (offRec + 1 != cbRec)
     4096                    return error(pszFile, "BAD LINNUM record at %#x: %d bytes left\n", off, cbRec - offRec - 1);
     4097                break;
    36264098            }
    36274099        }
     
    36304102        off += cbRec + 3;
    36314103    }
     4104
    36324105    return true;
     4106#undef OMF_READ_IDX
     4107#undef OMF_CHECK_RET
     4108}
     4109
     4110
     4111/**
     4112 * Writes the debug segment definitions (names too).
     4113 *
     4114 * @returns success indicator.
     4115 * @param   pThis       The OMF writer.
     4116 * @param   pOmfStuff   The OMF stuff with CV8 line number info.
     4117 */
     4118static bool convertOmfWriteDebugSegDefs(POMFWRITER pThis, POMFDETAILS pOmfStuff)
     4119{
     4120    if (   pOmfStuff->cSegLines == 0
     4121        || pOmfStuff->iSymbolsSeg != UINT16_MAX)
     4122        return true;
     4123
     4124    /*
     4125     * Emit the LNAMES we need.
     4126     */
     4127#if 1
     4128    if (   pOmfStuff->iSymbolsNm == UINT16_MAX
     4129        || pOmfStuff->iDebSymNm == UINT16_MAX)
     4130    {
     4131        if (   !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/)
     4132            || (   pOmfStuff->iSymbolsNm == UINT16_MAX
     4133                && !omfWriter_LNamesAdd(pThis, "$$SYMBOLS", &pOmfStuff->iSymbolsNm))
     4134            || (   pOmfStuff->iDebSymNm == UINT16_MAX
     4135                && !omfWriter_LNamesAdd(pThis, "DEBSYM", &pOmfStuff->iDebSymNm))
     4136            || !omfWriter_LNamesEnd(pThis) )
     4137            return false;
     4138    }
     4139#else
     4140    if (   !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/)
     4141        || !omfWriter_LNamesAdd(pThis, "$$SYMBOLS2", &pOmfStuff->iSymbolsNm)
     4142        || !omfWriter_LNamesAdd(pThis, "DEBSYM2", &pOmfStuff->iDebSymNm)
     4143        || !omfWriter_LNamesEnd(pThis) )
     4144        return false;
     4145#endif
     4146
     4147    /*
     4148     * Emit the segment defitions.
     4149     */
     4150    pOmfStuff->iSymbolsSeg = ++pOmfStuff->cSegDefs;
     4151
     4152    uint8_t   bSegAttr = 0;
     4153    bSegAttr |= 5 << 5; /* A: dword alignment */
     4154    bSegAttr |= 0 << 2; /* C: private */
     4155    bSegAttr |= 0 << 1; /* B: not big */
     4156    bSegAttr |= 1;      /* D: use32 */
     4157
     4158    /* calc the segment size. */
     4159    uint32_t  cbSeg = 4; /* dword 4 */
     4160    cbSeg += 4 + 4 + RT_ALIGN_32(pOmfStuff->cbStrTab, 4);
     4161    cbSeg += 4 + 4 + pOmfStuff->cSrcInfo * sizeof(pOmfStuff->paSrcInfo[0]);
     4162    uint32_t i = pOmfStuff->cSegLines;
     4163    while (i-- > 0)
     4164        if (pOmfStuff->paSegLines[i].cFiles > 0)
     4165            cbSeg += 4 + 4 + pOmfStuff->paSegLines[i].cb;
     4166    return omfWriter_SegDef(pThis, bSegAttr, cbSeg, pOmfStuff->iSymbolsNm, pOmfStuff->iDebSymNm);
     4167}
     4168
     4169
     4170/**
     4171 * Writes the debug segment data.
     4172 *
     4173 * @returns success indicator.
     4174 * @param   pThis       The OMF writer.
     4175 * @param   pOmfStuff   The OMF stuff with CV8 line number info.
     4176 */
     4177static bool convertOmfWriteDebugData(POMFWRITER pThis, POMFDETAILS pOmfStuff)
     4178{
     4179    if (pOmfStuff->cSegLines == 0)
     4180        return true;
     4181
     4182    /* Begin and write the CV version signature. */
     4183    uint32_t const  cbMaxChunk = RT_ALIGN(OMF_MAX_RECORD_PAYLOAD - 1 - 16, 4); /* keep the data dword aligned */
     4184    if (   !omfWriter_LEDataBegin(pThis, pOmfStuff->iSymbolsSeg, 0)
     4185        || !omfWriter_LEDataAddU32(pThis, RTCVSYMBOLS_SIGNATURE_CV8))
     4186        return false;
     4187
     4188    /*
     4189     * Emit the string table (no fixups).
     4190     */
     4191    uint32_t cbLeft = pOmfStuff->cbStrTab;
     4192    if (   !omfWriter_LEDataAddU32(pThis, RTCV8SYMBLOCK_TYPE_SRC_STR)
     4193        || !omfWriter_LEDataAddU32(pThis, cbLeft)
     4194        || !omfWriter_LEDataAddBytes(pThis, pOmfStuff->pchStrTab, RT_ALIGN_32(cbLeft, 4)) ) /* table is zero padded to nearest dword */
     4195        return false;
     4196
     4197    /*
     4198     * Emit the source file info table (no fixups).
     4199     */
     4200    cbLeft = pOmfStuff->cSrcInfo * sizeof(pOmfStuff->paSrcInfo[0]);
     4201    if (   !omfWriter_LEDataAddU32(pThis, RTCV8SYMBLOCK_TYPE_SRC_INFO)
     4202        || !omfWriter_LEDataAddU32(pThis, cbLeft)
     4203        || !omfWriter_LEDataAddBytes(pThis, pOmfStuff->paSrcInfo, cbLeft) )
     4204        return false;
     4205
     4206    /*
     4207     * Emit the segment line numbers. There are two fixups here at the start
     4208     * of each chunk.
     4209     */
     4210    POMFSEGLINES pSegLines = pOmfStuff->paSegLines;
     4211    uint32_t     i         = pOmfStuff->cSegLines;
     4212    while (i-- > 0)
     4213    {
     4214        if (pSegLines->cFiles)
     4215        {
     4216            /* Calc covered area. */
     4217            uint32_t cbSectionCovered = 0;
     4218            uint32_t j = pSegLines->cFiles;
     4219            while (j-- > 0)
     4220            {
     4221                uint32_t offLast = pSegLines->paFiles[j].paPairs[pSegLines->paFiles[j].cPairs - 1].offSection;
     4222                if (offLast > cbSectionCovered)
     4223                    offLast = cbSectionCovered;
     4224            }
     4225
     4226            /* For simplicity and debuggability, just split the LEDATA here. */
     4227            if (   !omfWriter_LEDataSplit(pThis)
     4228                || !omfWriter_LEDataAddU32(pThis, RTCV8SYMBLOCK_TYPE_SECT_LINES)
     4229                || !omfWriter_LEDataAddU32(pThis, pSegLines->cb)
     4230                || !omfWriter_LEDataAddU32(pThis, 0)                /*RTCV8LINESHDR::offSection*/
     4231                || !omfWriter_LEDataAddU16(pThis, 0)                /*RTCV8LINESHDR::iSection*/
     4232                || !omfWriter_LEDataAddU16(pThis, 0)                /*RTCV8LINESHDR::u16Padding*/
     4233                || !omfWriter_LEDataAddU32(pThis, cbSectionCovered) /*RTCV8LINESHDR::cbSectionCovered*/ )
     4234                return false;
     4235
     4236            /* Fixup #1: segment offset - IMAGE_REL_AMD64_SECREL. */
     4237            if (!omfWriter_LEDataAddFixupNoDisp(pThis, 4 + 4 + RT_OFFSETOF(RTCV8LINESHDR, offSection), OMF_FIX_LOC_32BIT_OFFSET,
     4238                                                OMF_FIX_F_SEGDEF, pSegLines->idxSeg,
     4239                                                OMF_FIX_T_SEGDEF_NO_DISP, pSegLines->idxSeg))
     4240                return false;
     4241
     4242
     4243            /* Fixup #2: segment number - IMAGE_REL_AMD64_SECTION. */
     4244            if (!omfWriter_LEDataAddFixupNoDisp(pThis, 4 + 4 + RT_OFFSETOF(RTCV8LINESHDR, iSection), OMF_FIX_LOC_16BIT_SEGMENT,
     4245                                                OMF_FIX_F_SEGDEF, pSegLines->idxSeg,
     4246                                                OMF_FIX_T_SEGDEF_NO_DISP, pSegLines->idxSeg))
     4247                return false;
     4248
     4249            /* Emit data for each source file. */
     4250            for (uint32_t j = 0; j < pSegLines->cFiles; j++)
     4251            {
     4252                uint32_t const cbPairs = pSegLines->paFiles[j].cPairs * sizeof(RTCV8LINEPAIR);
     4253                if (   !omfWriter_LEDataAddU32(pThis, pSegLines->paFiles[j].offSrcInfo)   /*RTCV8LINESSRCMAP::offSourceInfo*/
     4254                    || !omfWriter_LEDataAddU32(pThis, pSegLines->paFiles[j].cPairs)       /*RTCV8LINESSRCMAP::cLines*/
     4255                    || !omfWriter_LEDataAddU32(pThis, cbPairs + sizeof(RTCV8LINESSRCMAP)) /*RTCV8LINESSRCMAP::cb*/
     4256                    || !omfWriter_LEDataAddBytes(pThis, pSegLines->paFiles[j].paPairs, cbPairs))
     4257                    return false;
     4258            }
     4259        }
     4260        pSegLines++;
     4261    }
     4262
     4263    return omfWriter_LEDataEnd(pThis);
     4264}
     4265
     4266
     4267/**
     4268 * This does the actual converting, passthru style.
     4269 *
     4270 * It only modifies, removes and inserts stuff it care about, the rest is passed
     4271 * thru as-is.
     4272 *
     4273 * @returns success indicator.
     4274 * @param   pThis       The OMF writer.
     4275 * @param   pbFile      The original file content.
     4276 * @param   cbFile      The size of the original file.
     4277 * @param   pOmfStuff   The OMF stuff we've gathered during the first pass,
     4278 *                      contains CV8 line number info if we converted anything.
     4279 */
     4280static bool convertOmfPassthru(POMFWRITER pThis, uint8_t const *pbFile, size_t cbFile, POMFDETAILS pOmfStuff)
     4281{
     4282    bool const  fConvertLineNumbers = true;
     4283    bool        fSeenTheAdr         = false;
     4284    uint32_t    off = 0;
     4285    while (off + 3 < cbFile)
     4286    {
     4287        uint8_t         bRecType = pbFile[off];
     4288        uint16_t        cbRec    = RT_MAKE_U16(pbFile[off + 1], pbFile[off + 2]);
     4289        uint32_t        offRec   = 0;
     4290        uint8_t const  *pbRec    = &pbFile[off + 3];
     4291
     4292#define OMF_READ_IDX(a_idx, a_Name) \
     4293            do { \
     4294                a_idx = pbRec[offRec++]; \
     4295                if ((a_idx) & 0x80) \
     4296                    a_idx = (((a_idx) & 0x7f) << 8) | pbRec[offRec++]; \
     4297            } while (0)
     4298
     4299        /*
     4300         * Remove/insert switch.  will
     4301         */
     4302        bool fSkip = false;
     4303        switch (bRecType)
     4304        {
     4305            /*
     4306             * Mangle watcom intrinsics if necessary.
     4307             */
     4308            case OMF_EXTDEF:
     4309                if (pOmfStuff->fMayNeedMangling)
     4310                {
     4311                    if (!omfWriter_ExtDefBegin(pThis))
     4312                        return false;
     4313                    while (offRec + 1 < cbRec)
     4314                    {
     4315                        uint8_t cchName = pbRec[offRec++];
     4316                        char   *pchName = (char *)&pbRec[offRec];
     4317                        offRec += cchName;
     4318
     4319                        uint16_t idxType;
     4320                        OMF_READ_IDX(idxType, EXTDEF);
     4321
     4322                        /* Look for g_apszExtDefRenames entries that requires changing. */
     4323                        if (   cchName >= 5
     4324                            && cchName <= 7
     4325                            && pchName[0] == '_'
     4326                            && pchName[1] == '_'
     4327                            && (   pchName[2] == 'U'
     4328                                || pchName[2] == 'I'
     4329                                || pchName[2] == 'P')
     4330                            && (   pchName[3] == '4'
     4331                                || pchName[3] == '8'
     4332                                || pchName[3] == 'I'
     4333                                || pchName[3] == 'T') )
     4334                        {
     4335                            char szName[12];
     4336                            memcpy(szName, pchName, cchName);
     4337                            szName[cchName] = '\0';
     4338
     4339                            uint32_t i = RT_ELEMENTS(g_apszExtDefRenames);
     4340                            while (i-- > 0)
     4341                                if (   cchName == (uint8_t)g_apszExtDefRenames[i][0]
     4342                                    && memcmp(&g_apszExtDefRenames[i][1], szName, cchName) == 0)
     4343                                {
     4344                                    szName[0] = pOmfStuff->fProbably32bit ? '?' : '_';
     4345                                    szName[1] = '?';
     4346                                    break;
     4347                                }
     4348
     4349                            if (!omfWriter_ExtDefAddN(pThis, szName, cchName, idxType))
     4350                                return false;
     4351                        }
     4352                        else if (!omfWriter_ExtDefAddN(pThis, pchName, cchName, idxType))
     4353                            return false;
     4354                    }
     4355                    if (!omfWriter_ExtDefEnd(pThis))
     4356                        return false;
     4357                    fSkip = true;
     4358                }
     4359                break;
     4360
     4361            /*
     4362             * Remove line number records.
     4363             */
     4364            case OMF_LINNUM16:
     4365            case OMF_LINNUM32:
     4366                fSkip = fConvertLineNumbers;
     4367                break;
     4368
     4369            /*
     4370             * Remove all but the first OMF_THEADR.
     4371             */
     4372            case OMF_THEADR:
     4373                fSkip = fSeenTheAdr && fConvertLineNumbers;
     4374                fSeenTheAdr = true;
     4375                break;
     4376
     4377            /*
     4378             * Remove borland source file changes. Also, emit our SEGDEF
     4379             * before the pass marker.
     4380             */
     4381            case OMF_COMENT:
     4382                if (fConvertLineNumbers)
     4383                {
     4384                    fSkip = pbRec[1] == OMF_CCLS_BORLAND_SRC_FILE;
     4385                    if (pbRec[1] == OMF_CCLS_LINK_PASS_SEP)
     4386                        if (!convertOmfWriteDebugSegDefs(pThis, pOmfStuff))
     4387                            return false;
     4388                }
     4389                break;
     4390
     4391            /*
     4392             * Redo these to the OMF writer is on top of the index thing.
     4393             */
     4394            case OMF_LNAMES:
     4395                if (!omfWriter_LNamesBegin(pThis, false /*fAddZeroEntry*/))
     4396                    return false;
     4397                while (offRec + 1 < cbRec)
     4398                {
     4399                    uint8_t     cch = pbRec[offRec];
     4400                    const char *pch = (const char *)&pbRec[offRec + 1];
     4401                    if (!omfWriter_LNamesAddN(pThis, pch, cch, NULL))
     4402                        return false;
     4403                    offRec += cch + 1;
     4404                }
     4405                if (!omfWriter_LNamesEnd(pThis))
     4406                    return false;
     4407
     4408                fSkip = true;
     4409                break;
     4410
     4411            /*
     4412             * Upon seeing MODEND we write out the debug info.
     4413             */
     4414            case OMF_MODEND16:
     4415            case OMF_MODEND32:
     4416                if (fConvertLineNumbers)
     4417                {
     4418                    if (   convertOmfWriteDebugSegDefs(pThis, pOmfStuff)
     4419                        && convertOmfWriteDebugData(pThis, pOmfStuff))
     4420                    { /* likely */ }
     4421                    else return false;
     4422                }
     4423                break;
     4424        }
     4425
     4426        /*
     4427         * Pass the record thru, if so was decided.
     4428         */
     4429        if (!fSkip)
     4430        {
     4431            if (   omfWriter_RecBegin(pThis, bRecType)
     4432                && omfWriter_RecAddBytes(pThis, pbRec, cbRec)
     4433                && omfWriter_RecEnd(pThis, false))
     4434            { /* likely */ }
     4435            else return false;
     4436        }
     4437
     4438        /* advance */
     4439        off += cbRec + 3;
     4440    }
     4441
     4442    return true;
     4443}
     4444
     4445
     4446/**
     4447 * Converts LINNUMs and compiler intrinsics in an OMF object file.
     4448 *
     4449 * Wlink does a cheesy (to use their own term) job of generating the
     4450 * sstSrcModule subsection.  It is limited to one file and cannot deal with line
     4451 * numbers in different segment.  The latter is very annoying in assembly files
     4452 * that jumps between segments, these a frequent on crash stacks.
     4453 *
     4454 * The solution is to convert to the same line number tables that cl.exe /Z7
     4455 * generates for our 64-bit C code, we named that format codeview v8, or CV8.
     4456 * Our code codeview debug info reader can deal with this already because of the
     4457 * 64-bit code, so Bob's your uncle.
     4458 *
     4459 * @returns success indicator.
     4460 * @param   pszFile     The name of the file being converted.
     4461 * @param   pbFile      The file content.
     4462 * @param   cbFile      The size of the file content.
     4463 * @param   pDst        The destiation (output) file.
     4464 */
     4465static bool convertOmfToOmf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, FILE *pDst)
     4466{
     4467    /*
     4468     * Collect line number information.
     4469     */
     4470    OMFDETAILS OmfStuff;
     4471    if (!collectOmfDetails(pszFile, pbFile, cbFile, &OmfStuff))
     4472        return false;
     4473
     4474    /*
     4475     * Instantiate the OMF writer and do pass-thru modifications.
     4476     */
     4477    bool fRc;
     4478    POMFWRITER pThis = omfWriter_Create(pszFile, 0, 0, pDst);
     4479    if (pThis)
     4480    {
     4481        fRc = convertOmfPassthru(pThis, pbFile, cbFile, &OmfStuff);
     4482        omfWriter_Destroy(pThis);
     4483    }
     4484    else
     4485        fRc = false;
     4486
     4487
     4488    /*
     4489     * Cleanup OmfStuff.
     4490     */
     4491    uint32_t i = OmfStuff.cSegLines;
     4492    while (i-- >0)
     4493    {
     4494        uint32_t j = OmfStuff.paSegLines[i].cFiles;
     4495        while (j-- > 0)
     4496            free(OmfStuff.paSegLines[i].paFiles[j].paPairs);
     4497        free(OmfStuff.paSegLines[i].paFiles);
     4498    }
     4499    free(OmfStuff.paSegLines);
     4500    free(OmfStuff.paSrcInfo);
     4501    free(OmfStuff.pchStrTab);
     4502    return fRc;
    36334503}
    36344504
     
    36994569                 && RT_MAKE_U16(pbFile[1], pbFile[2]) < cbFile)
    37004570        {
    3701             const char **papchLNames = (const char **)calloc(sizeof(*papchLNames), _32K);
    3702             fRc = writefile(szOrgFile, pvFile, cbFile)
    3703                && convertomf(pszFile, pbFile, cbFile, papchLNames, _32K)
    3704                && writefile(pszFile, pvFile, cbFile);
    3705             free(papchLNames);
     4571            if (writefile(szOrgFile, pvFile, cbFile))
     4572            {
     4573                FILE *pDst = openfile(pszFile, true /*fWrite*/);
     4574                if (pDst)
     4575                {
     4576                    fRc = convertOmfToOmf(pszFile, pbFile, cbFile, pDst);
     4577                    fRc = fclose(pDst) == 0 && fRc;
     4578                }
     4579            }
    37064580        }
    37074581        else
Note: See TracChangeset for help on using the changeset viewer.

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