Ticket #5062: 5062-2.patch
| File 5062-2.patch, 52.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: … … 4773 5224 // and use #ifdefs for the other types. 4774 5225 4775 5226 // Step 1: Figure out what the relocated value should be 4776 if(scat->r_type == GENERIC_RELOC_VANILLA) 4777 { 4778 word = *wordPtr + (unsigned long) relocateAddress( 4779 oc, 5227 if (scat->r_type == GENERIC_RELOC_VANILLA) { 5228 word = *wordPtr 5229 + (unsigned long) relocateAddress(oc, 4780 5230 nSections, 4781 5231 sections, 4782 5232 scat->r_value) … … 4796 5246 struct scattered_relocation_info *pair = 4797 5247 (struct scattered_relocation_info*) &relocs[i+1]; 4798 5248 4799 if (!pair->r_scattered || pair->r_type != GENERIC_RELOC_PAIR)5249 if (!pair->r_scattered || pair->r_type != GENERIC_RELOC_PAIR) { 4800 5250 barf("Invalid Mach-O file: " 4801 5251 "RELOC_*_SECTDIFF not followed by RELOC_PAIR"); 5252 } 4802 5253 4803 5254 word = (unsigned long) 4804 5255 (relocateAddress(oc, nSections, sections, scat->r_value) … … 4812 5263 || scat->r_type == PPC_RELOC_LO14) 4813 5264 { // these are generated by label+offset things 4814 5265 struct relocation_info *pair = &relocs[i+1]; 4815 if((pair->r_address & R_SCATTERED) || pair->r_type != PPC_RELOC_PAIR) 5266 5267 if ((pair->r_address & R_SCATTERED) || pair->r_type != PPC_RELOC_PAIR) { 4816 5268 barf("Invalid Mach-O file: " 4817 5269 "PPC_RELOC_* not followed by PPC_RELOC_PAIR"); 5270 } 4818 5271 4819 5272 if(scat->r_type == PPC_RELOC_LO16) 4820 5273 { … … 4845 5298 i++; 4846 5299 } 4847 5300 #endif 4848 else 4849 { 5301 else { 4850 5302 barf ("Don't know how to handle this Mach-O " 4851 5303 "scattered relocation entry: " 4852 5304 "object file %s; entry type %ld; " … … 4869 5321 *wordPtr = word; 4870 5322 } 4871 5323 #ifdef powerpc_HOST_ARCH 4872 else if(scat->r_type == PPC_RELOC_LO16_SECTDIFF || scat->r_type == PPC_RELOC_LO16) 5324 else if (scat->r_type == PPC_RELOC_LO16_SECTDIFF 5325 || scat->r_type == PPC_RELOC_LO16) 4873 5326 { 4874 5327 ((unsigned short*) wordPtr)[1] = word & 0xFFFF; 4875 5328 } 4876 else if(scat->r_type == PPC_RELOC_HI16_SECTDIFF || scat->r_type == PPC_RELOC_HI16) 5329 else if (scat->r_type == PPC_RELOC_HI16_SECTDIFF 5330 || scat->r_type == PPC_RELOC_HI16) 4877 5331 { 4878 5332 ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF; 4879 5333 } 4880 else if(scat->r_type == PPC_RELOC_HA16_SECTDIFF || scat->r_type == PPC_RELOC_HA16) 5334 else if (scat->r_type == PPC_RELOC_HA16_SECTDIFF 5335 || scat->r_type == PPC_RELOC_HA16) 4881 5336 { 4882 5337 ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF) 4883 5338 + ((word & (1<<15)) ? 1 : 0); … … 4912 5367 else /* !(relocs[i].r_address & R_SCATTERED) */ 4913 5368 { 4914 5369 struct relocation_info *reloc = &relocs[i]; 4915 if(reloc->r_pcrel && !reloc->r_extern) 5370 if (reloc->r_pcrel && !reloc->r_extern) { 5371 IF_DEBUG(linker, debugBelch("relocateSection: pc relative but not external, skipping\n")); 4916 5372 continue; 5373 } 4917 5374 4918 if(reloc->r_length == 2) 4919 { 5375 if (reloc->r_length == 2) { 4920 5376 unsigned long word = 0; 4921 5377 #ifdef powerpc_HOST_ARCH 4922 5378 unsigned long jumpIsland = 0; … … 4928 5384 unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address); 4929 5385 checkProddableBlock(oc,wordPtr); 4930 5386 4931 if(reloc->r_type == GENERIC_RELOC_VANILLA) 4932 { 5387 if (reloc->r_type == GENERIC_RELOC_VANILLA) { 4933 5388 word = *wordPtr; 4934 5389 } 4935 5390 #ifdef powerpc_HOST_ARCH 4936 else if(reloc->r_type == PPC_RELOC_LO16) 4937 { 5391 else if (reloc->r_type == PPC_RELOC_LO16) { 4938 5392 word = ((unsigned short*) wordPtr)[1]; 4939 5393 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16; 4940 5394 } 4941 else if(reloc->r_type == PPC_RELOC_HI16) 4942 { 5395 else if (reloc->r_type == PPC_RELOC_HI16) { 4943 5396 word = ((unsigned short*) wordPtr)[1] << 16; 4944 5397 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF); 4945 5398 } 4946 else if(reloc->r_type == PPC_RELOC_HA16) 4947 { 5399 else if (reloc->r_type == PPC_RELOC_HA16) { 4948 5400 word = ((unsigned short*) wordPtr)[1] << 16; 4949 5401 word += ((short)relocs[i+1].r_address & (short)0xFFFF); 4950 5402 } 4951 else if(reloc->r_type == PPC_RELOC_BR24) 4952 { 5403 else if (reloc->r_type == PPC_RELOC_BR24) { 4953 5404 word = *wordPtr; 4954 5405 word = (word & 0x03FFFFFC) | ((word & 0x02000000) ? 0xFC000000 : 0); 4955 5406 } 4956 5407 #endif 4957 else 4958 { 5408 else { 4959 5409 barf("Can't handle this Mach-O relocation entry " 4960 5410 "(not scattered): " 4961 5411 "object file %s; entry type %ld; address %#lx\n", … … 4965 5415 return 0; 4966 5416 } 4967 5417 4968 if(!reloc->r_extern) 4969 { 4970 long delta = 4971 sections[reloc->r_symbolnum-1].offset 5418 if (!reloc->r_extern) { 5419 long delta = sections[reloc->r_symbolnum-1].offset 4972 5420 - sections[reloc->r_symbolnum-1].addr 4973 5421 + ((long) image); 4974 5422 4975 5423 word += delta; 4976 5424 } 4977 else 4978 { 5425 else { 4979 5426 struct nlist *symbol = &nlist[reloc->r_symbolnum]; 4980 5427 char *nm = image + symLC->stroff + symbol->n_un.n_strx; 4981 5428 void *symbolAddress = lookupSymbol(nm); 4982 if(!symbolAddress) 4983 {5429 5430 if (!symbolAddress) { 4984 5431 errorBelch("\nunknown symbol `%s'", nm); 4985 5432 return 0; 4986 5433 } 4987 5434 4988 if(reloc->r_pcrel) 4989 { 5435 if (reloc->r_pcrel) { 4990 5436 #ifdef powerpc_HOST_ARCH 4991 5437 // In the .o file, this should be a relative jump to NULL 4992 5438 // and we'll change it to a relative jump to the symbol … … 4996 5442 reloc->r_symbolnum, 4997 5443 (unsigned long) symbolAddress) 4998 5444 -> jumpIsland; 4999 if(jumpIsland != 0) 5000 { 5445 if (jumpIsland != 0) { 5001 5446 offsetToJumpIsland = word + jumpIsland 5002 5447 - (((long)image) + sect->offset - sect->addr); 5003 5448 } … … 5005 5450 word += (unsigned long) symbolAddress 5006 5451 - (((long)image) + sect->offset - sect->addr); 5007 5452 } 5008 else 5009 { 5453 else { 5010 5454 word += (unsigned long) symbolAddress; 5011 5455 } 5012 5456 } 5013 5457 5014 if(reloc->r_type == GENERIC_RELOC_VANILLA) 5015 { 5458 if (reloc->r_type == GENERIC_RELOC_VANILLA) { 5016 5459 *wordPtr = word; 5017 5460 continue; 5018 5461 } … … 5020 5463 else if(reloc->r_type == PPC_RELOC_LO16) 5021 5464 { 5022 5465 ((unsigned short*) wordPtr)[1] = word & 0xFFFF; 5023 i++; continue; 5466 i++; 5467 continue; 5024 5468 } 5025 5469 else if(reloc->r_type == PPC_RELOC_HI16) 5026 5470 { 5027 5471 ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF; 5028 i++; continue; 5472 i++; 5473 continue; 5029 5474 } 5030 5475 else if(reloc->r_type == PPC_RELOC_HA16) 5031 5476 { 5032 5477 ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF) 5033 5478 + ((word & (1<<15)) ? 1 : 0); 5034 i++; continue; 5479 i++; 5480 continue; 5035 5481 } 5036 5482 else if(reloc->r_type == PPC_RELOC_BR24) 5037 5483 { 5038 if ((word & 0x03) != 0)5484 if ((word & 0x03) != 0) { 5039 5485 barf("%s: unconditional relative branch with a displacement " 5040 5486 "which isn't a multiple of 4 bytes: %#lx", 5041 5487 OC_INFORMATIVE_FILENAME(oc), 5042 5488 word); 5489 } 5043 5490 5044 5491 if((word & 0xFE000000) != 0xFE000000 && 5045 (word & 0xFE000000) != 0x00000000) 5046 { 5492 (word & 0xFE000000) != 0x00000000) { 5047 5493 // The branch offset is too large. 5048 5494 // Therefore, we try to use a jump island. 5049 if(jumpIsland == 0) 5050 { 5495 if (jumpIsland == 0) { 5051 5496 barf("%s: unconditional relative branch out of range: " 5052 5497 "no jump island available: %#lx", 5053 5498 OC_INFORMATIVE_FILENAME(oc), … … 5055 5500 } 5056 5501 5057 5502 word = offsetToJumpIsland; 5503 5058 5504 if((word & 0xFE000000) != 0xFE000000 && 5059 (word & 0xFE000000) != 0x00000000)5505 (word & 0xFE000000) != 0x00000000) { 5060 5506 barf("%s: unconditional relative branch out of range: " 5061 5507 "jump island out of range: %#lx", 5062 5508 OC_INFORMATIVE_FILENAME(oc), 5063 5509 word); 5064 5510 } 5511 } 5065 5512 *wordPtr = (*wordPtr & 0xFC000003) | (word & 0x03FFFFFC); 5066 5513 continue; 5067 5514 } … … 5082 5529 } 5083 5530 #endif 5084 5531 } 5532 5085 5533 IF_DEBUG(linker, debugBelch("relocateSection: done\n")); 5086 5534 return 1; 5087 5535 } 5088 5536 5089 static int ocGetNames_MachO(ObjectCode* oc) 5537 static int 5538 ocGetNames_MachO(ObjectCode* oc) 5090 5539 { 5091 5540 char *image = (char*) oc->image; 5092 5541 struct mach_header *header = (struct mach_header*) image; … … 5104 5553 5105 5554 for(i=0;i<header->ncmds;i++) 5106 5555 { 5107 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64)5556 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) { 5108 5557 segLC = (struct segment_command*) lc; 5109 else if(lc->cmd == LC_SYMTAB) 5558 } 5559 else if (lc->cmd == LC_SYMTAB) { 5110 5560 symLC = (struct symtab_command*) lc; 5561 } 5562 5111 5563 lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize ); 5112 5564 } 5113 5565 … … 5115 5567 nlist = symLC ? (struct nlist*) (image + symLC->symoff) 5116 5568 : NULL; 5117 5569 5118 if (!segLC)5570 if (!segLC) { 5119 5571 barf("ocGetNames_MachO: no segment load command"); 5572 } 5120 5573 5574 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: will load %d sections\n", segLC->nsects)); 5121 5575 for(i=0;i<segLC->nsects;i++) 5122 5576 { 5123 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: segment %d\n", i)); 5124 if (sections[i].size == 0) 5577 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: section %d\n", i)); 5578 5579 if (sections[i].size == 0) { 5580 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: found a zero length section, skipping\n")); 5125 5581 continue; 5582 } 5126 5583 5127 5584 if((sections[i].flags & SECTION_TYPE) == S_ZEROFILL) 5128 5585 { … … 5131 5588 sections[i].offset = zeroFillArea - image; 5132 5589 } 5133 5590 5134 if(!strcmp(sections[i].sectname,"__text")) 5591 if (!strcmp(sections[i].sectname,"__text")) { 5592 5593 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __text section\n")); 5135 5594 addSection(oc, SECTIONKIND_CODE_OR_RODATA, 5136 5595 (void*) (image + sections[i].offset), 5137 5596 (void*) (image + sections[i].offset + sections[i].size)); 5138 else if(!strcmp(sections[i].sectname,"__const")) 5597 } 5598 else if (!strcmp(sections[i].sectname,"__const")) { 5599 5600 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __const section\n")); 5139 5601 addSection(oc, SECTIONKIND_RWDATA, 5140 5602 (void*) (image + sections[i].offset), 5141 5603 (void*) (image + sections[i].offset + sections[i].size)); 5142 else if(!strcmp(sections[i].sectname,"__data")) 5604 } 5605 else if (!strcmp(sections[i].sectname,"__data")) { 5606 5607 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __data section\n")); 5143 5608 addSection(oc, SECTIONKIND_RWDATA, 5144 5609 (void*) (image + sections[i].offset), 5145 5610 (void*) (image + sections[i].offset + sections[i].size)); 5611 } 5146 5612 else if(!strcmp(sections[i].sectname,"__bss") 5147 || !strcmp(sections[i].sectname,"__common")) 5613 || !strcmp(sections[i].sectname,"__common")) { 5614 5615 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: adding __bss section\n")); 5148 5616 addSection(oc, SECTIONKIND_RWDATA, 5149 5617 (void*) (image + sections[i].offset), 5150 5618 (void*) (image + sections[i].offset + sections[i].size)); 5151 5152 addProddableBlock(oc, (void*) (image + sections[i].offset), 5619 } 5620 addProddableBlock(oc, 5621 (void *) (image + sections[i].offset), 5153 5622 sections[i].size); 5154 5623 } 5155 5624 5156 5625 // count external symbols defined here 5157 5626 oc->n_symbols = 0; 5158 if(symLC) 5159 { 5160 for(i=0;i<symLC->nsyms;i++) 5161 { 5162 if(nlist[i].n_type & N_STAB) 5627 if (symLC) { 5628 for (i = 0; i < symLC->nsyms; i++) { 5629 if (nlist[i].n_type & N_STAB) { 5163 5630 ; 5631 } 5164 5632 else if(nlist[i].n_type & N_EXT) 5165 5633 { 5166 5634 if((nlist[i].n_type & N_TYPE) == N_UNDF … … 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 { … … 5204 5675 oc->symbols[curSymbol++] = nm; 5205 5676 } 5206 5677 } 5678 else 5679 { 5680 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not external, skipping\n")); 5681 } 5682 } 5683 else 5684 { 5685 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not defined in this section, skipping\n")); 5207 5686 } 5208 5687 } 5209 5688 } 5210 5689 5211 5690 commonStorage = stgCallocBytes(1,commonSize,"ocGetNames_MachO(common symbols)"); 5212 5691 commonCounter = (unsigned long)commonStorage; 5213 if(symLC) 5214 { 5215 for(i=0;i<symLC->nsyms;i++) 5216 { 5692 5693 if (symLC) { 5694 for (i = 0; i < symLC->nsyms; i++) { 5217 5695 if((nlist[i].n_type & N_TYPE) == N_UNDF 5218 && (nlist[i].n_type & N_EXT) && (nlist[i].n_value != 0)) 5219 { 5696 && (nlist[i].n_type & N_EXT) 5697 && (nlist[i].n_value != 0)) { 5698 5220 5699 char *nm = image + symLC->stroff + nlist[i].n_un.n_strx; 5221 5700 unsigned long sz = nlist[i].n_value; 5222 5701 … … 5231 5710 } 5232 5711 } 5233 5712 } 5713 5714 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: done\n")); 5234 5715 return 1; 5235 5716 } 5236 5717 5237 static int ocResolve_MachO(ObjectCode* oc) 5718 static int 5719 ocResolve_MachO(ObjectCode* oc) 5238 5720 { 5239 5721 char *image = (char*) oc->image; 5240 5722 struct mach_header *header = (struct mach_header*) image; … … 5249 5731 IF_DEBUG(linker, debugBelch("ocResolve_MachO: start\n")); 5250 5732 for (i = 0; i < header->ncmds; i++) 5251 5733 { 5252 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64)5734 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) { 5253 5735 segLC = (struct segment_command*) lc; 5254 else if(lc->cmd == LC_SYMTAB) 5736 IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a 32 or 64 bit segment load command\n")); 5737 } 5738 else if (lc->cmd == LC_SYMTAB) { 5255 5739 symLC = (struct symtab_command*) lc; 5256 else if(lc->cmd == LC_DYSYMTAB) 5740 IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a symbol table load command\n")); 5741 } 5742 else if (lc->cmd == LC_DYSYMTAB) { 5257 5743 dsymLC = (struct dysymtab_command*) lc; 5744 IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a dynamic symbol table load command\n")); 5745 } 5746 5258 5747 lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize ); 5259 5748 } 5260 5749 … … 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 … … 5322 5832 5323 5833 extern void* symbolsWithoutUnderscore[]; 5324 5834 5325 static void machoInitSymbolsWithoutUnderscore() 5835 static void 5836 machoInitSymbolsWithoutUnderscore(void) 5326 5837 { 5327 5838 void **p = symbolsWithoutUnderscore; 5328 5839 __asm__ volatile(".globl _symbolsWithoutUnderscore\n.data\n_symbolsWithoutUnderscore:"); … … 5350 5861 * Figure out by how much to shift the entire Mach-O file in memory 5351 5862 * when loading so that its single segment ends up 16-byte-aligned 5352 5863 */ 5353 static int machoGetMisalignment( FILE * f ) 5864 static int 5865 machoGetMisalignment( FILE * f ) 5354 5866 { 5355 5867 struct mach_header header; 5356 5868 int misalignment;
