Support EVEX encodings of maps 0-15
[nasm.git] / output / outmacho.c
blob892e4e38c8042671a7cda5bb5c5aeebf73856749
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2016 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * outmacho.c output routines for the Netwide Assembler to produce
36 * NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files
39 #include "compiler.h"
41 #include <stdio.h>
42 #include <stdlib.h>
43 #include <string.h>
44 #include <ctype.h>
46 #include "nasm.h"
47 #include "nasmlib.h"
48 #include "saa.h"
49 #include "raa.h"
50 #include "rbtree.h"
51 #include "output/outform.h"
52 #include "output/outlib.h"
54 #if defined(OF_MACHO) || defined(OF_MACHO64)
56 /* Mach-O in-file header structure sizes */
57 #define MACHO_HEADER_SIZE 28
58 #define MACHO_SEGCMD_SIZE 56
59 #define MACHO_SECTCMD_SIZE 68
60 #define MACHO_SYMCMD_SIZE 24
61 #define MACHO_NLIST_SIZE 12
62 #define MACHO_RELINFO_SIZE 8
64 #define MACHO_HEADER64_SIZE 32
65 #define MACHO_SEGCMD64_SIZE 72
66 #define MACHO_SECTCMD64_SIZE 80
67 #define MACHO_NLIST64_SIZE 16
69 /* Mach-O file header values */
70 #define MH_MAGIC 0xfeedface
71 #define MH_MAGIC_64 0xfeedfacf
72 #define CPU_TYPE_I386 7 /* x86 platform */
73 #define CPU_TYPE_X86_64 0x01000007 /* x86-64 platform */
74 #define CPU_SUBTYPE_I386_ALL 3 /* all-x86 compatible */
75 #define MH_OBJECT 0x1 /* object file */
77 /* Mach-O load commands */
78 #define LC_SEGMENT 0x1 /* 32-bit segment load cmd */
79 #define LC_SEGMENT_64 0x19 /* 64-bit segment load cmd */
80 #define LC_SYMTAB 0x2 /* symbol table load command */
82 /* Mach-O relocations numbers */
84 /* Generic relocs, used by i386 Mach-O */
85 #define GENERIC_RELOC_VANILLA 0 /* Generic relocation */
86 #define GENERIC_RELOC_TLV 5 /* Thread local */
88 #define X86_64_RELOC_UNSIGNED 0 /* Absolute address */
89 #define X86_64_RELOC_SIGNED 1 /* Signed 32-bit disp */
90 #define X86_64_RELOC_BRANCH 2 /* CALL/JMP with 32-bit disp */
91 #define X86_64_RELOC_GOT_LOAD 3 /* MOVQ of GOT entry */
92 #define X86_64_RELOC_GOT 4 /* Different GOT entry */
93 #define X86_64_RELOC_SUBTRACTOR 5 /* Subtracting two symbols */
94 #define X86_64_RELOC_SIGNED_1 6 /* SIGNED with -1 addend */
95 #define X86_64_RELOC_SIGNED_2 7 /* SIGNED with -2 addend */
96 #define X86_64_RELOC_SIGNED_4 8 /* SIGNED with -4 addend */
97 #define X86_64_RELOC_TLV 9 /* Thread local */
99 /* Mach-O VM permission constants */
100 #define VM_PROT_NONE (0x00)
101 #define VM_PROT_READ (0x01)
102 #define VM_PROT_WRITE (0x02)
103 #define VM_PROT_EXECUTE (0x04)
105 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
106 #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
108 /* Our internal relocation types */
109 enum reltype {
110 RL_ABS, /* Absolute relocation */
111 RL_REL, /* Relative relocation */
112 RL_TLV, /* Thread local */
113 RL_BRANCH, /* Relative direct branch */
114 RL_SUB, /* X86_64_RELOC_SUBTRACT */
115 RL_GOT, /* X86_64_RELOC_GOT */
116 RL_GOTLOAD /* X86_64_RELOC_GOT_LOAD */
118 #define RL_MAX_32 RL_TLV
119 #define RL_MAX_64 RL_GOTLOAD
121 struct macho_fmt {
122 uint32_t ptrsize; /* Pointer size in bytes */
123 uint32_t mh_magic; /* Which magic number to use */
124 uint32_t cpu_type; /* Which CPU type */
125 uint32_t lc_segment; /* Which segment load command */
126 uint32_t header_size; /* Header size */
127 uint32_t segcmd_size; /* Segment command size */
128 uint32_t sectcmd_size; /* Section command size */
129 uint32_t nlist_size; /* Nlist (symbol) size */
130 enum reltype maxreltype; /* Maximum entry in enum reltype permitted */
131 uint32_t reloc_abs; /* Absolute relocation type */
132 uint32_t reloc_rel; /* Relative relocation type */
133 uint32_t reloc_tlv; /* Thread local relocation type */
136 static struct macho_fmt fmt;
138 static void fwriteptr(uint64_t data, FILE * fp)
140 fwriteaddr(data, fmt.ptrsize, fp);
143 struct section {
144 /* nasm internal data */
145 struct section *next;
146 struct SAA *data;
147 int32_t index;
148 int32_t fileindex;
149 struct reloc *relocs;
150 struct rbtree *gsyms; /* Global symbols in section */
151 int align;
152 bool by_name; /* This section was specified by full MachO name */
154 /* data that goes into the file */
155 char sectname[16]; /* what this section is called */
156 char segname[16]; /* segment this section will be in */
157 uint64_t addr; /* in-memory address (subject to alignment) */
158 uint64_t size; /* in-memory and -file size */
159 uint64_t offset; /* in-file offset */
160 uint32_t pad; /* padding bytes before section */
161 uint32_t nreloc; /* relocation entry count */
162 uint32_t flags; /* type and attributes (masked) */
163 uint32_t extreloc; /* external relocations */
166 #define SECTION_TYPE 0x000000ff /* section type mask */
168 #define S_REGULAR (0x0) /* standard section */
169 #define S_ZEROFILL (0x1) /* zerofill, in-memory only */
171 #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
172 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
173 machine instructions */
174 #define S_ATTR_EXT_RELOC 0x00000200 /* section has external
175 relocation entries */
176 #define S_ATTR_LOC_RELOC 0x00000100 /* section has local
177 relocation entries */
178 #define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section uses pure
179 machine instructions */
181 /* Fake section for absolute symbols, *not* part of the section linked list */
182 static struct section absolute_sect;
184 static const struct sectmap {
185 const char *nasmsect;
186 const char *segname;
187 const char *sectname;
188 const int32_t flags;
189 } sectmap[] = {
190 {".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS},
191 {".data", "__DATA", "__data", S_REGULAR},
192 {".rodata", "__DATA", "__const", S_REGULAR},
193 {".bss", "__DATA", "__bss", S_ZEROFILL},
194 {NULL, NULL, NULL, 0}
197 struct reloc {
198 /* nasm internal data */
199 struct reloc *next;
201 /* data that goes into the file */
202 int32_t addr; /* op's offset in section */
203 uint32_t snum:24, /* contains symbol index if
204 ** ext otherwise in-file
205 ** section number */
206 pcrel:1, /* relative relocation */
207 length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */
208 ext:1, /* external symbol referenced */
209 type:4; /* reloc type */
212 #define R_ABS 0 /* absolute relocation */
213 #define R_SCATTERED 0x80000000 /* reloc entry is scattered if
214 ** highest bit == 1 */
216 struct symbol {
217 /* nasm internal data */
218 struct rbtree symv; /* Global symbol rbtree; "key" contains the
219 symbol offset. */
220 struct symbol *next; /* next symbol in the list */
221 char *name; /* name of this symbol */
222 int32_t initial_snum; /* symbol number used above in reloc */
223 int32_t snum; /* true snum for reloc */
225 /* data that goes into the file */
226 uint32_t strx; /* string table index */
227 uint8_t type; /* symbol type */
228 uint8_t sect; /* NO_SECT or section number */
229 uint16_t desc; /* for stab debugging, 0 for us */
232 /* symbol type bits */
233 #define N_EXT 0x01 /* global or external symbol */
235 #define N_UNDF 0x0 /* undefined symbol | n_sect == */
236 #define N_ABS 0x2 /* absolute symbol | NO_SECT */
237 #define N_SECT 0xe /* defined symbol, n_sect holds
238 ** section number */
240 #define N_TYPE 0x0e /* type bit mask */
242 #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
244 /* special section number values */
245 #define NO_SECT 0 /* no section, invalid */
246 #define MAX_SECT 255 /* maximum number of sections */
248 static struct section *sects, **sectstail, **sectstab;
249 static struct symbol *syms, **symstail;
250 static uint32_t nsyms;
252 /* These variables are set by macho_layout_symbols() to organize
253 the symbol table and string table in order the dynamic linker
254 expects. They are then used in macho_write() to put out the
255 symbols and strings in that order.
257 The order of the symbol table is:
258 local symbols
259 defined external symbols (sorted by name)
260 undefined external symbols (sorted by name)
262 The order of the string table is:
263 strings for external symbols
264 strings for local symbols
266 static uint32_t ilocalsym = 0;
267 static uint32_t iextdefsym = 0;
268 static uint32_t iundefsym = 0;
269 static uint32_t nlocalsym;
270 static uint32_t nextdefsym;
271 static uint32_t nundefsym;
272 static struct symbol **extdefsyms = NULL;
273 static struct symbol **undefsyms = NULL;
275 static struct RAA *extsyms;
276 static struct SAA *strs;
277 static uint32_t strslen;
279 /* Global file information. This should be cleaned up into either
280 a structure or as function arguments. */
281 static uint32_t head_ncmds = 0;
282 static uint32_t head_sizeofcmds = 0;
283 static uint64_t seg_filesize = 0;
284 static uint64_t seg_vmsize = 0;
285 static uint32_t seg_nsects = 0;
286 static uint64_t rel_padcnt = 0;
288 #define xstrncpy(xdst, xsrc) \
289 memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \
290 strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \
291 xdst[sizeof(xdst) - 1] = '\0'; /* proper null-termination */
293 #define alignint32_t(x) \
294 ALIGN(x, sizeof(int32_t)) /* align x to int32_t boundary */
296 #define alignint64_t(x) \
297 ALIGN(x, sizeof(int64_t)) /* align x to int64_t boundary */
299 #define alignptr(x) \
300 ALIGN(x, fmt.ptrsize) /* align x to output format width */
302 static struct section *get_section_by_name(const char *segname,
303 const char *sectname)
305 struct section *s;
307 for (s = sects; s != NULL; s = s->next)
308 if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname))
309 break;
311 return s;
314 static struct section *get_section_by_index(const int32_t index)
316 struct section *s;
318 for (s = sects; s != NULL; s = s->next)
319 if (index == s->index)
320 break;
322 return s;
326 * Special section numbers which are used to define Mach-O special
327 * symbols, which can be used with WRT to provide PIC relocation
328 * types.
330 static int32_t macho_tlvp_sect;
331 static int32_t macho_gotpcrel_sect;
333 static void macho_init(void)
335 sects = NULL;
336 sectstail = &sects;
338 /* Fake section for absolute symbols */
339 absolute_sect.index = NO_SEG;
341 syms = NULL;
342 symstail = &syms;
343 nsyms = 0;
344 nlocalsym = 0;
345 nextdefsym = 0;
346 nundefsym = 0;
348 extsyms = raa_init();
349 strs = saa_init(1L);
351 /* string table starts with a zero byte so index 0 is an empty string */
352 saa_wbytes(strs, zero_buffer, 1);
353 strslen = 1;
355 /* add special symbol for TLVP */
356 macho_tlvp_sect = seg_alloc() + 1;
357 define_label("..tlvp", macho_tlvp_sect, 0L, NULL, false, false);
361 static void sect_write(struct section *sect,
362 const uint8_t *data, uint32_t len)
364 saa_wbytes(sect->data, data, len);
365 sect->size += len;
369 * Find a suitable global symbol for a ..gotpcrel or ..tlvp reference
371 static struct symbol *macho_find_gsym(struct section *s,
372 uint64_t offset, bool exact)
374 struct rbtree *srb;
376 srb = rb_search(s->gsyms, offset);
378 if (!srb || (exact && srb->key != offset)) {
379 nasm_error(ERR_NONFATAL, "unable to find a suitable %s symbol"
380 " for this reference",
381 s == &absolute_sect ? "absolute" : "global");
382 return NULL;
385 return container_of(srb, struct symbol, symv);
388 static int64_t add_reloc(struct section *sect, int32_t section,
389 int64_t offset,
390 enum reltype reltype, int bytes)
392 struct reloc *r;
393 struct section *s;
394 int32_t fi;
395 int64_t adjust;
397 /* Double check this is a valid relocation type for this platform */
398 nasm_assert(reltype <= fmt.maxreltype);
400 /* the current end of the section will be the symbol's address for
401 ** now, might have to be fixed by macho_fixup_relocs() later on. make
402 ** sure we don't make the symbol scattered by setting the highest
403 ** bit by accident */
404 r = nasm_malloc(sizeof(struct reloc));
405 r->addr = sect->size & ~R_SCATTERED;
406 r->ext = 1;
407 adjust = bytes;
409 /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
410 r->length = ilog2_32(bytes);
412 /* set default relocation values */
413 r->type = fmt.reloc_abs;
414 r->pcrel = 0;
415 r->snum = R_ABS;
417 s = NULL;
418 if (section != NO_SEG)
419 s = get_section_by_index(section);
420 fi = s ? s->fileindex : NO_SECT;
422 /* absolute relocation */
423 switch (reltype) {
424 case RL_ABS:
425 if (section == NO_SEG) {
426 /* absolute (can this even happen?) */
427 r->ext = 0;
428 r->snum = R_ABS;
429 } else if (fi == NO_SECT) {
430 /* external */
431 r->snum = raa_read(extsyms, section);
432 } else {
433 /* local */
434 r->ext = 0;
435 r->snum = fi;
436 adjust = -sect->size;
438 break;
440 case RL_REL:
441 case RL_BRANCH:
442 r->type = fmt.reloc_rel;
443 r->pcrel = 1;
444 if (section == NO_SEG) {
445 /* absolute - seems to produce garbage no matter what */
446 nasm_error(ERR_NONFATAL, "Mach-O does not support relative "
447 "references to absolute addresses");
448 goto bail;
449 #if 0
450 /* This "seems" to be how it ought to work... */
452 struct symbol *sym = macho_find_gsym(&absolute_sect,
453 offset, false);
454 if (!sym)
455 goto bail;
457 sect->extreloc = 1;
458 r->snum = NO_SECT;
459 adjust = -sect->size;
460 #endif
461 } else if (fi == NO_SECT) {
462 /* external */
463 sect->extreloc = 1;
464 r->snum = raa_read(extsyms, section);
465 if (reltype == RL_BRANCH)
466 r->type = X86_64_RELOC_BRANCH;
467 } else {
468 /* local */
469 r->ext = 0;
470 r->snum = fi;
471 adjust = -sect->size;
473 break;
475 case RL_SUB:
476 r->pcrel = 0;
477 r->type = X86_64_RELOC_SUBTRACTOR;
478 break;
480 case RL_GOT:
481 r->type = X86_64_RELOC_GOT;
482 goto needsym;
484 case RL_GOTLOAD:
485 r->type = X86_64_RELOC_GOT_LOAD;
486 goto needsym;
488 case RL_TLV:
489 r->type = fmt.reloc_tlv;
490 goto needsym;
492 needsym:
493 r->pcrel = 1;
494 if (section == NO_SEG) {
495 nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT");
496 } else if (fi == NO_SECT) {
497 /* external */
498 r->snum = raa_read(extsyms, section);
499 } else {
500 /* internal */
501 struct symbol *sym = macho_find_gsym(s, offset, reltype != RL_TLV);
502 if (!sym)
503 goto bail;
504 r->snum = sym->initial_snum;
506 break;
509 /* NeXT as puts relocs in reversed order (address-wise) into the
510 ** files, so we do the same, doesn't seem to make much of a
511 ** difference either way */
512 r->next = sect->relocs;
513 sect->relocs = r;
514 if (r->ext)
515 sect->extreloc = 1;
516 ++sect->nreloc;
518 return adjust;
520 bail:
521 nasm_free(r);
522 return 0;
525 static void macho_output(int32_t secto, const void *data,
526 enum out_type type, uint64_t size,
527 int32_t section, int32_t wrt)
529 struct section *s;
530 int64_t addr, offset;
531 uint8_t mydata[16], *p;
532 bool is_bss;
533 enum reltype reltype;
535 if (secto == NO_SEG) {
536 if (type != OUT_RESERVE)
537 nasm_error(ERR_NONFATAL, "attempt to assemble code in "
538 "[ABSOLUTE] space");
539 return;
542 s = get_section_by_index(secto);
544 if (s == NULL) {
545 nasm_error(ERR_WARNING, "attempt to assemble code in"
546 " section %d: defaulting to `.text'", secto);
547 s = get_section_by_name("__TEXT", "__text");
549 /* should never happen */
550 if (s == NULL)
551 nasm_panic(0, "text section not found");
554 is_bss = (s->flags & SECTION_TYPE) == S_ZEROFILL;
556 if (is_bss && type != OUT_RESERVE) {
557 nasm_error(ERR_WARNING, "attempt to initialize memory in "
558 "BSS section: ignored");
559 s->size += realsize(type, size);
560 return;
563 memset(mydata, 0, sizeof(mydata));
565 switch (type) {
566 case OUT_RESERVE:
567 if (!is_bss) {
568 nasm_error(ERR_WARNING, "uninitialized space declared in"
569 " %s,%s section: zeroing", s->segname, s->sectname);
571 sect_write(s, NULL, size);
572 } else
573 s->size += size;
575 break;
577 case OUT_RAWDATA:
578 if (section != NO_SEG)
579 nasm_panic(0, "OUT_RAWDATA with other than NO_SEG");
581 sect_write(s, data, size);
582 break;
584 case OUT_ADDRESS:
586 int asize = abs((int)size);
588 addr = *(int64_t *)data;
589 if (section != NO_SEG) {
590 if (section % 2) {
591 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
592 " section base references");
593 } else if (wrt == NO_SEG) {
594 if (fmt.ptrsize == 8 && asize != 8) {
595 nasm_error(ERR_NONFATAL,
596 "Mach-O 64-bit format does not support"
597 " 32-bit absolute addresses");
598 } else {
599 add_reloc(s, section, addr, RL_ABS, asize);
601 } else {
602 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
603 " this use of WRT");
607 p = mydata;
608 WRITEADDR(p, addr, asize);
609 sect_write(s, mydata, asize);
610 break;
613 case OUT_REL2ADR:
614 nasm_assert(section != secto);
616 p = mydata;
617 offset = *(int64_t *)data;
618 addr = offset - size;
620 if (section != NO_SEG && section % 2) {
621 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
622 " section base references");
623 } else if (fmt.ptrsize == 8) {
624 nasm_error(ERR_NONFATAL, "Unsupported non-32-bit"
625 " Macho-O relocation [2]");
626 } else if (wrt != NO_SEG) {
627 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
628 " this use of WRT");
629 wrt = NO_SEG; /* we can at least _try_ to continue */
630 } else {
631 addr += add_reloc(s, section, addr+size, RL_REL, 2);
634 WRITESHORT(p, addr);
635 sect_write(s, mydata, 2);
636 break;
638 case OUT_REL4ADR:
639 nasm_assert(section != secto);
641 p = mydata;
642 offset = *(int64_t *)data;
643 addr = offset - size;
644 reltype = RL_REL;
646 if (section != NO_SEG && section % 2) {
647 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
648 " section base references");
649 } else if (wrt == NO_SEG) {
650 if (fmt.ptrsize == 8 &&
651 (s->flags & S_ATTR_SOME_INSTRUCTIONS)) {
652 uint8_t opcode[2];
654 opcode[0] = opcode[1] = 0;
656 /* HACK: Retrieve instruction opcode */
657 if (likely(s->data->datalen >= 2)) {
658 saa_fread(s->data, s->data->datalen-2, opcode, 2);
659 } else if (s->data->datalen == 1) {
660 saa_fread(s->data, 0, opcode+1, 1);
663 if ((opcode[0] != 0x0f && (opcode[1] & 0xfe) == 0xe8) ||
664 (opcode[0] == 0x0f && (opcode[1] & 0xf0) == 0x80)) {
665 /* Direct call, jmp, or jcc */
666 reltype = RL_BRANCH;
669 } else if (wrt == macho_gotpcrel_sect) {
670 reltype = RL_GOT;
672 if ((s->flags & S_ATTR_SOME_INSTRUCTIONS) &&
673 s->data->datalen >= 3) {
674 uint8_t gotload[3];
676 /* HACK: Retrieve instruction opcode */
677 saa_fread(s->data, s->data->datalen-3, gotload, 3);
678 if ((gotload[0] & 0xf8) == 0x48 &&
679 gotload[1] == 0x8b &&
680 (gotload[2] & 0307) == 0005) {
681 /* movq <reg>,[rel sym wrt ..gotpcrel] */
682 reltype = RL_GOTLOAD;
685 } else if (wrt == macho_tlvp_sect) {
686 reltype = RL_TLV;
687 } else {
688 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
689 " this use of WRT");
690 /* continue with RL_REL */
693 addr += add_reloc(s, section, offset, reltype, 4);
694 WRITELONG(p, addr);
695 sect_write(s, mydata, 4);
696 break;
698 default:
699 nasm_error(ERR_NONFATAL, "Unrepresentable relocation in Mach-O");
700 break;
704 static int32_t macho_section(char *name, int pass, int *bits)
706 char *sectionAttributes;
707 const struct sectmap *sm;
708 struct section *s;
709 const char *section, *segment;
710 uint32_t flags;
711 char *currentAttribute;
712 char *comma;
713 bool new_seg;
715 (void)pass;
717 /* Default to the appropriate number of bits. */
718 if (!name) {
719 *bits = fmt.ptrsize << 3;
720 name = ".text";
721 sectionAttributes = NULL;
722 } else {
723 sectionAttributes = name;
724 name = nasm_strsep(&sectionAttributes, " \t");
727 section = segment = NULL;
728 flags = 0;
730 comma = strchr(name, ',');
731 if (comma) {
732 int len;
734 *comma = '\0';
735 segment = name;
736 section = comma+1;
738 len = strlen(segment);
739 if (len == 0) {
740 nasm_error(ERR_NONFATAL, "empty segment name\n");
741 } else if (len >= 16) {
742 nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment);
745 len = strlen(section);
746 if (len == 0) {
747 nasm_error(ERR_NONFATAL, "empty section name\n");
748 } else if (len >= 16) {
749 nasm_error(ERR_NONFATAL, "section name %s too long\n", section);
752 if (!strcmp(section, "__text")) {
753 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
754 S_ATTR_PURE_INSTRUCTIONS;
755 } else if (!strcmp(section, "__bss")) {
756 flags = S_ZEROFILL;
757 } else {
758 flags = S_REGULAR;
760 } else {
761 for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
762 /* make lookup into section name translation table */
763 if (!strcmp(name, sm->nasmsect)) {
764 segment = sm->segname;
765 section = sm->sectname;
766 flags = sm->flags;
767 goto found;
770 nasm_error(ERR_NONFATAL, "unknown section name\n");
771 return NO_SEG;
774 found:
775 /* try to find section with that name */
776 s = get_section_by_name(segment, section);
778 /* create it if it doesn't exist yet */
779 if (!s) {
780 new_seg = true;
782 s = *sectstail = nasm_zalloc(sizeof(struct section));
783 sectstail = &s->next;
785 s->data = saa_init(1L);
786 s->index = seg_alloc();
787 s->fileindex = ++seg_nsects;
788 s->align = -1;
789 s->pad = -1;
790 s->offset = -1;
791 s->by_name = false;
793 xstrncpy(s->segname, segment);
794 xstrncpy(s->sectname, section);
795 s->size = 0;
796 s->nreloc = 0;
797 s->flags = flags;
798 } else {
799 new_seg = false;
802 if (comma)
803 *comma = ','; /* Restore comma */
805 s->by_name = s->by_name || comma; /* Was specified by name */
807 flags = (uint32_t)-1;
809 while ((NULL != sectionAttributes)
810 && (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
811 if (0 != *currentAttribute) {
812 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
813 char *end;
814 int newAlignment, value;
816 value = strtoul(currentAttribute + 6, (char**)&end, 0);
817 newAlignment = alignlog2_32(value);
819 if (0 != *end) {
820 nasm_error(ERR_NONFATAL,
821 "unknown or missing alignment value \"%s\" "
822 "specified for section \"%s\"",
823 currentAttribute + 6,
824 name);
825 } else if (0 > newAlignment) {
826 nasm_error(ERR_NONFATAL,
827 "alignment of %d (for section \"%s\") is not "
828 "a power of two",
829 value,
830 name);
833 if (s->align < newAlignment)
834 s->align = newAlignment;
835 } else if (!nasm_stricmp("data", currentAttribute)) {
836 flags = S_REGULAR;
837 } else if (!nasm_stricmp("code", currentAttribute) ||
838 !nasm_stricmp("text", currentAttribute)) {
839 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
840 S_ATTR_PURE_INSTRUCTIONS;
841 } else if (!nasm_stricmp("mixed", currentAttribute)) {
842 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS;
843 } else if (!nasm_stricmp("bss", currentAttribute)) {
844 flags = S_ZEROFILL;
845 } else {
846 nasm_error(ERR_NONFATAL,
847 "unknown section attribute %s for section %s",
848 currentAttribute,
849 name);
853 if (flags != (uint32_t)-1) {
854 if (!new_seg && s->flags != flags) {
855 nasm_error(ERR_NONFATAL,
856 "inconsistent section attributes for section %s\n",
857 name);
858 } else {
859 s->flags = flags;
864 return s->index;
867 static void macho_symdef(char *name, int32_t section, int64_t offset,
868 int is_global, char *special)
870 struct symbol *sym;
872 if (special) {
873 nasm_error(ERR_NONFATAL, "The Mach-O output format does "
874 "not support any special symbol types");
875 return;
878 if (is_global == 3) {
879 nasm_error(ERR_NONFATAL, "The Mach-O format does not "
880 "(yet) support forward reference fixups.");
881 return;
884 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
886 * This is a NASM special symbol. We never allow it into
887 * the Macho-O symbol table, even if it's a valid one. If it
888 * _isn't_ a valid one, we should barf immediately.
890 if (strcmp(name, "..gotpcrel") && strcmp(name, "..tlvp"))
891 nasm_error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
892 return;
895 sym = *symstail = nasm_zalloc(sizeof(struct symbol));
896 sym->next = NULL;
897 symstail = &sym->next;
899 sym->name = name;
900 sym->strx = strslen;
901 sym->type = 0;
902 sym->desc = 0;
903 sym->symv.key = offset;
904 sym->initial_snum = -1;
906 /* external and common symbols get N_EXT */
907 if (is_global != 0) {
908 sym->type |= N_EXT;
911 if (section == NO_SEG) {
912 /* symbols in no section get absolute */
913 sym->type |= N_ABS;
914 sym->sect = NO_SECT;
916 /* all absolute symbols are available to use as references */
917 absolute_sect.gsyms = rb_insert(absolute_sect.gsyms, &sym->symv);
918 } else {
919 struct section *s = get_section_by_index(section);
921 sym->type |= N_SECT;
923 /* get the in-file index of the section the symbol was defined in */
924 sym->sect = s ? s->fileindex : NO_SECT;
926 /* track the initially allocated symbol number for use in future fix-ups */
927 sym->initial_snum = nsyms;
929 if (!s) {
930 /* remember symbol number of references to external
931 ** symbols, this works because every external symbol gets
932 ** its own section number allocated internally by nasm and
933 ** can so be used as a key */
934 extsyms = raa_write(extsyms, section, nsyms);
936 switch (is_global) {
937 case 1:
938 case 2:
939 /* there isn't actually a difference between global
940 ** and common symbols, both even have their size in
941 ** sym->symv.key */
942 sym->type = N_EXT;
943 break;
945 default:
946 /* give an error on unfound section if it's not an
947 ** external or common symbol (assemble_file() does a
948 ** seg_alloc() on every call for them) */
949 nasm_panic(0, "in-file index for section %d not found, is_global = %d", section, is_global);
950 break;
952 } else if (is_global) {
953 s->gsyms = rb_insert(s->gsyms, &sym->symv);
956 ++nsyms;
959 static void macho_sectalign(int32_t seg, unsigned int value)
961 struct section *s;
962 int align;
964 nasm_assert(!(seg & 1));
966 s = get_section_by_index(seg);
968 if (!s || !is_power2(value))
969 return;
971 align = alignlog2_32(value);
972 if (s->align < align)
973 s->align = align;
976 static int32_t macho_segbase(int32_t section)
978 return section;
981 static void macho_filename(char *inname, char *outname)
983 standard_extension(inname, outname, ".o");
986 extern macros_t macho_stdmac[];
988 /* Comparison function for qsort symbol layout. */
989 static int layout_compare (const struct symbol **s1,
990 const struct symbol **s2)
992 return (strcmp ((*s1)->name, (*s2)->name));
995 /* The native assembler does a few things in a similar function
997 * Remove temporary labels
998 * Sort symbols according to local, external, undefined (by name)
999 * Order the string table
1001 We do not remove temporary labels right now.
1003 numsyms is the total number of symbols we have. strtabsize is the
1004 number entries in the string table. */
1006 static void macho_layout_symbols (uint32_t *numsyms,
1007 uint32_t *strtabsize)
1009 struct symbol *sym, **symp;
1010 uint32_t i,j;
1012 *numsyms = 0;
1013 *strtabsize = sizeof (char);
1015 symp = &syms;
1017 while ((sym = *symp)) {
1018 /* Undefined symbols are now external. */
1019 if (sym->type == N_UNDF)
1020 sym->type |= N_EXT;
1022 if ((sym->type & N_EXT) == 0) {
1023 sym->snum = *numsyms;
1024 *numsyms = *numsyms + 1;
1025 nlocalsym++;
1027 else {
1028 if ((sym->type & N_TYPE) != N_UNDF) {
1029 nextdefsym++;
1030 } else {
1031 nundefsym++;
1034 /* If we handle debug info we'll want
1035 to check for it here instead of just
1036 adding the symbol to the string table. */
1037 sym->strx = *strtabsize;
1038 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
1039 *strtabsize += strlen(sym->name) + 1;
1041 symp = &(sym->next);
1044 /* Next, sort the symbols. Most of this code is a direct translation from
1045 the Apple cctools symbol layout. We need to keep compatibility with that. */
1046 /* Set the indexes for symbol groups into the symbol table */
1047 ilocalsym = 0;
1048 iextdefsym = nlocalsym;
1049 iundefsym = nlocalsym + nextdefsym;
1051 /* allocate arrays for sorting externals by name */
1052 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
1053 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
1055 i = 0;
1056 j = 0;
1058 symp = &syms;
1060 while ((sym = *symp)) {
1062 if((sym->type & N_EXT) == 0) {
1063 sym->strx = *strtabsize;
1064 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
1065 *strtabsize += strlen(sym->name) + 1;
1067 else {
1068 if((sym->type & N_TYPE) != N_UNDF) {
1069 extdefsyms[i++] = sym;
1070 } else {
1071 undefsyms[j++] = sym;
1074 symp = &(sym->next);
1077 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
1078 (int (*)(const void *, const void *))layout_compare);
1079 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
1080 (int (*)(const void *, const void *))layout_compare);
1082 for(i = 0; i < nextdefsym; i++) {
1083 extdefsyms[i]->snum = *numsyms;
1084 *numsyms += 1;
1086 for(j = 0; j < nundefsym; j++) {
1087 undefsyms[j]->snum = *numsyms;
1088 *numsyms += 1;
1092 /* Calculate some values we'll need for writing later. */
1094 static void macho_calculate_sizes (void)
1096 struct section *s;
1097 int fi;
1099 /* count sections and calculate in-memory and in-file offsets */
1100 for (s = sects; s != NULL; s = s->next) {
1101 uint64_t newaddr;
1103 /* recalculate segment address based on alignment and vm size */
1104 s->addr = seg_vmsize;
1106 /* we need section alignment to calculate final section address */
1107 if (s->align == -1)
1108 s->align = DEFAULT_SECTION_ALIGNMENT;
1110 newaddr = ALIGN(s->addr, 1 << s->align);
1111 s->addr = newaddr;
1113 seg_vmsize = newaddr + s->size;
1115 /* zerofill sections aren't actually written to the file */
1116 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1118 * LLVM/Xcode as always aligns the section data to 4
1119 * bytes; there is a comment in the LLVM source code that
1120 * perhaps aligning to pointer size would be better.
1122 s->pad = ALIGN(seg_filesize, 4) - seg_filesize;
1123 s->offset = seg_filesize + s->pad;
1124 seg_filesize += s->size + s->pad;
1128 /* calculate size of all headers, load commands and sections to
1129 ** get a pointer to the start of all the raw data */
1130 if (seg_nsects > 0) {
1131 ++head_ncmds;
1132 head_sizeofcmds += fmt.segcmd_size + seg_nsects * fmt.sectcmd_size;
1135 if (nsyms > 0) {
1136 ++head_ncmds;
1137 head_sizeofcmds += MACHO_SYMCMD_SIZE;
1140 if (seg_nsects > MAX_SECT) {
1141 nasm_fatal(0, "MachO output is limited to %d sections\n",
1142 MAX_SECT);
1145 /* Create a table of sections by file index to avoid linear search */
1146 sectstab = nasm_malloc((seg_nsects + 1) * sizeof(*sectstab));
1147 sectstab[NO_SECT] = &absolute_sect;
1148 for (s = sects, fi = 1; s != NULL; s = s->next, fi++)
1149 sectstab[fi] = s;
1152 /* Write out the header information for the file. */
1154 static void macho_write_header (void)
1156 fwriteint32_t(fmt.mh_magic, ofile); /* magic */
1157 fwriteint32_t(fmt.cpu_type, ofile); /* CPU type */
1158 fwriteint32_t(CPU_SUBTYPE_I386_ALL, ofile); /* CPU subtype */
1159 fwriteint32_t(MH_OBJECT, ofile); /* Mach-O file type */
1160 fwriteint32_t(head_ncmds, ofile); /* number of load commands */
1161 fwriteint32_t(head_sizeofcmds, ofile); /* size of load commands */
1162 fwriteint32_t(0, ofile); /* no flags */
1163 fwritezero(fmt.header_size - 7*4, ofile); /* reserved fields */
1166 /* Write out the segment load command at offset. */
1168 static uint32_t macho_write_segment (uint64_t offset)
1170 uint64_t rel_base = alignptr(offset + seg_filesize);
1171 uint32_t s_reloff = 0;
1172 struct section *s;
1174 fwriteint32_t(fmt.lc_segment, ofile); /* cmd == LC_SEGMENT_64 */
1176 /* size of load command including section load commands */
1177 fwriteint32_t(fmt.segcmd_size + seg_nsects * fmt.sectcmd_size,
1178 ofile);
1180 /* in an MH_OBJECT file all sections are in one unnamed (name
1181 ** all zeros) segment */
1182 fwritezero(16, ofile);
1183 fwriteptr(0, ofile); /* in-memory offset */
1184 fwriteptr(seg_vmsize, ofile); /* in-memory size */
1185 fwriteptr(offset, ofile); /* in-file offset to data */
1186 fwriteptr(seg_filesize, ofile); /* in-file size */
1187 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* maximum vm protection */
1188 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* initial vm protection */
1189 fwriteint32_t(seg_nsects, ofile); /* number of sections */
1190 fwriteint32_t(0, ofile); /* no flags */
1192 /* emit section headers */
1193 for (s = sects; s != NULL; s = s->next) {
1194 if (s->nreloc) {
1195 nasm_assert((s->flags & SECTION_TYPE) != S_ZEROFILL);
1196 s->flags |= S_ATTR_LOC_RELOC;
1197 if (s->extreloc)
1198 s->flags |= S_ATTR_EXT_RELOC;
1199 } else if (!strcmp(s->segname, "__DATA") &&
1200 !strcmp(s->sectname, "__const") &&
1201 !s->by_name &&
1202 !get_section_by_name("__TEXT", "__const")) {
1204 * The MachO equivalent to .rodata can be either
1205 * __DATA,__const or __TEXT,__const; the latter only if
1206 * there are no relocations. However, when mixed it is
1207 * better to specify the segments explicitly.
1209 xstrncpy(s->segname, "__TEXT");
1212 nasm_write(s->sectname, sizeof(s->sectname), ofile);
1213 nasm_write(s->segname, sizeof(s->segname), ofile);
1214 fwriteptr(s->addr, ofile);
1215 fwriteptr(s->size, ofile);
1217 /* dummy data for zerofill sections or proper values */
1218 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1219 nasm_assert(s->pad != (uint32_t)-1);
1220 offset += s->pad;
1221 fwriteint32_t(offset, ofile);
1222 offset += s->size;
1223 /* Write out section alignment, as a power of two.
1224 e.g. 32-bit word alignment would be 2 (2^2 = 4). */
1225 fwriteint32_t(s->align, ofile);
1226 /* To be compatible with cctools as we emit
1227 a zero reloff if we have no relocations. */
1228 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile);
1229 fwriteint32_t(s->nreloc, ofile);
1231 s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
1232 } else {
1233 fwriteint32_t(0, ofile);
1234 fwriteint32_t(s->align, ofile);
1235 fwriteint32_t(0, ofile);
1236 fwriteint32_t(0, ofile);
1239 fwriteint32_t(s->flags, ofile); /* flags */
1240 fwriteint32_t(0, ofile); /* reserved */
1241 fwriteptr(0, ofile); /* reserved */
1244 rel_padcnt = rel_base - offset;
1245 offset = rel_base + s_reloff;
1247 return offset;
1250 /* For a given chain of relocs r, write out the entire relocation
1251 chain to the object file. */
1253 static void macho_write_relocs (struct reloc *r)
1255 while (r) {
1256 uint32_t word2;
1258 fwriteint32_t(r->addr, ofile); /* reloc offset */
1260 word2 = r->snum;
1261 word2 |= r->pcrel << 24;
1262 word2 |= r->length << 25;
1263 word2 |= r->ext << 27;
1264 word2 |= r->type << 28;
1265 fwriteint32_t(word2, ofile); /* reloc data */
1266 r = r->next;
1270 /* Write out the section data. */
1271 static void macho_write_section (void)
1273 struct section *s;
1274 struct reloc *r;
1275 uint8_t *p;
1276 int32_t len;
1277 int64_t l;
1278 union offset {
1279 uint64_t val;
1280 uint8_t buf[8];
1281 } blk;
1283 for (s = sects; s != NULL; s = s->next) {
1284 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
1285 continue;
1287 /* Like a.out Mach-O references things in the data or bss
1288 * sections by addresses which are actually relative to the
1289 * start of the _text_ section, in the _file_. See outaout.c
1290 * for more information. */
1291 saa_rewind(s->data);
1292 for (r = s->relocs; r != NULL; r = r->next) {
1293 len = (uint32_t)1 << r->length;
1294 if (len > 4) /* Can this ever be an issue?! */
1295 len = 8;
1296 blk.val = 0;
1297 saa_fread(s->data, r->addr, blk.buf, len);
1299 /* get offset based on relocation type */
1300 #ifdef WORDS_LITTLEENDIAN
1301 l = blk.val;
1302 #else
1303 l = blk.buf[0];
1304 l += ((int64_t)blk.buf[1]) << 8;
1305 l += ((int64_t)blk.buf[2]) << 16;
1306 l += ((int64_t)blk.buf[3]) << 24;
1307 l += ((int64_t)blk.buf[4]) << 32;
1308 l += ((int64_t)blk.buf[5]) << 40;
1309 l += ((int64_t)blk.buf[6]) << 48;
1310 l += ((int64_t)blk.buf[7]) << 56;
1311 #endif
1313 /* If the relocation is internal add to the current section
1314 offset. Otherwise the only value we need is the symbol
1315 offset which we already have. The linker takes care
1316 of the rest of the address. */
1317 if (!r->ext) {
1318 /* generate final address by section address and offset */
1319 nasm_assert(r->snum <= seg_nsects);
1320 l += sectstab[r->snum]->addr;
1321 if (r->pcrel)
1322 l -= s->addr;
1325 /* write new offset back */
1326 p = blk.buf;
1327 WRITEDLONG(p, l);
1328 saa_fwrite(s->data, r->addr, blk.buf, len);
1331 /* dump the section data to file */
1332 fwritezero(s->pad, ofile);
1333 saa_fpwrite(s->data, ofile);
1336 /* pad last section up to reloc entries on pointer boundary */
1337 fwritezero(rel_padcnt, ofile);
1339 /* emit relocation entries */
1340 for (s = sects; s != NULL; s = s->next)
1341 macho_write_relocs (s->relocs);
1344 /* Write out the symbol table. We should already have sorted this
1345 before now. */
1346 static void macho_write_symtab (void)
1348 struct symbol *sym;
1349 uint64_t i;
1351 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1353 for (sym = syms; sym != NULL; sym = sym->next) {
1354 if ((sym->type & N_EXT) == 0) {
1355 fwriteint32_t(sym->strx, ofile); /* string table entry number */
1356 nasm_write(&sym->type, 1, ofile); /* symbol type */
1357 nasm_write(&sym->sect, 1, ofile); /* section */
1358 fwriteint16_t(sym->desc, ofile); /* description */
1360 /* Fix up the symbol value now that we know the final section
1361 sizes. */
1362 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1363 nasm_assert(sym->sect <= seg_nsects);
1364 sym->symv.key += sectstab[sym->sect]->addr;
1367 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1371 for (i = 0; i < nextdefsym; i++) {
1372 sym = extdefsyms[i];
1373 fwriteint32_t(sym->strx, ofile);
1374 nasm_write(&sym->type, 1, ofile); /* symbol type */
1375 nasm_write(&sym->sect, 1, ofile); /* section */
1376 fwriteint16_t(sym->desc, ofile); /* description */
1378 /* Fix up the symbol value now that we know the final section
1379 sizes. */
1380 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1381 nasm_assert(sym->sect <= seg_nsects);
1382 sym->symv.key += sectstab[sym->sect]->addr;
1385 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1388 for (i = 0; i < nundefsym; i++) {
1389 sym = undefsyms[i];
1390 fwriteint32_t(sym->strx, ofile);
1391 nasm_write(&sym->type, 1, ofile); /* symbol type */
1392 nasm_write(&sym->sect, 1, ofile); /* section */
1393 fwriteint16_t(sym->desc, ofile); /* description */
1395 /* Fix up the symbol value now that we know the final section
1396 sizes. */
1397 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1398 nasm_assert(sym->sect <= seg_nsects);
1399 sym->symv.key += sectstab[sym->sect]->addr;
1402 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1407 /* Fixup the snum in the relocation entries, we should be
1408 doing this only for externally referenced symbols. */
1409 static void macho_fixup_relocs (struct reloc *r)
1411 struct symbol *sym;
1413 while (r != NULL) {
1414 if (r->ext) {
1415 for (sym = syms; sym != NULL; sym = sym->next) {
1416 if (sym->initial_snum == r->snum) {
1417 r->snum = sym->snum;
1418 break;
1422 r = r->next;
1426 /* Write out the object file. */
1428 static void macho_write (void)
1430 uint64_t offset = 0;
1432 /* mach-o object file structure:
1434 ** mach header
1435 ** uint32_t magic
1436 ** int cpu type
1437 ** int cpu subtype
1438 ** uint32_t mach file type
1439 ** uint32_t number of load commands
1440 ** uint32_t size of all load commands
1441 ** (includes section struct size of segment command)
1442 ** uint32_t flags
1444 ** segment command
1445 ** uint32_t command type == LC_SEGMENT[_64]
1446 ** uint32_t size of load command
1447 ** (including section load commands)
1448 ** char[16] segment name
1449 ** pointer in-memory offset
1450 ** pointer in-memory size
1451 ** pointer in-file offset to data area
1452 ** pointer in-file size
1453 ** (in-memory size excluding zerofill sections)
1454 ** int maximum vm protection
1455 ** int initial vm protection
1456 ** uint32_t number of sections
1457 ** uint32_t flags
1459 ** section commands
1460 ** char[16] section name
1461 ** char[16] segment name
1462 ** pointer in-memory offset
1463 ** pointer in-memory size
1464 ** uint32_t in-file offset
1465 ** uint32_t alignment
1466 ** (irrelevant in MH_OBJECT)
1467 ** uint32_t in-file offset of relocation entires
1468 ** uint32_t number of relocations
1469 ** uint32_t flags
1470 ** uint32_t reserved
1471 ** uint32_t reserved
1473 ** symbol table command
1474 ** uint32_t command type == LC_SYMTAB
1475 ** uint32_t size of load command
1476 ** uint32_t symbol table offset
1477 ** uint32_t number of symbol table entries
1478 ** uint32_t string table offset
1479 ** uint32_t string table size
1481 ** raw section data
1483 ** padding to pointer boundary
1485 ** relocation data (struct reloc)
1486 ** int32_t offset
1487 ** uint data (symbolnum, pcrel, length, extern, type)
1489 ** symbol table data (struct nlist)
1490 ** int32_t string table entry number
1491 ** uint8_t type
1492 ** (extern, absolute, defined in section)
1493 ** uint8_t section
1494 ** (0 for global symbols, section number of definition (>= 1, <=
1495 ** 254) for local symbols, size of variable for common symbols
1496 ** [type == extern])
1497 ** int16_t description
1498 ** (for stab debugging format)
1499 ** pointer value (i.e. file offset) of symbol or stab offset
1501 ** string table data
1502 ** list of null-terminated strings
1505 /* Emit the Mach-O header. */
1506 macho_write_header();
1508 offset = fmt.header_size + head_sizeofcmds;
1510 /* emit the segment load command */
1511 if (seg_nsects > 0)
1512 offset = macho_write_segment (offset);
1513 else
1514 nasm_error(ERR_WARNING, "no sections?");
1516 if (nsyms > 0) {
1517 /* write out symbol command */
1518 fwriteint32_t(LC_SYMTAB, ofile); /* cmd == LC_SYMTAB */
1519 fwriteint32_t(MACHO_SYMCMD_SIZE, ofile); /* size of load command */
1520 fwriteint32_t(offset, ofile); /* symbol table offset */
1521 fwriteint32_t(nsyms, ofile); /* number of symbol
1522 ** table entries */
1523 offset += nsyms * fmt.nlist_size;
1524 fwriteint32_t(offset, ofile); /* string table offset */
1525 fwriteint32_t(strslen, ofile); /* string table size */
1528 /* emit section data */
1529 if (seg_nsects > 0)
1530 macho_write_section ();
1532 /* emit symbol table if we have symbols */
1533 if (nsyms > 0)
1534 macho_write_symtab ();
1536 /* we don't need to pad here, we are already aligned */
1538 /* emit string table */
1539 saa_fpwrite(strs, ofile);
1541 /* We do quite a bit here, starting with finalizing all of the data
1542 for the object file, writing, and then freeing all of the data from
1543 the file. */
1545 static void macho_cleanup(void)
1547 struct section *s;
1548 struct reloc *r;
1549 struct symbol *sym;
1551 /* Sort all symbols. */
1552 macho_layout_symbols (&nsyms, &strslen);
1554 /* Fixup relocation entries */
1555 for (s = sects; s != NULL; s = s->next) {
1556 macho_fixup_relocs (s->relocs);
1559 /* First calculate and finalize needed values. */
1560 macho_calculate_sizes();
1561 macho_write();
1563 /* free up everything */
1564 while (sects->next) {
1565 s = sects;
1566 sects = sects->next;
1568 saa_free(s->data);
1569 while (s->relocs != NULL) {
1570 r = s->relocs;
1571 s->relocs = s->relocs->next;
1572 nasm_free(r);
1575 nasm_free(s);
1578 saa_free(strs);
1579 raa_free(extsyms);
1581 while (syms) {
1582 sym = syms;
1583 syms = syms->next;
1584 nasm_free (sym);
1587 nasm_free(extdefsyms);
1588 nasm_free(undefsyms);
1589 nasm_free(sectstab);
1592 #ifdef OF_MACHO32
1593 static const struct macho_fmt macho32_fmt = {
1595 MH_MAGIC,
1596 CPU_TYPE_I386,
1597 LC_SEGMENT,
1598 MACHO_HEADER_SIZE,
1599 MACHO_SEGCMD_SIZE,
1600 MACHO_SECTCMD_SIZE,
1601 MACHO_NLIST_SIZE,
1602 RL_MAX_32,
1603 GENERIC_RELOC_VANILLA,
1604 GENERIC_RELOC_VANILLA,
1605 GENERIC_RELOC_TLV
1608 static void macho32_init(void)
1610 fmt = macho32_fmt;
1611 macho_init();
1613 macho_gotpcrel_sect = NO_SEG;
1616 const struct ofmt of_macho32 = {
1617 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files",
1618 "macho32",
1621 null_debug_arr,
1622 &null_debug_form,
1623 macho_stdmac,
1624 macho32_init,
1625 null_setinfo,
1626 macho_output,
1627 macho_symdef,
1628 macho_section,
1629 macho_sectalign,
1630 macho_segbase,
1631 null_directive,
1632 macho_filename,
1633 macho_cleanup
1635 #endif
1637 #ifdef OF_MACHO64
1638 static const struct macho_fmt macho64_fmt = {
1640 MH_MAGIC_64,
1641 CPU_TYPE_X86_64,
1642 LC_SEGMENT_64,
1643 MACHO_HEADER64_SIZE,
1644 MACHO_SEGCMD64_SIZE,
1645 MACHO_SECTCMD64_SIZE,
1646 MACHO_NLIST64_SIZE,
1647 RL_MAX_64,
1648 X86_64_RELOC_UNSIGNED,
1649 X86_64_RELOC_SIGNED,
1650 X86_64_RELOC_TLV
1653 static void macho64_init(void)
1655 fmt = macho64_fmt;
1656 macho_init();
1658 /* add special symbol for ..gotpcrel */
1659 macho_gotpcrel_sect = seg_alloc() + 1;
1660 define_label("..gotpcrel", macho_gotpcrel_sect, 0L, NULL, false, false);
1663 const struct ofmt of_macho64 = {
1664 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files",
1665 "macho64",
1668 null_debug_arr,
1669 &null_debug_form,
1670 macho_stdmac,
1671 macho64_init,
1672 null_setinfo,
1673 macho_output,
1674 macho_symdef,
1675 macho_section,
1676 macho_sectalign,
1677 macho_segbase,
1678 null_directive,
1679 macho_filename,
1680 macho_cleanup
1682 #endif
1684 #endif
1687 * Local Variables:
1688 * mode:c
1689 * c-basic-offset:4
1690 * End:
1692 * end of file */