Merge branch 'nasm-2.14.xx'
[nasm.git] / output / outmacho.c
blobf5673c89a9e984f504e6acd1bd166add22a32d89
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2018 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 "ilog2.h"
49 #include "labels.h"
50 #include "error.h"
51 #include "saa.h"
52 #include "raa.h"
53 #include "rbtree.h"
54 #include "hashtbl.h"
55 #include "outform.h"
56 #include "outlib.h"
57 #include "ver.h"
58 #include "dwarf.h"
60 #if defined(OF_MACHO) || defined(OF_MACHO64)
62 /* Mach-O in-file header structure sizes */
63 #define MACHO_HEADER_SIZE 28
64 #define MACHO_SEGCMD_SIZE 56
65 #define MACHO_SECTCMD_SIZE 68
66 #define MACHO_SYMCMD_SIZE 24
67 #define MACHO_NLIST_SIZE 12
68 #define MACHO_RELINFO_SIZE 8
70 #define MACHO_HEADER64_SIZE 32
71 #define MACHO_SEGCMD64_SIZE 72
72 #define MACHO_SECTCMD64_SIZE 80
73 #define MACHO_NLIST64_SIZE 16
75 /* Mach-O file header values */
76 #define MH_MAGIC 0xfeedface
77 #define MH_MAGIC_64 0xfeedfacf
78 #define CPU_TYPE_I386 7 /* x86 platform */
79 #define CPU_TYPE_X86_64 0x01000007 /* x86-64 platform */
80 #define CPU_SUBTYPE_I386_ALL 3 /* all-x86 compatible */
81 #define MH_OBJECT 0x1 /* object file */
83 /* Mach-O header flags */
84 #define MH_SUBSECTIONS_VIA_SYMBOLS 0x2000
86 /* Mach-O load commands */
87 #define LC_SEGMENT 0x1 /* 32-bit segment load cmd */
88 #define LC_SEGMENT_64 0x19 /* 64-bit segment load cmd */
89 #define LC_SYMTAB 0x2 /* symbol table load command */
91 /* Mach-O relocations numbers */
93 /* Generic relocs, used by i386 Mach-O */
94 #define GENERIC_RELOC_VANILLA 0 /* Generic relocation */
95 #define GENERIC_RELOC_TLV 5 /* Thread local */
97 #define X86_64_RELOC_UNSIGNED 0 /* Absolute address */
98 #define X86_64_RELOC_SIGNED 1 /* Signed 32-bit disp */
99 #define X86_64_RELOC_BRANCH 2 /* CALL/JMP with 32-bit disp */
100 #define X86_64_RELOC_GOT_LOAD 3 /* MOVQ of GOT entry */
101 #define X86_64_RELOC_GOT 4 /* Different GOT entry */
102 #define X86_64_RELOC_SUBTRACTOR 5 /* Subtracting two symbols */
103 #define X86_64_RELOC_SIGNED_1 6 /* SIGNED with -1 addend */
104 #define X86_64_RELOC_SIGNED_2 7 /* SIGNED with -2 addend */
105 #define X86_64_RELOC_SIGNED_4 8 /* SIGNED with -4 addend */
106 #define X86_64_RELOC_TLV 9 /* Thread local */
108 /* Mach-O VM permission constants */
109 #define VM_PROT_NONE (0x00)
110 #define VM_PROT_READ (0x01)
111 #define VM_PROT_WRITE (0x02)
112 #define VM_PROT_EXECUTE (0x04)
114 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
115 #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
117 /* Our internal relocation types */
118 enum reltype {
119 RL_ABS, /* Absolute relocation */
120 RL_REL, /* Relative relocation */
121 RL_TLV, /* Thread local */
122 RL_BRANCH, /* Relative direct branch */
123 RL_SUB, /* X86_64_RELOC_SUBTRACT */
124 RL_GOT, /* X86_64_RELOC_GOT */
125 RL_GOTLOAD /* X86_64_RELOC_GOT_LOAD */
127 #define RL_MAX_32 RL_TLV
128 #define RL_MAX_64 RL_GOTLOAD
130 struct macho_fmt {
131 uint32_t ptrsize; /* Pointer size in bytes */
132 uint32_t mh_magic; /* Which magic number to use */
133 uint32_t cpu_type; /* Which CPU type */
134 uint32_t lc_segment; /* Which segment load command */
135 uint32_t header_size; /* Header size */
136 uint32_t segcmd_size; /* Segment command size */
137 uint32_t sectcmd_size; /* Section command size */
138 uint32_t nlist_size; /* Nlist (symbol) size */
139 enum reltype maxreltype; /* Maximum entry in enum reltype permitted */
140 uint32_t reloc_abs; /* Absolute relocation type */
141 uint32_t reloc_rel; /* Relative relocation type */
142 uint32_t reloc_tlv; /* Thread local relocation type */
143 bool forcesym; /* Always use "external" (symbol-relative) relocations */
146 static struct macho_fmt fmt;
148 static void fwriteptr(uint64_t data, FILE * fp)
150 fwriteaddr(data, fmt.ptrsize, fp);
153 struct section {
154 /* nasm internal data */
155 struct section *next;
156 struct SAA *data;
157 int32_t index; /* Main section index */
158 int32_t subsection; /* Current subsection index */
159 int32_t fileindex;
160 struct reloc *relocs;
161 struct rbtree *syms[2]; /* All/global symbols symbols in section */
162 int align;
163 bool by_name; /* This section was specified by full MachO name */
164 char namestr[34]; /* segment,section as a C string */
166 /* data that goes into the file */
167 char sectname[16]; /* what this section is called */
168 char segname[16]; /* segment this section will be in */
169 uint64_t addr; /* in-memory address (subject to alignment) */
170 uint64_t size; /* in-memory and -file size */
171 uint64_t offset; /* in-file offset */
172 uint32_t pad; /* padding bytes before section */
173 uint32_t nreloc; /* relocation entry count */
174 uint32_t flags; /* type and attributes (masked) */
175 uint32_t extreloc; /* external relocations */
178 #define SECTION_TYPE 0x000000ff /* section type mask */
180 #define S_REGULAR (0x0) /* standard section */
181 #define S_ZEROFILL (0x1) /* zerofill, in-memory only */
183 #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
184 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
185 machine instructions */
186 #define S_ATTR_EXT_RELOC 0x00000200 /* section has external relocation entries */
187 #define S_ATTR_LOC_RELOC 0x00000100 /* section has local relocation entries */
188 #define S_ATTR_DEBUG 0x02000000
189 #define S_ATTR_SELF_MODIFYING_CODE 0x04000000
190 #define S_ATTR_LIVE_SUPPORT 0x08000000
191 #define S_ATTR_NO_DEAD_STRIP 0x10000000 /* no dead stripping */
192 #define S_ATTR_STRIP_STATIC_SYMS 0x20000000
193 #define S_ATTR_NO_TOC 0x40000000
194 #define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section uses pure machine instructions */
195 #define S_ATTR_DEBUG 0x02000000 /* debug section */
197 #define S_NASM_TYPE_MASK 0x800004ff /* we consider these bits "section type" */
199 /* fake section for absolute symbols, *not* part of the section linked list */
200 static struct section absolute_sect;
202 struct reloc {
203 /* nasm internal data */
204 struct reloc *next;
206 /* data that goes into the file */
207 int32_t addr; /* op's offset in section */
208 uint32_t snum:24, /* contains symbol index if
209 ** ext otherwise in-file
210 ** section number */
211 pcrel:1, /* relative relocation */
212 length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */
213 ext:1, /* external symbol referenced */
214 type:4; /* reloc type */
217 #define R_ABS 0 /* absolute relocation */
218 #define R_SCATTERED 0x80000000 /* reloc entry is scattered if
219 ** highest bit == 1 */
221 struct symbol {
222 /* nasm internal data */
223 struct rbtree symv[2]; /* All/global symbol rbtrees; "key" contains the
224 symbol offset. */
225 struct symbol *next; /* next symbol in the list */
226 char *name; /* name of this symbol */
227 int32_t initial_snum; /* symbol number used above in reloc */
228 int32_t snum; /* true snum for reloc */
230 /* data that goes into the file */
231 uint32_t strx; /* string table index */
232 uint8_t type; /* symbol type */
233 uint8_t sect; /* NO_SECT or section number */
234 uint16_t desc; /* for stab debugging, 0 for us */
237 /* symbol type bits */
238 #define N_EXT 0x01 /* global or external symbol */
239 #define N_PEXT 0x10 /* private external symbol */
241 #define N_UNDF 0x0 /* undefined symbol | n_sect == */
242 #define N_ABS 0x2 /* absolute symbol | NO_SECT */
243 #define N_SECT 0xe /* defined symbol, n_sect holds
244 ** section number */
246 #define N_TYPE 0x0e /* type bit mask */
248 #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
250 /* special section number values */
251 #define NO_SECT 0 /* no section, invalid */
252 #define MAX_SECT 255 /* maximum number of sections */
254 static struct section *sects, **sectstail, **sectstab;
255 static struct symbol *syms, **symstail;
256 static uint32_t nsyms;
258 /* These variables are set by macho_layout_symbols() to organize
259 the symbol table and string table in order the dynamic linker
260 expects. They are then used in macho_write() to put out the
261 symbols and strings in that order.
263 The order of the symbol table is:
264 local symbols
265 defined external symbols (sorted by name)
266 undefined external symbols (sorted by name)
268 The order of the string table is:
269 strings for external symbols
270 strings for local symbols
272 static uint32_t ilocalsym = 0;
273 static uint32_t iextdefsym = 0;
274 static uint32_t iundefsym = 0;
275 static uint32_t nlocalsym;
276 static uint32_t nextdefsym;
277 static uint32_t nundefsym;
278 static struct symbol **extdefsyms = NULL;
279 static struct symbol **undefsyms = NULL;
281 static struct RAA *extsyms;
282 static struct SAA *strs;
283 static uint32_t strslen;
285 /* Global file information. This should be cleaned up into either
286 a structure or as function arguments. */
287 static uint32_t head_ncmds = 0;
288 static uint32_t head_sizeofcmds = 0;
289 static uint32_t head_flags = 0;
290 static uint64_t seg_filesize = 0;
291 static uint64_t seg_vmsize = 0;
292 static uint32_t seg_nsects = 0;
293 static uint64_t rel_padcnt = 0;
296 * Functions for handling fixed-length zero-padded string
297 * fields, that may or may not be null-terminated.
300 /* Copy a string into a zero-padded fixed-length field */
301 #define xstrncpy(xdst, xsrc) strncpy(xdst, xsrc, sizeof(xdst))
303 /* Compare a fixed-length field with a string */
304 #define xstrncmp(xdst, xsrc) strncmp(xdst, xsrc, sizeof(xdst))
306 #define alignint32_t(x) \
307 ALIGN(x, sizeof(int32_t)) /* align x to int32_t boundary */
309 #define alignint64_t(x) \
310 ALIGN(x, sizeof(int64_t)) /* align x to int64_t boundary */
312 #define alignptr(x) \
313 ALIGN(x, fmt.ptrsize) /* align x to output format width */
315 static struct hash_table section_by_name;
316 static struct RAA *section_by_index;
318 static struct section * never_null
319 find_or_add_section(const char *segname, const char *sectname)
321 struct hash_insert hi;
322 void **sp;
323 struct section *s;
324 char sect[34];
326 snprintf(sect, sizeof sect, "%-16s,%-16s", segname, sectname);
328 sp = hash_find(&section_by_name, sect, &hi);
329 if (sp)
330 return (struct section *)(*sp);
332 s = nasm_zalloc(sizeof *s);
333 xstrncpy(s->segname, segname);
334 xstrncpy(s->sectname, sectname);
335 xstrncpy(s->namestr, sect);
336 hash_add(&hi, s->namestr, s);
338 s->index = s->subsection = seg_alloc();
339 section_by_index = raa_write_ptr(section_by_index, s->index >> 1, s);
341 return s;
344 static inline bool is_new_section(const struct section *s)
346 return !s->data;
349 static struct section *get_section_by_name(const char *segname,
350 const char *sectname)
352 char sect[34];
353 void **sp;
355 snprintf(sect, sizeof sect, "%-16s,%-16s", segname, sectname);
357 sp = hash_find(&section_by_name, sect, NULL);
358 return sp ? (struct section *)(*sp) : NULL;
361 static struct section *get_section_by_index(int32_t index)
363 if (index < 0 || index >= SEG_ABS || (index & 1))
364 return NULL;
366 return raa_read_ptr(section_by_index, index >> 1);
369 struct dir_list {
370 struct dir_list *next;
371 struct dir_list *last;
372 const char *dir_name;
373 uint32_t dir;
376 struct file_list {
377 struct file_list *next;
378 struct file_list *last;
379 const char *file_name;
380 uint32_t file;
381 struct dir_list *dir;
384 struct dw_sect_list {
385 struct SAA *psaa;
386 int32_t section;
387 uint32_t line;
388 uint64_t offset;
389 uint32_t file;
390 struct dw_sect_list *next;
391 struct dw_sect_list *last;
394 struct section_info {
395 uint64_t size;
396 int32_t secto;
399 #define DW_LN_BASE (-5)
400 #define DW_LN_RANGE 14
401 #define DW_OPCODE_BASE 13
402 #define DW_MAX_LN (DW_LN_BASE + DW_LN_RANGE)
403 #define DW_MAX_SP_OPCODE 256
405 static struct file_list *dw_head_file = 0, *dw_cur_file = 0, **dw_last_file_next = NULL;
406 static struct dir_list *dw_head_dir = 0, **dw_last_dir_next = NULL;
407 static struct dw_sect_list *dw_head_sect = 0, *dw_cur_sect = 0, *dw_last_sect = 0;
408 static uint32_t cur_line = 0, dw_num_files = 0, dw_num_dirs = 0, dw_num_sects = 0;
409 static bool dbg_immcall = false;
410 static const char *module_name = NULL;
413 * Special section numbers which are used to define Mach-O special
414 * symbols, which can be used with WRT to provide PIC relocation
415 * types.
417 static int32_t macho_tlvp_sect;
418 static int32_t macho_gotpcrel_sect;
420 static void macho_init(void)
422 module_name = inname;
423 sects = NULL;
424 sectstail = &sects;
426 /* Fake section for absolute symbols */
427 absolute_sect.index = NO_SEG;
429 syms = NULL;
430 symstail = &syms;
431 nsyms = 0;
432 nlocalsym = 0;
433 nextdefsym = 0;
434 nundefsym = 0;
436 extsyms = raa_init();
437 strs = saa_init(1L);
439 section_by_index = raa_init();
440 hash_init(&section_by_name, HASH_MEDIUM);
442 /* string table starts with a zero byte so index 0 is an empty string */
443 saa_wbytes(strs, zero_buffer, 1);
444 strslen = 1;
446 /* add special symbol for TLVP */
447 macho_tlvp_sect = seg_alloc() + 1;
448 backend_label("..tlvp", macho_tlvp_sect, 0L);
451 static void sect_write(struct section *sect,
452 const uint8_t *data, uint32_t len)
454 saa_wbytes(sect->data, data, len);
455 sect->size += len;
459 * Find a suitable global symbol for a ..gotpcrel or ..tlvp reference
461 static struct symbol *macho_find_sym(struct section *s, uint64_t offset,
462 bool global, bool exact)
464 struct rbtree *srb;
466 srb = rb_search(s->syms[global], offset);
468 if (!srb || (exact && srb->key != offset)) {
469 nasm_error(ERR_NONFATAL, "unable to find a suitable%s%s symbol"
470 " for this reference",
471 global ? " global" : "",
472 s == &absolute_sect ? " absolute " : "");
473 return NULL;
476 return container_of(srb - global, struct symbol, symv);
479 static int64_t add_reloc(struct section *sect, int32_t section,
480 int64_t offset,
481 enum reltype reltype, int bytes)
483 struct reloc *r;
484 struct section *s;
485 int32_t fi;
486 int64_t adjust;
488 /* Double check this is a valid relocation type for this platform */
489 nasm_assert(reltype <= fmt.maxreltype);
491 /* the current end of the section will be the symbol's address for
492 ** now, might have to be fixed by macho_fixup_relocs() later on. make
493 ** sure we don't make the symbol scattered by setting the highest
494 ** bit by accident */
495 r = nasm_malloc(sizeof(struct reloc));
496 r->addr = sect->size & ~R_SCATTERED;
497 r->ext = 1;
498 adjust = 0;
500 /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
501 r->length = ilog2_32(bytes);
503 /* set default relocation values */
504 r->type = fmt.reloc_abs;
505 r->pcrel = 0;
506 r->snum = R_ABS;
508 s = get_section_by_index(section);
509 fi = s ? s->fileindex : NO_SECT;
511 /* absolute relocation */
512 switch (reltype) {
513 case RL_ABS:
514 if (section == NO_SEG) {
515 /* absolute (can this even happen?) */
516 r->ext = 0;
517 } else if (fi == NO_SECT) {
518 /* external */
519 r->snum = raa_read(extsyms, section);
520 } else {
521 /* local */
522 r->ext = 0;
523 r->snum = fi;
525 break;
527 case RL_REL:
528 case RL_BRANCH:
529 r->type = fmt.reloc_rel;
530 r->pcrel = 1;
531 if (section == NO_SEG) {
532 /* may optionally be converted below by fmt.forcesym */
533 r->ext = 0;
534 } else if (fi == NO_SECT) {
535 /* external */
536 sect->extreloc = 1;
537 r->snum = raa_read(extsyms, section);
538 if (reltype == RL_BRANCH)
539 r->type = X86_64_RELOC_BRANCH;
540 } else {
541 /* local */
542 r->ext = 0;
543 r->snum = fi;
544 if (reltype == RL_BRANCH)
545 r->type = X86_64_RELOC_BRANCH;
547 break;
549 case RL_SUB: /* obsolete */
550 nasm_error(ERR_WARNING, "relcation with subtraction"
551 "becomes to be obsolete");
552 r->ext = 0;
553 r->type = X86_64_RELOC_SUBTRACTOR;
554 break;
556 case RL_GOT:
557 r->type = X86_64_RELOC_GOT;
558 goto needsym;
560 case RL_GOTLOAD:
561 r->type = X86_64_RELOC_GOT_LOAD;
562 goto needsym;
564 case RL_TLV:
565 r->type = fmt.reloc_tlv;
566 goto needsym;
568 needsym:
569 r->pcrel = (fmt.ptrsize == 8 ? 1 : 0);
570 if (section == NO_SEG) {
571 nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT");
572 goto bail;
573 } else if (fi == NO_SECT) {
574 /* external */
575 r->snum = raa_read(extsyms, section);
576 } else {
577 /* internal - GOTPCREL doesn't need to be in global */
578 struct symbol *sym = macho_find_sym(s, offset,
579 false, /* reltype != RL_TLV */
580 true);
581 if (!sym) {
582 nasm_error(ERR_NONFATAL, "Symbol for WRT not found");
583 goto bail;
586 adjust -= sym->symv[0].key;
587 r->snum = sym->initial_snum;
589 break;
593 * For 64-bit Mach-O, force a symbol reference if at all possible
594 * Allow for r->snum == R_ABS by searching absolute_sect
596 if (!r->ext && fmt.forcesym) {
597 struct symbol *sym = macho_find_sym(s ? s : &absolute_sect,
598 offset, false, false);
599 if (sym) {
600 adjust -= sym->symv[0].key;
601 r->snum = sym->initial_snum;
602 r->ext = 1;
606 if (r->pcrel)
607 adjust += ((r->ext && fmt.ptrsize == 8) ? bytes : -(int64_t)sect->size);
609 /* NeXT as puts relocs in reversed order (address-wise) into the
610 ** files, so we do the same, doesn't seem to make much of a
611 ** difference either way */
612 r->next = sect->relocs;
613 sect->relocs = r;
614 if (r->ext)
615 sect->extreloc = 1;
616 ++sect->nreloc;
618 return adjust;
620 bail:
621 nasm_free(r);
622 return 0;
625 static void macho_output(int32_t secto, const void *data,
626 enum out_type type, uint64_t size,
627 int32_t section, int32_t wrt)
629 struct section *s;
630 int64_t addr, offset;
631 uint8_t mydata[16], *p;
632 bool is_bss;
633 enum reltype reltype;
635 s = get_section_by_index(secto);
636 if (!s) {
637 nasm_error(ERR_WARNING, "attempt to assemble code in"
638 " section %d: defaulting to `.text'", secto);
639 s = get_section_by_name("__TEXT", "__text");
641 /* should never happen */
642 if (!s)
643 nasm_panic("text section not found");
646 /* debug code generation only for sections tagged with
647 * instruction attribute */
648 if (s->flags & S_ATTR_SOME_INSTRUCTIONS)
650 struct section_info sinfo;
651 sinfo.size = s->size;
652 sinfo.secto = secto;
653 dfmt->debug_output(0, &sinfo);
656 is_bss = (s->flags & SECTION_TYPE) == S_ZEROFILL;
658 if (is_bss && type != OUT_RESERVE) {
659 nasm_error(ERR_WARNING, "attempt to initialize memory in "
660 "BSS section: ignored");
661 /* FIXME */
662 nasm_error(ERR_WARNING, "section size may be negative"
663 "with address symbols");
664 s->size += realsize(type, size);
665 return;
668 memset(mydata, 0, sizeof(mydata));
670 switch (type) {
671 case OUT_RESERVE:
672 if (!is_bss) {
673 nasm_error(ERR_WARNING, "uninitialized space declared in"
674 " %s,%s section: zeroing", s->segname, s->sectname);
676 sect_write(s, NULL, size);
677 } else
678 s->size += size;
680 break;
682 case OUT_RAWDATA:
683 sect_write(s, data, size);
684 break;
686 case OUT_ADDRESS:
688 int asize = abs((int)size);
690 addr = *(int64_t *)data;
691 if (section != NO_SEG) {
692 if (section % 2) {
693 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
694 " section base references");
695 } else if (wrt == NO_SEG) {
696 if (fmt.ptrsize == 8 && asize != 8) {
697 nasm_error(ERR_NONFATAL,
698 "Mach-O 64-bit format does not support"
699 " 32-bit absolute addresses");
700 } else {
701 addr += add_reloc(s, section, addr, RL_ABS, asize);
703 } else if (wrt == macho_tlvp_sect && fmt.ptrsize != 8 &&
704 asize == (int) fmt.ptrsize) {
705 addr += add_reloc(s, section, addr, RL_TLV, asize);
706 } else {
707 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
708 " this use of WRT");
712 p = mydata;
713 WRITEADDR(p, addr, asize);
714 sect_write(s, mydata, asize);
715 break;
718 case OUT_REL1ADR:
719 case OUT_REL2ADR:
721 p = mydata;
722 offset = *(int64_t *)data;
723 addr = offset - size;
725 if (section != NO_SEG && section % 2) {
726 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
727 " section base references");
728 } else if (fmt.ptrsize == 8) {
729 nasm_error(ERR_NONFATAL, "Unsupported non-32-bit"
730 " Macho-O relocation [2]");
731 } else if (wrt != NO_SEG) {
732 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
733 " this use of WRT");
734 wrt = NO_SEG; /* we can at least _try_ to continue */
735 } else {
736 addr += add_reloc(s, section, addr+size, RL_REL,
737 type == OUT_REL1ADR ? 1 : 2);
740 WRITESHORT(p, addr);
741 sect_write(s, mydata, type == OUT_REL1ADR ? 1 : 2);
742 break;
744 case OUT_REL4ADR:
745 case OUT_REL8ADR:
747 p = mydata;
748 offset = *(int64_t *)data;
749 addr = offset - size;
750 reltype = RL_REL;
752 if (section != NO_SEG && section % 2) {
753 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
754 " section base references");
755 } else if (wrt == NO_SEG) {
756 if (fmt.ptrsize == 8 &&
757 (s->flags & S_ATTR_SOME_INSTRUCTIONS)) {
758 uint8_t opcode[2];
760 opcode[0] = opcode[1] = 0;
762 /* HACK: Retrieve instruction opcode */
763 if (likely(s->data->datalen >= 2)) {
764 saa_fread(s->data, s->data->datalen-2, opcode, 2);
765 } else if (s->data->datalen == 1) {
766 saa_fread(s->data, 0, opcode+1, 1);
769 if ((opcode[0] != 0x0f && (opcode[1] & 0xfe) == 0xe8) ||
770 (opcode[0] == 0x0f && (opcode[1] & 0xf0) == 0x80)) {
771 /* Direct call, jmp, or jcc */
772 reltype = RL_BRANCH;
775 } else if (wrt == macho_gotpcrel_sect) {
776 reltype = RL_GOT;
778 if ((s->flags & S_ATTR_SOME_INSTRUCTIONS) &&
779 s->data->datalen >= 3) {
780 uint8_t gotload[3];
782 /* HACK: Retrieve instruction opcode */
783 saa_fread(s->data, s->data->datalen-3, gotload, 3);
784 if ((gotload[0] & 0xf8) == 0x48 &&
785 gotload[1] == 0x8b &&
786 (gotload[2] & 0307) == 0005) {
787 /* movq <reg>,[rel sym wrt ..gotpcrel] */
788 reltype = RL_GOTLOAD;
791 } else if (wrt == macho_tlvp_sect && fmt.ptrsize == 8) {
792 reltype = RL_TLV;
793 } else {
794 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
795 " this use of WRT");
796 /* continue with RL_REL */
799 addr += add_reloc(s, section, offset, reltype,
800 type == OUT_REL4ADR ? 4 : 8);
801 WRITELONG(p, addr);
802 sect_write(s, mydata, type == OUT_REL4ADR ? 4 : 8);
803 break;
805 default:
806 nasm_error(ERR_NONFATAL, "Unrepresentable relocation in Mach-O");
807 break;
811 /* Translation table from traditional Unix section names to Mach-O */
812 static const struct sectmap {
813 const char *nasmsect;
814 const char *segname;
815 const char *sectname;
816 const uint32_t flags;
817 } sectmap[] = {
818 {".text", "__TEXT", "__text",
819 S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS},
820 {".data", "__DATA", "__data", S_REGULAR},
821 {".rodata", "__DATA", "__const", S_REGULAR},
822 {".bss", "__DATA", "__bss", S_ZEROFILL},
823 {".debug_abbrev", "__DWARF", "__debug_abbrev", S_ATTR_DEBUG},
824 {".debug_info", "__DWARF", "__debug_info", S_ATTR_DEBUG},
825 {".debug_line", "__DWARF", "__debug_line", S_ATTR_DEBUG},
826 {".debug_str", "__DWARF", "__debug_str", S_ATTR_DEBUG},
827 {NULL, NULL, NULL, 0}
830 #define NO_TYPE S_NASM_TYPE_MASK
832 /* Section type or attribute directives */
833 static const struct sect_attribs {
834 const char *name;
835 uint32_t flags;
836 } sect_attribs[] = {
837 { "data", S_REGULAR },
838 { "code", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS },
839 { "mixed", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS },
840 { "bss", S_ZEROFILL },
841 { "zerofill", S_ZEROFILL },
842 { "no_dead_strip", NO_TYPE|S_ATTR_NO_DEAD_STRIP },
843 { "live_support", NO_TYPE|S_ATTR_LIVE_SUPPORT },
844 { "strip_static_syms", NO_TYPE|S_ATTR_STRIP_STATIC_SYMS },
845 { "debug", NO_TYPE|S_ATTR_DEBUG },
846 { NULL, 0 }
849 static int32_t macho_section(char *name, int pass, int *bits)
851 char *sectionAttributes;
852 const struct sectmap *sm;
853 struct section *s;
854 const char *section, *segment;
855 uint32_t flags;
856 const struct sect_attribs *sa;
857 char *currentAttribute;
858 char *comma;
860 bool new_seg;
862 (void)pass;
864 /* Default to the appropriate number of bits. */
865 if (!name) {
866 *bits = fmt.ptrsize << 3;
867 name = ".text";
868 sectionAttributes = NULL;
869 } else {
870 sectionAttributes = name;
871 name = nasm_strsep(&sectionAttributes, " \t");
874 section = segment = NULL;
875 flags = 0;
877 comma = strchr(name, ',');
878 if (comma) {
879 int len;
881 *comma = '\0';
882 segment = name;
883 section = comma+1;
885 len = strlen(segment);
886 if (len == 0) {
887 nasm_error(ERR_NONFATAL, "empty segment name\n");
888 } else if (len > 16) {
889 nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment);
892 len = strlen(section);
893 if (len == 0) {
894 nasm_error(ERR_NONFATAL, "empty section name\n");
895 } else if (len > 16) {
896 nasm_error(ERR_NONFATAL, "section name %s too long\n", section);
899 if (!strcmp(section, "__text")) {
900 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
901 S_ATTR_PURE_INSTRUCTIONS;
902 } else if (!strcmp(section, "__bss")) {
903 flags = S_ZEROFILL;
904 } else {
905 flags = S_REGULAR;
907 } else {
908 for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
909 /* make lookup into section name translation table */
910 if (!strcmp(name, sm->nasmsect)) {
911 segment = sm->segname;
912 section = sm->sectname;
913 flags = sm->flags;
914 goto found;
917 nasm_error(ERR_NONFATAL, "unknown section name\n");
918 return NO_SEG;
921 found:
922 /* try to find section with that name, or create it */
923 s = find_or_add_section(segment, section);
924 new_seg = is_new_section(s);
926 /* initialize it if it is a brand new section */
927 if (new_seg) {
928 *sectstail = s;
929 sectstail = &s->next;
931 s->data = saa_init(1L);
932 s->fileindex = ++seg_nsects;
933 s->align = -1;
934 s->pad = -1;
935 s->offset = -1;
936 s->by_name = false;
938 s->size = 0;
939 s->nreloc = 0;
940 s->flags = flags;
943 if (comma)
944 *comma = ','; /* Restore comma */
946 s->by_name = s->by_name || comma; /* Was specified by name */
948 flags = NO_TYPE;
950 while (sectionAttributes &&
951 (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
952 if (!*currentAttribute)
953 continue;
955 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
956 char *end;
957 int newAlignment, value;
959 value = strtoul(currentAttribute + 6, (char**)&end, 0);
960 newAlignment = alignlog2_32(value);
962 if (0 != *end) {
963 nasm_error(ERR_NONFATAL,
964 "unknown or missing alignment value \"%s\" "
965 "specified for section \"%s\"",
966 currentAttribute + 6,
967 name);
968 } else if (0 > newAlignment) {
969 nasm_error(ERR_NONFATAL,
970 "alignment of %d (for section \"%s\") is not "
971 "a power of two",
972 value,
973 name);
976 if (s->align < newAlignment)
977 s->align = newAlignment;
978 } else {
979 for (sa = sect_attribs; sa->name; sa++) {
980 if (!nasm_stricmp(sa->name, currentAttribute)) {
981 if ((sa->flags & S_NASM_TYPE_MASK) != NO_TYPE) {
982 flags = (flags & ~S_NASM_TYPE_MASK)
983 | (sa->flags & S_NASM_TYPE_MASK);
985 flags |= sa->flags & ~S_NASM_TYPE_MASK;
986 break;
990 if (!sa->name) {
991 nasm_error(ERR_NONFATAL,
992 "unknown section attribute %s for section %s",
993 currentAttribute, name);
998 if ((flags & S_NASM_TYPE_MASK) != NO_TYPE) {
999 if (!new_seg && ((s->flags ^ flags) & S_NASM_TYPE_MASK)) {
1000 nasm_error(ERR_NONFATAL,
1001 "inconsistent section attributes for section %s\n",
1002 name);
1003 } else {
1004 s->flags = (s->flags & ~S_NASM_TYPE_MASK) | flags;
1006 } else {
1007 s->flags |= flags & ~S_NASM_TYPE_MASK;
1010 return s->subsection;
1013 static int32_t macho_herelabel(const char *name, enum label_type type,
1014 int32_t section, int32_t *subsection,
1015 bool *copyoffset)
1017 struct section *s;
1018 int32_t subsec;
1019 (void)name;
1021 if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS))
1022 return section;
1024 /* No subsection only for local labels */
1025 if (type == LBL_LOCAL)
1026 return section;
1028 s = get_section_by_index(section);
1029 if (!s)
1030 return section;
1032 subsec = *subsection;
1033 if (subsec == NO_SEG) {
1034 /* Allocate a new subsection index */
1035 subsec = *subsection = seg_alloc();
1036 section_by_index = raa_write_ptr(section_by_index, subsec >> 1, s);
1039 s->subsection = subsec;
1040 *copyoffset = true; /* Maintain previous offset */
1041 return subsec;
1044 static void macho_symdef(char *name, int32_t section, int64_t offset,
1045 int is_global, char *special)
1047 struct symbol *sym;
1048 struct section *s;
1049 bool special_used = false;
1051 #if defined(DEBUG) && DEBUG>2
1052 nasm_error(ERR_DEBUG,
1053 " macho_symdef: %s, pass0=%d, passn=%"PRId64", sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
1054 name, pass0, passn, section, offset, is_global, special);
1055 #endif
1057 if (is_global == 3) {
1058 if (special) {
1059 int n = strcspn(special, " \t");
1061 if (!nasm_strnicmp(special, "private_extern", n)) {
1062 for (sym = syms; sym != NULL; sym = sym->next) {
1063 if (!strcmp(name, sym->name)) {
1064 if (sym->type & N_PEXT)
1065 return; /* nothing to be done */
1066 else
1067 break;
1072 nasm_error(ERR_NONFATAL, "The Mach-O format does not "
1073 "(yet) support forward reference fixups.");
1074 return;
1077 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
1079 * This is a NASM special symbol. We never allow it into
1080 * the Macho-O symbol table, even if it's a valid one. If it
1081 * _isn't_ a valid one, we should barf immediately.
1083 if (strcmp(name, "..gotpcrel") && strcmp(name, "..tlvp"))
1084 nasm_error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
1085 return;
1088 sym = *symstail = nasm_zalloc(sizeof(struct symbol));
1089 sym->next = NULL;
1090 symstail = &sym->next;
1092 sym->name = name;
1093 sym->strx = strslen;
1094 sym->type = 0;
1095 sym->desc = 0;
1096 sym->symv[0].key = offset;
1097 sym->symv[1].key = offset;
1098 sym->initial_snum = -1;
1100 /* external and common symbols get N_EXT */
1101 if (is_global != 0) {
1102 sym->type |= N_EXT;
1104 if (is_global == 1) {
1105 /* check special to see if the global symbol shall be marked as private external: N_PEXT */
1106 if (special) {
1107 int n = strcspn(special, " \t");
1109 if (!nasm_strnicmp(special, "private_extern", n))
1110 sym->type |= N_PEXT;
1111 else
1112 nasm_error(ERR_NONFATAL, "unrecognised symbol type `%.*s'", n, special);
1114 special_used = true;
1117 /* track the initially allocated symbol number for use in future fix-ups */
1118 sym->initial_snum = nsyms;
1120 if (section == NO_SEG) {
1121 /* symbols in no section get absolute */
1122 sym->type |= N_ABS;
1123 sym->sect = NO_SECT;
1125 s = &absolute_sect;
1126 } else {
1127 s = get_section_by_index(section);
1129 sym->type |= N_SECT;
1131 /* get the in-file index of the section the symbol was defined in */
1132 sym->sect = s ? s->fileindex : NO_SECT;
1134 if (!s) {
1135 /* remember symbol number of references to external
1136 ** symbols, this works because every external symbol gets
1137 ** its own section number allocated internally by nasm and
1138 ** can so be used as a key */
1139 extsyms = raa_write(extsyms, section, nsyms);
1141 switch (is_global) {
1142 case 1:
1143 case 2:
1144 /* there isn't actually a difference between global
1145 ** and common symbols, both even have their size in
1146 ** sym->symv[0].key */
1147 sym->type = N_EXT;
1148 break;
1150 default:
1151 /* give an error on unfound section if it's not an
1152 ** external or common symbol (assemble_file() does a
1153 ** seg_alloc() on every call for them) */
1154 nasm_panic("in-file index for section %d not found, is_global = %d", section, is_global);
1155 break;
1160 if (s) {
1161 s->syms[0] = rb_insert(s->syms[0], &sym->symv[0]);
1162 if (is_global)
1163 s->syms[1] = rb_insert(s->syms[1], &sym->symv[1]);
1166 ++nsyms;
1168 if (special && !special_used)
1169 nasm_error(ERR_NONFATAL, "no special symbol features supported here");
1172 static void macho_sectalign(int32_t seg, unsigned int value)
1174 struct section *s;
1175 int align;
1177 nasm_assert(!(seg & 1));
1179 s = get_section_by_index(seg);
1181 if (!s || !is_power2(value))
1182 return;
1184 align = alignlog2_32(value);
1185 if (s->align < align)
1186 s->align = align;
1189 extern macros_t macho_stdmac[];
1191 /* Comparison function for qsort symbol layout. */
1192 static int layout_compare (const struct symbol **s1,
1193 const struct symbol **s2)
1195 return (strcmp ((*s1)->name, (*s2)->name));
1198 /* The native assembler does a few things in a similar function
1200 * Remove temporary labels
1201 * Sort symbols according to local, external, undefined (by name)
1202 * Order the string table
1204 We do not remove temporary labels right now.
1206 numsyms is the total number of symbols we have. strtabsize is the
1207 number entries in the string table. */
1209 static void macho_layout_symbols (uint32_t *numsyms,
1210 uint32_t *strtabsize)
1212 struct symbol *sym, **symp;
1213 uint32_t i,j;
1215 *numsyms = 0;
1216 *strtabsize = sizeof (char);
1218 symp = &syms;
1220 while ((sym = *symp)) {
1221 /* Undefined symbols are now external. */
1222 if (sym->type == N_UNDF)
1223 sym->type |= N_EXT;
1225 if ((sym->type & N_EXT) == 0) {
1226 sym->snum = *numsyms;
1227 *numsyms = *numsyms + 1;
1228 nlocalsym++;
1230 else {
1231 if ((sym->type & N_TYPE) != N_UNDF) {
1232 nextdefsym++;
1233 } else {
1234 nundefsym++;
1237 /* If we handle debug info we'll want
1238 to check for it here instead of just
1239 adding the symbol to the string table. */
1240 sym->strx = *strtabsize;
1241 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
1242 *strtabsize += strlen(sym->name) + 1;
1244 symp = &(sym->next);
1247 /* Next, sort the symbols. Most of this code is a direct translation from
1248 the Apple cctools symbol layout. We need to keep compatibility with that. */
1249 /* Set the indexes for symbol groups into the symbol table */
1250 ilocalsym = 0;
1251 iextdefsym = nlocalsym;
1252 iundefsym = nlocalsym + nextdefsym;
1254 /* allocate arrays for sorting externals by name */
1255 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
1256 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
1258 i = 0;
1259 j = 0;
1261 symp = &syms;
1263 while ((sym = *symp)) {
1265 if((sym->type & N_EXT) == 0) {
1266 sym->strx = *strtabsize;
1267 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
1268 *strtabsize += strlen(sym->name) + 1;
1270 else {
1271 if ((sym->type & N_TYPE) != N_UNDF) {
1272 extdefsyms[i++] = sym;
1273 } else {
1274 undefsyms[j++] = sym;
1277 symp = &(sym->next);
1280 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
1281 (int (*)(const void *, const void *))layout_compare);
1282 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
1283 (int (*)(const void *, const void *))layout_compare);
1285 for(i = 0; i < nextdefsym; i++) {
1286 extdefsyms[i]->snum = *numsyms;
1287 *numsyms += 1;
1289 for(j = 0; j < nundefsym; j++) {
1290 undefsyms[j]->snum = *numsyms;
1291 *numsyms += 1;
1295 /* Calculate some values we'll need for writing later. */
1297 static void macho_calculate_sizes (void)
1299 struct section *s;
1300 int fi;
1302 /* count sections and calculate in-memory and in-file offsets */
1303 for (s = sects; s != NULL; s = s->next) {
1304 uint64_t newaddr;
1306 /* recalculate segment address based on alignment and vm size */
1307 s->addr = seg_vmsize;
1309 /* we need section alignment to calculate final section address */
1310 if (s->align == -1)
1311 s->align = DEFAULT_SECTION_ALIGNMENT;
1313 newaddr = ALIGN(s->addr, UINT64_C(1) << s->align);
1314 s->addr = newaddr;
1316 seg_vmsize = newaddr + s->size;
1318 /* zerofill sections aren't actually written to the file */
1319 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1321 * LLVM/Xcode as always aligns the section data to 4
1322 * bytes; there is a comment in the LLVM source code that
1323 * perhaps aligning to pointer size would be better.
1325 s->pad = ALIGN(seg_filesize, 4) - seg_filesize;
1326 s->offset = seg_filesize + s->pad;
1327 seg_filesize += s->size + s->pad;
1329 /* filesize and vmsize needs to be aligned */
1330 seg_vmsize += s->pad;
1334 /* calculate size of all headers, load commands and sections to
1335 ** get a pointer to the start of all the raw data */
1336 if (seg_nsects > 0) {
1337 ++head_ncmds;
1338 head_sizeofcmds += fmt.segcmd_size + seg_nsects * fmt.sectcmd_size;
1341 if (nsyms > 0) {
1342 ++head_ncmds;
1343 head_sizeofcmds += MACHO_SYMCMD_SIZE;
1346 if (seg_nsects > MAX_SECT) {
1347 nasm_fatal("MachO output is limited to %d sections\n",
1348 MAX_SECT);
1351 /* Create a table of sections by file index to avoid linear search */
1352 sectstab = nasm_malloc((seg_nsects + 1) * sizeof(*sectstab));
1353 sectstab[NO_SECT] = &absolute_sect;
1354 for (s = sects, fi = 1; s != NULL; s = s->next, fi++)
1355 sectstab[fi] = s;
1358 /* Write out the header information for the file. */
1360 static void macho_write_header (void)
1362 fwriteint32_t(fmt.mh_magic, ofile); /* magic */
1363 fwriteint32_t(fmt.cpu_type, ofile); /* CPU type */
1364 fwriteint32_t(CPU_SUBTYPE_I386_ALL, ofile); /* CPU subtype */
1365 fwriteint32_t(MH_OBJECT, ofile); /* Mach-O file type */
1366 fwriteint32_t(head_ncmds, ofile); /* number of load commands */
1367 fwriteint32_t(head_sizeofcmds, ofile); /* size of load commands */
1368 fwriteint32_t(head_flags, ofile); /* flags, if any */
1369 fwritezero(fmt.header_size - 7*4, ofile); /* reserved fields */
1372 /* Write out the segment load command at offset. */
1374 static uint32_t macho_write_segment (uint64_t offset)
1376 uint64_t rel_base = alignptr(offset + seg_filesize);
1377 uint32_t s_reloff = 0;
1378 struct section *s;
1380 fwriteint32_t(fmt.lc_segment, ofile); /* cmd == LC_SEGMENT_64 */
1382 /* size of load command including section load commands */
1383 fwriteint32_t(fmt.segcmd_size + seg_nsects * fmt.sectcmd_size,
1384 ofile);
1386 /* in an MH_OBJECT file all sections are in one unnamed (name
1387 ** all zeros) segment */
1388 fwritezero(16, ofile);
1389 fwriteptr(0, ofile); /* in-memory offset */
1390 fwriteptr(seg_vmsize, ofile); /* in-memory size */
1391 fwriteptr(offset, ofile); /* in-file offset to data */
1392 fwriteptr(seg_filesize, ofile); /* in-file size */
1393 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* maximum vm protection */
1394 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* initial vm protection */
1395 fwriteint32_t(seg_nsects, ofile); /* number of sections */
1396 fwriteint32_t(0, ofile); /* no flags */
1398 /* emit section headers */
1399 for (s = sects; s != NULL; s = s->next) {
1400 if (s->nreloc) {
1401 nasm_assert((s->flags & SECTION_TYPE) != S_ZEROFILL);
1402 s->flags |= S_ATTR_LOC_RELOC;
1403 if (s->extreloc)
1404 s->flags |= S_ATTR_EXT_RELOC;
1405 } else if (!xstrncmp(s->segname, "__DATA") &&
1406 !xstrncmp(s->sectname, "__const") &&
1407 !s->by_name &&
1408 !get_section_by_name("__TEXT", "__const")) {
1410 * The MachO equivalent to .rodata can be either
1411 * __DATA,__const or __TEXT,__const; the latter only if
1412 * there are no relocations. However, when mixed it is
1413 * better to specify the segments explicitly.
1415 xstrncpy(s->segname, "__TEXT");
1418 nasm_write(s->sectname, sizeof(s->sectname), ofile);
1419 nasm_write(s->segname, sizeof(s->segname), ofile);
1420 fwriteptr(s->addr, ofile);
1421 fwriteptr(s->size, ofile);
1423 /* dummy data for zerofill sections or proper values */
1424 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1425 nasm_assert(s->pad != (uint32_t)-1);
1426 offset += s->pad;
1427 fwriteint32_t(offset, ofile);
1428 offset += s->size;
1429 /* Write out section alignment, as a power of two.
1430 e.g. 32-bit word alignment would be 2 (2^2 = 4). */
1431 fwriteint32_t(s->align, ofile);
1432 /* To be compatible with cctools as we emit
1433 a zero reloff if we have no relocations. */
1434 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile);
1435 fwriteint32_t(s->nreloc, ofile);
1437 s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
1438 } else {
1439 fwriteint32_t(0, ofile);
1440 fwriteint32_t(s->align, ofile);
1441 fwriteint32_t(0, ofile);
1442 fwriteint32_t(0, ofile);
1445 fwriteint32_t(s->flags, ofile); /* flags */
1446 fwriteint32_t(0, ofile); /* reserved */
1447 fwriteptr(0, ofile); /* reserved */
1450 rel_padcnt = rel_base - offset;
1451 offset = rel_base + s_reloff;
1453 return offset;
1456 /* For a given chain of relocs r, write out the entire relocation
1457 chain to the object file. */
1459 static void macho_write_relocs (struct reloc *r)
1461 while (r) {
1462 uint32_t word2;
1464 fwriteint32_t(r->addr, ofile); /* reloc offset */
1466 word2 = r->snum;
1467 word2 |= r->pcrel << 24;
1468 word2 |= r->length << 25;
1469 word2 |= r->ext << 27;
1470 word2 |= r->type << 28;
1471 fwriteint32_t(word2, ofile); /* reloc data */
1472 r = r->next;
1476 /* Write out the section data. */
1477 static void macho_write_section (void)
1479 struct section *s;
1480 struct reloc *r;
1481 uint8_t *p;
1482 int32_t len;
1483 int64_t l;
1484 union offset {
1485 uint64_t val;
1486 uint8_t buf[8];
1487 } blk;
1489 for (s = sects; s != NULL; s = s->next) {
1490 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
1491 continue;
1493 /* Like a.out Mach-O references things in the data or bss
1494 * sections by addresses which are actually relative to the
1495 * start of the _text_ section, in the _file_. See outaout.c
1496 * for more information. */
1497 saa_rewind(s->data);
1498 for (r = s->relocs; r != NULL; r = r->next) {
1499 len = (uint32_t)1 << r->length;
1500 if (len > 4) /* Can this ever be an issue?! */
1501 len = 8;
1502 blk.val = 0;
1503 saa_fread(s->data, r->addr, blk.buf, len);
1505 /* get offset based on relocation type */
1506 #ifdef WORDS_LITTLEENDIAN
1507 l = blk.val;
1508 #else
1509 l = blk.buf[0];
1510 l += ((int64_t)blk.buf[1]) << 8;
1511 l += ((int64_t)blk.buf[2]) << 16;
1512 l += ((int64_t)blk.buf[3]) << 24;
1513 l += ((int64_t)blk.buf[4]) << 32;
1514 l += ((int64_t)blk.buf[5]) << 40;
1515 l += ((int64_t)blk.buf[6]) << 48;
1516 l += ((int64_t)blk.buf[7]) << 56;
1517 #endif
1519 /* If the relocation is internal add to the current section
1520 offset. Otherwise the only value we need is the symbol
1521 offset which we already have. The linker takes care
1522 of the rest of the address. */
1523 if (!r->ext) {
1524 /* generate final address by section address and offset */
1525 nasm_assert(r->snum <= seg_nsects);
1526 l += sectstab[r->snum]->addr;
1527 if (r->pcrel)
1528 l -= s->addr;
1529 } else if (r->pcrel && r->type == GENERIC_RELOC_VANILLA) {
1530 l -= s->addr;
1533 /* write new offset back */
1534 p = blk.buf;
1535 WRITEDLONG(p, l);
1536 saa_fwrite(s->data, r->addr, blk.buf, len);
1539 /* dump the section data to file */
1540 fwritezero(s->pad, ofile);
1541 saa_fpwrite(s->data, ofile);
1544 /* pad last section up to reloc entries on pointer boundary */
1545 fwritezero(rel_padcnt, ofile);
1547 /* emit relocation entries */
1548 for (s = sects; s != NULL; s = s->next)
1549 macho_write_relocs (s->relocs);
1552 /* Write out the symbol table. We should already have sorted this
1553 before now. */
1554 static void macho_write_symtab (void)
1556 struct symbol *sym;
1557 uint64_t i;
1559 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1561 for (sym = syms; sym != NULL; sym = sym->next) {
1562 if ((sym->type & N_EXT) == 0) {
1563 fwriteint32_t(sym->strx, ofile); /* string table entry number */
1564 nasm_write(&sym->type, 1, ofile); /* symbol type */
1565 nasm_write(&sym->sect, 1, ofile); /* section */
1566 fwriteint16_t(sym->desc, ofile); /* description */
1568 /* Fix up the symbol value now that we know the final section
1569 sizes. */
1570 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1571 nasm_assert(sym->sect <= seg_nsects);
1572 sym->symv[0].key += sectstab[sym->sect]->addr;
1575 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1579 for (i = 0; i < nextdefsym; i++) {
1580 sym = extdefsyms[i];
1581 fwriteint32_t(sym->strx, ofile);
1582 nasm_write(&sym->type, 1, ofile); /* symbol type */
1583 nasm_write(&sym->sect, 1, ofile); /* section */
1584 fwriteint16_t(sym->desc, ofile); /* description */
1586 /* Fix up the symbol value now that we know the final section
1587 sizes. */
1588 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1589 nasm_assert(sym->sect <= seg_nsects);
1590 sym->symv[0].key += sectstab[sym->sect]->addr;
1593 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1596 for (i = 0; i < nundefsym; i++) {
1597 sym = undefsyms[i];
1598 fwriteint32_t(sym->strx, ofile);
1599 nasm_write(&sym->type, 1, ofile); /* symbol type */
1600 nasm_write(&sym->sect, 1, ofile); /* section */
1601 fwriteint16_t(sym->desc, ofile); /* description */
1603 /* Fix up the symbol value now that we know the final section
1604 sizes. */
1605 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1606 nasm_assert(sym->sect <= seg_nsects);
1607 sym->symv[0].key += sectstab[sym->sect]->addr;
1610 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1615 /* Fixup the snum in the relocation entries, we should be
1616 doing this only for externally referenced symbols. */
1617 static void macho_fixup_relocs (struct reloc *r)
1619 struct symbol *sym;
1621 while (r != NULL) {
1622 if (r->ext) {
1623 for (sym = syms; sym != NULL; sym = sym->next) {
1624 if (sym->initial_snum == r->snum) {
1625 r->snum = sym->snum;
1626 break;
1630 r = r->next;
1634 /* Write out the object file. */
1636 static void macho_write (void)
1638 uint64_t offset = 0;
1640 /* mach-o object file structure:
1642 ** mach header
1643 ** uint32_t magic
1644 ** int cpu type
1645 ** int cpu subtype
1646 ** uint32_t mach file type
1647 ** uint32_t number of load commands
1648 ** uint32_t size of all load commands
1649 ** (includes section struct size of segment command)
1650 ** uint32_t flags
1652 ** segment command
1653 ** uint32_t command type == LC_SEGMENT[_64]
1654 ** uint32_t size of load command
1655 ** (including section load commands)
1656 ** char[16] segment name
1657 ** pointer in-memory offset
1658 ** pointer in-memory size
1659 ** pointer in-file offset to data area
1660 ** pointer in-file size
1661 ** (in-memory size excluding zerofill sections)
1662 ** int maximum vm protection
1663 ** int initial vm protection
1664 ** uint32_t number of sections
1665 ** uint32_t flags
1667 ** section commands
1668 ** char[16] section name
1669 ** char[16] segment name
1670 ** pointer in-memory offset
1671 ** pointer in-memory size
1672 ** uint32_t in-file offset
1673 ** uint32_t alignment
1674 ** (irrelevant in MH_OBJECT)
1675 ** uint32_t in-file offset of relocation entires
1676 ** uint32_t number of relocations
1677 ** uint32_t flags
1678 ** uint32_t reserved
1679 ** uint32_t reserved
1681 ** symbol table command
1682 ** uint32_t command type == LC_SYMTAB
1683 ** uint32_t size of load command
1684 ** uint32_t symbol table offset
1685 ** uint32_t number of symbol table entries
1686 ** uint32_t string table offset
1687 ** uint32_t string table size
1689 ** raw section data
1691 ** padding to pointer boundary
1693 ** relocation data (struct reloc)
1694 ** int32_t offset
1695 ** uint data (symbolnum, pcrel, length, extern, type)
1697 ** symbol table data (struct nlist)
1698 ** int32_t string table entry number
1699 ** uint8_t type
1700 ** (extern, absolute, defined in section)
1701 ** uint8_t section
1702 ** (0 for global symbols, section number of definition (>= 1, <=
1703 ** 254) for local symbols, size of variable for common symbols
1704 ** [type == extern])
1705 ** int16_t description
1706 ** (for stab debugging format)
1707 ** pointer value (i.e. file offset) of symbol or stab offset
1709 ** string table data
1710 ** list of null-terminated strings
1713 /* Emit the Mach-O header. */
1714 macho_write_header();
1716 offset = fmt.header_size + head_sizeofcmds;
1718 /* emit the segment load command */
1719 if (seg_nsects > 0)
1720 offset = macho_write_segment (offset);
1721 else
1722 nasm_error(ERR_WARNING, "no sections?");
1724 if (nsyms > 0) {
1725 /* write out symbol command */
1726 fwriteint32_t(LC_SYMTAB, ofile); /* cmd == LC_SYMTAB */
1727 fwriteint32_t(MACHO_SYMCMD_SIZE, ofile); /* size of load command */
1728 fwriteint32_t(offset, ofile); /* symbol table offset */
1729 fwriteint32_t(nsyms, ofile); /* number of symbol
1730 ** table entries */
1731 offset += nsyms * fmt.nlist_size;
1732 fwriteint32_t(offset, ofile); /* string table offset */
1733 fwriteint32_t(strslen, ofile); /* string table size */
1736 /* emit section data */
1737 if (seg_nsects > 0)
1738 macho_write_section ();
1740 /* emit symbol table if we have symbols */
1741 if (nsyms > 0)
1742 macho_write_symtab ();
1744 /* we don't need to pad here, we are already aligned */
1746 /* emit string table */
1747 saa_fpwrite(strs, ofile);
1749 /* We do quite a bit here, starting with finalizing all of the data
1750 for the object file, writing, and then freeing all of the data from
1751 the file. */
1753 static void macho_cleanup(void)
1755 struct section *s;
1756 struct reloc *r;
1757 struct symbol *sym;
1759 dfmt->cleanup();
1761 /* Sort all symbols. */
1762 macho_layout_symbols (&nsyms, &strslen);
1764 /* Fixup relocation entries */
1765 for (s = sects; s != NULL; s = s->next) {
1766 macho_fixup_relocs (s->relocs);
1769 /* First calculate and finalize needed values. */
1770 macho_calculate_sizes();
1771 macho_write();
1773 /* free up everything */
1774 while (sects->next) {
1775 s = sects;
1776 sects = sects->next;
1778 saa_free(s->data);
1779 while (s->relocs != NULL) {
1780 r = s->relocs;
1781 s->relocs = s->relocs->next;
1782 nasm_free(r);
1785 nasm_free(s);
1788 saa_free(strs);
1790 raa_free(extsyms);
1792 while (syms) {
1793 sym = syms;
1794 syms = syms->next;
1795 nasm_free (sym);
1798 nasm_free(extdefsyms);
1799 nasm_free(undefsyms);
1800 nasm_free(sectstab);
1801 raa_free(section_by_index);
1802 hash_free(&section_by_name);
1805 static bool macho_set_section_attribute_by_symbol(const char *label, uint32_t flags)
1807 struct section *s;
1808 int32_t nasm_seg;
1809 int64_t offset;
1811 if (!lookup_label(label, &nasm_seg, &offset)) {
1812 nasm_error(ERR_NONFATAL, "unknown symbol `%s' in no_dead_strip", label);
1813 return false;
1816 s = get_section_by_index(nasm_seg);
1817 if (!s) {
1818 nasm_error(ERR_NONFATAL, "symbol `%s' is external or absolute", label);
1819 return false;
1822 s->flags |= flags;
1823 return true;
1827 * Mark a symbol for no dead stripping
1829 static enum directive_result macho_no_dead_strip(const char *labels)
1831 char *s, *p, *ep;
1832 char ec;
1833 enum directive_result rv = DIRR_ERROR;
1834 bool real = passn > 1;
1836 p = s = nasm_strdup(labels);
1837 while (*p) {
1838 ep = nasm_skip_identifier(p);
1839 if (!ep) {
1840 nasm_error(ERR_NONFATAL, "invalid symbol in NO_DEAD_STRIP");
1841 goto err;
1843 ec = *ep;
1844 if (ec && ec != ',' && !nasm_isspace(ec)) {
1845 nasm_error(ERR_NONFATAL, "cannot parse contents after symbol");
1846 goto err;
1848 *ep = '\0';
1849 if (real) {
1850 if (!macho_set_section_attribute_by_symbol(p, S_ATTR_NO_DEAD_STRIP))
1851 rv = DIRR_ERROR;
1853 *ep = ec;
1854 p = nasm_skip_spaces(ep);
1855 if (*p == ',')
1856 p = nasm_skip_spaces(++p);
1859 rv = DIRR_OK;
1861 err:
1862 nasm_free(s);
1863 return rv;
1867 * Mach-O pragmas
1869 static enum directive_result
1870 macho_pragma(const struct pragma *pragma)
1872 bool real = passn > 1;
1874 switch (pragma->opcode) {
1875 case D_SUBSECTIONS_VIA_SYMBOLS:
1876 if (*pragma->tail)
1877 return DIRR_BADPARAM;
1879 if (real)
1880 head_flags |= MH_SUBSECTIONS_VIA_SYMBOLS;
1882 /* Jmp-match optimization conflicts */
1883 optimizing.flag |= OPTIM_DISABLE_JMP_MATCH;
1885 return DIRR_OK;
1887 case D_NO_DEAD_STRIP:
1888 return macho_no_dead_strip(pragma->tail);
1890 default:
1891 return DIRR_UNKNOWN; /* Not a Mach-O directive */
1895 static const struct pragma_facility macho_pragma_list[] = {
1896 { "macho", macho_pragma },
1897 { NULL, macho_pragma } /* Implements macho32/macho64 namespaces */
1900 static void macho_dbg_generate(void)
1902 uint8_t *p_buf = NULL, *p_buf_base = NULL;
1903 size_t saa_len = 0, high_addr = 0, total_len = 0;
1904 struct section *p_section = NULL;
1905 /* calculated at debug_str and referenced at debug_info */
1906 uint32_t producer_str_offset = 0, module_str_offset = 0, dir_str_offset = 0;
1908 /* debug section defines */
1910 int bits = 0;
1911 macho_section(".debug_abbrev", 0, &bits);
1912 macho_section(".debug_info", 0, &bits);
1913 macho_section(".debug_line", 0, &bits);
1914 macho_section(".debug_str", 0, &bits);
1917 /* dw section walk to find high_addr and total_len */
1919 struct dw_sect_list *p_sect;
1921 list_for_each(p_sect, dw_head_sect) {
1922 uint64_t offset = get_section_by_index(p_sect->section)->size;
1923 struct SAA *p_linep = p_sect->psaa;
1925 saa_write8(p_linep, 2); /* std op 2 */
1926 saa_write8(p_linep, offset - p_sect->offset);
1927 saa_write8(p_linep, DW_LNS_extended_op);
1928 saa_write8(p_linep, 1); /* operand length */
1929 saa_write8(p_linep, DW_LNE_end_sequence);
1931 total_len += p_linep->datalen;
1932 high_addr += offset;
1936 /* debug line */
1938 struct dw_sect_list *p_sect;
1939 size_t linep_off, buf_size;
1940 struct SAA *p_lines = saa_init(1L);
1941 struct dir_list *p_dir;
1942 struct file_list *p_file;
1944 p_section = get_section_by_name("__DWARF", "__debug_line");
1945 nasm_assert(p_section != NULL);
1947 saa_write8(p_lines, 1); /* minimum instruction length */
1948 saa_write8(p_lines, 1); /* initial value of "is_stmt" */
1949 saa_write8(p_lines, DW_LN_BASE); /* line base */
1950 saa_write8(p_lines, DW_LN_RANGE); /* line range */
1951 saa_write8(p_lines, DW_OPCODE_BASE); /* opcode base */
1952 saa_write8(p_lines, 0); /* std opcode 1 length */
1953 saa_write8(p_lines, 1); /* std opcode 2 length */
1954 saa_write8(p_lines, 1); /* std opcode 3 length */
1955 saa_write8(p_lines, 1); /* std opcode 4 length */
1956 saa_write8(p_lines, 1); /* std opcode 5 length */
1957 saa_write8(p_lines, 0); /* std opcode 6 length */
1958 saa_write8(p_lines, 0); /* std opcode 7 length */
1959 saa_write8(p_lines, 0); /* std opcode 8 length */
1960 saa_write8(p_lines, 1); /* std opcode 9 length */
1961 saa_write8(p_lines, 0); /* std opcode 10 length */
1962 saa_write8(p_lines, 0); /* std opcode 11 length */
1963 saa_write8(p_lines, 1); /* std opcode 12 length */
1964 list_for_each(p_dir, dw_head_dir) {
1965 saa_wcstring(p_lines, p_dir->dir_name);
1967 saa_write8(p_lines, 0); /* end of table */
1969 list_for_each(p_file, dw_head_file) {
1970 saa_wcstring(p_lines, p_file->file_name);
1971 saa_write8(p_lines, p_file->dir->dir); /* directory id */
1972 saa_write8(p_lines, 0); /* time */
1973 saa_write8(p_lines, 0); /* size */
1975 saa_write8(p_lines, 0); /* end of table */
1977 linep_off = p_lines->datalen;
1978 /* 10 bytes for initial & prolong length, and dwarf version info */
1979 buf_size = saa_len = linep_off + total_len + 10;
1980 p_buf_base = p_buf = nasm_malloc(buf_size);
1982 WRITELONG(p_buf, saa_len - 4); /* initial length; size excluding itself */
1983 WRITESHORT(p_buf, 2); /* dwarf version */
1984 WRITELONG(p_buf, linep_off); /* prolong length */
1986 saa_rnbytes(p_lines, p_buf, linep_off);
1987 p_buf += linep_off;
1988 saa_free(p_lines);
1990 list_for_each(p_sect, dw_head_sect) {
1991 struct SAA *p_linep = p_sect->psaa;
1993 saa_len = p_linep->datalen;
1994 saa_rnbytes(p_linep, p_buf, saa_len);
1995 p_buf += saa_len;
1997 saa_free(p_linep);
2000 macho_output(p_section->index, p_buf_base, OUT_RAWDATA, buf_size, NO_SEG, 0);
2002 nasm_free(p_buf_base);
2005 /* string section */
2007 struct SAA *p_str = saa_init(1L);
2008 char *cur_path = nasm_realpath(module_name);
2009 char *cur_file = nasm_basename(cur_path);
2010 char *cur_dir = nasm_dirname(cur_path);
2012 p_section = get_section_by_name("__DWARF", "__debug_str");
2013 nasm_assert(p_section != NULL);
2015 producer_str_offset = 0;
2016 module_str_offset = dir_str_offset = saa_wcstring(p_str, nasm_signature);
2017 dir_str_offset += saa_wcstring(p_str, cur_file);
2018 saa_wcstring(p_str, cur_dir);
2020 saa_len = p_str->datalen;
2021 p_buf = nasm_malloc(saa_len);
2022 saa_rnbytes(p_str, p_buf, saa_len);
2023 macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0);
2025 nasm_free(cur_path);
2026 nasm_free(cur_file);
2027 nasm_free(cur_dir);
2028 saa_free(p_str);
2029 nasm_free(p_buf);
2032 /* debug info */
2034 struct SAA *p_info = saa_init(1L);
2036 p_section = get_section_by_name("__DWARF", "__debug_info");
2037 nasm_assert(p_section != NULL);
2039 /* size will be overwritten once determined, so skip in p_info layout */
2040 saa_write16(p_info, 2); /* dwarf version */
2041 saa_write32(p_info, 0); /* offset info abbrev */
2042 saa_write8(p_info, (ofmt == &of_macho64) ? 8 : 4); /* pointer size */
2044 saa_write8(p_info, 1); /* abbrev entry number */
2046 saa_write32(p_info, producer_str_offset); /* offset from string table for DW_AT_producer */
2047 saa_write16(p_info, DW_LANG_Mips_Assembler); /* DW_AT_language */
2048 saa_write32(p_info, module_str_offset); /* offset from string table for DW_AT_name */
2049 saa_write32(p_info, dir_str_offset); /* offset from string table for DW_AT_comp_dir */
2050 saa_write32(p_info, 0); /* DW_AT_stmt_list */
2052 if (ofmt == &of_macho64) {
2053 saa_write64(p_info, 0); /* DW_AT_low_pc */
2054 saa_write64(p_info, high_addr); /* DW_AT_high_pc */
2055 } else {
2056 saa_write32(p_info, 0); /* DW_AT_low_pc */
2057 saa_write32(p_info, high_addr); /* DW_AT_high_pc */
2060 saa_write8(p_info, 2); /* abbrev entry number */
2062 if (ofmt == &of_macho64) {
2063 saa_write64(p_info, 0); /* DW_AT_low_pc */
2064 saa_write64(p_info, 0); /* DW_AT_frame_base */
2065 } else {
2066 saa_write32(p_info, 0); /* DW_AT_low_pc */
2067 saa_write32(p_info, 0); /* DW_AT_frame_base */
2069 saa_write8(p_info, DW_END_default);
2071 saa_len = p_info->datalen;
2072 p_buf_base = p_buf = nasm_malloc(saa_len + 4); /* 4B for size info */
2074 WRITELONG(p_buf, saa_len);
2075 saa_rnbytes(p_info, p_buf, saa_len);
2076 macho_output(p_section->index, p_buf_base, OUT_RAWDATA, saa_len + 4, NO_SEG, 0);
2078 saa_free(p_info);
2079 nasm_free(p_buf_base);
2082 /* abbrev section */
2084 struct SAA *p_abbrev = saa_init(1L);
2086 p_section = get_section_by_name("__DWARF", "__debug_abbrev");
2087 nasm_assert(p_section != NULL);
2089 saa_write8(p_abbrev, 1); /* entry number */
2091 saa_write8(p_abbrev, DW_TAG_compile_unit);
2092 saa_write8(p_abbrev, DW_CHILDREN_yes);
2094 saa_write8(p_abbrev, DW_AT_producer);
2095 saa_write8(p_abbrev, DW_FORM_strp);
2097 saa_write8(p_abbrev, DW_AT_language);
2098 saa_write8(p_abbrev, DW_FORM_data2);
2100 saa_write8(p_abbrev, DW_AT_name);
2101 saa_write8(p_abbrev, DW_FORM_strp);
2103 saa_write8(p_abbrev, DW_AT_comp_dir);
2104 saa_write8(p_abbrev, DW_FORM_strp);
2106 saa_write8(p_abbrev, DW_AT_stmt_list);
2107 saa_write8(p_abbrev, DW_FORM_data4);
2109 saa_write8(p_abbrev, DW_AT_low_pc);
2110 saa_write8(p_abbrev, DW_FORM_addr);
2112 saa_write8(p_abbrev, DW_AT_high_pc);
2113 saa_write8(p_abbrev, DW_FORM_addr);
2115 saa_write16(p_abbrev, DW_END_default);
2117 saa_write8(p_abbrev, 2); /* entry number */
2119 saa_write8(p_abbrev, DW_TAG_subprogram);
2120 saa_write8(p_abbrev, DW_CHILDREN_no);
2122 saa_write8(p_abbrev, DW_AT_low_pc);
2123 saa_write8(p_abbrev, DW_FORM_addr);
2125 saa_write8(p_abbrev, DW_AT_frame_base);
2126 saa_write8(p_abbrev, DW_FORM_addr);
2128 saa_write16(p_abbrev, DW_END_default);
2130 saa_write8(p_abbrev, 0); /* Terminal zero entry */
2132 saa_len = p_abbrev->datalen;
2134 p_buf = nasm_malloc(saa_len);
2136 saa_rnbytes(p_abbrev, p_buf, saa_len);
2137 macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0);
2139 saa_free(p_abbrev);
2140 nasm_free(p_buf);
2144 static void new_file_list (const char *file_name, const char *dir_name)
2146 struct dir_list *dir_list;
2147 bool need_new_dir_list = true;
2149 nasm_new(dw_cur_file);
2150 dw_cur_file->file = ++dw_num_files;
2151 dw_cur_file->file_name = file_name;
2152 if(!dw_head_file) {
2153 dw_head_file = dw_cur_file;
2154 } else {
2155 *dw_last_file_next = dw_cur_file;
2157 dw_last_file_next = &(dw_cur_file->next);
2159 if(dw_head_dir) {
2160 list_for_each(dir_list, dw_head_dir) {
2161 if(!(strcmp(dir_name, dir_list->dir_name))) {
2162 dw_cur_file->dir = dir_list;
2163 need_new_dir_list = false;
2164 break;
2169 if(need_new_dir_list)
2171 nasm_new(dir_list);
2172 dir_list->dir = dw_num_dirs++;
2173 dir_list->dir_name = dir_name;
2174 if(!dw_head_dir) {
2175 dw_head_dir = dir_list;
2176 } else {
2177 *dw_last_dir_next = dir_list;
2179 dw_last_dir_next = &(dir_list->next);
2180 dw_cur_file->dir = dir_list;
2184 static void macho_dbg_init(void)
2188 static void macho_dbg_linenum(const char *file_name, int32_t line_num, int32_t segto)
2190 bool need_new_list = true;
2191 const char *cur_file = nasm_basename(file_name);
2192 const char *cur_dir = nasm_dirname(file_name);
2193 (void)segto;
2195 if(!dw_cur_file || strcmp(cur_file, dw_cur_file->file_name) ||
2196 strcmp(cur_dir, dw_cur_file->dir->dir_name)) {
2197 if(dw_head_file) {
2198 struct file_list *match;
2200 list_for_each(match, dw_head_file) {
2201 if(!(strcmp(cur_file, match->file_name)) &&
2202 !(strcmp(cur_dir, match->dir->dir_name))) {
2203 dw_cur_file = match;
2204 dw_cur_file->dir = match->dir;
2205 need_new_list = false;
2206 break;
2211 if(need_new_list) {
2212 new_file_list(cur_file, cur_dir);
2216 dbg_immcall = true;
2217 cur_line = line_num;
2220 static void macho_dbg_output(int type, void *param)
2222 struct section_info *sinfo_param = (struct section_info *)param;
2223 int32_t secto = sinfo_param->secto;
2224 bool need_new_sect = false;
2225 struct SAA *p_linep = NULL;
2226 (void)type;
2228 if(!(dw_cur_sect && (dw_cur_sect->section == secto))) {
2229 need_new_sect = true;
2230 if(dw_head_sect) {
2231 struct dw_sect_list *match = dw_head_sect;
2232 uint32_t idx = 0;
2234 for(; idx < dw_num_sects; idx++) {
2235 if(match->section == secto) {
2236 dw_cur_sect = match;
2237 need_new_sect = false;
2238 break;
2240 match = match->next;
2245 if(need_new_sect) {
2246 nasm_new(dw_cur_sect);
2247 dw_num_sects ++;
2248 p_linep = dw_cur_sect->psaa = saa_init(1L);
2249 dw_cur_sect->line = dw_cur_sect->file = 1;
2250 dw_cur_sect->offset = 0;
2251 dw_cur_sect->next = NULL;
2252 dw_cur_sect->section = secto;
2254 saa_write8(p_linep, DW_LNS_extended_op);
2255 saa_write8(p_linep, (ofmt == &of_macho64) ? 9 : 5);
2256 saa_write8(p_linep, DW_LNE_set_address);
2257 if (ofmt == &of_macho64) {
2258 saa_write64(p_linep, 0);
2259 } else {
2260 saa_write32(p_linep, 0);
2263 if(!dw_head_sect) {
2264 dw_head_sect = dw_last_sect = dw_cur_sect;
2265 } else {
2266 dw_last_sect->next = dw_cur_sect;
2267 dw_last_sect = dw_cur_sect;
2271 if(dbg_immcall == true) {
2272 int32_t line_delta = cur_line - dw_cur_sect->line;
2273 int32_t offset_delta = sinfo_param->size - dw_cur_sect->offset;
2274 uint32_t cur_file = dw_cur_file->file;
2275 p_linep = dw_cur_sect->psaa;
2277 if(cur_file != dw_cur_sect->file) {
2278 saa_write8(p_linep, DW_LNS_set_file);
2279 saa_write8(p_linep, cur_file);
2280 dw_cur_sect->file = cur_file;
2283 if(line_delta) {
2284 int special_opcode = (line_delta - DW_LN_BASE) + (DW_LN_RANGE * offset_delta) +
2285 DW_OPCODE_BASE;
2287 if((line_delta >= DW_LN_BASE) && (line_delta < DW_MAX_LN) &&
2288 (special_opcode < DW_MAX_SP_OPCODE)) {
2289 saa_write8(p_linep, special_opcode);
2290 } else {
2291 saa_write8(p_linep, DW_LNS_advance_line);
2292 saa_wleb128s(p_linep, line_delta);
2293 if(offset_delta) {
2294 saa_write8(p_linep, DW_LNS_advance_pc);
2295 saa_wleb128u(p_linep, offset_delta);
2297 saa_write8(p_linep, DW_LNS_copy);
2300 dw_cur_sect->line = cur_line;
2301 dw_cur_sect->offset = sinfo_param->size;
2304 dbg_immcall = false;
2308 static void macho_dbg_cleanup(void)
2310 /* dwarf sectors generation */
2311 macho_dbg_generate();
2314 struct dw_sect_list *p_sect = dw_head_sect;
2315 struct file_list *p_file = dw_head_file;
2316 uint32_t idx = 0;
2318 for(; idx < dw_num_sects; idx++) {
2319 struct dw_sect_list *next = p_sect->next;
2320 nasm_free(p_sect);
2321 p_sect = next;
2324 for(idx = 0; idx < dw_num_files; idx++) {
2325 struct file_list *next = p_file->next;
2326 nasm_free(p_file);
2327 p_file = next;
2332 #ifdef OF_MACHO32
2333 static const struct macho_fmt macho32_fmt = {
2335 MH_MAGIC,
2336 CPU_TYPE_I386,
2337 LC_SEGMENT,
2338 MACHO_HEADER_SIZE,
2339 MACHO_SEGCMD_SIZE,
2340 MACHO_SECTCMD_SIZE,
2341 MACHO_NLIST_SIZE,
2342 RL_MAX_32,
2343 GENERIC_RELOC_VANILLA,
2344 GENERIC_RELOC_VANILLA,
2345 GENERIC_RELOC_TLV,
2346 false /* Allow segment-relative relocations */
2349 static void macho32_init(void)
2351 fmt = macho32_fmt;
2352 macho_init();
2354 macho_gotpcrel_sect = NO_SEG;
2357 static const struct dfmt macho32_df_dwarf = {
2358 "MachO32 (i386) dwarf debug format for Darwin/MacOS",
2359 "dwarf",
2360 macho_dbg_init,
2361 macho_dbg_linenum,
2362 null_debug_deflabel,
2363 null_debug_directive,
2364 null_debug_typevalue,
2365 macho_dbg_output,
2366 macho_dbg_cleanup,
2367 NULL /*pragma list*/
2370 static const struct dfmt * const macho32_df_arr[2] =
2371 { &macho32_df_dwarf, NULL };
2373 const struct ofmt of_macho32 = {
2374 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files",
2375 "macho32",
2376 ".o",
2379 macho32_df_arr,
2380 &macho32_df_dwarf,
2381 macho_stdmac,
2382 macho32_init,
2383 null_reset,
2384 nasm_do_legacy_output,
2385 macho_output,
2386 macho_symdef,
2387 macho_section,
2388 macho_herelabel,
2389 macho_sectalign,
2390 null_segbase,
2391 null_directive,
2392 macho_cleanup,
2393 macho_pragma_list
2395 #endif
2397 #ifdef OF_MACHO64
2398 static const struct macho_fmt macho64_fmt = {
2400 MH_MAGIC_64,
2401 CPU_TYPE_X86_64,
2402 LC_SEGMENT_64,
2403 MACHO_HEADER64_SIZE,
2404 MACHO_SEGCMD64_SIZE,
2405 MACHO_SECTCMD64_SIZE,
2406 MACHO_NLIST64_SIZE,
2407 RL_MAX_64,
2408 X86_64_RELOC_UNSIGNED,
2409 X86_64_RELOC_SIGNED,
2410 X86_64_RELOC_TLV,
2411 true /* Force symbol-relative relocations */
2414 static void macho64_init(void)
2416 fmt = macho64_fmt;
2417 macho_init();
2419 /* add special symbol for ..gotpcrel */
2420 macho_gotpcrel_sect = seg_alloc() + 1;
2421 backend_label("..gotpcrel", macho_gotpcrel_sect, 0L);
2424 static const struct dfmt macho64_df_dwarf = {
2425 "MachO64 (x86-64) dwarf debug format for Darwin/MacOS",
2426 "dwarf",
2427 macho_dbg_init,
2428 macho_dbg_linenum,
2429 null_debug_deflabel,
2430 null_debug_directive,
2431 null_debug_typevalue,
2432 macho_dbg_output,
2433 macho_dbg_cleanup,
2434 NULL /*pragma list*/
2437 static const struct dfmt * const macho64_df_arr[2] =
2438 { &macho64_df_dwarf, NULL };
2440 const struct ofmt of_macho64 = {
2441 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files",
2442 "macho64",
2443 ".o",
2446 macho64_df_arr,
2447 &macho64_df_dwarf,
2448 macho_stdmac,
2449 macho64_init,
2450 null_reset,
2451 nasm_do_legacy_output,
2452 macho_output,
2453 macho_symdef,
2454 macho_section,
2455 macho_herelabel,
2456 macho_sectalign,
2457 null_segbase,
2458 null_directive,
2459 macho_cleanup,
2460 macho_pragma_list,
2462 #endif
2464 #endif
2467 * Local Variables:
2468 * mode:c
2469 * c-basic-offset:4
2470 * End:
2472 * end of file */