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