Changes to be committed:
[nasm.git] / output / outmacho64.c
blob79b6a451af306abdb66c14917f316a559aea94fb
1 /* outmacho64.c output routines for the Netwide Assembler to produce
2 * NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files
4 * The Netwide Assembler is copyright (C) 1996 Simon Tatham and
5 * Julian Hall. All rights reserved. The software is
6 * redistributable under the license given in the file "LICENSE"
7 * distributed in the NASM archive.
8 */
10 /* Most of this file is, like Mach-O itself, based on a.out. For more
11 * guidelines see outaout.c. */
13 #include "compiler.h"
15 #include <stdio.h>
16 #include <stdlib.h>
17 #include <string.h>
18 #include <ctype.h>
19 #include <inttypes.h>
21 #include "nasm.h"
22 #include "nasmlib.h"
23 #include "saa.h"
24 #include "raa.h"
25 #include "outform.h"
26 #include "compiler.h"
28 #if defined(OF_MACHO64)
30 /* Mach-O in-file header structure sizes */
31 #define MACHO_HEADER64_SIZE (32)
32 #define MACHO_SEGCMD64_SIZE (72)
33 #define MACHO_SECTCMD64_SIZE (80)
34 #define MACHO_SYMCMD_SIZE (24)
35 #define MACHO_NLIST64_SIZE (16)
36 #define MACHO_RELINFO64_SIZE (8)
38 /* Mach-O file header values */
39 #define MH_MAGIC_64 (0xfeedfacf)
40 #define CPU_TYPE_X86_64 (0x01000007) /* x86-64 platform */
41 #define CPU_SUBTYPE_I386_ALL (3) /* all-x86 compatible */
42 #define MH_OBJECT (0x1) /* object file */
44 #define LC_SEGMENT_64 (0x19) /* segment load command */
45 #define LC_SYMTAB (0x2) /* symbol table load command */
47 #define VM_PROT_NONE (0x00)
48 #define VM_PROT_READ (0x01)
49 #define VM_PROT_WRITE (0x02)
50 #define VM_PROT_EXECUTE (0x04)
52 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
53 #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
55 struct section {
56 /* nasm internal data */
57 struct section *next;
58 struct SAA *data;
59 int32_t index;
60 struct reloc *relocs;
61 int align;
63 /* data that goes into the file */
64 char sectname[16]; /* what this section is called */
65 char segname[16]; /* segment this section will be in */
66 uint64_t size; /* in-memory and -file size */
67 uint32_t nreloc; /* relocation entry count */
68 uint32_t flags; /* type and attributes (masked) */
71 #define SECTION_TYPE 0x000000ff /* section type mask */
73 #define S_REGULAR (0x0) /* standard section */
74 #define S_ZEROFILL (0x1) /* zerofill, in-memory only */
76 #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
77 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
78 machine instructions */
79 #define S_ATTR_EXT_RELOC 0x00000200 /* section has external
80 relocation entries */
81 #define S_ATTR_LOC_RELOC 0x00000100 /* section has local
82 relocation entries */
83 #define S_ATTR_PURE_INSTRUCTIONS 0x80000000 /* section uses pure
84 machine instructions */
86 static struct sectmap {
87 const char *nasmsect;
88 const char *segname;
89 const char *sectname;
90 const int32_t flags;
91 } sectmap[] = {
92 {".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS|S_ATTR_PURE_INSTRUCTIONS},
93 {".data", "__DATA", "__data", S_REGULAR},
94 {".rodata", "__DATA", "__const", S_REGULAR},
95 {".bss", "__DATA", "__bss", S_ZEROFILL},
96 {NULL, NULL, NULL, 0}
99 struct reloc {
100 /* nasm internal data */
101 struct reloc *next;
103 /* data that goes into the file */
104 int32_t addr; /* op's offset in section */
105 uint32_t snum:24, /* contains symbol index if
106 ** ext otherwise in-file
107 ** section number */
108 pcrel:1, /* relative relocation */
109 length:2, /* 0=byte, 1=word, 2=int32_t, 3=int64_t */
110 ext:1, /* external symbol referenced */
111 type:4; /* reloc type */
114 #define R_ABS 0 /* absolute relocation */
115 #define R_SCATTERED 0x80000000 /* reloc entry is scattered if
116 ** highest bit == 1 */
118 struct symbol {
119 /* nasm internal data */
120 struct symbol *next; /* next symbol in the list */
121 char *name; /* name of this symbol */
122 int32_t initial_snum; /* symbol number used above in
123 reloc */
124 int32_t snum; /* true snum for reloc */
126 /* data that goes into the file */
127 uint32_t strx; /* string table index */
128 uint8_t type; /* symbol type */
129 uint8_t sect; /* NO_SECT or section number */
130 int16_t desc; /* for stab debugging, 0 for us */
131 uint64_t value; /* offset of symbol in section */
134 /* symbol type bits */
135 #define N_EXT 0x01 /* global or external symbol */
137 #define N_UNDF 0x0 /* undefined symbol | n_sect == */
138 #define N_ABS 0x2 /* absolute symbol | NO_SECT */
139 #define N_SECT 0xe /* defined symbol, n_sect holds
140 ** section number */
142 #define N_TYPE 0x0e /* type bit mask */
144 #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
146 /* special section number values */
147 #define NO_SECT 0 /* no section, invalid */
148 #define MAX_SECT 255 /* maximum number of sections */
150 static struct section *sects, **sectstail;
151 static struct symbol *syms, **symstail;
152 static uint32_t nsyms;
154 /* These variables are set by macho_layout_symbols() to organize
155 the symbol table and string table in order the dynamic linker
156 expects. They are then used in macho_write() to put out the
157 symbols and strings in that order.
159 The order of the symbol table is:
160 local symbols
161 defined external symbols (sorted by name)
162 undefined external symbols (sorted by name)
164 The order of the string table is:
165 strings for external symbols
166 strings for local symbols
168 static uint32_t ilocalsym = 0;
169 static uint32_t iextdefsym = 0;
170 static uint32_t iundefsym = 0;
171 static uint32_t nlocalsym;
172 static uint32_t nextdefsym;
173 static uint32_t nundefsym;
174 static struct symbol **extdefsyms = NULL;
175 static struct symbol **undefsyms = NULL;
177 static struct RAA *extsyms;
178 static struct SAA *strs;
179 static uint32_t strslen;
181 static FILE *machofp;
182 static efunc error;
183 static evalfunc evaluate;
185 extern struct ofmt of_macho;
187 /* Global file information. This should be cleaned up into either
188 a structure or as function arguments. */
189 uint32_t head_ncmds64 = 0;
190 uint32_t head_sizeofcmds64 = 0;
191 uint64_t seg_filesize64 = 0;
192 uint64_t seg_vmsize64 = 0;
193 uint32_t seg_nsects64 = 0;
194 uint64_t rel_padcnt64 = 0;
197 #define xstrncpy(xdst, xsrc) \
198 memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \
199 strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \
200 xdst[sizeof(xdst) - 1] = '\0'; /* proper null-termination */
202 #define align(x, y) \
203 (((x) + (y) - 1) & ~((y) - 1)) /* align x to multiple of y */
205 #define alignint32_t(x) \
206 align(x, sizeof(int32_t)) /* align x to int32_t boundary */
208 #define alignint64_t(x) \
209 align(x, sizeof(int64_t)) /* align x to int64_t boundary */
211 static void debug_reloc (struct reloc *);
212 static void debug_section_relocs (struct section *) _unused;
214 static int exact_log2 (uint32_t align)
216 if (align == 0) {
217 return 0;
218 } else if (align & (align-1)) {
219 return -1; /* Not a power of 2 */
220 } else {
221 #ifdef HAVE_GNUC_4
222 return __builtin_ctzl (align);
223 #else
224 uint32_t result = 0;
226 /* We know exactly one bit is set at this point. */
227 if (align & 0xffff0000)
228 result |= 16;
229 if (align & 0xff00ff00)
230 result |= 8;
231 if (align & 0xf0f0f0f0)
232 result |= 4;
233 if (align & 0xcccccccc)
234 result |= 2;
235 if (align & 0xaaaaaaaa)
236 result |= 1;
238 return result;
239 #endif
243 static struct section *get_section_by_name(const char *segname,
244 const char *sectname)
246 struct section *s;
248 for (s = sects; s != NULL; s = s->next)
249 if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname))
250 break;
252 return s;
255 static struct section *get_section_by_index(const int32_t index)
257 struct section *s;
259 for (s = sects; s != NULL; s = s->next)
260 if (index == s->index)
261 break;
263 return s;
266 static int32_t get_section_index_by_name(const char *segname,
267 const char *sectname)
269 struct section *s;
271 for (s = sects; s != NULL; s = s->next)
272 if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname))
273 return s->index;
275 return -1;
278 static char *get_section_name_by_index(const int32_t index)
280 struct section *s;
282 for (s = sects; s != NULL; s = s->next)
283 if (index == s->index)
284 return s->sectname;
286 return NULL;
289 static uint8_t get_section_fileindex_by_index(const int32_t index)
291 struct section *s;
292 uint8_t i = 1;
294 for (s = sects; s != NULL && i < MAX_SECT; s = s->next, ++i)
295 if (index == s->index)
296 return i;
298 if (i == MAX_SECT)
299 error(ERR_WARNING,
300 "too many sections (>255) - clipped by fileindex");
302 return NO_SECT;
305 static void macho_init(FILE * fp, efunc errfunc, ldfunc ldef,
306 evalfunc eval)
308 char zero = 0;
310 maxbits = 64;
311 machofp = fp;
312 error = errfunc;
313 evaluate = eval;
315 (void)ldef; /* placate optimizers */
317 sects = NULL;
318 sectstail = &sects;
320 syms = NULL;
321 symstail = &syms;
322 nsyms = 0;
323 nlocalsym = 0;
324 nextdefsym = 0;
325 nundefsym = 0;
327 extsyms = raa_init();
328 strs = saa_init(1L);
330 /* string table starts with a zero byte - don't ask why */
331 saa_wbytes(strs, &zero, sizeof(char));
332 strslen = 1;
335 static int macho_setinfo(enum geninfo type, char **val)
337 (void)type;
338 (void)val;
339 return 0;
342 static void sect_write(struct section *sect,
343 const uint8_t *data, uint32_t len)
345 saa_wbytes(sect->data, data, len);
346 sect->size += len;
349 static void add_reloc(struct section *sect, int32_t section,
350 int pcrel, int bytes)
352 struct reloc *r;
353 int32_t fi;
355 /* NeXT as puts relocs in reversed order (address-wise) into the
356 ** files, so we do the same, doesn't seem to make much of a
357 ** difference either way */
358 r = nasm_malloc(sizeof(struct reloc));
359 r->next = sect->relocs;
360 sect->relocs = r;
362 /* the current end of the section will be the symbol's address for
363 ** now, might have to be fixed by macho_fixup_relocs() later on. make
364 ** sure we don't make the symbol scattered by setting the highest
365 ** bit by accident */
366 r->addr = sect->size & ~R_SCATTERED;
367 r->ext = 1;
368 r->pcrel = (pcrel ? 1 : 0);
370 /* match byte count 1, 2, 4, 8 to length codes 0, 1, 2, 3 respectively */
371 switch(bytes){
372 case 1:
373 r->length = 0;
374 break;
375 case 2:
376 r->length = 1;
377 break;
378 case 4:
379 r->length = 2;
380 break;
381 case 8:
382 r->length = 3;
383 break;
384 default:
385 break;
388 /* absolute relocation */
389 r->type = 0; // X86_64_RELOC_UNSIGNED
390 r->snum = R_ABS; // Absolute Symbol (indicates no relocation)
392 /* relative relocation */
393 if (pcrel == 1) {
395 /* intra-section */
396 if (section == NO_SEG) {
397 r->type = 1; // X86_64_RELOC_SIGNED
399 /* inter-section */
400 } else {
401 fi = get_section_fileindex_by_index(section);
403 /* external */
404 if (fi == NO_SECT) {
405 r->snum = raa_read(extsyms, section);
407 /* local */
408 } else {
409 r->type = 2; // X86_64_RELOC_BRANCH
410 r->snum = fi;
412 /* standard relocation */
413 r->type = 1; // X86_64_RELOC_SIGNED
418 /* subtractor */
419 } else if(pcrel == 2) {
420 r->type = 5; // X86_64_RELOC_SUBTRACTOR
422 ++sect->nreloc;
425 static void macho_output(int32_t secto, const void *data,
426 enum out_type type, uint64_t size,
427 int32_t section, int32_t wrt)
429 struct section *s, *sbss;
430 int32_t addr;
431 uint8_t mydata[8], *p;
433 if (wrt != NO_SEG) {
434 wrt = NO_SEG;
435 error(ERR_NONFATAL, "WRT not supported by Mach-O output format");
436 /* continue to do _something_ */
439 if (secto == NO_SEG) {
440 if (type != OUT_RESERVE)
441 error(ERR_NONFATAL, "attempt to assemble code in "
442 "[ABSOLUTE] space");
444 return;
447 s = get_section_by_index(secto);
449 if (s == NULL) {
450 error(ERR_WARNING, "attempt to assemble code in"
451 " section %d: defaulting to `.text'", secto);
452 s = get_section_by_name("__TEXT", "__text");
454 /* should never happen */
455 if (s == NULL)
456 error(ERR_PANIC, "text section not found");
459 sbss = get_section_by_name("__DATA", "__bss");
461 if (s == sbss && type != OUT_RESERVE) {
462 error(ERR_WARNING, "attempt to initialize memory in the"
463 " BSS section: ignored");
465 switch (type) {
466 case OUT_REL2ADR:
467 size = 2;
468 break;
470 case OUT_REL4ADR:
471 size = 4;
472 break;
474 default:
475 break;
478 s->size += size;
479 return;
482 switch (type) {
483 case OUT_RESERVE:
484 if (s != sbss) {
485 error(ERR_WARNING, "uninitialized space declared in"
486 " %s section: zeroing",
487 get_section_name_by_index(secto));
489 sect_write(s, NULL, size);
490 } else
491 s->size += size;
493 break;
495 case OUT_RAWDATA:
496 if (section != NO_SEG)
497 error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
499 sect_write(s, data, size);
500 break;
502 case OUT_ADDRESS:
503 addr = *(int64_t *)data;
505 if (section != NO_SEG) {
506 if (section % 2) {
507 error(ERR_NONFATAL, "Mach-O format does not support"
508 " section base references");
509 } else {
510 if (wrt == NO_SEG) {
511 if (size < 8) {
512 // add_reloc(s, section, 2, size);
513 // sect_write(s, data, size);
515 add_reloc(s, section, 0, size);
516 }else{
517 error(ERR_NONFATAL, "Mach-O format does not support"
518 " this... um... thingy right now...");
523 p = mydata;
524 WRITEADDR(p, addr, size);
525 sect_write(s, mydata, size);
526 break;
528 case OUT_REL2ADR:
529 if (section == secto)
530 error(ERR_PANIC, "intra-section OUT_REL2ADR");
532 if (section != NO_SEG && section % 2) {
533 error(ERR_NONFATAL, "Mach-O format does not support"
534 " section base references");
535 } else {
536 add_reloc(s, section, 1, 2);
539 p = mydata;
540 WRITESHORT(p, *(int32_t *)data - (size + s->size));
541 sect_write(s, mydata, 2L);
542 break;
544 case OUT_REL4ADR:
545 // if (section == secto)
546 // error(ERR_PANIC, "intra-section OUT_REL4ADR");
548 if (section != NO_SEG && section % 2) {
549 error(ERR_NONFATAL, "Mach-O format does not support"
550 " section base references");
551 } else {
552 add_reloc(s, section, 1, 4);
555 p = mydata;
556 WRITELONG(p, *(int32_t *)data - (size + s->size));
557 sect_write(s, mydata, 4L);
558 break;
560 default:
561 error(ERR_PANIC, "unknown output type?");
562 break;
566 static int32_t macho_section(char *name, int pass, int *bits)
568 int32_t index, originalIndex;
569 char *sectionAttributes;
570 struct sectmap *sm;
571 struct section *s;
573 (void)pass;
575 /* Default to 64 bits. */
576 if (!name) {
577 *bits = 64;
578 name = ".text";
579 sectionAttributes = NULL;
580 } else {
581 sectionAttributes = name;
582 name = nasm_strsep(&sectionAttributes, " \t");
585 for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
586 /* make lookup into section name translation table */
587 if (!strcmp(name, sm->nasmsect)) {
588 char *currentAttribute;
590 /* try to find section with that name */
591 originalIndex = index = get_section_index_by_name(sm->segname,
592 sm->sectname);
594 /* create it if it doesn't exist yet */
595 if (index == -1) {
596 s = *sectstail = nasm_malloc(sizeof(struct section));
597 s->next = NULL;
598 sectstail = &s->next;
600 s->data = saa_init(1L);
601 s->index = seg_alloc();
602 s->relocs = NULL;
603 s->align = -1;
605 xstrncpy(s->segname, sm->segname);
606 xstrncpy(s->sectname, sm->sectname);
607 s->size = 0;
608 s->nreloc = 0;
609 s->flags = sm->flags;
611 index = s->index;
612 } else {
613 s = get_section_by_index(index);
616 while ((NULL != sectionAttributes)
617 && (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
618 if (0 != *currentAttribute) {
619 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
620 char *end;
621 int newAlignment, value;
623 value = strtoul(currentAttribute + 6, (char**)&end, 0);
624 newAlignment = exact_log2(value);
626 if (0 != *end) {
627 error(ERR_PANIC,
628 "unknown or missing alignment value \"%s\" "
629 "specified for section \"%s\"",
630 currentAttribute + 6,
631 name);
632 return NO_SEG;
633 } else if (0 > newAlignment) {
634 error(ERR_PANIC,
635 "alignment of %d (for section \"%s\") is not "
636 "a power of two",
637 value,
638 name);
639 return NO_SEG;
642 if ((-1 != originalIndex)
643 && (s->align != newAlignment)
644 && (s->align != -1)) {
645 error(ERR_PANIC,
646 "section \"%s\" has already been specified "
647 "with alignment %d, conflicts with new "
648 "alignment of %d",
649 name,
650 (1 << s->align),
651 value);
652 return NO_SEG;
655 s->align = newAlignment;
656 } else if (!nasm_stricmp("data", currentAttribute)) {
657 /* Do nothing; 'data' is implicit */
658 } else {
659 error(ERR_PANIC,
660 "unknown section attribute %s for section %s",
661 currentAttribute,
662 name);
663 return NO_SEG;
668 return index;
672 error(ERR_PANIC, "invalid section name %s", name);
673 return NO_SEG;
676 static void macho_symdef(char *name, int32_t section, int64_t offset,
677 int is_global, char *special)
679 struct symbol *sym;
681 if (special) {
682 error(ERR_NONFATAL, "The Mach-O output format does "
683 "not support any special symbol types");
684 return;
687 if (is_global == 3) {
688 error(ERR_NONFATAL, "The Mach-O format does not "
689 "(yet) support forward reference fixups.");
690 return;
693 sym = *symstail = nasm_malloc(sizeof(struct symbol));
694 sym->next = NULL;
695 symstail = &sym->next;
697 sym->name = name;
698 sym->strx = strslen;
699 sym->type = 0;
700 sym->desc = 0;
701 sym->value = offset;
702 sym->initial_snum = -1;
704 /* external and common symbols get N_EXT */
705 if (is_global != 0) {
706 sym->type |= N_EXT;
709 if (section == NO_SEG) {
710 /* symbols in no section get absolute */
711 sym->type |= N_ABS;
712 sym->sect = NO_SECT;
713 } else {
714 sym->type |= N_SECT;
716 /* get the in-file index of the section the symbol was defined in */
717 sym->sect = get_section_fileindex_by_index(section);
719 if (sym->sect == NO_SECT) {
720 /* remember symbol number of references to external
721 ** symbols, this works because every external symbol gets
722 ** its own section number allocated internally by nasm and
723 ** can so be used as a key */
724 extsyms = raa_write(extsyms, section, nsyms);
725 sym->initial_snum = nsyms;
727 switch (is_global) {
728 case 1:
729 case 2:
730 /* there isn't actually a difference between global
731 ** and common symbols, both even have their size in
732 ** sym->value */
733 sym->type = N_EXT;
734 break;
736 default:
737 /* give an error on unfound section if it's not an
738 ** external or common symbol (assemble_file() does a
739 ** seg_alloc() on every call for them) */
740 error(ERR_PANIC, "in-file index for section %d not found",
741 section);
745 ++nsyms;
748 static int32_t macho_segbase(int32_t section)
750 return section;
753 static int macho_directive(char *directive, char *value, int pass)
755 (void)directive;
756 (void)value;
757 (void)pass;
758 return 0;
761 static void macho_filename(char *inname, char *outname, efunc error)
763 standard_extension(inname, outname, ".o", error);
766 extern macros_t macho_stdmac[];
768 /* Comparison function for qsort symbol layout. */
769 static int layout_compare (const struct symbol **s1,
770 const struct symbol **s2)
772 return (strcmp ((*s1)->name, (*s2)->name));
775 /* The native assembler does a few things in a similar function
777 * Remove temporary labels
778 * Sort symbols according to local, external, undefined (by name)
779 * Order the string table
781 We do not remove temporary labels right now.
783 numsyms is the total number of symbols we have. strtabsize is the
784 number entries in the string table. */
786 static void macho_layout_symbols (uint32_t *numsyms,
787 uint32_t *strtabsize)
789 struct symbol *sym, **symp;
790 uint32_t i,j;
792 *numsyms = 0;
793 *strtabsize = sizeof (char);
795 symp = &syms;
797 while ((sym = *symp)) {
798 /* Undefined symbols are now external. */
799 if (sym->type == N_UNDF)
800 sym->type |= N_EXT;
802 if ((sym->type & N_EXT) == 0) {
803 sym->snum = *numsyms;
804 *numsyms = *numsyms + 1;
805 nlocalsym++;
807 else {
808 if ((sym->type & N_TYPE) != N_UNDF)
809 nextdefsym++;
810 else
811 nundefsym++;
813 /* If we handle debug info we'll want
814 to check for it here instead of just
815 adding the symbol to the string table. */
816 sym->strx = *strtabsize;
817 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
818 *strtabsize += strlen(sym->name) + 1;
820 symp = &(sym->next);
823 /* Next, sort the symbols. Most of this code is a direct translation from
824 the Apple cctools symbol layout. We need to keep compatibility with that. */
825 /* Set the indexes for symbol groups into the symbol table */
826 ilocalsym = 0;
827 iextdefsym = nlocalsym;
828 iundefsym = nlocalsym + nextdefsym;
830 /* allocate arrays for sorting externals by name */
831 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
832 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
834 i = 0;
835 j = 0;
837 symp = &syms;
839 while ((sym = *symp)) {
841 if((sym->type & N_EXT) == 0) {
842 sym->strx = *strtabsize;
843 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
844 *strtabsize += strlen(sym->name) + 1;
846 else {
847 if((sym->type & N_TYPE) != N_UNDF)
848 extdefsyms[i++] = sym;
849 else
850 undefsyms[j++] = sym;
852 symp = &(sym->next);
855 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
856 (int (*)(const void *, const void *))layout_compare);
857 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
858 (int (*)(const void *, const void *))layout_compare);
860 for(i = 0; i < nextdefsym; i++) {
861 extdefsyms[i]->snum = *numsyms;
862 *numsyms += 1;
864 for(j = 0; j < nundefsym; j++) {
865 undefsyms[j]->snum = *numsyms;
866 *numsyms += 1;
870 /* Calculate some values we'll need for writing later. */
872 static void macho_calculate_sizes (void)
874 struct section *s;
876 /* count sections and calculate in-memory and in-file offsets */
877 for (s = sects; s != NULL; s = s->next) {
878 /* zerofill sections aren't actually written to the file */
879 if ((s->flags & SECTION_TYPE) != S_ZEROFILL)
880 seg_filesize64 += s->size;
882 seg_vmsize64 += s->size;
883 ++seg_nsects64;
886 /* calculate size of all headers, load commands and sections to
887 ** get a pointer to the start of all the raw data */
888 if (seg_nsects64 > 0) {
889 ++head_ncmds64;
890 head_sizeofcmds64 +=
891 MACHO_SEGCMD64_SIZE + seg_nsects64 * MACHO_SECTCMD64_SIZE;
894 if (nsyms > 0) {
895 ++head_ncmds64;
896 head_sizeofcmds64 += MACHO_SYMCMD_SIZE;
900 /* Write out the header information for the file. */
902 static void macho_write_header (void)
904 fwriteint32_t(MH_MAGIC_64, machofp); /* magic */
905 fwriteint32_t(CPU_TYPE_X86_64, machofp); /* CPU type */
906 fwriteint32_t(CPU_SUBTYPE_I386_ALL, machofp); /* CPU subtype */
907 fwriteint32_t(MH_OBJECT, machofp); /* Mach-O file type */
908 fwriteint32_t(head_ncmds64, machofp); /* number of load commands */
909 fwriteint32_t(head_sizeofcmds64, machofp); /* size of load commands */
910 fwriteint32_t(0, machofp); /* no flags */
911 fwriteint32_t(0, machofp); /* reserved for future use */
914 /* Write out the segment load command at offset. */
916 static uint32_t macho_write_segment (uint64_t offset)
918 uint64_t s_addr = 0;
919 uint64_t rel_base = alignint64_t (offset + seg_filesize64);
920 uint32_t s_reloff = 0;
921 struct section *s;
923 fwriteint32_t(LC_SEGMENT_64, machofp); /* cmd == LC_SEGMENT_64 */
925 /* size of load command including section load commands */
926 fwriteint32_t(MACHO_SEGCMD64_SIZE + seg_nsects64 *
927 MACHO_SECTCMD64_SIZE, machofp);
929 /* in an MH_OBJECT file all sections are in one unnamed (name
930 ** all zeros) segment */
931 fwrite("\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0", 16, 1, machofp);
932 fwriteint64_t(0, machofp); /* in-memory offset */
933 fwriteint64_t(seg_vmsize64, machofp); /* in-memory size */
934 fwriteint64_t(offset, machofp); /* in-file offset to data */
935 fwriteint64_t(seg_filesize64, machofp); /* in-file size */
936 fwriteint32_t(VM_PROT_DEFAULT, machofp); /* maximum vm protection */
937 fwriteint32_t(VM_PROT_DEFAULT, machofp); /* initial vm protection */
938 fwriteint32_t(seg_nsects64, machofp); /* number of sections */
939 fwriteint32_t(0, machofp); /* no flags */
941 /* emit section headers */
942 for (s = sects; s != NULL; s = s->next) {
943 fwrite(s->sectname, sizeof(s->sectname), 1, machofp);
944 fwrite(s->segname, sizeof(s->segname), 1, machofp);
945 fwriteint64_t(s_addr, machofp);
946 fwriteint64_t(s->size, machofp);
948 /* dummy data for zerofill sections or proper values */
949 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
950 fwriteint32_t(offset, machofp);
951 /* Write out section alignment, as a power of two.
952 e.g. 32-bit word alignment would be 2 (2^^2 = 4). */
953 if (s->align == -1)
954 s->align = DEFAULT_SECTION_ALIGNMENT;
955 fwriteint32_t(s->align, machofp);
956 /* To be compatible with cctools as we emit
957 a zero reloff if we have no relocations. */
958 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, machofp);
959 fwriteint32_t(s->nreloc, machofp);
961 offset += s->size;
962 s_reloff += s->nreloc * MACHO_RELINFO64_SIZE;
963 } else {
964 fwriteint32_t(0, machofp);
965 fwriteint32_t(0, machofp);
966 fwriteint32_t(0, machofp);
967 fwriteint32_t(0, machofp);
970 if(s->nreloc) s->flags |= S_ATTR_LOC_RELOC;
971 fwriteint32_t(s->flags, machofp); /* flags */
972 fwriteint32_t(0, machofp); /* reserved */
973 fwriteint32_t(0, machofp); /* reserved */
975 fwriteint32_t(0, machofp); /* align */
976 s_addr += s->size;
979 rel_padcnt64 = rel_base - offset;
980 offset = rel_base + s_reloff;
982 return offset;
985 /* For a given chain of relocs r, write out the entire relocation
986 chain to the object file. */
988 static void macho_write_relocs (struct reloc *r)
990 while (r) {
991 uint32_t word2;
993 fwriteint32_t(r->addr, machofp); /* reloc offset */
995 word2 = r->snum;
996 word2 |= r->pcrel << 24;
997 word2 |= r->length << 25;
998 word2 |= r->ext << 27;
999 word2 |= r->type << 28;
1000 fwriteint32_t(word2, machofp); /* reloc data */
1002 r = r->next;
1006 /* Write out the section data. */
1007 static void macho_write_section (void)
1009 struct section *s, *s2;
1010 struct reloc *r;
1011 char *rel_paddata = "\0\0\0\0\0\0\0";
1012 uint8_t fi, *p, *q, blk[8];
1013 int32_t len;
1014 int64_t l;
1016 for (s = sects; s != NULL; s = s->next) {
1017 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
1018 continue;
1020 /* no padding needs to be done to the sections */
1022 /* Like a.out Mach-O references things in the data or bss
1023 * sections by addresses which are actually relative to the
1024 * start of the _text_ section, in the _file_. See outaout.c
1025 * for more information. */
1026 saa_rewind(s->data);
1027 for (r = s->relocs; r != NULL; r = r->next) {
1028 len = (int32_t)r->length << 1;
1029 if(len > 4) len = 8;
1030 saa_fread(s->data, r->addr, blk, len);
1031 p = q = blk;
1032 l = *p++;
1034 /* get offset based on relocation type */
1035 if (r->length > 0) {
1036 l += ((int64_t)*p++) << 8;
1038 if (r->length > 1) {
1039 l += ((int64_t)*p++) << 16;
1040 l += ((int64_t)*p++) << 24;
1043 if (r->length > 2) {
1044 l += ((int64_t)*p++) << 32;
1045 l += ((int64_t)*p++) << 40;
1046 l += ((int64_t)*p++) << 48;
1047 l += ((int64_t)*p++) << 56;
1053 /* If the relocation is internal add to the current section
1054 offset. Otherwise the only value we need is the symbol
1055 offset which we already have. The linker takes care
1056 of the rest of the address. */
1057 if (!r->ext) {
1058 /* add sizes of previous sections to current offset */
1059 for (s2 = sects, fi = 1;
1060 s2 != NULL && fi < r->snum; s2 = s2->next, fi++)
1061 l += s2->size;
1064 /* write new offset back */
1065 if (r->length == 3)
1066 WRITEDLONG(q, l);
1067 else if (r->length == 2)
1068 WRITELONG(q, l);
1069 else if (r->length == 1)
1070 WRITESHORT(q, l);
1071 else
1072 *q++ = l & 0xFF;
1074 saa_fwrite(s->data, r->addr, blk, len);
1077 /* dump the section data to file */
1078 saa_fpwrite(s->data, machofp);
1081 /* pad last section up to reloc entries on int64_t boundary */
1082 fwrite(rel_paddata, rel_padcnt64, 1, machofp);
1084 /* emit relocation entries */
1085 for (s = sects; s != NULL; s = s->next)
1086 macho_write_relocs (s->relocs);
1089 /* Write out the symbol table. We should already have sorted this
1090 before now. */
1091 static void macho_write_symtab (void)
1093 struct symbol *sym;
1094 struct section *s;
1095 int64_t fi;
1096 uint64_t i;
1098 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1100 for (sym = syms; sym != NULL; sym = sym->next) {
1101 if ((sym->type & N_EXT) == 0) {
1102 fwriteint32_t(sym->strx, machofp); /* string table entry number */
1103 fwrite(&sym->type, 1, 1, machofp); /* symbol type */
1104 fwrite(&sym->sect, 1, 1, machofp); /* section */
1105 fwriteint16_t(sym->desc, machofp); /* description */
1107 /* Fix up the symbol value now that we know the final section
1108 sizes. */
1109 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1110 for (s = sects, fi = 1;
1111 s != NULL && fi < sym->sect; s = s->next, ++fi)
1112 sym->value += s->size;
1115 fwriteint64_t(sym->value, machofp); /* value (i.e. offset) */
1119 for (i = 0; i < nextdefsym; i++) {
1120 sym = extdefsyms[i];
1121 fwriteint32_t(sym->strx, machofp);
1122 fwrite(&sym->type, 1, 1, machofp); /* symbol type */
1123 fwrite(&sym->sect, 1, 1, machofp); /* section */
1124 fwriteint16_t(sym->desc, machofp); /* description */
1126 /* Fix up the symbol value now that we know the final section
1127 sizes. */
1128 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1129 for (s = sects, fi = 1;
1130 s != NULL && fi < sym->sect; s = s->next, ++fi)
1131 sym->value += s->size;
1134 fwriteint64_t(sym->value, machofp); /* value (i.e. offset) */
1137 for (i = 0; i < nundefsym; i++) {
1138 sym = undefsyms[i];
1139 fwriteint32_t(sym->strx, machofp);
1140 fwrite(&sym->type, 1, 1, machofp); // symbol type
1141 fwrite(&sym->sect, 1, 1, machofp); // section
1142 fwriteint16_t(sym->desc, machofp); // description
1144 // Fix up the symbol value now that we know the final section sizes.
1145 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1146 for (s = sects, fi = 1;
1147 s != NULL && fi < sym->sect; s = s->next, ++fi)
1148 sym->value += s->size;
1151 fwriteint64_t(sym->value, machofp); // value (i.e. offset)
1156 /* Fixup the snum in the relocation entries, we should be
1157 doing this only for externally undefined symbols. */
1158 static void macho_fixup_relocs (struct reloc *r)
1160 struct symbol *sym;
1161 uint32_t i;
1163 while (r != NULL) {
1164 if (r->ext) {
1165 for (i = 0; i < nundefsym; i++) {
1166 sym = undefsyms[i];
1167 if (sym->initial_snum == r->snum) {
1168 r->snum = sym->snum;
1169 break;
1173 r = r->next;
1177 /* Write out the object file. */
1179 static void macho_write (void)
1181 uint64_t offset = 0;
1183 /* mach-o object file structure:
1185 ** mach header
1186 ** uint32_t magic
1187 ** int cpu type
1188 ** int cpu subtype
1189 ** uint32_t mach file type
1190 ** uint32_t number of load commands
1191 ** uint32_t size of all load commands
1192 ** (includes section struct size of segment command)
1193 ** uint32_t flags
1195 ** segment command
1196 ** uint32_t command type == LC_SEGMENT_64
1197 ** uint32_t size of load command
1198 ** (including section load commands)
1199 ** char[16] segment name
1200 ** uint64_t in-memory offset
1201 ** uint64_t in-memory size
1202 ** uint64_t in-file offset to data area
1203 ** uint64_t in-file size
1204 ** (in-memory size excluding zerofill sections)
1205 ** int maximum vm protection
1206 ** int initial vm protection
1207 ** uint32_t number of sections
1208 ** uint32_t flags
1210 ** section commands
1211 ** char[16] section name
1212 ** char[16] segment name
1213 ** uint64_t in-memory offset
1214 ** uint64_t in-memory size
1215 ** uint32_t in-file offset
1216 ** uint32_t alignment
1217 ** (irrelevant in MH_OBJECT)
1218 ** uint32_t in-file offset of relocation entires
1219 ** uint32_t number of relocations
1220 ** uint32_t flags
1221 ** uint32_t reserved
1222 ** uint32_t reserved
1224 ** symbol table command
1225 ** uint32_t command type == LC_SYMTAB
1226 ** uint32_t size of load command
1227 ** uint32_t symbol table offset
1228 ** uint32_t number of symbol table entries
1229 ** uint32_t string table offset
1230 ** uint32_t string table size
1232 ** raw section data
1234 ** padding to int64_t boundary
1236 ** relocation data (struct reloc)
1237 ** int32_t offset
1238 ** uint data (symbolnum, pcrel, length, extern, type)
1240 ** symbol table data (struct nlist)
1241 ** int32_t string table entry number
1242 ** uint8_t type
1243 ** (extern, absolute, defined in section)
1244 ** uint8_t section
1245 ** (0 for global symbols, section number of definition (>= 1, <=
1246 ** 254) for local symbols, size of variable for common symbols
1247 ** [type == extern])
1248 ** int16_t description
1249 ** (for stab debugging format)
1250 ** uint64_t value (i.e. file offset) of symbol or stab offset
1252 ** string table data
1253 ** list of null-terminated strings
1256 /* Emit the Mach-O header. */
1257 macho_write_header();
1259 offset = MACHO_HEADER64_SIZE + head_sizeofcmds64;
1261 /* emit the segment load command */
1262 if (seg_nsects64 > 0)
1263 offset = macho_write_segment (offset);
1264 else
1265 error(ERR_WARNING, "no sections?");
1267 if (nsyms > 0) {
1268 /* write out symbol command */
1269 fwriteint32_t(LC_SYMTAB, machofp); /* cmd == LC_SYMTAB */
1270 fwriteint32_t(MACHO_SYMCMD_SIZE, machofp); /* size of load command */
1271 fwriteint32_t(offset, machofp); /* symbol table offset */
1272 fwriteint32_t(nsyms, machofp); /* number of symbol
1273 ** table entries */
1275 offset += nsyms * MACHO_NLIST64_SIZE;
1276 fwriteint32_t(offset, machofp); /* string table offset */
1277 fwriteint32_t(strslen, machofp); /* string table size */
1280 /* emit section data */
1281 if (seg_nsects64 > 0)
1282 macho_write_section ();
1284 /* emit symbol table if we have symbols */
1285 if (nsyms > 0)
1286 macho_write_symtab ();
1288 /* we don't need to pad here since MACHO_NLIST64_SIZE == 16 */
1290 /* emit string table */
1291 saa_fpwrite(strs, machofp);
1293 /* We do quite a bit here, starting with finalizing all of the data
1294 for the object file, writing, and then freeing all of the data from
1295 the file. */
1297 static void macho_cleanup(int debuginfo)
1299 struct section *s;
1300 struct reloc *r;
1301 struct symbol *sym;
1303 (void)debuginfo;
1305 /* Sort all symbols. */
1306 macho_layout_symbols (&nsyms, &strslen);
1308 /* Fixup relocation entries */
1309 for (s = sects; s != NULL; s = s->next) {
1310 macho_fixup_relocs (s->relocs);
1313 /* First calculate and finalize needed values. */
1314 macho_calculate_sizes();
1315 macho_write();
1317 /* done - yay! */
1318 fclose(machofp);
1320 /* free up everything */
1321 while (sects->next) {
1322 s = sects;
1323 sects = sects->next;
1325 saa_free(s->data);
1326 while (s->relocs != NULL) {
1327 r = s->relocs;
1328 s->relocs = s->relocs->next;
1329 nasm_free(r);
1332 nasm_free(s);
1335 saa_free(strs);
1336 raa_free(extsyms);
1338 if (syms) {
1339 while (syms->next) {
1340 sym = syms;
1341 syms = syms->next;
1343 nasm_free (sym);
1348 /* Debugging routines. */
1349 static void debug_reloc (struct reloc *r)
1351 fprintf (stdout, "reloc:\n");
1352 fprintf (stdout, "\taddr: %"PRId32"\n", r->addr);
1353 fprintf (stdout, "\tsnum: %d\n", r->snum);
1354 fprintf (stdout, "\tpcrel: %d\n", r->pcrel);
1355 fprintf (stdout, "\tlength: %d\n", r->length);
1356 fprintf (stdout, "\text: %d\n", r->ext);
1357 fprintf (stdout, "\ttype: %d\n", r->type);
1360 static void debug_section_relocs (struct section *s)
1362 struct reloc *r = s->relocs;
1364 fprintf (stdout, "relocs for section %s:\n\n", s->sectname);
1366 while (r != NULL) {
1367 debug_reloc (r);
1368 r = r->next;
1372 struct ofmt of_macho64 = {
1373 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X (x86_64) object files",
1374 "macho64",
1375 NULL,
1376 null_debug_arr,
1377 &null_debug_form,
1378 macho_stdmac,
1379 macho_init,
1380 macho_setinfo,
1381 macho_output,
1382 macho_symdef,
1383 macho_section,
1384 macho_segbase,
1385 macho_directive,
1386 macho_filename,
1387 macho_cleanup
1390 #endif
1393 * Local Variables:
1394 * mode:c
1395 * c-basic-offset:4
1396 * End:
1398 * end of file */