VirtualBox

Changeset 60139 in vbox


Ignore:
Timestamp:
Mar 22, 2016 7:18:42 PM (9 years ago)
Author:
vboxsync
Message:

VBoxBs3ObjConverter: Fixed ELF bugs, output now links.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/ValidationKit/bootsectors/bs3kit/VBoxBs3ObjConverter.cpp

    r60137 r60139  
    665665    if (pThis->aFixupps[iFixupp].cbRec + cbSubRec >= OMF_MAX_RECORD_PAYLOAD)
    666666    {
     667        if (g_cVerbose >= 2)
     668            printf("debug: FIXUPP split\n");
    667669        iFixupp++;
    668670        if (iFixupp >= RT_ELEMENTS(pThis->aFixupps))
     
    695697        || idxTarget >= _32K
    696698        || fTargetDisp != (bTarget <= OMF_FIX_T_FRAME_NO) )
    697         /*return*/ error(pThis->pszSrc,
     699        return error(pThis->pszSrc,
    698700                     "Internal error: offDataRec=%#x bFrame=%u idxFrame=%#x bTarget=%u idxTarget=%#x fTargetDisp=%d offTargetDisp=%#x\n",
    699701                     offDataRec, bFrame, idxFrame, bTarget, idxTarget, fTargetDisp, offTargetDisp);
     
    742744        for (unsigned iFixupp = 0; iFixupp <= pThis->iFixupp; iFixupp++)
    743745        {
    744             uint8_t const cbRec = pThis->aFixupps[iFixupp].cbRec;
     746            uint16_t const cbRec = pThis->aFixupps[iFixupp].cbRec;
    745747            if (!cbRec)
    746748                break;
     749            if (g_cVerbose >= 3)
     750                printf("debug: FIXUPP32 #%u cbRec=%#x\n", iFixupp, cbRec);
    747751            if (   !omfWriter_RecBegin(pThis, OMF_FIXUPP32)
    748752                || !omfWriter_RecAddBytes(pThis, pThis->aFixupps[iFixupp].abData, cbRec)
     
    10341038    return fRet;
    10351039}
    1036 
    1037 #define ELF_TO_OMF_CONVERSION
    1038 
    1039 #ifdef ELF_TO_OMF_CONVERSION
    10401040
    10411041
     
    14851485                    return error(pThis->pszSrc, "Wtf? cbVirtData is zero!\n");
    14861486            }
     1487            if (g_cVerbose >= 2)
     1488                printf("debug: LEDATA off=%#x cb=%#x cRelocs=%#x sect=#%u segdef=%#x grpdef=%#x '%s'\n",
     1489                       off, cbChunk, cRelocs, i, pThis->paSegments[i].iSegDef, pThis->paSegments[i].iGrpDef, pszSegNm);
    14871490
    14881491            /*
     
    16791682    return false;
    16801683}
    1681 
    1682 #else /* !ELF_TO_OMF_CONVERSION */
    1683 
    1684 static bool convertelf(const char *pszFile, uint8_t *pbFile, size_t cbFile)
    1685 {
    1686     /*
    1687      * Validate the header and our other expectations.
    1688      */
    1689     ELFDETAILS ElfStuff;
    1690     if (!validateElf(pszFile, pbFile, cbFile, &ElfStuff))
    1691         return false;
    1692 
    1693     /*
    1694      * Locate the section name string table.
    1695      * We assume it's okay as we only reference it in verbose mode.
    1696      */
    1697     Elf64_Ehdr const   *pEhdr     = (Elf64_Ehdr const *)pbFile;
    1698     Elf64_Shdr const   *paShdrs   = (Elf64_Shdr const *)&pbFile[pEhdr->e_shoff];
    1699     const char         *pszStrTab = (const char *)&pbFile[paShdrs[pEhdr->e_shstrndx].sh_offset];
    1700 
    1701     /*
    1702      * Work the section table.
    1703      */
    1704     for (uint32_t i = 1; i < pEhdr->e_shnum; i++)
    1705     {
    1706         if (g_cVerbose)
    1707             printf("shdr[%u]: name=%#x '%s' type=%#x flags=%#" ELF_FMT_X64 " addr=%#" ELF_FMT_X64 " off=%#" ELF_FMT_X64 " size=%#" ELF_FMT_X64 "\n"
    1708                    "          link=%u info=%#x align=%#" ELF_FMT_X64 " entsize=%#" ELF_FMT_X64 "\n",
    1709                    i, paShdrs[i].sh_name, &pszStrTab[paShdrs[i].sh_name], paShdrs[i].sh_type, paShdrs[i].sh_flags,
    1710                    paShdrs[i].sh_addr, paShdrs[i].sh_offset, paShdrs[i].sh_size,
    1711                    paShdrs[i].sh_link, paShdrs[i].sh_info, paShdrs[i].sh_addralign, paShdrs[i].sh_entsize);
    1712         if (paShdrs[i].sh_type == SHT_RELA)
    1713         {
    1714             Elf64_Rela    *paRelocs = (Elf64_Rela *)&pbFile[paShdrs[i].sh_offset];
    1715             uint32_t const cRelocs  = paShdrs[i].sh_size / sizeof(Elf64_Rela);
    1716             for (uint32_t j = 0; j < cRelocs; j++)
    1717             {
    1718                 uint32_t const uType = ELF64_R_TYPE(paRelocs[j].r_info);
    1719                 if (g_cVerbose > 1)
    1720                     printf("%#018" ELF_FMT_X64 "  %#018" ELF_FMT_X64 " %s  %+" ELF_FMT_D64 "\n", paRelocs[j].r_offset, paRelocs[j].r_info,
    1721                            uType < RT_ELEMENTS(g_apszElfAmd64RelTypes) ? g_apszElfAmd64RelTypes[uType] : "unknown", paRelocs[j].r_addend);
    1722 
    1723                 /* Truncate 64-bit wide absolute relocations, ASSUMING that the high bits
    1724                    are already zero and won't be non-zero after calculating the fixup value. */
    1725                 if (uType == R_X86_64_64)
    1726                 {
    1727                     paRelocs[j].r_info &= ~(uint64_t)0xff;
    1728                     paRelocs[j].r_info |= R_X86_64_32;
    1729                 }
    1730             }
    1731         }
    1732         else if (paShdrs[i].sh_type == SHT_REL)
    1733             return error(pszFile, "Did not expect SHT_REL sections (#%u '%s')\n", i, &pszStrTab[paShdrs[i].sh_name]);
    1734     }
    1735     return true;
    1736 }
    1737 
    1738 #endif /* !ELF_TO_OMF_CONVERSION */
    1739 
    17401684
    17411685
     
    25832527
    25842528
     2529/*********************************************************************************************************************************
     2530*   Mach-O/AMD64 -> OMF/i386 Converter                                                                                           *
     2531*********************************************************************************************************************************/
     2532
     2533//#define MACHO_TO_OMF_CONVERSION
     2534#ifdef MACHO_TO_OMF_CONVERSION
     2535
     2536/** AMD64 relocation type names for Mach-O. */
     2537static const char * const g_apszMachOAmd64RelTypes[] =
     2538{
     2539    "X86_64_RELOC_UNSIGNED",
     2540    "X86_64_RELOC_SIGNED",
     2541    "X86_64_RELOC_BRANCH",
     2542    "X86_64_RELOC_GOT_LOAD",
     2543    "X86_64_RELOC_GOT",
     2544    "X86_64_RELOC_SUBTRACTOR",
     2545    "X86_64_RELOC_SIGNED_1",
     2546    "X86_64_RELOC_SIGNED_2",
     2547    "X86_64_RELOC_SIGNED_4"
     2548};
     2549
     2550/** AMD64 relocation type sizes for Mach-O. */
     2551static uint8_t const g_acbMachOAmd64RelTypes[] =
     2552{
     2553    8, /* X86_64_RELOC_UNSIGNED */
     2554    4, /* X86_64_RELOC_SIGNED */
     2555    4, /* X86_64_RELOC_BRANCH */
     2556    4, /* X86_64_RELOC_GOT_LOAD */
     2557    4, /* X86_64_RELOC_GOT */
     2558    8, /* X86_64_RELOC_SUBTRACTOR */
     2559    4, /* X86_64_RELOC_SIGNED_1 */
     2560    4, /* X86_64_RELOC_SIGNED_2 */
     2561    4, /* X86_64_RELOC_SIGNED_4 */
     2562};
     2563
     2564/** Macro for getting the size of a AMD64 ELF relocation. */
     2565#define ELF_AMD64_RELOC_SIZE(a_Type) ( (a_Type) < RT_ELEMENTS(g_acbElfAmd64RelTypes) ? g_acbElfAmd64RelTypes[(a_Type)] : 1)
     2566
     2567
     2568typedef struct ELFDETAILS
     2569{
     2570    /** The ELF header. */
     2571    Elf64_Ehdr const   *pEhdr;
     2572    /** The section header table.   */
     2573    Elf64_Shdr const   *paShdrs;
     2574    /** The string table for the section names. */
     2575    const char         *pchShStrTab;
     2576
     2577    /** The symbol table section number. UINT16_MAX if not found.   */
     2578    uint16_t            iSymSh;
     2579    /** The string table section number. UINT16_MAX if not found. */
     2580    uint16_t            iStrSh;
     2581
     2582    /** The symbol table.   */
     2583    Elf64_Sym const    *paSymbols;
     2584    /** The number of symbols in the symbol table. */
     2585    uint32_t            cSymbols;
     2586
     2587    /** Pointer to the (symbol) string table if found. */
     2588    const char         *pchStrTab;
     2589    /** The string table size. */
     2590    size_t              cbStrTab;
     2591
     2592} ELFDETAILS;
     2593typedef ELFDETAILS *PELFDETAILS;
     2594typedef ELFDETAILS const *PCELFDETAILS;
     2595
     2596
     2597static bool validateElf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, PELFDETAILS pElfStuff)
     2598{
     2599    /*
     2600     * Initialize the ELF details structure.
     2601     */
     2602    memset(pElfStuff, 0,  sizeof(*pElfStuff));
     2603    pElfStuff->iSymSh = UINT16_MAX;
     2604    pElfStuff->iStrSh = UINT16_MAX;
     2605
     2606    /*
     2607     * Validate the header and our other expectations.
     2608     */
     2609    Elf64_Ehdr const *pEhdr = (Elf64_Ehdr const *)pbFile;
     2610    pElfStuff->pEhdr = pEhdr;
     2611    if (   pEhdr->e_ident[EI_CLASS] != ELFCLASS64
     2612        || pEhdr->e_ident[EI_DATA]  != ELFDATA2LSB
     2613        || pEhdr->e_ehsize          != sizeof(Elf64_Ehdr)
     2614        || pEhdr->e_shentsize       != sizeof(Elf64_Shdr)
     2615        || pEhdr->e_version         != EV_CURRENT )
     2616        return error(pszFile, "Unsupported ELF config\n");
     2617    if (pEhdr->e_type != ET_REL)
     2618        return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_type);
     2619    if (pEhdr->e_machine != EM_X86_64)
     2620        return error(pszFile, "Expected relocatable ELF file (e_type=%d)\n", pEhdr->e_machine);
     2621    if (pEhdr->e_phnum != 0)
     2622        return error(pszFile, "Expected e_phnum to be zero not %u\n", pEhdr->e_phnum);
     2623    if (pEhdr->e_shnum < 2)
     2624        return error(pszFile, "Expected e_shnum to be two or higher\n");
     2625    if (pEhdr->e_shstrndx >= pEhdr->e_shnum || pEhdr->e_shstrndx == 0)
     2626        return error(pszFile, "Bad e_shstrndx=%u (e_shnum=%u)\n", pEhdr->e_shstrndx, pEhdr->e_shnum);
     2627    if (   pEhdr->e_shoff >= cbFile
     2628        || pEhdr->e_shoff + pEhdr->e_shnum * sizeof(Elf64_Shdr) > cbFile)
     2629        return error(pszFile, "Section table is outside the file (e_shoff=%#llx, e_shnum=%u, cbFile=%#llx)\n",
     2630                     pEhdr->e_shstrndx, pEhdr->e_shnum, (uint64_t)cbFile);
     2631
     2632    /*
     2633     * Locate the section name string table.
     2634     * We assume it's okay as we only reference it in verbose mode.
     2635     */
     2636    Elf64_Shdr const *paShdrs = (Elf64_Shdr const *)&pbFile[pEhdr->e_shoff];
     2637    pElfStuff->paShdrs = paShdrs;
     2638
     2639    Elf64_Xword const cbShStrTab = paShdrs[pEhdr->e_shstrndx].sh_size;
     2640    if (   paShdrs[pEhdr->e_shstrndx].sh_offset > cbFile
     2641        || cbShStrTab > cbFile
     2642        || paShdrs[pEhdr->e_shstrndx].sh_offset + cbShStrTab > cbFile)
     2643        return error(pszFile,
     2644                     "Section string table is outside the file (sh_offset=%#" ELF_FMT_X64 " sh_size=%#" ELF_FMT_X64 " cbFile=%#" ELF_FMT_X64 ")\n",
     2645                     paShdrs[pEhdr->e_shstrndx].sh_offset, paShdrs[pEhdr->e_shstrndx].sh_size, (Elf64_Xword)cbFile);
     2646    const char *pchShStrTab = (const char *)&pbFile[paShdrs[pEhdr->e_shstrndx].sh_offset];
     2647    pElfStuff->pchShStrTab = pchShStrTab;
     2648
     2649    /*
     2650     * Work the section table.
     2651     */
     2652    bool fRet = true;
     2653    for (uint32_t i = 1; i < pEhdr->e_shnum; i++)
     2654    {
     2655        if (paShdrs[i].sh_name >= cbShStrTab)
     2656            return error(pszFile, "Invalid sh_name value (%#x) for section #%u\n", paShdrs[i].sh_name, i);
     2657        const char *pszShNm = &pchShStrTab[paShdrs[i].sh_name];
     2658
     2659        if (   paShdrs[i].sh_offset > cbFile
     2660            || paShdrs[i].sh_size > cbFile
     2661            || paShdrs[i].sh_offset + paShdrs[i].sh_size > cbFile)
     2662            return error(pszFile, "Section #%u '%s' has data outside the file: %#" ELF_FMT_X64 " LB %#" ELF_FMT_X64 " (cbFile=%#" ELF_FMT_X64 ")\n",
     2663                         i, pszShNm, paShdrs[i].sh_offset, paShdrs[i].sh_size, (Elf64_Xword)cbFile);
     2664        if (g_cVerbose)
     2665            printf("shdr[%u]: name=%#x '%s' type=%#x flags=%#" ELF_FMT_X64 " addr=%#" ELF_FMT_X64 " off=%#" ELF_FMT_X64 " size=%#" ELF_FMT_X64 "\n"
     2666                   "          link=%u info=%#x align=%#" ELF_FMT_X64 " entsize=%#" ELF_FMT_X64 "\n",
     2667                   i, paShdrs[i].sh_name, pszShNm, paShdrs[i].sh_type, paShdrs[i].sh_flags,
     2668                   paShdrs[i].sh_addr, paShdrs[i].sh_offset, paShdrs[i].sh_size,
     2669                   paShdrs[i].sh_link, paShdrs[i].sh_info, paShdrs[i].sh_addralign, paShdrs[i].sh_entsize);
     2670
     2671        if (paShdrs[i].sh_link >= pEhdr->e_shnum)
     2672            return error(pszFile, "Section #%u '%s' links to a section outside the section table: %#x, max %#x\n",
     2673                         i, pszShNm, paShdrs[i].sh_link, pEhdr->e_shnum);
     2674        if (!RT_IS_POWER_OF_TWO(paShdrs[i].sh_addralign))
     2675            return error(pszFile, "Section #%u '%s' alignment value is not a power of two: %#" ELF_FMT_X64 "\n",
     2676                         i, pszShNm, paShdrs[i].sh_addralign);
     2677        if (!RT_IS_POWER_OF_TWO(paShdrs[i].sh_addralign))
     2678            return error(pszFile, "Section #%u '%s' alignment value is not a power of two: %#" ELF_FMT_X64 "\n",
     2679                         i, pszShNm, paShdrs[i].sh_addralign);
     2680        if (paShdrs[i].sh_addr != 0)
     2681            return error(pszFile, "Section #%u '%s' has non-zero address: %#" ELF_FMT_X64 "\n", i, pszShNm, paShdrs[i].sh_addr);
     2682
     2683        if (paShdrs[i].sh_type == SHT_RELA)
     2684        {
     2685            if (paShdrs[i].sh_entsize != sizeof(Elf64_Rela))
     2686                return error(pszFile, "Expected sh_entsize to be %u not %u for section #%u (%s)\n", (unsigned)sizeof(Elf64_Rela),
     2687                             paShdrs[i].sh_entsize, i, pszShNm);
     2688            uint32_t const cRelocs = paShdrs[i].sh_size / sizeof(Elf64_Rela);
     2689            if (cRelocs * sizeof(Elf64_Rela) != paShdrs[i].sh_size)
     2690                return error(pszFile, "Uneven relocation entry count in #%u (%s): sh_size=%#" ELF_FMT_X64 "\n",
     2691                             i, pszShNm, paShdrs[i].sh_size);
     2692            if (   paShdrs[i].sh_offset > cbFile
     2693                || paShdrs[i].sh_size  >= cbFile
     2694                || paShdrs[i].sh_offset + paShdrs[i].sh_size > cbFile)
     2695                return error(pszFile, "The content of section #%u '%s' is outside the file (%#" ELF_FMT_X64 " LB %#" ELF_FMT_X64 ", cbFile=%#lx)\n",
     2696                             i, pszShNm, paShdrs[i].sh_offset, paShdrs[i].sh_size, (unsigned long)cbFile);
     2697            if (paShdrs[i].sh_info != i - 1)
     2698                return error(pszFile, "Expected relocation section #%u (%s) to link to previous section: sh_info=%#u\n",
     2699                             i, pszShNm, (unsigned)paShdrs[i].sh_link);
     2700            if (paShdrs[paShdrs[i].sh_link].sh_type != SHT_SYMTAB)
     2701                return error(pszFile, "Expected relocation section #%u (%s) to link to symbol table: sh_link=%#u -> sh_type=%#x\n",
     2702                             i, pszShNm, (unsigned)paShdrs[i].sh_link, (unsigned)paShdrs[paShdrs[i].sh_link].sh_type);
     2703            uint32_t cSymbols = paShdrs[paShdrs[i].sh_link].sh_size / paShdrs[paShdrs[i].sh_link].sh_entsize;
     2704
     2705            Elf64_Rela const  *paRelocs = (Elf64_Rela *)&pbFile[paShdrs[i].sh_offset];
     2706            for (uint32_t j = 0; j < cRelocs; j++)
     2707            {
     2708                uint8_t const bType = ELF64_R_TYPE(paRelocs[j].r_info);
     2709                if (RT_UNLIKELY(bType >= R_X86_64_COUNT))
     2710                    fRet = error(pszFile,
     2711                                 "%#018" ELF_FMT_X64 "  %#018" ELF_FMT_X64 ": unknown fix up %#x  (%+" ELF_FMT_D64 ")\n",
     2712                                 paRelocs[j].r_offset, paRelocs[j].r_info, bType, paRelocs[j].r_addend);
     2713                if (RT_UNLIKELY(   j > 1
     2714                                && paRelocs[j].r_offset <= paRelocs[j - 1].r_offset
     2715                                &&   paRelocs[j].r_offset + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[j].r_info))
     2716                                   < paRelocs[j - 1].r_offset ))
     2717                    fRet = error(pszFile,
     2718                                 "%#018" ELF_FMT_X64 "  %#018" ELF_FMT_X64 ": out of offset order (prev %" ELF_FMT_X64 ")\n",
     2719                                 paRelocs[j].r_offset, paRelocs[j].r_info, paRelocs[j - 1].r_offset);
     2720                uint32_t const iSymbol = ELF64_R_SYM(paRelocs[j].r_info);
     2721                if (RT_UNLIKELY(iSymbol >= cSymbols))
     2722                    fRet = error(pszFile,
     2723                                 "%#018" ELF_FMT_X64 "  %#018" ELF_FMT_X64 ": symbol index (%#x) out of bounds (%#x)\n",
     2724                                 paRelocs[j].r_offset, paRelocs[j].r_info, iSymbol, cSymbols);
     2725            }
     2726            if (RT_UNLIKELY(   cRelocs > 0
     2727                            && fRet
     2728                            && (   paRelocs[cRelocs - 1].r_offset > paShdrs[i - 1].sh_size
     2729                                || paRelocs[cRelocs - 1].r_offset + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[cRelocs-1].r_info))
     2730                                   > paShdrs[i - 1].sh_size )))
     2731                fRet = error(pszFile,
     2732                             "%#018" ELF_FMT_X64 "  %#018" ELF_FMT_X64 ": out of bounds (sh_size %" ELF_FMT_X64 ")\n",
     2733                             paRelocs[cRelocs - 1].r_offset, paRelocs[cRelocs - 1].r_info, paShdrs[i - 1].sh_size);
     2734
     2735        }
     2736        else if (paShdrs[i].sh_type == SHT_REL)
     2737            fRet = error(pszFile, "Section #%u '%s': Unexpected SHT_REL section\n", i, pszShNm);
     2738        else if (paShdrs[i].sh_type == SHT_SYMTAB)
     2739        {
     2740            if (paShdrs[i].sh_entsize != sizeof(Elf64_Sym))
     2741                fRet = error(pszFile, "Section #%u '%s': Unsupported symbol table entry size in : #%u (expected #%u)\n",
     2742                             i, pszShNm, paShdrs[i].sh_entsize, sizeof(Elf64_Sym));
     2743            Elf64_Xword const cSymbols = paShdrs[i].sh_size / paShdrs[i].sh_entsize;
     2744            if (cSymbols * paShdrs[i].sh_entsize != paShdrs[i].sh_size)
     2745                fRet = error(pszFile, "Section #%u '%s': Size not a multiple of entry size: %#" ELF_FMT_X64 " %% %#" ELF_FMT_X64 " = %#" ELF_FMT_X64 "\n",
     2746                             i, pszShNm, paShdrs[i].sh_size, paShdrs[i].sh_entsize, paShdrs[i].sh_size % paShdrs[i].sh_entsize);
     2747            if (cSymbols > UINT32_MAX)
     2748                fRet = error(pszFile, "Section #%u '%s': too many symbols: %" ELF_FMT_X64 "\n",
     2749                             i, pszShNm, paShdrs[i].sh_size, cSymbols);
     2750
     2751            if (pElfStuff->iSymSh == UINT16_MAX)
     2752            {
     2753                pElfStuff->iSymSh    = (uint16_t)i;
     2754                pElfStuff->paSymbols = (Elf64_Sym const *)&pbFile[paShdrs[i].sh_offset];
     2755                pElfStuff->cSymbols  = cSymbols;
     2756
     2757                if (paShdrs[i].sh_link != 0)
     2758                {
     2759                    /* Note! The symbol string table section header may not have been validated yet! */
     2760                    Elf64_Shdr const *pStrTabShdr = &paShdrs[paShdrs[i].sh_link];
     2761                    pElfStuff->iStrSh    = paShdrs[i].sh_link;
     2762                    pElfStuff->pchStrTab = (const char *)&pbFile[pStrTabShdr->sh_offset];
     2763                    pElfStuff->cbStrTab  = (size_t)pStrTabShdr->sh_size;
     2764                }
     2765                else
     2766                    fRet = error(pszFile, "Section #%u '%s': String table link is out of bounds (%#x)\n",
     2767                                 i, pszShNm, paShdrs[i].sh_link);
     2768            }
     2769            else
     2770                fRet = error(pszFile, "Section #%u '%s': Found additonal symbol table, previous in #%u\n",
     2771                             i, pszShNm, pElfStuff->iSymSh);
     2772        }
     2773    }
     2774    return fRet;
     2775}
     2776
     2777static bool convertElfSectionsToSegDefsAndGrpDefs(POMFWRITER pThis, PCELFDETAILS pElfStuff)
     2778{
     2779    /*
     2780     * Do the list of names pass.
     2781     */
     2782    uint16_t idxGrpFlat, idxGrpData;
     2783    uint16_t idxClassCode, idxClassData, idxClassDwarf;
     2784    if (   !omfWriter_LNamesBegin(pThis)
     2785        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FLAT"), &idxGrpFlat)
     2786        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3DATA64_GROUP"), &idxGrpData)
     2787        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("BS3CLASS64CODE"), &idxClassCode)
     2788        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("FAR_DATA"), &idxClassData)
     2789        || !omfWriter_LNamesAddN(pThis, RT_STR_TUPLE("DWARF"), &idxClassDwarf)
     2790       )
     2791        return false;
     2792
     2793    bool              fHaveData = false;
     2794    Elf64_Shdr const *pShdr     = &pElfStuff->paShdrs[1];
     2795    Elf64_Half const  cSections = pElfStuff->pEhdr->e_shnum;
     2796    for (Elf64_Half i = 1; i < cSections; i++, pShdr++)
     2797    {
     2798        const char *pszName = &pElfStuff->pchShStrTab[pShdr->sh_name];
     2799        if (*pszName == '\0')
     2800            return error(pThis->pszSrc, "Section #%u has an empty name!\n", i);
     2801
     2802        switch (pShdr->sh_type)
     2803        {
     2804            case SHT_PROGBITS:
     2805            case SHT_NOBITS:
     2806                /* We drop a few sections we don't want:. */
     2807                if (   strcmp(pszName, ".comment") != 0         /* compiler info  */
     2808                    && strcmp(pszName, ".note.GNU-stack") != 0  /* some empty section for hinting the linker/whatever */
     2809                    && strcmp(pszName, ".eh_frame") != 0        /* unwind / exception info */
     2810                    )
     2811                {
     2812                    pThis->paSegments[i].iSegDef  = UINT16_MAX;
     2813                    pThis->paSegments[i].iGrpDef  = UINT16_MAX;
     2814
     2815                    /* Translate the name and determine group and class.
     2816                       Note! We currently strip sub-sections. */
     2817                    if (   strcmp(pszName, ".text") == 0
     2818                        || strncmp(pszName, RT_STR_TUPLE(".text.")) == 0)
     2819                    {
     2820                        pszName = "BS3TEXT64";
     2821                        pThis->paSegments[i].iGrpNm   = idxGrpFlat;
     2822                        pThis->paSegments[i].iClassNm = idxClassCode;
     2823                    }
     2824                    else if (   strcmp(pszName, ".data") == 0
     2825                             || strncmp(pszName, RT_STR_TUPLE(".data.")) == 0)
     2826                    {
     2827                        pszName = "BS3DATA64";
     2828                        pThis->paSegments[i].iGrpNm   = idxGrpData;
     2829                        pThis->paSegments[i].iClassNm = idxClassData;
     2830                    }
     2831                    else if (strcmp(pszName, ".bss") == 0)
     2832                    {
     2833                        pszName = "BS3BSS64";
     2834                        pThis->paSegments[i].iGrpNm   = idxGrpData;
     2835                        pThis->paSegments[i].iClassNm = idxClassData;
     2836                    }
     2837                    else if (   strcmp(pszName, ".rodata") == 0
     2838                             || strncmp(pszName, RT_STR_TUPLE(".rodata.")) == 0)
     2839                    {
     2840                        pszName = "BS3DATA64CONST";
     2841                        pThis->paSegments[i].iGrpNm   = idxGrpData;
     2842                        pThis->paSegments[i].iClassNm = idxClassData;
     2843                    }
     2844                    else if (strncmp(pszName, RT_STR_TUPLE(".debug_")) == 0)
     2845                    {
     2846                        pThis->paSegments[i].iGrpNm   = UINT16_MAX;
     2847                        pThis->paSegments[i].iClassNm = idxClassDwarf;
     2848                    }
     2849                    else
     2850                    {
     2851                        pThis->paSegments[i].iGrpNm   = idxGrpData;
     2852                        pThis->paSegments[i].iClassNm = idxClassData;
     2853                        error(pThis->pszSrc, "Unknown data (?) segment: '%s'\n", pszName);
     2854                    }
     2855
     2856                    /* Save the name. */
     2857                    pThis->paSegments[i].pszName  = strdup(pszName);
     2858                    if (!pThis->paSegments[i].pszName)
     2859                        return error(pThis->pszSrc, "Out of memory!\n");
     2860
     2861                    /* Add the section name. */
     2862                    if (!omfWriter_LNamesAdd(pThis, pThis->paSegments[i].pszName, &pThis->paSegments[i].iSegNm))
     2863                        return false;
     2864
     2865                    fHaveData |= pThis->paSegments[i].iGrpDef == idxGrpData;
     2866                    break;
     2867                }
     2868                /* fall thru */
     2869
     2870            default:
     2871                pThis->paSegments[i].iSegDef  = UINT16_MAX;
     2872                pThis->paSegments[i].iGrpDef  = UINT16_MAX;
     2873                pThis->paSegments[i].iSegNm   = UINT16_MAX;
     2874                pThis->paSegments[i].iGrpNm   = UINT16_MAX;
     2875                pThis->paSegments[i].iClassNm = UINT16_MAX;
     2876                pThis->paSegments[i].pszName  = NULL;
     2877                break;
     2878        }
     2879    }
     2880
     2881    if (!omfWriter_LNamesEnd(pThis))
     2882        return false;
     2883
     2884    /*
     2885     * Emit segment definitions.
     2886     */
     2887    uint16_t iSegDef = 1; /* Start counting at 1. */
     2888    pShdr = &pElfStuff->paShdrs[1];
     2889    for (Elf64_Half i = 1; i < cSections; i++, pShdr++)
     2890    {
     2891        if (pThis->paSegments[i].iSegNm == UINT16_MAX)
     2892            continue;
     2893
     2894        uint8_t bSegAttr = 0;
     2895
     2896        /* The A field. */
     2897        switch (pShdr->sh_addralign)
     2898        {
     2899            case 0:
     2900            case 1:
     2901                bSegAttr |= 1 << 5;
     2902                break;
     2903            case 2:
     2904                bSegAttr |= 2 << 5;
     2905                break;
     2906            case 4:
     2907                bSegAttr |= 5 << 5;
     2908                break;
     2909            case 8:
     2910            case 16:
     2911                bSegAttr |= 3 << 5;
     2912                break;
     2913            case 32:
     2914            case 64:
     2915            case 128:
     2916            case 256:
     2917                bSegAttr |= 4 << 5;
     2918                break;
     2919            default:
     2920                bSegAttr |= 6 << 5; /* page aligned, pharlabs extension. */
     2921                break;
     2922        }
     2923
     2924        /* The C field. */
     2925        bSegAttr |= 2 << 2; /* public */
     2926
     2927        /* The B field. We don't have 4GB segments, so leave it as zero. */
     2928
     2929        /* The D field shall be set as we're doing USE32.  */
     2930        bSegAttr |= 1;
     2931
     2932
     2933        /* Done. */
     2934        if (!omfWriter_SegDef(pThis, bSegAttr, (uint32_t)pShdr->sh_size,
     2935                              pThis->paSegments[i].iSegNm,
     2936                              pThis->paSegments[i].iClassNm))
     2937            return false;
     2938        pThis->paSegments[i].iSegDef = iSegDef++;
     2939    }
     2940
     2941    /*
     2942     * Flat group definition (#1) - special, no members.
     2943     */
     2944    uint16_t iGrpDef = 1;
     2945    if (   !omfWriter_GrpDefBegin(pThis, idxGrpFlat)
     2946        || !omfWriter_GrpDefEnd(pThis))
     2947        return false;
     2948    for (uint16_t i = 0; i < cSections; i++)
     2949        if (pThis->paSegments[i].iGrpNm == idxGrpFlat)
     2950            pThis->paSegments[i].iGrpDef = iGrpDef;
     2951    pThis->idxGrpFlat = iGrpDef++;
     2952
     2953    /*
     2954     * Data group definition (#2).
     2955     */
     2956    /** @todo do we need to consider missing segments and ordering? */
     2957    uint16_t cGrpNms = 0;
     2958    uint16_t aiGrpNms[2];
     2959    if (fHaveData)
     2960        aiGrpNms[cGrpNms++] = idxGrpData;
     2961    for (uint32_t iGrpNm = 0; iGrpNm < cGrpNms; iGrpNm++)
     2962    {
     2963        if (!omfWriter_GrpDefBegin(pThis, aiGrpNms[iGrpNm]))
     2964            return false;
     2965        for (uint16_t i = 0; i < cSections; i++)
     2966            if (pThis->paSegments[i].iGrpNm == aiGrpNms[iGrpNm])
     2967            {
     2968                pThis->paSegments[i].iGrpDef = iGrpDef;
     2969                if (!omfWriter_GrpDefAddSegDef(pThis, pThis->paSegments[i].iSegDef))
     2970                    return false;
     2971            }
     2972        if (!omfWriter_GrpDefEnd(pThis))
     2973            return false;
     2974        iGrpDef++;
     2975    }
     2976
     2977    return true;
     2978}
     2979
     2980static bool convertElfSymbolsToPubDefsAndExtDefs(POMFWRITER pThis, PCELFDETAILS pElfStuff)
     2981{
     2982    if (!pElfStuff->cSymbols)
     2983        return true;
     2984
     2985    /*
     2986     * Process the symbols the first.
     2987     */
     2988    uint32_t cAbsSyms = 0;
     2989    uint32_t cExtSyms = 0;
     2990    uint32_t cPubSyms = 0;
     2991    for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++)
     2992        pThis->paSegments[iSeg].cPubDefs = 0;
     2993
     2994    uint32_t const          cSections = pElfStuff->pEhdr->e_shnum;
     2995    uint32_t const          cSymbols  = pElfStuff->cSymbols;
     2996    Elf64_Sym const * const paSymbols = pElfStuff->paSymbols;
     2997    for (uint32_t iSym = 0; iSym < cSymbols; iSym++)
     2998    {
     2999        const uint8_t bBind      = ELF64_ST_BIND(paSymbols[iSym].st_info);
     3000        const uint8_t bType      = ELF64_ST_TYPE(paSymbols[iSym].st_info);
     3001        const char   *pszSymName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name];
     3002        if (   *pszSymName == '\0'
     3003            && bType == STT_SECTION
     3004            && paSymbols[iSym].st_shndx < cSections)
     3005            pszSymName = &pElfStuff->pchShStrTab[pElfStuff->paShdrs[paSymbols[iSym].st_shndx].sh_name];
     3006
     3007        pThis->paSymbols[iSym].enmType   = OMFSYMTYPE_IGNORED;
     3008        pThis->paSymbols[iSym].idx       = UINT16_MAX;
     3009        pThis->paSymbols[iSym].idxSegDef = UINT16_MAX;
     3010        pThis->paSymbols[iSym].idxGrpDef = UINT16_MAX;
     3011
     3012        uint32_t const idxSection = paSymbols[iSym].st_shndx;
     3013        if (idxSection == SHN_UNDEF)
     3014        {
     3015            if (bBind == STB_GLOBAL)
     3016            {
     3017                pThis->paSymbols[iSym].enmType = OMFSYMTYPE_EXTDEF;
     3018                cExtSyms++;
     3019                if (*pszSymName == '\0')
     3020                    return error(pThis->pszSrc, "External symbol #%u (%s) has an empty name.\n", iSym, pszSymName);
     3021            }
     3022            else if (bBind != STB_LOCAL || iSym != 0) /* Entry zero is usually a dummy. */
     3023                return error(pThis->pszSrc, "Unsupported or invalid bind type %#x for undefined symbol #%u (%s)\n",
     3024                             bBind, iSym, pszSymName);
     3025        }
     3026        else if (idxSection < cSections)
     3027        {
     3028            pThis->paSymbols[iSym].idxSegDef = pThis->paSegments[idxSection].iSegDef;
     3029            pThis->paSymbols[iSym].idxGrpDef = pThis->paSegments[idxSection].iGrpDef;
     3030            if (bBind == STB_GLOBAL)
     3031            {
     3032                pThis->paSymbols[iSym].enmType = OMFSYMTYPE_PUBDEF;
     3033                pThis->paSegments[idxSection].cPubDefs++;
     3034                cPubSyms++;
     3035                if (bType == STT_SECTION)
     3036                    return error(pThis->pszSrc, "Don't know how to export STT_SECTION symbol #%u (%s)\n", iSym, pszSymName);
     3037                if (*pszSymName == '\0')
     3038                    return error(pThis->pszSrc, "Public symbol #%u (%s) has an empty name.\n", iSym, pszSymName);
     3039            }
     3040            else if (bType == STT_SECTION)
     3041                pThis->paSymbols[iSym].enmType = OMFSYMTYPE_SEGDEF;
     3042            else
     3043                pThis->paSymbols[iSym].enmType = OMFSYMTYPE_INTERNAL;
     3044        }
     3045        else if (idxSection == SHN_ABS)
     3046        {
     3047            if (bType != STT_FILE)
     3048            {
     3049                if (bBind == STB_GLOBAL)
     3050                {
     3051                    pThis->paSymbols[iSym].enmType   = OMFSYMTYPE_PUBDEF;
     3052                    pThis->paSymbols[iSym].idxSegDef = 0;
     3053                    pThis->paSymbols[iSym].idxGrpDef = 0;
     3054                    cAbsSyms++;
     3055                    if (*pszSymName == '\0')
     3056                        return error(pThis->pszSrc, "Public absolute symbol #%u (%s) has an empty name.\n", iSym, pszSymName);
     3057                }
     3058                else
     3059                    return error(pThis->pszSrc, "Unsupported or invalid bind type %#x for absolute symbol #%u (%s)\n",
     3060                                 bBind, iSym, pszSymName);
     3061            }
     3062        }
     3063        else
     3064            return error(pThis->pszSrc, "Unsupported or invalid section number %#x for symbol #%u (%s)\n",
     3065                         idxSection, iSym, pszSymName);
     3066    }
     3067
     3068    /*
     3069     * Emit the PUBDEFs the first time around (see order of records in TIS spec).
     3070     */
     3071    uint16_t idxPubDef = 1;
     3072    if (cPubSyms)
     3073    {
     3074        for (uint32_t iSeg = 0; iSeg < pThis->cSegments; iSeg++)
     3075            if (pThis->paSegments[iSeg].cPubDefs > 0)
     3076            {
     3077                uint16_t const idxSegDef = pThis->paSegments[iSeg].iSegDef;
     3078                if (!omfWriter_PubDefBegin(pThis, pThis->paSegments[iSeg].iGrpDef, idxSegDef))
     3079                    return false;
     3080                for (uint16_t iSym = 0; iSym < cSymbols; iSym++)
     3081                    if (   pThis->paSymbols[iSym].idxSegDef == idxSegDef
     3082                        && pThis->paSymbols[iSym].enmType   == OMFSYMTYPE_PUBDEF)
     3083                    {
     3084                        const char *pszName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name];
     3085                        if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].st_value, pszName))
     3086                            return false;
     3087
     3088                        /* If the symbol doesn't start with an underscore and is a _c64 or _lm64 symbol,
     3089                           add an underscore prefixed alias to ease access from 16-bit and 32-bit code. */
     3090                        size_t cchName = strlen(pszName);
     3091                        if (   *pszName != '_'
     3092                            && (   (cchName > 4 && strcmp(&pszName[cchName - 4], "_c64")  == 0)
     3093                                || (cchName > 5 && strcmp(&pszName[cchName - 5], "_lm64") == 0) ) )
     3094                        {
     3095                            char   szCdeclName[512];
     3096                            if (cchName > sizeof(szCdeclName) - 2)
     3097                                cchName = sizeof(szCdeclName) - 2;
     3098                            szCdeclName[0] = '_';
     3099                            memcpy(&szCdeclName[1], pszName, cchName);
     3100                            szCdeclName[cchName + 1] = '\0';
     3101                            if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].st_value, szCdeclName))
     3102                                return false;
     3103                        }
     3104
     3105                        pThis->paSymbols[iSym].idx = idxPubDef++;
     3106                    }
     3107                if (!omfWriter_PubDefEnd(pThis))
     3108                    return false;
     3109            }
     3110    }
     3111
     3112    if (cAbsSyms > 0)
     3113    {
     3114        if (!omfWriter_PubDefBegin(pThis, 0, 0))
     3115            return false;
     3116        for (uint16_t iSym = 0; iSym < cSymbols; iSym++)
     3117            if (   pThis->paSymbols[iSym].idxSegDef == 0
     3118                && pThis->paSymbols[iSym].enmType   == OMFSYMTYPE_PUBDEF)
     3119            {
     3120                const char *pszName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name];
     3121                if (!omfWriter_PubDefAdd(pThis, paSymbols[iSym].st_value, pszName))
     3122                    return false;
     3123                pThis->paSymbols[iSym].idx = idxPubDef++;
     3124            }
     3125        if (!omfWriter_PubDefEnd(pThis))
     3126            return false;
     3127    }
     3128
     3129    /*
     3130     * Go over the symbol table and emit external definition records.
     3131     */
     3132    if (!omfWriter_ExtDefBegin(pThis))
     3133        return false;
     3134    uint16_t idxExtDef = 1;
     3135    for (uint16_t iSym = 0; iSym < cSymbols; iSym++)
     3136        if (pThis->paSymbols[iSym].enmType == OMFSYMTYPE_EXTDEF)
     3137        {
     3138            const char *pszName = &pElfStuff->pchStrTab[paSymbols[iSym].st_name];
     3139            if (!omfWriter_ExtDefAdd(pThis, pszName))
     3140                return false;
     3141            pThis->paSymbols[iSym].idx = idxExtDef++;
     3142        }
     3143
     3144    if (!omfWriter_ExtDefEnd(pThis))
     3145        return false;
     3146
     3147    return true;
     3148}
     3149
     3150static bool convertElfSectionsToLeDataAndFixupps(POMFWRITER pThis, PCELFDETAILS pElfStuff, uint8_t const *pbFile, size_t cbFile)
     3151{
     3152    Elf64_Sym const    *paSymbols = pElfStuff->paSymbols;
     3153    Elf64_Shdr const   *paShdrs   = pElfStuff->paShdrs;
     3154    bool                fRet      = true;
     3155    for (uint32_t i = 1; i < pThis->cSegments; i++)
     3156    {
     3157        if (pThis->paSegments[i].iSegDef == UINT16_MAX)
     3158            continue;
     3159
     3160        const char         *pszSegNm   = &pElfStuff->pchShStrTab[paShdrs[i].sh_name];
     3161        bool const          fRelocs    = i + 1 < pThis->cSegments && paShdrs[i + 1].sh_type == SHT_RELA;
     3162        uint32_t            cRelocs    = fRelocs ? paShdrs[i + 1].sh_size / sizeof(Elf64_Rela) : 0;
     3163        Elf64_Rela const   *paRelocs   = fRelocs ? (Elf64_Rela *)&pbFile[paShdrs[i + 1].sh_offset] : NULL;
     3164        Elf64_Xword         cbVirtData = paShdrs[i].sh_size;
     3165        Elf64_Xword         cbData     = paShdrs[i].sh_type == SHT_NOBITS ? 0 : cbVirtData;
     3166        uint8_t const      *pbData     = &pbFile[paShdrs[i].sh_offset];
     3167        uint32_t            off        = 0;
     3168
     3169        /* The OMF record size requires us to split larger sections up.  To make
     3170           life simple, we fill zeros for unitialized (BSS) stuff. */
     3171        const uint32_t cbMaxData = RT_MIN(OMF_MAX_RECORD_PAYLOAD - 1 - (pThis->paSegments[i].iSegDef >= 128) - 4 - 1, _1K);
     3172        while (cbVirtData > 0)
     3173        {
     3174            /* Figure out how many bytes to put out in this chunk.  Must make sure
     3175               fixups doesn't cross chunk boundraries.  ASSUMES sorted relocs. */
     3176            uint32_t       cChunkRelocs = cRelocs;
     3177            uint32_t       cbChunk      = cbVirtData;
     3178            uint32_t       offEnd       = off + cbChunk;
     3179            if (cbChunk > cbMaxData)
     3180            {
     3181                cbChunk      = cbMaxData;
     3182                offEnd       = off + cbChunk;
     3183                cChunkRelocs = 0;
     3184
     3185                /* Quickly determin the reloc range. */
     3186                while (   cChunkRelocs < cRelocs
     3187                       && paRelocs[cChunkRelocs].r_offset < offEnd)
     3188                    cChunkRelocs++;
     3189
     3190                /* Ensure final reloc doesn't go beyond chunk. */
     3191                while (   cChunkRelocs > 0
     3192                       &&     paRelocs[cChunkRelocs - 1].r_offset
     3193                            + ELF_AMD64_RELOC_SIZE(ELF64_R_TYPE(paRelocs[cChunkRelocs - 1].r_info))
     3194                          > offEnd)
     3195                {
     3196                    uint32_t cbDrop = offEnd - paRelocs[cChunkRelocs - 1].r_offset;
     3197                    cbChunk -= cbDrop;
     3198                    offEnd  -= cbDrop;
     3199                    cChunkRelocs--;
     3200                }
     3201
     3202                if (!cbVirtData)
     3203                    return error(pThis->pszSrc, "Wtf? cbVirtData is zero!\n");
     3204            }
     3205
     3206            /*
     3207             * We stash the bytes into the OMF writer record buffer, receiving a
     3208             * pointer to the start of it so we can make adjustments if necessary.
     3209             */
     3210            uint8_t *pbCopy;
     3211            if (!omfWriter_LEDataBegin(pThis, pThis->paSegments[i].iSegDef, off, cbChunk, cbData, pbData, &pbCopy))
     3212                return false;
     3213
     3214            /*
     3215             * Convert fiuxps.
     3216             */
     3217            for (uint32_t iReloc = 0; iReloc < cChunkRelocs; iReloc++)
     3218            {
     3219                /* Get the OMF and ELF data for the symbol the reloc references. */
     3220                uint32_t const          uType      = ELF64_R_TYPE(paRelocs[iReloc].r_info);
     3221                uint32_t const          iSymbol    = ELF64_R_SYM(paRelocs[iReloc].r_info);
     3222                Elf64_Sym const * const pElfSym    =        &paSymbols[iSymbol];
     3223                POMFSYMBOL const        pOmfSym    = &pThis->paSymbols[iSymbol];
     3224                const char * const      pszSymName = &pElfStuff->pchStrTab[pElfSym->st_name];
     3225
     3226                /* Calc fixup location in the pending chunk and setup a flexible pointer to it. */
     3227                uint16_t  offDataRec = (uint16_t)(paRelocs[iReloc].r_offset - off);
     3228                RTPTRUNION uLoc;
     3229                uLoc.pu8 = &pbCopy[offDataRec];
     3230
     3231                /* OMF fixup data initialized with typical defaults. */
     3232                bool        fSelfRel  = true;
     3233                uint8_t     bLocation = OMF_FIX_LOC_32BIT_OFFSET;
     3234                uint8_t     bFrame    = OMF_FIX_F_GRPDEF;
     3235                uint16_t    idxFrame  = pThis->idxGrpFlat;
     3236                uint8_t     bTarget;
     3237                uint16_t    idxTarget;
     3238                bool        fTargetDisp;
     3239                uint32_t    offTargetDisp;
     3240                switch (pOmfSym->enmType)
     3241                {
     3242                    case OMFSYMTYPE_INTERNAL:
     3243                    case OMFSYMTYPE_PUBDEF:
     3244                        bTarget       = OMF_FIX_T_SEGDEF;
     3245                        idxTarget     = pOmfSym->idxSegDef;
     3246                        fTargetDisp   = true;
     3247                        offTargetDisp = pElfSym->st_value;
     3248                        break;
     3249
     3250                    case OMFSYMTYPE_SEGDEF:
     3251                        bTarget       = OMF_FIX_T_SEGDEF_NO_DISP;
     3252                        idxTarget     = pOmfSym->idxSegDef;
     3253                        fTargetDisp   = false;
     3254                        offTargetDisp = 0;
     3255                        break;
     3256
     3257                    case OMFSYMTYPE_EXTDEF:
     3258                        bTarget       = OMF_FIX_T_EXTDEF_NO_DISP;
     3259                        idxTarget     = pOmfSym->idx;
     3260                        fTargetDisp   = false;
     3261                        offTargetDisp = 0;
     3262                        break;
     3263
     3264                    default:
     3265                        return error(pThis->pszSrc, "Relocation in segment #%u '%s' references ignored or invalid symbol (%s)\n",
     3266                                     i, pszSegNm, pszSymName);
     3267                }
     3268
     3269                /* Do COFF relocation type conversion. */
     3270                switch (uType)
     3271                {
     3272                    case R_X86_64_64:
     3273                    {
     3274                        int64_t iAddend = paRelocs[iReloc].r_addend;
     3275                        if (iAddend > _1G || iAddend < -_1G)
     3276                            fRet = error(pThis->pszSrc, "R_X86_64_64 with large addend (%" ELF_FMT_D64 ") at %#x in segment #%u '%s'\n",
     3277                                         iAddend, paRelocs[iReloc].r_offset, i, pszSegNm);
     3278                        *uLoc.pu64 = iAddend;
     3279                        fSelfRel = false;
     3280                        break;
     3281                    }
     3282
     3283                    case R_X86_64_32:
     3284                    case R_X86_64_32S:  /* signed, unsigned, whatever. */
     3285                        fSelfRel = false;
     3286                        /* fall thru */
     3287                    case R_X86_64_PC32:
     3288                    {
     3289                        /* defaults are ok, just handle the addend. */
     3290                        int32_t iAddend = paRelocs[iReloc].r_addend;
     3291                        if (iAddend != paRelocs[iReloc].r_addend)
     3292                            fRet = error(pThis->pszSrc, "R_X86_64_PC32 with large addend (%d) at %#x in segment #%u '%s'\n",
     3293                                         iAddend, paRelocs[iReloc].r_offset, i, pszSegNm);
     3294                        *uLoc.pu32 = iAddend;
     3295                        break;
     3296                    }
     3297
     3298                    case R_X86_64_NONE:
     3299                        continue; /* Ignore this one */
     3300
     3301                    case R_X86_64_GOT32:
     3302                    case R_X86_64_PLT32:
     3303                    case R_X86_64_COPY:
     3304                    case R_X86_64_GLOB_DAT:
     3305                    case R_X86_64_JMP_SLOT:
     3306                    case R_X86_64_RELATIVE:
     3307                    case R_X86_64_GOTPCREL:
     3308                    case R_X86_64_16:
     3309                    case R_X86_64_PC16:
     3310                    case R_X86_64_8:
     3311                    case R_X86_64_PC8:
     3312                    case R_X86_64_DTPMOD64:
     3313                    case R_X86_64_DTPOFF64:
     3314                    case R_X86_64_TPOFF64:
     3315                    case R_X86_64_TLSGD:
     3316                    case R_X86_64_TLSLD:
     3317                    case R_X86_64_DTPOFF32:
     3318                    case R_X86_64_GOTTPOFF:
     3319                    case R_X86_64_TPOFF32:
     3320                    default:
     3321                        return error(pThis->pszSrc, "Unsupported fixup type %#x (%s) at rva=%#x in section #%u '%s' against '%s'\n",
     3322                                     uType, g_apszElfAmd64RelTypes[uType], paRelocs[iReloc].r_offset, i, pszSegNm, pszSymName);
     3323                }
     3324
     3325                /* Add the fixup. */
     3326                if (idxFrame == UINT16_MAX)
     3327                    error(pThis->pszSrc, "idxFrame=UINT16_MAX for %s type=%s\n", pszSymName, g_apszElfAmd64RelTypes[uType]);
     3328                fRet = omfWriter_LEDataAddFixup(pThis, offDataRec, fSelfRel, bLocation, bFrame, idxFrame,
     3329                                                bTarget, idxTarget, fTargetDisp, offTargetDisp) && fRet;
     3330            }
     3331
     3332            /*
     3333             * Write the LEDATA and associated FIXUPPs.
     3334             */
     3335            if (!omfWriter_LEDataEnd(pThis))
     3336                return false;
     3337
     3338            /*
     3339             * Advance.
     3340             */
     3341            paRelocs   += cChunkRelocs;
     3342            cRelocs    -= cChunkRelocs;
     3343            if (cbData > cbChunk)
     3344            {
     3345                cbData -= cbChunk;
     3346                pbData += cbChunk;
     3347            }
     3348            else
     3349                cbData  = 0;
     3350            off        += cbChunk;
     3351            cbVirtData -= cbChunk;
     3352        }
     3353    }
     3354
     3355    return fRet;
     3356}
     3357
     3358
     3359static bool convertMachoToOmf(const char *pszFile, uint8_t const *pbFile, size_t cbFile, FILE *pDst)
     3360{
     3361    /*
     3362     * Validate the source file a little.
     3363     */
     3364    ELFDETAILS ElfStuff;
     3365    if (!validateElf(pszFile, pbFile, cbFile, &ElfStuff))
     3366        return false;
     3367
     3368    /*
     3369     * Instantiate the OMF writer.
     3370     */
     3371    POMFWRITER pThis = omfWriter_Create(pszFile, ElfStuff.pEhdr->e_shnum, ElfStuff.cSymbols, pDst);
     3372    if (!pThis)
     3373        return false;
     3374
     3375    /*
     3376     * Write the OMF object file.
     3377     */
     3378    if (omfWriter_BeginModule(pThis, pszFile))
     3379    {
     3380        Elf64_Ehdr const *pEhdr     = (Elf64_Ehdr const *)pbFile;
     3381        Elf64_Shdr const *paShdrs   = (Elf64_Shdr const *)&pbFile[pEhdr->e_shoff];
     3382        const char       *pszStrTab = (const char *)&pbFile[paShdrs[pEhdr->e_shstrndx].sh_offset];
     3383
     3384        if (   convertElfSectionsToSegDefsAndGrpDefs(pThis, &ElfStuff)
     3385            && convertElfSymbolsToPubDefsAndExtDefs(pThis, &ElfStuff)
     3386            && omfWriter_LinkPassSeparator(pThis)
     3387            && convertElfSectionsToLeDataAndFixupps(pThis, &ElfStuff, pbFile, cbFile)
     3388            && omfWriter_EndModule(pThis) )
     3389        {
     3390
     3391            omfWriter_Destroy(pThis);
     3392            return true;
     3393        }
     3394    }
     3395
     3396    omfWriter_Destroy(pThis);
     3397    return false;
     3398}
     3399
     3400#endif /* !MACHO_TO_OMF_CONVERSION */
     3401
    25853402
    25863403/*********************************************************************************************************************************
     
    28523669            && pbFile[3] == ELFMAG3)
    28533670        {
    2854 #ifdef ELF_TO_OMF_CONVERSION
    28553671            if (writefile(szOrgFile, pvFile, cbFile))
    28563672            {
     
    28623678                }
    28633679            }
    2864 #else
    2865             fRc = writefile(szOrgFile, pvFile, cbFile)
    2866                && convertelf(pszFile, pbFile, cbFile)
    2867                && writefile(pszFile, pvFile, cbFile);
    2868 #endif
    28693680        }
    28703681        else if (   cbFile > sizeof(IMAGE_FILE_HEADER)
Note: See TracChangeset for help on using the changeset viewer.

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