Changeset 60265 in vbox for trunk/src/VBox
- Timestamp:
- Mar 31, 2016 12:48:14 AM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 106306
- Location:
- trunk/src/VBox/ValidationKit/bootsectors
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/ValidationKit/bootsectors/Config.kmk
r60231 r60265 90 90 TOOL_VBoxNasm_ASFLAGS ?= $(TOOL_NASM_ASFLAGS) 91 91 TOOL_VBoxNasm_COMPILE_AS_OUTPUT = $(outbase).lst 92 TOOL_VBoxNasm_COMPILE_AS_DEPEND = 92 TOOL_VBoxNasm_COMPILE_AS_DEPEND = $(VBoxBs3ObjConverter_1_TARGET) 93 93 TOOL_VBoxNasm_COMPILE_AS_DEPORD = 94 94 define TOOL_VBoxNasm_COMPILE_AS_CMDS … … 98 98 -o $(obj)\ 99 99 $(abspath $(source)) 100 $(QUIET)$(VBoxBs3ObjConverter_1_TARGET) "$(obj)" 100 101 $(QUIET)$(REDIRECT) -C $(PATH_OUT_BASE) -wo $(dep) -- $(TOOL_VBoxNasm_AS)\ 101 102 $(flags) $(addsuffix /,$(addprefix -i, $(incs))) $(addprefix -D, $(defs))\ … … 367 368 # Debug info format depends on what we use for 64-bit. 368 369 if1of ($(KBUILD_HOST), win) 369 BS3_OW_DBG_OPT = -hc 370 BS3_OW_DBG_OPT = -hc -d1+ 371 #BS3_OW_DBG_OPT = -hd -d1+ 370 372 BS3_OW_DBG_LDOPT = codeview 371 373 else 372 BS3_OW_DBG_OPT = -hd 374 BS3_OW_DBG_OPT = -hd -d1+ 373 375 BS3_OW_DBG_LDOPT = dwarf 374 376 endif … … 399 401 # Note! Using -d1 as -d1+ and -d2 causes suboptimal code to be generated (strlen 400 402 # 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. 401 405 # Note! Optimization options should come after debug stuff as -d2 for instance 402 406 # disables all optimziations. … … 458 462 TEMPLATE_VBoxBS3KitImg_CXXTOOL = Bs3Ow16 459 463 TEMPLATE_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+ 461 465 TEMPLATE_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+ 463 467 TEMPLATE_VBoxBS3KitImg_CDEFS = ARCH_BITS=16 RT_ARCH_X86 464 468 … … 586 590 TEMPLATE_VBoxBS3KitImg32_CXXTOOL = Bs3Ow32 587 591 TEMPLATE_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+ 589 593 TEMPLATE_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+ 591 595 TEMPLATE_VBoxBS3KitImg32_INCS = $(VBOX_PATH_BS3KIT_SRC) . 592 596 TEMPLATE_VBoxBS3KitImg32_LDTOOL = VBoxBsUnusedLd … … 611 615 TEMPLATE_VBoxBS3KitImg64_CTOOL := Bs3Vcc64 612 616 TEMPLATE_VBoxBS3KitImg64_CXXTOOL := Bs3Vcc64 613 TEMPLATE_VBoxBS3KitImg64_CFLAGS = -Z i-O1 -Oi -GF -GS- -Gy -Gs65536614 TEMPLATE_VBoxBS3KitImg64_CXXFLAGS = -Z i-O1 -Oi -GF -GS- -Gy -Gs65536617 TEMPLATE_VBoxBS3KitImg64_CFLAGS = -Z7 -O1 -Oi -GF -GS- -Gy -Gs65536 618 TEMPLATE_VBoxBS3KitImg64_CXXFLAGS = -Z7 -O1 -Oi -GF -GS- -Gy -Gs65536 615 619 else 616 620 TEMPLATE_VBoxBS3KitImg64_CTOOL := Bs3Gcc64Elf64 -
trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp
r60197 r60265 43 43 #include <iprt/formats/pecoff.h> 44 44 #include <iprt/formats/omf.h> 45 #include <iprt/formats/codeview.h> 45 46 46 47 … … 258 259 FILE *pDst; 259 260 261 /** Pointer to the table mapping from source segments/section to segdefs. */ 262 POMFTOSEGDEF paSegments; 260 263 /** Number of source segments/sections. */ 261 264 uint32_t cSegments; 262 /** Pointer to the table mapping from source segments/section to segdefs. */263 POMFTOSEGDEF paSegments;264 265 265 266 /** Number of entries in the source symbol table. */ … … 267 268 /** Pointer to the table mapping from source symbols to OMF stuff. */ 268 269 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; 269 279 270 280 /** The index of the next list of names entry. */ … … 277 287 /** The record data buffer (too large, but whatever). */ 278 288 uint8_t abData[_1K + 64]; 279 /** Alignment padding. */280 uint8_t abAlign[2];281 289 282 290 /** Current FIXUPP entry. */ … … 397 405 static bool omfWriter_RecAddBytes(POMFWRITER pThis, const void *pvData, size_t cbData) 398 406 { 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) 400 409 { 401 410 memcpy(&pThis->abData[pThis->cbRec], pvData, cbData); … … 403 412 return true; 404 413 } 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); 406 416 } 407 417 … … 476 486 } 477 487 478 static bool omfWriter_LNamesBegin(POMFWRITER pThis )488 static bool omfWriter_LNamesBegin(POMFWRITER pThis, bool fAddZeroEntry) 479 489 { 480 490 /* First entry is an empty string. */ 481 491 return omfWriter_RecBegin(pThis, OMF_LNAMES) 482 492 && ( pThis->idxNextName > 1 493 || !fAddZeroEntry 483 494 || omfWriter_LNamesAddN(pThis, "", 0, NULL)); 484 495 } … … 576 587 * EXTDEF - Add an entry, split record if necessary. 577 588 */ 578 static bool omfWriter_ExtDefAddN(POMFWRITER pThis, const char *pchString, size_t cchString )589 static bool omfWriter_ExtDefAddN(POMFWRITER pThis, const char *pchString, size_t cchString, uint16_t idxType) 579 590 { 580 591 /* Split? */ … … 590 601 591 602 return omfWriter_RecAddStringN(pThis, pchString, cchString) 592 && omfWriter_RecAddIdx(pThis, 0); /* type */603 && omfWriter_RecAddIdx(pThis, idxType); /* type */ 593 604 } 594 605 … … 598 609 static bool omfWriter_ExtDefAdd(POMFWRITER pThis, const char *pszString) 599 610 { 600 return omfWriter_ExtDefAddN(pThis, pszString, strlen(pszString) );611 return omfWriter_ExtDefAddN(pThis, pszString, strlen(pszString), 0); 601 612 } 602 613 … … 621 632 } 622 633 634 623 635 /** 624 636 * LEDATA + FIXUPP - Begin records. 625 637 */ 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) 638 static 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 */ 662 static bool omfWriter_LEDataBeginEx(POMFWRITER pThis, uint16_t idxSeg, uint32_t offSeg, 663 uint32_t cbData, uint32_t cbRawData, void const *pbRawData, uint8_t **ppbData) 628 664 { 629 665 if ( omfWriter_RecBegin(pThis, OMF_LEDATA32) … … 643 679 memset(&pbDst[cbRawData], 0, cbData - cbRawData); 644 680 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; 646 686 647 687 /* Reset the associated FIXUPP records. */ … … 736 776 737 777 /** 778 * LEDATA + FIXUPP - Add simple fixup, split if necessary. 779 */ 780 static 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 /** 738 789 * LEDATA + FIXUPP - End of records. 739 790 */ … … 755 806 } 756 807 pThis->iFixupp = 0; 808 return true; 809 } 810 return false; 811 } 812 813 /** 814 * LEDATA + FIXUPP - Splits the LEDATA record. 815 */ 816 static 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 */ 825 static 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 */ 835 static 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 */ 846 static 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 */ 874 static 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 */ 888 static 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 */ 902 static 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; 757 908 return true; 758 909 } … … 1047 1198 uint16_t idxGrpFlat, idxGrpData; 1048 1199 uint16_t idxClassCode, idxClassData, idxClassDwarf; 1049 if ( !omfWriter_LNamesBegin(pThis )1200 if ( !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/) 1050 1201 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat) 1051 1202 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData) … … 1494 1645 */ 1495 1646 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)) 1497 1648 return false; 1498 1649 … … 1790 1941 uint16_t idxGrpFlat, idxGrpData; 1791 1942 uint16_t idxClassCode, idxClassData, idxClassDebugSymbols, idxClassDebugTypes; 1792 if ( !omfWriter_LNamesBegin(pThis )1943 if ( !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/) 1793 1944 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat) 1794 1945 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData) … … 2323 2474 */ 2324 2475 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)) 2326 2477 return false; 2327 2478 … … 2782 2933 uint16_t idxGrpFlat, idxGrpData; 2783 2934 uint16_t idxClassCode, idxClassData, idxClassDwarf; 2784 if ( !omfWriter_LNamesBegin(pThis )2935 if ( !omfWriter_LNamesBegin(pThis, true /*fAddZeroEntry*/) 2785 2936 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat) 2786 2937 || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData) … … 3209 3360 */ 3210 3361 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)) 3212 3363 return false; 3213 3364 … … 3440 3591 3441 3592 /** 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 */ 3595 typedef 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; 3606 typedef OMFFILEINES *POMFFILEINES; 3607 3608 /** 3609 * Records line number information for a segment (for CV8 debug info). 3610 */ 3611 typedef 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; 3622 typedef OMFSEGLINES *POMFSEGLINES; 3623 3624 /** 3625 * OMF conversion details. 3444 3626 * 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. 3449 3628 */ 3450 static bool convertomf(const char *pszFile, uint8_t *pbFile, size_t cbFile, const char **papchLNames, uint32_t cLNamesMax) 3629 typedef 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; 3663 typedef OMFDETAILS *POMFDETAILS; 3664 typedef 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 */ 3677 static 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 */ 3748 static 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 */ 3849 static bool collectOmfDetails(const char *pszFile, uint8_t const *pbFile, size_t cbFile, POMFDETAILS pOmfStuff) 3451 3850 { 3452 3851 uint32_t cLNames = 0; 3453 3852 uint32_t cExtDefs = 0; 3454 3853 uint32_t cPubDefs = 0; 3455 bool fProbably32bit = false;3456 3854 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; 3457 3863 3458 3864 while (off + 3 < cbFile) … … 3465 3871 return error(pszFile, "Invalid record length at %#x: %#x (cbFile=%#lx)\n", off, cbRec, (unsigned long)cbFile); 3466 3872 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]; 3472 3875 #define OMF_CHECK_RET(a_cbReq, a_Name) /* Not taking the checksum into account, so we're good with 1 or 2 byte fields. */ \ 3473 3876 if (offRec + (a_cbReq) <= cbRec) {/*likely*/} \ 3474 3877 else return error(pszFile, "Malformed " #a_Name "! off=%#x offRec=%#x cbRec=%#x cbNeeded=%#x line=%d\n", \ 3475 3878 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 3476 3887 switch (bRecType) 3477 3888 { 3478 3889 /* 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. 3480 3922 */ 3481 3923 case OMF_EXTDEF: 3482 {3483 3924 while (offRec + 1 < cbRec) 3484 3925 { … … 3488 3929 offRec += cch; 3489 3930 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); 3494 3933 3495 3934 if (g_cVerbose > 2) … … 3499 3938 3500 3939 /* Look for g_apszExtDefRenames entries that requires changing. */ 3501 if ( cch >= 5 3940 if ( !pOmfStuff->fMayNeedMangling 3941 && cch >= 5 3502 3942 && cch <= 7 3503 3943 && pchName[0] == '_' … … 3511 3951 || pchName[3] == 'T') ) 3512 3952 { 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; 3522 3954 } 3523 3524 cExtDefs++;3525 3955 } 3526 3956 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 }3554 3957 3555 3958 /* 3556 3959 * Display public names if -v is specified. 3557 3960 */ 3961 case OMF_PUBDEF32: 3962 case OMF_LPUBDEF32: 3963 pOmfStuff->fProbably32bit = true; 3558 3964 case OMF_PUBDEF16: 3559 case OMF_PUBDEF32:3560 3965 case OMF_LPUBDEF16: 3561 case OMF_LPUBDEF32:3562 {3563 3966 if (g_cVerbose > 0) 3564 3967 { … … 3568 3971 pszRec++; 3569 3972 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); 3579 3978 3580 3979 uint16_t uFrameBase = 0; … … 3610 4009 } 3611 4010 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); 3616 4013 3617 4014 if (g_cVerbose > 2) … … 3619 4016 else if (g_cVerbose > 0) 3620 4017 printf("%04x:%08x %c %-*.*s\n", uSeg, offSeg, chType, cch, cch, pchName); 3621 3622 cPubDefs++;3623 4018 } 3624 4019 } 3625 4020 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; 3626 4098 } 3627 4099 } … … 3630 4102 off += cbRec + 3; 3631 4103 } 4104 3632 4105 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 */ 4118 static 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 */ 4177 static 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 */ 4280 static 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 */ 4465 static 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; 3633 4503 } 3634 4504 … … 3699 4569 && RT_MAKE_U16(pbFile[1], pbFile[2]) < cbFile) 3700 4570 { 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 } 3706 4580 } 3707 4581 else
Note:
See TracChangeset
for help on using the changeset viewer.