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 4569 4642 return 1; 4570 4643 } 4571 4644 4572 static unsigned long relocateAddress( 4645 4646 #ifndef x86_64_HOST_ARCH 4647 4648 static unsigned long 4649 relocateAddress( 4573 4650 ObjectCode* oc, 4574 4651 int nSections, 4575 4652 struct section* sections, 4576 4653 unsigned long address) 4577 4654 { 4578 4655 int i; 4656 unsigned long relocated; 4657 4579 4658 IF_DEBUG(linker, debugBelch("relocateAddress: start\n")); 4580 4659 for (i = 0; i < nSections; i++) 4581 4660 { 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 4583 4664 if (sections[i].addr <= address 4584 4665 && address < sections[i].addr + sections[i].size) 4585 4666 { 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; 4588 4680 } 4589 4681 } 4590 4682 barf("Invalid Mach-O file:" … … 4592 4684 return 0; 4593 4685 } 4594 4686 4595 static int relocateSection( 4687 #endif 4688 4689 4690 static void 4691 checkProddableBlock_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 4726 static uint64_t 4727 findExternalSymbol( 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 4771 static uint64_t 4772 findInternalReference( 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 4809 static int 4810 relocateSection( 4596 4811 ObjectCode* oc, 4597 4812 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) 4600 4818 { 4601 4819 struct relocation_info *relocs; 4602 4820 int i, n; 4603 4821 4604 4822 IF_DEBUG(linker, debugBelch("relocateSection: start\n")); 4605 4823 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")); 4607 4831 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")); 4609 4835 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")); 4611 4839 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")); 4613 4843 return 1; 4844 } 4845 4846 // If we reach this point, we have a section that may need relocations. 4614 4847 4615 4848 n = sect->nreloc; 4616 IF_DEBUG(linker, debugBelch("relocateSection: number of relocations: %d\n", n));4849 relocs = (struct relocation_info *) (image + sect->reloff); 4617 4850 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++) { 4619 4854 4620 for(i=0;i<n;i++)4621 {4622 4855 #ifdef x86_64_HOST_ARCH 4856 4623 4857 struct relocation_info *reloc = &relocs[i]; 4624 4858 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 4631 4877 int type = reloc->r_type; 4632 4878 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 4634 4893 switch(reloc->r_length) 4635 4894 { 4636 4895 case 0: 4637 thing = *(uint8_t*)thingPtr;4638 baseValue = (uint64_t)thingPtr + 1;4896 fixup = *(uint8_t *)fixupPtr; 4897 pc = (uint64_t)fixupPtr + 1; 4639 4898 break; 4640 4899 case 1: 4641 thing = *(uint16_t*)thingPtr;4642 baseValue = (uint64_t)thingPtr + 2;4900 fixup = *(uint16_t *)fixupPtr; 4901 pc = (uint64_t)fixupPtr + 2; 4643 4902 break; 4644 4903 case 2: 4645 thing = *(uint32_t*)thingPtr;4646 baseValue = (uint64_t)thingPtr + 4;4904 fixup = *(uint32_t *)fixupPtr; 4905 pc = (uint64_t)fixupPtr + 4; 4647 4906 break; 4648 4907 case 3: 4649 thing = *(uint64_t*)thingPtr;4650 baseValue = (uint64_t)thingPtr + 8;4908 fixup = *(uint64_t *)fixupPtr; 4909 pc = (uint64_t)fixupPtr + 8; 4651 4910 break; 4652 4911 default: 4653 barf(" Unknown size.");4912 barf("relocateSection: Unknown relocation length %d", reloc->r_length); 4654 4913 } 4655 4914 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. 4659 4947 4660 if (type == X86_64_RELOC_GOT 4661 || type == X86_64_RELOC_GOT_LOAD) 4948 switch (type) 4662 4949 { 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: 4665 4970 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. 4669 4973 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"); 4671 5027 } 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)); 4676 5031 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)); 4686 5036 } 4687 5037 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 } 4690 5058 } 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"); 4691 5088 } 4692 else4693 {4694 // If the relocation is not through the global offset table4695 // or external, then set the value to the baseValue. This4696 // will leave displacements into the __const section4697 // unchanged (as they ought to be).4698 5089 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)); 4700 5093 } 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")); 4701 5115 4702 IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", (void *)value));5116 uint64_t addend = 0; 4703 5117 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) 4705 5123 { 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; 4711 5136 } 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)); 4714 5140 } 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. 4715 5146 4716 switch(type)5147 switch (reloc->r_type) 4717 5148 { 4718 case X86_64_RELOC_UNSIGNED: 4719 ASSERT(!reloc->r_pcrel); 4720 thing += value; 5149 case X86_64_RELOC_SIGNED: 5150 addend = 0; 4721 5151 break; 4722 case X86_64_RELOC_SIGNED:4723 5152 case X86_64_RELOC_SIGNED_1: 5153 addend = 1; 5154 break; 4724 5155 case X86_64_RELOC_SIGNED_2: 5156 addend = 2; 5157 break; 4725 5158 case X86_64_RELOC_SIGNED_4: 4726 ASSERT(reloc->r_pcrel); 4727 thing += value - baseValue; 5159 addend = 4; 4728 5160 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 4732 5169 break; 5170 4733 5171 default: 4734 barf("unkown relocation"); 5172 barf("relocateSection: unknown relocation type"); 5173 4735 5174 } 4736 5175 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 4737 5179 switch(reloc->r_length) 4738 5180 { 4739 5181 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; 4741 5185 break; 4742 5186 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; 4744 5190 break; 4745 5191 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; 4747 5195 break; 4748 5196 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; 4750 5200 break; 4751 5201 } 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) { 4755 5206 struct scattered_relocation_info *scat = 4756 5207 (struct scattered_relocation_info*) &relocs[i]; 4757 5208 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 4762 5212 unsigned long word = 0; 4763 5213 unsigned long* wordPtr = (unsigned long*) (image + sect->offset + scat->r_address); 5214 4764 5215 checkProddableBlock(oc,wordPtr); 4765 5216 4766 5217 // Note on relocation types: … … 5169 5637 commonSize += nlist[i].n_value; 5170 5638 oc->n_symbols++; 5171 5639 } 5172 else if ((nlist[i].n_type & N_TYPE) == N_SECT)5640 else if ((nlist[i].n_type & N_TYPE) == N_SECT) { 5173 5641 oc->n_symbols++; 5174 5642 } 5175 5643 } 5176 5644 } 5645 } 5646 5177 5647 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: %d external symbols\n", oc->n_symbols)); 5178 5648 oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(char*), 5179 5649 "ocGetNames_MachO(oc->symbols)"); 5180 5650 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) { 5186 5655 ; 5656 } 5187 5657 else if((nlist[i].n_type & N_TYPE) == N_SECT) 5188 5658 { 5189 if (nlist[i].n_type & N_EXT)5659 if ((nlist[i].n_type & N_EXT) && !(nlist[i].n_type & N_PEXT)) 5190 5660 { 5191 5661 char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; 5662 5192 5663 if ((nlist[i].n_desc & N_WEAK_DEF) && lookupSymbol(nm)) { 5193 5664 // 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)); 5195 5666 } 5196 5667 else 5197 5668 { … … 5262 5751 nlist = symLC ? (struct nlist*) (image + symLC->symoff) 5263 5752 : NULL; 5264 5753 5265 if(dsymLC) 5266 { 5754 if (dsymLC) { 5267 5755 unsigned long *indirectSyms 5268 5756 = (unsigned long*) (image + dsymLC->indirectsymoff); 5269 5757 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) 5276 5763 { 5764 IF_DEBUG(linker, debugBelch("ocResolve_machO: resolving __la_symbol_ptr, __la_sym_ptr2 or __la_sym_ptr3 section\n")); 5277 5765 if(!resolveImports(oc,image,symLC,§ions[i],indirectSyms,nlist)) 5278 5766 return 0; 5279 5767 } 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) 5282 5770 { 5771 IF_DEBUG(linker, debugBelch("ocResolve_machO: resolving __nl_symbol_ptr or __pointers section\n")); 5283 5772 if(!resolveImports(oc,image,symLC,§ions[i],indirectSyms,nlist)) 5284 5773 return 0; 5285 5774 } 5286 else if (!strcmp(sections[i].sectname,"__jump_table"))5775 else if (strcmp(sections[i].sectname,"__jump_table") == 0) 5287 5776 { 5777 IF_DEBUG(linker, debugBelch("ocResolve_MachO: resolving jump table\n")); 5288 5778 if(!resolveImports(oc,image,symLC,§ions[i],indirectSyms,nlist)) 5289 5779 return 0; 5290 5780 } 5291 5781 else 5292 5782 { 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)); 5294 5784 } 5295 5785 } 5786 IF_DEBUG(linker, debugBelch("ocResolve_MachO: done resolving dynamic symbols\n")); 5296 5787 } 5297 5788 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)); 5301 5808 5302 5809 if (!relocateSection(oc,image,symLC,nlist,segLC->nsects,sections,§ions[i])) 5303 5810 return 0; 5304 5811 } 5305 5812 5813 IF_DEBUG(linker, debugBelch("ocResolve_MachO: finished relocating\n")); 5814 5306 5815 #if defined (powerpc_HOST_ARCH) 5307 5816 ocFlushInstructionCache( oc ); 5308 5817 #endif 5309 5818 5819 IF_DEBUG(linker, debugBelch("ocResolve_MachO: done\n")); 5310 5820 return 1; 5311 5821 } 5312 5822
