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