eval: Use nasm_error helpers
[nasm.git] / output / outmacho.c
blob14aec076e2159be1d7c3e0a23e1b666c45876992
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"
59 #include "macho.h"
61 #if defined(OF_MACHO) || defined(OF_MACHO64)
63 /* Mach-O in-file header structure sizes */
64 #define MACHO_HEADER_SIZE 28
65 #define MACHO_SEGCMD_SIZE 56
66 #define MACHO_SECTCMD_SIZE 68
67 #define MACHO_SYMCMD_SIZE 24
68 #define MACHO_NLIST_SIZE 12
69 #define MACHO_RELINFO_SIZE 8
71 #define MACHO_HEADER64_SIZE 32
72 #define MACHO_SEGCMD64_SIZE 72
73 #define MACHO_SECTCMD64_SIZE 80
74 #define MACHO_NLIST64_SIZE 16
76 /* Mach-O relocations numbers */
78 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
79 #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
81 /* Our internal relocation types */
82 enum reltype {
83 RL_ABS, /* Absolute relocation */
84 RL_REL, /* Relative relocation */
85 RL_TLV, /* Thread local */
86 RL_BRANCH, /* Relative direct branch */
87 RL_SUB, /* X86_64_RELOC_SUBTRACT */
88 RL_GOT, /* X86_64_RELOC_GOT */
89 RL_GOTLOAD /* X86_64_RELOC_GOT_LOAD */
91 #define RL_MAX_32 RL_TLV
92 #define RL_MAX_64 RL_GOTLOAD
94 struct macho_fmt {
95 uint32_t ptrsize; /* Pointer size in bytes */
96 uint32_t mh_magic; /* Which magic number to use */
97 uint32_t cpu_type; /* Which CPU type */
98 uint32_t lc_segment; /* Which segment load command */
99 uint32_t header_size; /* Header size */
100 uint32_t segcmd_size; /* Segment command size */
101 uint32_t sectcmd_size; /* Section command size */
102 uint32_t nlist_size; /* Nlist (symbol) size */
103 enum reltype maxreltype; /* Maximum entry in enum reltype permitted */
104 uint32_t reloc_abs; /* Absolute relocation type */
105 uint32_t reloc_rel; /* Relative relocation type */
106 uint32_t reloc_tlv; /* Thread local relocation type */
107 bool forcesym; /* Always use "external" (symbol-relative) relocations */
110 static struct macho_fmt fmt;
112 static void fwriteptr(uint64_t data, FILE * fp)
114 fwriteaddr(data, fmt.ptrsize, fp);
117 struct section {
118 /* nasm internal data */
119 struct section *next;
120 struct SAA *data;
121 int32_t index; /* Main section index */
122 int32_t subsection; /* Current subsection index */
123 int32_t fileindex;
124 struct reloc *relocs;
125 struct rbtree *syms[2]; /* All/global symbols symbols in section */
126 int align;
127 bool by_name; /* This section was specified by full MachO name */
128 char namestr[34]; /* segment,section as a C string */
130 /* data that goes into the file */
131 char sectname[16]; /* what this section is called */
132 char segname[16]; /* segment this section will be in */
133 uint64_t addr; /* in-memory address (subject to alignment) */
134 uint64_t size; /* in-memory and -file size */
135 uint64_t offset; /* in-file offset */
136 uint32_t pad; /* padding bytes before section */
137 uint32_t nreloc; /* relocation entry count */
138 uint32_t flags; /* type and attributes (masked) */
139 uint32_t extreloc; /* external relocations */
142 #define S_NASM_TYPE_MASK 0x800004ff /* we consider these bits "section type" */
144 /* fake section for absolute symbols, *not* part of the section linked list */
145 static struct section absolute_sect;
147 struct reloc {
148 /* nasm internal data */
149 struct reloc *next;
151 /* data that goes into the file */
152 int32_t addr; /* op's offset in section */
153 uint32_t snum:24, /* contains symbol index if
154 ** ext otherwise in-file
155 ** section number */
156 pcrel:1, /* relative relocation */
157 length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */
158 ext:1, /* external symbol referenced */
159 type:4; /* reloc type */
162 struct symbol {
163 /* nasm internal data */
164 struct rbtree symv[2]; /* All/global symbol rbtrees; "key" contains the
165 symbol offset. */
166 struct symbol *next; /* next symbol in the list */
167 char *name; /* name of this symbol */
168 int32_t initial_snum; /* symbol number used above in reloc */
169 int32_t snum; /* true snum for reloc */
171 /* data that goes into the file */
172 uint32_t strx; /* string table index */
173 uint8_t type; /* symbol type */
174 uint8_t sect; /* NO_SECT or section number */
175 uint16_t desc; /* for stab debugging, 0 for us */
178 #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
180 static struct section *sects, **sectstail, **sectstab;
181 static struct symbol *syms, **symstail;
182 static uint32_t nsyms;
184 /* These variables are set by macho_layout_symbols() to organize
185 the symbol table and string table in order the dynamic linker
186 expects. They are then used in macho_write() to put out the
187 symbols and strings in that order.
189 The order of the symbol table is:
190 local symbols
191 defined external symbols (sorted by name)
192 undefined external symbols (sorted by name)
194 The order of the string table is:
195 strings for external symbols
196 strings for local symbols
198 static uint32_t ilocalsym = 0;
199 static uint32_t iextdefsym = 0;
200 static uint32_t iundefsym = 0;
201 static uint32_t nlocalsym;
202 static uint32_t nextdefsym;
203 static uint32_t nundefsym;
204 static struct symbol **extdefsyms = NULL;
205 static struct symbol **undefsyms = NULL;
207 static struct RAA *extsyms;
208 static struct SAA *strs;
209 static uint32_t strslen;
211 /* Global file information. This should be cleaned up into either
212 a structure or as function arguments. */
213 static uint32_t head_ncmds = 0;
214 static uint32_t head_sizeofcmds = 0;
215 static uint32_t head_flags = 0;
216 static uint64_t seg_filesize = 0;
217 static uint64_t seg_vmsize = 0;
218 static uint32_t seg_nsects = 0;
219 static uint64_t rel_padcnt = 0;
222 * Functions for handling fixed-length zero-padded string
223 * fields, that may or may not be null-terminated.
226 /* Copy a string into a zero-padded fixed-length field */
227 #define xstrncpy(xdst, xsrc) strncpy(xdst, xsrc, sizeof(xdst))
229 /* Compare a fixed-length field with a string */
230 #define xstrncmp(xdst, xsrc) strncmp(xdst, xsrc, sizeof(xdst))
232 #define alignint32_t(x) \
233 ALIGN(x, sizeof(int32_t)) /* align x to int32_t boundary */
235 #define alignint64_t(x) \
236 ALIGN(x, sizeof(int64_t)) /* align x to int64_t boundary */
238 #define alignptr(x) \
239 ALIGN(x, fmt.ptrsize) /* align x to output format width */
241 static struct hash_table section_by_name;
242 static struct RAA *section_by_index;
244 static struct section * never_null
245 find_or_add_section(const char *segname, const char *sectname)
247 struct hash_insert hi;
248 void **sp;
249 struct section *s;
250 char sect[34];
252 snprintf(sect, sizeof sect, "%-16s,%-16s", segname, sectname);
254 sp = hash_find(&section_by_name, sect, &hi);
255 if (sp)
256 return (struct section *)(*sp);
258 s = nasm_zalloc(sizeof *s);
259 xstrncpy(s->segname, segname);
260 xstrncpy(s->sectname, sectname);
261 xstrncpy(s->namestr, sect);
262 hash_add(&hi, s->namestr, s);
264 s->index = s->subsection = seg_alloc();
265 section_by_index = raa_write_ptr(section_by_index, s->index >> 1, s);
267 return s;
270 static inline bool is_new_section(const struct section *s)
272 return !s->data;
275 static struct section *get_section_by_name(const char *segname,
276 const char *sectname)
278 char sect[34];
279 void **sp;
281 snprintf(sect, sizeof sect, "%-16s,%-16s", segname, sectname);
283 sp = hash_find(&section_by_name, sect, NULL);
284 return sp ? (struct section *)(*sp) : NULL;
287 static struct section *get_section_by_index(int32_t index)
289 if (index < 0 || index >= SEG_ABS || (index & 1))
290 return NULL;
292 return raa_read_ptr(section_by_index, index >> 1);
295 struct dir_list {
296 struct dir_list *next;
297 struct dir_list *last;
298 const char *dir_name;
299 uint32_t dir;
302 struct file_list {
303 struct file_list *next;
304 struct file_list *last;
305 const char *file_name;
306 uint32_t file;
307 struct dir_list *dir;
310 struct dw_sect_list {
311 struct SAA *psaa;
312 int32_t section;
313 uint32_t line;
314 uint64_t offset;
315 uint32_t file;
316 struct dw_sect_list *next;
317 struct dw_sect_list *last;
320 struct section_info {
321 uint64_t size;
322 int32_t secto;
325 #define DW_LN_BASE (-5)
326 #define DW_LN_RANGE 14
327 #define DW_OPCODE_BASE 13
328 #define DW_MAX_LN (DW_LN_BASE + DW_LN_RANGE)
329 #define DW_MAX_SP_OPCODE 256
331 static struct file_list *dw_head_file = 0, *dw_cur_file = 0, **dw_last_file_next = NULL;
332 static struct dir_list *dw_head_dir = 0, **dw_last_dir_next = NULL;
333 static struct dw_sect_list *dw_head_sect = 0, *dw_cur_sect = 0, *dw_last_sect = 0;
334 static uint32_t cur_line = 0, dw_num_files = 0, dw_num_dirs = 0, dw_num_sects = 0;
335 static bool dbg_immcall = false;
336 static const char *module_name = NULL;
339 * Special section numbers which are used to define Mach-O special
340 * symbols, which can be used with WRT to provide PIC relocation
341 * types.
343 static int32_t macho_tlvp_sect;
344 static int32_t macho_gotpcrel_sect;
346 static void macho_init(void)
348 module_name = inname;
349 sects = NULL;
350 sectstail = &sects;
352 /* Fake section for absolute symbols */
353 absolute_sect.index = NO_SEG;
355 syms = NULL;
356 symstail = &syms;
357 nsyms = 0;
358 nlocalsym = 0;
359 nextdefsym = 0;
360 nundefsym = 0;
362 extsyms = raa_init();
363 strs = saa_init(1L);
365 section_by_index = raa_init();
366 hash_init(&section_by_name, HASH_MEDIUM);
368 /* string table starts with a zero byte so index 0 is an empty string */
369 saa_wbytes(strs, zero_buffer, 1);
370 strslen = 1;
372 /* add special symbol for TLVP */
373 macho_tlvp_sect = seg_alloc() + 1;
374 backend_label("..tlvp", macho_tlvp_sect, 0L);
377 static void sect_write(struct section *sect,
378 const uint8_t *data, uint32_t len)
380 saa_wbytes(sect->data, data, len);
381 sect->size += len;
385 * Find a suitable global symbol for a ..gotpcrel or ..tlvp reference
387 static struct symbol *macho_find_sym(struct section *s, uint64_t offset,
388 bool global, bool exact)
390 struct rbtree *srb;
392 srb = rb_search(s->syms[global], offset);
394 if (!srb || (exact && srb->key != offset)) {
395 nasm_error(ERR_NONFATAL, "unable to find a suitable%s%s symbol"
396 " for this reference",
397 global ? " global" : "",
398 s == &absolute_sect ? " absolute " : "");
399 return NULL;
402 return container_of(srb - global, struct symbol, symv);
405 static int64_t add_reloc(struct section *sect, int32_t section,
406 int64_t offset,
407 enum reltype reltype, int bytes)
409 struct reloc *r;
410 struct section *s;
411 int32_t fi;
412 int64_t adjust;
414 /* Double check this is a valid relocation type for this platform */
415 nasm_assert(reltype <= fmt.maxreltype);
417 /* the current end of the section will be the symbol's address for
418 ** now, might have to be fixed by macho_fixup_relocs() later on. make
419 ** sure we don't make the symbol scattered by setting the highest
420 ** bit by accident */
421 r = nasm_malloc(sizeof(struct reloc));
422 r->addr = sect->size & ~R_SCATTERED;
423 r->ext = 1;
424 adjust = 0;
426 /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
427 r->length = ilog2_32(bytes);
429 /* set default relocation values */
430 r->type = fmt.reloc_abs;
431 r->pcrel = 0;
432 r->snum = R_ABS;
434 s = get_section_by_index(section);
435 fi = s ? s->fileindex : NO_SECT;
437 /* absolute relocation */
438 switch (reltype) {
439 case RL_ABS:
440 if (section == NO_SEG) {
441 /* absolute (can this even happen?) */
442 r->ext = 0;
443 } else if (fi == NO_SECT) {
444 /* external */
445 r->snum = raa_read(extsyms, section);
446 } else {
447 /* local */
448 r->ext = 0;
449 r->snum = fi;
451 break;
453 case RL_REL:
454 case RL_BRANCH:
455 r->type = fmt.reloc_rel;
456 r->pcrel = 1;
457 if (section == NO_SEG) {
458 /* may optionally be converted below by fmt.forcesym */
459 r->ext = 0;
460 } else if (fi == NO_SECT) {
461 /* external */
462 sect->extreloc = 1;
463 r->snum = raa_read(extsyms, section);
464 if (reltype == RL_BRANCH)
465 r->type = X86_64_RELOC_BRANCH;
466 } else {
467 /* local */
468 r->ext = 0;
469 r->snum = fi;
470 if (reltype == RL_BRANCH)
471 r->type = X86_64_RELOC_BRANCH;
473 break;
475 case RL_SUB: /* obsolete */
476 nasm_error(ERR_WARNING, "relcation with subtraction"
477 "becomes to be obsolete");
478 r->ext = 0;
479 r->type = X86_64_RELOC_SUBTRACTOR;
480 break;
482 case RL_GOT:
483 r->type = X86_64_RELOC_GOT;
484 goto needsym;
486 case RL_GOTLOAD:
487 r->type = X86_64_RELOC_GOT_LOAD;
488 goto needsym;
490 case RL_TLV:
491 r->type = fmt.reloc_tlv;
492 goto needsym;
494 needsym:
495 r->pcrel = (fmt.ptrsize == 8 ? 1 : 0);
496 if (section == NO_SEG) {
497 nasm_error(ERR_NONFATAL, "Unsupported use of use of WRT");
498 goto bail;
499 } else if (fi == NO_SECT) {
500 /* external */
501 r->snum = raa_read(extsyms, section);
502 } else {
503 /* internal - GOTPCREL doesn't need to be in global */
504 struct symbol *sym = macho_find_sym(s, offset,
505 false, /* reltype != RL_TLV */
506 true);
507 if (!sym) {
508 nasm_error(ERR_NONFATAL, "Symbol for WRT not found");
509 goto bail;
512 adjust -= sym->symv[0].key;
513 r->snum = sym->initial_snum;
515 break;
519 * For 64-bit Mach-O, force a symbol reference if at all possible
520 * Allow for r->snum == R_ABS by searching absolute_sect
522 if (!r->ext && fmt.forcesym) {
523 struct symbol *sym = macho_find_sym(s ? s : &absolute_sect,
524 offset, false, false);
525 if (sym) {
526 adjust -= sym->symv[0].key;
527 r->snum = sym->initial_snum;
528 r->ext = 1;
532 if (r->pcrel)
533 adjust += ((r->ext && fmt.ptrsize == 8) ? bytes : -(int64_t)sect->size);
535 /* NeXT as puts relocs in reversed order (address-wise) into the
536 ** files, so we do the same, doesn't seem to make much of a
537 ** difference either way */
538 r->next = sect->relocs;
539 sect->relocs = r;
540 if (r->ext)
541 sect->extreloc = 1;
542 ++sect->nreloc;
544 return adjust;
546 bail:
547 nasm_free(r);
548 return 0;
551 static void macho_output(int32_t secto, const void *data,
552 enum out_type type, uint64_t size,
553 int32_t section, int32_t wrt)
555 struct section *s;
556 int64_t addr, offset;
557 uint8_t mydata[16], *p;
558 bool is_bss;
559 enum reltype reltype;
561 s = get_section_by_index(secto);
562 if (!s) {
563 nasm_error(ERR_WARNING, "attempt to assemble code in"
564 " section %d: defaulting to `.text'", secto);
565 s = get_section_by_name("__TEXT", "__text");
567 /* should never happen */
568 if (!s)
569 nasm_panic("text section not found");
572 /* debug code generation only for sections tagged with
573 * instruction attribute */
574 if (s->flags & S_ATTR_SOME_INSTRUCTIONS)
576 struct section_info sinfo;
577 sinfo.size = s->size;
578 sinfo.secto = secto;
579 dfmt->debug_output(0, &sinfo);
582 is_bss = (s->flags & SECTION_TYPE) == S_ZEROFILL;
584 if (is_bss && type != OUT_RESERVE) {
585 nasm_error(ERR_WARNING, "attempt to initialize memory in "
586 "BSS section: ignored");
587 /* FIXME */
588 nasm_error(ERR_WARNING, "section size may be negative"
589 "with address symbols");
590 s->size += realsize(type, size);
591 return;
594 memset(mydata, 0, sizeof(mydata));
596 switch (type) {
597 case OUT_RESERVE:
598 if (!is_bss) {
599 nasm_error(ERR_WARNING, "uninitialized space declared in"
600 " %s,%s section: zeroing", s->segname, s->sectname);
602 sect_write(s, NULL, size);
603 } else
604 s->size += size;
606 break;
608 case OUT_RAWDATA:
609 sect_write(s, data, size);
610 break;
612 case OUT_ADDRESS:
614 int asize = abs((int)size);
616 addr = *(int64_t *)data;
617 if (section != NO_SEG) {
618 if (section % 2) {
619 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
620 " section base references");
621 } else if (wrt == NO_SEG) {
622 if (fmt.ptrsize == 8 && asize != 8) {
623 nasm_error(ERR_NONFATAL,
624 "Mach-O 64-bit format does not support"
625 " 32-bit absolute addresses");
626 } else {
627 addr += add_reloc(s, section, addr, RL_ABS, asize);
629 } else if (wrt == macho_tlvp_sect && fmt.ptrsize != 8 &&
630 asize == (int) fmt.ptrsize) {
631 addr += add_reloc(s, section, addr, RL_TLV, asize);
632 } else {
633 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
634 " this use of WRT");
638 p = mydata;
639 WRITEADDR(p, addr, asize);
640 sect_write(s, mydata, asize);
641 break;
644 case OUT_REL1ADR:
645 case OUT_REL2ADR:
647 p = mydata;
648 offset = *(int64_t *)data;
649 addr = offset - size;
651 if (section != NO_SEG && section % 2) {
652 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
653 " section base references");
654 } else if (fmt.ptrsize == 8) {
655 nasm_error(ERR_NONFATAL, "Unsupported non-32-bit"
656 " Macho-O relocation [2]");
657 } else if (wrt != NO_SEG) {
658 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
659 " this use of WRT");
660 wrt = NO_SEG; /* we can at least _try_ to continue */
661 } else {
662 addr += add_reloc(s, section, addr+size, RL_REL,
663 type == OUT_REL1ADR ? 1 : 2);
666 WRITESHORT(p, addr);
667 sect_write(s, mydata, type == OUT_REL1ADR ? 1 : 2);
668 break;
670 case OUT_REL4ADR:
671 case OUT_REL8ADR:
673 p = mydata;
674 offset = *(int64_t *)data;
675 addr = offset - size;
676 reltype = RL_REL;
678 if (section != NO_SEG && section % 2) {
679 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
680 " section base references");
681 } else if (wrt == NO_SEG) {
682 if (fmt.ptrsize == 8 &&
683 (s->flags & S_ATTR_SOME_INSTRUCTIONS)) {
684 uint8_t opcode[2];
686 opcode[0] = opcode[1] = 0;
688 /* HACK: Retrieve instruction opcode */
689 if (likely(s->data->datalen >= 2)) {
690 saa_fread(s->data, s->data->datalen-2, opcode, 2);
691 } else if (s->data->datalen == 1) {
692 saa_fread(s->data, 0, opcode+1, 1);
695 if ((opcode[0] != 0x0f && (opcode[1] & 0xfe) == 0xe8) ||
696 (opcode[0] == 0x0f && (opcode[1] & 0xf0) == 0x80)) {
697 /* Direct call, jmp, or jcc */
698 reltype = RL_BRANCH;
701 } else if (wrt == macho_gotpcrel_sect) {
702 reltype = RL_GOT;
704 if ((s->flags & S_ATTR_SOME_INSTRUCTIONS) &&
705 s->data->datalen >= 3) {
706 uint8_t gotload[3];
708 /* HACK: Retrieve instruction opcode */
709 saa_fread(s->data, s->data->datalen-3, gotload, 3);
710 if ((gotload[0] & 0xf8) == 0x48 &&
711 gotload[1] == 0x8b &&
712 (gotload[2] & 0307) == 0005) {
713 /* movq <reg>,[rel sym wrt ..gotpcrel] */
714 reltype = RL_GOTLOAD;
717 } else if (wrt == macho_tlvp_sect && fmt.ptrsize == 8) {
718 reltype = RL_TLV;
719 } else {
720 nasm_error(ERR_NONFATAL, "Mach-O format does not support"
721 " this use of WRT");
722 /* continue with RL_REL */
725 addr += add_reloc(s, section, offset, reltype,
726 type == OUT_REL4ADR ? 4 : 8);
727 WRITELONG(p, addr);
728 sect_write(s, mydata, type == OUT_REL4ADR ? 4 : 8);
729 break;
731 default:
732 nasm_error(ERR_NONFATAL, "Unrepresentable relocation in Mach-O");
733 break;
737 #define S_CODE (S_REGULAR | S_ATTR_SOME_INSTRUCTIONS | S_ATTR_PURE_INSTRUCTIONS)
738 #define NO_TYPE S_NASM_TYPE_MASK
740 /* Translation table from traditional Unix section names to Mach-O */
741 static const struct macho_known_section {
742 const char *nasmsect;
743 const char *segname;
744 const char *sectname;
745 const uint32_t flags;
746 } known_sections[] = {
747 { ".text", "__TEXT", "__text", S_CODE },
748 { ".data", "__DATA", "__data", S_REGULAR },
749 { ".rodata", "__DATA", "__const", S_REGULAR },
750 { ".bss", "__DATA", "__bss", S_ZEROFILL },
751 { ".debug_abbrev", "__DWARF", "__debug_abbrev", S_ATTR_DEBUG },
752 { ".debug_info", "__DWARF", "__debug_info", S_ATTR_DEBUG },
753 { ".debug_line", "__DWARF", "__debug_line", S_ATTR_DEBUG },
754 { ".debug_str", "__DWARF", "__debug_str", S_ATTR_DEBUG },
757 /* Section type or attribute directives */
758 static const struct macho_known_section_attr {
759 const char *name;
760 uint32_t flags;
761 } sect_attribs[] = {
762 { "data", S_REGULAR },
763 { "code", S_CODE },
764 { "mixed", S_REGULAR | S_ATTR_SOME_INSTRUCTIONS },
765 { "bss", S_ZEROFILL },
766 { "zerofill", S_ZEROFILL },
767 { "no_dead_strip", NO_TYPE | S_ATTR_NO_DEAD_STRIP },
768 { "live_support", NO_TYPE | S_ATTR_LIVE_SUPPORT },
769 { "strip_static_syms", NO_TYPE | S_ATTR_STRIP_STATIC_SYMS },
770 { "debug", NO_TYPE | S_ATTR_DEBUG },
771 { NULL, 0 }
774 static const struct macho_known_section *
775 lookup_known_section(const char *name, bool by_sectname)
777 size_t i;
779 if (name && name[0]) {
780 for (i = 0; i < ARRAY_SIZE(known_sections); i++) {
781 const char *p = by_sectname ?
782 known_sections[i].sectname :
783 known_sections[i].nasmsect;
784 if (!strcmp(name, p))
785 return &known_sections[i];
789 return NULL;
792 static int32_t macho_section(char *name, int pass, int *bits)
794 const struct macho_known_section *known_section;
795 const struct macho_known_section_attr *sa;
796 char *sectionAttributes;
797 struct section *s;
798 const char *section, *segment;
799 uint32_t flags;
800 char *currentAttribute;
801 char *comma;
803 bool new_seg;
805 (void)pass;
807 /* Default to the appropriate number of bits. */
808 if (!name) {
809 *bits = fmt.ptrsize << 3;
810 name = ".text";
811 sectionAttributes = NULL;
812 } else {
813 sectionAttributes = name;
814 name = nasm_strsep(&sectionAttributes, " \t");
817 section = segment = NULL;
818 flags = 0;
820 comma = strchr(name, ',');
821 if (comma) {
822 int len;
824 *comma = '\0';
825 segment = name;
826 section = comma+1;
828 len = strlen(segment);
829 if (len == 0) {
830 nasm_error(ERR_NONFATAL, "empty segment name\n");
831 } else if (len > 16) {
832 nasm_error(ERR_NONFATAL, "segment name %s too long\n", segment);
835 len = strlen(section);
836 if (len == 0) {
837 nasm_error(ERR_NONFATAL, "empty section name\n");
838 } else if (len > 16) {
839 nasm_error(ERR_NONFATAL, "section name %s too long\n", section);
842 known_section = lookup_known_section(section, true);
843 if (known_section)
844 flags = known_section->flags;
845 else
846 flags = S_REGULAR;
847 } else {
848 known_section = lookup_known_section(name, false);
849 if (!known_section) {
850 nasm_error(ERR_NONFATAL, "unknown section name %s\n", name);
851 return NO_SEG;
854 segment = known_section->segname;
855 section = known_section->sectname;
856 flags = known_section->flags;
859 /* try to find section with that name, or create it */
860 s = find_or_add_section(segment, section);
861 new_seg = is_new_section(s);
863 /* initialize it if it is a brand new section */
864 if (new_seg) {
865 *sectstail = s;
866 sectstail = &s->next;
868 s->data = saa_init(1L);
869 s->fileindex = ++seg_nsects;
870 s->align = -1;
871 s->pad = -1;
872 s->offset = -1;
873 s->by_name = false;
875 s->size = 0;
876 s->nreloc = 0;
877 s->flags = flags;
880 if (comma)
881 *comma = ','; /* Restore comma */
883 s->by_name = s->by_name || comma; /* Was specified by name */
885 flags = NO_TYPE;
887 while (sectionAttributes &&
888 (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
889 if (!*currentAttribute)
890 continue;
892 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
893 char *end;
894 int newAlignment, value;
896 value = strtoul(currentAttribute + 6, (char**)&end, 0);
897 newAlignment = alignlog2_32(value);
899 if (0 != *end) {
900 nasm_error(ERR_NONFATAL,
901 "unknown or missing alignment value \"%s\" "
902 "specified for section \"%s\"",
903 currentAttribute + 6,
904 name);
905 } else if (0 > newAlignment) {
906 nasm_error(ERR_NONFATAL,
907 "alignment of %d (for section \"%s\") is not "
908 "a power of two",
909 value,
910 name);
913 if (s->align < newAlignment)
914 s->align = newAlignment;
915 } else {
916 for (sa = sect_attribs; sa->name; sa++) {
917 if (!nasm_stricmp(sa->name, currentAttribute)) {
918 if ((sa->flags & S_NASM_TYPE_MASK) != NO_TYPE) {
919 flags = (flags & ~S_NASM_TYPE_MASK)
920 | (sa->flags & S_NASM_TYPE_MASK);
922 flags |= sa->flags & ~S_NASM_TYPE_MASK;
923 break;
927 if (!sa->name) {
928 nasm_error(ERR_NONFATAL,
929 "unknown section attribute %s for section %s",
930 currentAttribute, name);
935 if ((flags & S_NASM_TYPE_MASK) != NO_TYPE) {
936 if (!new_seg && ((s->flags ^ flags) & S_NASM_TYPE_MASK)) {
937 nasm_error(ERR_NONFATAL,
938 "inconsistent section attributes for section %s\n",
939 name);
940 } else {
941 s->flags = (s->flags & ~S_NASM_TYPE_MASK) | flags;
943 } else {
944 s->flags |= flags & ~S_NASM_TYPE_MASK;
947 return s->subsection;
950 static int32_t macho_herelabel(const char *name, enum label_type type,
951 int32_t section, int32_t *subsection,
952 bool *copyoffset)
954 struct section *s;
955 int32_t subsec;
956 (void)name;
958 if (!(head_flags & MH_SUBSECTIONS_VIA_SYMBOLS))
959 return section;
961 /* No subsection only for local labels */
962 if (type == LBL_LOCAL)
963 return section;
965 s = get_section_by_index(section);
966 if (!s)
967 return section;
969 subsec = *subsection;
970 if (subsec == NO_SEG) {
971 /* Allocate a new subsection index */
972 subsec = *subsection = seg_alloc();
973 section_by_index = raa_write_ptr(section_by_index, subsec >> 1, s);
976 s->subsection = subsec;
977 *copyoffset = true; /* Maintain previous offset */
978 return subsec;
981 static void macho_symdef(char *name, int32_t section, int64_t offset,
982 int is_global, char *special)
984 struct symbol *sym;
985 struct section *s;
986 bool special_used = false;
988 #if defined(DEBUG) && DEBUG>2
989 nasm_error(ERR_DEBUG,
990 " macho_symdef: %s, pass0=%d, passn=%"PRId64", sec=%"PRIx32", off=%"PRIx64", is_global=%d, %s\n",
991 name, pass0, passn, section, offset, is_global, special);
992 #endif
994 if (is_global == 3) {
995 if (special) {
996 int n = strcspn(special, " \t");
998 if (!nasm_strnicmp(special, "private_extern", n)) {
999 for (sym = syms; sym != NULL; sym = sym->next) {
1000 if (!strcmp(name, sym->name)) {
1001 if (sym->type & N_PEXT)
1002 return; /* nothing to be done */
1003 else
1004 break;
1009 nasm_error(ERR_NONFATAL, "The Mach-O format does not "
1010 "(yet) support forward reference fixups.");
1011 return;
1014 if (name[0] == '.' && name[1] == '.' && name[2] != '@') {
1016 * This is a NASM special symbol. We never allow it into
1017 * the Macho-O symbol table, even if it's a valid one. If it
1018 * _isn't_ a valid one, we should barf immediately.
1020 if (strcmp(name, "..gotpcrel") && strcmp(name, "..tlvp"))
1021 nasm_error(ERR_NONFATAL, "unrecognized special symbol `%s'", name);
1022 return;
1025 sym = *symstail = nasm_zalloc(sizeof(struct symbol));
1026 sym->next = NULL;
1027 symstail = &sym->next;
1029 sym->name = name;
1030 sym->strx = strslen;
1031 sym->type = 0;
1032 sym->desc = 0;
1033 sym->symv[0].key = offset;
1034 sym->symv[1].key = offset;
1035 sym->initial_snum = -1;
1037 /* external and common symbols get N_EXT */
1038 if (is_global != 0) {
1039 sym->type |= N_EXT;
1041 if (is_global == 1) {
1042 /* check special to see if the global symbol shall be marked as private external: N_PEXT */
1043 if (special) {
1044 int n = strcspn(special, " \t");
1046 if (!nasm_strnicmp(special, "private_extern", n))
1047 sym->type |= N_PEXT;
1048 else
1049 nasm_error(ERR_NONFATAL, "unrecognised symbol type `%.*s'", n, special);
1051 special_used = true;
1054 /* track the initially allocated symbol number for use in future fix-ups */
1055 sym->initial_snum = nsyms;
1057 if (section == NO_SEG) {
1058 /* symbols in no section get absolute */
1059 sym->type |= N_ABS;
1060 sym->sect = NO_SECT;
1062 s = &absolute_sect;
1063 } else {
1064 s = get_section_by_index(section);
1066 sym->type |= N_SECT;
1068 /* get the in-file index of the section the symbol was defined in */
1069 sym->sect = s ? s->fileindex : NO_SECT;
1071 if (!s) {
1072 /* remember symbol number of references to external
1073 ** symbols, this works because every external symbol gets
1074 ** its own section number allocated internally by nasm and
1075 ** can so be used as a key */
1076 extsyms = raa_write(extsyms, section, nsyms);
1078 switch (is_global) {
1079 case 1:
1080 case 2:
1081 /* there isn't actually a difference between global
1082 ** and common symbols, both even have their size in
1083 ** sym->symv[0].key */
1084 sym->type = N_EXT;
1085 break;
1087 default:
1088 /* give an error on unfound section if it's not an
1089 ** external or common symbol (assemble_file() does a
1090 ** seg_alloc() on every call for them) */
1091 nasm_panic("in-file index for section %d not found, is_global = %d", section, is_global);
1092 break;
1097 if (s) {
1098 s->syms[0] = rb_insert(s->syms[0], &sym->symv[0]);
1099 if (is_global)
1100 s->syms[1] = rb_insert(s->syms[1], &sym->symv[1]);
1103 ++nsyms;
1105 if (special && !special_used)
1106 nasm_error(ERR_NONFATAL, "no special symbol features supported here");
1109 static void macho_sectalign(int32_t seg, unsigned int value)
1111 struct section *s;
1112 int align;
1114 nasm_assert(!(seg & 1));
1116 s = get_section_by_index(seg);
1118 if (!s || !is_power2(value))
1119 return;
1121 align = alignlog2_32(value);
1122 if (s->align < align)
1123 s->align = align;
1126 extern macros_t macho_stdmac[];
1128 /* Comparison function for qsort symbol layout. */
1129 static int layout_compare (const struct symbol **s1,
1130 const struct symbol **s2)
1132 return (strcmp ((*s1)->name, (*s2)->name));
1135 /* The native assembler does a few things in a similar function
1137 * Remove temporary labels
1138 * Sort symbols according to local, external, undefined (by name)
1139 * Order the string table
1141 We do not remove temporary labels right now.
1143 numsyms is the total number of symbols we have. strtabsize is the
1144 number entries in the string table. */
1146 static void macho_layout_symbols (uint32_t *numsyms,
1147 uint32_t *strtabsize)
1149 struct symbol *sym, **symp;
1150 uint32_t i,j;
1152 *numsyms = 0;
1153 *strtabsize = sizeof (char);
1155 symp = &syms;
1157 while ((sym = *symp)) {
1158 /* Undefined symbols are now external. */
1159 if (sym->type == N_UNDF)
1160 sym->type |= N_EXT;
1162 if ((sym->type & N_EXT) == 0) {
1163 sym->snum = *numsyms;
1164 *numsyms = *numsyms + 1;
1165 nlocalsym++;
1167 else {
1168 if ((sym->type & N_TYPE) != N_UNDF) {
1169 nextdefsym++;
1170 } else {
1171 nundefsym++;
1174 /* If we handle debug info we'll want
1175 to check for it here instead of just
1176 adding the symbol to the string table. */
1177 sym->strx = *strtabsize;
1178 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
1179 *strtabsize += strlen(sym->name) + 1;
1181 symp = &(sym->next);
1184 /* Next, sort the symbols. Most of this code is a direct translation from
1185 the Apple cctools symbol layout. We need to keep compatibility with that. */
1186 /* Set the indexes for symbol groups into the symbol table */
1187 ilocalsym = 0;
1188 iextdefsym = nlocalsym;
1189 iundefsym = nlocalsym + nextdefsym;
1191 /* allocate arrays for sorting externals by name */
1192 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
1193 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
1195 i = 0;
1196 j = 0;
1198 symp = &syms;
1200 while ((sym = *symp)) {
1202 if((sym->type & N_EXT) == 0) {
1203 sym->strx = *strtabsize;
1204 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
1205 *strtabsize += strlen(sym->name) + 1;
1207 else {
1208 if ((sym->type & N_TYPE) != N_UNDF) {
1209 extdefsyms[i++] = sym;
1210 } else {
1211 undefsyms[j++] = sym;
1214 symp = &(sym->next);
1217 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
1218 (int (*)(const void *, const void *))layout_compare);
1219 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
1220 (int (*)(const void *, const void *))layout_compare);
1222 for(i = 0; i < nextdefsym; i++) {
1223 extdefsyms[i]->snum = *numsyms;
1224 *numsyms += 1;
1226 for(j = 0; j < nundefsym; j++) {
1227 undefsyms[j]->snum = *numsyms;
1228 *numsyms += 1;
1232 /* Calculate some values we'll need for writing later. */
1234 static void macho_calculate_sizes (void)
1236 struct section *s;
1237 int fi;
1239 /* count sections and calculate in-memory and in-file offsets */
1240 for (s = sects; s != NULL; s = s->next) {
1241 uint64_t newaddr;
1243 /* recalculate segment address based on alignment and vm size */
1244 s->addr = seg_vmsize;
1246 /* we need section alignment to calculate final section address */
1247 if (s->align == -1)
1248 s->align = DEFAULT_SECTION_ALIGNMENT;
1250 newaddr = ALIGN(s->addr, UINT64_C(1) << s->align);
1251 s->addr = newaddr;
1253 seg_vmsize = newaddr + s->size;
1255 /* zerofill sections aren't actually written to the file */
1256 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1258 * LLVM/Xcode as always aligns the section data to 4
1259 * bytes; there is a comment in the LLVM source code that
1260 * perhaps aligning to pointer size would be better.
1262 s->pad = ALIGN(seg_filesize, 4) - seg_filesize;
1263 s->offset = seg_filesize + s->pad;
1264 seg_filesize += s->size + s->pad;
1266 /* filesize and vmsize needs to be aligned */
1267 seg_vmsize += s->pad;
1271 /* calculate size of all headers, load commands and sections to
1272 ** get a pointer to the start of all the raw data */
1273 if (seg_nsects > 0) {
1274 ++head_ncmds;
1275 head_sizeofcmds += fmt.segcmd_size + seg_nsects * fmt.sectcmd_size;
1278 if (nsyms > 0) {
1279 ++head_ncmds;
1280 head_sizeofcmds += MACHO_SYMCMD_SIZE;
1283 if (seg_nsects > MAX_SECT) {
1284 nasm_fatal("MachO output is limited to %d sections\n",
1285 MAX_SECT);
1288 /* Create a table of sections by file index to avoid linear search */
1289 sectstab = nasm_malloc((seg_nsects + 1) * sizeof(*sectstab));
1290 sectstab[NO_SECT] = &absolute_sect;
1291 for (s = sects, fi = 1; s != NULL; s = s->next, fi++)
1292 sectstab[fi] = s;
1295 /* Write out the header information for the file. */
1297 static void macho_write_header (void)
1299 fwriteint32_t(fmt.mh_magic, ofile); /* magic */
1300 fwriteint32_t(fmt.cpu_type, ofile); /* CPU type */
1301 fwriteint32_t(CPU_SUBTYPE_I386_ALL, ofile); /* CPU subtype */
1302 fwriteint32_t(MH_OBJECT, ofile); /* Mach-O file type */
1303 fwriteint32_t(head_ncmds, ofile); /* number of load commands */
1304 fwriteint32_t(head_sizeofcmds, ofile); /* size of load commands */
1305 fwriteint32_t(head_flags, ofile); /* flags, if any */
1306 fwritezero(fmt.header_size - 7*4, ofile); /* reserved fields */
1309 /* Write out the segment load command at offset. */
1311 static uint32_t macho_write_segment (uint64_t offset)
1313 uint64_t rel_base = alignptr(offset + seg_filesize);
1314 uint32_t s_reloff = 0;
1315 struct section *s;
1317 fwriteint32_t(fmt.lc_segment, ofile); /* cmd == LC_SEGMENT_64 */
1319 /* size of load command including section load commands */
1320 fwriteint32_t(fmt.segcmd_size + seg_nsects * fmt.sectcmd_size,
1321 ofile);
1323 /* in an MH_OBJECT file all sections are in one unnamed (name
1324 ** all zeros) segment */
1325 fwritezero(16, ofile);
1326 fwriteptr(0, ofile); /* in-memory offset */
1327 fwriteptr(seg_vmsize, ofile); /* in-memory size */
1328 fwriteptr(offset, ofile); /* in-file offset to data */
1329 fwriteptr(seg_filesize, ofile); /* in-file size */
1330 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* maximum vm protection */
1331 fwriteint32_t(VM_PROT_DEFAULT, ofile); /* initial vm protection */
1332 fwriteint32_t(seg_nsects, ofile); /* number of sections */
1333 fwriteint32_t(0, ofile); /* no flags */
1335 /* emit section headers */
1336 for (s = sects; s != NULL; s = s->next) {
1337 if (s->nreloc) {
1338 nasm_assert((s->flags & SECTION_TYPE) != S_ZEROFILL);
1339 s->flags |= S_ATTR_LOC_RELOC;
1340 if (s->extreloc)
1341 s->flags |= S_ATTR_EXT_RELOC;
1342 } else if (!xstrncmp(s->segname, "__DATA") &&
1343 !xstrncmp(s->sectname, "__const") &&
1344 !s->by_name &&
1345 !get_section_by_name("__TEXT", "__const")) {
1347 * The MachO equivalent to .rodata can be either
1348 * __DATA,__const or __TEXT,__const; the latter only if
1349 * there are no relocations. However, when mixed it is
1350 * better to specify the segments explicitly.
1352 xstrncpy(s->segname, "__TEXT");
1355 nasm_write(s->sectname, sizeof(s->sectname), ofile);
1356 nasm_write(s->segname, sizeof(s->segname), ofile);
1357 fwriteptr(s->addr, ofile);
1358 fwriteptr(s->size, ofile);
1360 /* dummy data for zerofill sections or proper values */
1361 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
1362 nasm_assert(s->pad != (uint32_t)-1);
1363 offset += s->pad;
1364 fwriteint32_t(offset, ofile);
1365 offset += s->size;
1366 /* Write out section alignment, as a power of two.
1367 e.g. 32-bit word alignment would be 2 (2^2 = 4). */
1368 fwriteint32_t(s->align, ofile);
1369 /* To be compatible with cctools as we emit
1370 a zero reloff if we have no relocations. */
1371 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, ofile);
1372 fwriteint32_t(s->nreloc, ofile);
1374 s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
1375 } else {
1376 fwriteint32_t(0, ofile);
1377 fwriteint32_t(s->align, ofile);
1378 fwriteint32_t(0, ofile);
1379 fwriteint32_t(0, ofile);
1382 fwriteint32_t(s->flags, ofile); /* flags */
1383 fwriteint32_t(0, ofile); /* reserved */
1384 fwriteptr(0, ofile); /* reserved */
1387 rel_padcnt = rel_base - offset;
1388 offset = rel_base + s_reloff;
1390 return offset;
1393 /* For a given chain of relocs r, write out the entire relocation
1394 chain to the object file. */
1396 static void macho_write_relocs (struct reloc *r)
1398 while (r) {
1399 uint32_t word2;
1401 fwriteint32_t(r->addr, ofile); /* reloc offset */
1403 word2 = r->snum;
1404 word2 |= r->pcrel << 24;
1405 word2 |= r->length << 25;
1406 word2 |= r->ext << 27;
1407 word2 |= r->type << 28;
1408 fwriteint32_t(word2, ofile); /* reloc data */
1409 r = r->next;
1413 /* Write out the section data. */
1414 static void macho_write_section (void)
1416 struct section *s;
1417 struct reloc *r;
1418 uint8_t *p;
1419 int32_t len;
1420 int64_t l;
1421 union offset {
1422 uint64_t val;
1423 uint8_t buf[8];
1424 } blk;
1426 for (s = sects; s != NULL; s = s->next) {
1427 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
1428 continue;
1430 /* Like a.out Mach-O references things in the data or bss
1431 * sections by addresses which are actually relative to the
1432 * start of the _text_ section, in the _file_. See outaout.c
1433 * for more information. */
1434 saa_rewind(s->data);
1435 for (r = s->relocs; r != NULL; r = r->next) {
1436 len = (uint32_t)1 << r->length;
1437 if (len > 4) /* Can this ever be an issue?! */
1438 len = 8;
1439 blk.val = 0;
1440 saa_fread(s->data, r->addr, blk.buf, len);
1442 /* get offset based on relocation type */
1443 #ifdef WORDS_LITTLEENDIAN
1444 l = blk.val;
1445 #else
1446 l = blk.buf[0];
1447 l += ((int64_t)blk.buf[1]) << 8;
1448 l += ((int64_t)blk.buf[2]) << 16;
1449 l += ((int64_t)blk.buf[3]) << 24;
1450 l += ((int64_t)blk.buf[4]) << 32;
1451 l += ((int64_t)blk.buf[5]) << 40;
1452 l += ((int64_t)blk.buf[6]) << 48;
1453 l += ((int64_t)blk.buf[7]) << 56;
1454 #endif
1456 /* If the relocation is internal add to the current section
1457 offset. Otherwise the only value we need is the symbol
1458 offset which we already have. The linker takes care
1459 of the rest of the address. */
1460 if (!r->ext) {
1461 /* generate final address by section address and offset */
1462 nasm_assert(r->snum <= seg_nsects);
1463 l += sectstab[r->snum]->addr;
1464 if (r->pcrel)
1465 l -= s->addr;
1466 } else if (r->pcrel && r->type == GENERIC_RELOC_VANILLA) {
1467 l -= s->addr;
1470 /* write new offset back */
1471 p = blk.buf;
1472 WRITEDLONG(p, l);
1473 saa_fwrite(s->data, r->addr, blk.buf, len);
1476 /* dump the section data to file */
1477 fwritezero(s->pad, ofile);
1478 saa_fpwrite(s->data, ofile);
1481 /* pad last section up to reloc entries on pointer boundary */
1482 fwritezero(rel_padcnt, ofile);
1484 /* emit relocation entries */
1485 for (s = sects; s != NULL; s = s->next)
1486 macho_write_relocs (s->relocs);
1489 /* Write out the symbol table. We should already have sorted this
1490 before now. */
1491 static void macho_write_symtab (void)
1493 struct symbol *sym;
1494 uint64_t i;
1496 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1498 for (sym = syms; sym != NULL; sym = sym->next) {
1499 if ((sym->type & N_EXT) == 0) {
1500 fwriteint32_t(sym->strx, ofile); /* string table entry number */
1501 nasm_write(&sym->type, 1, ofile); /* symbol type */
1502 nasm_write(&sym->sect, 1, ofile); /* section */
1503 fwriteint16_t(sym->desc, ofile); /* description */
1505 /* Fix up the symbol value now that we know the final section
1506 sizes. */
1507 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1508 nasm_assert(sym->sect <= seg_nsects);
1509 sym->symv[0].key += sectstab[sym->sect]->addr;
1512 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1516 for (i = 0; i < nextdefsym; i++) {
1517 sym = extdefsyms[i];
1518 fwriteint32_t(sym->strx, ofile);
1519 nasm_write(&sym->type, 1, ofile); /* symbol type */
1520 nasm_write(&sym->sect, 1, ofile); /* section */
1521 fwriteint16_t(sym->desc, ofile); /* description */
1523 /* Fix up the symbol value now that we know the final section
1524 sizes. */
1525 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1526 nasm_assert(sym->sect <= seg_nsects);
1527 sym->symv[0].key += sectstab[sym->sect]->addr;
1530 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1533 for (i = 0; i < nundefsym; i++) {
1534 sym = undefsyms[i];
1535 fwriteint32_t(sym->strx, ofile);
1536 nasm_write(&sym->type, 1, ofile); /* symbol type */
1537 nasm_write(&sym->sect, 1, ofile); /* section */
1538 fwriteint16_t(sym->desc, ofile); /* description */
1540 /* Fix up the symbol value now that we know the final section
1541 sizes. */
1542 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1543 nasm_assert(sym->sect <= seg_nsects);
1544 sym->symv[0].key += sectstab[sym->sect]->addr;
1547 fwriteptr(sym->symv[0].key, ofile); /* value (i.e. offset) */
1552 /* Fixup the snum in the relocation entries, we should be
1553 doing this only for externally referenced symbols. */
1554 static void macho_fixup_relocs (struct reloc *r)
1556 struct symbol *sym;
1558 while (r != NULL) {
1559 if (r->ext) {
1560 for (sym = syms; sym != NULL; sym = sym->next) {
1561 if (sym->initial_snum == r->snum) {
1562 r->snum = sym->snum;
1563 break;
1567 r = r->next;
1571 /* Write out the object file. */
1573 static void macho_write (void)
1575 uint64_t offset = 0;
1577 /* mach-o object file structure:
1579 ** mach header
1580 ** uint32_t magic
1581 ** int cpu type
1582 ** int cpu subtype
1583 ** uint32_t mach file type
1584 ** uint32_t number of load commands
1585 ** uint32_t size of all load commands
1586 ** (includes section struct size of segment command)
1587 ** uint32_t flags
1589 ** segment command
1590 ** uint32_t command type == LC_SEGMENT[_64]
1591 ** uint32_t size of load command
1592 ** (including section load commands)
1593 ** char[16] segment name
1594 ** pointer in-memory offset
1595 ** pointer in-memory size
1596 ** pointer in-file offset to data area
1597 ** pointer in-file size
1598 ** (in-memory size excluding zerofill sections)
1599 ** int maximum vm protection
1600 ** int initial vm protection
1601 ** uint32_t number of sections
1602 ** uint32_t flags
1604 ** section commands
1605 ** char[16] section name
1606 ** char[16] segment name
1607 ** pointer in-memory offset
1608 ** pointer in-memory size
1609 ** uint32_t in-file offset
1610 ** uint32_t alignment
1611 ** (irrelevant in MH_OBJECT)
1612 ** uint32_t in-file offset of relocation entires
1613 ** uint32_t number of relocations
1614 ** uint32_t flags
1615 ** uint32_t reserved
1616 ** uint32_t reserved
1618 ** symbol table command
1619 ** uint32_t command type == LC_SYMTAB
1620 ** uint32_t size of load command
1621 ** uint32_t symbol table offset
1622 ** uint32_t number of symbol table entries
1623 ** uint32_t string table offset
1624 ** uint32_t string table size
1626 ** raw section data
1628 ** padding to pointer boundary
1630 ** relocation data (struct reloc)
1631 ** int32_t offset
1632 ** uint data (symbolnum, pcrel, length, extern, type)
1634 ** symbol table data (struct nlist)
1635 ** int32_t string table entry number
1636 ** uint8_t type
1637 ** (extern, absolute, defined in section)
1638 ** uint8_t section
1639 ** (0 for global symbols, section number of definition (>= 1, <=
1640 ** 254) for local symbols, size of variable for common symbols
1641 ** [type == extern])
1642 ** int16_t description
1643 ** (for stab debugging format)
1644 ** pointer value (i.e. file offset) of symbol or stab offset
1646 ** string table data
1647 ** list of null-terminated strings
1650 /* Emit the Mach-O header. */
1651 macho_write_header();
1653 offset = fmt.header_size + head_sizeofcmds;
1655 /* emit the segment load command */
1656 if (seg_nsects > 0)
1657 offset = macho_write_segment (offset);
1658 else
1659 nasm_error(ERR_WARNING, "no sections?");
1661 if (nsyms > 0) {
1662 /* write out symbol command */
1663 fwriteint32_t(LC_SYMTAB, ofile); /* cmd == LC_SYMTAB */
1664 fwriteint32_t(MACHO_SYMCMD_SIZE, ofile); /* size of load command */
1665 fwriteint32_t(offset, ofile); /* symbol table offset */
1666 fwriteint32_t(nsyms, ofile); /* number of symbol
1667 ** table entries */
1668 offset += nsyms * fmt.nlist_size;
1669 fwriteint32_t(offset, ofile); /* string table offset */
1670 fwriteint32_t(strslen, ofile); /* string table size */
1673 /* emit section data */
1674 if (seg_nsects > 0)
1675 macho_write_section ();
1677 /* emit symbol table if we have symbols */
1678 if (nsyms > 0)
1679 macho_write_symtab ();
1681 /* we don't need to pad here, we are already aligned */
1683 /* emit string table */
1684 saa_fpwrite(strs, ofile);
1686 /* We do quite a bit here, starting with finalizing all of the data
1687 for the object file, writing, and then freeing all of the data from
1688 the file. */
1690 static void macho_cleanup(void)
1692 struct section *s;
1693 struct reloc *r;
1694 struct symbol *sym;
1696 dfmt->cleanup();
1698 /* Sort all symbols. */
1699 macho_layout_symbols (&nsyms, &strslen);
1701 /* Fixup relocation entries */
1702 for (s = sects; s != NULL; s = s->next) {
1703 macho_fixup_relocs (s->relocs);
1706 /* First calculate and finalize needed values. */
1707 macho_calculate_sizes();
1708 macho_write();
1710 /* free up everything */
1711 while (sects->next) {
1712 s = sects;
1713 sects = sects->next;
1715 saa_free(s->data);
1716 while (s->relocs != NULL) {
1717 r = s->relocs;
1718 s->relocs = s->relocs->next;
1719 nasm_free(r);
1722 nasm_free(s);
1725 saa_free(strs);
1727 raa_free(extsyms);
1729 while (syms) {
1730 sym = syms;
1731 syms = syms->next;
1732 nasm_free (sym);
1735 nasm_free(extdefsyms);
1736 nasm_free(undefsyms);
1737 nasm_free(sectstab);
1738 raa_free(section_by_index);
1739 hash_free(&section_by_name);
1742 static bool macho_set_section_attribute_by_symbol(const char *label, uint32_t flags)
1744 struct section *s;
1745 int32_t nasm_seg;
1746 int64_t offset;
1748 if (!lookup_label(label, &nasm_seg, &offset)) {
1749 nasm_error(ERR_NONFATAL, "unknown symbol `%s' in no_dead_strip", label);
1750 return false;
1753 s = get_section_by_index(nasm_seg);
1754 if (!s) {
1755 nasm_error(ERR_NONFATAL, "symbol `%s' is external or absolute", label);
1756 return false;
1759 s->flags |= flags;
1760 return true;
1764 * Mark a symbol for no dead stripping
1766 static enum directive_result macho_no_dead_strip(const char *labels)
1768 char *s, *p, *ep;
1769 char ec;
1770 enum directive_result rv = DIRR_ERROR;
1771 bool real = passn > 1;
1773 p = s = nasm_strdup(labels);
1774 while (*p) {
1775 ep = nasm_skip_identifier(p);
1776 if (!ep) {
1777 nasm_error(ERR_NONFATAL, "invalid symbol in NO_DEAD_STRIP");
1778 goto err;
1780 ec = *ep;
1781 if (ec && ec != ',' && !nasm_isspace(ec)) {
1782 nasm_error(ERR_NONFATAL, "cannot parse contents after symbol");
1783 goto err;
1785 *ep = '\0';
1786 if (real) {
1787 if (!macho_set_section_attribute_by_symbol(p, S_ATTR_NO_DEAD_STRIP))
1788 rv = DIRR_ERROR;
1790 *ep = ec;
1791 p = nasm_skip_spaces(ep);
1792 if (*p == ',')
1793 p = nasm_skip_spaces(++p);
1796 rv = DIRR_OK;
1798 err:
1799 nasm_free(s);
1800 return rv;
1804 * Mach-O pragmas
1806 static enum directive_result
1807 macho_pragma(const struct pragma *pragma)
1809 bool real = passn > 1;
1811 switch (pragma->opcode) {
1812 case D_SUBSECTIONS_VIA_SYMBOLS:
1813 if (*pragma->tail)
1814 return DIRR_BADPARAM;
1816 if (real)
1817 head_flags |= MH_SUBSECTIONS_VIA_SYMBOLS;
1819 /* Jmp-match optimization conflicts */
1820 optimizing.flag |= OPTIM_DISABLE_JMP_MATCH;
1822 return DIRR_OK;
1824 case D_NO_DEAD_STRIP:
1825 return macho_no_dead_strip(pragma->tail);
1827 default:
1828 return DIRR_UNKNOWN; /* Not a Mach-O directive */
1832 static const struct pragma_facility macho_pragma_list[] = {
1833 { "macho", macho_pragma },
1834 { NULL, macho_pragma } /* Implements macho32/macho64 namespaces */
1837 static void macho_dbg_generate(void)
1839 uint8_t *p_buf = NULL, *p_buf_base = NULL;
1840 size_t saa_len = 0, high_addr = 0, total_len = 0;
1841 struct section *p_section = NULL;
1842 /* calculated at debug_str and referenced at debug_info */
1843 uint32_t producer_str_offset = 0, module_str_offset = 0, dir_str_offset = 0;
1845 /* debug section defines */
1847 int bits = 0;
1848 macho_section(".debug_abbrev", 0, &bits);
1849 macho_section(".debug_info", 0, &bits);
1850 macho_section(".debug_line", 0, &bits);
1851 macho_section(".debug_str", 0, &bits);
1854 /* dw section walk to find high_addr and total_len */
1856 struct dw_sect_list *p_sect;
1858 list_for_each(p_sect, dw_head_sect) {
1859 uint64_t offset = get_section_by_index(p_sect->section)->size;
1860 struct SAA *p_linep = p_sect->psaa;
1862 saa_write8(p_linep, 2); /* std op 2 */
1863 saa_write8(p_linep, offset - p_sect->offset);
1864 saa_write8(p_linep, DW_LNS_extended_op);
1865 saa_write8(p_linep, 1); /* operand length */
1866 saa_write8(p_linep, DW_LNE_end_sequence);
1868 total_len += p_linep->datalen;
1869 high_addr += offset;
1873 /* debug line */
1875 struct dw_sect_list *p_sect;
1876 size_t linep_off, buf_size;
1877 struct SAA *p_lines = saa_init(1L);
1878 struct dir_list *p_dir;
1879 struct file_list *p_file;
1881 p_section = get_section_by_name("__DWARF", "__debug_line");
1882 nasm_assert(p_section != NULL);
1884 saa_write8(p_lines, 1); /* minimum instruction length */
1885 saa_write8(p_lines, 1); /* initial value of "is_stmt" */
1886 saa_write8(p_lines, DW_LN_BASE); /* line base */
1887 saa_write8(p_lines, DW_LN_RANGE); /* line range */
1888 saa_write8(p_lines, DW_OPCODE_BASE); /* opcode base */
1889 saa_write8(p_lines, 0); /* std opcode 1 length */
1890 saa_write8(p_lines, 1); /* std opcode 2 length */
1891 saa_write8(p_lines, 1); /* std opcode 3 length */
1892 saa_write8(p_lines, 1); /* std opcode 4 length */
1893 saa_write8(p_lines, 1); /* std opcode 5 length */
1894 saa_write8(p_lines, 0); /* std opcode 6 length */
1895 saa_write8(p_lines, 0); /* std opcode 7 length */
1896 saa_write8(p_lines, 0); /* std opcode 8 length */
1897 saa_write8(p_lines, 1); /* std opcode 9 length */
1898 saa_write8(p_lines, 0); /* std opcode 10 length */
1899 saa_write8(p_lines, 0); /* std opcode 11 length */
1900 saa_write8(p_lines, 1); /* std opcode 12 length */
1901 list_for_each(p_dir, dw_head_dir) {
1902 saa_wcstring(p_lines, p_dir->dir_name);
1904 saa_write8(p_lines, 0); /* end of table */
1906 list_for_each(p_file, dw_head_file) {
1907 saa_wcstring(p_lines, p_file->file_name);
1908 saa_write8(p_lines, p_file->dir->dir); /* directory id */
1909 saa_write8(p_lines, 0); /* time */
1910 saa_write8(p_lines, 0); /* size */
1912 saa_write8(p_lines, 0); /* end of table */
1914 linep_off = p_lines->datalen;
1915 /* 10 bytes for initial & prolong length, and dwarf version info */
1916 buf_size = saa_len = linep_off + total_len + 10;
1917 p_buf_base = p_buf = nasm_malloc(buf_size);
1919 WRITELONG(p_buf, saa_len - 4); /* initial length; size excluding itself */
1920 WRITESHORT(p_buf, 2); /* dwarf version */
1921 WRITELONG(p_buf, linep_off); /* prolong length */
1923 saa_rnbytes(p_lines, p_buf, linep_off);
1924 p_buf += linep_off;
1925 saa_free(p_lines);
1927 list_for_each(p_sect, dw_head_sect) {
1928 struct SAA *p_linep = p_sect->psaa;
1930 saa_len = p_linep->datalen;
1931 saa_rnbytes(p_linep, p_buf, saa_len);
1932 p_buf += saa_len;
1934 saa_free(p_linep);
1937 macho_output(p_section->index, p_buf_base, OUT_RAWDATA, buf_size, NO_SEG, 0);
1939 nasm_free(p_buf_base);
1942 /* string section */
1944 struct SAA *p_str = saa_init(1L);
1945 char *cur_path = nasm_realpath(module_name);
1946 char *cur_file = nasm_basename(cur_path);
1947 char *cur_dir = nasm_dirname(cur_path);
1949 p_section = get_section_by_name("__DWARF", "__debug_str");
1950 nasm_assert(p_section != NULL);
1952 producer_str_offset = 0;
1953 module_str_offset = dir_str_offset = saa_wcstring(p_str, nasm_signature());
1954 dir_str_offset += saa_wcstring(p_str, cur_file);
1955 saa_wcstring(p_str, cur_dir);
1957 saa_len = p_str->datalen;
1958 p_buf = nasm_malloc(saa_len);
1959 saa_rnbytes(p_str, p_buf, saa_len);
1960 macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0);
1962 nasm_free(cur_path);
1963 nasm_free(cur_file);
1964 nasm_free(cur_dir);
1965 saa_free(p_str);
1966 nasm_free(p_buf);
1969 /* debug info */
1971 struct SAA *p_info = saa_init(1L);
1973 p_section = get_section_by_name("__DWARF", "__debug_info");
1974 nasm_assert(p_section != NULL);
1976 /* size will be overwritten once determined, so skip in p_info layout */
1977 saa_write16(p_info, 2); /* dwarf version */
1978 saa_write32(p_info, 0); /* offset info abbrev */
1979 saa_write8(p_info, (ofmt == &of_macho64) ? 8 : 4); /* pointer size */
1981 saa_write8(p_info, 1); /* abbrev entry number */
1983 saa_write32(p_info, producer_str_offset); /* offset from string table for DW_AT_producer */
1984 saa_write16(p_info, DW_LANG_Mips_Assembler); /* DW_AT_language */
1985 saa_write32(p_info, module_str_offset); /* offset from string table for DW_AT_name */
1986 saa_write32(p_info, dir_str_offset); /* offset from string table for DW_AT_comp_dir */
1987 saa_write32(p_info, 0); /* DW_AT_stmt_list */
1989 if (ofmt == &of_macho64) {
1990 saa_write64(p_info, 0); /* DW_AT_low_pc */
1991 saa_write64(p_info, high_addr); /* DW_AT_high_pc */
1992 } else {
1993 saa_write32(p_info, 0); /* DW_AT_low_pc */
1994 saa_write32(p_info, high_addr); /* DW_AT_high_pc */
1997 saa_write8(p_info, 2); /* abbrev entry number */
1999 if (ofmt == &of_macho64) {
2000 saa_write64(p_info, 0); /* DW_AT_low_pc */
2001 saa_write64(p_info, 0); /* DW_AT_frame_base */
2002 } else {
2003 saa_write32(p_info, 0); /* DW_AT_low_pc */
2004 saa_write32(p_info, 0); /* DW_AT_frame_base */
2006 saa_write8(p_info, DW_END_default);
2008 saa_len = p_info->datalen;
2009 p_buf_base = p_buf = nasm_malloc(saa_len + 4); /* 4B for size info */
2011 WRITELONG(p_buf, saa_len);
2012 saa_rnbytes(p_info, p_buf, saa_len);
2013 macho_output(p_section->index, p_buf_base, OUT_RAWDATA, saa_len + 4, NO_SEG, 0);
2015 saa_free(p_info);
2016 nasm_free(p_buf_base);
2019 /* abbrev section */
2021 struct SAA *p_abbrev = saa_init(1L);
2023 p_section = get_section_by_name("__DWARF", "__debug_abbrev");
2024 nasm_assert(p_section != NULL);
2026 saa_write8(p_abbrev, 1); /* entry number */
2028 saa_write8(p_abbrev, DW_TAG_compile_unit);
2029 saa_write8(p_abbrev, DW_CHILDREN_yes);
2031 saa_write8(p_abbrev, DW_AT_producer);
2032 saa_write8(p_abbrev, DW_FORM_strp);
2034 saa_write8(p_abbrev, DW_AT_language);
2035 saa_write8(p_abbrev, DW_FORM_data2);
2037 saa_write8(p_abbrev, DW_AT_name);
2038 saa_write8(p_abbrev, DW_FORM_strp);
2040 saa_write8(p_abbrev, DW_AT_comp_dir);
2041 saa_write8(p_abbrev, DW_FORM_strp);
2043 saa_write8(p_abbrev, DW_AT_stmt_list);
2044 saa_write8(p_abbrev, DW_FORM_data4);
2046 saa_write8(p_abbrev, DW_AT_low_pc);
2047 saa_write8(p_abbrev, DW_FORM_addr);
2049 saa_write8(p_abbrev, DW_AT_high_pc);
2050 saa_write8(p_abbrev, DW_FORM_addr);
2052 saa_write16(p_abbrev, DW_END_default);
2054 saa_write8(p_abbrev, 2); /* entry number */
2056 saa_write8(p_abbrev, DW_TAG_subprogram);
2057 saa_write8(p_abbrev, DW_CHILDREN_no);
2059 saa_write8(p_abbrev, DW_AT_low_pc);
2060 saa_write8(p_abbrev, DW_FORM_addr);
2062 saa_write8(p_abbrev, DW_AT_frame_base);
2063 saa_write8(p_abbrev, DW_FORM_addr);
2065 saa_write16(p_abbrev, DW_END_default);
2067 saa_write8(p_abbrev, 0); /* Terminal zero entry */
2069 saa_len = p_abbrev->datalen;
2071 p_buf = nasm_malloc(saa_len);
2073 saa_rnbytes(p_abbrev, p_buf, saa_len);
2074 macho_output(p_section->index, p_buf, OUT_RAWDATA, saa_len, NO_SEG, 0);
2076 saa_free(p_abbrev);
2077 nasm_free(p_buf);
2081 static void new_file_list (const char *file_name, const char *dir_name)
2083 struct dir_list *dir_list;
2084 bool need_new_dir_list = true;
2086 nasm_new(dw_cur_file);
2087 dw_cur_file->file = ++dw_num_files;
2088 dw_cur_file->file_name = file_name;
2089 if(!dw_head_file) {
2090 dw_head_file = dw_cur_file;
2091 } else {
2092 *dw_last_file_next = dw_cur_file;
2094 dw_last_file_next = &(dw_cur_file->next);
2096 if(dw_head_dir) {
2097 list_for_each(dir_list, dw_head_dir) {
2098 if(!(strcmp(dir_name, dir_list->dir_name))) {
2099 dw_cur_file->dir = dir_list;
2100 need_new_dir_list = false;
2101 break;
2106 if(need_new_dir_list)
2108 nasm_new(dir_list);
2109 dir_list->dir = dw_num_dirs++;
2110 dir_list->dir_name = dir_name;
2111 if(!dw_head_dir) {
2112 dw_head_dir = dir_list;
2113 } else {
2114 *dw_last_dir_next = dir_list;
2116 dw_last_dir_next = &(dir_list->next);
2117 dw_cur_file->dir = dir_list;
2121 static void macho_dbg_init(void)
2125 static void macho_dbg_linenum(const char *file_name, int32_t line_num, int32_t segto)
2127 bool need_new_list = true;
2128 const char *cur_file = nasm_basename(file_name);
2129 const char *cur_dir = nasm_dirname(file_name);
2130 (void)segto;
2132 if(!dw_cur_file || strcmp(cur_file, dw_cur_file->file_name) ||
2133 strcmp(cur_dir, dw_cur_file->dir->dir_name)) {
2134 if(dw_head_file) {
2135 struct file_list *match;
2137 list_for_each(match, dw_head_file) {
2138 if(!(strcmp(cur_file, match->file_name)) &&
2139 !(strcmp(cur_dir, match->dir->dir_name))) {
2140 dw_cur_file = match;
2141 dw_cur_file->dir = match->dir;
2142 need_new_list = false;
2143 break;
2148 if(need_new_list) {
2149 new_file_list(cur_file, cur_dir);
2153 dbg_immcall = true;
2154 cur_line = line_num;
2157 static void macho_dbg_output(int type, void *param)
2159 struct section_info *sinfo_param = (struct section_info *)param;
2160 int32_t secto = sinfo_param->secto;
2161 bool need_new_sect = false;
2162 struct SAA *p_linep = NULL;
2163 (void)type;
2165 if(!(dw_cur_sect && (dw_cur_sect->section == secto))) {
2166 need_new_sect = true;
2167 if(dw_head_sect) {
2168 struct dw_sect_list *match = dw_head_sect;
2169 uint32_t idx = 0;
2171 for(; idx < dw_num_sects; idx++) {
2172 if(match->section == secto) {
2173 dw_cur_sect = match;
2174 need_new_sect = false;
2175 break;
2177 match = match->next;
2182 if(need_new_sect) {
2183 nasm_new(dw_cur_sect);
2184 dw_num_sects ++;
2185 p_linep = dw_cur_sect->psaa = saa_init(1L);
2186 dw_cur_sect->line = dw_cur_sect->file = 1;
2187 dw_cur_sect->offset = 0;
2188 dw_cur_sect->next = NULL;
2189 dw_cur_sect->section = secto;
2191 saa_write8(p_linep, DW_LNS_extended_op);
2192 saa_write8(p_linep, (ofmt == &of_macho64) ? 9 : 5);
2193 saa_write8(p_linep, DW_LNE_set_address);
2194 if (ofmt == &of_macho64) {
2195 saa_write64(p_linep, 0);
2196 } else {
2197 saa_write32(p_linep, 0);
2200 if(!dw_head_sect) {
2201 dw_head_sect = dw_last_sect = dw_cur_sect;
2202 } else {
2203 dw_last_sect->next = dw_cur_sect;
2204 dw_last_sect = dw_cur_sect;
2208 if(dbg_immcall == true) {
2209 int32_t line_delta = cur_line - dw_cur_sect->line;
2210 int32_t offset_delta = sinfo_param->size - dw_cur_sect->offset;
2211 uint32_t cur_file = dw_cur_file->file;
2212 p_linep = dw_cur_sect->psaa;
2214 if(cur_file != dw_cur_sect->file) {
2215 saa_write8(p_linep, DW_LNS_set_file);
2216 saa_write8(p_linep, cur_file);
2217 dw_cur_sect->file = cur_file;
2220 if(line_delta) {
2221 int special_opcode = (line_delta - DW_LN_BASE) + (DW_LN_RANGE * offset_delta) +
2222 DW_OPCODE_BASE;
2224 if((line_delta >= DW_LN_BASE) && (line_delta < DW_MAX_LN) &&
2225 (special_opcode < DW_MAX_SP_OPCODE)) {
2226 saa_write8(p_linep, special_opcode);
2227 } else {
2228 saa_write8(p_linep, DW_LNS_advance_line);
2229 saa_wleb128s(p_linep, line_delta);
2230 if(offset_delta) {
2231 saa_write8(p_linep, DW_LNS_advance_pc);
2232 saa_wleb128u(p_linep, offset_delta);
2234 saa_write8(p_linep, DW_LNS_copy);
2237 dw_cur_sect->line = cur_line;
2238 dw_cur_sect->offset = sinfo_param->size;
2241 dbg_immcall = false;
2245 static void macho_dbg_cleanup(void)
2247 /* dwarf sectors generation */
2248 macho_dbg_generate();
2251 struct dw_sect_list *p_sect = dw_head_sect;
2252 struct file_list *p_file = dw_head_file;
2253 uint32_t idx = 0;
2255 for(; idx < dw_num_sects; idx++) {
2256 struct dw_sect_list *next = p_sect->next;
2257 nasm_free(p_sect);
2258 p_sect = next;
2261 for(idx = 0; idx < dw_num_files; idx++) {
2262 struct file_list *next = p_file->next;
2263 nasm_free(p_file);
2264 p_file = next;
2269 #ifdef OF_MACHO32
2270 static const struct macho_fmt macho32_fmt = {
2272 MH_MAGIC,
2273 CPU_TYPE_I386,
2274 LC_SEGMENT,
2275 MACHO_HEADER_SIZE,
2276 MACHO_SEGCMD_SIZE,
2277 MACHO_SECTCMD_SIZE,
2278 MACHO_NLIST_SIZE,
2279 RL_MAX_32,
2280 GENERIC_RELOC_VANILLA,
2281 GENERIC_RELOC_VANILLA,
2282 GENERIC_RELOC_TLV,
2283 false /* Allow segment-relative relocations */
2286 static void macho32_init(void)
2288 fmt = macho32_fmt;
2289 macho_init();
2291 macho_gotpcrel_sect = NO_SEG;
2294 static const struct dfmt macho32_df_dwarf = {
2295 "MachO32 (i386) dwarf debug format for Darwin/MacOS",
2296 "dwarf",
2297 macho_dbg_init,
2298 macho_dbg_linenum,
2299 null_debug_deflabel,
2300 null_debug_directive,
2301 null_debug_typevalue,
2302 macho_dbg_output,
2303 macho_dbg_cleanup,
2304 NULL /*pragma list*/
2307 static const struct dfmt * const macho32_df_arr[2] =
2308 { &macho32_df_dwarf, NULL };
2310 const struct ofmt of_macho32 = {
2311 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (i386) object files",
2312 "macho32",
2313 ".o",
2316 macho32_df_arr,
2317 &macho32_df_dwarf,
2318 macho_stdmac,
2319 macho32_init,
2320 null_reset,
2321 nasm_do_legacy_output,
2322 macho_output,
2323 macho_symdef,
2324 macho_section,
2325 macho_herelabel,
2326 macho_sectalign,
2327 null_segbase,
2328 null_directive,
2329 macho_cleanup,
2330 macho_pragma_list
2332 #endif
2334 #ifdef OF_MACHO64
2335 static const struct macho_fmt macho64_fmt = {
2337 MH_MAGIC_64,
2338 CPU_TYPE_X86_64,
2339 LC_SEGMENT_64,
2340 MACHO_HEADER64_SIZE,
2341 MACHO_SEGCMD64_SIZE,
2342 MACHO_SECTCMD64_SIZE,
2343 MACHO_NLIST64_SIZE,
2344 RL_MAX_64,
2345 X86_64_RELOC_UNSIGNED,
2346 X86_64_RELOC_SIGNED,
2347 X86_64_RELOC_TLV,
2348 true /* Force symbol-relative relocations */
2351 static void macho64_init(void)
2353 fmt = macho64_fmt;
2354 macho_init();
2356 /* add special symbol for ..gotpcrel */
2357 macho_gotpcrel_sect = seg_alloc() + 1;
2358 backend_label("..gotpcrel", macho_gotpcrel_sect, 0L);
2361 static const struct dfmt macho64_df_dwarf = {
2362 "MachO64 (x86-64) dwarf debug format for Darwin/MacOS",
2363 "dwarf",
2364 macho_dbg_init,
2365 macho_dbg_linenum,
2366 null_debug_deflabel,
2367 null_debug_directive,
2368 null_debug_typevalue,
2369 macho_dbg_output,
2370 macho_dbg_cleanup,
2371 NULL /*pragma list*/
2374 static const struct dfmt * const macho64_df_arr[2] =
2375 { &macho64_df_dwarf, NULL };
2377 const struct ofmt of_macho64 = {
2378 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files",
2379 "macho64",
2380 ".o",
2383 macho64_df_arr,
2384 &macho64_df_dwarf,
2385 macho_stdmac,
2386 macho64_init,
2387 null_reset,
2388 nasm_do_legacy_output,
2389 macho_output,
2390 macho_symdef,
2391 macho_section,
2392 macho_herelabel,
2393 macho_sectalign,
2394 null_segbase,
2395 null_directive,
2396 macho_cleanup,
2397 macho_pragma_list,
2399 #endif
2401 #endif
2404 * Local Variables:
2405 * mode:c
2406 * c-basic-offset:4
2407 * End:
2409 * end of file */