Remove unnecessary C99-isms
[nasm.git] / output / outmacho.c
blob746dbcbbfb103222d19601aced15757c4cfc14fc
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>
45 #include <inttypes.h>
47 #include "nasm.h"
48 #include "nasmlib.h"
49 #include "saa.h"
50 #include "raa.h"
51 #include "rbtree.h"
52 #include "output/outform.h"
53 #include "output/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 load commands */
79 #define LC_SEGMENT 0x1 /* 32-bit segment load cmd */
80 #define LC_SEGMENT_64 0x19 /* 64-bit segment load cmd */
81 #define LC_SYMTAB 0x2 /* symbol table load command */
83 /* Mach-O relocations numbers */
85 /* Generic relocs, used by i386 Mach-O */
86 #define GENERIC_RELOC_VANILLA 0 /* Generic relocation */
87 #define GENERIC_RELOC_TLV 5 /* Thread local */
89 #define X86_64_RELOC_UNSIGNED 0 /* Absolute address */
90 #define X86_64_RELOC_SIGNED 1 /* Signed 32-bit disp */
91 #define X86_64_RELOC_BRANCH 2 /* CALL/JMP with 32-bit disp */
92 #define X86_64_RELOC_GOT_LOAD 3 /* MOVQ of GOT entry */
93 #define X86_64_RELOC_GOT 4 /* Different GOT entry */
94 #define X86_64_RELOC_SUBTRACTOR 5 /* Subtracting two symbols */
95 #define X86_64_RELOC_SIGNED_1 6 /* SIGNED with -1 addend */
96 #define X86_64_RELOC_SIGNED_2 7 /* SIGNED with -2 addend */
97 #define X86_64_RELOC_SIGNED_4 8 /* SIGNED with -4 addend */
98 #define X86_64_RELOC_TLV 9 /* Thread local */
100 /* Mach-O VM permission constants */
101 #define VM_PROT_NONE (0x00)
102 #define VM_PROT_READ (0x01)
103 #define VM_PROT_WRITE (0x02)
104 #define VM_PROT_EXECUTE (0x04)
106 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
107 #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
109 /* Our internal relocation types */
110 enum reltype {
111 RL_ABS, /* Absolute relocation */
112 RL_REL, /* Relative relocation */
113 RL_TLV, /* Thread local */
114 RL_BRANCH, /* Relative direct branch */
115 RL_SUB, /* X86_64_RELOC_SUBTRACT */
116 RL_GOT, /* X86_64_RELOC_GOT */
117 RL_GOTLOAD /* X86_64_RELOC_GOT_LOAD */
119 #define RL_MAX_32 RL_TLV
120 #define RL_MAX_64 RL_GOTLOAD
122 struct macho_fmt {
123 uint32_t ptrsize; /* Pointer size in bytes */
124 uint32_t mh_magic; /* Which magic number to use */
125 uint32_t cpu_type; /* Which CPU type */
126 uint32_t lc_segment; /* Which segment load command */
127 uint32_t header_size; /* Header size */
128 uint32_t segcmd_size; /* Segment command size */
129 uint32_t sectcmd_size; /* Section command size */
130 uint32_t nlist_size; /* Nlist (symbol) size */
131 enum reltype maxreltype; /* Maximum entry in enum reltype permitted */
132 uint32_t reloc_abs; /* Absolute relocation type */
133 uint32_t reloc_rel; /* Relative relocation type */
134 uint32_t reloc_tlv; /* Thread local relocation type */
137 static struct macho_fmt fmt;
139 static void fwriteptr(uint64_t data, FILE * fp)
141 fwriteaddr(data, fmt.ptrsize, fp);
144 struct section {
145 /* nasm internal data */
146 struct section *next;
147 struct SAA *data;
148 int32_t index;
149 int32_t fileindex;
150 struct reloc *relocs;
151 struct rbtree *gsyms; /* Global symbols in section */
152 int align;
153 bool by_name; /* This section was specified by full MachO name */
155 /* data that goes into the file */
156 char sectname[16]; /* what this section is called */
157 char segname[16]; /* segment this section will be in */
158 uint64_t addr; /* in-memory address (subject to alignment) */
159 uint64_t size; /* in-memory and -file size */
160 uint64_t offset; /* in-file offset */
161 uint32_t pad; /* padding bytes before section */
162 uint32_t nreloc; /* relocation entry count */
163 uint32_t flags; /* type and attributes (masked) */
164 uint32_t extreloc; /* external relocations */
167 #define SECTION_TYPE 0x000000ff /* section type mask */
169 #define S_REGULAR (0x0) /* standard section */
170 #define S_ZEROFILL (0x1) /* zerofill, in-memory only */
172 #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
173 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
174 machine instructions */
175 #define S_ATTR_EXT_RELOC 0x00000200 /* section has external
176 relocation entries */
177 #define S_ATTR_LOC_RELOC 0x00000100 /* section has local
178 relocation entries */
179 #define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section uses pure
180 machine instructions */
182 /* Fake section for absolute symbols, *not* part of the section linked list */
183 static struct section absolute_sect;
185 static const struct sectmap {
186 const char *nasmsect;
187 const char *segname;
188 const char *sectname;
189 const int32_t flags;
190 } sectmap[] = {
191 {".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS},
192 {".data", "__DATA", "__data", S_REGULAR},
193 {".rodata", "__DATA", "__const", S_REGULAR},
194 {".bss", "__DATA", "__bss", S_ZEROFILL},
195 {NULL, NULL, NULL, 0}
198 struct reloc {
199 /* nasm internal data */
200 struct reloc *next;
202 /* data that goes into the file */
203 int32_t addr; /* op's offset in section */
204 uint32_t snum:24, /* contains symbol index if
205 ** ext otherwise in-file
206 ** section number */
207 pcrel:1, /* relative relocation */
208 length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */
209 ext:1, /* external symbol referenced */
210 type:4; /* reloc type */
213 #define R_ABS 0 /* absolute relocation */
214 #define R_SCATTERED 0x80000000 /* reloc entry is scattered if
215 ** highest bit == 1 */
217 struct symbol {
218 /* nasm internal data */
219 struct rbtree symv; /* Global symbol rbtree; "key" contains the
220 symbol offset. */
221 struct symbol *next; /* next symbol in the list */
222 char *name; /* name of this symbol */
223 int32_t initial_snum; /* symbol number used above in reloc */
224 int32_t snum; /* true snum for reloc */
226 /* data that goes into the file */
227 uint32_t strx; /* string table index */
228 uint8_t type; /* symbol type */
229 uint8_t sect; /* NO_SECT or section number */
230 uint16_t desc; /* for stab debugging, 0 for us */
233 /* symbol type bits */
234 #define N_EXT 0x01 /* global or external symbol */
236 #define N_UNDF 0x0 /* undefined symbol | n_sect == */
237 #define N_ABS 0x2 /* absolute symbol | NO_SECT */
238 #define N_SECT 0xe /* defined symbol, n_sect holds
239 ** section number */
241 #define N_TYPE 0x0e /* type bit mask */
243 #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
245 /* special section number values */
246 #define NO_SECT 0 /* no section, invalid */
247 #define MAX_SECT 255 /* maximum number of sections */
249 static struct section *sects, **sectstail, **sectstab;
250 static struct symbol *syms, **symstail;
251 static uint32_t nsyms;
253 /* These variables are set by macho_layout_symbols() to organize
254 the symbol table and string table in order the dynamic linker
255 expects. They are then used in macho_write() to put out the
256 symbols and strings in that order.
258 The order of the symbol table is:
259 local symbols
260 defined external symbols (sorted by name)
261 undefined external symbols (sorted by name)
263 The order of the string table is:
264 strings for external symbols
265 strings for local symbols
267 static uint32_t ilocalsym = 0;
268 static uint32_t iextdefsym = 0;
269 static uint32_t iundefsym = 0;
270 static uint32_t nlocalsym;
271 static uint32_t nextdefsym;
272 static uint32_t nundefsym;
273 static struct symbol **extdefsyms = NULL;
274 static struct symbol **undefsyms = NULL;
276 static struct RAA *extsyms;
277 static struct SAA *strs;
278 static uint32_t strslen;
280 /* Global file information. This should be cleaned up into either
281 a structure or as function arguments. */
282 static uint32_t head_ncmds = 0;
283 static uint32_t head_sizeofcmds = 0;
284 static uint64_t seg_filesize = 0;
285 static uint64_t seg_vmsize = 0;
286 static uint32_t seg_nsects = 0;
287 static uint64_t rel_padcnt = 0;
289 #define xstrncpy(xdst, xsrc) \
290 memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \
291 strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \
292 xdst[sizeof(xdst) - 1] = '\0'; /* proper null-termination */
294 #define alignint32_t(x) \
295 ALIGN(x, sizeof(int32_t)) /* align x to int32_t boundary */
297 #define alignint64_t(x) \
298 ALIGN(x, sizeof(int64_t)) /* align x to int64_t boundary */
300 #define alignptr(x) \
301 ALIGN(x, fmt.ptrsize) /* align x to output format width */
303 static void debug_reloc (struct reloc *);
304 static void debug_section_relocs (struct section *) _unused;
306 static struct section *get_section_by_name(const char *segname,
307 const char *sectname)
309 struct section *s;
311 for (s = sects; s != NULL; s = s->next)
312 if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname))
313 break;
315 return s;
318 static struct section *get_section_by_index(const int32_t index)
320 struct section *s;
322 for (s = sects; s != NULL; s = s->next)
323 if (index == s->index)
324 break;
326 return s;
330 * Special section numbers which are used to define Mach-O special
331 * symbols, which can be used with WRT to provide PIC relocation
332 * types.
334 static int32_t macho_tlvp_sect;
335 static int32_t macho_gotpcrel_sect;
337 static void macho_init(void)
339 sects = NULL;
340 sectstail = &sects;
342 /* Fake section for absolute symbols */
343 absolute_sect.index = NO_SEG;
345 syms = NULL;
346 symstail = &syms;
347 nsyms = 0;
348 nlocalsym = 0;
349 nextdefsym = 0;
350 nundefsym = 0;
352 extsyms = raa_init();
353 strs = saa_init(1L);
355 /* string table starts with a zero byte so index 0 is an empty string */
356 saa_wbytes(strs, zero_buffer, 1);
357 strslen = 1;
359 /* add special symbol for TLVP */
360 macho_tlvp_sect = seg_alloc() + 1;
361 define_label("..tlvp", macho_tlvp_sect, 0L, NULL, false, false);
365 static void sect_write(struct section *sect,
366 const uint8_t *data, uint32_t len)
368 saa_wbytes(sect->data, data, len);
369 sect->size += len;
373 * Find a suitable global symbol for a ..gotpcrel or ..tlvp reference
375 static struct symbol *macho_find_gsym(struct section *s,
376 uint64_t offset, bool exact)
378 struct rbtree *srb;
380 srb = rb_search(s->gsyms, offset);
382 if (!srb || (exact && srb->key != offset)) {
383 nasm_error(ERR_NONFATAL, "unable to find a suitable %s symbol"
384 " for this reference",
385 s == &absolute_sect ? "absolute" : "global");
386 return NULL;
389 return container_of(srb, struct symbol, symv);
392 static int64_t add_reloc(struct section *sect, int32_t section,
393 int64_t offset,
394 enum reltype reltype, int bytes)
396 struct reloc *r;
397 struct section *s;
398 int32_t fi;
399 int64_t adjust;
401 /* Double check this is a valid relocation type for this platform */
402 nasm_assert(reltype <= fmt.maxreltype);
404 /* the current end of the section will be the symbol's address for
405 ** now, might have to be fixed by macho_fixup_relocs() later on. make
406 ** sure we don't make the symbol scattered by setting the highest
407 ** bit by accident */
408 r = nasm_malloc(sizeof(struct reloc));
409 r->addr = sect->size & ~R_SCATTERED;
410 r->ext = 1;
411 adjust = bytes;
413 /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
414 r->length = ilog2_32(bytes);
416 /* set default relocation values */
417 r->type = fmt.reloc_abs;
418 r->pcrel = 0;
419 r->snum = R_ABS;
421 s = NULL;
422 if (section != NO_SEG)
423 s = get_section_by_index(section);
424 fi = s ? s->fileindex : NO_SECT;
426 /* absolute relocation */
427 switch (reltype) {
428 case RL_ABS:
429 if (section == NO_SEG) {
430 /* absolute (can this even happen?) */
431 r->ext = 0;
432 r->snum = R_ABS;
433 } else if (fi == NO_SECT) {
434 /* external */
435 r->snum = raa_read(extsyms, section);
436 } else {
437 /* local */
438 r->ext = 0;
439 r->snum = fi;
440 adjust = -sect->size;
442 break;
444 case RL_REL:
445 case RL_BRANCH:
446 r->type = fmt.reloc_rel;
447 r->pcrel = 1;
448 if (section == NO_SEG) {
449 /* absolute - seems to produce garbage no matter what */
450 nasm_error(ERR_NONFATAL, "Mach-O does not support relative "
451 "references to absolute addresses");
452 goto bail;
453 #if 0
454 /* This "seems" to be how it ought to work... */
456 struct symbol *sym = macho_find_gsym(&absolute_sect,
457 offset, false);
458 if (!sym)
459 goto bail;
461 sect->extreloc = 1;
462 r->snum = NO_SECT;
463 adjust = -sect->size;
464 #endif
465 } else if (fi == NO_SECT) {
466 /* external */
467 sect->extreloc = 1;
468 r->snum = raa_read(extsyms, section);
469 if (reltype == RL_BRANCH)
470 r->type = X86_64_RELOC_BRANCH;
471 } else {
472 /* local */
473 r->ext = 0;
474 r->snum = fi;
475 adjust = -sect->size;
477 break;
479 case RL_SUB:
480 r->pcrel = 0;
481 r->type = X86_64_RELOC_SUBTRACTOR;
482 break;
484 case RL_GOT:
485 r->type = X86_64_RELOC_GOT;
486 goto needsym;
488 case RL_GOTLOAD:
489 r->type = X86_64_RELOC_GOT_LOAD;
490 goto needsym;
492 case RL_TLV:
493 r->type = fmt.reloc_tlv;
494 goto needsym;
496 needsym:
497 r->pcrel = 1;
498 if (section == NO_SEG) {
499 nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT");
500 } else if (fi == NO_SECT) {
501 /* external */
502 r->snum = raa_read(extsyms, section);
503 } else {
504 /* internal */
505 struct symbol *sym = macho_find_gsym(s, offset, reltype != RL_TLV);
506 if (!sym)
507 goto bail;
508 r->snum = sym->initial_snum;
510 break;
513 /* NeXT as puts relocs in reversed order (address-wise) into the
514 ** files, so we do the same, doesn't seem to make much of a
515 ** difference either way */
516 r->next = sect->relocs;
517 sect->relocs = r;
518 if (r->ext)
519 sect->extreloc = 1;
520 ++sect->nreloc;
522 return adjust;
524 bail:
525 nasm_free(r);
526 return 0;
529 static void macho_output(int32_t secto, const void *data,
530 enum out_type type, uint64_t size,
531 int32_t section, int32_t wrt)
533 struct section *s;
534 int64_t addr, offset;
535 uint8_t mydata[16], *p;
536 bool is_bss;
537 enum reltype reltype;
539 if (secto == NO_SEG) {
540 if (type != OUT_RESERVE)
541 nasm_error(ERR_NONFATAL, "attempt to assemble code in "
542 "[ABSOLUTE] space");
543 return;
546 s = get_section_by_index(secto);
548 if (s == NULL) {
549 nasm_error(ERR_WARNING, "attempt to assemble code in"
550 " section %d: defaulting to `.text'", secto);
551 s = get_section_by_name("__TEXT", "__text");
553 /* should never happen */
554 if (s == NULL)
555 nasm_panic(0, "text section not found");
558 is_bss = (s->flags & SECTION_TYPE) == S_ZEROFILL;
560 if (is_bss && type != OUT_RESERVE) {
561 nasm_error(ERR_WARNING, "attempt to initialize memory in "
562 "BSS section: ignored");
563 s->size += realsize(type, size);
564 return;
567 memset(mydata, 0, sizeof(mydata));
569 switch (type) {
570 case OUT_RESERVE:
571 if (!is_bss) {
572 nasm_error(ERR_WARNING, "uninitialized space declared in"
573 " %s,%s section: zeroing", s->segname, s->sectname);
575 sect_write(s, NULL, size);
576 } else
577 s->size += size;
579 break;
581 case OUT_RAWDATA:
582 if (section != NO_SEG)
583 nasm_panic(0, "OUT_RAWDATA with other than NO_SEG");
585 sect_write(s, data, size);
586 break;
588 case OUT_ADDRESS:
590 int asize = abs((int)size);
592 addr = *(int64_t *)data;
593 if (section != NO_SEG) {
594 if (section % 2) {
595 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
596 " section base references");
597 } else if (wrt == NO_SEG) {
598 if (fmt.ptrsize == 8 && asize != 8) {
599 nasm_error(ERR_NONFATAL,
600 "Mach-O 64-bit format does not support"
601 " 32-bit absolute addresses");
602 } else {
603 add_reloc(s, section, addr, RL_ABS, asize);
605 } else {
606 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
607 " this use of WRT");
611 p = mydata;
612 WRITEADDR(p, addr, asize);
613 sect_write(s, mydata, asize);
614 break;
617 case OUT_REL2ADR:
618 nasm_assert(section != secto);
620 p = mydata;
621 offset = *(int64_t *)data;
622 addr = offset - size;
624 if (section != NO_SEG && section % 2) {
625 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
626 " section base references");
627 } else if (fmt.ptrsize == 8) {
628 nasm_error(ERR_NONFATAL, "Unsupported non-32-bit"
629 " Macho-O relocation [2]");
630 } else if (wrt != NO_SEG) {
631 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
632 " this use of WRT");
633 wrt = NO_SEG; /* we can at least _try_ to continue */
634 } else {
635 addr += add_reloc(s, section, addr+size, RL_REL, 2);
638 WRITESHORT(p, addr);
639 sect_write(s, mydata, 2);
640 break;
642 case OUT_REL4ADR:
643 nasm_assert(section != secto);
645 p = mydata;
646 offset = *(int64_t *)data;
647 addr = offset - size;
648 reltype = RL_REL;
650 if (section != NO_SEG && section % 2) {
651 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
652 " section base references");
653 } else if (wrt == NO_SEG) {
654 if (fmt.ptrsize == 8 &&
655 (s->flags & S_ATTR_SOME_INSTRUCTIONS)) {
656 uint8_t opcode[2];
658 opcode[0] = opcode[1] = 0;
660 /* HACK: Retrieve instruction opcode */
661 if (likely(s->data->datalen >= 2)) {
662 saa_fread(s->data, s->data->datalen-2, opcode, 2);
663 } else if (s->data->datalen == 1) {
664 saa_fread(s->data, 0, opcode+1, 1);
667 if ((opcode[0] != 0x0f && (opcode[1] & 0xfe) == 0xe8) ||
668 (opcode[0] == 0x0f && (opcode[1] & 0xf0) == 0x80)) {
669 /* Direct call, jmp, or jcc */
670 reltype = RL_BRANCH;
673 } else if (wrt == macho_gotpcrel_sect) {
674 reltype = RL_GOT;
676 if ((s->flags & S_ATTR_SOME_INSTRUCTIONS) &&
677 s->data->datalen >= 3) {
678 uint8_t gotload[3];
680 /* HACK: Retrieve instruction opcode */
681 saa_fread(s->data, s->data->datalen-3, gotload, 3);
682 if ((gotload[0] & 0xf8) == 0x48 &&
683 gotload[1] == 0x8b &&
684 (gotload[2] & 0307) == 0005) {
685 /* movq <reg>,[rel sym wrt ..gotpcrel] */
686 reltype = RL_GOTLOAD;
689 } else if (wrt == macho_tlvp_sect) {
690 reltype = RL_TLV;
691 } else {
692 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
693 " this use of WRT");
694 /* continue with RL_REL */
697 addr += add_reloc(s, section, offset, reltype, 4);
698 WRITELONG(p, addr);
699 sect_write(s, mydata, 4);
700 break;
702 default:
703 nasm_error(ERR_NONFATAL, "Unrepresentable relocation in Mach-O");
704 break;
708 static int32_t macho_section(char *name, int pass, int *bits)
710 char *sectionAttributes;
711 const struct sectmap *sm;
712 struct section *s;
713 const char *section, *segment;
714 uint32_t flags;
715 char *currentAttribute;
716 char *comma;
717 bool new_seg;
719 (void)pass;
721 /* Default to the appropriate number of bits. */
722 if (!name) {
723 *bits = fmt.ptrsize << 3;
724 name = ".text";
725 sectionAttributes = NULL;
726 } else {
727 sectionAttributes = name;
728 name = nasm_strsep(&sectionAttributes, " \t");
731 section = segment = NULL;
732 flags = 0;
734 comma = strchr(name, ',');
735 if (comma) {
736 int len;
738 *comma = '\0';
739 segment = name;
740 section = comma+1;
742 len = strlen(segment);
743 if (len == 0) {
744 nasm_error(ERR_NONFATAL, "empty segment name\n");
745 } else if (len >= 16) {
746 nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment);
749 len = strlen(section);
750 if (len == 0) {
751 nasm_error(ERR_NONFATAL, "empty section name\n");
752 } else if (len >= 16) {
753 nasm_error(ERR_NONFATAL, "section name %s too long\n", section);
756 if (!strcmp(section, "__text")) {
757 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
758 S_ATTR_PURE_INSTRUCTIONS;
759 } else if (!strcmp(section, "__bss")) {
760 flags = S_ZEROFILL;
761 } else {
762 flags = S_REGULAR;
764 } else {
765 for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
766 /* make lookup into section name translation table */
767 if (!strcmp(name, sm->nasmsect)) {
768 segment = sm->segname;
769 section = sm->sectname;
770 flags = sm->flags;
771 goto found;
774 nasm_error(ERR_NONFATAL, "unknown section name\n");
775 return NO_SEG;
778 found:
779 /* try to find section with that name */
780 s = get_section_by_name(segment, section);
782 /* create it if it doesn't exist yet */
783 if (!s) {
784 new_seg = true;
786 s = *sectstail = nasm_zalloc(sizeof(struct section));
787 sectstail = &s->next;
789 s->data = saa_init(1L);
790 s->index = seg_alloc();
791 s->fileindex = ++seg_nsects;
792 s->align = -1;
793 s->pad = -1;
794 s->offset = -1;
795 s->by_name = false;
797 xstrncpy(s->segname, segment);
798 xstrncpy(s->sectname, section);
799 s->size = 0;
800 s->nreloc = 0;
801 s->flags = flags;
802 } else {
803 new_seg = false;
806 if (comma)
807 *comma = ','; /* Restore comma */
809 s->by_name = s->by_name || comma; /* Was specified by name */
811 flags = (uint32_t)-1;
813 while ((NULL != sectionAttributes)
814 && (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
815 if (0 != *currentAttribute) {
816 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
817 char *end;
818 int newAlignment, value;
820 value = strtoul(currentAttribute + 6, (char**)&end, 0);
821 newAlignment = alignlog2_32(value);
823 if (0 != *end) {
824 nasm_error(ERR_NONFATAL,
825 "unknown or missing alignment value \"%s\" "
826 "specified for section \"%s\"",
827 currentAttribute + 6,
828 name);
829 } else if (0 > newAlignment) {
830 nasm_error(ERR_NONFATAL,
831 "alignment of %d (for section \"%s\") is not "
832 "a power of two",
833 value,
834 name);
837 if (s->align < newAlignment)
838 s->align = newAlignment;
839 } else if (!nasm_stricmp("data", currentAttribute)) {
840 flags = S_REGULAR;
841 } else if (!nasm_stricmp("code", currentAttribute) ||
842 !nasm_stricmp("text", currentAttribute)) {
843 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
844 S_ATTR_PURE_INSTRUCTIONS;
845 } else if (!nasm_stricmp("mixed", currentAttribute)) {
846 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS;
847 } else if (!nasm_stricmp("bss", currentAttribute)) {
848 flags = S_ZEROFILL;
849 } else {
850 nasm_error(ERR_NONFATAL,
851 "unknown section attribute %s for section %s",
852 currentAttribute,
853 name);
857 if (flags != (uint32_t)-1) {
858 if (!new_seg && s->flags != flags) {
859 nasm_error(ERR_NONFATAL,
860 "inconsistent section attributes for section %s\n",
861 name);
862 } else {
863 s->flags = flags;
868 return s->index;
871 static void macho_symdef(char *name, int32_t section, int64_t offset,
872 int is_global, char *special)
874 struct symbol *sym;
876 if (special) {
877 nasm_error(ERR_NONFATAL, "The Mach-O output format does "
878 "not support any special symbol types");
879 return;
882 if (is_global == 3) {
883 nasm_error(ERR_NONFATAL, "The Mach-O format does not "
884 "(yet) support forward reference fixups.");
885 return;
888 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
890 * This is a NASM special symbol. We never allow it into
891 * the Macho-O symbol table, even if it's a valid one. If it
892 * _isn't_ a valid one, we should barf immediately.
894 if (strcmp(name, "..gotpcrel") && strcmp(name, "..tlvp"))
895 nasm_error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
896 return;
899 sym = *symstail = nasm_zalloc(sizeof(struct symbol));
900 sym->next = NULL;
901 symstail = &sym->next;
903 sym->name = name;
904 sym->strx = strslen;
905 sym->type = 0;
906 sym->desc = 0;
907 sym->symv.key = offset;
908 sym->initial_snum = -1;
910 /* external and common symbols get N_EXT */
911 if (is_global != 0) {
912 sym->type |= N_EXT;
915 if (section == NO_SEG) {
916 /* symbols in no section get absolute */
917 sym->type |= N_ABS;
918 sym->sect = NO_SECT;
920 /* all absolute symbols are available to use as references */
921 absolute_sect.gsyms = rb_insert(absolute_sect.gsyms, &sym->symv);
922 } else {
923 struct section *s = get_section_by_index(section);
925 sym->type |= N_SECT;
927 /* get the in-file index of the section the symbol was defined in */
928 sym->sect = s ? s->fileindex : NO_SECT;
930 /* track the initially allocated symbol number for use in future fix-ups */
931 sym->initial_snum = nsyms;
933 if (!s) {
934 /* remember symbol number of references to external
935 ** symbols, this works because every external symbol gets
936 ** its own section number allocated internally by nasm and
937 ** can so be used as a key */
938 extsyms = raa_write(extsyms, section, nsyms);
940 switch (is_global) {
941 case 1:
942 case 2:
943 /* there isn't actually a difference between global
944 ** and common symbols, both even have their size in
945 ** sym->symv.key */
946 sym->type = N_EXT;
947 break;
949 default:
950 /* give an error on unfound section if it's not an
951 ** external or common symbol (assemble_file() does a
952 ** seg_alloc() on every call for them) */
953 nasm_panic(0, "in-file index for section %d not found, is_global = %d", section, is_global);
954 break;
956 } else if (is_global) {
957 s->gsyms = rb_insert(s->gsyms, &sym->symv);
960 ++nsyms;
963 static void macho_sectalign(int32_t seg, unsigned int value)
965 struct section *s;
966 int align;
968 nasm_assert(!(seg & 1));
970 s = get_section_by_index(seg);
972 if (!s || !is_power2(value))
973 return;
975 align = alignlog2_32(value);
976 if (s->align < align)
977 s->align = align;
980 static int32_t macho_segbase(int32_t section)
982 return section;
985 static void macho_filename(char *inname, char *outname)
987 standard_extension(inname, outname, ".o");
990 extern macros_t macho_stdmac[];
992 /* Comparison function for qsort symbol layout. */
993 static int layout_compare (const struct symbol **s1,
994 const struct symbol **s2)
996 return (strcmp ((*s1)->name, (*s2)->name));
999 /* The native assembler does a few things in a similar function
1001 * Remove temporary labels
1002 * Sort symbols according to local, external, undefined (by name)
1003 * Order the string table
1005 We do not remove temporary labels right now.
1007 numsyms is the total number of symbols we have. strtabsize is the
1008 number entries in the string table. */
1010 static void macho_layout_symbols (uint32_t *numsyms,
1011 uint32_t *strtabsize)
1013 struct symbol *sym, **symp;
1014 uint32_t i,j;
1016 *numsyms = 0;
1017 *strtabsize = sizeof (char);
1019 symp = &syms;
1021 while ((sym = *symp)) {
1022 /* Undefined symbols are now external. */
1023 if (sym->type == N_UNDF)
1024 sym->type |= N_EXT;
1026 if ((sym->type & N_EXT) == 0) {
1027 sym->snum = *numsyms;
1028 *numsyms = *numsyms + 1;
1029 nlocalsym++;
1031 else {
1032 if ((sym->type & N_TYPE) != N_UNDF) {
1033 nextdefsym++;
1034 } else {
1035 nundefsym++;
1038 /* If we handle debug info we'll want
1039 to check for it here instead of just
1040 adding the symbol to the string table. */
1041 sym->strx = *strtabsize;
1042 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
1043 *strtabsize += strlen(sym->name) + 1;
1045 symp = &(sym->next);
1048 /* Next, sort the symbols. Most of this code is a direct translation from
1049 the Apple cctools symbol layout. We need to keep compatibility with that. */
1050 /* Set the indexes for symbol groups into the symbol table */
1051 ilocalsym = 0;
1052 iextdefsym = nlocalsym;
1053 iundefsym = nlocalsym + nextdefsym;
1055 /* allocate arrays for sorting externals by name */
1056 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
1057 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
1059 i = 0;
1060 j = 0;
1062 symp = &syms;
1064 while ((sym = *symp)) {
1066 if((sym->type & N_EXT) == 0) {
1067 sym->strx = *strtabsize;
1068 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
1069 *strtabsize += strlen(sym->name) + 1;
1071 else {
1072 if((sym->type & N_TYPE) != N_UNDF) {
1073 extdefsyms[i++] = sym;
1074 } else {
1075 undefsyms[j++] = sym;
1078 symp = &(sym->next);
1081 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
1082 (int (*)(const void *, const void *))layout_compare);
1083 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
1084 (int (*)(const void *, const void *))layout_compare);
1086 for(i = 0; i < nextdefsym; i++) {
1087 extdefsyms[i]->snum = *numsyms;
1088 *numsyms += 1;
1090 for(j = 0; j < nundefsym; j++) {
1091 undefsyms[j]->snum = *numsyms;
1092 *numsyms += 1;
1096 /* Calculate some values we'll need for writing later. */
1098 static void macho_calculate_sizes (void)
1100 struct section *s;
1101 int fi;
1103 /* count sections and calculate in-memory and in-file offsets */
1104 for (s = sects; s != NULL; s = s->next) {
1105 uint64_t newaddr;
1107 /* recalculate segment address based on alignment and vm size */
1108 s->addr = seg_vmsize;
1110 /* we need section alignment to calculate final section address */
1111 if (s->align == -1)
1112 s->align = DEFAULT_SECTION_ALIGNMENT;
1114 newaddr = ALIGN(s->addr, 1 << s->align);
1115 s->addr = newaddr;
1117 seg_vmsize = newaddr + s->size;
1119 /* zerofill sections aren't actually written to the file */
1120 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1122 * LLVM/Xcode as always aligns the section data to 4
1123 * bytes; there is a comment in the LLVM source code that
1124 * perhaps aligning to pointer size would be better.
1126 s->pad = ALIGN(seg_filesize, 4) - seg_filesize;
1127 s->offset = seg_filesize + s->pad;
1128 seg_filesize += s->size + s->pad;
1132 /* calculate size of all headers, load commands and sections to
1133 ** get a pointer to the start of all the raw data */
1134 if (seg_nsects > 0) {
1135 ++head_ncmds;
1136 head_sizeofcmds += fmt.segcmd_size + seg_nsects * fmt.sectcmd_size;
1139 if (nsyms > 0) {
1140 ++head_ncmds;
1141 head_sizeofcmds += MACHO_SYMCMD_SIZE;
1144 if (seg_nsects > MAX_SECT) {
1145 nasm_error(ERR_FATAL, "MachO output is limited to %d sections\n",
1146 MAX_SECT);
1149 /* Create a table of sections by file index to avoid linear search */
1150 sectstab = nasm_malloc((seg_nsects + 1) * sizeof(*sectstab));
1151 sectstab[NO_SECT] = &absolute_sect;
1152 for (s = sects, fi = 1; s != NULL; s = s->next, fi++)
1153 sectstab[fi] = s;
1156 /* Write out the header information for the file. */
1158 static void macho_write_header (void)
1160 fwriteint32_t(fmt.mh_magic, ofile); /* magic */
1161 fwriteint32_t(fmt.cpu_type, ofile); /* CPU type */
1162 fwriteint32_t(CPU_SUBTYPE_I386_ALL, ofile); /* CPU subtype */
1163 fwriteint32_t(MH_OBJECT, ofile); /* Mach-O file type */
1164 fwriteint32_t(head_ncmds, ofile); /* number of load commands */
1165 fwriteint32_t(head_sizeofcmds, ofile); /* size of load commands */
1166 fwriteint32_t(0, ofile); /* no flags */
1167 fwritezero(fmt.header_size - 7*4, ofile); /* reserved fields */
1170 /* Write out the segment load command at offset. */
1172 static uint32_t macho_write_segment (uint64_t offset)
1174 uint64_t rel_base = alignptr(offset + seg_filesize);
1175 uint32_t s_reloff = 0;
1176 struct section *s;
1178 fwriteint32_t(fmt.lc_segment, ofile); /* cmd == LC_SEGMENT_64 */
1180 /* size of load command including section load commands */
1181 fwriteint32_t(fmt.segcmd_size + seg_nsects * fmt.sectcmd_size,
1182 ofile);
1184 /* in an MH_OBJECT file all sections are in one unnamed (name
1185 ** all zeros) segment */
1186 fwritezero(16, ofile);
1187 fwriteptr(0, ofile); /* in-memory offset */
1188 fwriteptr(seg_vmsize, ofile); /* in-memory size */
1189 fwriteptr(offset, ofile); /* in-file offset to data */
1190 fwriteptr(seg_filesize, ofile); /* in-file size */
1191 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* maximum vm protection */
1192 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* initial vm protection */
1193 fwriteint32_t(seg_nsects, ofile); /* number of sections */
1194 fwriteint32_t(0, ofile); /* no flags */
1196 /* emit section headers */
1197 for (s = sects; s != NULL; s = s->next) {
1198 if (s->nreloc) {
1199 nasm_assert((s->flags & SECTION_TYPE) != S_ZEROFILL);
1200 s->flags |= S_ATTR_LOC_RELOC;
1201 if (s->extreloc)
1202 s->flags |= S_ATTR_EXT_RELOC;
1203 } else if (!strcmp(s->segname, "__DATA") &&
1204 !strcmp(s->sectname, "__const") &&
1205 !s->by_name &&
1206 !get_section_by_name("__TEXT", "__const")) {
1208 * The MachO equivalent to .rodata can be either
1209 * __DATA,__const or __TEXT,__const; the latter only if
1210 * there are no relocations. However, when mixed it is
1211 * better to specify the segments explicitly.
1213 xstrncpy(s->segname, "__TEXT");
1216 nasm_write(s->sectname, sizeof(s->sectname), ofile);
1217 nasm_write(s->segname, sizeof(s->segname), ofile);
1218 fwriteptr(s->addr, ofile);
1219 fwriteptr(s->size, ofile);
1221 /* dummy data for zerofill sections or proper values */
1222 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1223 nasm_assert(s->pad != (uint32_t)-1);
1224 offset += s->pad;
1225 fwriteint32_t(offset, ofile);
1226 offset += s->size;
1227 /* Write out section alignment, as a power of two.
1228 e.g. 32-bit word alignment would be 2 (2^2 = 4). */
1229 fwriteint32_t(s->align, ofile);
1230 /* To be compatible with cctools as we emit
1231 a zero reloff if we have no relocations. */
1232 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile);
1233 fwriteint32_t(s->nreloc, ofile);
1235 s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
1236 } else {
1237 fwriteint32_t(0, ofile);
1238 fwriteint32_t(s->align, ofile);
1239 fwriteint32_t(0, ofile);
1240 fwriteint32_t(0, ofile);
1243 fwriteint32_t(s->flags, ofile); /* flags */
1244 fwriteint32_t(0, ofile); /* reserved */
1245 fwriteptr(0, ofile); /* reserved */
1248 rel_padcnt = rel_base - offset;
1249 offset = rel_base + s_reloff;
1251 return offset;
1254 /* For a given chain of relocs r, write out the entire relocation
1255 chain to the object file. */
1257 static void macho_write_relocs (struct reloc *r)
1259 while (r) {
1260 uint32_t word2;
1262 fwriteint32_t(r->addr, ofile); /* reloc offset */
1264 word2 = r->snum;
1265 word2 |= r->pcrel << 24;
1266 word2 |= r->length << 25;
1267 word2 |= r->ext << 27;
1268 word2 |= r->type << 28;
1269 fwriteint32_t(word2, ofile); /* reloc data */
1270 r = r->next;
1274 /* Write out the section data. */
1275 static void macho_write_section (void)
1277 struct section *s;
1278 struct reloc *r;
1279 uint8_t *p;
1280 int32_t len;
1281 int64_t l;
1282 union offset {
1283 uint64_t val;
1284 uint8_t buf[8];
1285 } blk;
1287 for (s = sects; s != NULL; s = s->next) {
1288 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
1289 continue;
1291 /* Like a.out Mach-O references things in the data or bss
1292 * sections by addresses which are actually relative to the
1293 * start of the _text_ section, in the _file_. See outaout.c
1294 * for more information. */
1295 saa_rewind(s->data);
1296 for (r = s->relocs; r != NULL; r = r->next) {
1297 len = (uint32_t)1 << r->length;
1298 if (len > 4) /* Can this ever be an issue?! */
1299 len = 8;
1300 blk.val = 0;
1301 saa_fread(s->data, r->addr, blk.buf, len);
1303 /* get offset based on relocation type */
1304 #ifdef WORDS_LITTLEENDIAN
1305 l = blk.val;
1306 #else
1307 l = blk.buf[0];
1308 l += ((int64_t)blk.buf[1]) << 8;
1309 l += ((int64_t)blk.buf[2]) << 16;
1310 l += ((int64_t)blk.buf[3]) << 24;
1311 l += ((int64_t)blk.buf[4]) << 32;
1312 l += ((int64_t)blk.buf[5]) << 40;
1313 l += ((int64_t)blk.buf[6]) << 48;
1314 l += ((int64_t)blk.buf[7]) << 56;
1315 #endif
1317 /* If the relocation is internal add to the current section
1318 offset. Otherwise the only value we need is the symbol
1319 offset which we already have. The linker takes care
1320 of the rest of the address. */
1321 if (!r->ext) {
1322 /* generate final address by section address and offset */
1323 nasm_assert(r->snum <= seg_nsects);
1324 l += sectstab[r->snum]->addr;
1325 if (r->pcrel)
1326 l -= s->addr;
1329 /* write new offset back */
1330 p = blk.buf;
1331 WRITEDLONG(p, l);
1332 saa_fwrite(s->data, r->addr, blk.buf, len);
1335 /* dump the section data to file */
1336 fwritezero(s->pad, ofile);
1337 saa_fpwrite(s->data, ofile);
1340 /* pad last section up to reloc entries on pointer boundary */
1341 fwritezero(rel_padcnt, ofile);
1343 /* emit relocation entries */
1344 for (s = sects; s != NULL; s = s->next)
1345 macho_write_relocs (s->relocs);
1348 /* Write out the symbol table. We should already have sorted this
1349 before now. */
1350 static void macho_write_symtab (void)
1352 struct symbol *sym;
1353 uint64_t i;
1355 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1357 for (sym = syms; sym != NULL; sym = sym->next) {
1358 if ((sym->type & N_EXT) == 0) {
1359 fwriteint32_t(sym->strx, ofile); /* string table entry number */
1360 nasm_write(&sym->type, 1, ofile); /* symbol type */
1361 nasm_write(&sym->sect, 1, ofile); /* section */
1362 fwriteint16_t(sym->desc, ofile); /* description */
1364 /* Fix up the symbol value now that we know the final section
1365 sizes. */
1366 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1367 nasm_assert(sym->sect <= seg_nsects);
1368 sym->symv.key += sectstab[sym->sect]->addr;
1371 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1375 for (i = 0; i < nextdefsym; i++) {
1376 sym = extdefsyms[i];
1377 fwriteint32_t(sym->strx, ofile);
1378 nasm_write(&sym->type, 1, ofile); /* symbol type */
1379 nasm_write(&sym->sect, 1, ofile); /* section */
1380 fwriteint16_t(sym->desc, ofile); /* description */
1382 /* Fix up the symbol value now that we know the final section
1383 sizes. */
1384 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1385 nasm_assert(sym->sect <= seg_nsects);
1386 sym->symv.key += sectstab[sym->sect]->addr;
1389 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1392 for (i = 0; i < nundefsym; i++) {
1393 sym = undefsyms[i];
1394 fwriteint32_t(sym->strx, ofile);
1395 nasm_write(&sym->type, 1, ofile); /* symbol type */
1396 nasm_write(&sym->sect, 1, ofile); /* section */
1397 fwriteint16_t(sym->desc, ofile); /* description */
1399 /* Fix up the symbol value now that we know the final section
1400 sizes. */
1401 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1402 nasm_assert(sym->sect <= seg_nsects);
1403 sym->symv.key += sectstab[sym->sect]->addr;
1406 fwriteptr(sym->symv.key, ofile); /* value (i.e. offset) */
1411 /* Fixup the snum in the relocation entries, we should be
1412 doing this only for externally referenced symbols. */
1413 static void macho_fixup_relocs (struct reloc *r)
1415 struct symbol *sym;
1417 while (r != NULL) {
1418 if (r->ext) {
1419 for (sym = syms; sym != NULL; sym = sym->next) {
1420 if (sym->initial_snum == r->snum) {
1421 r->snum = sym->snum;
1422 break;
1426 r = r->next;
1430 /* Write out the object file. */
1432 static void macho_write (void)
1434 uint64_t offset = 0;
1436 /* mach-o object file structure:
1438 ** mach header
1439 ** uint32_t magic
1440 ** int cpu type
1441 ** int cpu subtype
1442 ** uint32_t mach file type
1443 ** uint32_t number of load commands
1444 ** uint32_t size of all load commands
1445 ** (includes section struct size of segment command)
1446 ** uint32_t flags
1448 ** segment command
1449 ** uint32_t command type == LC_SEGMENT[_64]
1450 ** uint32_t size of load command
1451 ** (including section load commands)
1452 ** char[16] segment name
1453 ** pointer in-memory offset
1454 ** pointer in-memory size
1455 ** pointer in-file offset to data area
1456 ** pointer in-file size
1457 ** (in-memory size excluding zerofill sections)
1458 ** int maximum vm protection
1459 ** int initial vm protection
1460 ** uint32_t number of sections
1461 ** uint32_t flags
1463 ** section commands
1464 ** char[16] section name
1465 ** char[16] segment name
1466 ** pointer in-memory offset
1467 ** pointer in-memory size
1468 ** uint32_t in-file offset
1469 ** uint32_t alignment
1470 ** (irrelevant in MH_OBJECT)
1471 ** uint32_t in-file offset of relocation entires
1472 ** uint32_t number of relocations
1473 ** uint32_t flags
1474 ** uint32_t reserved
1475 ** uint32_t reserved
1477 ** symbol table command
1478 ** uint32_t command type == LC_SYMTAB
1479 ** uint32_t size of load command
1480 ** uint32_t symbol table offset
1481 ** uint32_t number of symbol table entries
1482 ** uint32_t string table offset
1483 ** uint32_t string table size
1485 ** raw section data
1487 ** padding to pointer boundary
1489 ** relocation data (struct reloc)
1490 ** int32_t offset
1491 ** uint data (symbolnum, pcrel, length, extern, type)
1493 ** symbol table data (struct nlist)
1494 ** int32_t string table entry number
1495 ** uint8_t type
1496 ** (extern, absolute, defined in section)
1497 ** uint8_t section
1498 ** (0 for global symbols, section number of definition (>= 1, <=
1499 ** 254) for local symbols, size of variable for common symbols
1500 ** [type == extern])
1501 ** int16_t description
1502 ** (for stab debugging format)
1503 ** pointer value (i.e. file offset) of symbol or stab offset
1505 ** string table data
1506 ** list of null-terminated strings
1509 /* Emit the Mach-O header. */
1510 macho_write_header();
1512 offset = fmt.header_size + head_sizeofcmds;
1514 /* emit the segment load command */
1515 if (seg_nsects > 0)
1516 offset = macho_write_segment (offset);
1517 else
1518 nasm_error(ERR_WARNING, "no sections?");
1520 if (nsyms > 0) {
1521 /* write out symbol command */
1522 fwriteint32_t(LC_SYMTAB, ofile); /* cmd == LC_SYMTAB */
1523 fwriteint32_t(MACHO_SYMCMD_SIZE, ofile); /* size of load command */
1524 fwriteint32_t(offset, ofile); /* symbol table offset */
1525 fwriteint32_t(nsyms, ofile); /* number of symbol
1526 ** table entries */
1527 offset += nsyms * fmt.nlist_size;
1528 fwriteint32_t(offset, ofile); /* string table offset */
1529 fwriteint32_t(strslen, ofile); /* string table size */
1532 /* emit section data */
1533 if (seg_nsects > 0)
1534 macho_write_section ();
1536 /* emit symbol table if we have symbols */
1537 if (nsyms > 0)
1538 macho_write_symtab ();
1540 /* we don't need to pad here, we are already aligned */
1542 /* emit string table */
1543 saa_fpwrite(strs, ofile);
1545 /* We do quite a bit here, starting with finalizing all of the data
1546 for the object file, writing, and then freeing all of the data from
1547 the file. */
1549 static void macho_cleanup(int debuginfo)
1551 struct section *s;
1552 struct reloc *r;
1553 struct symbol *sym;
1555 (void)debuginfo;
1557 /* Sort all symbols. */
1558 macho_layout_symbols (&nsyms, &strslen);
1560 /* Fixup relocation entries */
1561 for (s = sects; s != NULL; s = s->next) {
1562 macho_fixup_relocs (s->relocs);
1565 /* First calculate and finalize needed values. */
1566 macho_calculate_sizes();
1567 macho_write();
1569 /* free up everything */
1570 while (sects->next) {
1571 s = sects;
1572 sects = sects->next;
1574 saa_free(s->data);
1575 while (s->relocs != NULL) {
1576 r = s->relocs;
1577 s->relocs = s->relocs->next;
1578 nasm_free(r);
1581 nasm_free(s);
1584 saa_free(strs);
1585 raa_free(extsyms);
1587 while (syms) {
1588 sym = syms;
1589 syms = syms->next;
1590 nasm_free (sym);
1593 nasm_free(extdefsyms);
1594 nasm_free(undefsyms);
1595 nasm_free(sectstab);
1598 /* Debugging routines. */
1599 static void debug_reloc (struct reloc *r)
1601 fprintf (stdout, "reloc:\n");
1602 fprintf (stdout, "\taddr: %"PRId32"\n", r->addr);
1603 fprintf (stdout, "\tsnum: %d\n", r->snum);
1604 fprintf (stdout, "\tpcrel: %d\n", r->pcrel);
1605 fprintf (stdout, "\tlength: %d\n", r->length);
1606 fprintf (stdout, "\text: %d\n", r->ext);
1607 fprintf (stdout, "\ttype: %d\n", r->type);
1610 static void debug_section_relocs (struct section *s)
1612 struct reloc *r = s->relocs;
1614 fprintf (stdout, "relocs for section %s:\n\n", s->sectname);
1616 while (r != NULL) {
1617 debug_reloc (r);
1618 r = r->next;
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 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 macho_output,
1657 macho_symdef,
1658 macho_section,
1659 macho_sectalign,
1660 macho_segbase,
1661 null_directive,
1662 macho_filename,
1663 macho_cleanup
1665 #endif
1667 #ifdef OF_MACHO64
1668 static const struct macho_fmt macho64_fmt = {
1670 MH_MAGIC_64,
1671 CPU_TYPE_X86_64,
1672 LC_SEGMENT_64,
1673 MACHO_HEADER64_SIZE,
1674 MACHO_SEGCMD64_SIZE,
1675 MACHO_SECTCMD64_SIZE,
1676 MACHO_NLIST64_SIZE,
1677 RL_MAX_64,
1678 X86_64_RELOC_UNSIGNED,
1679 X86_64_RELOC_SIGNED,
1680 X86_64_RELOC_TLV
1683 static void macho64_init(void)
1685 fmt = macho64_fmt;
1686 macho_init();
1688 /* add special symbol for ..gotpcrel */
1689 macho_gotpcrel_sect = seg_alloc() + 1;
1690 define_label("..gotpcrel", macho_gotpcrel_sect, 0L, NULL, false, false);
1693 struct ofmt of_macho64 = {
1694 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files",
1695 "macho64",
1698 null_debug_arr,
1699 &null_debug_form,
1700 macho_stdmac,
1701 macho64_init,
1702 null_setinfo,
1703 macho_output,
1704 macho_symdef,
1705 macho_section,
1706 macho_sectalign,
1707 macho_segbase,
1708 null_directive,
1709 macho_filename,
1710 macho_cleanup
1712 #endif
1714 #endif
1717 * Local Variables:
1718 * mode:c
1719 * c-basic-offset:4
1720 * End:
1722 * end of file */