Ticket #4828: Linker.c.diff

File Linker.c.diff, 7.1 KB (added by gwright, 3 years ago)

Patch for rts/Linker.c to load fat archives on OS X

  • tmp/

    old new  
    9999#elif defined(darwin_HOST_OS) 
    100100#  define OBJFORMAT_MACHO 
    101101#  include <regex.h> 
     102#  include <mach/machine.h> 
     103#  include <mach-o/fat.h> 
    102104#  include <mach-o/loader.h> 
    103105#  include <mach-o/nlist.h> 
    104106#  include <mach-o/reloc.h> 
     
    16901692    char *fileName; 
    16911693    size_t fileNameSize; 
    16921694    int isObject, isGnuIndex; 
    1693     char tmp[12]; 
     1695    char tmp[20]; 
    16941696    char *gnuFileIndex; 
    16951697    int gnuFileIndexSize; 
    1696 #if !defined(USE_MMAP) && defined(darwin_HOST_OS) 
     1698#if defined(darwin_HOST_OS) 
     1699    int i; 
     1700    uint32_t nfat_arch, nfat_offset, cputype, cpusubtype; 
     1701#if !defined(USE_MMAP) 
    16971702    int misalignment; 
    16981703#endif 
     1704#endif 
    16991705 
    17001706    IF_DEBUG(linker, debugBelch("loadArchive: Loading archive `%s'\n", path)); 
    17011707 
     
    17091715    if (!f) 
    17101716        barf("loadObj: can't read `%s'", path); 
    17111717 
     1718    /* Check if this is an archive by looking for the magic "!<arch>\n" 
     1719     * string.  Usually, if this fails, we barf and quit.  On Darwin however, 
     1720     * we may have a fat archive, which contains archives for more than 
     1721     * one architecture.  Fat archives start with the magic number 0xcafebabe, 
     1722     * always stored big endian.  If we find a fat_header, we scan through 
     1723     * the fat_arch structs, searching through for one for our host 
     1724     * architecture.  If a matching struct is found, we read the offset 
     1725     * of our archive data (nfat_offset) and seek forward nfat_offset bytes 
     1726     * from the start of the file. 
     1727     * 
     1728     * A subtlety is that all of the members of the fat_header and fat_arch 
     1729     * structs are stored big endian, so we need to call byte order 
     1730     * conversion functions. 
     1731     * 
     1732     * If we find the appropriate architecture in a fat archive, we gobble 
     1733     * its magic "!<arch>\n" string and continue processing just as if 
     1734     * we had a single architecture archive. 
     1735     */ 
     1736 
    17121737    n = fread ( tmp, 1, 8, f ); 
    1713     if (strncmp(tmp, "!<arch>\n", 8) != 0) 
    1714         barf("loadArchive: Not an archive: `%s'", path); 
     1738    if (strncmp(tmp, "!<arch>\n", 8) != 0) { 
     1739 
     1740#if defined(darwin_HOST_OS) 
     1741        /* Not a standard archive, look for a fat archive magic number: */ 
     1742#if defined(i386_HOST_ARCH) || defined(x86_64_HOST_ARCH) 
     1743        if ((*(uint32_t *)tmp) == FAT_CIGAM) { 
     1744            nfat_arch = ntohl(*(uint32_t *)(tmp + 4)); 
     1745            IF_DEBUG(linker, debugBelch("loadArchive: found little endian fat archive containing %d architectures\n", nfat_arch)); 
     1746            nfat_offset = 0; 
     1747             
     1748            for (i = 0; (i < (int)nfat_arch) && (nfat_offset == 0); i++) { 
     1749                /* search for the right x86 arch */ 
     1750                n = fread( tmp, 1, 20, f ); 
     1751                cputype = ntohl(*(uint32_t *)tmp); 
     1752                cpusubtype = ntohl(*(uint32_t *)(tmp + 4)); 
     1753 
     1754#if defined(i386_HOST_ARCH) 
     1755                if (cputype == CPU_TYPE_X86 && cpusubtype == CPU_SUBTYPE_X86_ALL) { 
     1756                        IF_DEBUG(linker, debugBelch("loadArchive: found an x86 (32 bit) archive in a fat archive\n"));                             nfat_offset = ntohl(*(uint32_t *)(tmp + 8)); 
     1757                } 
     1758#endif 
     1759 
     1760#if defined(x86_64_HOST_ARCH) 
     1761                if (cputype == CPU_TYPE_X86_64 && cpusubtype == CPU_SUBTYPE_X86_64_ALL) { 
     1762                        IF_DEBUG(linker, debugBelch("loadArchive: found a x86_64 `archive in a fat archive\n"));                                   nfat_offset = ntohl(*(uint32_t *)(tmp + 8)); 
     1763                } 
     1764#endif 
     1765            } 
     1766 
     1767            if (nfat_offset == 0) { 
     1768                barf ("loadArchive: searched %d architectures, but no host arch found", nfat_arch); 
     1769            } else { 
     1770                n = fseek( f, nfat_offset, SEEK_SET ); 
     1771                n = fread ( tmp, 1, 8, f ); 
     1772                if (strncmp(tmp, "!<arch>\n", 8) != 0) { 
     1773                    barf("loadArchive: couldn't find archive in `%s' at offset %d", path, nfat_offset); 
     1774                } 
     1775            } 
     1776 
     1777        } 
     1778        else 
     1779#endif 
     1780 
     1781#if defined(powerpc_HOST_ARCH) || defined(powerpc64_HOST_ARCH) 
     1782        if ((*(uint32_t *)tmp) == FAT_MAGIC) { 
     1783            nfat_arch = ntohl(*(uint32_t *)(tmp + 4)); 
     1784            IF_DEBUG(linker, debugBelch("loadArchive: found big endian fat archive containing %d architectures\n", nfat_arch)); 
     1785            nfat_offset = 0; 
     1786 
     1787            for (i = 0; (i < (int)nfat_arch) && (nfat_offset == 0); i++) { 
     1788                /* search for the right ppc arch */ 
     1789                n = fread( tmp, 1, 20, f ); 
     1790                cputype = ntohl(*(uint32_t *)tmp); 
     1791                cpusubtype = ntohl(*(uint32_t *)(tmp + 4)); 
     1792 
     1793#if defined(powerpc_HOST_ARCH) 
     1794                if (cputype == CPU_TYPE_POWERPC && cpusubtype == CPU_SUBTYPE_POWERPC_ALL) { 
     1795                    IF_DEBUG(linker, debugBelch("loadArchive: found a PowerPC 32 bit archive in a fat archive\n")); 
     1796                    nfat_offset = ntohl(*(uint32_t *)(tmp + 8)); 
     1797                } 
     1798#endif 
     1799 
     1800#if defined(powerpc64_HOST_ARCH) 
     1801                if (cputype == CPU_TYPE_POWERPC64 && cpusubtype == CPU_SUBTYPE_POWERPC_ALL) { 
     1802                    IF_DEBUG(linker, debugBelch("loadArchive: found a PowerPC 64 bit archive in a fat archive\n")); 
     1803                    nfat_offset = ntohl(*(uint32_t *)(tmp + 8)); 
     1804                } 
     1805#endif 
     1806            } 
     1807 
     1808            if (nfat_offset == 0) { 
     1809                barf ("loadArchive: searched %d architectures, but no host arch found", nfat_arch); 
     1810            } else { 
     1811                n = fseek( f, nfat_offset, SEEK_SET ); 
     1812                n = fread ( tmp, 1, 8, f ); 
     1813                if (strncmp(tmp, "!<arch>\n", 8) != 0) { 
     1814                    barf("loadArchive: couldn't find archive in `%s' at offset %d", path, nfat_offset); 
     1815                } 
     1816            } 
     1817        } 
     1818        else 
     1819#endif 
     1820#endif 
     1821                barf("loadArchive: Not an archive: `%s'", path); 
     1822    } 
    17151823 
    17161824    while(1) { 
    17171825        n = fread ( fileName, 1, 16, f ); 
     
    46504758        } 
    46514759 
    46524760        IF_DEBUG(linker, 
    4653                  debugBelch("relocateSection: length = %d, thing = %d, baseValue = %p\n", 
    4654                             reloc->r_length, thing, baseValue)); 
     4761                 debugBelch("relocateSection: length = %d, thing = 0x%lx, baseValue = %p\n", 
     4762                            reloc->r_length, (unsigned long)thing, (void *)baseValue)); 
    46554763 
    46564764        if (type == X86_64_RELOC_GOT 
    46574765           || type == X86_64_RELOC_GOT_LOAD) 
     
    46744782            IF_DEBUG(linker, debugBelch("               : type  = %d\n", symbol->n_type)); 
    46754783            IF_DEBUG(linker, debugBelch("               : sect  = %d\n", symbol->n_sect)); 
    46764784            IF_DEBUG(linker, debugBelch("               : desc  = %d\n", symbol->n_desc)); 
    4677             IF_DEBUG(linker, debugBelch("               : value = %d\n", symbol->n_value)); 
     4785            IF_DEBUG(linker, debugBelch("               : value = %p\n", (void *)symbol->n_value)); 
    46784786            if ((symbol->n_type & N_TYPE) == N_SECT) { 
    46794787                value = relocateAddress(oc, nSections, sections, 
    46804788                                        symbol->n_value); 
    4681                 IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n", nm, value)); 
     4789                IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n", nm, (void *)value)); 
    46824790            } 
    46834791            else { 
    46844792                value = (uint64_t) lookupSymbol(nm); 
    4685                 IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s, address %p\n", nm, value)); 
     4793                IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s, address %p\n", nm, (void *)value)); 
    46864794            } 
    46874795        } 
    46884796        else 
     
    46924800                  + (uint64_t) image; 
    46934801        } 
    46944802       
    4695         IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", value)); 
     4803        IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", (void *)value)); 
    46964804 
    46974805        if (type == X86_64_RELOC_BRANCH) 
    46984806        {