Add ocInit_MachO
[ghc.git] / rts / linker / MachO.c
1 #include "Rts.h"
2
3 #if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
4
5 #include "RtsUtils.h"
6 #include "GetEnv.h"
7 #include "LinkerInternals.h"
8 #include "linker/MachO.h"
9 #include "linker/CacheFlush.h"
10 #include "linker/SymbolExtras.h"
11
12 #include <string.h>
13 #include <regex.h>
14 #include <mach/machine.h>
15 #include <mach-o/fat.h>
16 #include <mach-o/loader.h>
17 #include <mach-o/nlist.h>
18 #include <mach-o/reloc.h>
19
20 #if defined(HAVE_SYS_MMAN_H) && RTS_LINKER_USE_MMAP
21 # include <sys/mman.h>
22 #endif
23
24 #if defined(powerpc_HOST_ARCH)
25 # include <mach-o/ppc/reloc.h>
26 #endif
27
28 #if defined(x86_64_HOST_ARCH)
29 # include <mach-o/x86_64/reloc.h>
30 #endif
31
32 /*
33 Support for MachO linking on Darwin/MacOS X
34 by Wolfgang Thaller (wolfgang.thaller@gmx.net)
35
36 I hereby formally apologize for the hackish nature of this code.
37 Things that need to be done:
38 *) implement ocVerifyImage_MachO
39 *) add still more sanity checks.
40 */
41
42 #if x86_64_HOST_ARCH || powerpc64_HOST_ARCH
43 #define mach_header mach_header_64
44 #define segment_command segment_command_64
45 #define section section_64
46 #define nlist nlist_64
47 #endif
48
49 /*
50 * Initialize some common data in the object code so we don't have to
51 * continuously look up the addresses.
52 */
53 void
54 ocInit_MachO(ObjectCode * oc)
55 {
56 oc->info = (ObjectCodeFormatInfo*)stgCallocBytes(
57 1, sizeof(ObjectCodeFormatInfo),
58 "ocInit_MachO(ObjectCodeFormatInfo)");
59 oc->info->header = (MachOHeader *) oc->image;
60 oc->info->symCmd = NULL;
61 oc->info->segCmd = NULL;
62 oc->info->dsymCmd = NULL;
63
64 MachOLoadCommand *lc = (MachOLoadCommand*)(oc->image + sizeof(MachOHeader));
65 for(size_t i = 0; i < oc->info->header->ncmds; i++) {
66 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) {
67 oc->info->segCmd = (MachOSegmentCommand*) lc;
68 }
69 else if (lc->cmd == LC_SYMTAB) {
70 oc->info->symCmd = (MachOSymtabCommand*) lc;
71 }
72 else if (lc->cmd == LC_DYSYMTAB) {
73 oc->info->dsymCmd = (MachODsymtabCommand*) lc;
74 }
75 lc = (MachOLoadCommand *) ( ((char*)lc) + lc->cmdsize );
76 }
77 if (NULL == oc->info->segCmd) {
78 barf("ocGetNames_MachO: no segment load command");
79 }
80
81 oc->info->macho_sections = (MachOSection*) (oc->info->segCmd+1);
82 oc->n_sections = oc->info->segCmd->nsects;
83
84 oc->info->nlist = oc->info->symCmd == NULL
85 ? NULL
86 : (MachONList *)(oc->image + oc->info->symCmd->symoff);
87 oc->info->names = oc->image + oc->info->symCmd->stroff;
88
89 /* If we have symbols, allocate and fill the macho_symbols
90 * This will make relocation easier.
91 */
92 oc->info->n_macho_symbols = 0;
93 oc->info->macho_symbols = NULL;
94
95 if(NULL != oc->info->nlist) {
96 oc->info->n_macho_symbols = oc->info->symCmd->nsyms;
97 oc->info->macho_symbols = (MachOSymbol*)stgCallocBytes(
98 oc->info->symCmd->nsyms,
99 sizeof(MachOSymbol),
100 "ocInit_MachO(MachOSymbol)");
101 for(uint32_t i = 0; i < oc->info->symCmd->nsyms; i++) {
102 oc->info->macho_symbols[i].name = oc->info->names
103 + oc->info->nlist[i].n_un.n_strx;
104 oc->info->macho_symbols[i].nlist = &oc->info->nlist[i];
105 /* we don't have an address for this symbol yet; this will be
106 * populated during ocGetNames_MachO. hence addr = NULL
107 */
108 oc->info->macho_symbols[i].addr = NULL;
109 }
110 }
111 }
112
113 void
114 ocDeinit_MachO(ObjectCode * oc) {
115 if(oc->info->n_macho_symbols > 0) {
116 stgFree(oc->info->macho_symbols);
117 }
118 stgFree(oc->info);
119 }
120 static int
121 resolveImports(
122 ObjectCode* oc,
123 char *image,
124 struct symtab_command *symLC,
125 struct section *sect, // ptr to lazy or non-lazy symbol pointer section
126 unsigned long *indirectSyms,
127 struct nlist *nlist);
128
129 #if NEED_SYMBOL_EXTRAS
130 #if defined(powerpc_HOST_ARCH)
131 int
132 ocAllocateSymbolExtras_MachO(ObjectCode* oc)
133 {
134 struct mach_header *header = (struct mach_header *) oc->image;
135 struct load_command *lc = (struct load_command *) (header + 1);
136 unsigned i;
137
138 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
139
140 for (i = 0; i < header->ncmds; i++) {
141 if (lc->cmd == LC_SYMTAB) {
142
143 // Find out the first and last undefined external
144 // symbol, so we don't have to allocate too many
145 // jump islands/GOT entries.
146
147 struct symtab_command *symLC = (struct symtab_command *) lc;
148 unsigned min = symLC->nsyms, max = 0;
149 struct nlist *nlist =
150 symLC ? (struct nlist*) ((char*) oc->image + symLC->symoff)
151 : NULL;
152
153 for (i = 0; i < symLC->nsyms; i++) {
154
155 if (nlist[i].n_type & N_STAB) {
156 ;
157 } else if (nlist[i].n_type & N_EXT) {
158
159 if((nlist[i].n_type & N_TYPE) == N_UNDF
160 && (nlist[i].n_value == 0)) {
161
162 if (i < min) {
163 min = i;
164 }
165
166 if (i > max) {
167 max = i;
168 }
169 }
170 }
171 }
172
173 if (max >= min) {
174 return ocAllocateSymbolExtras(oc, max - min + 1, min);
175 }
176
177 break;
178 }
179
180 lc = (struct load_command *) ( ((char *)lc) + lc->cmdsize );
181 }
182
183 return ocAllocateSymbolExtras(oc,0,0);
184 }
185
186 #elif defined(x86_64_HOST_ARCH)
187
188 int
189 ocAllocateSymbolExtras_MachO(ObjectCode* oc)
190 {
191 struct mach_header *header = (struct mach_header *) oc->image;
192 struct load_command *lc = (struct load_command *) (header + 1);
193 unsigned i;
194
195 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
196
197 for (i = 0; i < header->ncmds; i++) {
198 if (lc->cmd == LC_SYMTAB) {
199
200 // Just allocate one entry for every symbol
201 struct symtab_command *symLC = (struct symtab_command *) lc;
202
203 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocate %d symbols\n", symLC->nsyms));
204 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
205 return ocAllocateSymbolExtras(oc, symLC->nsyms, 0);
206 }
207
208 lc = (struct load_command *) ( ((char *)lc) + lc->cmdsize );
209 }
210
211 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocated no symbols\n"));
212 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
213 return ocAllocateSymbolExtras(oc,0,0);
214 }
215
216 #else
217 #error Unknown MachO architecture
218 #endif /* HOST_ARCH */
219 #endif /* NEED_SYMBOL_EXTRAS */
220
221 int
222 ocVerifyImage_MachO(ObjectCode * oc)
223 {
224 char *image = (char*) oc->image;
225 struct mach_header *header = (struct mach_header*) image;
226
227 IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: start\n"));
228
229 #if x86_64_HOST_ARCH || powerpc64_HOST_ARCH || aarch64_HOST_ARCH
230 if(header->magic != MH_MAGIC_64) {
231 errorBelch("Could not load image %s: bad magic!\n"
232 " Expected %08x (64bit), got %08x%s\n",
233 oc->fileName, MH_MAGIC_64, header->magic,
234 header->magic == MH_MAGIC ? " (32bit)." : ".");
235 return 0;
236 }
237 #else
238 if(header->magic != MH_MAGIC) {
239 errorBelch("Could not load image %s: bad magic!\n"
240 " Expected %08x (32bit), got %08x%s\n",
241 oc->fileName, MH_MAGIC, header->magic,
242 header->magic == MH_MAGIC_64 ? " (64bit)." : ".");
243 return 0;
244 }
245 #endif
246
247 // FIXME: do some more verifying here
248 IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: done\n"));
249 return 1;
250 }
251
252 static int
253 resolveImports(
254 ObjectCode* oc,
255 char *image,
256 struct symtab_command *symLC,
257 struct section *sect, // ptr to lazy or non-lazy symbol pointer section
258 unsigned long *indirectSyms,
259 struct nlist *nlist)
260 {
261 unsigned i;
262 size_t itemSize = 4;
263
264 IF_DEBUG(linker, debugBelch("resolveImports: start\n"));
265
266 #if i386_HOST_ARCH
267 int isJumpTable = 0;
268
269 if (strcmp(sect->sectname,"__jump_table") == 0) {
270 isJumpTable = 1;
271 itemSize = 5;
272 ASSERT(sect->reserved2 == itemSize);
273 }
274
275 #endif
276
277 for(i = 0; i * itemSize < sect->size; i++)
278 {
279 // according to otool, reserved1 contains the first index into the indirect symbol table
280 struct nlist *symbol = &nlist[indirectSyms[sect->reserved1+i]];
281 SymbolName* nm = image + symLC->stroff + symbol->n_un.n_strx;
282 SymbolAddr* addr = NULL;
283
284 IF_DEBUG(linker, debugBelch("resolveImports: resolving %s\n", nm));
285
286 if ((symbol->n_type & N_TYPE) == N_UNDF
287 && (symbol->n_type & N_EXT) && (symbol->n_value != 0)) {
288 addr = (SymbolAddr*) (symbol->n_value);
289 IF_DEBUG(linker, debugBelch("resolveImports: undefined external %s has value %p\n", nm, addr));
290 } else {
291 addr = lookupSymbol_(nm);
292 IF_DEBUG(linker, debugBelch("resolveImports: looking up %s, %p\n", nm, addr));
293 }
294
295 if (addr == NULL)
296 {
297 errorBelch("\nlookupSymbol failed in resolveImports\n"
298 "%s: unknown symbol `%s'", oc->fileName, nm);
299 return 0;
300 }
301 ASSERT(addr);
302
303 #if i386_HOST_ARCH
304 if (isJumpTable) {
305 checkProddableBlock(oc,image + sect->offset + i*itemSize, 5);
306
307 *(image + sect->offset + i * itemSize) = 0xe9; // jmp opcode
308 *(unsigned*)(image + sect->offset + i*itemSize + 1)
309 = (SymbolAddr*)addr - (image + sect->offset + i*itemSize + 5);
310 }
311 else
312 #endif
313 {
314 checkProddableBlock(oc,
315 ((void**)(image + sect->offset)) + i,
316 sizeof(void *));
317 ((void**)(image + sect->offset))[i] = addr;
318 }
319 }
320
321 IF_DEBUG(linker, debugBelch("resolveImports: done\n"));
322 return 1;
323 }
324
325 static unsigned long
326 relocateAddress(
327 ObjectCode* oc,
328 int nSections,
329 struct section* sections,
330 unsigned long address)
331 {
332 int i;
333 IF_DEBUG(linker, debugBelch("relocateAddress: start\n"));
334 for (i = 0; i < nSections; i++)
335 {
336 IF_DEBUG(linker, debugBelch(" relocating address in section %d\n", i));
337 if (sections[i].addr <= address
338 && address < sections[i].addr + sections[i].size)
339 {
340 return (unsigned long)oc->image
341 + sections[i].offset + address - sections[i].addr;
342 }
343 }
344 barf("Invalid Mach-O file:"
345 "Address out of bounds while relocating object file");
346 return 0;
347 }
348
349 static int
350 relocateSection(
351 ObjectCode* oc,
352 char *image,
353 struct symtab_command *symLC, struct nlist *nlist,
354 int nSections, struct section* sections, struct section *sect)
355 {
356 struct relocation_info *relocs;
357 int i, n;
358
359 IF_DEBUG(linker, debugBelch("relocateSection: start\n"));
360
361 if(!strcmp(sect->sectname,"__la_symbol_ptr"))
362 return 1;
363 else if(!strcmp(sect->sectname,"__nl_symbol_ptr"))
364 return 1;
365 else if(!strcmp(sect->sectname,"__la_sym_ptr2"))
366 return 1;
367 else if(!strcmp(sect->sectname,"__la_sym_ptr3"))
368 return 1;
369
370 n = sect->nreloc;
371 IF_DEBUG(linker, debugBelch("relocateSection: number of relocations: %d\n", n));
372
373 relocs = (struct relocation_info*) (image + sect->reloff);
374
375 for(i = 0; i < n; i++)
376 {
377 #ifdef x86_64_HOST_ARCH
378 struct relocation_info *reloc = &relocs[i];
379
380 char *thingPtr = image + sect->offset + reloc->r_address;
381 uint64_t thing;
382 /* We shouldn't need to initialise this, but gcc on OS X 64 bit
383 complains that it may be used uninitialized if we don't */
384 uint64_t value = 0;
385 uint64_t baseValue;
386 int type = reloc->r_type;
387
388 IF_DEBUG(linker, debugBelch("relocateSection: relocation %d\n", i));
389 IF_DEBUG(linker, debugBelch(" : type = %d\n", reloc->r_type));
390 IF_DEBUG(linker, debugBelch(" : address = %d\n", reloc->r_address));
391 IF_DEBUG(linker, debugBelch(" : symbolnum = %u\n", reloc->r_symbolnum));
392 IF_DEBUG(linker, debugBelch(" : pcrel = %d\n", reloc->r_pcrel));
393 IF_DEBUG(linker, debugBelch(" : length = %d\n", reloc->r_length));
394 IF_DEBUG(linker, debugBelch(" : extern = %d\n", reloc->r_extern));
395 IF_DEBUG(linker, debugBelch(" : type = %d\n", reloc->r_type));
396
397 switch(reloc->r_length)
398 {
399 case 0:
400 checkProddableBlock(oc,thingPtr,1);
401 thing = *(uint8_t*)thingPtr;
402 baseValue = (uint64_t)thingPtr + 1;
403 break;
404 case 1:
405 checkProddableBlock(oc,thingPtr,2);
406 thing = *(uint16_t*)thingPtr;
407 baseValue = (uint64_t)thingPtr + 2;
408 break;
409 case 2:
410 checkProddableBlock(oc,thingPtr,4);
411 thing = *(uint32_t*)thingPtr;
412 baseValue = (uint64_t)thingPtr + 4;
413 break;
414 case 3:
415 checkProddableBlock(oc,thingPtr,8);
416 thing = *(uint64_t*)thingPtr;
417 baseValue = (uint64_t)thingPtr + 8;
418 break;
419 default:
420 barf("Unknown size.");
421 }
422
423 IF_DEBUG(linker,
424 debugBelch("relocateSection: length = %d, thing = %" PRId64 ", baseValue = %p\n",
425 reloc->r_length, thing, (char *)baseValue));
426
427 if (type == X86_64_RELOC_GOT
428 || type == X86_64_RELOC_GOT_LOAD)
429 {
430 struct nlist *symbol = &nlist[reloc->r_symbolnum];
431 SymbolName* nm = image + symLC->stroff + symbol->n_un.n_strx;
432 SymbolAddr* addr = NULL;
433
434 IF_DEBUG(linker, debugBelch("relocateSection: making jump island for %s, extern = %d, X86_64_RELOC_GOT\n", nm, reloc->r_extern));
435
436 ASSERT(reloc->r_extern);
437 if (reloc->r_extern == 0) {
438 errorBelch("\nrelocateSection: global offset table relocation for symbol with r_extern == 0\n");
439 }
440
441 if (symbol->n_type & N_EXT) {
442 // The external bit is set, meaning the symbol is exported,
443 // and therefore can be looked up in this object module's
444 // symtab, or it is undefined, meaning dlsym must be used
445 // to resolve it.
446
447 addr = lookupSymbol_(nm);
448 IF_DEBUG(linker, debugBelch("relocateSection: looked up %s, "
449 "external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n", nm));
450 IF_DEBUG(linker, debugBelch(" : addr = %p\n", addr));
451
452 if (addr == NULL) {
453 errorBelch("\nlookupSymbol failed in relocateSection (RELOC_GOT)\n"
454 "%s: unknown symbol `%s'", oc->fileName, nm);
455 return 0;
456 }
457 } else {
458 IF_DEBUG(linker, debugBelch("relocateSection: %s is not an exported symbol\n", nm));
459
460 // The symbol is not exported, or defined in another
461 // module, so it must be in the current object module,
462 // at the location given by the section index and
463 // symbol address (symbol->n_value)
464
465 if ((symbol->n_type & N_TYPE) == N_SECT) {
466 addr = (void *)relocateAddress(oc, nSections, sections, symbol->n_value);
467 IF_DEBUG(linker, debugBelch("relocateSection: calculated relocation %p of "
468 "non-external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n",
469 (void *)symbol->n_value));
470 IF_DEBUG(linker, debugBelch(" : addr = %p\n", addr));
471 } else {
472 errorBelch("\nrelocateSection: %s is not exported,"
473 " and should be defined in a section, but isn't!\n", nm);
474 }
475 }
476
477 value = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, (unsigned long)addr)->addr;
478
479 type = X86_64_RELOC_SIGNED;
480 }
481 else if (reloc->r_extern)
482 {
483 struct nlist *symbol = &nlist[reloc->r_symbolnum];
484 SymbolName* nm = image + symLC->stroff + symbol->n_un.n_strx;
485 SymbolAddr* addr = NULL;
486
487 IF_DEBUG(linker, debugBelch("relocateSection: looking up external symbol %s\n", nm));
488 IF_DEBUG(linker, debugBelch(" : type = %d\n", symbol->n_type));
489 IF_DEBUG(linker, debugBelch(" : sect = %d\n", symbol->n_sect));
490 IF_DEBUG(linker, debugBelch(" : desc = %d\n", symbol->n_desc));
491 IF_DEBUG(linker, debugBelch(" : value = %p\n", (void *)symbol->n_value));
492
493 if ((symbol->n_type & N_TYPE) == N_SECT) {
494 value = relocateAddress(oc, nSections, sections,
495 symbol->n_value);
496 IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n", nm, (void *)value));
497 }
498 else {
499 addr = lookupSymbol_(nm);
500 if (addr == NULL)
501 {
502 errorBelch("\nlookupSymbol failed in relocateSection (relocate external)\n"
503 "%s: unknown symbol `%s'", oc->fileName, nm);
504 return 0;
505 }
506
507 value = (uint64_t) addr;
508 IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s, address %p\n", nm, (void *)value));
509 }
510 }
511 else
512 {
513 // If the relocation is not through the global offset table
514 // or external, then set the value to the baseValue. This
515 // will leave displacements into the __const section
516 // unchanged (as they ought to be).
517
518 value = baseValue;
519 }
520
521 IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", (void *)value));
522
523 if (type == X86_64_RELOC_BRANCH)
524 {
525 if((int32_t)(value - baseValue) != (int64_t)(value - baseValue))
526 {
527 ASSERT(reloc->r_extern);
528 value = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, value)
529 -> jumpIsland;
530 }
531 ASSERT((int32_t)(value - baseValue) == (int64_t)(value - baseValue));
532 type = X86_64_RELOC_SIGNED;
533 }
534
535 switch(type)
536 {
537 case X86_64_RELOC_UNSIGNED:
538 ASSERT(!reloc->r_pcrel);
539 thing += value;
540 break;
541 case X86_64_RELOC_SIGNED:
542 case X86_64_RELOC_SIGNED_1:
543 case X86_64_RELOC_SIGNED_2:
544 case X86_64_RELOC_SIGNED_4:
545 ASSERT(reloc->r_pcrel);
546 thing += value - baseValue;
547 break;
548 case X86_64_RELOC_SUBTRACTOR:
549 ASSERT(!reloc->r_pcrel);
550 thing -= value;
551 break;
552 default:
553 barf("unkown relocation");
554 }
555
556 switch(reloc->r_length)
557 {
558 case 0:
559 *(uint8_t*)thingPtr = thing;
560 break;
561 case 1:
562 *(uint16_t*)thingPtr = thing;
563 break;
564 case 2:
565 *(uint32_t*)thingPtr = thing;
566 break;
567 case 3:
568 *(uint64_t*)thingPtr = thing;
569 break;
570 }
571 #else /* x86_64_HOST_ARCH */
572 if(relocs[i].r_address & R_SCATTERED)
573 {
574 struct scattered_relocation_info *scat =
575 (struct scattered_relocation_info*) &relocs[i];
576
577 if(!scat->r_pcrel)
578 {
579 if(scat->r_length == 2)
580 {
581 unsigned long word = 0;
582 unsigned long* wordPtr = (unsigned long*) (image + sect->offset + scat->r_address);
583
584 /* In this check we assume that sizeof(unsigned long) = 2 * sizeof(unsigned short)
585 on powerpc_HOST_ARCH */
586 checkProddableBlock(oc,wordPtr,sizeof(unsigned long));
587
588 // Note on relocation types:
589 // i386 uses the GENERIC_RELOC_* types,
590 // while ppc uses special PPC_RELOC_* types.
591 // *_RELOC_VANILLA and *_RELOC_PAIR have the same value
592 // in both cases, all others are different.
593 // Therefore, we use GENERIC_RELOC_VANILLA
594 // and GENERIC_RELOC_PAIR instead of the PPC variants,
595 // and use #ifdefs for the other types.
596
597 // Step 1: Figure out what the relocated value should be
598 if (scat->r_type == GENERIC_RELOC_VANILLA) {
599 word = *wordPtr
600 + (unsigned long) relocateAddress(oc,
601 nSections,
602 sections,
603 scat->r_value)
604 - scat->r_value;
605 }
606 #ifdef powerpc_HOST_ARCH
607 else if(scat->r_type == PPC_RELOC_SECTDIFF
608 || scat->r_type == PPC_RELOC_LO16_SECTDIFF
609 || scat->r_type == PPC_RELOC_HI16_SECTDIFF
610 || scat->r_type == PPC_RELOC_HA16_SECTDIFF
611 || scat->r_type == PPC_RELOC_LOCAL_SECTDIFF)
612 #else /* powerpc_HOST_ARCH */
613 else if(scat->r_type == GENERIC_RELOC_SECTDIFF
614 || scat->r_type == GENERIC_RELOC_LOCAL_SECTDIFF)
615 #endif /* powerpc_HOST_ARCH */
616 {
617 struct scattered_relocation_info *pair =
618 (struct scattered_relocation_info*) &relocs[i+1];
619
620 if (!pair->r_scattered || pair->r_type != GENERIC_RELOC_PAIR) {
621 barf("Invalid Mach-O file: "
622 "RELOC_*_SECTDIFF not followed by RELOC_PAIR");
623 }
624
625 word = (unsigned long)
626 (relocateAddress(oc, nSections, sections, scat->r_value)
627 - relocateAddress(oc, nSections, sections, pair->r_value));
628 i++;
629 }
630 #ifdef powerpc_HOST_ARCH
631 else if(scat->r_type == PPC_RELOC_HI16
632 || scat->r_type == PPC_RELOC_LO16
633 || scat->r_type == PPC_RELOC_HA16
634 || scat->r_type == PPC_RELOC_LO14)
635 { // these are generated by label+offset things
636 struct relocation_info *pair = &relocs[i+1];
637
638 if ((pair->r_address & R_SCATTERED) || pair->r_type != PPC_RELOC_PAIR) {
639 barf("Invalid Mach-O file: "
640 "PPC_RELOC_* not followed by PPC_RELOC_PAIR");
641 }
642
643 if(scat->r_type == PPC_RELOC_LO16)
644 {
645 word = ((unsigned short*) wordPtr)[1];
646 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
647 }
648 else if(scat->r_type == PPC_RELOC_LO14)
649 {
650 barf("Unsupported Relocation: PPC_RELOC_LO14");
651 word = ((unsigned short*) wordPtr)[1] & 0xFFFC;
652 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
653 }
654 else if(scat->r_type == PPC_RELOC_HI16)
655 {
656 word = ((unsigned short*) wordPtr)[1] << 16;
657 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF);
658 }
659 else if(scat->r_type == PPC_RELOC_HA16)
660 {
661 word = ((unsigned short*) wordPtr)[1] << 16;
662 word += ((short)relocs[i+1].r_address & (short)0xFFFF);
663 }
664
665
666 word += (unsigned long) relocateAddress(oc, nSections, sections, scat->r_value)
667 - scat->r_value;
668
669 i++;
670 }
671 #endif /* powerpc_HOST_ARCH */
672 else {
673 barf ("Don't know how to handle this Mach-O "
674 "scattered relocation entry: "
675 "object file %s; entry type %ld; "
676 "address %#lx\n",
677 OC_INFORMATIVE_FILENAME(oc),
678 scat->r_type,
679 scat->r_address);
680 return 0;
681 }
682
683 #ifdef powerpc_HOST_ARCH
684 if(scat->r_type == GENERIC_RELOC_VANILLA
685 || scat->r_type == PPC_RELOC_SECTDIFF)
686 #else /* powerpc_HOST_ARCH */
687 if(scat->r_type == GENERIC_RELOC_VANILLA
688 || scat->r_type == GENERIC_RELOC_SECTDIFF
689 || scat->r_type == GENERIC_RELOC_LOCAL_SECTDIFF)
690 #endif /* powerpc_HOST_ARCH */
691 {
692 *wordPtr = word;
693 }
694 #ifdef powerpc_HOST_ARCH
695 else if (scat->r_type == PPC_RELOC_LO16_SECTDIFF
696 || scat->r_type == PPC_RELOC_LO16)
697 {
698 ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
699 }
700 else if (scat->r_type == PPC_RELOC_HI16_SECTDIFF
701 || scat->r_type == PPC_RELOC_HI16)
702 {
703 ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF;
704 }
705 else if (scat->r_type == PPC_RELOC_HA16_SECTDIFF
706 || scat->r_type == PPC_RELOC_HA16)
707 {
708 ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
709 + ((word & (1<<15)) ? 1 : 0);
710 }
711 #endif /* powerpc_HOST_ARCH */
712 }
713 else
714 {
715 barf("Can't handle Mach-O scattered relocation entry "
716 "with this r_length tag: "
717 "object file %s; entry type %ld; "
718 "r_length tag %ld; address %#lx\n",
719 OC_INFORMATIVE_FILENAME(oc),
720 scat->r_type,
721 scat->r_length,
722 scat->r_address);
723 return 0;
724 }
725 }
726 else /* scat->r_pcrel */
727 {
728 barf("Don't know how to handle *PC-relative* Mach-O "
729 "scattered relocation entry: "
730 "object file %s; entry type %ld; address %#lx\n",
731 OC_INFORMATIVE_FILENAME(oc),
732 scat->r_type,
733 scat->r_address);
734 return 0;
735 }
736
737 }
738 else /* !(relocs[i].r_address & R_SCATTERED) */
739 {
740 struct relocation_info *reloc = &relocs[i];
741 if (reloc->r_pcrel && !reloc->r_extern) {
742 IF_DEBUG(linker, debugBelch("relocateSection: pc relative but not external, skipping\n"));
743 continue;
744 }
745
746 if (reloc->r_length == 2) {
747 unsigned long word = 0;
748 #ifdef powerpc_HOST_ARCH
749 unsigned long jumpIsland = 0;
750 long offsetToJumpIsland = 0xBADBAD42; // initialise to bad value
751 // to avoid warning and to catch
752 // bugs.
753 #endif /* powerpc_HOST_ARCH */
754
755 unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address);
756
757 /* In this check we assume that sizeof(unsigned long) = 2 * sizeof(unsigned short)
758 on powerpc_HOST_ARCH */
759 checkProddableBlock(oc,wordPtr, sizeof(unsigned long));
760
761 if (reloc->r_type == GENERIC_RELOC_VANILLA) {
762 word = *wordPtr;
763 }
764 #ifdef powerpc_HOST_ARCH
765 else if (reloc->r_type == PPC_RELOC_LO16) {
766 word = ((unsigned short*) wordPtr)[1];
767 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
768 }
769 else if (reloc->r_type == PPC_RELOC_HI16) {
770 word = ((unsigned short*) wordPtr)[1] << 16;
771 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF);
772 }
773 else if (reloc->r_type == PPC_RELOC_HA16) {
774 word = ((unsigned short*) wordPtr)[1] << 16;
775 word += ((short)relocs[i+1].r_address & (short)0xFFFF);
776 }
777 else if (reloc->r_type == PPC_RELOC_BR24) {
778 word = *wordPtr;
779 word = (word & 0x03FFFFFC) | ((word & 0x02000000) ? 0xFC000000 : 0);
780 }
781 #endif /* powerpc_HOST_ARCH */
782 else {
783 barf("Can't handle this Mach-O relocation entry "
784 "(not scattered): "
785 "object file %s; entry type %ld; address %#lx\n",
786 OC_INFORMATIVE_FILENAME(oc),
787 reloc->r_type,
788 reloc->r_address);
789 return 0;
790 }
791
792 if (!reloc->r_extern) {
793 long delta = sections[reloc->r_symbolnum-1].offset
794 - sections[reloc->r_symbolnum-1].addr
795 + ((long) image);
796
797 word += delta;
798 }
799 else {
800 struct nlist *symbol = &nlist[reloc->r_symbolnum];
801 char *nm = image + symLC->stroff + symbol->n_un.n_strx;
802 void *symbolAddress = lookupSymbol_(nm);
803
804 if (!symbolAddress) {
805 errorBelch("\nunknown symbol `%s'", nm);
806 return 0;
807 }
808
809 if (reloc->r_pcrel) {
810 #ifdef powerpc_HOST_ARCH
811 // In the .o file, this should be a relative jump to NULL
812 // and we'll change it to a relative jump to the symbol
813 ASSERT(word + reloc->r_address == 0);
814 jumpIsland = (unsigned long)
815 &makeSymbolExtra(oc,
816 reloc->r_symbolnum,
817 (unsigned long) symbolAddress)
818 -> jumpIsland;
819 if (jumpIsland != 0) {
820 offsetToJumpIsland = word + jumpIsland
821 - (((long)image) + sect->offset - sect->addr);
822 }
823 #endif /* powerpc_HOST_ARCH */
824 word += (unsigned long) symbolAddress
825 - (((long)image) + sect->offset - sect->addr);
826 }
827 else {
828 word += (unsigned long) symbolAddress;
829 }
830 }
831
832 if (reloc->r_type == GENERIC_RELOC_VANILLA) {
833 *wordPtr = word;
834 continue;
835 }
836 #ifdef powerpc_HOST_ARCH
837 else if(reloc->r_type == PPC_RELOC_LO16)
838 {
839 ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
840 i++;
841 continue;
842 }
843 else if(reloc->r_type == PPC_RELOC_HI16)
844 {
845 ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF;
846 i++;
847 continue;
848 }
849 else if(reloc->r_type == PPC_RELOC_HA16)
850 {
851 ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
852 + ((word & (1<<15)) ? 1 : 0);
853 i++;
854 continue;
855 }
856 else if(reloc->r_type == PPC_RELOC_BR24)
857 {
858 if ((word & 0x03) != 0) {
859 barf("%s: unconditional relative branch with a displacement "
860 "which isn't a multiple of 4 bytes: %#lx",
861 OC_INFORMATIVE_FILENAME(oc),
862 word);
863 }
864
865 if((word & 0xFE000000) != 0xFE000000 &&
866 (word & 0xFE000000) != 0x00000000) {
867 // The branch offset is too large.
868 // Therefore, we try to use a jump island.
869 if (jumpIsland == 0) {
870 barf("%s: unconditional relative branch out of range: "
871 "no jump island available: %#lx",
872 OC_INFORMATIVE_FILENAME(oc),
873 word);
874 }
875
876 word = offsetToJumpIsland;
877
878 if((word & 0xFE000000) != 0xFE000000 &&
879 (word & 0xFE000000) != 0x00000000) {
880 barf("%s: unconditional relative branch out of range: "
881 "jump island out of range: %#lx",
882 OC_INFORMATIVE_FILENAME(oc),
883 word);
884 }
885 }
886 *wordPtr = (*wordPtr & 0xFC000003) | (word & 0x03FFFFFC);
887 continue;
888 }
889 #endif /* powerpc_HOST_ARCH */
890 }
891 else
892 {
893 barf("Can't handle Mach-O relocation entry (not scattered) "
894 "with this r_length tag: "
895 "object file %s; entry type %ld; "
896 "r_length tag %ld; address %#lx\n",
897 OC_INFORMATIVE_FILENAME(oc),
898 reloc->r_type,
899 reloc->r_length,
900 reloc->r_address);
901 return 0;
902 }
903 }
904 #endif /* x86_64_HOST_ARCH */
905 }
906
907 IF_DEBUG(linker, debugBelch("relocateSection: done\n"));
908 return 1;
909 }
910
911 int
912 ocGetNames_MachO(ObjectCode* oc)
913 {
914 char *image = (char*) oc->image;
915 struct mach_header *header = (struct mach_header*) image;
916 struct load_command *lc = (struct load_command*) (image + sizeof(struct mach_header));
917 unsigned i,curSymbol = 0;
918 struct segment_command *segLC = NULL;
919 struct section *sections;
920 struct symtab_command *symLC = NULL;
921 struct nlist *nlist;
922 unsigned long commonSize = 0;
923 SymbolAddr* commonStorage = NULL;
924 unsigned long commonCounter;
925
926 IF_DEBUG(linker,debugBelch("ocGetNames_MachO: start\n"));
927
928 for(i=0;i<header->ncmds;i++)
929 {
930 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) {
931 segLC = (struct segment_command*) lc;
932 }
933 else if (lc->cmd == LC_SYMTAB) {
934 symLC = (struct symtab_command*) lc;
935 }
936
937 lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize );
938 }
939
940 sections = (struct section*) (segLC+1);
941 nlist = symLC ? (struct nlist*) (image + symLC->symoff)
942 : NULL;
943
944 if (!segLC) {
945 barf("ocGetNames_MachO: no segment load command");
946 }
947
948 Section *secArray;
949 secArray = (Section*)stgCallocBytes(
950 sizeof(Section),
951 segLC->nsects,
952 "ocGetNames_MachO(sections)");
953 oc->sections = secArray;
954 oc->n_sections = segLC->nsects;
955
956 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: will load %d sections\n", segLC->nsects));
957 for(i=0;i<segLC->nsects;i++)
958 {
959 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: section %d\n", i));
960
961 if (sections[i].size == 0) {
962 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: found a zero length section, skipping\n"));
963 continue;
964 }
965
966 if((sections[i].flags & SECTION_TYPE) == S_ZEROFILL) {
967 char * zeroFillArea;
968 if (RTS_LINKER_USE_MMAP) {
969 zeroFillArea = mmapForLinker(sections[i].size, MAP_ANONYMOUS,
970 -1, 0);
971 if (zeroFillArea == NULL) return 0;
972 memset(zeroFillArea, 0, sections[i].size);
973 }
974 else {
975 zeroFillArea = stgCallocBytes(1,sections[i].size,
976 "ocGetNames_MachO(common symbols)");
977 }
978 sections[i].offset = zeroFillArea - image;
979 }
980
981 SectionKind kind = SECTIONKIND_OTHER;
982
983 if (0==strcmp(sections[i].sectname,"__text")) {
984 kind = SECTIONKIND_CODE_OR_RODATA;
985 }
986 else if (0==strcmp(sections[i].sectname,"__const") ||
987 0==strcmp(sections[i].sectname,"__data") ||
988 0==strcmp(sections[i].sectname,"__bss") ||
989 0==strcmp(sections[i].sectname,"__common") ||
990 0==strcmp(sections[i].sectname,"__mod_init_func")) {
991 kind = SECTIONKIND_RWDATA;
992 }
993
994 addSection(&secArray[i], kind, SECTION_NOMEM,
995 (void *)(image + sections[i].offset),
996 sections[i].size,
997 0, 0, 0);
998
999 addProddableBlock(oc,
1000 (void *) (image + sections[i].offset),
1001 sections[i].size);
1002 }
1003
1004 // count external symbols defined here
1005 oc->n_symbols = 0;
1006 if (symLC) {
1007 for (i = 0; i < symLC->nsyms; i++) {
1008 if (nlist[i].n_type & N_STAB) {
1009 ;
1010 }
1011 else if(nlist[i].n_type & N_EXT)
1012 {
1013 if((nlist[i].n_type & N_TYPE) == N_UNDF
1014 && (nlist[i].n_value != 0))
1015 {
1016 commonSize += nlist[i].n_value;
1017 oc->n_symbols++;
1018 }
1019 else if((nlist[i].n_type & N_TYPE) == N_SECT)
1020 oc->n_symbols++;
1021 }
1022 }
1023 }
1024 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: %d external symbols\n", oc->n_symbols));
1025 oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(SymbolName*),
1026 "ocGetNames_MachO(oc->symbols)");
1027
1028 if(symLC)
1029 {
1030 for(i=0;i<symLC->nsyms;i++)
1031 {
1032 if(nlist[i].n_type & N_STAB)
1033 ;
1034 else if((nlist[i].n_type & N_TYPE) == N_SECT)
1035 {
1036 if(nlist[i].n_type & N_EXT)
1037 {
1038 SymbolName* nm = image + symLC->stroff + nlist[i].n_un.n_strx;
1039 if ((nlist[i].n_desc & N_WEAK_DEF) && lookupSymbol_(nm)) {
1040 // weak definition, and we already have a definition
1041 IF_DEBUG(linker, debugBelch(" weak: %s\n", nm));
1042 }
1043 else
1044 {
1045 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting %s\n", nm));
1046 SymbolAddr* addr = image
1047 + sections[nlist[i].n_sect - 1].offset
1048 - sections[nlist[i].n_sect - 1].addr
1049 + nlist[i].n_value;
1050
1051 ghciInsertSymbolTable( oc->fileName
1052 , symhash
1053 , nm
1054 , addr
1055 , HS_BOOL_FALSE
1056 , oc);
1057
1058 oc->symbols[curSymbol] = nm;
1059 curSymbol++;
1060 }
1061 }
1062 else
1063 {
1064 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not external, skipping\n"));
1065 }
1066 }
1067 else
1068 {
1069 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not defined in this section, skipping\n"));
1070 }
1071 }
1072 }
1073
1074 commonStorage = stgCallocBytes(1,commonSize,"ocGetNames_MachO(common symbols)");
1075 commonCounter = (unsigned long)commonStorage;
1076
1077 if (symLC) {
1078 for (i = 0; i < symLC->nsyms; i++) {
1079 if((nlist[i].n_type & N_TYPE) == N_UNDF
1080 && (nlist[i].n_type & N_EXT)
1081 && (nlist[i].n_value != 0)) {
1082
1083 SymbolName* nm = image + symLC->stroff + nlist[i].n_un.n_strx;
1084 unsigned long sz = nlist[i].n_value;
1085
1086 nlist[i].n_value = commonCounter;
1087
1088 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm));
1089 ghciInsertSymbolTable(oc->fileName, symhash, nm,
1090 (void*)commonCounter, HS_BOOL_FALSE, oc);
1091 oc->symbols[curSymbol] = nm;
1092 curSymbol++;
1093
1094 commonCounter += sz;
1095 }
1096 }
1097 }
1098
1099 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: done\n"));
1100 return 1;
1101 }
1102
1103 int
1104 ocResolve_MachO(ObjectCode* oc)
1105 {
1106 char *image = (char*) oc->image;
1107 struct mach_header *header = (struct mach_header*) image;
1108 struct load_command *lc = (struct load_command*) (image + sizeof(struct mach_header));
1109 unsigned i;
1110 struct segment_command *segLC = NULL;
1111 struct section *sections;
1112 struct symtab_command *symLC = NULL;
1113 struct dysymtab_command *dsymLC = NULL;
1114 struct nlist *nlist;
1115
1116 IF_DEBUG(linker, debugBelch("ocResolve_MachO: start\n"));
1117 for (i = 0; i < header->ncmds; i++)
1118 {
1119 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) {
1120 segLC = (struct segment_command*) lc;
1121 IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a 32 or 64 bit segment load command\n"));
1122 }
1123 else if (lc->cmd == LC_SYMTAB) {
1124 symLC = (struct symtab_command*) lc;
1125 IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a symbol table load command\n"));
1126 }
1127 else if (lc->cmd == LC_DYSYMTAB) {
1128 dsymLC = (struct dysymtab_command*) lc;
1129 IF_DEBUG(linker, debugBelch("ocResolve_MachO: found a dynamic symbol table load command\n"));
1130 }
1131
1132 lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize );
1133 }
1134
1135 sections = (struct section*) (segLC+1);
1136 nlist = symLC ? (struct nlist*) (image + symLC->symoff)
1137 : NULL;
1138
1139 if(dsymLC)
1140 {
1141 unsigned long *indirectSyms
1142 = (unsigned long*) (image + dsymLC->indirectsymoff);
1143
1144 IF_DEBUG(linker, debugBelch("ocResolve_MachO: resolving dsymLC\n"));
1145 for (i = 0; i < segLC->nsects; i++)
1146 {
1147 if( !strcmp(sections[i].sectname,"__la_symbol_ptr")
1148 || !strcmp(sections[i].sectname,"__la_sym_ptr2")
1149 || !strcmp(sections[i].sectname,"__la_sym_ptr3"))
1150 {
1151 if(!resolveImports(oc,image,symLC,&sections[i],indirectSyms,nlist))
1152 return 0;
1153 }
1154 else if(!strcmp(sections[i].sectname,"__nl_symbol_ptr")
1155 || !strcmp(sections[i].sectname,"__pointers"))
1156 {
1157 if(!resolveImports(oc,image,symLC,&sections[i],indirectSyms,nlist))
1158 return 0;
1159 }
1160 else if(!strcmp(sections[i].sectname,"__jump_table"))
1161 {
1162 if(!resolveImports(oc,image,symLC,&sections[i],indirectSyms,nlist))
1163 return 0;
1164 }
1165 else
1166 {
1167 IF_DEBUG(linker, debugBelch("ocResolve_MachO: unknown section\n"));
1168 }
1169 }
1170 }
1171
1172 for(i=0;i<segLC->nsects;i++)
1173 {
1174 IF_DEBUG(linker, debugBelch("ocResolve_MachO: relocating section %d\n", i));
1175
1176 if (!relocateSection(oc,image,symLC,nlist,segLC->nsects,sections,&sections[i]))
1177 return 0;
1178 }
1179
1180 #if defined (powerpc_HOST_ARCH)
1181 ocFlushInstructionCache( oc );
1182 #endif
1183
1184 return 1;
1185 }
1186
1187 int
1188 ocRunInit_MachO ( ObjectCode *oc )
1189 {
1190 char *image = (char*) oc->image;
1191 struct mach_header *header = (struct mach_header*) image;
1192 struct load_command *lc = (struct load_command*) (image + sizeof(struct mach_header));
1193 struct segment_command *segLC = NULL;
1194 struct section *sections;
1195 uint32_t i;
1196
1197 for (i = 0; i < header->ncmds; i++) {
1198 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) {
1199 segLC = (struct segment_command*) lc;
1200 }
1201 lc = (struct load_command *) ( ((char*)lc) + lc->cmdsize );
1202 }
1203 if (!segLC) {
1204 barf("ocRunInit_MachO: no segment load command");
1205 }
1206 sections = (struct section*) (segLC+1);
1207
1208 int argc, envc;
1209 char **argv, **envv;
1210
1211 getProgArgv(&argc, &argv);
1212 getProgEnvv(&envc, &envv);
1213
1214 for (i = 0; i < segLC->nsects; i++) {
1215 // ToDo: replace this with a proper check for the S_MOD_INIT_FUNC_POINTERS
1216 // flag. We should do this elsewhere in the Mach-O linker code
1217 // too. Note that the system linker will *refuse* to honor
1218 // sections which don't have this flag, so this could cause
1219 // weird behavior divergence (albeit reproducible).
1220 if (0 == strcmp(sections[i].sectname,"__mod_init_func")) {
1221 char *init_startC = image + sections[i].offset;
1222 init_t *init = (init_t*)init_startC;
1223 init_t *init_end = (init_t*)(init_startC + sections[i].size);
1224 for (; init < init_end; init++) {
1225 (*init)(argc, argv, envv);
1226 }
1227 }
1228 }
1229
1230 freeProgEnvv(envc, envv);
1231 return 1;
1232 }
1233
1234 #ifdef powerpc_HOST_ARCH
1235 /*
1236 * The Mach-O object format uses leading underscores. But not everywhere.
1237 * There is a small number of runtime support functions defined in
1238 * libcc_dynamic.a whose name does not have a leading underscore.
1239 * As a consequence, we can't get their address from C code.
1240 * We have to use inline assembler just to take the address of a function.
1241 * Yuck.
1242 */
1243
1244 extern void* symbolsWithoutUnderscore[];
1245
1246 void
1247 machoInitSymbolsWithoutUnderscore(void)
1248 {
1249 void **p = symbolsWithoutUnderscore;
1250 __asm__ volatile(".globl _symbolsWithoutUnderscore\n.data\n_symbolsWithoutUnderscore:");
1251
1252 #undef SymI_NeedsProto
1253 #undef SymI_NeedsDataProto
1254
1255 #define SymI_NeedsProto(x) \
1256 __asm__ volatile(".long " # x);
1257
1258 #define SymI_NeedsDataProto(x) \
1259 SymI_NeedsProto(x)
1260
1261 RTS_MACHO_NOUNDERLINE_SYMBOLS
1262
1263 __asm__ volatile(".text");
1264
1265 #undef SymI_NeedsProto
1266 #undef SymI_NeedsDataProto
1267
1268 #define SymI_NeedsProto(x) \
1269 ghciInsertSymbolTable("(GHCi built-in symbols)", symhash, #x, *p++, HS_BOOL_FALSE, NULL);
1270
1271 #define SymI_NeedsDataProto(x) \
1272 SymI_NeedsProto(x)
1273
1274 RTS_MACHO_NOUNDERLINE_SYMBOLS
1275
1276 #undef SymI_NeedsProto
1277 #undef SymI_NeedsDataProto
1278 }
1279 #endif
1280
1281 /*
1282 * Figure out by how much to shift the entire Mach-O file in memory
1283 * when loading so that its single segment ends up 16-byte-aligned
1284 */
1285 int
1286 machoGetMisalignment( FILE * f )
1287 {
1288 struct mach_header header;
1289 int misalignment;
1290
1291 {
1292 int n = fread(&header, sizeof(header), 1, f);
1293 if (n != 1) {
1294 barf("machoGetMisalignment: can't read the Mach-O header");
1295 }
1296 }
1297 fseek(f, -sizeof(header), SEEK_CUR);
1298
1299 #if x86_64_HOST_ARCH || powerpc64_HOST_ARCH
1300 if(header.magic != MH_MAGIC_64) {
1301 barf("Bad magic. Expected: %08x, got: %08x.",
1302 MH_MAGIC_64, header.magic);
1303 }
1304 #else
1305 if(header.magic != MH_MAGIC) {
1306 barf("Bad magic. Expected: %08x, got: %08x.",
1307 MH_MAGIC, header.magic);
1308 }
1309 #endif
1310
1311 misalignment = (header.sizeofcmds + sizeof(header))
1312 & 0xF;
1313
1314 return misalignment ? (16 - misalignment) : 0;
1315 }
1316
1317 #endif /* darwin_HOST_OS, ios_HOST_OS */