Ticket #5062: 5062-3.patch

File 5062-3.patch, 34.0 KB (added by igloo, 2 years ago)
  • rts/Linker.c

    diff -rN -u old-ghc//rts/Linker.c new-ghc//rts/Linker.c
    old new  
    45694642    return 1; 
    45704643} 
    45714644 
    4572 static unsigned long relocateAddress( 
     4645 
     4646#ifndef x86_64_HOST_ARCH 
     4647 
     4648static unsigned long 
     4649relocateAddress( 
    45734650    ObjectCode* oc, 
    45744651    int nSections, 
    45754652    struct section* sections, 
    45764653    unsigned long address) 
    45774654{ 
    45784655    int i; 
     4656    unsigned long relocated; 
     4657 
    45794658    IF_DEBUG(linker, debugBelch("relocateAddress: start\n")); 
    45804659    for (i = 0; i < nSections; i++) 
    45814660    { 
    4582             IF_DEBUG(linker, debugBelch("    relocating address in section %d\n", i)); 
     4661        IF_DEBUG(linker, debugBelch("relocateAddress: \ttrying to relocate address %#lx in section %d\n", address, i)); 
     4662 
     4663        // check if the address to be relocated is in section i 
    45834664        if (sections[i].addr <= address 
    45844665            && address < sections[i].addr + sections[i].size) 
    45854666        { 
    4586             return (unsigned long)oc->image 
    4587                     + sections[i].offset + address - sections[i].addr; 
     4667            relocated = (unsigned long)oc->image + sections[i].offset + address - sections[i].addr; 
     4668 
     4669            IF_DEBUG(linker, debugBelch("relocateAddress: \tin section %d, relocated address is %#lx\n", i, relocated)); 
     4670            IF_DEBUG(linker, debugBelch("relocateAddress: \toc->image = %lu (%#lx)\n", (unsigned long)oc->image, 
     4671                                        (unsigned long)oc->image)); 
     4672            IF_DEBUG(linker, debugBelch("relocateAddress: \tsections[%d].offset = %u (%#x)\n", i, sections[i].offset, 
     4673                                        sections[i].offset)); 
     4674            IF_DEBUG(linker, debugBelch("relocateAddress: \taddress = %ld (%#lx)\n", address, address)); 
     4675 
     4676            IF_DEBUG(linker, debugBelch("relocateAddress: \tsections[%d].addr = %llu (%#llx)\n", i, sections[i].addr, 
     4677                                        sections[i].addr)); 
     4678            IF_DEBUG(linker, debugBelch("relocateAddress: done\n")); 
     4679            return relocated; 
    45884680        } 
    45894681    } 
    45904682    barf("Invalid Mach-O file:" 
     
    45924684    return 0; 
    45934685} 
    45944686 
    4595 static int relocateSection( 
     4687#endif 
     4688 
     4689 
     4690static void 
     4691checkProddableBlock_MachO (ObjectCode *oc, void *addr, int ll) 
     4692{ 
     4693    ProddableBlock* pb; 
     4694    int len; 
     4695 
     4696    // For x86_64, ll is the base 2 logarithm of the relocation 
     4697    // length. 
     4698    // 
     4699    // We need to check the actual relocation length instead of 
     4700    // the maximum length, otherwise we might incorrectly conclude 
     4701    // that the last relocation in a ProddableBlock runs off the end. 
     4702 
     4703    if (ll >= 0 && ll <= 3) { 
     4704        len = 2^ll; 
     4705    } else { 
     4706        barf("checkProddableBlock_MachO: invalid relocation length, %d\n", ll); 
     4707    } 
     4708 
     4709    for (pb = oc->proddables; pb != NULL; pb = pb->next) { 
     4710        char *s = (char *)(pb->start); 
     4711        char *e = s + pb->size - 1; 
     4712        char *a = (char *)addr; 
     4713 
     4714        if (a >= s && (a + (len - 1)) <= e) { 
     4715            return; 
     4716        } 
     4717    } 
     4718 
     4719    barf("checkProddableBlock_MachO: invalid fixup in runtime linker at %p, length %d", addr, len); 
     4720} 
     4721 
     4722 
     4723// Look up a symbol, either defined in the symbol table as an exportable 
     4724// reference in the current image. 
     4725 
     4726static uint64_t 
     4727findExternalSymbol( 
     4728    struct nlist *symbol, 
     4729    char *symbolName, 
     4730    ObjectCode *oc, 
     4731    struct section *sections) 
     4732{ 
     4733    uint64_t addr; 
     4734 
     4735    // If this is an exported external symbol, i.e., one that is 
     4736    // defined in this object file, then the N_SECT bit is set.  
     4737    // We just look up its address in the nlist. If not, look 
     4738    // up the address in the symbol table. 
     4739 
     4740    IF_DEBUG(linker, debugBelch("findSymbolAddress: looking for symbol %s\n", symbolName)); 
     4741    if ((symbol->n_type & N_TYPE) == N_SECT) { 
     4742        IF_DEBUG(linker, debugBelch("findSymbolAddress: \t%s is defined in this object file\n", symbolName)); 
     4743 
     4744        int sect = symbol->n_sect - 1; 
     4745        addr = (uint64_t) (oc->image + sections[sect].offset - sections[sect].addr + symbol->n_value); 
     4746 
     4747        IF_DEBUG(linker, debugBelch("findSymbolAddress: \toc->image = %p\n", oc->image)); 
     4748        IF_DEBUG(linker, debugBelch("findSymbolAddress: \tsection[%d].offset = %#0x\n", sect, sections[sect].offset)); 
     4749        IF_DEBUG(linker, debugBelch("findSymbolAddress: \tsection[%d].addr = %#0llx\n", sect, (unsigned long long)sections[sect].addr)); 
     4750        IF_DEBUG(linker, debugBelch("findSymbolAddress: \tsymbol->n_value = %#0llx\n", (unsigned long long)symbol->n_value)); 
     4751    } else { 
     4752        IF_DEBUG(linker, debugBelch("findSymbolAddress: \tsearching for %s in symbol table\n", symbolName)); 
     4753 
     4754        addr = (uint64_t) lookupSymbol(symbolName); 
     4755        if (!addr) { 
     4756            barf("findExternalSymbol: failed to find %s in the symbol table", symbolName); 
     4757        } else { 
     4758            IF_DEBUG(linker, debugBelch("findExternalSymbol: symbol %s is at %p\n", symbolName, (void *) addr)); 
     4759        } 
     4760    } 
     4761 
     4762    return addr; 
     4763} 
     4764 
     4765 
     4766// Look up an internal reference.  In this case, the fixup value initially 
     4767// read from the relocation entry contains the offset into the target section. 
     4768// We just need to find the installed memory address of the start of the 
     4769// target section. 
     4770 
     4771static uint64_t 
     4772findInternalReference( 
     4773    struct relocation_info *reloc, 
     4774    ObjectCode *oc, 
     4775    struct section *sections) 
     4776{ 
     4777    uint64_t addr; 
     4778 
     4779    // If reloc->r_symbolnum equals R_ABS (which is numerically zero), 
     4780    // the symbol is not relocatable and zero is returned, indicating that the 
     4781    // fixup should be written back unchanged.  Othewise, look up the 
     4782    // file offset of section number (reloc->r_symbolnum - 1) and add it 
     4783    // to the base address of the memory image. 
     4784 
     4785    if (reloc->r_symbolnum == R_ABS) { 
     4786        addr = 0; 
     4787        IF_DEBUG(linker, debugBelch("relocateSection: internal symbol is absolute (no relocation)\n")); 
     4788    } else { 
     4789        int sect = reloc->r_symbolnum - 1; 
     4790        addr = (uint64_t) (oc->image + sections[sect].offset); 
     4791        IF_DEBUG(linker, debugBelch("relocateSection: internal symbol is in section %d at %0llx\n", sect, addr)); 
     4792    } 
     4793 
     4794    return addr; 
     4795} 
     4796 
     4797 
     4798// Limits for pc relative offsets: 
     4799 
     4800#define MAX_8_BIT_FORWARD_DISPL 127 
     4801#define MIN_8_BIT_BACKWARD_DISPL -128 
     4802#define MAX_32_BIT_FORWARD_DISPL 2147483647 
     4803#define MIN_32_BIT_BACKWARD_DISPL -2147483648 
     4804 
     4805 
     4806// Perform all of the relocations in a section.  This is the core 
     4807// of the relocation operation. 
     4808 
     4809static int 
     4810relocateSection( 
    45964811    ObjectCode* oc, 
    45974812    char *image, 
    4598     struct symtab_command *symLC, struct nlist *nlist, 
    4599     int nSections, struct section* sections, struct section *sect) 
     4813    struct symtab_command *symLC, 
     4814    struct nlist *nlist, 
     4815    int nSections, 
     4816    struct section *sections, 
     4817    struct section *sect) 
    46004818{ 
    46014819    struct relocation_info *relocs; 
    46024820    int i, n; 
    46034821 
    46044822    IF_DEBUG(linker, debugBelch("relocateSection: start\n")); 
    46054823 
    4606     if(!strcmp(sect->sectname,"__la_symbol_ptr")) 
     4824    // Certain sections are only used for external references (references 
     4825    // to symbols defined in other files).  Symbols in these sections 
     4826    // have to be resolved to the installed address, but don't contain 
     4827    // relocations, so they are skipped. 
     4828 
     4829    if (strcmp(sect->sectname,"__la_symbol_ptr") == 0) { 
     4830        IF_DEBUG(linker, debugBelch("relocateSection: __la_symbol_ptr section, skipping\n"));  
    46074831        return 1; 
    4608     else if(!strcmp(sect->sectname,"__nl_symbol_ptr")) 
     4832    } 
     4833    else if (strcmp(sect->sectname,"__nl_symbol_ptr") == 0) { 
     4834        IF_DEBUG(linker, debugBelch("relocateSection: __nl_symbol_ptr section, skipping\n"));  
    46094835        return 1; 
    4610     else if(!strcmp(sect->sectname,"__la_sym_ptr2")) 
     4836    } 
     4837    else if (strcmp(sect->sectname,"__la_sym_ptr2") == 0) { 
     4838        IF_DEBUG(linker, debugBelch("relocateSection: __la_sym_ptr2 section, skipping\n"));  
    46114839        return 1; 
    4612     else if(!strcmp(sect->sectname,"__la_sym_ptr3")) 
     4840    } 
     4841    else if (strcmp(sect->sectname,"__la_sym_ptr3") == 0) { 
     4842        IF_DEBUG(linker, debugBelch("relocateSection: __la_sym_ptr3 section, skipping\n"));  
    46134843        return 1; 
     4844    } 
     4845 
     4846    // If we reach this point, we have a section that may need relocations. 
    46144847 
    46154848    n = sect->nreloc; 
    4616     IF_DEBUG(linker, debugBelch("relocateSection: number of relocations: %d\n", n)); 
     4849    relocs = (struct relocation_info *) (image + sect->reloff); 
    46174850 
    4618     relocs = (struct relocation_info*) (image + sect->reloff); 
     4851    IF_DEBUG(linker, debugBelch("relocateSection: section %s has %d relocations\n", sect->sectname, n)); 
     4852 
     4853    for (i = 0; i < n; i++) { 
    46194854 
    4620     for(i=0;i<n;i++) 
    4621     { 
    46224855#ifdef x86_64_HOST_ARCH 
     4856 
    46234857        struct relocation_info *reloc = &relocs[i]; 
    46244858 
    4625         char    *thingPtr = image + sect->offset + reloc->r_address; 
    4626         uint64_t thing; 
    4627         /* We shouldn't need to initialise this, but gcc on OS X 64 bit 
    4628            complains that it may be used uninitialized if we don't */ 
    4629         uint64_t value = 0; 
    4630         uint64_t baseValue; 
     4859        // The object that may require relocation (commonly, a "fixup") is 
     4860        // located at offset reloc->r_address from the start of the section. 
     4861        // The start of the section is at memory address image + sect->offset. 
     4862        // The location of the fixup is therefore given by the expression 
     4863        // for fixupPtr below. 
     4864        // 
     4865        // The variable fixup will contain the final fixed-up value written 
     4866        // to the location given by fixupPtr. 
     4867 
     4868        void    *fixupPtr = image + sect->offset + reloc->r_address; 
     4869        uint64_t fixup; 
     4870 
     4871        uint64_t addr; 
     4872        uint64_t pc; 
     4873 
     4874        struct nlist *symbol = NULL; 
     4875        char *symbolName     = NULL; 
     4876         
    46314877        int type = reloc->r_type; 
    46324878 
    4633         checkProddableBlock(oc,thingPtr); 
     4879        if (nSections > 255) { 
     4880                barf("relocateSection: nSections > 255"); 
     4881        } 
     4882 
     4883        // Check that we can write to the location that fixupPtr points to. 
     4884        // If we can't, checkProddableBlock_MachO will barf. 
     4885         
     4886        checkProddableBlock_MachO(oc, fixupPtr, reloc->r_length); 
     4887 
     4888        // Read the object to be relocated (the "fixup") from the fixupPtr. 
     4889        // Then calculate the notional program counter ("pc") used for 
     4890        // relative relocations. The notional pc is address of the next 
     4891        // instruction after the one containing the relocation. 
     4892 
    46344893        switch(reloc->r_length) 
    46354894        { 
    46364895            case 0: 
    4637                 thing = *(uint8_t*)thingPtr; 
    4638                 baseValue = (uint64_t)thingPtr + 1; 
     4896                fixup = *(uint8_t *)fixupPtr; 
     4897                pc    = (uint64_t)fixupPtr + 1; 
    46394898                break; 
    46404899            case 1: 
    4641                 thing = *(uint16_t*)thingPtr; 
    4642                 baseValue = (uint64_t)thingPtr + 2; 
     4900                fixup = *(uint16_t *)fixupPtr; 
     4901                pc    = (uint64_t)fixupPtr + 2; 
    46434902                break; 
    46444903            case 2: 
    4645                 thing = *(uint32_t*)thingPtr; 
    4646                 baseValue = (uint64_t)thingPtr + 4; 
     4904                fixup = *(uint32_t *)fixupPtr; 
     4905                pc    = (uint64_t)fixupPtr + 4; 
    46474906                break; 
    46484907            case 3: 
    4649                 thing = *(uint64_t*)thingPtr; 
    4650                 baseValue = (uint64_t)thingPtr + 8; 
     4908                fixup = *(uint64_t *)fixupPtr; 
     4909                pc    = (uint64_t)fixupPtr + 8; 
    46514910                break; 
    46524911            default: 
    4653                 barf("Unknown size."); 
     4912                barf("relocateSection: Unknown relocation length %d", reloc->r_length); 
    46544913        } 
    46554914 
    4656         IF_DEBUG(linker, 
    4657                  debugBelch("relocateSection: length = %d, thing = %" PRId64 ", baseValue = %p\n", 
    4658                             reloc->r_length, thing, (char *)baseValue)); 
     4915        IF_DEBUG(linker, debugBelch("relocateSection: relocation %d has\n", i)); 
     4916        IF_DEBUG(linker, debugBelch("relocateSection: \tr_address   = %d (%#x)\n", 
     4917                                    reloc->r_address, 
     4918                                    reloc->r_address)); 
     4919        IF_DEBUG(linker, debugBelch("relocateSection: \tr_symbolnum = %u (%#x)\n", 
     4920                                    reloc->r_symbolnum, 
     4921                                    reloc->r_symbolnum)); 
     4922        IF_DEBUG(linker, debugBelch("relocateSection: \tr_pcrel     = %d\n", 
     4923                                    reloc->r_pcrel)); 
     4924        IF_DEBUG(linker, debugBelch("relocateSection: \tr_length    = %d\n", 
     4925                                    reloc->r_length)); 
     4926        IF_DEBUG(linker, debugBelch("relocateSection: \tr_extern    = %d\n", 
     4927                                    reloc->r_extern)); 
     4928        IF_DEBUG(linker, debugBelch("relocateSection: \tr_type      = %d (%#x)\n", 
     4929                                    reloc->r_type, reloc->r_type)); 
     4930        IF_DEBUG(linker, debugBelch("relocateSection: \tfixupPtr = %p, fixup = 0x%lx, pc = %p\n", 
     4931                                    fixupPtr, 
     4932                                    (unsigned long)fixup, 
     4933                                    (void *)pc)); 
     4934 
     4935        // For external relocations, get the symbol table entry and the 
     4936        // symbol name. 
     4937 
     4938        if (reloc->r_extern) { 
     4939            symbol     = &nlist[reloc->r_symbolnum]; 
     4940            symbolName = image + symLC->stroff + symbol->n_un.n_strx; 
     4941        } 
     4942 
     4943        // Do the relocation.  This is not the shortest possible way 
     4944        // to do this, but by considering each type of relocation and 
     4945        // whether the relocation is external and the length of the relocated 
     4946        // object, all invalid cases can be caught. 
    46594947 
    4660         if (type == X86_64_RELOC_GOT 
    4661            || type == X86_64_RELOC_GOT_LOAD) 
     4948        switch (type) 
    46624949        { 
    4663             struct nlist *symbol = &nlist[reloc->r_symbolnum]; 
    4664             char *nm = image + symLC->stroff + symbol->n_un.n_strx; 
     4950        case X86_64_RELOC_GOT: 
     4951        case X86_64_RELOC_GOT_LOAD: 
     4952 
     4953            ASSERT(reloc->r_pcrel);          // GOT and GOT_LOAD are always pc-relative, 
     4954            ASSERT(reloc->r_extern);         // always external, 
     4955            ASSERT(reloc->r_length == 2);    // and always 32 bit. 
     4956 
     4957            // Create a Global Offset Table (GOT) entry and install the 
     4958            // address of the symbol in the table.  The address of the 
     4959            // GOT entry is target of the final pc relative relocation. 
     4960 
     4961            addr = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, (unsigned long)lookupSymbol(symbolName))->addr; 
     4962 
     4963            IF_DEBUG(linker, debugBelch("relocateSection: type is X64_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n")); 
     4964            IF_DEBUG(linker, debugBelch("relocateSection: GOT entry for %s is at %0llx\n", symbolName, addr)); 
     4965 
     4966            fixup += (addr - pc); 
     4967            break; 
     4968 
     4969        case X86_64_RELOC_UNSIGNED: 
    46654970 
    4666             IF_DEBUG(linker, debugBelch("relocateSection: making jump island for %s, extern = %d, X86_64_RELOC_GOT\n", nm, reloc->r_extern)); 
    4667             ASSERT(reloc->r_extern); 
    4668             value = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, (unsigned long)lookupSymbol(nm))->addr; 
     4971            ASSERT(!reloc->r_pcrel);          // UNSIGNED relocs are always absolute addresses 
     4972            ASSERT(reloc->r_length >= 2);     // and always 32 or 64 bits. 
    46694973 
    4670             type = X86_64_RELOC_SIGNED; 
     4974            IF_DEBUG(linker, debugBelch("relocateSection: type is X86_64_RELOC_UNSIGNED\n")); 
     4975 
     4976            if (reloc->r_extern) { 
     4977                addr = findExternalSymbol(symbol, symbolName, oc, sections); 
     4978                IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s found at %0llx\n", symbolName, addr)); 
     4979            } 
     4980            else { 
     4981                // Non-external, UNSIGNED relocation: the fixup contains the address 
     4982                // of the target from the start of the memory image.  So just add 
     4983                // the memory address of the begining of the mmap'ed object code. 
     4984 
     4985                int s = reloc->r_symbolnum - 1; 
     4986                addr = (uint64_t)(oc->image + sections[s].offset - sections[s].addr); 
     4987                IF_DEBUG(linker, debugBelch("relocateSection: start target section is at %0llx\n", addr)); 
     4988            } 
     4989 
     4990            fixup += addr; 
     4991 
     4992            break; 
     4993 
     4994        case X86_64_RELOC_BRANCH: 
     4995 
     4996            ASSERT(reloc->r_pcrel);           // BRANCH relocs are always pc-relative, 
     4997            ASSERT(reloc->r_length == 0 ||    // and either 8 or 32 bits. 
     4998                   reloc->r_length == 2); 
     4999 
     5000            IF_DEBUG(linker, debugBelch("relocateSection: type is X86_64_RELOC_BRANCH\n")); 
     5001 
     5002            int64_t displ; 
     5003 
     5004            if (reloc->r_length == 0) { 
     5005                if (reloc->r_extern) { 
     5006                    addr = findExternalSymbol(symbol, symbolName, oc, sections); 
     5007                    IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s found at %0llx\n", symbolName, addr)); 
     5008                } 
     5009                else { 
     5010                    addr = findInternalReference(reloc, oc, sections); 
     5011                    IF_DEBUG(linker, debugBelch("relocateSection: internal reference found at %0llx\n", addr)); 
     5012                } 
     5013 
     5014                if (addr == 0) { 
     5015                    barf("relocateSection: non-relocatable symbol found in 8 bit BRANCH relocation\n"); 
     5016                }  
     5017 
     5018                displ = addr - pc; 
     5019 
     5020                if (displ > 0) { 
     5021                    if (displ > MAX_8_BIT_FORWARD_DISPL) { 
     5022                        barf("relocateSection: required 8 bit displacement too far forward"); 
     5023                    } 
     5024                } else { 
     5025                    if (displ < MIN_8_BIT_BACKWARD_DISPL) { 
     5026                        barf("relocateSection: required 8 bit displacement too far backward"); 
    46715027        } 
    4672         else if(reloc->r_extern) 
    4673         { 
    4674             struct nlist *symbol = &nlist[reloc->r_symbolnum]; 
    4675             char *nm = image + symLC->stroff + symbol->n_un.n_strx; 
     5028                } 
     5029 
     5030                IF_DEBUG(linker, debugBelch("relocateSection: 8 bit BRANCH displacement = %lld (%#0llx)\n", displ, (unsigned long long) displ)); 
    46765031 
    4677             IF_DEBUG(linker, debugBelch("relocateSection: looking up external symbol %s\n", nm)); 
    4678             IF_DEBUG(linker, debugBelch("               : type  = %d\n", symbol->n_type)); 
    4679             IF_DEBUG(linker, debugBelch("               : sect  = %d\n", symbol->n_sect)); 
    4680             IF_DEBUG(linker, debugBelch("               : desc  = %d\n", symbol->n_desc)); 
    4681             IF_DEBUG(linker, debugBelch("               : value = %p\n", (void *)symbol->n_value)); 
    4682             if ((symbol->n_type & N_TYPE) == N_SECT) { 
    4683                 value = relocateAddress(oc, nSections, sections, 
    4684                                         symbol->n_value); 
    4685                 IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n", nm, (void *)value)); 
     5032            } else { 
     5033                if (reloc->r_extern) { 
     5034                    addr = findExternalSymbol(symbol, symbolName, oc, sections); 
     5035                    IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s found at %0llx\n", symbolName, addr)); 
    46865036            } 
    46875037            else { 
    4688                 value = (uint64_t) lookupSymbol(nm); 
    4689                 IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s, address %p\n", nm, (void *)value)); 
     5038                    addr = findInternalReference(reloc, oc, sections); 
     5039                    IF_DEBUG(linker, debugBelch("relocateSection: internal reference found at %0llx\n", addr)); 
     5040                } 
     5041 
     5042                if (addr == 0) { 
     5043                    barf("relocateSection: non-relocatable symbol found in 32 bit BRANCH relocation\n"); 
     5044                }  
     5045 
     5046                displ = addr - pc; 
     5047 
     5048                IF_DEBUG(linker, debugBelch("relocateSection: 32 bit BRANCH displacement = %lld (%#0llx)\n", displ, (unsigned long long) displ)); 
     5049                 
     5050                if (((displ > 0) && (displ > MAX_32_BIT_FORWARD_DISPL)) 
     5051                 || ((displ < 0) && (displ < MIN_32_BIT_BACKWARD_DISPL))) { 
     5052                    addr = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, addr)->jumpIsland; 
     5053                    IF_DEBUG(linker, debugBelch("relocateSection: making jump island for 32 bit BRANCH relocation: %#0llx\n", addr)); 
     5054                    displ = addr - pc; 
     5055 
     5056                    IF_DEBUG(linker, debugBelch("relocateSection: 32 bit BRANCH displacement to jump island= %lld (%#0llx)\n", displ, (unsigned long long) displ)); 
     5057                } 
    46905058            } 
     5059 
     5060            fixup += displ; 
     5061 
     5062            break; 
     5063 
     5064        case X86_64_RELOC_SUBTRACTOR: 
     5065 
     5066            IF_DEBUG(linker, debugBelch("relocateSection: type is X86_64_RELOC_SUBTRACTOR\n")); 
     5067 
     5068            // An X86_64_RELOC_SUBTRACTOR can never be the last relocation 
     5069            // in a section, since it must be followed by an X86_64_RELOC_UNSIGNED. 
     5070            // Barf if this isn't true. 
     5071 
     5072            if (i == (n - 1)) { 
     5073                barf("X86_64_RELOC_SUBTRACTOR is the last relocation in section %s", sect->sectname); 
     5074            } 
     5075 
     5076            struct relocation_info *nextReloc =  &relocs[i + 1]; 
     5077 
     5078            ASSERT(!reloc->r_pcrel);                              // SUBTRACTOR relocs must not be pc relative, 
     5079            ASSERT(reloc->r_length == 2 ||                        // must be 32 or 64 bits, 
     5080                   reloc->r_length == 3);                         // 
     5081            ASSERT(reloc->r_extern);                              // must be external, 
     5082            ASSERT(nextReloc->r_type == X86_64_RELOC_UNSIGNED);   // must be followed by a X86_64_RELOC_UNSIGNED, 
     5083            ASSERT(nextReloc->r_length == nextReloc->r_length);   // with the same length as the SUBTRACTOR reloc, 
     5084            ASSERT(!nextReloc->r_pcrel);                          // and must also not be pc relative. Got it? 
     5085 
     5086            if (nextReloc->r_type != X86_64_RELOC_UNSIGNED) { 
     5087                barf("relocateSection: SUBTRACTOR must be followed by UNSIGNED"); 
    46915088        } 
    4692         else 
    4693         { 
    4694             // If the relocation is not through the global offset table 
    4695             // or external, then set the value to the baseValue.  This 
    4696             // will leave displacements into the __const section 
    4697             // unchanged (as they ought to be). 
    46985089 
    4699             value = baseValue; 
     5090            if (reloc->r_length == 2) { 
     5091                    addr = findExternalSymbol(symbol, symbolName, oc, sections); 
     5092                    IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s found at %0llx\n", symbolName, addr)); 
    47005093        } 
     5094            else { 
     5095                    addr = findExternalSymbol(symbol, symbolName, oc, sections); 
     5096                    IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s found at %0llx\n", symbolName, addr)); 
     5097            } 
     5098 
     5099            // Subtract the symbol address from the fixup.  The subsequent 
     5100            // UNSIGNED relocation will add the address of another external 
     5101            // symbol, so the final relocation will be the difference of the 
     5102            // symbol addresses, plus any offset originally saved in the 
     5103            // fixup location. 
     5104 
     5105            fixup -= addr; 
     5106 
     5107            break; 
     5108 
     5109        case X86_64_RELOC_SIGNED: 
     5110        case X86_64_RELOC_SIGNED_1: 
     5111        case X86_64_RELOC_SIGNED_2: 
     5112        case X86_64_RELOC_SIGNED_4: 
     5113 
     5114            IF_DEBUG(linker, debugBelch("relocateSection: type is X86_64_RELOC_SIGNED/1/2/4\n")); 
    47015115 
    4702         IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", (void *)value)); 
     5116            uint64_t addend = 0; 
    47035117 
    4704         if (type == X86_64_RELOC_BRANCH) 
     5118            ASSERT(reloc->r_pcrel);           // SIGNED relocs are always pc relative 
     5119            ASSERT(reloc->r_length == 2);     // and 32 bits long. 
     5120 
     5121            if (reloc->r_extern) { 
     5122                switch (reloc->r_type) 
    47055123        { 
    4706             if((int32_t)(value - baseValue) != (int64_t)(value - baseValue)) 
    4707             { 
    4708                 ASSERT(reloc->r_extern); 
    4709                 value = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, value) 
    4710                                         -> jumpIsland; 
     5124                case X86_64_RELOC_SIGNED: 
     5125                    addend = 0; 
     5126                    break; 
     5127                case X86_64_RELOC_SIGNED_1: 
     5128                    addend = 1; 
     5129                    break; 
     5130                case X86_64_RELOC_SIGNED_2: 
     5131                    addend = 2; 
     5132                    break; 
     5133                case X86_64_RELOC_SIGNED_4: 
     5134                    addend = 4; 
     5135                    break; 
    47115136            } 
    4712             ASSERT((int32_t)(value - baseValue) == (int64_t)(value - baseValue)); 
    4713             type = X86_64_RELOC_SIGNED; 
     5137 
     5138                addr = findExternalSymbol(symbol, symbolName, oc, sections); 
     5139                IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s found at %0llx\n", symbolName, addr)); 
    47145140        } 
     5141            else { 
     5142 
     5143                // Relocations that are both SIGNED and not external 
     5144                // have compiler computed offsets to the target address 
     5145                // in the object file. We needn't do anything at all with these. 
    47155146 
    4716         switch(type) 
     5147                switch (reloc->r_type) 
    47175148        { 
    4718             case X86_64_RELOC_UNSIGNED: 
    4719                 ASSERT(!reloc->r_pcrel); 
    4720                 thing += value; 
     5149                case X86_64_RELOC_SIGNED: 
     5150                    addend = 0; 
    47215151                break; 
    4722             case X86_64_RELOC_SIGNED: 
    47235152            case X86_64_RELOC_SIGNED_1: 
     5153                    addend = 1; 
     5154                    break; 
    47245155            case X86_64_RELOC_SIGNED_2: 
     5156                    addend = 2; 
     5157                    break; 
    47255158            case X86_64_RELOC_SIGNED_4: 
    4726                 ASSERT(reloc->r_pcrel); 
    4727                 thing += value - baseValue; 
     5159                    addend = 4; 
    47285160                break; 
    4729             case X86_64_RELOC_SUBTRACTOR: 
    4730                 ASSERT(!reloc->r_pcrel); 
    4731                 thing -= value; 
     5161                } 
     5162 
     5163                addr = pc; 
     5164                IF_DEBUG(linker, debugBelch("relocateSection: not external, leaving fixup unchanged.\n")); 
     5165            } 
     5166 
     5167            fixup += (addr - pc) + addend; 
     5168 
    47325169                break; 
     5170 
    47335171            default: 
    4734                 barf("unkown relocation"); 
     5172            barf("relocateSection: unknown relocation type"); 
     5173 
    47355174        } 
    47365175 
     5176        IF_DEBUG(linker, debugBelch("relocateSection: FINAL: reloc = %d, addr = %0lx, fixup = %0llx\n", i, (unsigned long)reloc->r_address, fixup)); 
     5177        // Write the fixed-up value back to the image. 
     5178 
    47375179        switch(reloc->r_length) 
    47385180        { 
    47395181            case 0: 
    4740                 *(uint8_t*)thingPtr = thing; 
     5182                IF_DEBUG(linker, debugBelch("relocateSection: 8 bit reloc, fixup %#0x written to %p\n", 
     5183                                            (uint8_t)fixup, fixupPtr)); 
     5184                *(uint8_t *)fixupPtr = fixup; 
    47415185                break; 
    47425186            case 1: 
    4743                 *(uint16_t*)thingPtr = thing; 
     5187                IF_DEBUG(linker, debugBelch("relocateSection: 16 bit reloc, fixup %#0x written to %p\n", 
     5188                                            (uint16_t)fixup, fixupPtr)); 
     5189                *(uint16_t *)fixupPtr = fixup; 
    47445190                break; 
    47455191            case 2: 
    4746                 *(uint32_t*)thingPtr = thing; 
     5192                IF_DEBUG(linker, debugBelch("relocateSection: 32 bit reloc, fixup %#0x written to %p\n", 
     5193                                            (uint32_t)fixup, fixupPtr)); 
     5194                *(uint32_t *)fixupPtr = fixup; 
    47475195                break; 
    47485196            case 3: 
    4749                 *(uint64_t*)thingPtr = thing; 
     5197                IF_DEBUG(linker, debugBelch("relocateSection: 64 bit reloc, fixup %#0llx written to %p\n", 
     5198                                            (uint64_t)fixup, fixupPtr)); 
     5199                *(uint64_t *)fixupPtr = fixup; 
    47505200                break; 
    47515201        } 
    4752 #else 
    4753         if(relocs[i].r_address & R_SCATTERED) 
    4754         { 
     5202 
     5203#else // x86 and powerpc architectures start here 
     5204 
     5205        if (relocs[i].r_address & R_SCATTERED) { 
    47555206            struct scattered_relocation_info *scat = 
    47565207                (struct scattered_relocation_info*) &relocs[i]; 
    47575208 
    4758             if(!scat->r_pcrel) 
    4759             { 
    4760                 if(scat->r_length == 2) 
    4761                 { 
     5209            if (!scat->r_pcrel) { 
     5210                if (scat->r_length == 2) { 
     5211 
    47625212                    unsigned long word = 0; 
    47635213                    unsigned long* wordPtr = (unsigned long*) (image + sect->offset + scat->r_address); 
     5214 
    47645215                    checkProddableBlock(oc,wordPtr); 
    47655216 
    47665217                    // Note on relocation types: 
     
    51695637                    commonSize += nlist[i].n_value; 
    51705638                    oc->n_symbols++; 
    51715639                } 
    5172                 else if((nlist[i].n_type & N_TYPE) == N_SECT) 
     5640                else if ((nlist[i].n_type & N_TYPE) == N_SECT) { 
    51735641                    oc->n_symbols++; 
    51745642            } 
    51755643        } 
    51765644    } 
     5645    } 
     5646 
    51775647    IF_DEBUG(linker, debugBelch("ocGetNames_MachO: %d external symbols\n", oc->n_symbols)); 
    51785648    oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(char*), 
    51795649                                   "ocGetNames_MachO(oc->symbols)"); 
    51805650 
    5181     if(symLC) 
    5182     { 
    5183         for(i=0;i<symLC->nsyms;i++) 
    5184         { 
    5185             if(nlist[i].n_type & N_STAB) 
     5651    if (symLC) { 
     5652        for (i = 0; i < symLC->nsyms; i++) { 
     5653            IF_DEBUG(linker, debugBelch("ocGetNames_MachO: symbol type is %#04x\n", nlist[i].n_type)); 
     5654            if (nlist[i].n_type & N_STAB) { 
    51865655                ; 
     5656            } 
    51875657            else if((nlist[i].n_type & N_TYPE) == N_SECT) 
    51885658            { 
    5189                 if(nlist[i].n_type & N_EXT) 
     5659                if ((nlist[i].n_type & N_EXT) && !(nlist[i].n_type & N_PEXT)) 
    51905660                { 
    51915661                    char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; 
     5662 
    51925663                    if ((nlist[i].n_desc & N_WEAK_DEF) && lookupSymbol(nm)) { 
    51935664                        // weak definition, and we already have a definition 
    5194                         IF_DEBUG(linker, debugBelch("    weak: %s\n", nm)); 
     5665                        IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \tweak: %s\n", nm)); 
    51955666                    } 
    51965667                    else 
    51975668                    { 
     
    52625751    nlist = symLC ? (struct nlist*) (image + symLC->symoff) 
    52635752                  : NULL; 
    52645753 
    5265     if(dsymLC) 
    5266     { 
     5754    if (dsymLC) { 
    52675755        unsigned long *indirectSyms 
    52685756            = (unsigned long*) (image + dsymLC->indirectsymoff); 
    52695757 
    5270         IF_DEBUG(linker, debugBelch("ocResolve_MachO: resolving dsymLC\n")); 
    5271         for (i = 0; i < segLC->nsects; i++) 
    5272         { 
    5273             if(    !strcmp(sections[i].sectname,"__la_symbol_ptr") 
    5274                 || !strcmp(sections[i].sectname,"__la_sym_ptr2") 
    5275                 || !strcmp(sections[i].sectname,"__la_sym_ptr3")) 
     5758        IF_DEBUG(linker, debugBelch("ocResolve_MachO: trying to resolve dynamic symbols\n")); 
     5759        for (i = 0; i < segLC->nsects; i++) { 
     5760            if (    strcmp(sections[i].sectname,"__la_symbol_ptr") == 0 
     5761                 || strcmp(sections[i].sectname,"__la_sym_ptr2")   == 0 
     5762                 || strcmp(sections[i].sectname,"__la_sym_ptr3")   == 0) 
    52765763            { 
     5764                IF_DEBUG(linker, debugBelch("ocResolve_machO: resolving __la_symbol_ptr, __la_sym_ptr2 or __la_sym_ptr3 section\n")); 
    52775765                if(!resolveImports(oc,image,symLC,&sections[i],indirectSyms,nlist)) 
    52785766                    return 0; 
    52795767            } 
    5280             else if(!strcmp(sections[i].sectname,"__nl_symbol_ptr") 
    5281                 ||  !strcmp(sections[i].sectname,"__pointers")) 
     5768            else if (strcmp(sections[i].sectname,"__nl_symbol_ptr") == 0 
     5769                 ||  strcmp(sections[i].sectname,"__pointers")      == 0) 
    52825770            { 
     5771                IF_DEBUG(linker, debugBelch("ocResolve_machO: resolving __nl_symbol_ptr or __pointers section\n")); 
    52835772                if(!resolveImports(oc,image,symLC,&sections[i],indirectSyms,nlist)) 
    52845773                    return 0; 
    52855774            } 
    5286             else if(!strcmp(sections[i].sectname,"__jump_table")) 
     5775            else if (strcmp(sections[i].sectname,"__jump_table") == 0) 
    52875776            { 
     5777                IF_DEBUG(linker, debugBelch("ocResolve_MachO: resolving jump table\n")); 
    52885778                if(!resolveImports(oc,image,symLC,&sections[i],indirectSyms,nlist)) 
    52895779                    return 0; 
    52905780            } 
    52915781            else 
    52925782            { 
    5293                 IF_DEBUG(linker, debugBelch("ocResolve_MachO: unknown section\n")); 
     5783                    IF_DEBUG(linker, debugBelch("ocResolve_MachO: %s is not used by the dynamic linker, skipping\n", sections[i].sectname)); 
    52945784            } 
    52955785        } 
     5786        IF_DEBUG(linker, debugBelch("ocResolve_MachO: done resolving dynamic symbols\n")); 
    52965787    } 
    52975788 
    5298     for(i=0;i<segLC->nsects;i++) 
    5299     { 
    5300             IF_DEBUG(linker, debugBelch("ocResolve_MachO: relocating section %d\n", i)); 
     5789    IF_DEBUG(linker, debugBelch("ocResolve_MachO: beginning relocations\n")); 
     5790 
     5791    IF_DEBUG(linker,  
     5792    for (i = 0; i < segLC->nsects; i++) { 
     5793        debugBelch("ocResolve_MachO: \tsection[%d].sectname = %s\n", i, sections[i].sectname); 
     5794        debugBelch("ocResolve_MachO: \tsection[%d].segname  = %s\n", i, sections[i].segname); 
     5795        debugBelch("ocResolve_MachO: \tsection[%d].addr     = %#0llx\n", i, (unsigned long long)sections[i].addr); 
     5796        debugBelch("ocResolve_MachO: \tsection[%d].size     = %#0llx\n", i, (unsigned long long)sections[i].size); 
     5797        debugBelch("ocResolve_MachO: \tsection[%d].offset   = %#0lx\n", i, (unsigned long)sections[i].offset); 
     5798        debugBelch("ocResolve_MachO: \tsection[%d].align    = %#0lx\n", i, (unsigned long)sections[i].align); 
     5799        debugBelch("ocResolve_MachO: \tsection[%d].reloff   = %#0lx\n", i, (unsigned long)sections[i].reloff); 
     5800        debugBelch("ocResolve_MachO: \tsection[%d].nreloc   = %#0lx\n", i, (unsigned long)sections[i].nreloc); 
     5801        debugBelch("ocResolve_MachO: \tsection[%d].flags    = %#0lx\n", i, (unsigned long)sections[i].flags); 
     5802        debugBelch("ocResolve_MachO: \n"); 
     5803    }); 
     5804 
     5805    for (i = 0; i < segLC->nsects; i++) { 
     5806 
     5807        IF_DEBUG(linker, debugBelch("ocResolve_MachO: relocating section %d (%s)\n", i, sections[i].sectname)); 
    53015808 
    53025809        if (!relocateSection(oc,image,symLC,nlist,segLC->nsects,sections,&sections[i])) 
    53035810            return 0; 
    53045811    } 
    53055812 
     5813    IF_DEBUG(linker, debugBelch("ocResolve_MachO: finished relocating\n")); 
     5814 
    53065815#if defined (powerpc_HOST_ARCH) 
    53075816    ocFlushInstructionCache( oc ); 
    53085817#endif 
    53095818 
     5819    IF_DEBUG(linker, debugBelch("ocResolve_MachO: done\n")); 
    53105820    return 1; 
    53115821} 
    53125822