Revert "Add a RTS option -xp to load PIC object anywhere in address space"
[ghc.git] / rts / linker / MachO.c
1 #include "Rts.h"
2
3 #if defined(darwin_HOST_OS) || defined(ios_HOST_OS)
4
5 #if defined(ios_HOST_OS)
6 #if !RTS_LINKER_USE_MMAP
7 #error "ios must use mmap and mprotect!"
8 #endif
9 /* for roundUpToPage */
10 #include "sm/OSMem.h"
11 #endif
12
13 #include "RtsUtils.h"
14 #include "GetEnv.h"
15 #include "LinkerInternals.h"
16 #include "linker/MachO.h"
17 #include "linker/CacheFlush.h"
18 #include "linker/SymbolExtras.h"
19
20 #include <string.h>
21 #include <regex.h>
22 #include <mach/machine.h>
23 #include <mach-o/fat.h>
24 #include <mach-o/loader.h>
25 #include <mach-o/nlist.h>
26 #include <mach-o/reloc.h>
27
28 #if defined(HAVE_SYS_MMAN_H) && RTS_LINKER_USE_MMAP
29 # include <sys/mman.h>
30 #endif
31
32 #if defined(powerpc_HOST_ARCH)
33 # include <mach-o/ppc/reloc.h>
34 #endif
35
36 #if defined(x86_64_HOST_ARCH)
37 # include <mach-o/x86_64/reloc.h>
38 #endif
39
40 #if defined(aarch64_HOST_ARCH)
41 # include <mach-o/arm64/reloc.h>
42 #endif
43
44 /*
45 Support for MachO linking on Darwin/MacOS X
46 by Wolfgang Thaller (wolfgang.thaller@gmx.net)
47
48 I hereby formally apologize for the hackish nature of this code.
49 Things that need to be done:
50 *) implement ocVerifyImage_MachO
51 *) add still more sanity checks.
52 */
53 #if defined(aarch64_HOST_ARCH)
54 /* aarch64 linker by moritz angermann <moritz@lichtzwerge.de> */
55
56 /* often times we need to extend some value of certain number of bits
57 * int an int64_t for e.g. relative offsets.
58 */
59 int64_t signExtend(uint64_t val, uint8_t bits);
60 /* Helper functions to check some instruction properties */
61 bool isVectorPp(uint32_t *p);
62 bool isLoadStore(uint32_t *p);
63
64 /* aarch64 relocations may contain an addend alreay in the position
65 * where we want to write the address offset to. Thus decoding as well
66 * as encoding is needed.
67 */
68 bool fitsBits(size_t bits, int64_t value);
69 int64_t decodeAddend(ObjectCode * oc, Section * section,
70 MachORelocationInfo * ri);
71 void encodeAddend(ObjectCode * oc, Section * section,
72 MachORelocationInfo * ri, int64_t addend);
73
74 /* finding and making stubs. We don't need to care about the symbol they
75 * represent. As long as two stubs point to the same address, they are identical
76 */
77 bool findStub(Section * section, void ** addr);
78 bool makeStub(Section * section, void ** addr);
79 void freeStubs(Section * section);
80
81 /* Global Offset Table logic */
82 bool isGotLoad(MachORelocationInfo * ri);
83 bool needGotSlot(MachONList * symbol);
84 bool makeGot(ObjectCode * oc);
85 void freeGot(ObjectCode * oc);
86 #endif /* aarch64_HOST_ARCH */
87
88 #if defined(ios_HOST_OS)
89 /* on iOS we need to ensure we only have r+w or r+x pages hence we need to mmap
90 * pages r+w and r+x mprotect them later on.
91 */
92 bool ocMprotect_MachO( ObjectCode *oc );
93 #endif /* ios_HOST_OS */
94
95 /*
96 * Initialize some common data in the object code so we don't have to
97 * continuously look up the addresses.
98 */
99 void
100 ocInit_MachO(ObjectCode * oc)
101 {
102 oc->info = (struct ObjectCodeFormatInfo*)stgCallocBytes(
103 1, sizeof *oc->info,
104 "ocInit_MachO(ObjectCodeFormatInfo)");
105 oc->info->header = (MachOHeader *) oc->image;
106 oc->info->symCmd = NULL;
107 oc->info->segCmd = NULL;
108 oc->info->dsymCmd = NULL;
109
110 MachOLoadCommand *lc = (MachOLoadCommand*)(oc->image + sizeof(MachOHeader));
111 for(size_t i = 0; i < oc->info->header->ncmds; i++) {
112 if (lc->cmd == LC_SEGMENT || lc->cmd == LC_SEGMENT_64) {
113 oc->info->segCmd = (MachOSegmentCommand*) lc;
114 }
115 else if (lc->cmd == LC_SYMTAB) {
116 oc->info->symCmd = (MachOSymtabCommand*) lc;
117 }
118 else if (lc->cmd == LC_DYSYMTAB) {
119 oc->info->dsymCmd = (MachODsymtabCommand*) lc;
120 }
121 lc = (MachOLoadCommand *) ( ((char*)lc) + lc->cmdsize );
122 }
123 if (NULL == oc->info->segCmd) {
124 barf("ocGetNames_MachO: no segment load command");
125 }
126
127 oc->info->macho_sections = (MachOSection*) (oc->info->segCmd+1);
128 oc->n_sections = oc->info->segCmd->nsects;
129
130 oc->info->nlist = oc->info->symCmd == NULL
131 ? NULL
132 : (MachONList *)(oc->image + oc->info->symCmd->symoff);
133 oc->info->names = oc->info->symCmd == NULL
134 ? NULL
135 : (oc->image + oc->info->symCmd->stroff);
136
137 /* If we have symbols, allocate and fill the macho_symbols
138 * This will make relocation easier.
139 */
140 oc->info->n_macho_symbols = 0;
141 oc->info->macho_symbols = NULL;
142
143 if(NULL != oc->info->nlist) {
144 oc->info->n_macho_symbols = oc->info->symCmd->nsyms;
145 oc->info->macho_symbols = (MachOSymbol*)stgCallocBytes(
146 oc->info->symCmd->nsyms,
147 sizeof(MachOSymbol),
148 "ocInit_MachO(MachOSymbol)");
149 for(uint32_t i = 0; i < oc->info->symCmd->nsyms; i++) {
150 oc->info->macho_symbols[i].name = oc->info->names
151 + oc->info->nlist[i].n_un.n_strx;
152 oc->info->macho_symbols[i].nlist = &oc->info->nlist[i];
153 /* we don't have an address for this symbol yet; this will be
154 * populated during ocGetNames_MachO. hence addr = NULL
155 */
156 oc->info->macho_symbols[i].addr = NULL;
157 }
158 }
159 }
160
161 void
162 ocDeinit_MachO(ObjectCode * oc) {
163 if(oc->info->n_macho_symbols > 0) {
164 stgFree(oc->info->macho_symbols);
165 }
166 #if defined(aarch64_HOST_ARCH)
167 freeGot(oc);
168 for(int i = 0; i < oc->n_sections; i++) {
169 freeStubs(&oc->sections[i]);
170 }
171 #endif
172 stgFree(oc->info);
173 }
174
175 static int
176 resolveImports(
177 ObjectCode* oc,
178 MachOSection *sect, // ptr to lazy or non-lazy symbol pointer section
179 unsigned long *indirectSyms);
180
181 #if NEED_SYMBOL_EXTRAS
182 #if defined(powerpc_HOST_ARCH)
183 int
184 ocAllocateSymbolExtras_MachO(ObjectCode* oc)
185 {
186
187 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
188
189 // Find out the first and last undefined external
190 // symbol, so we don't have to allocate too many
191 // jump islands/GOT entries.
192
193 unsigned min = oc->info->symCmd->nsyms, max = 0;
194
195 for (unsigned i = 0; i < oc->info->symCmd->nsyms; i++) {
196
197 if (oc->info->nlist[i].n_type & N_STAB) {
198 ;
199 } else if (oc->info->nlist[i].n_type & N_EXT) {
200
201 if((oc->info->nlist[i].n_type & N_TYPE) == N_UNDF
202 && (oc->info->nlist[i].n_value == 0)) {
203
204 if (i < min) {
205 min = i;
206 }
207
208 if (i > max) {
209 max = i;
210 }
211 }
212 }
213 }
214
215 if (max >= min) {
216 return ocAllocateSymbolExtras(oc, max - min + 1, min);
217 }
218
219 return ocAllocateSymbolExtras(oc,0,0);
220 }
221
222 #elif defined(x86_64_HOST_ARCH) || defined(aarch64_HOST_ARCH)
223
224 int
225 ocAllocateSymbolExtras_MachO(ObjectCode* oc)
226 {
227 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: start\n"));
228
229 if (NULL != oc->info->symCmd) {
230 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocate %d symbols\n", oc->info->symCmd->nsyms));
231 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
232 return ocAllocateSymbolExtras(oc, oc->info->symCmd->nsyms, 0);
233 }
234
235 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: allocated no symbols\n"));
236 IF_DEBUG(linker, debugBelch("ocAllocateSymbolExtras_MachO: done\n"));
237 return ocAllocateSymbolExtras(oc,0,0);
238 }
239
240 #else
241 #error Unknown MachO architecture
242 #endif /* HOST_ARCH */
243 #endif /* NEED_SYMBOL_EXTRAS */
244
245 int
246 ocVerifyImage_MachO(ObjectCode * oc)
247 {
248 char *image = (char*) oc->image;
249 MachOHeader *header = (MachOHeader*) image;
250
251 IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: start\n"));
252
253 #if defined(x86_64_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \
254 || defined(aarch64_HOST_ARCH)
255 if(header->magic != MH_MAGIC_64) {
256 errorBelch("Could not load image %s: bad magic!\n"
257 " Expected %08x (64bit), got %08x%s\n",
258 oc->fileName, MH_MAGIC_64, header->magic,
259 header->magic == MH_MAGIC ? " (32bit)." : ".");
260 return 0;
261 }
262 #else
263 if(header->magic != MH_MAGIC) {
264 errorBelch("Could not load image %s: bad magic!\n"
265 " Expected %08x (32bit), got %08x%s\n",
266 oc->fileName, MH_MAGIC, header->magic,
267 header->magic == MH_MAGIC_64 ? " (64bit)." : ".");
268 return 0;
269 }
270 #endif
271
272 // FIXME: do some more verifying here
273 IF_DEBUG(linker, debugBelch("ocVerifyImage_MachO: done\n"));
274 return 1;
275 }
276
277 static int
278 resolveImports(
279 ObjectCode* oc,
280 MachOSection *sect, // ptr to lazy or non-lazy symbol pointer section
281 unsigned long *indirectSyms)
282 {
283 size_t itemSize = 4;
284
285 IF_DEBUG(linker, debugBelch("resolveImports: start\n"));
286
287 #if defined(i386_HOST_ARCH)
288 int isJumpTable = 0;
289
290 if (strcmp(sect->sectname,"__jump_table") == 0) {
291 isJumpTable = 1;
292 itemSize = 5;
293 ASSERT(sect->reserved2 == itemSize);
294 }
295
296 #endif
297
298 for(unsigned i = 0; i * itemSize < sect->size; i++)
299 {
300 // according to otool, reserved1 contains the first index into the
301 // indirect symbol table
302 unsigned long indirectSymbolIndex = indirectSyms[sect->reserved1+i];
303 MachOSymbol *symbol = &oc->info->macho_symbols[indirectSymbolIndex];
304 SymbolAddr* addr = NULL;
305
306 IF_DEBUG(linker, debugBelch("resolveImports: resolving %s\n", symbol->name));
307
308 if ((symbol->nlist->n_type & N_TYPE) == N_UNDF
309 && (symbol->nlist->n_type & N_EXT) && (symbol->nlist->n_value != 0)) {
310 addr = (SymbolAddr*) (symbol->nlist->n_value);
311 IF_DEBUG(linker, debugBelch("resolveImports: undefined external %s has value %p\n", symbol->name, addr));
312 } else {
313 addr = lookupSymbol_(symbol->name);
314 IF_DEBUG(linker, debugBelch("resolveImports: looking up %s, %p\n", symbol->name, addr));
315 }
316
317 if (addr == NULL)
318 {
319 errorBelch("\nlookupSymbol failed in resolveImports\n"
320 "%s: unknown symbol `%s'", oc->fileName, symbol->name);
321 return 0;
322 }
323 ASSERT(addr);
324
325 #if defined(i386_HOST_ARCH)
326 if (isJumpTable) {
327 checkProddableBlock(oc,oc->image + sect->offset + i*itemSize, 5);
328
329 *(oc->image + sect->offset + i * itemSize) = 0xe9; // jmp opcode
330 *(unsigned*)(oc->image + sect->offset + i*itemSize + 1)
331 = (SymbolAddr*)addr - (oc->image + sect->offset + i*itemSize + 5);
332 }
333 else
334 #endif
335 {
336 checkProddableBlock(oc,
337 ((void**)(oc->image + sect->offset)) + i,
338 sizeof(void *));
339 ((void**)(oc->image + sect->offset))[i] = addr;
340 }
341 }
342
343 IF_DEBUG(linker, debugBelch("resolveImports: done\n"));
344 return 1;
345 }
346
347 #if defined(aarch64_HOST_ARCH)
348 /* aarch64 linker by moritz angermann <moritz@lichtzwerge.de> */
349
350 int64_t
351 signExtend(uint64_t val, uint8_t bits) {
352 return (int64_t)(val << (64-bits)) >> (64-bits);
353 }
354
355 bool
356 isVectorOp(uint32_t *p) {
357 return (*p & 0x04800000) == 0x04800000;
358 }
359
360 bool
361 isLoadStore(uint32_t *p) {
362 return (*p & 0x3B000000) == 0x39000000;
363 }
364
365 int64_t
366 decodeAddend(ObjectCode * oc, Section * section, MachORelocationInfo * ri) {
367
368 /* the instruction. It is 32bit wide */
369 uint32_t * p = (uint32_t*)((uint8_t*)section->start + ri->r_address);
370
371 checkProddableBlock(oc, (void*)p, 1 << ri->r_length);
372
373 switch(ri->r_type) {
374 case ARM64_RELOC_UNSIGNED:
375 case ARM64_RELOC_SUBTRACTOR: {
376 switch (ri->r_length) {
377 case 0: return signExtend(*(uint8_t*)p, 8 * (1 << ri->r_length));
378 case 1: return signExtend(*(uint16_t*)p, 8 * (1 << ri->r_length));
379 case 2: return signExtend(*(uint32_t*)p, 8 * (1 << ri->r_length));
380 case 3: return signExtend(*(uint64_t*)p, 8 * (1 << ri->r_length));
381 default:
382 barf("Unsupported r_length (%d) for SUBTRACTOR relocation",
383 ri->r_length);
384 }
385 }
386 case ARM64_RELOC_BRANCH26:
387 /* take the lower 26 bits and shift them by 2. The last two are
388 * implicilty 0 (as the instructions must be aligned!) and sign
389 * extend to 64 bits.
390 */
391 return signExtend( (*p & 0x03FFFFFF) << 2, 28 );
392 case ARM64_RELOC_PAGE21:
393 case ARM64_RELOC_GOT_LOAD_PAGE21:
394 /* take the instruction bits masked with 0x6 (0110), and push them
395 * down. into the last two bits, and mask in the
396 *
397 * the 21 bits are encoded as follows in the instruction
398 *
399 * -**- ---* **** **** **** **** ***-- ----
400 * ^^
401 * ''-- these are the low two bits.
402 */
403 return signExtend( (*p & 0x60000000) >> 29
404 | ((*p & 0x01FFFFE0) >> 3) << 12, 33);
405 case ARM64_RELOC_PAGEOFF12:
406 case ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
407 /* the 12 bits for the page offset are encoded from bit 11 onwards
408 *
409 * ---- ---- --** **** **** **-- ---- ----
410 */
411 int64_t a = (*p & 0x003FFC00) >> 10;
412 int shift = 0;
413 if (isLoadStore(p)) {
414 shift = (*p >> 30) & 0x3;
415 if(0 == shift && isVectorOp(p)) {
416 shift = 4;
417 }
418 }
419 return a << shift;
420 }
421 }
422 barf("unsupported relocation type: %d\n", ri->r_type);
423 }
424
425 inline bool
426 fitsBits(size_t bits, int64_t value) {
427 if(bits == 64) return true;
428 if(bits > 64) barf("fits_bits with %d bits and an 64bit integer!", bits);
429 return 0 == (value >> bits) // All bits off: 0
430 || -1 == (value >> bits); // All bits on: -1
431 }
432
433 void
434 encodeAddend(ObjectCode * oc, Section * section,
435 MachORelocationInfo * ri, int64_t addend) {
436 uint32_t * p = (uint32_t*)((uint8_t*)section->start + ri->r_address);
437
438 checkProddableBlock(oc, (void*)p, 1 << ri->r_length);
439
440 switch (ri->r_type) {
441 case ARM64_RELOC_UNSIGNED:
442 case ARM64_RELOC_SUBTRACTOR: {
443 if(!fitsBits(8 << ri->r_length, addend))
444 barf("Relocation out of range for UNSIGNED/SUBTRACTOR");
445 switch (ri->r_length) {
446 case 0: *(uint8_t*)p = (uint8_t)addend; break;
447 case 1: *(uint16_t*)p = (uint16_t)addend; break;
448 case 2: *(uint32_t*)p = (uint32_t)addend; break;
449 case 3: *(uint64_t*)p = (uint64_t)addend; break;
450 default:
451 barf("Unsupported r_length (%d) for SUBTRACTOR relocation",
452 ri->r_length);
453 }
454 return;
455 }
456 case ARM64_RELOC_BRANCH26: {
457 /* We can only store 26 bits in the instruction, due to alignment we
458 * do not need the last two bits of the value. If the value >> 2
459 * still exceeds 26bits, we won't be able to reach it.
460 */
461 if(!fitsBits(26, addend >> 2))
462 barf("Relocation target for BRACH26 out of range.");
463 *p = (*p & 0xFC000000) | ((uint32_t)(addend >> 2) & 0x03FFFFFF);
464 return;
465 }
466 case ARM64_RELOC_PAGE21:
467 case ARM64_RELOC_GOT_LOAD_PAGE21: {
468 /* We store 21bits, in bits 6 to 24, and bits 30 and 31.
469 * The encoded value describes a multiple of 4k pages, and together
470 * with the PAGEOFF12 relocation allows to address a relative range
471 * of +-4GB.
472 */
473 if(!fitsBits(21, addend >> 12))
474 barf("Relocation target for PAGE21 out of range.");
475 *p = (*p & 0x9F00001F) | (uint32_t)((addend << 17) & 0x60000000)
476 | (uint32_t)((addend >> 9) & 0x00FFFFE0);
477 return;
478 }
479 case ARM64_RELOC_PAGEOFF12:
480 case ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
481 /* Store an offset into a page (4k). Depending on the instruction
482 * the bits are stored at slightly different positions.
483 */
484 if(!fitsBits(12, addend))
485 barf("Relocation target for PAGEOFF12 out or range.");
486
487 int shift = 0;
488 if(isLoadStore(p)) {
489 shift = (*p >> 30) & 0x3;
490 if(0 == shift && isVectorOp(p)) {
491 shift = 4;
492 }
493 }
494 *p = (*p & 0xFFC003FF)
495 | ((uint32_t)(addend >> shift << 10) & 0x003FFC00);
496 return;
497 }
498 }
499 barf("unsupported relocation type: %d\n", ri->r_type);
500 }
501
502 bool
503 isGotLoad(struct relocation_info * ri) {
504 return ri->r_type == ARM64_RELOC_GOT_LOAD_PAGE21
505 || ri->r_type == ARM64_RELOC_GOT_LOAD_PAGEOFF12;
506 }
507
508 /* This is very similar to makeSymbolExtra
509 * However, as we load sections into different
510 * pages, that may be further appart than
511 * branching allows, we'll use some extra
512 * space at the end of each section allocated
513 * for stubs.
514 */
515 bool
516 findStub(Section * section, void ** addr) {
517
518 for(Stub * s = section->info->stubs; s != NULL; s = s->next) {
519 if(s->target == *addr) {
520 *addr = s->addr;
521 return EXIT_SUCCESS;
522 }
523 }
524 return EXIT_FAILURE;
525 }
526
527 bool
528 makeStub(Section * section, void ** addr) {
529
530 Stub * s = stgCallocBytes(1, sizeof(Stub), "makeStub(Stub)");
531 s->target = *addr;
532 s->addr = (uint8_t*)section->info->stub_offset
533 + ((8+8)*section->info->nstubs) + 8;
534 s->next = NULL;
535
536 /* target address */
537 *(uint64_t*)((uint8_t*)s->addr - 8) = (uint64_t)s->target;
538 /* ldr x16, - (8 bytes) */
539 *(uint32_t*)(s->addr) = (uint32_t)0x58ffffd0;
540 /* br x16 */
541 *(uint32_t*)((uint8_t*)s->addr + 4) = (uint32_t)0xd61f0200;
542
543 if(section->info->nstubs == 0) {
544 /* no stubs yet, let's just create this one */
545 section->info->stubs = s;
546 } else {
547 Stub * tail = section->info->stubs;
548 while(tail->next != NULL) tail = tail->next;
549 tail->next = s;
550 }
551 section->info->nstubs += 1;
552 *addr = s->addr;
553 return EXIT_SUCCESS;
554 }
555 void
556 freeStubs(Section * section) {
557 if(section->info->nstubs == 0)
558 return;
559 Stub * last = section->info->stubs;
560 while(last->next != NULL) {
561 Stub * t = last;
562 last = last->next;
563 stgFree(t);
564 }
565 section->info->stubs = NULL;
566 section->info->nstubs = 0;
567 }
568
569 /*
570 * Check if we need a global offset table slot for a
571 * given symbol
572 */
573 bool
574 needGotSlot(MachONList * symbol) {
575 return (symbol->n_type & N_EXT) /* is an external symbol */
576 && (N_UNDF == (symbol->n_type & N_TYPE) /* and is undefined */
577 || NO_SECT != symbol->n_sect); /* or is defined in a
578 * different section */
579 }
580
581 bool
582 makeGot(ObjectCode * oc) {
583 size_t got_slots = 0;
584
585 for(size_t i=0; i < oc->info->n_macho_symbols; i++)
586 if(needGotSlot(oc->info->macho_symbols[i].nlist))
587 got_slots += 1;
588
589 if(got_slots > 0) {
590 oc->info->got_size = got_slots * sizeof(void*);
591 oc->info->got_start = mmap(NULL, oc->info->got_size,
592 PROT_READ | PROT_WRITE,
593 MAP_ANON | MAP_PRIVATE,
594 -1, 0);
595 if( oc->info->got_start == MAP_FAILED ) {
596 barf("MAP_FAILED. errno=%d", errno );
597 return EXIT_FAILURE;
598 }
599 /* update got_addr */
600 size_t slot = 0;
601 for(size_t i=0; i < oc->info->n_macho_symbols; i++)
602 if(needGotSlot(oc->info->macho_symbols[i].nlist))
603 oc->info->macho_symbols[i].got_addr
604 = ((uint8_t*)oc->info->got_start)
605 + (slot++ * sizeof(void *));
606 }
607 return EXIT_SUCCESS;
608 }
609
610 void
611 freeGot(ObjectCode * oc) {
612 munmap(oc->info->got_start, oc->info->got_size);
613 oc->info->got_start = NULL;
614 oc->info->got_size = 0;
615 }
616
617 static int
618 relocateSectionAarch64(ObjectCode * oc, Section * section)
619 {
620 if(section->size == 0)
621 return 1;
622 /* at this point, we have:
623 *
624 * - loaded the sections (potentially into non-contiguous memory),
625 * (in ocGetNames_MachO)
626 * - registered exported sybmols
627 * (in ocGetNames_MachO)
628 * - and fixed the nlist[i].n_value for common storage symbols (N_UNDF,
629 * N_EXT and n_value != 0) so that they point into the common storage.
630 * (in ocGetNames_MachO)
631 * - All oc->symbols however should now point at the right place.
632 */
633
634 /* we need to care about the explicit addend */
635 int64_t explicit_addend = 0;
636 size_t nreloc = section->info->macho_section->nreloc;
637
638 for(size_t i = 0; i < nreloc; i++) {
639 MachORelocationInfo * ri = &section->info->relocation_info[i];
640 switch (ri->r_type) {
641 case ARM64_RELOC_UNSIGNED: {
642 MachOSymbol* symbol = &oc->info->macho_symbols[ri->r_symbolnum];
643 int64_t addend = decodeAddend(oc, section, ri);
644 uint64_t value = 0;
645 if(symbol->nlist->n_type & N_EXT) {
646 /* external symbols should be able to be
647 * looked up via the lookupSymbol_ function.
648 * Either through the global symbol hashmap
649 * or asking the system, if not found
650 * in the symbol hashmap
651 */
652 value = (uint64_t)lookupSymbol_((char*)symbol->name);
653 if(!value)
654 barf("Could not lookup symbol: %s!", symbol->name);
655 } else {
656 value = (uint64_t)symbol->addr; // address of the symbol.
657 }
658 encodeAddend(oc, section, ri, value + addend);
659 break;
660 }
661 case ARM64_RELOC_SUBTRACTOR:
662 {
663 MachOSymbol* symbol = &oc->info->macho_symbols[ri->r_symbolnum];
664 // subtractor and unsigned are called in tandem:
665 // first pc <- pc - symbol address (SUBTRACTOR)
666 // second pc <- pc + symbol address (UNSIGNED)
667 // to achieve pc <- pc + target - base.
668 //
669 // the current implementation uses absolute addresses,
670 // which is simpler than trying to do this section
671 // relative, but could more easily lead to overflow.
672 //
673 if(!(i+1 < nreloc)
674 || !(section->info->relocation_info[i+1].r_type
675 == ARM64_RELOC_UNSIGNED))
676 barf("SUBTRACTOR relocation *must* be followed by UNSIGNED relocation.");
677
678 int64_t addend = decodeAddend(oc, section, ri);
679 int64_t value = (uint64_t)symbol->addr;
680 encodeAddend(oc, section, ri, addend - value);
681 break;
682 }
683 case ARM64_RELOC_BRANCH26: {
684 MachOSymbol* symbol = &oc->info->macho_symbols[ri->r_symbolnum];
685
686 // pre-existing addend
687 int64_t addend = decodeAddend(oc, section, ri);
688 // address of the branch (b/bl) instruction.
689 uint64_t pc = (uint64_t)section->start + ri->r_address;
690 uint64_t value = 0;
691 if(symbol->nlist->n_type & N_EXT) {
692 value = (uint64_t)lookupSymbol_((char*)symbol->name);
693 if(!value)
694 barf("Could not lookup symbol: %s!", symbol->name);
695 } else {
696 value = (uint64_t)symbol->addr; // address of the symbol.
697 }
698 if((value - pc + addend) >> (2 + 26)) {
699 /* we need a stub */
700 /* check if we already have that stub */
701 if(findStub(section, (void**)&value)) {
702 /* did not find it. Crete a new stub. */
703 if(makeStub(section, (void**)&value)) {
704 barf("could not find or make stub");
705 }
706 }
707 }
708 encodeAddend(oc, section, ri, value - pc + addend);
709 break;
710 }
711 case ARM64_RELOC_PAGE21:
712 case ARM64_RELOC_GOT_LOAD_PAGE21: {
713 MachOSymbol* symbol = &oc->info->macho_symbols[ri->r_symbolnum];
714 int64_t addend = decodeAddend(oc, section, ri);
715 if(!(explicit_addend == 0 || addend == 0))
716 barf("explicit_addend and addend can't be set at the same time.");
717 uint64_t pc = (uint64_t)section->start + ri->r_address;
718 uint64_t value = (uint64_t)(isGotLoad(ri) ? symbol->got_addr : symbol->addr);
719 encodeAddend(oc, section, ri, ((value + addend + explicit_addend) & (-4096)) - (pc & (-4096)));
720
721 // reset, just in case.
722 explicit_addend = 0;
723 break;
724 }
725 case ARM64_RELOC_PAGEOFF12:
726 case ARM64_RELOC_GOT_LOAD_PAGEOFF12: {
727 MachOSymbol* symbol = &oc->info->macho_symbols[ri->r_symbolnum];
728 int64_t addend = decodeAddend(oc, section, ri);
729 if(!(explicit_addend == 0 || addend == 0))
730 barf("explicit_addend and addend can't be set at the same time.");
731 uint64_t value = (uint64_t)(isGotLoad(ri) ? symbol->got_addr : symbol->addr);
732 encodeAddend(oc, section, ri, 0xFFF & (value + addend + explicit_addend));
733
734 // reset, just in case.
735 explicit_addend = 0;
736 break;
737 }
738 case ARM64_RELOC_ADDEND: {
739 explicit_addend = signExtend(ri->r_symbolnum, 24);
740 if(!(i+1 < nreloc)
741 || !(section->info->relocation_info[i+1].r_type == ARM64_RELOC_PAGE21
742 || section->info->relocation_info[i+1].r_type == ARM64_RELOC_PAGEOFF12))
743 barf("ADDEND relocation *must* be followed by PAGE or PAGEOFF relocation");
744 break;
745 }
746 default: {
747 barf("Relocation of type: %d not (yet) supported!\n", ri->r_type);
748 }
749 }
750 }
751 return 1;
752 }
753
754 #else /* non aarch64_HOST_ARCH branch -- aarch64 doesn't use relocateAddress */
755
756 /*
757 * Try to find the final loaded address for some addres.
758 * Look through all sections, locating the section that
759 * contains the address and compute the absolue address.
760 */
761 static unsigned long
762 relocateAddress(
763 ObjectCode* oc,
764 int nSections,
765 MachOSection* sections,
766 unsigned long address)
767 {
768 int i;
769 IF_DEBUG(linker, debugBelch("relocateAddress: start\n"));
770 for (i = 0; i < nSections; i++)
771 {
772 IF_DEBUG(linker, debugBelch(" relocating address in section %d\n", i));
773 if (sections[i].addr <= address
774 && address < sections[i].addr + sections[i].size)
775 {
776 return (unsigned long)oc->image
777 + sections[i].offset + address - sections[i].addr;
778 }
779 }
780 barf("Invalid Mach-O file:"
781 "Address out of bounds while relocating object file");
782 return 0;
783 }
784
785 #endif /* aarch64_HOST_ARCH */
786
787 #if !defined(aarch64_HOST_ARCH)
788 static int
789 relocateSection(
790 ObjectCode* oc,
791 char *image,
792 MachOSymtabCommand *symLC, MachONList *nlist,
793 int nSections, MachOSection* sections, MachOSection *sect)
794 {
795 MachORelocationInfo *relocs;
796 int i, n;
797
798 IF_DEBUG(linker, debugBelch("relocateSection: start\n"));
799
800 if(!strcmp(sect->sectname,"__la_symbol_ptr"))
801 return 1;
802 else if(!strcmp(sect->sectname,"__nl_symbol_ptr"))
803 return 1;
804 else if(!strcmp(sect->sectname,"__la_sym_ptr2"))
805 return 1;
806 else if(!strcmp(sect->sectname,"__la_sym_ptr3"))
807 return 1;
808
809 n = sect->nreloc;
810 IF_DEBUG(linker, debugBelch("relocateSection: number of relocations: %d\n", n));
811
812 relocs = (MachORelocationInfo*) (image + sect->reloff);
813
814 for(i = 0; i < n; i++)
815 {
816 #if defined(x86_64_HOST_ARCH)
817 MachORelocationInfo *reloc = &relocs[i];
818
819 char *thingPtr = image + sect->offset + reloc->r_address;
820 uint64_t thing;
821 /* We shouldn't need to initialise this, but gcc on OS X 64 bit
822 complains that it may be used uninitialized if we don't */
823 uint64_t value = 0;
824 uint64_t baseValue;
825 int type = reloc->r_type;
826
827 IF_DEBUG(linker, debugBelch("relocateSection: relocation %d\n", i));
828 IF_DEBUG(linker, debugBelch(" : type = %d\n", reloc->r_type));
829 IF_DEBUG(linker, debugBelch(" : address = %d\n", reloc->r_address));
830 IF_DEBUG(linker, debugBelch(" : symbolnum = %u\n", reloc->r_symbolnum));
831 IF_DEBUG(linker, debugBelch(" : pcrel = %d\n", reloc->r_pcrel));
832 IF_DEBUG(linker, debugBelch(" : length = %d\n", reloc->r_length));
833 IF_DEBUG(linker, debugBelch(" : extern = %d\n", reloc->r_extern));
834 IF_DEBUG(linker, debugBelch(" : type = %d\n", reloc->r_type));
835
836 switch(reloc->r_length)
837 {
838 case 0:
839 checkProddableBlock(oc,thingPtr,1);
840 thing = *(uint8_t*)thingPtr;
841 baseValue = (uint64_t)thingPtr + 1;
842 break;
843 case 1:
844 checkProddableBlock(oc,thingPtr,2);
845 thing = *(uint16_t*)thingPtr;
846 baseValue = (uint64_t)thingPtr + 2;
847 break;
848 case 2:
849 checkProddableBlock(oc,thingPtr,4);
850 thing = *(uint32_t*)thingPtr;
851 baseValue = (uint64_t)thingPtr + 4;
852 break;
853 case 3:
854 checkProddableBlock(oc,thingPtr,8);
855 thing = *(uint64_t*)thingPtr;
856 baseValue = (uint64_t)thingPtr + 8;
857 break;
858 default:
859 barf("Unknown size.");
860 }
861
862 IF_DEBUG(linker,
863 debugBelch("relocateSection: length = %d, thing = %" PRId64 ", baseValue = %p\n",
864 reloc->r_length, thing, (char *)baseValue));
865
866 if (type == X86_64_RELOC_GOT
867 || type == X86_64_RELOC_GOT_LOAD)
868 {
869 MachONList *symbol = &nlist[reloc->r_symbolnum];
870 SymbolName* nm = image + symLC->stroff + symbol->n_un.n_strx;
871 SymbolAddr* addr = NULL;
872
873 IF_DEBUG(linker, debugBelch("relocateSection: making jump island for %s, extern = %d, X86_64_RELOC_GOT\n", nm, reloc->r_extern));
874
875 ASSERT(reloc->r_extern);
876 if (reloc->r_extern == 0) {
877 errorBelch("\nrelocateSection: global offset table relocation for symbol with r_extern == 0\n");
878 }
879
880 if (symbol->n_type & N_EXT) {
881 // The external bit is set, meaning the symbol is exported,
882 // and therefore can be looked up in this object module's
883 // symtab, or it is undefined, meaning dlsym must be used
884 // to resolve it.
885
886 addr = lookupSymbol_(nm);
887 IF_DEBUG(linker, debugBelch("relocateSection: looked up %s, "
888 "external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n", nm));
889 IF_DEBUG(linker, debugBelch(" : addr = %p\n", addr));
890
891 if (addr == NULL) {
892 errorBelch("\nlookupSymbol failed in relocateSection (RELOC_GOT)\n"
893 "%s: unknown symbol `%s'", oc->fileName, nm);
894 return 0;
895 }
896 } else {
897 IF_DEBUG(linker, debugBelch("relocateSection: %s is not an exported symbol\n", nm));
898
899 // The symbol is not exported, or defined in another
900 // module, so it must be in the current object module,
901 // at the location given by the section index and
902 // symbol address (symbol->n_value)
903
904 if ((symbol->n_type & N_TYPE) == N_SECT) {
905 addr = (void *)relocateAddress(oc, nSections, sections, symbol->n_value);
906 IF_DEBUG(linker, debugBelch("relocateSection: calculated relocation %p of "
907 "non-external X86_64_RELOC_GOT or X86_64_RELOC_GOT_LOAD\n",
908 (void *)symbol->n_value));
909 IF_DEBUG(linker, debugBelch(" : addr = %p\n", addr));
910 } else {
911 errorBelch("\nrelocateSection: %s is not exported,"
912 " and should be defined in a section, but isn't!\n", nm);
913 }
914 }
915
916 value = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, (unsigned long)addr)->addr;
917
918 type = X86_64_RELOC_SIGNED;
919 }
920 else if (reloc->r_extern)
921 {
922 MachONList *symbol = &nlist[reloc->r_symbolnum];
923 SymbolName* nm = image + symLC->stroff + symbol->n_un.n_strx;
924 SymbolAddr* addr = NULL;
925
926 IF_DEBUG(linker, debugBelch("relocateSection: looking up external symbol %s\n", nm));
927 IF_DEBUG(linker, debugBelch(" : type = %d\n", symbol->n_type));
928 IF_DEBUG(linker, debugBelch(" : sect = %d\n", symbol->n_sect));
929 IF_DEBUG(linker, debugBelch(" : desc = %d\n", symbol->n_desc));
930 IF_DEBUG(linker, debugBelch(" : value = %p\n", (void *)symbol->n_value));
931
932 if ((symbol->n_type & N_TYPE) == N_SECT) {
933 value = relocateAddress(oc, nSections, sections,
934 symbol->n_value);
935 IF_DEBUG(linker, debugBelch("relocateSection, defined external symbol %s, relocated address %p\n", nm, (void *)value));
936 }
937 else {
938 addr = lookupSymbol_(nm);
939 if (addr == NULL)
940 {
941 errorBelch("\nlookupSymbol failed in relocateSection (relocate external)\n"
942 "%s: unknown symbol `%s'", oc->fileName, nm);
943 return 0;
944 }
945
946 value = (uint64_t) addr;
947 IF_DEBUG(linker, debugBelch("relocateSection: external symbol %s, address %p\n", nm, (void *)value));
948 }
949 }
950 else
951 {
952 // If the relocation is not through the global offset table
953 // or external, then set the value to the baseValue. This
954 // will leave displacements into the __const section
955 // unchanged (as they ought to be).
956
957 value = baseValue;
958 }
959
960 IF_DEBUG(linker, debugBelch("relocateSection: value = %p\n", (void *)value));
961
962 if (type == X86_64_RELOC_BRANCH)
963 {
964 if((int32_t)(value - baseValue) != (int64_t)(value - baseValue))
965 {
966 ASSERT(reloc->r_extern);
967 value = (uint64_t) &makeSymbolExtra(oc, reloc->r_symbolnum, value)
968 -> jumpIsland;
969 }
970 ASSERT((int32_t)(value - baseValue) == (int64_t)(value - baseValue));
971 type = X86_64_RELOC_SIGNED;
972 }
973
974 switch(type)
975 {
976 case X86_64_RELOC_UNSIGNED:
977 ASSERT(!reloc->r_pcrel);
978 thing += value;
979 break;
980 case X86_64_RELOC_SIGNED:
981 case X86_64_RELOC_SIGNED_1:
982 case X86_64_RELOC_SIGNED_2:
983 case X86_64_RELOC_SIGNED_4:
984 ASSERT(reloc->r_pcrel);
985 thing += value - baseValue;
986 break;
987 case X86_64_RELOC_SUBTRACTOR:
988 ASSERT(!reloc->r_pcrel);
989 thing -= value;
990 break;
991 default:
992 barf("unknown relocation");
993 }
994
995 switch(reloc->r_length)
996 {
997 case 0:
998 *(uint8_t*)thingPtr = thing;
999 break;
1000 case 1:
1001 *(uint16_t*)thingPtr = thing;
1002 break;
1003 case 2:
1004 *(uint32_t*)thingPtr = thing;
1005 break;
1006 case 3:
1007 *(uint64_t*)thingPtr = thing;
1008 break;
1009 }
1010 #else /* x86_64_HOST_ARCH */
1011 if(relocs[i].r_address & R_SCATTERED)
1012 {
1013 MachOScatteredRelocationInfo *scat =
1014 (MachOScatteredRelocationInfo*) &relocs[i];
1015
1016 if(!scat->r_pcrel)
1017 {
1018 if(scat->r_length == 2)
1019 {
1020 unsigned long word = 0;
1021 unsigned long* wordPtr = (unsigned long*) (image + sect->offset + scat->r_address);
1022
1023 /* In this check we assume that sizeof(unsigned long) = 2 * sizeof(unsigned short)
1024 on powerpc_HOST_ARCH */
1025 checkProddableBlock(oc,wordPtr,sizeof(unsigned long));
1026
1027 // Note on relocation types:
1028 // i386 uses the GENERIC_RELOC_* types,
1029 // while ppc uses special PPC_RELOC_* types.
1030 // *_RELOC_VANILLA and *_RELOC_PAIR have the same value
1031 // in both cases, all others are different.
1032 // Therefore, we use GENERIC_RELOC_VANILLA
1033 // and GENERIC_RELOC_PAIR instead of the PPC variants,
1034 // and use #ifdefs for the other types.
1035
1036 // Step 1: Figure out what the relocated value should be
1037 if (scat->r_type == GENERIC_RELOC_VANILLA) {
1038 word = *wordPtr
1039 + (unsigned long) relocateAddress(oc,
1040 nSections,
1041 sections,
1042 scat->r_value)
1043 - scat->r_value;
1044 }
1045 #if defined(powerpc_HOST_ARCH)
1046 else if(scat->r_type == PPC_RELOC_SECTDIFF
1047 || scat->r_type == PPC_RELOC_LO16_SECTDIFF
1048 || scat->r_type == PPC_RELOC_HI16_SECTDIFF
1049 || scat->r_type == PPC_RELOC_HA16_SECTDIFF
1050 || scat->r_type == PPC_RELOC_LOCAL_SECTDIFF)
1051 #else /* powerpc_HOST_ARCH */
1052 else if(scat->r_type == GENERIC_RELOC_SECTDIFF
1053 || scat->r_type == GENERIC_RELOC_LOCAL_SECTDIFF)
1054 #endif /* powerpc_HOST_ARCH */
1055 {
1056 MachOScatteredRelocationInfo *pair =
1057 (MachOScatteredRelocationInfo*) &relocs[i+1];
1058
1059 if (!pair->r_scattered || pair->r_type != GENERIC_RELOC_PAIR) {
1060 barf("Invalid Mach-O file: "
1061 "RELOC_*_SECTDIFF not followed by RELOC_PAIR");
1062 }
1063
1064 word = (unsigned long)
1065 (relocateAddress(oc, nSections, sections, scat->r_value)
1066 - relocateAddress(oc, nSections, sections, pair->r_value));
1067 i++;
1068 }
1069 #if defined(powerpc_HOST_ARCH)
1070 else if(scat->r_type == PPC_RELOC_HI16
1071 || scat->r_type == PPC_RELOC_LO16
1072 || scat->r_type == PPC_RELOC_HA16
1073 || scat->r_type == PPC_RELOC_LO14)
1074 { // these are generated by label+offset things
1075 MachORelocationInfo *pair = &relocs[i+1];
1076
1077 if ((pair->r_address & R_SCATTERED) || pair->r_type != PPC_RELOC_PAIR) {
1078 barf("Invalid Mach-O file: "
1079 "PPC_RELOC_* not followed by PPC_RELOC_PAIR");
1080 }
1081
1082 if(scat->r_type == PPC_RELOC_LO16)
1083 {
1084 word = ((unsigned short*) wordPtr)[1];
1085 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
1086 }
1087 else if(scat->r_type == PPC_RELOC_LO14)
1088 {
1089 barf("Unsupported Relocation: PPC_RELOC_LO14");
1090 word = ((unsigned short*) wordPtr)[1] & 0xFFFC;
1091 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
1092 }
1093 else if(scat->r_type == PPC_RELOC_HI16)
1094 {
1095 word = ((unsigned short*) wordPtr)[1] << 16;
1096 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF);
1097 }
1098 else if(scat->r_type == PPC_RELOC_HA16)
1099 {
1100 word = ((unsigned short*) wordPtr)[1] << 16;
1101 word += ((short)relocs[i+1].r_address & (short)0xFFFF);
1102 }
1103
1104
1105 word += (unsigned long) relocateAddress(oc, nSections, sections, scat->r_value)
1106 - scat->r_value;
1107
1108 i++;
1109 }
1110 #endif /* powerpc_HOST_ARCH */
1111 else {
1112 barf ("Don't know how to handle this Mach-O "
1113 "scattered relocation entry: "
1114 "object file %s; entry type %ld; "
1115 "address %#lx\n",
1116 OC_INFORMATIVE_FILENAME(oc),
1117 scat->r_type,
1118 scat->r_address);
1119 return 0;
1120 }
1121
1122 #if defined(powerpc_HOST_ARCH)
1123 if(scat->r_type == GENERIC_RELOC_VANILLA
1124 || scat->r_type == PPC_RELOC_SECTDIFF)
1125 #else /* powerpc_HOST_ARCH */
1126 if(scat->r_type == GENERIC_RELOC_VANILLA
1127 || scat->r_type == GENERIC_RELOC_SECTDIFF
1128 || scat->r_type == GENERIC_RELOC_LOCAL_SECTDIFF)
1129 #endif /* powerpc_HOST_ARCH */
1130 {
1131 *wordPtr = word;
1132 }
1133 #if defined(powerpc_HOST_ARCH)
1134 else if (scat->r_type == PPC_RELOC_LO16_SECTDIFF
1135 || scat->r_type == PPC_RELOC_LO16)
1136 {
1137 ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
1138 }
1139 else if (scat->r_type == PPC_RELOC_HI16_SECTDIFF
1140 || scat->r_type == PPC_RELOC_HI16)
1141 {
1142 ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF;
1143 }
1144 else if (scat->r_type == PPC_RELOC_HA16_SECTDIFF
1145 || scat->r_type == PPC_RELOC_HA16)
1146 {
1147 ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
1148 + ((word & (1<<15)) ? 1 : 0);
1149 }
1150 #endif /* powerpc_HOST_ARCH */
1151 }
1152 else
1153 {
1154 barf("Can't handle Mach-O scattered relocation entry "
1155 "with this r_length tag: "
1156 "object file %s; entry type %ld; "
1157 "r_length tag %ld; address %#lx\n",
1158 OC_INFORMATIVE_FILENAME(oc),
1159 scat->r_type,
1160 scat->r_length,
1161 scat->r_address);
1162 return 0;
1163 }
1164 }
1165 else /* scat->r_pcrel */
1166 {
1167 barf("Don't know how to handle *PC-relative* Mach-O "
1168 "scattered relocation entry: "
1169 "object file %s; entry type %ld; address %#lx\n",
1170 OC_INFORMATIVE_FILENAME(oc),
1171 scat->r_type,
1172 scat->r_address);
1173 return 0;
1174 }
1175
1176 }
1177 else /* !(relocs[i].r_address & R_SCATTERED) */
1178 {
1179 MachORelocationInfo *reloc = &relocs[i];
1180 if (reloc->r_pcrel && !reloc->r_extern) {
1181 IF_DEBUG(linker, debugBelch("relocateSection: pc relative but not external, skipping\n"));
1182 continue;
1183 }
1184
1185 if (reloc->r_length == 2) {
1186 unsigned long word = 0;
1187 #if defined(powerpc_HOST_ARCH)
1188 unsigned long jumpIsland = 0;
1189 long offsetToJumpIsland = 0xBADBAD42; // initialise to bad value
1190 // to avoid warning and to catch
1191 // bugs.
1192 #endif /* powerpc_HOST_ARCH */
1193
1194 unsigned long* wordPtr = (unsigned long*) (image + sect->offset + reloc->r_address);
1195
1196 /* In this check we assume that sizeof(unsigned long) = 2 * sizeof(unsigned short)
1197 on powerpc_HOST_ARCH */
1198 checkProddableBlock(oc,wordPtr, sizeof(unsigned long));
1199
1200 if (reloc->r_type == GENERIC_RELOC_VANILLA) {
1201 word = *wordPtr;
1202 }
1203 #if defined(powerpc_HOST_ARCH)
1204 else if (reloc->r_type == PPC_RELOC_LO16) {
1205 word = ((unsigned short*) wordPtr)[1];
1206 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF) << 16;
1207 }
1208 else if (reloc->r_type == PPC_RELOC_HI16) {
1209 word = ((unsigned short*) wordPtr)[1] << 16;
1210 word |= ((unsigned long) relocs[i+1].r_address & 0xFFFF);
1211 }
1212 else if (reloc->r_type == PPC_RELOC_HA16) {
1213 word = ((unsigned short*) wordPtr)[1] << 16;
1214 word += ((short)relocs[i+1].r_address & (short)0xFFFF);
1215 }
1216 else if (reloc->r_type == PPC_RELOC_BR24) {
1217 word = *wordPtr;
1218 word = (word & 0x03FFFFFC) | ((word & 0x02000000) ? 0xFC000000 : 0);
1219 }
1220 #endif /* powerpc_HOST_ARCH */
1221 else {
1222 barf("Can't handle this Mach-O relocation entry "
1223 "(not scattered): "
1224 "object file %s; entry type %ld; address %#lx\n",
1225 OC_INFORMATIVE_FILENAME(oc),
1226 reloc->r_type,
1227 reloc->r_address);
1228 return 0;
1229 }
1230
1231 if (!reloc->r_extern) {
1232 long delta = sections[reloc->r_symbolnum-1].offset
1233 - sections[reloc->r_symbolnum-1].addr
1234 + ((long) image);
1235
1236 word += delta;
1237 }
1238 else {
1239 MachONList *symbol = &nlist[reloc->r_symbolnum];
1240 char *nm = image + symLC->stroff + symbol->n_un.n_strx;
1241 void *symbolAddress = lookupSymbol_(nm);
1242
1243 if (!symbolAddress) {
1244 errorBelch("\nunknown symbol `%s'", nm);
1245 return 0;
1246 }
1247
1248 if (reloc->r_pcrel) {
1249 #if defined(powerpc_HOST_ARCH)
1250 // In the .o file, this should be a relative jump to NULL
1251 // and we'll change it to a relative jump to the symbol
1252 ASSERT(word + reloc->r_address == 0);
1253 jumpIsland = (unsigned long)
1254 &makeSymbolExtra(oc,
1255 reloc->r_symbolnum,
1256 (unsigned long) symbolAddress)
1257 -> jumpIsland;
1258 if (jumpIsland != 0) {
1259 offsetToJumpIsland = word + jumpIsland
1260 - (((long)image) + sect->offset - sect->addr);
1261 }
1262 #endif /* powerpc_HOST_ARCH */
1263 word += (unsigned long) symbolAddress
1264 - (((long)image) + sect->offset - sect->addr);
1265 }
1266 else {
1267 word += (unsigned long) symbolAddress;
1268 }
1269 }
1270
1271 if (reloc->r_type == GENERIC_RELOC_VANILLA) {
1272 *wordPtr = word;
1273 continue;
1274 }
1275 #if defined(powerpc_HOST_ARCH)
1276 else if(reloc->r_type == PPC_RELOC_LO16)
1277 {
1278 ((unsigned short*) wordPtr)[1] = word & 0xFFFF;
1279 i++;
1280 continue;
1281 }
1282 else if(reloc->r_type == PPC_RELOC_HI16)
1283 {
1284 ((unsigned short*) wordPtr)[1] = (word >> 16) & 0xFFFF;
1285 i++;
1286 continue;
1287 }
1288 else if(reloc->r_type == PPC_RELOC_HA16)
1289 {
1290 ((unsigned short*) wordPtr)[1] = ((word >> 16) & 0xFFFF)
1291 + ((word & (1<<15)) ? 1 : 0);
1292 i++;
1293 continue;
1294 }
1295 else if(reloc->r_type == PPC_RELOC_BR24)
1296 {
1297 if ((word & 0x03) != 0) {
1298 barf("%s: unconditional relative branch with a displacement "
1299 "which isn't a multiple of 4 bytes: %#lx",
1300 OC_INFORMATIVE_FILENAME(oc),
1301 word);
1302 }
1303
1304 if((word & 0xFE000000) != 0xFE000000 &&
1305 (word & 0xFE000000) != 0x00000000) {
1306 // The branch offset is too large.
1307 // Therefore, we try to use a jump island.
1308 if (jumpIsland == 0) {
1309 barf("%s: unconditional relative branch out of range: "
1310 "no jump island available: %#lx",
1311 OC_INFORMATIVE_FILENAME(oc),
1312 word);
1313 }
1314
1315 word = offsetToJumpIsland;
1316
1317 if((word & 0xFE000000) != 0xFE000000 &&
1318 (word & 0xFE000000) != 0x00000000) {
1319 barf("%s: unconditional relative branch out of range: "
1320 "jump island out of range: %#lx",
1321 OC_INFORMATIVE_FILENAME(oc),
1322 word);
1323 }
1324 }
1325 *wordPtr = (*wordPtr & 0xFC000003) | (word & 0x03FFFFFC);
1326 continue;
1327 }
1328 #endif /* powerpc_HOST_ARCH */
1329 }
1330 else
1331 {
1332 barf("Can't handle Mach-O relocation entry (not scattered) "
1333 "with this r_length tag: "
1334 "object file %s; entry type %ld; "
1335 "r_length tag %ld; address %#lx\n",
1336 OC_INFORMATIVE_FILENAME(oc),
1337 reloc->r_type,
1338 reloc->r_length,
1339 reloc->r_address);
1340 return 0;
1341 }
1342 }
1343 #endif /* x86_64_HOST_ARCH */
1344 }
1345
1346 IF_DEBUG(linker, debugBelch("relocateSection: done\n"));
1347 return 1;
1348 }
1349 #endif /* aarch64_HOST_ARCH */
1350
1351 /* Note [mmap r+w+x]
1352 * ~~~~~~~~~~~~~~~~~
1353 *
1354 * iOS does not permit to mmap r+w+x, hence wo only mmap r+w, and later change
1355 * to r+x via mprotect. While this could would be nice to have for all hosts
1356 * and not just for iOS, it entail that the rest of the linker code supports
1357 * that, this includes:
1358 *
1359 * - mmap and mprotect need to be available.
1360 * - text and data sections need to be mapped into different pages. Ideally
1361 * the text and data sections would be aggregated, to prevent using a single
1362 * page for every section, however tiny.
1363 * - the relocation code for each object file format / architecture, needs to
1364 * respect the (now) non-contiguousness of the sections.
1365 * - with sections being mapped potentially far apart from each other, it must
1366 * be made sure that the pages are reachable within the architectures
1367 * addressability for relative or absolute access.
1368 */
1369
1370 int
1371 ocGetNames_MachO(ObjectCode* oc)
1372 {
1373 unsigned curSymbol = 0;
1374
1375 unsigned long commonSize = 0;
1376 SymbolAddr* commonStorage = NULL;
1377 unsigned long commonCounter;
1378
1379 IF_DEBUG(linker,debugBelch("ocGetNames_MachO: start\n"));
1380
1381 Section *secArray;
1382 secArray = (Section*)stgCallocBytes(
1383 sizeof(Section),
1384 oc->info->segCmd->nsects,
1385 "ocGetNames_MachO(sections)");
1386
1387 oc->sections = secArray;
1388
1389 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: will load %d sections\n",
1390 oc->n_sections));
1391 for(int i=0; i < oc->n_sections; i++)
1392 {
1393 MachOSection * section = &oc->info->macho_sections[i];
1394
1395 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: section %d\n", i));
1396
1397 if (section->size == 0) {
1398 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: found a zero length section, skipping\n"));
1399 continue;
1400 }
1401
1402 // XXX, use SECTION_TYPE attributes, instead of relying on the name?
1403
1404 SectionKind kind = SECTIONKIND_OTHER;
1405
1406 if (0==strcmp(section->sectname,"__text")) {
1407 kind = SECTIONKIND_CODE_OR_RODATA;
1408 }
1409 else if (0==strcmp(section->sectname,"__const") ||
1410 0==strcmp(section->sectname,"__data") ||
1411 0==strcmp(section->sectname,"__bss") ||
1412 0==strcmp(section->sectname,"__common") ||
1413 0==strcmp(section->sectname,"__mod_init_func")) {
1414 kind = SECTIONKIND_RWDATA;
1415 }
1416
1417 switch(section->flags & SECTION_TYPE) {
1418 #if defined(ios_HOST_OS)
1419 case S_ZEROFILL:
1420 case S_GB_ZEROFILL: {
1421 // See Note [mmap r+w+x]
1422 void * mem = mmap(NULL, section->size,
1423 PROT_READ | PROT_WRITE,
1424 MAP_ANON | MAP_PRIVATE,
1425 -1, 0);
1426 if( mem == MAP_FAILED ) {
1427 barf("failed to mmap allocate memory for zerofill section %d of size %d. errno = %d", i, section->size, errno);
1428 }
1429 addSection(&secArray[i], kind, SECTION_MMAP, mem, section->size,
1430 0, mem, roundUpToPage(section->size));
1431 addProddableBlock(oc, mem, (int)section->size);
1432
1433 secArray[i].info->nstubs = 0;
1434 secArray[i].info->stub_offset = NULL;
1435 secArray[i].info->stub_size = 0;
1436 secArray[i].info->stubs = NULL;
1437
1438 secArray[i].info->macho_section = section;
1439 secArray[i].info->relocation_info
1440 = (MachORelocationInfo*)(oc->image + section->reloff);
1441 break;
1442 }
1443 default: {
1444 // The secion should have a non-zero offset. As the offset is
1445 // relativ to the image, and must be somewhere after the header.
1446 if(section->offset == 0) barf("section with zero offset!");
1447 /* on iOS, we must allocate the code in r+x sections and
1448 * the data in r+w sections, as the system does not allow
1449 * for r+w+x, we must allocate each section in a new page
1450 * range.
1451 *
1452 * copy the sections's memory to some page-aligned place via
1453 * mmap and memcpy. This will later allow us to selectively
1454 * use mprotect on pages with data (r+w) and pages text (r+x).
1455 * We initially start with r+w, so that we can modify the
1456 * pages during relocations, prior to setting it r+x.
1457 */
1458
1459 /* We also need space for stubs. As pages can be assigned
1460 * randomly in the addressable space, we need to keep the
1461 * stubs close to the section. The strategy we are going
1462 * to use is to allocate them right after the section. And
1463 * we are going to be generous and allocare a stub slot
1464 * for each relocation to keep it simple.
1465 */
1466 size_t n_ext_sec_sym = section->nreloc; /* number of relocations
1467 * for this section. Should
1468 * be a good upper bound
1469 */
1470 size_t stub_space = /* eight bytes for the 64 bit address,
1471 * and another eight bytes for the two
1472 * instructions (ldr, br) for each relocation.
1473 */ 16 * n_ext_sec_sym;
1474 // See Note [mmap r+w+x]
1475 void * mem = mmap(NULL, section->size+stub_space,
1476 PROT_READ | PROT_WRITE,
1477 MAP_ANON | MAP_PRIVATE,
1478 -1, 0);
1479 if( mem == MAP_FAILED ) {
1480 barf("failed to mmap allocate memory to load section %d. errno = %d", i, errno );
1481 }
1482 memcpy( mem, oc->image + section->offset, section->size);
1483
1484 addSection(&secArray[i], kind, SECTION_MMAP,
1485 mem, section->size,
1486 0, mem, roundUpToPage(section->size+stub_space));
1487 addProddableBlock(oc, mem, (int)section->size);
1488
1489 secArray[i].info->nstubs = 0;
1490 secArray[i].info->stub_offset = ((uint8_t*)mem) + section->size;
1491 secArray[i].info->stub_size = stub_space;
1492 secArray[i].info->stubs = NULL;
1493
1494 secArray[i].info->macho_section = section;
1495 secArray[i].info->relocation_info
1496 = (MachORelocationInfo*)(oc->image + section->reloff);
1497 break;
1498 }
1499
1500 #else /* any other host */
1501 case S_ZEROFILL:
1502 case S_GB_ZEROFILL: {
1503 char * zeroFillArea;
1504 if (RTS_LINKER_USE_MMAP) {
1505 zeroFillArea = mmapForLinker(section->size, MAP_ANONYMOUS,
1506 -1, 0);
1507 if (zeroFillArea == NULL) return 0;
1508 memset(zeroFillArea, 0, section->size);
1509 }
1510 else {
1511 zeroFillArea = stgCallocBytes(1,section->size,
1512 "ocGetNames_MachO(common symbols)");
1513 }
1514 section->offset = zeroFillArea - oc->image;
1515
1516 addSection(&secArray[i], kind, SECTION_NOMEM,
1517 (void *)(oc->image + section->offset),
1518 section->size,
1519 0, 0, 0);
1520
1521 addProddableBlock(oc,
1522 (void *) (oc->image + section->offset),
1523 section->size);
1524
1525 secArray[i].info->nstubs = 0;
1526 secArray[i].info->stub_offset = NULL;
1527 secArray[i].info->stub_size = 0;
1528 secArray[i].info->stubs = NULL;
1529
1530 secArray[i].info->macho_section = section;
1531 secArray[i].info->relocation_info
1532 = (MachORelocationInfo*)(oc->image + section->reloff);
1533 }
1534 default: {
1535 // just set the pointer to the loaded image.
1536 addSection(&secArray[i], kind, SECTION_NOMEM,
1537 (void *)(oc->image + section->offset),
1538 section->size,
1539 0, 0, 0);
1540
1541 addProddableBlock(oc,
1542 (void *) (oc->image + section->offset),
1543 section->size);
1544
1545 secArray[i].info->nstubs = 0;
1546 secArray[i].info->stub_offset = NULL;
1547 secArray[i].info->stub_size = 0;
1548 secArray[i].info->stubs = NULL;
1549
1550 secArray[i].info->macho_section = section;
1551 secArray[i].info->relocation_info
1552 = (MachORelocationInfo*)(oc->image + section->reloff);
1553 }
1554 #endif
1555 }
1556
1557 }
1558 /* now, as all sections have been loaded, we can resolve the absolute
1559 * address of symbols defined in those sections.
1560 */
1561 for(size_t i=0; i < oc->info->n_macho_symbols; i++) {
1562 MachOSymbol * s = &oc->info->macho_symbols[i];
1563 if( N_SECT == (s->nlist->n_type & N_TYPE) ) {
1564 /* section is given */
1565 uint8_t n = s->nlist->n_sect - 1;
1566 if(0 == oc->info->macho_sections[n].size) {
1567 continue;
1568 }
1569 if(s->nlist->n_sect == NO_SECT)
1570 barf("Symbol with N_SECT type, but no section.");
1571
1572 /* addr <- offset in memory where this section resides
1573 * - address rel. to the image where this section is stored
1574 * + symbol offset in the image
1575 */
1576 s->addr = (uint8_t*)oc->sections[n].start
1577 - oc->info->macho_sections[n].addr
1578 + s->nlist->n_value;
1579 if(NULL == s->addr)
1580 barf("Failed to compute address for symbol %s", s->name);
1581 }
1582 }
1583
1584 // count external symbols defined here
1585 oc->n_symbols = 0;
1586 if (oc->info->symCmd) {
1587 for (size_t i = 0; i < oc->info->n_macho_symbols; i++) {
1588 if (oc->info->nlist[i].n_type & N_STAB) {
1589 ;
1590 }
1591 else if(oc->info->nlist[i].n_type & N_EXT)
1592 {
1593 if((oc->info->nlist[i].n_type & N_TYPE) == N_UNDF
1594 && (oc->info->nlist[i].n_value != 0))
1595 {
1596 commonSize += oc->info->nlist[i].n_value;
1597 oc->n_symbols++;
1598 }
1599 else if((oc->info->nlist[i].n_type & N_TYPE) == N_SECT)
1600 oc->n_symbols++;
1601 }
1602 }
1603 }
1604 /* allocate space for the exported symbols
1605 * in the object code. This is used to track
1606 * which symbols will have to be removed when
1607 * this object code is unloaded
1608 */
1609 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: %d external symbols\n",
1610 oc->n_symbols));
1611 oc->symbols = stgMallocBytes(oc->n_symbols * sizeof(SymbolName*),
1612 "ocGetNames_MachO(oc->symbols)");
1613
1614 if (oc->info->symCmd) {
1615 for (size_t i = 0; i < oc->info->n_macho_symbols; i++) {
1616 if(oc->info->nlist[i].n_type & N_STAB)
1617 ;
1618 else if((oc->info->nlist[i].n_type & N_TYPE) == N_SECT)
1619 {
1620 if(oc->info->nlist[i].n_type & N_EXT)
1621 {
1622 SymbolName* nm = oc->info->macho_symbols[i].name;
1623 if ( (oc->info->nlist[i].n_desc & N_WEAK_DEF)
1624 && lookupSymbol_(nm)) {
1625 // weak definition, and we already have a definition
1626 IF_DEBUG(linker, debugBelch(" weak: %s\n", nm));
1627 }
1628 else
1629 {
1630 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting %s\n", nm));
1631 SymbolAddr* addr = oc->info->macho_symbols[i].addr;
1632
1633 ghciInsertSymbolTable( oc->fileName
1634 , symhash
1635 , nm
1636 , addr
1637 , HS_BOOL_FALSE
1638 , oc);
1639
1640 oc->symbols[curSymbol] = nm;
1641 curSymbol++;
1642 }
1643 }
1644 else
1645 {
1646 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not external, skipping\n"));
1647 }
1648 }
1649 else
1650 {
1651 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: \t...not defined in this section, skipping\n"));
1652 }
1653 }
1654 }
1655
1656 /* setup the common storage */
1657 commonStorage = stgCallocBytes(1,commonSize,"ocGetNames_MachO(common symbols)");
1658 commonCounter = (unsigned long)commonStorage;
1659
1660 if (oc->info->symCmd) {
1661 for (int i = 0; i < oc->n_symbols; i++) {
1662 if((oc->info->nlist[i].n_type & N_TYPE) == N_UNDF
1663 && (oc->info->nlist[i].n_type & N_EXT)
1664 && (oc->info->nlist[i].n_value != 0)) {
1665
1666 SymbolName* nm = oc->info->macho_symbols[i].name;
1667 unsigned long sz = oc->info->nlist[i].n_value;
1668
1669 oc->info->nlist[i].n_value = commonCounter;
1670
1671 /* also set the final address to the macho_symbol */
1672 oc->info->macho_symbols[i].addr = (void*)commonCounter;
1673
1674 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: inserting common symbol: %s\n", nm));
1675 ghciInsertSymbolTable(oc->fileName, symhash, nm,
1676 (void*)commonCounter, HS_BOOL_FALSE, oc);
1677 oc->symbols[curSymbol] = nm;
1678 curSymbol++;
1679
1680 commonCounter += sz;
1681 }
1682 }
1683 }
1684 #if defined(aarch64_HOST_ARCH)
1685 /* Setup the global offset table
1686 * This is for symbols that are external, and not defined here.
1687 * So that we can load their address indirectly.
1688 *
1689 * We will get GOT request for any symbol that is
1690 * - EXT and UNDF
1691 * - EXT and not in the same section.
1692 *
1693 * As sections are not necessarily contiguous and can live
1694 * anywhere in the addressable space. This obviously makes
1695 * sense. However it took me a while to figure this out.
1696 */
1697 makeGot(oc);
1698
1699 /* at this point, macho_symbols, should know the addresses for
1700 * all symbols defined by this object code.
1701 * - those that are defined in sections.
1702 * - those that are undefined, but have a value (common storage).
1703 */
1704 #endif
1705 IF_DEBUG(linker, debugBelch("ocGetNames_MachO: done\n"));
1706 return 1;
1707 }
1708
1709 #if defined(ios_HOST_OS)
1710 bool
1711 ocMprotect_MachO( ObjectCode *oc ) {
1712 for(int i=0; i < oc->n_sections; i++) {
1713 Section * section = &oc->sections[i];
1714 if(section->size == 0) continue;
1715 if( (section->info->macho_section->flags & SECTION_ATTRIBUTES_USR)
1716 == S_ATTR_PURE_INSTRUCTIONS) {
1717 if( 0 != mprotect(section->start,
1718 section->size + section->info->stub_size,
1719 PROT_READ | PROT_EXEC) ) {
1720 barf("mprotect failed! errno = %d", errno);
1721 return false;
1722 }
1723 }
1724 }
1725 return true;
1726 }
1727 #endif
1728
1729 int
1730 ocResolve_MachO(ObjectCode* oc)
1731 {
1732 IF_DEBUG(linker, debugBelch("ocResolve_MachO: start\n"));
1733
1734 if(NULL != oc->info->dsymCmd)
1735 {
1736 unsigned long *indirectSyms
1737 = (unsigned long*) (oc->image + oc->info->dsymCmd->indirectsymoff);
1738
1739 IF_DEBUG(linker, debugBelch("ocResolve_MachO: resolving dsymLC\n"));
1740 for (int i = 0; i < oc->n_sections; i++)
1741 {
1742 const char * sectionName = oc->info->macho_sections[i].sectname;
1743 if( !strcmp(sectionName,"__la_symbol_ptr")
1744 || !strcmp(sectionName,"__la_sym_ptr2")
1745 || !strcmp(sectionName,"__la_sym_ptr3"))
1746 {
1747 if(!resolveImports(oc,&oc->info->macho_sections[i],
1748 indirectSyms))
1749 return 0;
1750 }
1751 else if(!strcmp(sectionName,"__nl_symbol_ptr")
1752 || !strcmp(sectionName,"__pointers"))
1753 {
1754 if(!resolveImports(oc,&oc->info->macho_sections[i],
1755 indirectSyms))
1756 return 0;
1757 }
1758 else if(!strcmp(sectionName,"__jump_table"))
1759 {
1760 if(!resolveImports(oc,&oc->info->macho_sections[i],
1761 indirectSyms))
1762 return 0;
1763 }
1764 else
1765 {
1766 IF_DEBUG(linker, debugBelch("ocResolve_MachO: unknown section\n"));
1767 }
1768 }
1769 }
1770 #if defined(aarch64_HOST_ARCH)
1771 /* fill the GOT table */
1772 for(size_t i = 0; i < oc->info->n_macho_symbols; i++) {
1773 MachOSymbol * symbol = &oc->info->macho_symbols[i];
1774 if(needGotSlot(symbol->nlist)) {
1775 if(N_UNDF == (symbol->nlist->n_type & N_TYPE)) {
1776 /* an undefined symbol. So we need to ensure we
1777 * have the address.
1778 */
1779 if(NULL == symbol->addr) {
1780 symbol->addr = lookupSymbol_((char*)symbol->name);
1781 if(NULL == symbol->addr)
1782 barf("Failed to lookup symbol: %s", symbol->name);
1783 } else {
1784 // we already have the address.
1785 }
1786 } /* else it was defined in the same object,
1787 * just a different section. We should have
1788 * the address as well already
1789 */
1790 if(NULL == symbol->addr) {
1791 barf("Something went wrong!");
1792 }
1793 if(NULL == symbol->got_addr) {
1794 barf("Not good either!");
1795 }
1796 *(uint64_t*)symbol->got_addr = (uint64_t)symbol->addr;
1797 }
1798 }
1799 #endif
1800
1801 for(int i = 0; i < oc->n_sections; i++)
1802 {
1803 IF_DEBUG(linker, debugBelch("ocResolve_MachO: relocating section %d\n", i));
1804
1805 #if defined aarch64_HOST_ARCH
1806 if (!relocateSectionAarch64(oc, &oc->sections[i]))
1807 return 0;
1808 #else
1809 if (!relocateSection(oc,oc->image,oc->info->symCmd,oc->info->nlist,
1810 oc->info->segCmd->nsects,oc->info->macho_sections,
1811 &oc->info->macho_sections[i]))
1812 return 0;
1813 #endif
1814 }
1815 #if defined(ios_HOST_OS)
1816 if(!ocMprotect_MachO ( oc ))
1817 return 0;
1818 #endif
1819
1820 #if defined (powerpc_HOST_ARCH)
1821 ocFlushInstructionCache( oc );
1822 #endif
1823
1824 return 1;
1825 }
1826
1827 int
1828 ocRunInit_MachO ( ObjectCode *oc )
1829 {
1830 if (NULL == oc->info->segCmd) {
1831 barf("ocRunInit_MachO: no segment load command");
1832 }
1833
1834 int argc, envc;
1835 char **argv, **envv;
1836
1837 getProgArgv(&argc, &argv);
1838 getProgEnvv(&envc, &envv);
1839
1840 for (int i = 0; i < oc->n_sections; i++) {
1841 // ToDo: replace this with a proper check for the S_MOD_INIT_FUNC_POINTERS
1842 // flag. We should do this elsewhere in the Mach-O linker code
1843 // too. Note that the system linker will *refuse* to honor
1844 // sections which don't have this flag, so this could cause
1845 // weird behavior divergence (albeit reproducible).
1846 if (0 == strcmp(oc->info->macho_sections[i].sectname,
1847 "__mod_init_func")) {
1848
1849 void *init_startC = oc->sections[i].start;
1850 init_t *init = (init_t*)init_startC;
1851 init_t *init_end = (init_t*)((uint8_t*)init_startC
1852 + oc->sections[i].info->macho_section->size);
1853 for (; init < init_end; init++) {
1854 (*init)(argc, argv, envv);
1855 }
1856 }
1857 }
1858
1859 freeProgEnvv(envc, envv);
1860 return 1;
1861 }
1862
1863 #if defined(powerpc_HOST_ARCH)
1864 /*
1865 * The Mach-O object format uses leading underscores. But not everywhere.
1866 * There is a small number of runtime support functions defined in
1867 * libcc_dynamic.a whose name does not have a leading underscore.
1868 * As a consequence, we can't get their address from C code.
1869 * We have to use inline assembler just to take the address of a function.
1870 * Yuck.
1871 */
1872
1873 extern void* symbolsWithoutUnderscore[];
1874
1875 void
1876 machoInitSymbolsWithoutUnderscore(void)
1877 {
1878 void **p = symbolsWithoutUnderscore;
1879 __asm__ volatile(".globl _symbolsWithoutUnderscore\n.data\n_symbolsWithoutUnderscore:");
1880
1881 #undef SymI_NeedsProto
1882 #undef SymI_NeedsDataProto
1883
1884 #define SymI_NeedsProto(x) \
1885 __asm__ volatile(".long " # x);
1886
1887 #define SymI_NeedsDataProto(x) \
1888 SymI_NeedsProto(x)
1889
1890 RTS_MACHO_NOUNDERLINE_SYMBOLS
1891
1892 __asm__ volatile(".text");
1893
1894 #undef SymI_NeedsProto
1895 #undef SymI_NeedsDataProto
1896
1897 #define SymI_NeedsProto(x) \
1898 ghciInsertSymbolTable("(GHCi built-in symbols)", symhash, #x, *p++, HS_BOOL_FALSE, NULL);
1899
1900 #define SymI_NeedsDataProto(x) \
1901 SymI_NeedsProto(x)
1902
1903 RTS_MACHO_NOUNDERLINE_SYMBOLS
1904
1905 #undef SymI_NeedsProto
1906 #undef SymI_NeedsDataProto
1907 }
1908 #endif
1909
1910 /*
1911 * Figure out by how much to shift the entire Mach-O file in memory
1912 * when loading so that its single segment ends up 16-byte-aligned
1913 */
1914 int
1915 machoGetMisalignment( FILE * f )
1916 {
1917 MachOHeader header;
1918 int misalignment;
1919
1920 {
1921 size_t n = fread(&header, sizeof(header), 1, f);
1922 if (n != 1) {
1923 barf("machoGetMisalignment: can't read the Mach-O header");
1924 }
1925 }
1926 fseek(f, -sizeof(header), SEEK_CUR);
1927
1928 #if defined(x86_64_HOST_ARCH) || defined(powerpc64_HOST_ARCH) \
1929 || defined(aarch64_HOST_ARCH)
1930 if(header.magic != MH_MAGIC_64) {
1931 barf("Bad magic. Expected: %08x, got: %08x.",
1932 MH_MAGIC_64, header.magic);
1933 }
1934 #else
1935 if(header.magic != MH_MAGIC) {
1936 barf("Bad magic. Expected: %08x, got: %08x.",
1937 MH_MAGIC, header.magic);
1938 }
1939 #endif
1940
1941 misalignment = (header.sizeofcmds + sizeof(header))
1942 & 0xF;
1943
1944 return misalignment ? (16 - misalignment) : 0;
1945 }
1946
1947 #endif /* darwin_HOST_OS, ios_HOST_OS */