outmacho: support the "subsections_via_symbols" directive
[nasm.git] / output / outmacho.c
blob716f99fd3e860c21fd8a3756e1955360501e0d60
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2017 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 "error.h"
49 #include "saa.h"
50 #include "raa.h"
51 #include "rbtree.h"
52 #include "outform.h"
53 #include "outlib.h"
55 #if defined(OF_MACHO) || defined(OF_MACHO64)
57 /* Mach-O in-file header structure sizes */
58 #define MACHO_HEADER_SIZE 28
59 #define MACHO_SEGCMD_SIZE 56
60 #define MACHO_SECTCMD_SIZE 68
61 #define MACHO_SYMCMD_SIZE 24
62 #define MACHO_NLIST_SIZE 12
63 #define MACHO_RELINFO_SIZE 8
65 #define MACHO_HEADER64_SIZE 32
66 #define MACHO_SEGCMD64_SIZE 72
67 #define MACHO_SECTCMD64_SIZE 80
68 #define MACHO_NLIST64_SIZE 16
70 /* Mach-O file header values */
71 #define MH_MAGIC 0xfeedface
72 #define MH_MAGIC_64 0xfeedfacf
73 #define CPU_TYPE_I386 7 /* x86 platform */
74 #define CPU_TYPE_X86_64 0x01000007 /* x86-64 platform */
75 #define CPU_SUBTYPE_I386_ALL 3 /* all-x86 compatible */
76 #define MH_OBJECT 0x1 /* object file */
78 /* Mach-O header flags */
79 #define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000
81 /* Mach-O load commands */
82 #define LC_SEGMENT 0x1 /* 32-bit segment load cmd */
83 #define LC_SEGMENT_64 0x19 /* 64-bit segment load cmd */
84 #define LC_SYMTAB 0x2 /* symbol table load command */
86 /* Mach-O relocations numbers */
88 /* Generic relocs, used by i386 Mach-O */
89 #define GENERIC_RELOC_VANILLA 0 /* Generic relocation */
90 #define GENERIC_RELOC_TLV 5 /* Thread local */
92 #define X86_64_RELOC_UNSIGNED 0 /* Absolute address */
93 #define X86_64_RELOC_SIGNED 1 /* Signed 32-bit disp */
94 #define X86_64_RELOC_BRANCH 2 /* CALL/JMP with 32-bit disp */
95 #define X86_64_RELOC_GOT_LOAD 3 /* MOVQ of GOT entry */
96 #define X86_64_RELOC_GOT 4 /* Different GOT entry */
97 #define X86_64_RELOC_SUBTRACTOR 5 /* Subtracting two symbols */
98 #define X86_64_RELOC_SIGNED_1 6 /* SIGNED with -1 addend */
99 #define X86_64_RELOC_SIGNED_2 7 /* SIGNED with -2 addend */
100 #define X86_64_RELOC_SIGNED_4 8 /* SIGNED with -4 addend */
101 #define X86_64_RELOC_TLV 9 /* Thread local */
103 /* Mach-O VM permission constants */
104 #define VM_PROT_NONE (0x00)
105 #define VM_PROT_READ (0x01)
106 #define VM_PROT_WRITE (0x02)
107 #define VM_PROT_EXECUTE (0x04)
109 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
110 #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
112 /* Our internal relocation types */
113 enum reltype {
114 RL_ABS, /* Absolute relocation */
115 RL_REL, /* Relative relocation */
116 RL_TLV, /* Thread local */
117 RL_BRANCH, /* Relative direct branch */
118 RL_SUB, /* X86_64_RELOC_SUBTRACT */
119 RL_GOT, /* X86_64_RELOC_GOT */
120 RL_GOTLOAD /* X86_64_RELOC_GOT_LOAD */
122 #define RL_MAX_32 RL_TLV
123 #define RL_MAX_64 RL_GOTLOAD
125 struct macho_fmt {
126 uint32_t ptrsize; /* Pointer size in bytes */
127 uint32_t mh_magic; /* Which magic number to use */
128 uint32_t cpu_type; /* Which CPU type */
129 uint32_t lc_segment; /* Which segment load command */
130 uint32_t header_size; /* Header size */
131 uint32_t segcmd_size; /* Segment command size */
132 uint32_t sectcmd_size; /* Section command size */
133 uint32_t nlist_size; /* Nlist (symbol) size */
134 enum reltype maxreltype; /* Maximum entry in enum reltype permitted */
135 uint32_t reloc_abs; /* Absolute relocation type */
136 uint32_t reloc_rel; /* Relative relocation type */
137 uint32_t reloc_tlv; /* Thread local relocation type */
140 static struct macho_fmt fmt;
142 static void fwriteptr(uint64_t data, FILE * fp)
144 fwriteaddr(data, fmt.ptrsize, fp);
147 struct section {
148 /* nasm internal data */
149 struct section *next;
150 struct SAA *data;
151 int32_t index;
152 int32_t fileindex;
153 struct reloc *relocs;
154 struct rbtree *gsyms; /* Global symbols in section */
155 int align;
156 bool by_name; /* This section was specified by full MachO name */
158 /* data that goes into the file */
159 char sectname[16]; /* what this section is called */
160 char segname[16]; /* segment this section will be in */
161 uint64_t addr; /* in-memory address (subject to alignment) */
162 uint64_t size; /* in-memory and -file size */
163 uint64_t offset; /* in-file offset */
164 uint32_t pad; /* padding bytes before section */
165 uint32_t nreloc; /* relocation entry count */
166 uint32_t flags; /* type and attributes (masked) */
167 uint32_t extreloc; /* external relocations */
170 #define SECTION_TYPE 0x000000ff /* section type mask */
172 #define S_REGULAR (0x0) /* standard section */
173 #define S_ZEROFILL (0x1) /* zerofill, in-memory only */
175 #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
176 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
177 machine instructions */
178 #define S_ATTR_EXT_RELOC 0x00000200 /* section has external
179 relocation entries */
180 #define S_ATTR_LOC_RELOC 0x00000100 /* section has local
181 relocation entries */
182 #define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section uses pure
183 machine instructions */
185 /* Fake section for absolute symbols, *not* part of the section linked list */
186 static struct section absolute_sect;
188 static const struct sectmap {
189 const char *nasmsect;
190 const char *segname;
191 const char *sectname;
192 const int32_t flags;
193 } sectmap[] = {
194 {".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS},
195 {".data", "__DATA", "__data", S_REGULAR},
196 {".rodata", "__DATA", "__const", S_REGULAR},
197 {".bss", "__DATA", "__bss", S_ZEROFILL},
198 {NULL, NULL, NULL, 0}
201 struct reloc {
202 /* nasm internal data */
203 struct reloc *next;
205 /* data that goes into the file */
206 int32_t addr; /* op's offset in section */
207 uint32_t snum:24, /* contains symbol index if
208 ** ext otherwise in-file
209 ** section number */
210 pcrel:1, /* relative relocation */
211 length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */
212 ext:1, /* external symbol referenced */
213 type:4; /* reloc type */
216 #define R_ABS 0 /* absolute relocation */
217 #define R_SCATTERED 0x80000000 /* reloc entry is scattered if
218 ** highest bit == 1 */
220 struct symbol {
221 /* nasm internal data */
222 struct rbtree symv; /* Global symbol rbtree; "key" contains the
223 symbol offset. */
224 struct symbol *next; /* next symbol in the list */
225 char *name; /* name of this symbol */
226 int32_t initial_snum; /* symbol number used above in reloc */
227 int32_t snum; /* true snum for reloc */
229 /* data that goes into the file */
230 uint32_t strx; /* string table index */
231 uint8_t type; /* symbol type */
232 uint8_t sect; /* NO_SECT or section number */
233 uint16_t desc; /* for stab debugging, 0 for us */
236 /* symbol type bits */
237 #define N_EXT 0x01 /* global or external symbol */
239 #define N_UNDF 0x0 /* undefined symbol | n_sect == */
240 #define N_ABS 0x2 /* absolute symbol | NO_SECT */
241 #define N_SECT 0xe /* defined symbol, n_sect holds
242 ** section number */
244 #define N_TYPE 0x0e /* type bit mask */
246 #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
248 /* special section number values */
249 #define NO_SECT 0 /* no section, invalid */
250 #define MAX_SECT 255 /* maximum number of sections */
252 static struct section *sects, **sectstail, **sectstab;
253 static struct symbol *syms, **symstail;
254 static uint32_t nsyms;
256 /* These variables are set by macho_layout_symbols() to organize
257 the symbol table and string table in order the dynamic linker
258 expects. They are then used in macho_write() to put out the
259 symbols and strings in that order.
261 The order of the symbol table is:
262 local symbols
263 defined external symbols (sorted by name)
264 undefined external symbols (sorted by name)
266 The order of the string table is:
267 strings for external symbols
268 strings for local symbols
270 static uint32_t ilocalsym = 0;
271 static uint32_t iextdefsym = 0;
272 static uint32_t iundefsym = 0;
273 static uint32_t nlocalsym;
274 static uint32_t nextdefsym;
275 static uint32_t nundefsym;
276 static struct symbol **extdefsyms = NULL;
277 static struct symbol **undefsyms = NULL;
279 static struct RAA *extsyms;
280 static struct SAA *strs;
281 static uint32_t strslen;
283 /* Global file information. This should be cleaned up into either
284 a structure or as function arguments. */
285 static uint32_t head_ncmds = 0;
286 static uint32_t head_sizeofcmds = 0;
287 static uint32_t head_flags = 0;
288 static uint64_t seg_filesize = 0;
289 static uint64_t seg_vmsize = 0;
290 static uint32_t seg_nsects = 0;
291 static uint64_t rel_padcnt = 0;
293 #define xstrncpy(xdst, xsrc) \
294 memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \
295 strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \
296 xdst[sizeof(xdst) - 1] = '\0'; /* proper null-termination */
298 #define alignint32_t(x) \
299 ALIGN(x, sizeof(int32_t)) /* align x to int32_t boundary */
301 #define alignint64_t(x) \
302 ALIGN(x, sizeof(int64_t)) /* align x to int64_t boundary */
304 #define alignptr(x) \
305 ALIGN(x, fmt.ptrsize) /* align x to output format width */
307 static struct section *get_section_by_name(const char *segname,
308 const char *sectname)
310 struct section *s;
312 for (s = sects; s != NULL; s = s->next)
313 if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname))
314 break;
316 return s;
319 static struct section *get_section_by_index(const int32_t index)
321 struct section *s;
323 for (s = sects; s != NULL; s = s->next)
324 if (index == s->index)
325 break;
327 return s;
331 * Special section numbers which are used to define Mach-O special
332 * symbols, which can be used with WRT to provide PIC relocation
333 * types.
335 static int32_t macho_tlvp_sect;
336 static int32_t macho_gotpcrel_sect;
338 static void macho_init(void)
340 sects = NULL;
341 sectstail = &sects;
343 /* Fake section for absolute symbols */
344 absolute_sect.index = NO_SEG;
346 syms = NULL;
347 symstail = &syms;
348 nsyms = 0;
349 nlocalsym = 0;
350 nextdefsym = 0;
351 nundefsym = 0;
353 extsyms = raa_init();
354 strs = saa_init(1L);
356 /* string table starts with a zero byte so index 0 is an empty string */
357 saa_wbytes(strs, zero_buffer, 1);
358 strslen = 1;
360 /* add special symbol for TLVP */
361 macho_tlvp_sect = seg_alloc() + 1;
362 define_label("..tlvp", macho_tlvp_sect, 0L, NULL, false, false);
366 static void sect_write(struct section *sect,
367 const uint8_t *data, uint32_t len)
369 saa_wbytes(sect->data, data, len);
370 sect->size += len;
374 * Find a suitable global symbol for a ..gotpcrel or ..tlvp reference
376 static struct symbol *macho_find_gsym(struct section *s,
377 uint64_t offset, bool exact)
379 struct rbtree *srb;
381 srb = rb_search(s->gsyms, offset);
383 if (!srb || (exact && srb->key != offset)) {
384 nasm_error(ERR_NONFATAL, "unable to find a suitable %s symbol"
385 " for this reference",
386 s == &absolute_sect ? "absolute" : "global");
387 return NULL;
390 return container_of(srb, struct symbol, symv);
393 static int64_t add_reloc(struct section *sect, int32_t section,
394 int64_t offset,
395 enum reltype reltype, int bytes)
397 struct reloc *r;
398 struct section *s;
399 int32_t fi;
400 int64_t adjust;
402 /* Double check this is a valid relocation type for this platform */
403 nasm_assert(reltype <= fmt.maxreltype);
405 /* the current end of the section will be the symbol's address for
406 ** now, might have to be fixed by macho_fixup_relocs() later on. make
407 ** sure we don't make the symbol scattered by setting the highest
408 ** bit by accident */
409 r = nasm_malloc(sizeof(struct reloc));
410 r->addr = sect->size & ~R_SCATTERED;
411 r->ext = 1;
412 adjust = bytes;
414 /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
415 r->length = ilog2_32(bytes);
417 /* set default relocation values */
418 r->type = fmt.reloc_abs;
419 r->pcrel = 0;
420 r->snum = R_ABS;
422 s = NULL;
423 if (section != NO_SEG)
424 s = get_section_by_index(section);
425 fi = s ? s->fileindex : NO_SECT;
427 /* absolute relocation */
428 switch (reltype) {
429 case RL_ABS:
430 if (section == NO_SEG) {
431 /* absolute (can this even happen?) */
432 r->ext = 0;
433 r->snum = R_ABS;
434 } else if (fi == NO_SECT) {
435 /* external */
436 r->snum = raa_read(extsyms, section);
437 } else {
438 /* local */
439 r->ext = 0;
440 r->snum = fi;
441 adjust = -sect->size;
443 break;
445 case RL_REL:
446 case RL_BRANCH:
447 r->type = fmt.reloc_rel;
448 r->pcrel = 1;
449 if (section == NO_SEG) {
450 /* absolute - seems to produce garbage no matter what */
451 nasm_error(ERR_NONFATAL, "Mach-O does not support relative "
452 "references to absolute addresses");
453 goto bail;
454 #if 0
455 /* This "seems" to be how it ought to work... */
457 struct symbol *sym = macho_find_gsym(&absolute_sect,
458 offset, false);
459 if (!sym)
460 goto bail;
462 sect->extreloc = 1;
463 r->snum = NO_SECT;
464 adjust = -sect->size;
465 #endif
466 } else if (fi == NO_SECT) {
467 /* external */
468 sect->extreloc = 1;
469 r->snum = raa_read(extsyms, section);
470 if (reltype == RL_BRANCH)
471 r->type = X86_64_RELOC_BRANCH;
472 else if (r->type == GENERIC_RELOC_VANILLA)
473 adjust = -sect->size;
474 } else {
475 /* local */
476 r->ext = 0;
477 r->snum = fi;
478 adjust = -sect->size;
480 break;
482 case RL_SUB:
483 r->pcrel = 0;
484 r->type = X86_64_RELOC_SUBTRACTOR;
485 break;
487 case RL_GOT:
488 r->type = X86_64_RELOC_GOT;
489 goto needsym;
491 case RL_GOTLOAD:
492 r->type = X86_64_RELOC_GOT_LOAD;
493 goto needsym;
495 case RL_TLV:
496 r->type = fmt.reloc_tlv;
497 goto needsym;
499 needsym:
500 r->pcrel = 1;
501 if (section == NO_SEG) {
502 nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT");
503 } else if (fi == NO_SECT) {
504 /* external */
505 r->snum = raa_read(extsyms, section);
506 } else {
507 /* internal */
508 struct symbol *sym = macho_find_gsym(s, offset, reltype != RL_TLV);
509 if (!sym)
510 goto bail;
511 r->snum = sym->initial_snum;
513 break;
516 /* NeXT as puts relocs in reversed order (address-wise) into the
517 ** files, so we do the same, doesn't seem to make much of a
518 ** difference either way */
519 r->next = sect->relocs;
520 sect->relocs = r;
521 if (r->ext)
522 sect->extreloc = 1;
523 ++sect->nreloc;
525 return adjust;
527 bail:
528 nasm_free(r);
529 return 0;
532 static void macho_output(int32_t secto, const void *data,
533 enum out_type type, uint64_t size,
534 int32_t section, int32_t wrt)
536 struct section *s;
537 int64_t addr, offset;
538 uint8_t mydata[16], *p;
539 bool is_bss;
540 enum reltype reltype;
542 if (secto == NO_SEG) {
543 if (type != OUT_RESERVE)
544 nasm_error(ERR_NONFATAL, "attempt to assemble code in "
545 "[ABSOLUTE] space");
546 return;
549 s = get_section_by_index(secto);
551 if (s == NULL) {
552 nasm_error(ERR_WARNING, "attempt to assemble code in"
553 " section %d: defaulting to `.text'", secto);
554 s = get_section_by_name("__TEXT", "__text");
556 /* should never happen */
557 if (s == NULL)
558 nasm_panic(0, "text section not found");
561 is_bss = (s->flags & SECTION_TYPE) == S_ZEROFILL;
563 if (is_bss && type != OUT_RESERVE) {
564 nasm_error(ERR_WARNING, "attempt to initialize memory in "
565 "BSS section: ignored");
566 s->size += realsize(type, size);
567 return;
570 memset(mydata, 0, sizeof(mydata));
572 switch (type) {
573 case OUT_RESERVE:
574 if (!is_bss) {
575 nasm_error(ERR_WARNING, "uninitialized space declared in"
576 " %s,%s section: zeroing", s->segname, s->sectname);
578 sect_write(s, NULL, size);
579 } else
580 s->size += size;
582 break;
584 case OUT_RAWDATA:
585 if (section != NO_SEG)
586 nasm_panic(0, "OUT_RAWDATA with other than NO_SEG");
588 sect_write(s, data, size);
589 break;
591 case OUT_ADDRESS:
593 int asize = abs((int)size);
595 addr = *(int64_t *)data;
596 if (section != NO_SEG) {
597 if (section % 2) {
598 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
599 " section base references");
600 } else if (wrt == NO_SEG) {
601 if (fmt.ptrsize == 8 && asize != 8) {
602 nasm_error(ERR_NONFATAL,
603 "Mach-O 64-bit format does not support"
604 " 32-bit absolute addresses");
605 } else {
606 add_reloc(s, section, addr, RL_ABS, asize);
608 } else {
609 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
610 " this use of WRT");
614 p = mydata;
615 WRITEADDR(p, addr, asize);
616 sect_write(s, mydata, asize);
617 break;
620 case OUT_REL2ADR:
621 nasm_assert(section != secto);
623 p = mydata;
624 offset = *(int64_t *)data;
625 addr = offset - size;
627 if (section != NO_SEG && section % 2) {
628 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
629 " section base references");
630 } else if (fmt.ptrsize == 8) {
631 nasm_error(ERR_NONFATAL, "Unsupported non-32-bit"
632 " Macho-O relocation [2]");
633 } else if (wrt != NO_SEG) {
634 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
635 " this use of WRT");
636 wrt = NO_SEG; /* we can at least _try_ to continue */
637 } else {
638 addr += add_reloc(s, section, addr+size, RL_REL, 2);
641 WRITESHORT(p, addr);
642 sect_write(s, mydata, 2);
643 break;
645 case OUT_REL4ADR:
646 nasm_assert(section != secto);
648 p = mydata;
649 offset = *(int64_t *)data;
650 addr = offset - size;
651 reltype = RL_REL;
653 if (section != NO_SEG && section % 2) {
654 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
655 " section base references");
656 } else if (wrt == NO_SEG) {
657 if (fmt.ptrsize == 8 &&
658 (s->flags & S_ATTR_SOME_INSTRUCTIONS)) {
659 uint8_t opcode[2];
661 opcode[0] = opcode[1] = 0;
663 /* HACK: Retrieve instruction opcode */
664 if (likely(s->data->datalen >= 2)) {
665 saa_fread(s->data, s->data->datalen-2, opcode, 2);
666 } else if (s->data->datalen == 1) {
667 saa_fread(s->data, 0, opcode+1, 1);
670 if ((opcode[0] != 0x0f && (opcode[1] & 0xfe) == 0xe8) ||
671 (opcode[0] == 0x0f && (opcode[1] & 0xf0) == 0x80)) {
672 /* Direct call, jmp, or jcc */
673 reltype = RL_BRANCH;
676 } else if (wrt == macho_gotpcrel_sect) {
677 reltype = RL_GOT;
679 if ((s->flags & S_ATTR_SOME_INSTRUCTIONS) &&
680 s->data->datalen >= 3) {
681 uint8_t gotload[3];
683 /* HACK: Retrieve instruction opcode */
684 saa_fread(s->data, s->data->datalen-3, gotload, 3);
685 if ((gotload[0] & 0xf8) == 0x48 &&
686 gotload[1] == 0x8b &&
687 (gotload[2] & 0307) == 0005) {
688 /* movq <reg>,[rel sym wrt ..gotpcrel] */
689 reltype = RL_GOTLOAD;
692 } else if (wrt == macho_tlvp_sect) {
693 reltype = RL_TLV;
694 } else {
695 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
696 " this use of WRT");
697 /* continue with RL_REL */
700 addr += add_reloc(s, section, offset, reltype, 4);
701 WRITELONG(p, addr);
702 sect_write(s, mydata, 4);
703 break;
705 default:
706 nasm_error(ERR_NONFATAL, "Unrepresentable relocation in Mach-O");
707 break;
711 static int32_t macho_section(char *name, int pass, int *bits)
713 char *sectionAttributes;
714 const struct sectmap *sm;
715 struct section *s;
716 const char *section, *segment;
717 uint32_t flags;
718 char *currentAttribute;
719 char *comma;
720 bool new_seg;
722 (void)pass;
724 /* Default to the appropriate number of bits. */
725 if (!name) {
726 *bits = fmt.ptrsize << 3;
727 name = ".text";
728 sectionAttributes = NULL;
729 } else {
730 sectionAttributes = name;
731 name = nasm_strsep(&sectionAttributes, " \t");
734 section = segment = NULL;
735 flags = 0;
737 comma = strchr(name, ',');
738 if (comma) {
739 int len;
741 *comma = '\0';
742 segment = name;
743 section = comma+1;
745 len = strlen(segment);
746 if (len == 0) {
747 nasm_error(ERR_NONFATAL, "empty segment name\n");
748 } else if (len >= 16) {
749 nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment);
752 len = strlen(section);
753 if (len == 0) {
754 nasm_error(ERR_NONFATAL, "empty section name\n");
755 } else if (len >= 16) {
756 nasm_error(ERR_NONFATAL, "section name %s too long\n", section);
759 if (!strcmp(section, "__text")) {
760 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
761 S_ATTR_PURE_INSTRUCTIONS;
762 } else if (!strcmp(section, "__bss")) {
763 flags = S_ZEROFILL;
764 } else {
765 flags = S_REGULAR;
767 } else {
768 for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
769 /* make lookup into section name translation table */
770 if (!strcmp(name, sm->nasmsect)) {
771 segment = sm->segname;
772 section = sm->sectname;
773 flags = sm->flags;
774 goto found;
777 nasm_error(ERR_NONFATAL, "unknown section name\n");
778 return NO_SEG;
781 found:
782 /* try to find section with that name */
783 s = get_section_by_name(segment, section);
785 /* create it if it doesn't exist yet */
786 if (!s) {
787 new_seg = true;
789 s = *sectstail = nasm_zalloc(sizeof(struct section));
790 sectstail = &s->next;
792 s->data = saa_init(1L);
793 s->index = seg_alloc();
794 s->fileindex = ++seg_nsects;
795 s->align = -1;
796 s->pad = -1;
797 s->offset = -1;
798 s->by_name = false;
800 xstrncpy(s->segname, segment);
801 xstrncpy(s->sectname, section);
802 s->size = 0;
803 s->nreloc = 0;
804 s->flags = flags;
805 } else {
806 new_seg = false;
809 if (comma)
810 *comma = ','; /* Restore comma */
812 s->by_name = s->by_name || comma; /* Was specified by name */
814 flags = (uint32_t)-1;
816 while ((NULL != sectionAttributes)
817 && (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
818 if (0 != *currentAttribute) {
819 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
820 char *end;
821 int newAlignment, value;
823 value = strtoul(currentAttribute + 6, (char**)&end, 0);
824 newAlignment = alignlog2_32(value);
826 if (0 != *end) {
827 nasm_error(ERR_NONFATAL,
828 "unknown or missing alignment value \"%s\" "
829 "specified for section \"%s\"",
830 currentAttribute + 6,
831 name);
832 } else if (0 > newAlignment) {
833 nasm_error(ERR_NONFATAL,
834 "alignment of %d (for section \"%s\") is not "
835 "a power of two",
836 value,
837 name);
840 if (s->align < newAlignment)
841 s->align = newAlignment;
842 } else if (!nasm_stricmp("data", currentAttribute)) {
843 flags = S_REGULAR;
844 } else if (!nasm_stricmp("code", currentAttribute) ||
845 !nasm_stricmp("text", currentAttribute)) {
846 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
847 S_ATTR_PURE_INSTRUCTIONS;
848 } else if (!nasm_stricmp("mixed", currentAttribute)) {
849 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS;
850 } else if (!nasm_stricmp("bss", currentAttribute)) {
851 flags = S_ZEROFILL;
852 } else {
853 nasm_error(ERR_NONFATAL,
854 "unknown section attribute %s for section %s",
855 currentAttribute,
856 name);
860 if (flags != (uint32_t)-1) {
861 if (!new_seg && s->flags != flags) {
862 nasm_error(ERR_NONFATAL,
863 "inconsistent section attributes for section %s\n",
864 name);
865 } else {
866 s->flags = flags;
871 return s->index;
874 static void macho_symdef(char *name, int32_t section, int64_t offset,
875 int is_global, char *special)
877 struct symbol *sym;
879 if (special) {
880 nasm_error(ERR_NONFATAL, "The Mach-O output format does "
881 "not support any special symbol types");
882 return;
885 if (is_global == 3) {
886 nasm_error(ERR_NONFATAL, "The Mach-O format does not "
887 "(yet) support forward reference fixups.");
888 return;
891 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
893 * This is a NASM special symbol. We never allow it into
894 * the Macho-O symbol table, even if it's a valid one. If it
895 * _isn't_ a valid one, we should barf immediately.
897 if (strcmp(name, "..gotpcrel") && strcmp(name, "..tlvp"))
898 nasm_error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
899 return;
902 sym = *symstail = nasm_zalloc(sizeof(struct symbol));
903 sym->next = NULL;
904 symstail = &sym->next;
906 sym->name = name;
907 sym->strx = strslen;
908 sym->type = 0;
909 sym->desc = 0;
910 sym->symv.key = offset;
911 sym->initial_snum = -1;
913 /* external and common symbols get N_EXT */
914 if (is_global != 0) {
915 sym->type |= N_EXT;
918 if (section == NO_SEG) {
919 /* symbols in no section get absolute */
920 sym->type |= N_ABS;
921 sym->sect = NO_SECT;
923 /* all absolute symbols are available to use as references */
924 absolute_sect.gsyms = rb_insert(absolute_sect.gsyms, &sym->symv);
925 } else {
926 struct section *s = get_section_by_index(section);
928 sym->type |= N_SECT;
930 /* get the in-file index of the section the symbol was defined in */
931 sym->sect = s ? s->fileindex : NO_SECT;
933 /* track the initially allocated symbol number for use in future fix-ups */
934 sym->initial_snum = nsyms;
936 if (!s) {
937 /* remember symbol number of references to external
938 ** symbols, this works because every external symbol gets
939 ** its own section number allocated internally by nasm and
940 ** can so be used as a key */
941 extsyms = raa_write(extsyms, section, nsyms);
943 switch (is_global) {
944 case 1:
945 case 2:
946 /* there isn't actually a difference between global
947 ** and common symbols, both even have their size in
948 ** sym->symv.key */
949 sym->type = N_EXT;
950 break;
952 default:
953 /* give an error on unfound section if it's not an
954 ** external or common symbol (assemble_file() does a
955 ** seg_alloc() on every call for them) */
956 nasm_panic(0, "in-file index for section %d not found, is_global = %d", section, is_global);
957 break;
959 } else if (is_global) {
960 s->gsyms = rb_insert(s->gsyms, &sym->symv);
963 ++nsyms;
966 static void macho_sectalign(int32_t seg, unsigned int value)
968 struct section *s;
969 int align;
971 nasm_assert(!(seg & 1));
973 s = get_section_by_index(seg);
975 if (!s || !is_power2(value))
976 return;
978 align = alignlog2_32(value);
979 if (s->align < align)
980 s->align = align;
983 static int32_t macho_segbase(int32_t section)
985 return section;
988 static void macho_filename(char *inname, char *outname)
990 standard_extension(inname, outname, ".o");
993 extern macros_t macho_stdmac[];
995 /* Comparison function for qsort symbol layout. */
996 static int layout_compare (const struct symbol **s1,
997 const struct symbol **s2)
999 return (strcmp ((*s1)->name, (*s2)->name));
1002 /* The native assembler does a few things in a similar function
1004 * Remove temporary labels
1005 * Sort symbols according to local, external, undefined (by name)
1006 * Order the string table
1008 We do not remove temporary labels right now.
1010 numsyms is the total number of symbols we have. strtabsize is the
1011 number entries in the string table. */
1013 static void macho_layout_symbols (uint32_t *numsyms,
1014 uint32_t *strtabsize)
1016 struct symbol *sym, **symp;
1017 uint32_t i,j;
1019 *numsyms = 0;
1020 *strtabsize = sizeof (char);
1022 symp = &syms;
1024 while ((sym = *symp)) {
1025 /* Undefined symbols are now external. */
1026 if (sym->type == N_UNDF)
1027 sym->type |= N_EXT;
1029 if ((sym->type & N_EXT) == 0) {
1030 sym->snum = *numsyms;
1031 *numsyms = *numsyms + 1;
1032 nlocalsym++;
1034 else {
1035 if ((sym->type & N_TYPE) != N_UNDF) {
1036 nextdefsym++;
1037 } else {
1038 nundefsym++;
1041 /* If we handle debug info we'll want
1042 to check for it here instead of just
1043 adding the symbol to the string table. */
1044 sym->strx = *strtabsize;
1045 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
1046 *strtabsize += strlen(sym->name) + 1;
1048 symp = &(sym->next);
1051 /* Next, sort the symbols. Most of this code is a direct translation from
1052 the Apple cctools symbol layout. We need to keep compatibility with that. */
1053 /* Set the indexes for symbol groups into the symbol table */
1054 ilocalsym = 0;
1055 iextdefsym = nlocalsym;
1056 iundefsym = nlocalsym + nextdefsym;
1058 /* allocate arrays for sorting externals by name */
1059 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
1060 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
1062 i = 0;
1063 j = 0;
1065 symp = &syms;
1067 while ((sym = *symp)) {
1069 if((sym->type & N_EXT) == 0) {
1070 sym->strx = *strtabsize;
1071 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
1072 *strtabsize += strlen(sym->name) + 1;
1074 else {
1075 if((sym->type & N_TYPE) != N_UNDF) {
1076 extdefsyms[i++] = sym;
1077 } else {
1078 undefsyms[j++] = sym;
1081 symp = &(sym->next);
1084 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
1085 (int (*)(const void *, const void *))layout_compare);
1086 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
1087 (int (*)(const void *, const void *))layout_compare);
1089 for(i = 0; i < nextdefsym; i++) {
1090 extdefsyms[i]->snum = *numsyms;
1091 *numsyms += 1;
1093 for(j = 0; j < nundefsym; j++) {
1094 undefsyms[j]->snum = *numsyms;
1095 *numsyms += 1;
1099 /* Calculate some values we'll need for writing later. */
1101 static void macho_calculate_sizes (void)
1103 struct section *s;
1104 int fi;
1106 /* count sections and calculate in-memory and in-file offsets */
1107 for (s = sects; s != NULL; s = s->next) {
1108 uint64_t newaddr;
1110 /* recalculate segment address based on alignment and vm size */
1111 s->addr = seg_vmsize;
1113 /* we need section alignment to calculate final section address */
1114 if (s->align == -1)
1115 s->align = DEFAULT_SECTION_ALIGNMENT;
1117 newaddr = ALIGN(s->addr, UINT64_C(1) << s->align);
1118 s->addr = newaddr;
1120 seg_vmsize = newaddr + s->size;
1122 /* zerofill sections aren't actually written to the file */
1123 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1125 * LLVM/Xcode as always aligns the section data to 4
1126 * bytes; there is a comment in the LLVM source code that
1127 * perhaps aligning to pointer size would be better.
1129 s->pad = ALIGN(seg_filesize, 4) - seg_filesize;
1130 s->offset = seg_filesize + s->pad;
1131 seg_filesize += s->size + s->pad;
1135 /* calculate size of all headers, load commands and sections to
1136 ** get a pointer to the start of all the raw data */
1137 if (seg_nsects > 0) {
1138 ++head_ncmds;
1139 head_sizeofcmds += fmt.segcmd_size + seg_nsects * fmt.sectcmd_size;
1142 if (nsyms > 0) {
1143 ++head_ncmds;
1144 head_sizeofcmds += MACHO_SYMCMD_SIZE;
1147 if (seg_nsects > MAX_SECT) {
1148 nasm_fatal(0, "MachO output is limited to %d sections\n",
1149 MAX_SECT);
1152 /* Create a table of sections by file index to avoid linear search */
1153 sectstab = nasm_malloc((seg_nsects + 1) * sizeof(*sectstab));
1154 sectstab[NO_SECT] = &absolute_sect;
1155 for (s = sects, fi = 1; s != NULL; s = s->next, fi++)
1156 sectstab[fi] = s;
1159 /* Write out the header information for the file. */
1161 static void macho_write_header (void)
1163 fwriteint32_t(fmt.mh_magic, ofile); /* magic */
1164 fwriteint32_t(fmt.cpu_type, ofile); /* CPU type */
1165 fwriteint32_t(CPU_SUBTYPE_I386_ALL, ofile); /* CPU subtype */
1166 fwriteint32_t(MH_OBJECT, ofile); /* Mach-O file type */
1167 fwriteint32_t(head_ncmds, ofile); /* number of load commands */
1168 fwriteint32_t(head_sizeofcmds, ofile); /* size of load commands */
1169 fwriteint32_t(head_flags, ofile); /* flags, if any */
1170 fwritezero(fmt.header_size - 7*4, ofile); /* reserved fields */
1173 /* Write out the segment load command at offset. */
1175 static uint32_t macho_write_segment (uint64_t offset)
1177 uint64_t rel_base = alignptr(offset + seg_filesize);
1178 uint32_t s_reloff = 0;
1179 struct section *s;
1181 fwriteint32_t(fmt.lc_segment, ofile); /* cmd == LC_SEGMENT_64 */
1183 /* size of load command including section load commands */
1184 fwriteint32_t(fmt.segcmd_size + seg_nsects * fmt.sectcmd_size,
1185 ofile);
1187 /* in an MH_OBJECT file all sections are in one unnamed (name
1188 ** all zeros) segment */
1189 fwritezero(16, ofile);
1190 fwriteptr(0, ofile); /* in-memory offset */
1191 fwriteptr(seg_vmsize, ofile); /* in-memory size */
1192 fwriteptr(offset, ofile); /* in-file offset to data */
1193 fwriteptr(seg_filesize, ofile); /* in-file size */
1194 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* maximum vm protection */
1195 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* initial vm protection */
1196 fwriteint32_t(seg_nsects, ofile); /* number of sections */
1197 fwriteint32_t(0, ofile); /* no flags */
1199 /* emit section headers */
1200 for (s = sects; s != NULL; s = s->next) {
1201 if (s->nreloc) {
1202 nasm_assert((s->flags & SECTION_TYPE) != S_ZEROFILL);
1203 s->flags |= S_ATTR_LOC_RELOC;
1204 if (s->extreloc)
1205 s->flags |= S_ATTR_EXT_RELOC;
1206 } else if (!strcmp(s->segname, "__DATA") &&
1207 !strcmp(s->sectname, "__const") &&
1208 !s->by_name &&
1209 !get_section_by_name("__TEXT", "__const")) {
1211 * The MachO equivalent to .rodata can be either
1212 * __DATA,__const or __TEXT,__const; the latter only if
1213 * there are no relocations. However, when mixed it is
1214 * better to specify the segments explicitly.
1216 xstrncpy(s->segname, "__TEXT");
1219 nasm_write(s->sectname, sizeof(s->sectname), ofile);
1220 nasm_write(s->segname, sizeof(s->segname), ofile);
1221 fwriteptr(s->addr, ofile);
1222 fwriteptr(s->size, ofile);
1224 /* dummy data for zerofill sections or proper values */
1225 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1226 nasm_assert(s->pad != (uint32_t)-1);
1227 offset += s->pad;
1228 fwriteint32_t(offset, ofile);
1229 offset += s->size;
1230 /* Write out section alignment, as a power of two.
1231 e.g. 32-bit word alignment would be 2 (2^2 = 4). */
1232 fwriteint32_t(s->align, ofile);
1233 /* To be compatible with cctools as we emit
1234 a zero reloff if we have no relocations. */
1235 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile);
1236 fwriteint32_t(s->nreloc, ofile);
1238 s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
1239 } else {
1240 fwriteint32_t(0, ofile);
1241 fwriteint32_t(s->align, ofile);
1242 fwriteint32_t(0, ofile);
1243 fwriteint32_t(0, ofile);
1246 fwriteint32_t(s->flags, ofile); /* flags */
1247 fwriteint32_t(0, ofile); /* reserved */
1248 fwriteptr(0, ofile); /* reserved */
1251 rel_padcnt = rel_base - offset;
1252 offset = rel_base + s_reloff;
1254 return offset;
1257 /* For a given chain of relocs r, write out the entire relocation
1258 chain to the object file. */
1260 static void macho_write_relocs (struct reloc *r)
1262 while (r) {
1263 uint32_t word2;
1265 fwriteint32_t(r->addr, ofile); /* reloc offset */
1267 word2 = r->snum;
1268 word2 |= r->pcrel << 24;
1269 word2 |= r->length << 25;
1270 word2 |= r->ext << 27;
1271 word2 |= r->type << 28;
1272 fwriteint32_t(word2, ofile); /* reloc data */
1273 r = r->next;
1277 /* Write out the section data. */
1278 static void macho_write_section (void)
1280 struct section *s;
1281 struct reloc *r;
1282 uint8_t *p;
1283 int32_t len;
1284 int64_t l;
1285 union offset {
1286 uint64_t val;
1287 uint8_t buf[8];
1288 } blk;
1290 for (s = sects; s != NULL; s = s->next) {
1291 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
1292 continue;
1294 /* Like a.out Mach-O references things in the data or bss
1295 * sections by addresses which are actually relative to the
1296 * start of the _text_ section, in the _file_. See outaout.c
1297 * for more information. */
1298 saa_rewind(s->data);
1299 for (r = s->relocs; r != NULL; r = r->next) {
1300 len = (uint32_t)1 << r->length;
1301 if (len > 4) /* Can this ever be an issue?! */
1302 len = 8;
1303 blk.val = 0;
1304 saa_fread(s->data, r->addr, blk.buf, len);
1306 /* get offset based on relocation type */
1307 #ifdef WORDS_LITTLEENDIAN
1308 l = blk.val;
1309 #else
1310 l = blk.buf[0];
1311 l += ((int64_t)blk.buf[1]) << 8;
1312 l += ((int64_t)blk.buf[2]) << 16;
1313 l += ((int64_t)blk.buf[3]) << 24;
1314 l += ((int64_t)blk.buf[4]) << 32;
1315 l += ((int64_t)blk.buf[5]) << 40;
1316 l += ((int64_t)blk.buf[6]) << 48;
1317 l += ((int64_t)blk.buf[7]) << 56;
1318 #endif
1320 /* If the relocation is internal add to the current section
1321 offset. Otherwise the only value we need is the symbol
1322 offset which we already have. The linker takes care
1323 of the rest of the address. */
1324 if (!r->ext) {
1325 /* generate final address by section address and offset */
1326 nasm_assert(r->snum <= seg_nsects);
1327 l += sectstab[r->snum]->addr;
1328 if (r->pcrel)
1329 l -= s->addr;
1330 } else if (r->pcrel && r->type == GENERIC_RELOC_VANILLA) {
1331 l -= s->addr;
1334 /* write new offset back */
1335 p = blk.buf;
1336 WRITEDLONG(p, l);
1337 saa_fwrite(s->data, r->addr, blk.buf, len);
1340 /* dump the section data to file */
1341 fwritezero(s->pad, ofile);
1342 saa_fpwrite(s->data, ofile);
1345 /* pad last section up to reloc entries on pointer boundary */
1346 fwritezero(rel_padcnt, ofile);
1348 /* emit relocation entries */
1349 for (s = sects; s != NULL; s = s->next)
1350 macho_write_relocs (s->relocs);
1353 /* Write out the symbol table. We should already have sorted this
1354 before now. */
1355 static void macho_write_symtab (void)
1357 struct symbol *sym;
1358 uint64_t i;
1360 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1362 for (sym = syms; sym != NULL; sym = sym->next) {
1363 if ((sym->type & N_EXT) == 0) {
1364 fwriteint32_t(sym->strx, ofile); /* string table entry number */
1365 nasm_write(&sym->type, 1, ofile); /* symbol type */
1366 nasm_write(&sym->sect, 1, ofile); /* section */
1367 fwriteint16_t(sym->desc, ofile); /* description */
1369 /* Fix up the symbol value now that we know the final section
1370 sizes. */
1371 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1372 nasm_assert(sym->sect <= seg_nsects);
1373 sym->symv.key += sectstab[sym->sect]->addr;
1376 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1380 for (i = 0; i < nextdefsym; i++) {
1381 sym = extdefsyms[i];
1382 fwriteint32_t(sym->strx, ofile);
1383 nasm_write(&sym->type, 1, ofile); /* symbol type */
1384 nasm_write(&sym->sect, 1, ofile); /* section */
1385 fwriteint16_t(sym->desc, ofile); /* description */
1387 /* Fix up the symbol value now that we know the final section
1388 sizes. */
1389 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1390 nasm_assert(sym->sect <= seg_nsects);
1391 sym->symv.key += sectstab[sym->sect]->addr;
1394 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1397 for (i = 0; i < nundefsym; i++) {
1398 sym = undefsyms[i];
1399 fwriteint32_t(sym->strx, ofile);
1400 nasm_write(&sym->type, 1, ofile); /* symbol type */
1401 nasm_write(&sym->sect, 1, ofile); /* section */
1402 fwriteint16_t(sym->desc, ofile); /* description */
1404 /* Fix up the symbol value now that we know the final section
1405 sizes. */
1406 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1407 nasm_assert(sym->sect <= seg_nsects);
1408 sym->symv.key += sectstab[sym->sect]->addr;
1411 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1416 /* Fixup the snum in the relocation entries, we should be
1417 doing this only for externally referenced symbols. */
1418 static void macho_fixup_relocs (struct reloc *r)
1420 struct symbol *sym;
1422 while (r != NULL) {
1423 if (r->ext) {
1424 for (sym = syms; sym != NULL; sym = sym->next) {
1425 if (sym->initial_snum == r->snum) {
1426 r->snum = sym->snum;
1427 break;
1431 r = r->next;
1435 /* Write out the object file. */
1437 static void macho_write (void)
1439 uint64_t offset = 0;
1441 /* mach-o object file structure:
1443 ** mach header
1444 ** uint32_t magic
1445 ** int cpu type
1446 ** int cpu subtype
1447 ** uint32_t mach file type
1448 ** uint32_t number of load commands
1449 ** uint32_t size of all load commands
1450 ** (includes section struct size of segment command)
1451 ** uint32_t flags
1453 ** segment command
1454 ** uint32_t command type == LC_SEGMENT[_64]
1455 ** uint32_t size of load command
1456 ** (including section load commands)
1457 ** char[16] segment name
1458 ** pointer in-memory offset
1459 ** pointer in-memory size
1460 ** pointer in-file offset to data area
1461 ** pointer in-file size
1462 ** (in-memory size excluding zerofill sections)
1463 ** int maximum vm protection
1464 ** int initial vm protection
1465 ** uint32_t number of sections
1466 ** uint32_t flags
1468 ** section commands
1469 ** char[16] section name
1470 ** char[16] segment name
1471 ** pointer in-memory offset
1472 ** pointer in-memory size
1473 ** uint32_t in-file offset
1474 ** uint32_t alignment
1475 ** (irrelevant in MH_OBJECT)
1476 ** uint32_t in-file offset of relocation entires
1477 ** uint32_t number of relocations
1478 ** uint32_t flags
1479 ** uint32_t reserved
1480 ** uint32_t reserved
1482 ** symbol table command
1483 ** uint32_t command type == LC_SYMTAB
1484 ** uint32_t size of load command
1485 ** uint32_t symbol table offset
1486 ** uint32_t number of symbol table entries
1487 ** uint32_t string table offset
1488 ** uint32_t string table size
1490 ** raw section data
1492 ** padding to pointer boundary
1494 ** relocation data (struct reloc)
1495 ** int32_t offset
1496 ** uint data (symbolnum, pcrel, length, extern, type)
1498 ** symbol table data (struct nlist)
1499 ** int32_t string table entry number
1500 ** uint8_t type
1501 ** (extern, absolute, defined in section)
1502 ** uint8_t section
1503 ** (0 for global symbols, section number of definition (>= 1, <=
1504 ** 254) for local symbols, size of variable for common symbols
1505 ** [type == extern])
1506 ** int16_t description
1507 ** (for stab debugging format)
1508 ** pointer value (i.e. file offset) of symbol or stab offset
1510 ** string table data
1511 ** list of null-terminated strings
1514 /* Emit the Mach-O header. */
1515 macho_write_header();
1517 offset = fmt.header_size + head_sizeofcmds;
1519 /* emit the segment load command */
1520 if (seg_nsects > 0)
1521 offset = macho_write_segment (offset);
1522 else
1523 nasm_error(ERR_WARNING, "no sections?");
1525 if (nsyms > 0) {
1526 /* write out symbol command */
1527 fwriteint32_t(LC_SYMTAB, ofile); /* cmd == LC_SYMTAB */
1528 fwriteint32_t(MACHO_SYMCMD_SIZE, ofile); /* size of load command */
1529 fwriteint32_t(offset, ofile); /* symbol table offset */
1530 fwriteint32_t(nsyms, ofile); /* number of symbol
1531 ** table entries */
1532 offset += nsyms * fmt.nlist_size;
1533 fwriteint32_t(offset, ofile); /* string table offset */
1534 fwriteint32_t(strslen, ofile); /* string table size */
1537 /* emit section data */
1538 if (seg_nsects > 0)
1539 macho_write_section ();
1541 /* emit symbol table if we have symbols */
1542 if (nsyms > 0)
1543 macho_write_symtab ();
1545 /* we don't need to pad here, we are already aligned */
1547 /* emit string table */
1548 saa_fpwrite(strs, ofile);
1550 /* We do quite a bit here, starting with finalizing all of the data
1551 for the object file, writing, and then freeing all of the data from
1552 the file. */
1554 static void macho_cleanup(void)
1556 struct section *s;
1557 struct reloc *r;
1558 struct symbol *sym;
1560 /* Sort all symbols. */
1561 macho_layout_symbols (&nsyms, &strslen);
1563 /* Fixup relocation entries */
1564 for (s = sects; s != NULL; s = s->next) {
1565 macho_fixup_relocs (s->relocs);
1568 /* First calculate and finalize needed values. */
1569 macho_calculate_sizes();
1570 macho_write();
1572 /* free up everything */
1573 while (sects->next) {
1574 s = sects;
1575 sects = sects->next;
1577 saa_free(s->data);
1578 while (s->relocs != NULL) {
1579 r = s->relocs;
1580 s->relocs = s->relocs->next;
1581 nasm_free(r);
1584 nasm_free(s);
1587 saa_free(strs);
1588 raa_free(extsyms);
1590 while (syms) {
1591 sym = syms;
1592 syms = syms->next;
1593 nasm_free (sym);
1596 nasm_free(extdefsyms);
1597 nasm_free(undefsyms);
1598 nasm_free(sectstab);
1602 * Mach-O-specific directives
1604 static enum directive_result
1605 macho_directive(enum directives directive, char *value, int pass)
1607 switch (directive) {
1608 case D_SUBSECTIONS_VIA_SYMBOLS:
1609 if (*value)
1610 return DIRR_BADPARAM;
1612 if (pass == 2)
1613 head_flags |= MH_SUBSECTIONS_VIA_SYMBOLS;
1615 return DIRR_OK;
1617 default:
1618 return DIRR_UNKNOWN; /* Not a Mach-O directive */
1622 #ifdef OF_MACHO32
1623 static const struct macho_fmt macho32_fmt = {
1625 MH_MAGIC,
1626 CPU_TYPE_I386,
1627 LC_SEGMENT,
1628 MACHO_HEADER_SIZE,
1629 MACHO_SEGCMD_SIZE,
1630 MACHO_SECTCMD_SIZE,
1631 MACHO_NLIST_SIZE,
1632 RL_MAX_32,
1633 GENERIC_RELOC_VANILLA,
1634 GENERIC_RELOC_VANILLA,
1635 GENERIC_RELOC_TLV
1638 static void macho32_init(void)
1640 fmt = macho32_fmt;
1641 macho_init();
1643 macho_gotpcrel_sect = NO_SEG;
1646 const struct ofmt of_macho32 = {
1647 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files",
1648 "macho32",
1651 null_debug_arr,
1652 &null_debug_form,
1653 macho_stdmac,
1654 macho32_init,
1655 null_setinfo,
1656 nasm_do_legacy_output,
1657 macho_output,
1658 macho_symdef,
1659 macho_section,
1660 macho_sectalign,
1661 macho_segbase,
1662 macho_directive,
1663 macho_filename,
1664 macho_cleanup,
1665 NULL /* pragma list */
1667 #endif
1669 #ifdef OF_MACHO64
1670 static const struct macho_fmt macho64_fmt = {
1672 MH_MAGIC_64,
1673 CPU_TYPE_X86_64,
1674 LC_SEGMENT_64,
1675 MACHO_HEADER64_SIZE,
1676 MACHO_SEGCMD64_SIZE,
1677 MACHO_SECTCMD64_SIZE,
1678 MACHO_NLIST64_SIZE,
1679 RL_MAX_64,
1680 X86_64_RELOC_UNSIGNED,
1681 X86_64_RELOC_SIGNED,
1682 X86_64_RELOC_TLV
1685 static void macho64_init(void)
1687 fmt = macho64_fmt;
1688 macho_init();
1690 /* add special symbol for ..gotpcrel */
1691 macho_gotpcrel_sect = seg_alloc() + 1;
1692 define_label("..gotpcrel", macho_gotpcrel_sect, 0L, NULL, false, false);
1695 const struct ofmt of_macho64 = {
1696 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files",
1697 "macho64",
1700 null_debug_arr,
1701 &null_debug_form,
1702 macho_stdmac,
1703 macho64_init,
1704 null_setinfo,
1705 nasm_do_legacy_output,
1706 macho_output,
1707 macho_symdef,
1708 macho_section,
1709 macho_sectalign,
1710 macho_segbase,
1711 macho_directive,
1712 macho_filename,
1713 macho_cleanup,
1714 NULL /* pragma list */
1716 #endif
1718 #endif
1721 * Local Variables:
1722 * mode:c
1723 * c-basic-offset:4
1724 * End:
1726 * end of file */