Andreas Klebinger pushed to branch wip/andreask/linker_fix at Glasgow Haskell Compiler / GHC

Commits:

6 changed files:

Changes:

  • rts/Linker.c
    ... ... @@ -1415,7 +1415,7 @@ preloadObjectFile (pathchar *path)
    1415 1415
         // We calculate the correct alignment from the header before
    
    1416 1416
         // reading the file, and then we misalign image on purpose so
    
    1417 1417
         // that the actual sections end up aligned again.
    
    1418
    -   misalignment = machoGetMisalignment(f);
    
    1418
    +   machoGetMisalignment(f, &misalignment);
    
    1419 1419
        image = stgMallocBytes(fileSize + misalignment, "loadObj(image)");
    
    1420 1420
        image += misalignment;
    
    1421 1421
     
    
    ... ... @@ -1441,14 +1441,7 @@ preloadObjectFile (pathchar *path)
    1441 1441
        /* FIXME (AP): =mapped= parameter unconditionally set to true */
    
    1442 1442
        oc = mkOc(STATIC_OBJECT, path, image, fileSize, true, NULL, misalignment);
    
    1443 1443
     
    
    1444
    -#if defined(OBJFORMAT_MACHO)
    
    1445
    -   if (ocVerifyImage_MachO( oc ))
    
    1446
    -       ocInit_MachO( oc );
    
    1447
    -#endif
    
    1448
    -#if defined(OBJFORMAT_ELF)
    
    1449
    -   if(ocVerifyImage_ELF( oc ))
    
    1450
    -       ocInit_ELF( oc );
    
    1451
    -#endif
    
    1444
    +   verifyAndInitOc(oc);
    
    1452 1445
        return oc;
    
    1453 1446
     }
    
    1454 1447
     
    
    ... ... @@ -1505,27 +1498,44 @@ HsInt loadObj (pathchar *path)
    1505 1498
        return r;
    
    1506 1499
     }
    
    1507 1500
     
    
    1501
    +// Call the relevant VeriffyImage_* and ocInit_* functions.
    
    1502
    +// Return 1 on success.
    
    1503
    +HsInt verifyAndInitOc (ObjectCode* oc)
    
    1504
    +{
    
    1505
    +    int r;
    
    1506
    +
    
    1507
    +     IF_DEBUG(linker, ocDebugBelch(oc, "start\n"));
    
    1508
    +
    
    1509
    +    /* verify the in-memory image */
    
    1510
    +#if defined(OBJFORMAT_ELF)
    
    1511
    +    r = ocVerifyImage_ELF ( oc );
    
    1512
    +    if(r) {
    
    1513
    +        ocInit_ELF( oc );
    
    1514
    +    }
    
    1515
    +#elif defined(OBJFORMAT_PEi386)
    
    1516
    +    r = ocVerifyImage_PEi386 ( oc );
    
    1517
    +#elif defined(OBJFORMAT_MACHO)
    
    1518
    +    r = ocVerifyImage_MachO ( oc );
    
    1519
    +    if(r) {
    
    1520
    +        ocInit_MachO( oc );
    
    1521
    +    }
    
    1522
    +#else
    
    1523
    +    barf("loadObj: no verify method");
    
    1524
    +#endif
    
    1525
    +    if (!r) {
    
    1526
    +        IF_DEBUG(linker, ocDebugBelch(oc, "ocVerifyImage_* failed\n"));
    
    1527
    +        return r;
    
    1528
    +    }
    
    1529
    +    return 1;
    
    1530
    +}
    
    1531
    +
    
    1532
    +// Precondition: oc already verified.
    
    1508 1533
     HsInt loadOc (ObjectCode* oc)
    
    1509 1534
     {
    
    1510 1535
        int r;
    
    1511 1536
     
    
    1512 1537
        IF_DEBUG(linker, ocDebugBelch(oc, "start\n"));
    
    1513 1538
     
    
    1514
    -   /* verify the in-memory image */
    
    1515
    -#  if defined(OBJFORMAT_ELF)
    
    1516
    -   r = ocVerifyImage_ELF ( oc );
    
    1517
    -#  elif defined(OBJFORMAT_PEi386)
    
    1518
    -   r = ocVerifyImage_PEi386 ( oc );
    
    1519
    -#  elif defined(OBJFORMAT_MACHO)
    
    1520
    -   r = ocVerifyImage_MachO ( oc );
    
    1521
    -#  else
    
    1522
    -   barf("loadObj: no verify method");
    
    1523
    -#  endif
    
    1524
    -   if (!r) {
    
    1525
    -       IF_DEBUG(linker, ocDebugBelch(oc, "ocVerifyImage_* failed\n"));
    
    1526
    -       return r;
    
    1527
    -   }
    
    1528
    -
    
    1529 1539
        /* Note [loadOc orderings]
    
    1530 1540
           ~~~~~~~~~~~~~~~~~~~~~~~
    
    1531 1541
           The order of `ocAllocateExtras` and `ocGetNames` matters. For MachO
    

  • rts/LinkerInternals.h
    ... ... @@ -485,12 +485,19 @@ HsInt loadArchive_ (pathchar *path);
    485 485
     HsInt isAlreadyLoaded( pathchar *path );
    
    486 486
     OStatus getObjectLoadStatus_ (pathchar *path);
    
    487 487
     ObjectCode *lookupObjectByPath(pathchar *path);
    
    488
    +
    
    489
    +/* Verify an objects is an a format that can be loaded and initialize the oc struct if required. */
    
    490
    +HsInt verifyAndInitOc( ObjectCode *oc );
    
    491
    +
    
    492
    +//Expects the oc to be verified already.
    
    488 493
     HsInt loadOc( ObjectCode* oc );
    
    489 494
     ObjectCode* mkOc( ObjectType type, pathchar *path, char *image, int imageSize,
    
    490 495
                       bool mapped, pathchar *archiveMemberName,
    
    491 496
                       int misalignment
    
    492 497
                       );
    
    493 498
     
    
    499
    +
    
    500
    +
    
    494 501
     void initSegment(Segment *s, void *start, size_t size, SegmentProt prot, int n_sections);
    
    495 502
     void freeSegments(ObjectCode *oc);
    
    496 503
     
    

  • rts/linker/LoadArchive.c
    ... ... @@ -110,56 +110,50 @@ static bool loadFatArchive(char input[static 20], FILE* f, pathchar* path)
    110 110
     }
    
    111 111
     #endif
    
    112 112
     
    
    113
    -enum ObjectFileFormat {
    
    114
    -    NotObject,
    
    115
    -    COFFAmd64,
    
    116
    -    COFFI386,
    
    117
    -    COFFAArch64,
    
    118
    -    ELF,
    
    119
    -    MachO32,
    
    120
    -    MachO64,
    
    121
    -};
    
    122
    -
    
    123
    -static enum ObjectFileFormat identifyObjectFile_(char* buf, size_t sz)
    
    124
    -{
    
    125
    -    if (sz > 2 && ((uint16_t*)buf)[0] == 0x8664) {
    
    126
    -        return COFFAmd64;
    
    127
    -    }
    
    128
    -    if (sz > 2 && ((uint16_t*)buf)[0] == 0x014c) {
    
    129
    -        return COFFI386;
    
    130
    -    }
    
    131
    -    if (sz > 2 && ((uint16_t*)buf)[0] == 0xaa64) {
    
    132
    -        return COFFAArch64;
    
    133
    -    }
    
    134
    -    if (sz > 4 && memcmp(buf, "\x7f" "ELF", 4) == 0) {
    
    135
    -        return ELF;
    
    136
    -    }
    
    137
    -    if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedface) {
    
    138
    -        return MachO32;
    
    139
    -    }
    
    140
    -    if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedfacf) {
    
    141
    -        return MachO64;
    
    142
    -    }
    
    143
    -    // BigObj COFF files ...
    
    144
    -    if (sz > 8 && ((uint64_t*)buf)[0] == 0x86640002ffff0000) {
    
    145
    -        return COFFAmd64;
    
    146
    -    }
    
    147
    -    if (sz > 8 && ((uint64_t*)buf)[0] == 0x014c0002ffff0000) {
    
    148
    -        return COFFI386;
    
    149
    -    }
    
    150
    -    if (sz > 8 && ((uint64_t*)buf)[0] == 0xaa640002ffff0000) {
    
    151
    -        return COFFAArch64;
    
    152
    -    }
    
    153
    -    return NotObject;
    
    154
    -}
    
    155
    -
    
    156
    -static enum ObjectFileFormat identifyObjectFile(FILE *f)
    
    157
    -{
    
    158
    -    char buf[32];
    
    159
    -    ssize_t sz = fread(buf, 1, 32, f);
    
    160
    -    CHECK(fseek(f, -sz, SEEK_CUR) == 0);
    
    161
    -    return identifyObjectFile_(buf, sz);
    
    162
    -}
    
    113
    +// enum ObjectFileFormat {
    
    114
    +//     NotObject,
    
    115
    +//     COFFAmd64,
    
    116
    +//     COFFI386,
    
    117
    +//     COFFAArch64,
    
    118
    +//     ELF,
    
    119
    +//     MachO32,
    
    120
    +//     MachO64,
    
    121
    +// };
    
    122
    +
    
    123
    +// static enum ObjectFileFormat identifyObjectFile_(char* buf, size_t sz)
    
    124
    +// {
    
    125
    +//     if (sz > 2 && ((uint16_t*)buf)[0] == 0x8664) {
    
    126
    +//         return COFFAmd64;
    
    127
    +//     }
    
    128
    +//     if (sz > 2 && ((uint16_t*)buf)[0] == 0x014c) {
    
    129
    +//         return COFFI386;
    
    130
    +//     }
    
    131
    +//     if (sz > 2 && ((uint16_t*)buf)[0] == 0xaa64) {
    
    132
    +//         return COFFAArch64;
    
    133
    +//     }
    
    134
    +//     if (sz > 4 && memcmp(buf, "\x7f" "ELF", 4) == 0) {
    
    135
    +//         return ELF;
    
    136
    +//     }
    
    137
    +//     if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedface) {
    
    138
    +//         return MachO32;
    
    139
    +//     }
    
    140
    +//     if (sz > 4 && ((uint32_t*)buf)[0] == 0xfeedfacf) {
    
    141
    +//         return MachO64;
    
    142
    +//     }
    
    143
    +//     // BigObj COFF files ...
    
    144
    +//     if (sz > 8 && ((uint64_t*)buf)[0] == 0x86640002ffff0000) {
    
    145
    +//         return COFFAmd64;
    
    146
    +//     }
    
    147
    +//     return NotObject;
    
    148
    +// }
    
    149
    +
    
    150
    +// static enum ObjectFileFormat identifyObjectFile(FILE *f)
    
    151
    +// {
    
    152
    +//     char buf[32];
    
    153
    +//     ssize_t sz = fread(buf, 1, 32, f);
    
    154
    +//     CHECK(fseek(f, -sz, SEEK_CUR) == 0);
    
    155
    +//     return identifyObjectFile_(buf, sz);
    
    156
    +// }
    
    163 157
     
    
    164 158
     static bool readThinArchiveMember(int n, int memberSize, pathchar* path,
    
    165 159
             char* fileName, char* image)
    
    ... ... @@ -553,9 +547,11 @@ HsInt loadArchive_ (pathchar *path)
    553 547
             }
    
    554 548
     
    
    555 549
             DEBUG_LOG("Found member file `%s'\n", fileName);
    
    556
    -
    
    557 550
             bool is_symbol_table = strcmp("", fileName) == 0;
    
    558
    -        enum ObjectFileFormat object_fmt = is_symbol_table ? NotObject : identifyObjectFile(f);
    
    551
    +
    
    552
    +/////////////////////////////////////////////////
    
    553
    +// We found the member file. Load it into memory.
    
    554
    +/////////////////////////////////////////////////
    
    559 555
     
    
    560 556
     #if defined(OBJFORMAT_PEi386)
    
    561 557
             /*
    
    ... ... @@ -575,17 +571,22 @@ HsInt loadArchive_ (pathchar *path)
    575 571
     #endif // windows
    
    576 572
     
    
    577 573
             DEBUG_LOG("\tthisFileNameSize = %d\n", (int)thisFileNameSize);
    
    578
    -        DEBUG_LOG("\tisObject = %d\n", object_fmt);
    
    574
    +        // DEBUG_LOG("\tisObject = %d\n", object_fmt);
    
    579 575
     
    
    580
    -        if ((!is_symbol_table && isThin) || object_fmt != NotObject) {
    
    581
    -            DEBUG_LOG("Member is an object file...loading...\n");
    
    576
    +        //if ((!is_symbol_table && isThin) || object_fmt != NotObject)
    
    577
    +        if (!is_symbol_table && !isImportLib)
    
    578
    +        {
    
    579
    +            DEBUG_LOG("Member might be an object file...loading...\n");
    
    582 580
     
    
    583 581
     #if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
    
    584 582
                 if (RTS_LINKER_USE_MMAP)
    
    585 583
                     image = mmapAnonForLinker(memberSize);
    
    586 584
                 else {
    
    587 585
                     /* See loadObj() */
    
    588
    -                misalignment = machoGetMisalignment(f);
    
    586
    +                if(!machoGetMisalignment(f, &misalignment))
    
    587
    +                    DEBUG_LOG("Failed to load member as mach-o file. Skipping.\n");
    
    588
    +                    continue;
    
    589
    +                }
    
    589 590
                     image = stgMallocBytes(memberSize + misalignment,
    
    590 591
                                             "loadArchive(image)");
    
    591 592
                     image += misalignment;
    
    ... ... @@ -616,19 +617,23 @@ HsInt loadArchive_ (pathchar *path)
    616 617
                 pathprintf(archiveMemberName, size+1, WSTR("%" PATH_FMT "(#%d:%.*s)"),
    
    617 618
                            path, memberIdx, (int)thisFileNameSize, fileName);
    
    618 619
     
    
    620
    +///////////////////////////////////////////////////////////////
    
    621
    +// Verfiy the object file is valid, and load it if appropriate.
    
    622
    +///////////////////////////////////////////////////////////////
    
    623
    +
    
    624
    +            // Prepare headers, doesn't load any data yet.
    
    619 625
                 ObjectCode *oc = mkOc(STATIC_OBJECT, path, image, memberSize, false, archiveMemberName,
    
    620 626
                                       misalignment);
    
    621
    -#if defined(OBJFORMAT_MACHO)
    
    622
    -            ASSERT(object_fmt == MachO32 || object_fmt == MachO64);
    
    623
    -            ocInit_MachO( oc );
    
    624
    -#endif
    
    625
    -#if defined(OBJFORMAT_ELF)
    
    626
    -            ASSERT(object_fmt == ELF);
    
    627
    -            ocInit_ELF( oc );
    
    628
    -#endif
    
    629
    -
    
    630 627
                 stgFree(archiveMemberName);
    
    631 628
     
    
    629
    +            if(!verifyAndInitOc( oc ))
    
    630
    +            {
    
    631
    +                freeObjectCode( oc );
    
    632
    +                IF_DEBUG(linker, ocDebugBelch(oc, "Faild to verify ... skipping."));
    
    633
    +                continue;
    
    634
    +            };
    
    635
    +
    
    636
    +
    
    632 637
                 if (0 == loadOc(oc)) {
    
    633 638
                     stgFree(fileName);
    
    634 639
                     fclose(f);
    

  • rts/linker/MachO.c
    ... ... @@ -1725,31 +1725,41 @@ ocRunFini_MachO ( ObjectCode *oc )
    1725 1725
     /*
    
    1726 1726
      * Figure out by how much to shift the entire Mach-O file in memory
    
    1727 1727
      * when loading so that its single segment ends up 16-byte-aligned
    
    1728
    + *
    
    1729
    + * Returns 1 and sets misalignment_out to the detected misalignment i
    
    1730
    + * f we successfully parsed the file.
    
    1731
    + *
    
    1732
    + * If we can't parse the file we set misalignment_out to 0 and return 0
    
    1728 1733
      */
    
    1729 1734
     int
    
    1730
    -machoGetMisalignment( FILE * f )
    
    1735
    +machoGetMisalignment( FILE * f, int* misalignment_out )
    
    1731 1736
     {
    
    1732 1737
         MachOHeader header;
    
    1733 1738
         int misalignment;
    
    1739
    +    *misalignment_out = 0;
    
    1734 1740
     
    
    1735 1741
         {
    
    1736 1742
             size_t n = fread(&header, sizeof(header), 1, f);
    
    1737 1743
             if (n != 1) {
    
    1738
    -            barf("machoGetMisalignment: can't read the Mach-O header");
    
    1744
    +            debugBelch("machoGetMisalignment: can't read the Mach-O header");
    
    1745
    +            return 0;
    
    1739 1746
             }
    
    1740 1747
         }
    
    1741 1748
         fseek(f, -sizeof(header), SEEK_CUR);
    
    1742 1749
     
    
    1743 1750
         if(header.magic != MH_MAGIC_64) {
    
    1744
    -        barf("Bad magic. Expected: %08x, got: %08x.",
    
    1751
    +        debugBelch("Bad magic. Expected: %08x, got: %08x.",
    
    1745 1752
                  MH_MAGIC_64, header.magic);
    
    1753
    +        return 0;
    
    1746 1754
         }
    
    1747 1755
     
    
    1748 1756
         misalignment = (header.sizeofcmds + sizeof(header))
    
    1749 1757
                         & 0xF;
    
    1750 1758
     
    
    1751 1759
         IF_DEBUG(linker, debugBelch("mach-o misalignment %d\n", misalignment));
    
    1752
    -    return misalignment ? (16 - misalignment) : 0;
    
    1760
    +    misalignment ? (16 - misalignment) : 0;
    
    1761
    +    *misalignment_out = misalignment
    
    1762
    +    return 1;
    
    1753 1763
     }
    
    1754 1764
     
    
    1755 1765
     #endif /* darwin_HOST_OS || ios_HOST_OS */

  • rts/linker/MachO.h
    ... ... @@ -13,7 +13,7 @@ int ocGetNames_MachO ( ObjectCode* oc );
    13 13
     int    ocResolve_MachO              ( ObjectCode* oc );
    
    14 14
     int    ocRunInit_MachO              ( ObjectCode* oc );
    
    15 15
     int    ocRunFini_MachO              ( ObjectCode* oc );
    
    16
    -int    machoGetMisalignment         ( FILE * );
    
    16
    +int    machoGetMisalignment         ( FILE *, int* );
    
    17 17
     int    ocAllocateExtras_MachO       ( ObjectCode* oc );
    
    18 18
     
    
    19 19
     SectionKind getSectionKind_MachO    ( MachOSection *macho );
    

  • rts/linker/PEi386.c
    ... ... @@ -775,6 +775,10 @@ COFF_OBJ_TYPE getObjectType ( char* image, pathchar* fileName )
    775 775
      *************/
    
    776 776
     COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc )
    
    777 777
     {
    
    778
    +   if((size_t) oc->fileSize < sizeof(IMAGE_FILE_HEADER)) {
    
    779
    +      errorBelch ("Supposed COFF file smaller than minimum header size.\n");
    
    780
    +      return NULL;
    
    781
    +   }
    
    778 782
        COFF_OBJ_TYPE coff_type = getObjectType (oc->image, OC_INFORMATIVE_FILENAME(oc));
    
    779 783
     
    
    780 784
        COFF_HEADER_INFO* info
    
    ... ... @@ -808,6 +812,11 @@ COFF_HEADER_INFO* getHeaderInfo ( ObjectCode* oc )
    808 812
              stgFree (info);
    
    809 813
              info = NULL;
    
    810 814
              errorBelch ("Unknown COFF %d type in getHeaderInfo.", coff_type);
    
    815
    +         if(oc->archiveMemberName) {
    
    816
    +             errorBelch ("Archive %" PATH_FMT ".\n", oc->archiveMemberName);
    
    817
    +         }
    
    818
    +        errorBelch ("In %" PATH_FMT ".\n", oc->fileName);
    
    819
    +
    
    811 820
             }
    
    812 821
             break;
    
    813 822
        }