macho/reloc: Fix addr size sensitive conditions
[nasm.git] / output / outmacho.c
blob4ec85690e0a6a20a09230470dd9a10f17ba98dd9
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 RAAPTR *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_ptr();
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 if (secto == NO_SEG) {
636 if (type != OUT_RESERVE)
637 nasm_error(ERR_NONFATAL, "attempt to assemble code in "
638 "[ABSOLUTE] space");
639 return;
642 s = get_section_by_index(secto);
643 if (!s) {
644 nasm_error(ERR_WARNING, "attempt to assemble code in"
645 " section %d: defaulting to `.text'", secto);
646 s = get_section_by_name("__TEXT", "__text");
648 /* should never happen */
649 if (!s)
650 nasm_panic(0, "text section not found");
653 /* debug code generation only for sections tagged with
654 * instruction attribute */
655 if (s->flags & S_ATTR_SOME_INSTRUCTIONS)
657 struct section_info sinfo;
658 sinfo.size = s->size;
659 sinfo.secto = secto;
660 dfmt->debug_output(0, &sinfo);
663 is_bss = (s->flags & SECTION_TYPE) == S_ZEROFILL;
665 if (is_bss && type != OUT_RESERVE) {
666 nasm_error(ERR_WARNING, "attempt to initialize memory in "
667 "BSS section: ignored");
668 s->size += realsize(type, size);
669 return;
672 memset(mydata, 0, sizeof(mydata));
674 switch (type) {
675 case OUT_RESERVE:
676 if (!is_bss) {
677 nasm_error(ERR_WARNING, "uninitialized space declared in"
678 " %s,%s section: zeroing", s->segname, s->sectname);
680 sect_write(s, NULL, size);
681 } else
682 s->size += size;
684 break;
686 case OUT_RAWDATA:
687 if (section != NO_SEG)
688 nasm_panic(0, "OUT_RAWDATA with other than NO_SEG");
690 sect_write(s, data, size);
691 break;
693 case OUT_ADDRESS:
695 int asize = abs((int)size);
697 addr = *(int64_t *)data;
698 if (section != NO_SEG) {
699 if (section % 2) {
700 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
701 " section base references");
702 } else if (wrt == NO_SEG) {
703 if (fmt.ptrsize == 8 && asize != 8) {
704 nasm_error(ERR_NONFATAL,
705 "Mach-O 64-bit format does not support"
706 " 32-bit absolute addresses");
707 } else {
708 addr += add_reloc(s, section, addr, RL_ABS, asize);
710 } else if (wrt == macho_tlvp_sect && fmt.ptrsize != 8 &&
711 asize == (int) fmt.ptrsize) {
712 addr += add_reloc(s, section, addr, RL_TLV, asize);
713 } else {
714 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
715 " this use of WRT");
719 p = mydata;
720 WRITEADDR(p, addr, asize);
721 sect_write(s, mydata, asize);
722 break;
725 case OUT_REL1ADR:
726 case OUT_REL2ADR:
728 p = mydata;
729 offset = *(int64_t *)data;
730 addr = offset - size;
732 if (section != NO_SEG && section % 2) {
733 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
734 " section base references");
735 } else if (fmt.ptrsize == 8) {
736 nasm_error(ERR_NONFATAL, "Unsupported non-32-bit"
737 " Macho-O relocation [2]");
738 } else if (wrt != NO_SEG) {
739 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
740 " this use of WRT");
741 wrt = NO_SEG; /* we can at least _try_ to continue */
742 } else {
743 addr += add_reloc(s, section, addr+size, RL_REL,
744 type == OUT_REL1ADR ? 1 : 2);
747 WRITESHORT(p, addr);
748 sect_write(s, mydata, type == OUT_REL1ADR ? 1 : 2);
749 break;
751 case OUT_REL4ADR:
752 case OUT_REL8ADR:
754 p = mydata;
755 offset = *(int64_t *)data;
756 addr = offset - size;
757 reltype = RL_REL;
759 if (section != NO_SEG && section % 2) {
760 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
761 " section base references");
762 } else if (wrt == NO_SEG) {
763 if (fmt.ptrsize == 8 &&
764 (s->flags & S_ATTR_SOME_INSTRUCTIONS)) {
765 uint8_t opcode[2];
767 opcode[0] = opcode[1] = 0;
769 /* HACK: Retrieve instruction opcode */
770 if (likely(s->data->datalen >= 2)) {
771 saa_fread(s->data, s->data->datalen-2, opcode, 2);
772 } else if (s->data->datalen == 1) {
773 saa_fread(s->data, 0, opcode+1, 1);
776 if ((opcode[0] != 0x0f && (opcode[1] & 0xfe) == 0xe8) ||
777 (opcode[0] == 0x0f && (opcode[1] & 0xf0) == 0x80)) {
778 /* Direct call, jmp, or jcc */
779 reltype = RL_BRANCH;
782 } else if (wrt == macho_gotpcrel_sect) {
783 reltype = RL_GOT;
785 if ((s->flags & S_ATTR_SOME_INSTRUCTIONS) &&
786 s->data->datalen >= 3) {
787 uint8_t gotload[3];
789 /* HACK: Retrieve instruction opcode */
790 saa_fread(s->data, s->data->datalen-3, gotload, 3);
791 if ((gotload[0] & 0xf8) == 0x48 &&
792 gotload[1] == 0x8b &&
793 (gotload[2] & 0307) == 0005) {
794 /* movq <reg>,[rel sym wrt ..gotpcrel] */
795 reltype = RL_GOTLOAD;
798 } else if (wrt == macho_tlvp_sect && fmt.ptrsize == 8) {
799 reltype = RL_TLV;
800 } else {
801 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
802 " this use of WRT");
803 /* continue with RL_REL */
806 addr += add_reloc(s, section, offset, reltype,
807 type == OUT_REL4ADR ? 4 : 8);
808 WRITELONG(p, addr);
809 sect_write(s, mydata, type == OUT_REL4ADR ? 4 : 8);
810 break;
812 default:
813 nasm_error(ERR_NONFATAL, "Unrepresentable relocation in Mach-O");
814 break;
818 /* Translation table from traditional Unix section names to Mach-O */
819 static const struct sectmap {
820 const char *nasmsect;
821 const char *segname;
822 const char *sectname;
823 const uint32_t flags;
824 } sectmap[] = {
825 {".text", "__TEXT", "__text",
826 S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS},
827 {".data", "__DATA", "__data", S_REGULAR},
828 {".rodata", "__DATA", "__const", S_REGULAR},
829 {".bss", "__DATA", "__bss", S_ZEROFILL},
830 {".debug_abbrev", "__DWARF", "__debug_abbrev", S_ATTR_DEBUG},
831 {".debug_info", "__DWARF", "__debug_info", S_ATTR_DEBUG},
832 {".debug_line", "__DWARF", "__debug_line", S_ATTR_DEBUG},
833 {".debug_str", "__DWARF", "__debug_str", S_ATTR_DEBUG},
834 {NULL, NULL, NULL, 0}
837 #define NO_TYPE S_NASM_TYPE_MASK
839 /* Section type or attribute directives */
840 static const struct sect_attribs {
841 const char *name;
842 uint32_t flags;
843 } sect_attribs[] = {
844 { "data", S_REGULAR },
845 { "code", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS },
846 { "mixed", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS },
847 { "bss", S_ZEROFILL },
848 { "zerofill", S_ZEROFILL },
849 { "no_dead_strip", NO_TYPE|S_ATTR_NO_DEAD_STRIP },
850 { "live_support", NO_TYPE|S_ATTR_LIVE_SUPPORT },
851 { "strip_static_syms", NO_TYPE|S_ATTR_STRIP_STATIC_SYMS },
852 { "debug", NO_TYPE|S_ATTR_DEBUG },
853 { NULL, 0 }
856 static int32_t macho_section(char *name, int pass, int *bits)
858 char *sectionAttributes;
859 const struct sectmap *sm;
860 struct section *s;
861 const char *section, *segment;
862 uint32_t flags;
863 const struct sect_attribs *sa;
864 char *currentAttribute;
865 char *comma;
867 bool new_seg;
869 (void)pass;
871 /* Default to the appropriate number of bits. */
872 if (!name) {
873 *bits = fmt.ptrsize << 3;
874 name = ".text";
875 sectionAttributes = NULL;
876 } else {
877 sectionAttributes = name;
878 name = nasm_strsep(&sectionAttributes, " \t");
881 section = segment = NULL;
882 flags = 0;
884 comma = strchr(name, ',');
885 if (comma) {
886 int len;
888 *comma = '\0';
889 segment = name;
890 section = comma+1;
892 len = strlen(segment);
893 if (len == 0) {
894 nasm_error(ERR_NONFATAL, "empty segment name\n");
895 } else if (len > 16) {
896 nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment);
899 len = strlen(section);
900 if (len == 0) {
901 nasm_error(ERR_NONFATAL, "empty section name\n");
902 } else if (len > 16) {
903 nasm_error(ERR_NONFATAL, "section name %s too long\n", section);
906 if (!strcmp(section, "__text")) {
907 flags = S_REGULAR | S_ATTR_SOME_INSTRUCTIONS |
908 S_ATTR_PURE_INSTRUCTIONS;
909 } else if (!strcmp(section, "__bss")) {
910 flags = S_ZEROFILL;
911 } else {
912 flags = S_REGULAR;
914 } else {
915 for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
916 /* make lookup into section name translation table */
917 if (!strcmp(name, sm->nasmsect)) {
918 segment = sm->segname;
919 section = sm->sectname;
920 flags = sm->flags;
921 goto found;
924 nasm_error(ERR_NONFATAL, "unknown section name\n");
925 return NO_SEG;
928 found:
929 /* try to find section with that name, or create it */
930 s = find_or_add_section(segment, section);
931 new_seg = is_new_section(s);
933 /* initialize it if it is a brand new section */
934 if (new_seg) {
935 *sectstail = s;
936 sectstail = &s->next;
938 s->data = saa_init(1L);
939 s->fileindex = ++seg_nsects;
940 s->align = -1;
941 s->pad = -1;
942 s->offset = -1;
943 s->by_name = false;
945 s->size = 0;
946 s->nreloc = 0;
947 s->flags = flags;
950 if (comma)
951 *comma = ','; /* Restore comma */
953 s->by_name = s->by_name || comma; /* Was specified by name */
955 flags = NO_TYPE;
957 while (sectionAttributes &&
958 (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
959 if (!*currentAttribute)
960 continue;
962 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
963 char *end;
964 int newAlignment, value;
966 value = strtoul(currentAttribute + 6, (char**)&end, 0);
967 newAlignment = alignlog2_32(value);
969 if (0 != *end) {
970 nasm_error(ERR_NONFATAL,
971 "unknown or missing alignment value \"%s\" "
972 "specified for section \"%s\"",
973 currentAttribute + 6,
974 name);
975 } else if (0 > newAlignment) {
976 nasm_error(ERR_NONFATAL,
977 "alignment of %d (for section \"%s\") is not "
978 "a power of two",
979 value,
980 name);
983 if (s->align < newAlignment)
984 s->align = newAlignment;
985 } else {
986 for (sa = sect_attribs; sa->name; sa++) {
987 if (!nasm_stricmp(sa->name, currentAttribute)) {
988 if ((sa->flags & S_NASM_TYPE_MASK) != NO_TYPE) {
989 flags = (flags & ~S_NASM_TYPE_MASK)
990 | (sa->flags & S_NASM_TYPE_MASK);
992 flags |= sa->flags & ~S_NASM_TYPE_MASK;
993 break;
997 if (!sa->name) {
998 nasm_error(ERR_NONFATAL,
999 "unknown section attribute %s for section %s",
1000 currentAttribute, name);
1005 if ((flags & S_NASM_TYPE_MASK) != NO_TYPE) {
1006 if (!new_seg && ((s->flags ^ flags) & S_NASM_TYPE_MASK)) {
1007 nasm_error(ERR_NONFATAL,
1008 "inconsistent section attributes for section %s\n",
1009 name);
1010 } else {
1011 s->flags = (s->flags & ~S_NASM_TYPE_MASK) | flags;
1013 } else {
1014 s->flags |= flags & ~S_NASM_TYPE_MASK;
1017 return s->subsection;
1020 static int32_t macho_herelabel(const char *name, enum label_type type,
1021 int32_t section, int32_t *subsection,
1022 bool *copyoffset)
1024 struct section *s;
1025 int32_t subsec;
1026 (void)name;
1028 if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS))
1029 return section;
1031 /* No subsection only for local labels */
1032 if (type == LBL_LOCAL)
1033 return section;
1035 s = get_section_by_index(section);
1036 if (!s)
1037 return section;
1039 subsec = *subsection;
1040 if (subsec == NO_SEG) {
1041 /* Allocate a new subsection index */
1042 subsec = *subsection = seg_alloc();
1043 section_by_index = raa_write_ptr(section_by_index, subsec >> 1, s);
1046 s->subsection = subsec;
1047 *copyoffset = true; /* Maintain previous offset */
1048 return subsec;
1051 static void macho_symdef(char *name, int32_t section, int64_t offset,
1052 int is_global, char *special)
1054 struct symbol *sym;
1055 struct section *s;
1056 bool special_used = false;
1058 #if defined(DEBUG) && DEBUG>2
1059 nasm_error(ERR_DEBUG,
1060 " macho_symdef: %s, pass0=%d, passn=%"PRId64", sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
1061 name, pass0, passn, section, offset, is_global, special);
1062 #endif
1064 if (is_global == 3) {
1065 if (special) {
1066 int n = strcspn(special, " \t");
1068 if (!nasm_strnicmp(special, "private_extern", n)) {
1069 for (sym = syms; sym != NULL; sym = sym->next) {
1070 if (!strcmp(name, sym->name)) {
1071 if (sym->type & N_PEXT)
1072 return; /* nothing to be done */
1073 else
1074 break;
1079 nasm_error(ERR_NONFATAL, "The Mach-O format does not "
1080 "(yet) support forward reference fixups.");
1081 return;
1084 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
1086 * This is a NASM special symbol. We never allow it into
1087 * the Macho-O symbol table, even if it's a valid one. If it
1088 * _isn't_ a valid one, we should barf immediately.
1090 if (strcmp(name, "..gotpcrel") && strcmp(name, "..tlvp"))
1091 nasm_error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
1092 return;
1095 sym = *symstail = nasm_zalloc(sizeof(struct symbol));
1096 sym->next = NULL;
1097 symstail = &sym->next;
1099 sym->name = name;
1100 sym->strx = strslen;
1101 sym->type = 0;
1102 sym->desc = 0;
1103 sym->symv[0].key = offset;
1104 sym->symv[1].key = offset;
1105 sym->initial_snum = -1;
1107 /* external and common symbols get N_EXT */
1108 if (is_global != 0) {
1109 sym->type |= N_EXT;
1111 if (is_global == 1) {
1112 /* check special to see if the global symbol shall be marked as private external: N_PEXT */
1113 if (special) {
1114 int n = strcspn(special, " \t");
1116 if (!nasm_strnicmp(special, "private_extern", n))
1117 sym->type |= N_PEXT;
1118 else
1119 nasm_error(ERR_NONFATAL, "unrecognised symbol type `%.*s'", n, special);
1121 special_used = true;
1124 /* track the initially allocated symbol number for use in future fix-ups */
1125 sym->initial_snum = nsyms;
1127 if (section == NO_SEG) {
1128 /* symbols in no section get absolute */
1129 sym->type |= N_ABS;
1130 sym->sect = NO_SECT;
1132 s = &absolute_sect;
1133 } else {
1134 s = get_section_by_index(section);
1136 sym->type |= N_SECT;
1138 /* get the in-file index of the section the symbol was defined in */
1139 sym->sect = s ? s->fileindex : NO_SECT;
1141 if (!s) {
1142 /* remember symbol number of references to external
1143 ** symbols, this works because every external symbol gets
1144 ** its own section number allocated internally by nasm and
1145 ** can so be used as a key */
1146 extsyms = raa_write(extsyms, section, nsyms);
1148 switch (is_global) {
1149 case 1:
1150 case 2:
1151 /* there isn't actually a difference between global
1152 ** and common symbols, both even have their size in
1153 ** sym->symv[0].key */
1154 sym->type = N_EXT;
1155 break;
1157 default:
1158 /* give an error on unfound section if it's not an
1159 ** external or common symbol (assemble_file() does a
1160 ** seg_alloc() on every call for them) */
1161 nasm_panic(0, "in-file index for section %d not found, is_global = %d", section, is_global);
1162 break;
1167 if (s) {
1168 s->syms[0] = rb_insert(s->syms[0], &sym->symv[0]);
1169 if (is_global)
1170 s->syms[1] = rb_insert(s->syms[1], &sym->symv[1]);
1173 ++nsyms;
1175 if (special && !special_used)
1176 nasm_error(ERR_NONFATAL, "no special symbol features supported here");
1179 static void macho_sectalign(int32_t seg, unsigned int value)
1181 struct section *s;
1182 int align;
1184 nasm_assert(!(seg & 1));
1186 s = get_section_by_index(seg);
1188 if (!s || !is_power2(value))
1189 return;
1191 align = alignlog2_32(value);
1192 if (s->align < align)
1193 s->align = align;
1196 static int32_t macho_segbase(int32_t section)
1198 return section;
1201 extern macros_t macho_stdmac[];
1203 /* Comparison function for qsort symbol layout. */
1204 static int layout_compare (const struct symbol **s1,
1205 const struct symbol **s2)
1207 return (strcmp ((*s1)->name, (*s2)->name));
1210 /* The native assembler does a few things in a similar function
1212 * Remove temporary labels
1213 * Sort symbols according to local, external, undefined (by name)
1214 * Order the string table
1216 We do not remove temporary labels right now.
1218 numsyms is the total number of symbols we have. strtabsize is the
1219 number entries in the string table. */
1221 static void macho_layout_symbols (uint32_t *numsyms,
1222 uint32_t *strtabsize)
1224 struct symbol *sym, **symp;
1225 uint32_t i,j;
1227 *numsyms = 0;
1228 *strtabsize = sizeof (char);
1230 symp = &syms;
1232 while ((sym = *symp)) {
1233 /* Undefined symbols are now external. */
1234 if (sym->type == N_UNDF)
1235 sym->type |= N_EXT;
1237 if ((sym->type & N_EXT) == 0) {
1238 sym->snum = *numsyms;
1239 *numsyms = *numsyms + 1;
1240 nlocalsym++;
1242 else {
1243 if ((sym->type & N_TYPE) != N_UNDF) {
1244 nextdefsym++;
1245 } else {
1246 nundefsym++;
1249 /* If we handle debug info we'll want
1250 to check for it here instead of just
1251 adding the symbol to the string table. */
1252 sym->strx = *strtabsize;
1253 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
1254 *strtabsize += strlen(sym->name) + 1;
1256 symp = &(sym->next);
1259 /* Next, sort the symbols. Most of this code is a direct translation from
1260 the Apple cctools symbol layout. We need to keep compatibility with that. */
1261 /* Set the indexes for symbol groups into the symbol table */
1262 ilocalsym = 0;
1263 iextdefsym = nlocalsym;
1264 iundefsym = nlocalsym + nextdefsym;
1266 /* allocate arrays for sorting externals by name */
1267 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
1268 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
1270 i = 0;
1271 j = 0;
1273 symp = &syms;
1275 while ((sym = *symp)) {
1277 if((sym->type & N_EXT) == 0) {
1278 sym->strx = *strtabsize;
1279 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
1280 *strtabsize += strlen(sym->name) + 1;
1282 else {
1283 if ((sym->type & N_TYPE) != N_UNDF) {
1284 extdefsyms[i++] = sym;
1285 } else {
1286 undefsyms[j++] = sym;
1289 symp = &(sym->next);
1292 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
1293 (int (*)(const void *, const void *))layout_compare);
1294 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
1295 (int (*)(const void *, const void *))layout_compare);
1297 for(i = 0; i < nextdefsym; i++) {
1298 extdefsyms[i]->snum = *numsyms;
1299 *numsyms += 1;
1301 for(j = 0; j < nundefsym; j++) {
1302 undefsyms[j]->snum = *numsyms;
1303 *numsyms += 1;
1307 /* Calculate some values we'll need for writing later. */
1309 static void macho_calculate_sizes (void)
1311 struct section *s;
1312 int fi;
1314 /* count sections and calculate in-memory and in-file offsets */
1315 for (s = sects; s != NULL; s = s->next) {
1316 uint64_t newaddr;
1318 /* recalculate segment address based on alignment and vm size */
1319 s->addr = seg_vmsize;
1321 /* we need section alignment to calculate final section address */
1322 if (s->align == -1)
1323 s->align = DEFAULT_SECTION_ALIGNMENT;
1325 newaddr = ALIGN(s->addr, UINT64_C(1) << s->align);
1326 s->addr = newaddr;
1328 seg_vmsize = newaddr + s->size;
1330 /* zerofill sections aren't actually written to the file */
1331 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1333 * LLVM/Xcode as always aligns the section data to 4
1334 * bytes; there is a comment in the LLVM source code that
1335 * perhaps aligning to pointer size would be better.
1337 s->pad = ALIGN(seg_filesize, 4) - seg_filesize;
1338 s->offset = seg_filesize + s->pad;
1339 seg_filesize += s->size + s->pad;
1341 /* filesize and vmsize needs to be aligned */
1342 seg_vmsize += s->pad;
1346 /* calculate size of all headers, load commands and sections to
1347 ** get a pointer to the start of all the raw data */
1348 if (seg_nsects > 0) {
1349 ++head_ncmds;
1350 head_sizeofcmds += fmt.segcmd_size + seg_nsects * fmt.sectcmd_size;
1353 if (nsyms > 0) {
1354 ++head_ncmds;
1355 head_sizeofcmds += MACHO_SYMCMD_SIZE;
1358 if (seg_nsects > MAX_SECT) {
1359 nasm_fatal(0, "MachO output is limited to %d sections\n",
1360 MAX_SECT);
1363 /* Create a table of sections by file index to avoid linear search */
1364 sectstab = nasm_malloc((seg_nsects + 1) * sizeof(*sectstab));
1365 sectstab[NO_SECT] = &absolute_sect;
1366 for (s = sects, fi = 1; s != NULL; s = s->next, fi++)
1367 sectstab[fi] = s;
1370 /* Write out the header information for the file. */
1372 static void macho_write_header (void)
1374 fwriteint32_t(fmt.mh_magic, ofile); /* magic */
1375 fwriteint32_t(fmt.cpu_type, ofile); /* CPU type */
1376 fwriteint32_t(CPU_SUBTYPE_I386_ALL, ofile); /* CPU subtype */
1377 fwriteint32_t(MH_OBJECT, ofile); /* Mach-O file type */
1378 fwriteint32_t(head_ncmds, ofile); /* number of load commands */
1379 fwriteint32_t(head_sizeofcmds, ofile); /* size of load commands */
1380 fwriteint32_t(head_flags, ofile); /* flags, if any */
1381 fwritezero(fmt.header_size - 7*4, ofile); /* reserved fields */
1384 /* Write out the segment load command at offset. */
1386 static uint32_t macho_write_segment (uint64_t offset)
1388 uint64_t rel_base = alignptr(offset + seg_filesize);
1389 uint32_t s_reloff = 0;
1390 struct section *s;
1392 fwriteint32_t(fmt.lc_segment, ofile); /* cmd == LC_SEGMENT_64 */
1394 /* size of load command including section load commands */
1395 fwriteint32_t(fmt.segcmd_size + seg_nsects * fmt.sectcmd_size,
1396 ofile);
1398 /* in an MH_OBJECT file all sections are in one unnamed (name
1399 ** all zeros) segment */
1400 fwritezero(16, ofile);
1401 fwriteptr(0, ofile); /* in-memory offset */
1402 fwriteptr(seg_vmsize, ofile); /* in-memory size */
1403 fwriteptr(offset, ofile); /* in-file offset to data */
1404 fwriteptr(seg_filesize, ofile); /* in-file size */
1405 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* maximum vm protection */
1406 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* initial vm protection */
1407 fwriteint32_t(seg_nsects, ofile); /* number of sections */
1408 fwriteint32_t(0, ofile); /* no flags */
1410 /* emit section headers */
1411 for (s = sects; s != NULL; s = s->next) {
1412 if (s->nreloc) {
1413 nasm_assert((s->flags & SECTION_TYPE) != S_ZEROFILL);
1414 s->flags |= S_ATTR_LOC_RELOC;
1415 if (s->extreloc)
1416 s->flags |= S_ATTR_EXT_RELOC;
1417 } else if (!xstrncmp(s->segname, "__DATA") &&
1418 !xstrncmp(s->sectname, "__const") &&
1419 !s->by_name &&
1420 !get_section_by_name("__TEXT", "__const")) {
1422 * The MachO equivalent to .rodata can be either
1423 * __DATA,__const or __TEXT,__const; the latter only if
1424 * there are no relocations. However, when mixed it is
1425 * better to specify the segments explicitly.
1427 xstrncpy(s->segname, "__TEXT");
1430 nasm_write(s->sectname, sizeof(s->sectname), ofile);
1431 nasm_write(s->segname, sizeof(s->segname), ofile);
1432 fwriteptr(s->addr, ofile);
1433 fwriteptr(s->size, ofile);
1435 /* dummy data for zerofill sections or proper values */
1436 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1437 nasm_assert(s->pad != (uint32_t)-1);
1438 offset += s->pad;
1439 fwriteint32_t(offset, ofile);
1440 offset += s->size;
1441 /* Write out section alignment, as a power of two.
1442 e.g. 32-bit word alignment would be 2 (2^2 = 4). */
1443 fwriteint32_t(s->align, ofile);
1444 /* To be compatible with cctools as we emit
1445 a zero reloff if we have no relocations. */
1446 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile);
1447 fwriteint32_t(s->nreloc, ofile);
1449 s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
1450 } else {
1451 fwriteint32_t(0, ofile);
1452 fwriteint32_t(s->align, ofile);
1453 fwriteint32_t(0, ofile);
1454 fwriteint32_t(0, ofile);
1457 fwriteint32_t(s->flags, ofile); /* flags */
1458 fwriteint32_t(0, ofile); /* reserved */
1459 fwriteptr(0, ofile); /* reserved */
1462 rel_padcnt = rel_base - offset;
1463 offset = rel_base + s_reloff;
1465 return offset;
1468 /* For a given chain of relocs r, write out the entire relocation
1469 chain to the object file. */
1471 static void macho_write_relocs (struct reloc *r)
1473 while (r) {
1474 uint32_t word2;
1476 fwriteint32_t(r->addr, ofile); /* reloc offset */
1478 word2 = r->snum;
1479 word2 |= r->pcrel << 24;
1480 word2 |= r->length << 25;
1481 word2 |= r->ext << 27;
1482 word2 |= r->type << 28;
1483 fwriteint32_t(word2, ofile); /* reloc data */
1484 r = r->next;
1488 /* Write out the section data. */
1489 static void macho_write_section (void)
1491 struct section *s;
1492 struct reloc *r;
1493 uint8_t *p;
1494 int32_t len;
1495 int64_t l;
1496 union offset {
1497 uint64_t val;
1498 uint8_t buf[8];
1499 } blk;
1501 for (s = sects; s != NULL; s = s->next) {
1502 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
1503 continue;
1505 /* Like a.out Mach-O references things in the data or bss
1506 * sections by addresses which are actually relative to the
1507 * start of the _text_ section, in the _file_. See outaout.c
1508 * for more information. */
1509 saa_rewind(s->data);
1510 for (r = s->relocs; r != NULL; r = r->next) {
1511 len = (uint32_t)1 << r->length;
1512 if (len > 4) /* Can this ever be an issue?! */
1513 len = 8;
1514 blk.val = 0;
1515 saa_fread(s->data, r->addr, blk.buf, len);
1517 /* get offset based on relocation type */
1518 #ifdef WORDS_LITTLEENDIAN
1519 l = blk.val;
1520 #else
1521 l = blk.buf[0];
1522 l += ((int64_t)blk.buf[1]) << 8;
1523 l += ((int64_t)blk.buf[2]) << 16;
1524 l += ((int64_t)blk.buf[3]) << 24;
1525 l += ((int64_t)blk.buf[4]) << 32;
1526 l += ((int64_t)blk.buf[5]) << 40;
1527 l += ((int64_t)blk.buf[6]) << 48;
1528 l += ((int64_t)blk.buf[7]) << 56;
1529 #endif
1531 /* If the relocation is internal add to the current section
1532 offset. Otherwise the only value we need is the symbol
1533 offset which we already have. The linker takes care
1534 of the rest of the address. */
1535 if (!r->ext) {
1536 /* generate final address by section address and offset */
1537 nasm_assert(r->snum <= seg_nsects);
1538 l += sectstab[r->snum]->addr;
1539 if (r->pcrel)
1540 l -= s->addr;
1541 } else if (r->pcrel && r->type == GENERIC_RELOC_VANILLA) {
1542 l -= s->addr;
1545 /* write new offset back */
1546 p = blk.buf;
1547 WRITEDLONG(p, l);
1548 saa_fwrite(s->data, r->addr, blk.buf, len);
1551 /* dump the section data to file */
1552 fwritezero(s->pad, ofile);
1553 saa_fpwrite(s->data, ofile);
1556 /* pad last section up to reloc entries on pointer boundary */
1557 fwritezero(rel_padcnt, ofile);
1559 /* emit relocation entries */
1560 for (s = sects; s != NULL; s = s->next)
1561 macho_write_relocs (s->relocs);
1564 /* Write out the symbol table. We should already have sorted this
1565 before now. */
1566 static void macho_write_symtab (void)
1568 struct symbol *sym;
1569 uint64_t i;
1571 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1573 for (sym = syms; sym != NULL; sym = sym->next) {
1574 if ((sym->type & N_EXT) == 0) {
1575 fwriteint32_t(sym->strx, ofile); /* string table entry number */
1576 nasm_write(&sym->type, 1, ofile); /* symbol type */
1577 nasm_write(&sym->sect, 1, ofile); /* section */
1578 fwriteint16_t(sym->desc, ofile); /* description */
1580 /* Fix up the symbol value now that we know the final section
1581 sizes. */
1582 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1583 nasm_assert(sym->sect <= seg_nsects);
1584 sym->symv[0].key += sectstab[sym->sect]->addr;
1587 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1591 for (i = 0; i < nextdefsym; i++) {
1592 sym = extdefsyms[i];
1593 fwriteint32_t(sym->strx, ofile);
1594 nasm_write(&sym->type, 1, ofile); /* symbol type */
1595 nasm_write(&sym->sect, 1, ofile); /* section */
1596 fwriteint16_t(sym->desc, ofile); /* description */
1598 /* Fix up the symbol value now that we know the final section
1599 sizes. */
1600 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1601 nasm_assert(sym->sect <= seg_nsects);
1602 sym->symv[0].key += sectstab[sym->sect]->addr;
1605 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1608 for (i = 0; i < nundefsym; i++) {
1609 sym = undefsyms[i];
1610 fwriteint32_t(sym->strx, ofile);
1611 nasm_write(&sym->type, 1, ofile); /* symbol type */
1612 nasm_write(&sym->sect, 1, ofile); /* section */
1613 fwriteint16_t(sym->desc, ofile); /* description */
1615 /* Fix up the symbol value now that we know the final section
1616 sizes. */
1617 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1618 nasm_assert(sym->sect <= seg_nsects);
1619 sym->symv[0].key += sectstab[sym->sect]->addr;
1622 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1627 /* Fixup the snum in the relocation entries, we should be
1628 doing this only for externally referenced symbols. */
1629 static void macho_fixup_relocs (struct reloc *r)
1631 struct symbol *sym;
1633 while (r != NULL) {
1634 if (r->ext) {
1635 for (sym = syms; sym != NULL; sym = sym->next) {
1636 if (sym->initial_snum == r->snum) {
1637 r->snum = sym->snum;
1638 break;
1642 r = r->next;
1646 /* Write out the object file. */
1648 static void macho_write (void)
1650 uint64_t offset = 0;
1652 /* mach-o object file structure:
1654 ** mach header
1655 ** uint32_t magic
1656 ** int cpu type
1657 ** int cpu subtype
1658 ** uint32_t mach file type
1659 ** uint32_t number of load commands
1660 ** uint32_t size of all load commands
1661 ** (includes section struct size of segment command)
1662 ** uint32_t flags
1664 ** segment command
1665 ** uint32_t command type == LC_SEGMENT[_64]
1666 ** uint32_t size of load command
1667 ** (including section load commands)
1668 ** char[16] segment name
1669 ** pointer in-memory offset
1670 ** pointer in-memory size
1671 ** pointer in-file offset to data area
1672 ** pointer in-file size
1673 ** (in-memory size excluding zerofill sections)
1674 ** int maximum vm protection
1675 ** int initial vm protection
1676 ** uint32_t number of sections
1677 ** uint32_t flags
1679 ** section commands
1680 ** char[16] section name
1681 ** char[16] segment name
1682 ** pointer in-memory offset
1683 ** pointer in-memory size
1684 ** uint32_t in-file offset
1685 ** uint32_t alignment
1686 ** (irrelevant in MH_OBJECT)
1687 ** uint32_t in-file offset of relocation entires
1688 ** uint32_t number of relocations
1689 ** uint32_t flags
1690 ** uint32_t reserved
1691 ** uint32_t reserved
1693 ** symbol table command
1694 ** uint32_t command type == LC_SYMTAB
1695 ** uint32_t size of load command
1696 ** uint32_t symbol table offset
1697 ** uint32_t number of symbol table entries
1698 ** uint32_t string table offset
1699 ** uint32_t string table size
1701 ** raw section data
1703 ** padding to pointer boundary
1705 ** relocation data (struct reloc)
1706 ** int32_t offset
1707 ** uint data (symbolnum, pcrel, length, extern, type)
1709 ** symbol table data (struct nlist)
1710 ** int32_t string table entry number
1711 ** uint8_t type
1712 ** (extern, absolute, defined in section)
1713 ** uint8_t section
1714 ** (0 for global symbols, section number of definition (>= 1, <=
1715 ** 254) for local symbols, size of variable for common symbols
1716 ** [type == extern])
1717 ** int16_t description
1718 ** (for stab debugging format)
1719 ** pointer value (i.e. file offset) of symbol or stab offset
1721 ** string table data
1722 ** list of null-terminated strings
1725 /* Emit the Mach-O header. */
1726 macho_write_header();
1728 offset = fmt.header_size + head_sizeofcmds;
1730 /* emit the segment load command */
1731 if (seg_nsects > 0)
1732 offset = macho_write_segment (offset);
1733 else
1734 nasm_error(ERR_WARNING, "no sections?");
1736 if (nsyms > 0) {
1737 /* write out symbol command */
1738 fwriteint32_t(LC_SYMTAB, ofile); /* cmd == LC_SYMTAB */
1739 fwriteint32_t(MACHO_SYMCMD_SIZE, ofile); /* size of load command */
1740 fwriteint32_t(offset, ofile); /* symbol table offset */
1741 fwriteint32_t(nsyms, ofile); /* number of symbol
1742 ** table entries */
1743 offset += nsyms * fmt.nlist_size;
1744 fwriteint32_t(offset, ofile); /* string table offset */
1745 fwriteint32_t(strslen, ofile); /* string table size */
1748 /* emit section data */
1749 if (seg_nsects > 0)
1750 macho_write_section ();
1752 /* emit symbol table if we have symbols */
1753 if (nsyms > 0)
1754 macho_write_symtab ();
1756 /* we don't need to pad here, we are already aligned */
1758 /* emit string table */
1759 saa_fpwrite(strs, ofile);
1761 /* We do quite a bit here, starting with finalizing all of the data
1762 for the object file, writing, and then freeing all of the data from
1763 the file. */
1765 static void macho_cleanup(void)
1767 struct section *s;
1768 struct reloc *r;
1769 struct symbol *sym;
1771 dfmt->cleanup();
1773 /* Sort all symbols. */
1774 macho_layout_symbols (&nsyms, &strslen);
1776 /* Fixup relocation entries */
1777 for (s = sects; s != NULL; s = s->next) {
1778 macho_fixup_relocs (s->relocs);
1781 /* First calculate and finalize needed values. */
1782 macho_calculate_sizes();
1783 macho_write();
1785 /* free up everything */
1786 while (sects->next) {
1787 s = sects;
1788 sects = sects->next;
1790 saa_free(s->data);
1791 while (s->relocs != NULL) {
1792 r = s->relocs;
1793 s->relocs = s->relocs->next;
1794 nasm_free(r);
1797 nasm_free(s);
1800 saa_free(strs);
1802 raa_free(extsyms);
1804 while (syms) {
1805 sym = syms;
1806 syms = syms->next;
1807 nasm_free (sym);
1810 nasm_free(extdefsyms);
1811 nasm_free(undefsyms);
1812 nasm_free(sectstab);
1813 raa_free_ptr(section_by_index);
1814 hash_free(&section_by_name);
1817 static bool macho_set_section_attribute_by_symbol(const char *label, uint32_t flags)
1819 struct section *s;
1820 int32_t nasm_seg;
1821 int64_t offset;
1823 if (!lookup_label(label, &nasm_seg, &offset)) {
1824 nasm_error(ERR_NONFATAL, "unknown symbol `%s' in no_dead_strip", label);
1825 return false;
1828 s = get_section_by_index(nasm_seg);
1829 if (!s) {
1830 nasm_error(ERR_NONFATAL, "symbol `%s' is external or absolute", label);
1831 return false;
1834 s->flags |= flags;
1835 return true;
1839 * Mark a symbol for no dead stripping
1841 static enum directive_result macho_no_dead_strip(const char *labels)
1843 char *s, *p, *ep;
1844 char ec;
1845 enum directive_result rv = DIRR_ERROR;
1846 bool real = passn > 1;
1848 p = s = nasm_strdup(labels);
1849 while (*p) {
1850 ep = nasm_skip_identifier(p);
1851 if (!ep) {
1852 nasm_error(ERR_NONFATAL, "invalid symbol in NO_DEAD_STRIP");
1853 goto err;
1855 ec = *ep;
1856 if (ec && ec != ',' && !nasm_isspace(ec)) {
1857 nasm_error(ERR_NONFATAL, "cannot parse contents after symbol");
1858 goto err;
1860 *ep = '\0';
1861 if (real) {
1862 if (!macho_set_section_attribute_by_symbol(p, S_ATTR_NO_DEAD_STRIP))
1863 rv = DIRR_ERROR;
1865 *ep = ec;
1866 p = nasm_skip_spaces(ep);
1867 if (*p == ',')
1868 p = nasm_skip_spaces(++p);
1871 rv = DIRR_OK;
1873 err:
1874 nasm_free(s);
1875 return rv;
1879 * Mach-O pragmas
1881 static enum directive_result
1882 macho_pragma(const struct pragma *pragma)
1884 bool real = passn > 1;
1886 switch (pragma->opcode) {
1887 case D_SUBSECTIONS_VIA_SYMBOLS:
1888 if (*pragma->tail)
1889 return DIRR_BADPARAM;
1891 if (real)
1892 head_flags |= MH_SUBSECTIONS_VIA_SYMBOLS;
1894 /* Jmp-match optimization conflicts */
1895 optimizing.flag |= OPTIM_DISABLE_JMP_MATCH;
1897 return DIRR_OK;
1899 case D_NO_DEAD_STRIP:
1900 return macho_no_dead_strip(pragma->tail);
1902 default:
1903 return DIRR_UNKNOWN; /* Not a Mach-O directive */
1907 static const struct pragma_facility macho_pragma_list[] = {
1908 { "macho", macho_pragma },
1909 { NULL, macho_pragma } /* Implements macho32/macho64 namespaces */
1912 static void macho_dbg_generate(void)
1914 uint8_t *p_buf = NULL, *p_buf_base = NULL;
1915 size_t saa_len = 0, high_addr = 0, total_len = 0;
1916 struct section *p_section = NULL;
1917 /* calculated at debug_str and referenced at debug_info */
1918 uint32_t producer_str_offset = 0, module_str_offset = 0, dir_str_offset = 0;
1920 /* debug section defines */
1922 int bits = 0;
1923 macho_section(".debug_abbrev", 0, &bits);
1924 macho_section(".debug_info", 0, &bits);
1925 macho_section(".debug_line", 0, &bits);
1926 macho_section(".debug_str", 0, &bits);
1929 /* dw section walk to find high_addr and total_len */
1931 struct dw_sect_list *p_sect;
1933 list_for_each(p_sect, dw_head_sect) {
1934 uint64_t offset = get_section_by_index(p_sect->section)->size;
1935 struct SAA *p_linep = p_sect->psaa;
1937 saa_write8(p_linep, 2); /* std op 2 */
1938 saa_write8(p_linep, offset - p_sect->offset);
1939 saa_write8(p_linep, DW_LNS_extended_op);
1940 saa_write8(p_linep, 1); /* operand length */
1941 saa_write8(p_linep, DW_LNE_end_sequence);
1943 total_len += p_linep->datalen;
1944 high_addr += offset;
1948 /* debug line */
1950 struct dw_sect_list *p_sect;
1951 size_t linep_off, buf_size;
1952 struct SAA *p_lines = saa_init(1L);
1953 struct dir_list *p_dir;
1954 struct file_list *p_file;
1956 p_section = get_section_by_name("__DWARF", "__debug_line");
1957 nasm_assert(p_section != NULL);
1959 saa_write8(p_lines, 1); /* minimum instruction length */
1960 saa_write8(p_lines, 1); /* initial value of "is_stmt" */
1961 saa_write8(p_lines, DW_LN_BASE); /* line base */
1962 saa_write8(p_lines, DW_LN_RANGE); /* line range */
1963 saa_write8(p_lines, DW_OPCODE_BASE); /* opcode base */
1964 saa_write8(p_lines, 0); /* std opcode 1 length */
1965 saa_write8(p_lines, 1); /* std opcode 2 length */
1966 saa_write8(p_lines, 1); /* std opcode 3 length */
1967 saa_write8(p_lines, 1); /* std opcode 4 length */
1968 saa_write8(p_lines, 1); /* std opcode 5 length */
1969 saa_write8(p_lines, 0); /* std opcode 6 length */
1970 saa_write8(p_lines, 0); /* std opcode 7 length */
1971 saa_write8(p_lines, 0); /* std opcode 8 length */
1972 saa_write8(p_lines, 1); /* std opcode 9 length */
1973 saa_write8(p_lines, 0); /* std opcode 10 length */
1974 saa_write8(p_lines, 0); /* std opcode 11 length */
1975 saa_write8(p_lines, 1); /* std opcode 12 length */
1976 list_for_each(p_dir, dw_head_dir) {
1977 saa_wcstring(p_lines, p_dir->dir_name);
1979 saa_write8(p_lines, 0); /* end of table */
1981 list_for_each(p_file, dw_head_file) {
1982 saa_wcstring(p_lines, p_file->file_name);
1983 saa_write8(p_lines, p_file->dir->dir); /* directory id */
1984 saa_write8(p_lines, 0); /* time */
1985 saa_write8(p_lines, 0); /* size */
1987 saa_write8(p_lines, 0); /* end of table */
1989 linep_off = p_lines->datalen;
1990 /* 10 bytes for initial & prolong length, and dwarf version info */
1991 buf_size = saa_len = linep_off + total_len + 10;
1992 p_buf_base = p_buf = nasm_malloc(buf_size);
1994 WRITELONG(p_buf, saa_len - 4); /* initial length; size excluding itself */
1995 WRITESHORT(p_buf, 2); /* dwarf version */
1996 WRITELONG(p_buf, linep_off); /* prolong length */
1998 saa_rnbytes(p_lines, p_buf, linep_off);
1999 p_buf += linep_off;
2000 saa_free(p_lines);
2002 list_for_each(p_sect, dw_head_sect) {
2003 struct SAA *p_linep = p_sect->psaa;
2005 saa_len = p_linep->datalen;
2006 saa_rnbytes(p_linep, p_buf, saa_len);
2007 p_buf += saa_len;
2009 saa_free(p_linep);
2012 macho_output(p_section->index, p_buf_base, OUT_RAWDATA, buf_size, NO_SEG, 0);
2014 nasm_free(p_buf_base);
2017 /* string section */
2019 struct SAA *p_str = saa_init(1L);
2020 char *cur_path = nasm_realpath(module_name);
2021 char *cur_file = nasm_basename(cur_path);
2022 char *cur_dir = nasm_dirname(cur_path);
2024 p_section = get_section_by_name("__DWARF", "__debug_str");
2025 nasm_assert(p_section != NULL);
2027 producer_str_offset = 0;
2028 module_str_offset = dir_str_offset = saa_wcstring(p_str, nasm_signature);
2029 dir_str_offset += saa_wcstring(p_str, cur_file);
2030 saa_wcstring(p_str, cur_dir);
2032 saa_len = p_str->datalen;
2033 p_buf = nasm_malloc(saa_len);
2034 saa_rnbytes(p_str, p_buf, saa_len);
2035 macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0);
2037 nasm_free(cur_path);
2038 nasm_free(cur_file);
2039 nasm_free(cur_dir);
2040 saa_free(p_str);
2041 nasm_free(p_buf);
2044 /* debug info */
2046 struct SAA *p_info = saa_init(1L);
2048 p_section = get_section_by_name("__DWARF", "__debug_info");
2049 nasm_assert(p_section != NULL);
2051 /* size will be overwritten once determined, so skip in p_info layout */
2052 saa_write16(p_info, 2); /* dwarf version */
2053 saa_write32(p_info, 0); /* offset info abbrev */
2054 saa_write8(p_info, (ofmt == &of_macho64) ? 8 : 4); /* pointer size */
2056 saa_write8(p_info, 1); /* abbrev entry number */
2058 saa_write32(p_info, producer_str_offset); /* offset from string table for DW_AT_producer */
2059 saa_write16(p_info, DW_LANG_Mips_Assembler); /* DW_AT_language */
2060 saa_write32(p_info, module_str_offset); /* offset from string table for DW_AT_name */
2061 saa_write32(p_info, dir_str_offset); /* offset from string table for DW_AT_comp_dir */
2062 saa_write32(p_info, 0); /* DW_AT_stmt_list */
2064 if (ofmt == &of_macho64) {
2065 saa_write64(p_info, 0); /* DW_AT_low_pc */
2066 saa_write64(p_info, high_addr); /* DW_AT_high_pc */
2067 } else {
2068 saa_write32(p_info, 0); /* DW_AT_low_pc */
2069 saa_write32(p_info, high_addr); /* DW_AT_high_pc */
2072 saa_write8(p_info, 2); /* abbrev entry number */
2074 if (ofmt == &of_macho64) {
2075 saa_write64(p_info, 0); /* DW_AT_low_pc */
2076 saa_write64(p_info, 0); /* DW_AT_frame_base */
2077 } else {
2078 saa_write32(p_info, 0); /* DW_AT_low_pc */
2079 saa_write32(p_info, 0); /* DW_AT_frame_base */
2081 saa_write8(p_info, DW_END_default);
2083 saa_len = p_info->datalen;
2084 p_buf_base = p_buf = nasm_malloc(saa_len + 4); /* 4B for size info */
2086 WRITELONG(p_buf, saa_len);
2087 saa_rnbytes(p_info, p_buf, saa_len);
2088 macho_output(p_section->index, p_buf_base, OUT_RAWDATA, saa_len + 4, NO_SEG, 0);
2090 saa_free(p_info);
2091 nasm_free(p_buf_base);
2094 /* abbrev section */
2096 struct SAA *p_abbrev = saa_init(1L);
2098 p_section = get_section_by_name("__DWARF", "__debug_abbrev");
2099 nasm_assert(p_section != NULL);
2101 saa_write8(p_abbrev, 1); /* entry number */
2103 saa_write8(p_abbrev, DW_TAG_compile_unit);
2104 saa_write8(p_abbrev, DW_CHILDREN_yes);
2106 saa_write8(p_abbrev, DW_AT_producer);
2107 saa_write8(p_abbrev, DW_FORM_strp);
2109 saa_write8(p_abbrev, DW_AT_language);
2110 saa_write8(p_abbrev, DW_FORM_data2);
2112 saa_write8(p_abbrev, DW_AT_name);
2113 saa_write8(p_abbrev, DW_FORM_strp);
2115 saa_write8(p_abbrev, DW_AT_comp_dir);
2116 saa_write8(p_abbrev, DW_FORM_strp);
2118 saa_write8(p_abbrev, DW_AT_stmt_list);
2119 saa_write8(p_abbrev, DW_FORM_data4);
2121 saa_write8(p_abbrev, DW_AT_low_pc);
2122 saa_write8(p_abbrev, DW_FORM_addr);
2124 saa_write8(p_abbrev, DW_AT_high_pc);
2125 saa_write8(p_abbrev, DW_FORM_addr);
2127 saa_write16(p_abbrev, DW_END_default);
2129 saa_write8(p_abbrev, 2); /* entry number */
2131 saa_write8(p_abbrev, DW_TAG_subprogram);
2132 saa_write8(p_abbrev, DW_CHILDREN_no);
2134 saa_write8(p_abbrev, DW_AT_low_pc);
2135 saa_write8(p_abbrev, DW_FORM_addr);
2137 saa_write8(p_abbrev, DW_AT_frame_base);
2138 saa_write8(p_abbrev, DW_FORM_addr);
2140 saa_write16(p_abbrev, DW_END_default);
2142 saa_write8(p_abbrev, 0); /* Terminal zero entry */
2144 saa_len = p_abbrev->datalen;
2146 p_buf = nasm_malloc(saa_len);
2148 saa_rnbytes(p_abbrev, p_buf, saa_len);
2149 macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0);
2151 saa_free(p_abbrev);
2152 nasm_free(p_buf);
2156 static void new_file_list (const char *file_name, const char *dir_name)
2158 struct dir_list *dir_list;
2159 bool need_new_dir_list = true;
2161 nasm_new(dw_cur_file);
2162 dw_cur_file->file = ++dw_num_files;
2163 dw_cur_file->file_name = file_name;
2164 if(!dw_head_file) {
2165 dw_head_file = dw_cur_file;
2166 } else {
2167 *dw_last_file_next = dw_cur_file;
2169 dw_last_file_next = &(dw_cur_file->next);
2171 if(dw_head_dir) {
2172 list_for_each(dir_list, dw_head_dir) {
2173 if(!(strcmp(dir_name, dir_list->dir_name))) {
2174 dw_cur_file->dir = dir_list;
2175 need_new_dir_list = false;
2176 break;
2181 if(need_new_dir_list)
2183 nasm_new(dir_list);
2184 dir_list->dir = dw_num_dirs++;
2185 dir_list->dir_name = dir_name;
2186 if(!dw_head_dir) {
2187 dw_head_dir = dir_list;
2188 } else {
2189 *dw_last_dir_next = dir_list;
2191 dw_last_dir_next = &(dir_list->next);
2192 dw_cur_file->dir = dir_list;
2196 static void macho_dbg_init(void)
2200 static void macho_dbg_linenum(const char *file_name, int32_t line_num, int32_t segto)
2202 bool need_new_list = true;
2203 const char *cur_file = nasm_basename(file_name);
2204 const char *cur_dir = nasm_dirname(file_name);
2205 (void)segto;
2207 if(!dw_cur_file || strcmp(cur_file, dw_cur_file->file_name) ||
2208 strcmp(cur_dir, dw_cur_file->dir->dir_name)) {
2209 if(dw_head_file) {
2210 struct file_list *match;
2212 list_for_each(match, dw_head_file) {
2213 if(!(strcmp(cur_file, match->file_name)) &&
2214 !(strcmp(cur_dir, match->dir->dir_name))) {
2215 dw_cur_file = match;
2216 dw_cur_file->dir = match->dir;
2217 need_new_list = false;
2218 break;
2223 if(need_new_list) {
2224 new_file_list(cur_file, cur_dir);
2228 dbg_immcall = true;
2229 cur_line = line_num;
2232 static void macho_dbg_output(int type, void *param)
2234 struct section_info *sinfo_param = (struct section_info *)param;
2235 int32_t secto = sinfo_param->secto;
2236 bool need_new_sect = false;
2237 struct SAA *p_linep = NULL;
2238 (void)type;
2240 if(!(dw_cur_sect && (dw_cur_sect->section == secto))) {
2241 need_new_sect = true;
2242 if(dw_head_sect) {
2243 struct dw_sect_list *match = dw_head_sect;
2244 uint32_t idx = 0;
2246 for(; idx < dw_num_sects; idx++) {
2247 if(match->section == secto) {
2248 dw_cur_sect = match;
2249 need_new_sect = false;
2250 break;
2252 match = match->next;
2257 if(need_new_sect) {
2258 nasm_new(dw_cur_sect);
2259 dw_num_sects ++;
2260 p_linep = dw_cur_sect->psaa = saa_init(1L);
2261 dw_cur_sect->line = dw_cur_sect->file = 1;
2262 dw_cur_sect->offset = 0;
2263 dw_cur_sect->next = NULL;
2264 dw_cur_sect->section = secto;
2266 saa_write8(p_linep, DW_LNS_extended_op);
2267 saa_write8(p_linep, (ofmt == &of_macho64) ? 9 : 5);
2268 saa_write8(p_linep, DW_LNE_set_address);
2269 if (ofmt == &of_macho64) {
2270 saa_write64(p_linep, 0);
2271 } else {
2272 saa_write32(p_linep, 0);
2275 if(!dw_head_sect) {
2276 dw_head_sect = dw_last_sect = dw_cur_sect;
2277 } else {
2278 dw_last_sect->next = dw_cur_sect;
2279 dw_last_sect = dw_cur_sect;
2283 if(dbg_immcall == true) {
2284 int32_t line_delta = cur_line - dw_cur_sect->line;
2285 int32_t offset_delta = sinfo_param->size - dw_cur_sect->offset;
2286 uint32_t cur_file = dw_cur_file->file;
2287 p_linep = dw_cur_sect->psaa;
2289 if(cur_file != dw_cur_sect->file) {
2290 saa_write8(p_linep, DW_LNS_set_file);
2291 saa_write8(p_linep, cur_file);
2292 dw_cur_sect->file = cur_file;
2295 if(line_delta) {
2296 int special_opcode = (line_delta - DW_LN_BASE) + (DW_LN_RANGE * offset_delta) +
2297 DW_OPCODE_BASE;
2299 if((line_delta >= DW_LN_BASE) && (line_delta < DW_MAX_LN) &&
2300 (special_opcode < DW_MAX_SP_OPCODE)) {
2301 saa_write8(p_linep, special_opcode);
2302 } else {
2303 saa_write8(p_linep, DW_LNS_advance_line);
2304 saa_wleb128s(p_linep, line_delta);
2305 if(offset_delta) {
2306 saa_write8(p_linep, DW_LNS_advance_pc);
2307 saa_wleb128u(p_linep, offset_delta);
2309 saa_write8(p_linep, DW_LNS_copy);
2312 dw_cur_sect->line = cur_line;
2313 dw_cur_sect->offset = sinfo_param->size;
2316 dbg_immcall = false;
2320 static void macho_dbg_cleanup(void)
2322 /* dwarf sectors generation */
2323 macho_dbg_generate();
2326 struct dw_sect_list *p_sect = dw_head_sect;
2327 struct file_list *p_file = dw_head_file;
2328 uint32_t idx = 0;
2330 for(; idx < dw_num_sects; idx++) {
2331 struct dw_sect_list *next = p_sect->next;
2332 nasm_free(p_sect);
2333 p_sect = next;
2336 for(idx = 0; idx < dw_num_files; idx++) {
2337 struct file_list *next = p_file->next;
2338 nasm_free(p_file);
2339 p_file = next;
2344 #ifdef OF_MACHO32
2345 static const struct macho_fmt macho32_fmt = {
2347 MH_MAGIC,
2348 CPU_TYPE_I386,
2349 LC_SEGMENT,
2350 MACHO_HEADER_SIZE,
2351 MACHO_SEGCMD_SIZE,
2352 MACHO_SECTCMD_SIZE,
2353 MACHO_NLIST_SIZE,
2354 RL_MAX_32,
2355 GENERIC_RELOC_VANILLA,
2356 GENERIC_RELOC_VANILLA,
2357 GENERIC_RELOC_TLV,
2358 false /* Allow segment-relative relocations */
2361 static void macho32_init(void)
2363 fmt = macho32_fmt;
2364 macho_init();
2366 macho_gotpcrel_sect = NO_SEG;
2369 static const struct dfmt macho32_df_dwarf = {
2370 "MachO32 (i386) dwarf debug format for Darwin/MacOS",
2371 "dwarf",
2372 macho_dbg_init,
2373 macho_dbg_linenum,
2374 null_debug_deflabel,
2375 null_debug_directive,
2376 null_debug_typevalue,
2377 macho_dbg_output,
2378 macho_dbg_cleanup,
2379 NULL /*pragma list*/
2382 static const struct dfmt * const macho32_df_arr[2] =
2383 { &macho32_df_dwarf, NULL };
2385 const struct ofmt of_macho32 = {
2386 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files",
2387 "macho32",
2388 ".o",
2391 macho32_df_arr,
2392 &macho32_df_dwarf,
2393 macho_stdmac,
2394 macho32_init,
2395 null_reset,
2396 nasm_do_legacy_output,
2397 macho_output,
2398 macho_symdef,
2399 macho_section,
2400 macho_herelabel,
2401 macho_sectalign,
2402 macho_segbase,
2403 null_directive,
2404 macho_cleanup,
2405 macho_pragma_list
2407 #endif
2409 #ifdef OF_MACHO64
2410 static const struct macho_fmt macho64_fmt = {
2412 MH_MAGIC_64,
2413 CPU_TYPE_X86_64,
2414 LC_SEGMENT_64,
2415 MACHO_HEADER64_SIZE,
2416 MACHO_SEGCMD64_SIZE,
2417 MACHO_SECTCMD64_SIZE,
2418 MACHO_NLIST64_SIZE,
2419 RL_MAX_64,
2420 X86_64_RELOC_UNSIGNED,
2421 X86_64_RELOC_SIGNED,
2422 X86_64_RELOC_TLV,
2423 true /* Force symbol-relative relocations */
2426 static void macho64_init(void)
2428 fmt = macho64_fmt;
2429 macho_init();
2431 /* add special symbol for ..gotpcrel */
2432 macho_gotpcrel_sect = seg_alloc() + 1;
2433 backend_label("..gotpcrel", macho_gotpcrel_sect, 0L);
2436 static const struct dfmt macho64_df_dwarf = {
2437 "MachO64 (x86-64) dwarf debug format for Darwin/MacOS",
2438 "dwarf",
2439 macho_dbg_init,
2440 macho_dbg_linenum,
2441 null_debug_deflabel,
2442 null_debug_directive,
2443 null_debug_typevalue,
2444 macho_dbg_output,
2445 macho_dbg_cleanup,
2446 NULL /*pragma list*/
2449 static const struct dfmt * const macho64_df_arr[2] =
2450 { &macho64_df_dwarf, NULL };
2452 const struct ofmt of_macho64 = {
2453 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files",
2454 "macho64",
2455 ".o",
2458 macho64_df_arr,
2459 &macho64_df_dwarf,
2460 macho_stdmac,
2461 macho64_init,
2462 null_reset,
2463 nasm_do_legacy_output,
2464 macho_output,
2465 macho_symdef,
2466 macho_section,
2467 macho_herelabel,
2468 macho_sectalign,
2469 macho_segbase,
2470 null_directive,
2471 macho_cleanup,
2472 macho_pragma_list,
2474 #endif
2476 #endif
2479 * Local Variables:
2480 * mode:c
2481 * c-basic-offset:4
2482 * End:
2484 * end of file */