Beginnings of a crude utility to dump the contents of an OMF file
[nasm/avx512.git] / output / outmacho.c
blob74aecada8f1286c2d44c8dab4442b4c2bd11bb58
1 /* ----------------------------------------------------------------------- *
2 *
3 * Copyright 1996-2009 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 /* Most of this file is, like Mach-O itself, based on a.out. For more
40 * guidelines see outaout.c. */
42 #include "compiler.h"
44 #include <stdio.h>
45 #include <stdlib.h>
46 #include <string.h>
47 #include <ctype.h>
48 #include <inttypes.h>
50 #include "nasm.h"
51 #include "nasmlib.h"
52 #include "saa.h"
53 #include "raa.h"
54 #include "output/outform.h"
55 #include "output/outlib.h"
57 #if defined(OF_MACHO)
59 /* Mach-O in-file header structure sizes */
60 #define MACHO_HEADER_SIZE (28)
61 #define MACHO_SEGCMD_SIZE (56)
62 #define MACHO_SECTCMD_SIZE (68)
63 #define MACHO_SYMCMD_SIZE (24)
64 #define MACHO_NLIST_SIZE (12)
65 #define MACHO_RELINFO_SIZE (8)
67 /* Mach-O file header values */
68 #define MH_MAGIC (0xfeedface)
69 #define CPU_TYPE_I386 (7) /* x86 platform */
70 #define CPU_SUBTYPE_I386_ALL (3) /* all-x86 compatible */
71 #define MH_OBJECT (0x1) /* object file */
73 #define LC_SEGMENT (0x1) /* segment load command */
74 #define LC_SYMTAB (0x2) /* symbol table load command */
76 #define VM_PROT_NONE (0x00)
77 #define VM_PROT_READ (0x01)
78 #define VM_PROT_WRITE (0x02)
79 #define VM_PROT_EXECUTE (0x04)
81 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
82 #define VM_PROT_ALL (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
84 struct section {
85 /* nasm internal data */
86 struct section *next;
87 struct SAA *data;
88 int32_t index;
89 struct reloc *relocs;
90 int align;
92 /* data that goes into the file */
93 char sectname[16]; /* what this section is called */
94 char segname[16]; /* segment this section will be in */
95 uint32_t addr; /* in-memory address (subject to alignment) */
96 uint32_t size; /* in-memory and -file size */
97 uint32_t nreloc; /* relocation entry count */
98 uint32_t flags; /* type and attributes (masked) */
101 #define SECTION_TYPE 0x000000ff /* section type mask */
103 #define S_REGULAR (0x0) /* standard section */
104 #define S_ZEROFILL (0x1) /* zerofill, in-memory only */
106 #define SECTION_ATTRIBUTES_SYS 0x00ffff00 /* system setable attributes */
107 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400 /* section contains some
108 machine instructions */
109 #define S_ATTR_EXT_RELOC 0x00000200 /* section has external
110 relocation entries */
111 #define S_ATTR_LOC_RELOC 0x00000100 /* section has local
112 relocation entries */
115 static struct sectmap {
116 const char *nasmsect;
117 const char *segname;
118 const char *sectname;
119 const int32_t flags;
120 } sectmap[] = {
121 {".text", "__TEXT", "__text", S_REGULAR|S_ATTR_SOME_INSTRUCTIONS},
122 {".data", "__DATA", "__data", S_REGULAR},
123 {".rodata", "__DATA", "__const", S_REGULAR},
124 {".bss", "__DATA", "__bss", S_ZEROFILL},
125 {NULL, NULL, NULL, 0}
128 struct reloc {
129 /* nasm internal data */
130 struct reloc *next;
132 /* data that goes into the file */
133 int32_t addr; /* op's offset in section */
134 unsigned int snum:24, /* contains symbol index if
135 ** ext otherwise in-file
136 ** section number */
137 pcrel:1, /* relative relocation */
138 length:2, /* 0=byte, 1=word, 2=int32_t */
139 ext:1, /* external symbol referenced */
140 type:4; /* reloc type, 0 for us */
143 #define R_ABS 0 /* absolute relocation */
144 #define R_SCATTERED 0x80000000 /* reloc entry is scattered if
145 ** highest bit == 1 */
147 struct symbol {
148 /* nasm internal data */
149 struct symbol *next; /* next symbol in the list */
150 char *name; /* name of this symbol */
151 int32_t initial_snum; /* symbol number used above in
152 reloc */
153 int32_t snum; /* true snum for reloc */
155 /* data that goes into the file */
156 int32_t strx; /* string table index */
157 uint8_t type; /* symbol type */
158 uint8_t sect; /* NO_SECT or section number */
159 int16_t desc; /* for stab debugging, 0 for us */
160 uint32_t value; /* offset of symbol in section */
163 /* symbol type bits */
164 #define N_EXT 0x01 /* global or external symbol */
166 #define N_UNDF 0x0 /* undefined symbol | n_sect == */
167 #define N_ABS 0x2 /* absolute symbol | NO_SECT */
168 #define N_SECT 0xe /* defined symbol, n_sect holds
169 ** section number */
171 #define N_TYPE 0x0e /* type bit mask */
173 #define DEFAULT_SECTION_ALIGNMENT 0 /* byte (i.e. no) alignment */
175 /* special section number values */
176 #define NO_SECT 0 /* no section, invalid */
177 #define MAX_SECT 255 /* maximum number of sections */
179 static struct section *sects, **sectstail;
180 static struct symbol *syms, **symstail;
181 static uint32_t nsyms;
183 /* These variables are set by macho_layout_symbols() to organize
184 the symbol table and string table in order the dynamic linker
185 expects. They are then used in macho_write() to put out the
186 symbols and strings in that order.
188 The order of the symbol table is:
189 local symbols
190 defined external symbols (sorted by name)
191 undefined external symbols (sorted by name)
193 The order of the string table is:
194 strings for external symbols
195 strings for local symbols
197 static uint32_t ilocalsym = 0;
198 static uint32_t iextdefsym = 0;
199 static uint32_t iundefsym = 0;
200 static uint32_t nlocalsym;
201 static uint32_t nextdefsym;
202 static uint32_t nundefsym;
203 static struct symbol **extdefsyms = NULL;
204 static struct symbol **undefsyms = NULL;
206 static struct RAA *extsyms;
207 static struct SAA *strs;
208 static uint32_t strslen;
210 static FILE *machofp;
211 static efunc error;
212 static evalfunc evaluate;
214 extern struct ofmt of_macho;
216 /* Global file information. This should be cleaned up into either
217 a structure or as function arguments. */
218 uint32_t head_ncmds = 0;
219 uint32_t head_sizeofcmds = 0;
220 uint32_t seg_filesize = 0;
221 uint32_t seg_vmsize = 0;
222 uint32_t seg_nsects = 0;
223 uint32_t rel_padcnt = 0;
226 #define xstrncpy(xdst, xsrc) \
227 memset(xdst, '\0', sizeof(xdst)); /* zero out whole buffer */ \
228 strncpy(xdst, xsrc, sizeof(xdst)); /* copy over string */ \
229 xdst[sizeof(xdst) - 1] = '\0'; /* proper null-termination */
231 #define align(x, y) \
232 (((x) + (y) - 1) & ~((y) - 1)) /* align x to multiple of y */
234 #define alignint32_t(x) \
235 align(x, sizeof(int32_t)) /* align x to int32_t boundary */
237 static void debug_reloc (struct reloc *);
238 static void debug_section_relocs (struct section *) _unused;
240 static int exact_log2 (uint32_t align)
242 if (align == 0) {
243 return 0;
244 } else if (align & (align-1)) {
245 return -1; /* Not a power of 2 */
246 } else {
247 #ifdef HAVE_GNUC_4
248 return __builtin_ctzl (align);
249 #else
250 uint32_t result = 0;
252 /* We know exactly one bit is set at this point. */
253 if (align & 0xffff0000)
254 result |= 16;
255 if (align & 0xff00ff00)
256 result |= 8;
257 if (align & 0xf0f0f0f0)
258 result |= 4;
259 if (align & 0xcccccccc)
260 result |= 2;
261 if (align & 0xaaaaaaaa)
262 result |= 1;
264 return result;
265 #endif
269 static struct section *get_section_by_name(const char *segname,
270 const char *sectname)
272 struct section *s;
274 for (s = sects; s != NULL; s = s->next)
275 if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname))
276 break;
278 return s;
281 static struct section *get_section_by_index(const int32_t index)
283 struct section *s;
285 for (s = sects; s != NULL; s = s->next)
286 if (index == s->index)
287 break;
289 return s;
292 static int32_t get_section_index_by_name(const char *segname,
293 const char *sectname)
295 struct section *s;
297 for (s = sects; s != NULL; s = s->next)
298 if (!strcmp(s->segname, segname) && !strcmp(s->sectname, sectname))
299 return s->index;
301 return -1;
304 static char *get_section_name_by_index(const int32_t index)
306 struct section *s;
308 for (s = sects; s != NULL; s = s->next)
309 if (index == s->index)
310 return s->sectname;
312 return NULL;
315 static uint8_t get_section_fileindex_by_index(const int32_t index)
317 struct section *s;
318 uint8_t i = 1;
320 for (s = sects; s != NULL && i < MAX_SECT; s = s->next, ++i)
321 if (index == s->index)
322 return i;
324 if (i == MAX_SECT)
325 error(ERR_WARNING,
326 "too many sections (>255) - clipped by fileindex");
328 return NO_SECT;
331 static void macho_init(FILE * fp, efunc errfunc, ldfunc ldef,
332 evalfunc eval)
334 char zero = 0;
336 machofp = fp;
337 error = errfunc;
338 evaluate = eval;
340 (void)ldef; /* placate optimisers */
342 sects = NULL;
343 sectstail = &sects;
345 syms = NULL;
346 symstail = &syms;
347 nsyms = 0;
348 nlocalsym = 0;
349 nextdefsym = 0;
350 nundefsym = 0;
352 extsyms = raa_init();
353 strs = saa_init(1L);
355 /* string table starts with a zero byte - don't ask why */
356 saa_wbytes(strs, &zero, sizeof(char));
357 strslen = 1;
360 static int macho_setinfo(enum geninfo type, char **val)
362 (void)type;
363 (void)val;
364 return 0;
367 static void sect_write(struct section *sect,
368 const uint8_t *data, uint32_t len)
370 saa_wbytes(sect->data, data, len);
371 sect->size += len;
374 static void add_reloc(struct section *sect, int32_t section,
375 int pcrel, int bytes)
377 struct reloc *r;
378 int32_t fi;
380 /* NeXT as puts relocs in reversed order (address-wise) into the
381 ** files, so we do the same, doesn't seem to make much of a
382 ** difference either way */
383 r = nasm_malloc(sizeof(struct reloc));
384 r->next = sect->relocs;
385 sect->relocs = r;
387 /* the current end of the section will be the symbol's address for
388 ** now, might have to be fixed by macho_fixup_relocs() later on. make
389 ** sure we don't make the symbol scattered by setting the highest
390 ** bit by accident */
391 r->addr = sect->size & ~R_SCATTERED;
392 r->ext = 0;
393 r->pcrel = pcrel;
395 /* match byte count 1, 2, 4 to length codes 0, 1, 2 respectively */
396 r->length = bytes >> 1;
398 /* vanilla relocation (GENERIC_RELOC_VANILLA) */
399 r->type = 0;
401 if (section == NO_SEG) {
402 /* absolute local symbol if no section index given */
403 r->snum = R_ABS;
404 } else {
405 fi = get_section_fileindex_by_index(section);
407 if (fi == NO_SECT) {
408 /* external symbol if no section with that index known,
409 ** symbol number was saved in macho_symdef() */
410 r->snum = raa_read(extsyms, section);
411 r->ext = 1;
412 } else {
413 /* local symbol in section fi */
414 r->snum = fi;
418 ++sect->nreloc;
421 static void macho_output(int32_t secto, const void *data,
422 enum out_type type, uint64_t size,
423 int32_t section, int32_t wrt)
425 struct section *s, *sbss;
426 int32_t addr;
427 uint8_t mydata[4], *p;
429 if (wrt != NO_SEG) {
430 wrt = NO_SEG;
431 error(ERR_NONFATAL, "WRT not supported by Mach-O output format");
432 /* continue to do _something_ */
435 if (secto == NO_SEG) {
436 if (type != OUT_RESERVE)
437 error(ERR_NONFATAL, "attempt to assemble code in "
438 "[ABSOLUTE] space");
440 return;
443 s = get_section_by_index(secto);
445 if (s == NULL) {
446 error(ERR_WARNING, "attempt to assemble code in"
447 " section %d: defaulting to `.text'", secto);
448 s = get_section_by_name("__TEXT", "__text");
450 /* should never happen */
451 if (s == NULL)
452 error(ERR_PANIC, "text section not found");
455 sbss = get_section_by_name("__DATA", "__bss");
457 if (s == sbss && type != OUT_RESERVE) {
458 error(ERR_WARNING, "attempt to initialize memory in the"
459 " BSS section: ignored");
460 s->size += realsize(type, size);
461 return;
464 switch (type) {
465 case OUT_RESERVE:
466 if (s != sbss) {
467 error(ERR_WARNING, "uninitialized space declared in"
468 " %s section: zeroing",
469 get_section_name_by_index(secto));
471 sect_write(s, NULL, size);
472 } else
473 s->size += size;
475 break;
477 case OUT_RAWDATA:
478 if (section != NO_SEG)
479 error(ERR_PANIC, "OUT_RAWDATA with other than NO_SEG");
481 sect_write(s, data, size);
482 break;
484 case OUT_ADDRESS:
485 addr = *(int64_t *)data;
487 if (section != NO_SEG) {
488 if (section % 2) {
489 error(ERR_NONFATAL, "Mach-O format does not support"
490 " section base references");
491 } else
492 add_reloc(s, section, 0, size);
495 p = mydata;
496 WRITEADDR(p, addr, size);
497 sect_write(s, mydata, size);
498 break;
500 case OUT_REL2ADR:
501 if (section == secto)
502 error(ERR_PANIC, "intra-section OUT_REL2ADR");
504 if (section != NO_SEG && section % 2) {
505 error(ERR_NONFATAL, "Mach-O format does not support"
506 " section base references");
507 } else
508 add_reloc(s, section, 1, 2);
510 p = mydata;
511 WRITESHORT(p, *(int32_t *)data - (size + s->size));
512 sect_write(s, mydata, 2L);
513 break;
515 case OUT_REL4ADR:
516 if (section == secto)
517 error(ERR_PANIC, "intra-section OUT_REL4ADR");
519 if (section != NO_SEG && section % 2) {
520 error(ERR_NONFATAL, "Mach-O format does not support"
521 " section base references");
522 } else
523 add_reloc(s, section, 1, 4);
525 p = mydata;
526 WRITELONG(p, *(int32_t *)data - (size + s->size));
527 sect_write(s, mydata, 4L);
528 break;
530 default:
531 error(ERR_PANIC, "unknown output type?");
532 break;
536 static int32_t macho_section(char *name, int pass, int *bits)
538 int32_t index, originalIndex;
539 char *sectionAttributes;
540 struct sectmap *sm;
541 struct section *s;
543 (void)pass;
545 /* Default to 32 bits. */
546 if (!name) {
547 *bits = 32;
548 name = ".text";
549 sectionAttributes = NULL;
550 } else {
551 sectionAttributes = name;
552 name = nasm_strsep(&sectionAttributes, " \t");
555 for (sm = sectmap; sm->nasmsect != NULL; ++sm) {
556 /* make lookup into section name translation table */
557 if (!strcmp(name, sm->nasmsect)) {
558 char *currentAttribute;
560 /* try to find section with that name */
561 originalIndex = index = get_section_index_by_name(sm->segname,
562 sm->sectname);
564 /* create it if it doesn't exist yet */
565 if (index == -1) {
566 s = *sectstail = nasm_malloc(sizeof(struct section));
567 s->next = NULL;
568 sectstail = &s->next;
570 s->data = saa_init(1L);
571 s->index = seg_alloc();
572 s->relocs = NULL;
573 s->align = -1;
575 xstrncpy(s->segname, sm->segname);
576 xstrncpy(s->sectname, sm->sectname);
577 s->size = 0;
578 s->nreloc = 0;
579 s->flags = sm->flags;
581 index = s->index;
582 } else {
583 s = get_section_by_index(index);
586 while ((NULL != sectionAttributes)
587 && (currentAttribute = nasm_strsep(&sectionAttributes, " \t"))) {
588 if (0 != *currentAttribute) {
589 if (!nasm_strnicmp("align=", currentAttribute, 6)) {
590 char *end;
591 int newAlignment, value;
593 value = strtoul(currentAttribute + 6, (char**)&end, 0);
594 newAlignment = exact_log2(value);
596 if (0 != *end) {
597 error(ERR_PANIC,
598 "unknown or missing alignment value \"%s\" "
599 "specified for section \"%s\"",
600 currentAttribute + 6,
601 name);
602 return NO_SEG;
603 } else if (0 > newAlignment) {
604 error(ERR_PANIC,
605 "alignment of %d (for section \"%s\") is not "
606 "a power of two",
607 value,
608 name);
609 return NO_SEG;
612 if ((-1 != originalIndex)
613 && (s->align != newAlignment)
614 && (s->align != -1)) {
615 error(ERR_PANIC,
616 "section \"%s\" has already been specified "
617 "with alignment %d, conflicts with new "
618 "alignment of %d",
619 name,
620 (1 << s->align),
621 value);
622 return NO_SEG;
625 s->align = newAlignment;
626 } else if (!nasm_stricmp("data", currentAttribute)) {
627 /* Do nothing; 'data' is implicit */
628 } else {
629 error(ERR_PANIC,
630 "unknown section attribute %s for section %s",
631 currentAttribute,
632 name);
633 return NO_SEG;
638 return index;
642 error(ERR_PANIC, "invalid section name %s", name);
643 return NO_SEG;
646 static void macho_symdef(char *name, int32_t section, int64_t offset,
647 int is_global, char *special)
649 struct symbol *sym;
651 if (special) {
652 error(ERR_NONFATAL, "The Mach-O output format does "
653 "not support any special symbol types");
654 return;
657 if (is_global == 3) {
658 error(ERR_NONFATAL, "The Mach-O format does not "
659 "(yet) support forward reference fixups.");
660 return;
663 sym = *symstail = nasm_malloc(sizeof(struct symbol));
664 sym->next = NULL;
665 symstail = &sym->next;
667 sym->name = name;
668 sym->strx = strslen;
669 sym->type = 0;
670 sym->desc = 0;
671 sym->value = offset;
672 sym->initial_snum = -1;
674 /* external and common symbols get N_EXT */
675 if (is_global != 0)
676 sym->type |= N_EXT;
678 if (section == NO_SEG) {
679 /* symbols in no section get absolute */
680 sym->type |= N_ABS;
681 sym->sect = NO_SECT;
682 } else {
683 sym->type |= N_SECT;
685 /* get the in-file index of the section the symbol was defined in */
686 sym->sect = get_section_fileindex_by_index(section);
688 if (sym->sect == NO_SECT) {
689 /* remember symbol number of references to external
690 ** symbols, this works because every external symbol gets
691 ** its own section number allocated internally by nasm and
692 ** can so be used as a key */
693 extsyms = raa_write(extsyms, section, nsyms);
694 sym->initial_snum = nsyms;
696 switch (is_global) {
697 case 1:
698 case 2:
699 /* there isn't actually a difference between global
700 ** and common symbols, both even have their size in
701 ** sym->value */
702 sym->type = N_EXT;
703 break;
705 default:
706 /* give an error on unfound section if it's not an
707 ** external or common symbol (assemble_file() does a
708 ** seg_alloc() on every call for them) */
709 error(ERR_PANIC, "in-file index for section %d not found",
710 section);
715 ++nsyms;
718 static int32_t macho_segbase(int32_t section)
720 return section;
723 static int macho_directive(char *directive, char *value, int pass)
725 (void)directive;
726 (void)value;
727 (void)pass;
728 return 0;
731 static void macho_filename(char *inname, char *outname, efunc error)
733 standard_extension(inname, outname, ".o", error);
736 extern macros_t macho_stdmac[];
738 /* Comparison function for qsort symbol layout. */
739 static int layout_compare (const struct symbol **s1,
740 const struct symbol **s2)
742 return (strcmp ((*s1)->name, (*s2)->name));
745 /* The native assembler does a few things in a similar function
747 * Remove temporary labels
748 * Sort symbols according to local, external, undefined (by name)
749 * Order the string table
751 We do not remove temporary labels right now.
753 numsyms is the total number of symbols we have. strtabsize is the
754 number entries in the string table. */
756 static void macho_layout_symbols (uint32_t *numsyms,
757 uint32_t *strtabsize)
759 struct symbol *sym, **symp;
760 uint32_t i,j;
762 *numsyms = 0;
763 *strtabsize = sizeof (char);
765 symp = &syms;
767 while ((sym = *symp)) {
768 /* Undefined symbols are now external. */
769 if (sym->type == N_UNDF)
770 sym->type |= N_EXT;
772 if ((sym->type & N_EXT) == 0) {
773 sym->snum = *numsyms;
774 *numsyms = *numsyms + 1;
775 nlocalsym++;
777 else {
778 if ((sym->type & N_TYPE) != N_UNDF)
779 nextdefsym++;
780 else
781 nundefsym++;
783 /* If we handle debug info we'll want
784 to check for it here instead of just
785 adding the symbol to the string table. */
786 sym->strx = *strtabsize;
787 saa_wbytes (strs, sym->name, (int32_t)(strlen(sym->name) + 1));
788 *strtabsize += strlen(sym->name) + 1;
790 symp = &(sym->next);
793 /* Next, sort the symbols. Most of this code is a direct translation from
794 the Apple cctools symbol layout. We need to keep compatibility with that. */
795 /* Set the indexes for symbol groups into the symbol table */
796 ilocalsym = 0;
797 iextdefsym = nlocalsym;
798 iundefsym = nlocalsym + nextdefsym;
800 /* allocate arrays for sorting externals by name */
801 extdefsyms = nasm_malloc(nextdefsym * sizeof(struct symbol *));
802 undefsyms = nasm_malloc(nundefsym * sizeof(struct symbol *));
804 i = 0;
805 j = 0;
807 symp = &syms;
809 while ((sym = *symp)) {
811 if((sym->type & N_EXT) == 0) {
812 sym->strx = *strtabsize;
813 saa_wbytes (strs, sym->name, (int32_t)(strlen (sym->name) + 1));
814 *strtabsize += strlen(sym->name) + 1;
816 else {
817 if((sym->type & N_TYPE) != N_UNDF)
818 extdefsyms[i++] = sym;
819 else
820 undefsyms[j++] = sym;
822 symp = &(sym->next);
825 qsort(extdefsyms, nextdefsym, sizeof(struct symbol *),
826 (int (*)(const void *, const void *))layout_compare);
827 qsort(undefsyms, nundefsym, sizeof(struct symbol *),
828 (int (*)(const void *, const void *))layout_compare);
830 for(i = 0; i < nextdefsym; i++) {
831 extdefsyms[i]->snum = *numsyms;
832 *numsyms += 1;
834 for(j = 0; j < nundefsym; j++) {
835 undefsyms[j]->snum = *numsyms;
836 *numsyms += 1;
840 /* Calculate some values we'll need for writing later. */
842 static void macho_calculate_sizes (void)
844 struct section *s;
846 /* count sections and calculate in-memory and in-file offsets */
847 for (s = sects; s != NULL; s = s->next) {
848 uint32_t pad = 0;
850 /* zerofill sections aren't actually written to the file */
851 if ((s->flags & SECTION_TYPE) != S_ZEROFILL)
852 seg_filesize += s->size;
854 /* recalculate segment address based on alignment and vm size */
855 s->addr = seg_vmsize;
856 /* we need section alignment to calculate final section address */
857 if (s->align == -1)
858 s->align = DEFAULT_SECTION_ALIGNMENT;
859 if(s->align) {
860 uint32_t newaddr = align(s->addr, 1 << s->align);
861 pad = newaddr - s->addr;
862 s->addr = newaddr;
865 seg_vmsize += s->size + pad;
866 ++seg_nsects;
869 /* calculate size of all headers, load commands and sections to
870 ** get a pointer to the start of all the raw data */
871 if (seg_nsects > 0) {
872 ++head_ncmds;
873 head_sizeofcmds +=
874 MACHO_SEGCMD_SIZE + seg_nsects * MACHO_SECTCMD_SIZE;
877 if (nsyms > 0) {
878 ++head_ncmds;
879 head_sizeofcmds += MACHO_SYMCMD_SIZE;
883 /* Write out the header information for the file. */
885 static void macho_write_header (void)
887 fwriteint32_t(MH_MAGIC, machofp); /* magic */
888 fwriteint32_t(CPU_TYPE_I386, machofp); /* CPU type */
889 fwriteint32_t(CPU_SUBTYPE_I386_ALL, machofp); /* CPU subtype */
890 fwriteint32_t(MH_OBJECT, machofp); /* Mach-O file type */
891 fwriteint32_t(head_ncmds, machofp); /* number of load commands */
892 fwriteint32_t(head_sizeofcmds, machofp); /* size of load commands */
893 fwriteint32_t(0, machofp); /* no flags */
896 /* Write out the segment load command at offset. */
898 static uint32_t macho_write_segment (uint32_t offset)
900 uint32_t rel_base = alignint32_t (offset + seg_filesize);
901 uint32_t s_reloff = 0;
902 struct section *s;
904 fwriteint32_t(LC_SEGMENT, machofp); /* cmd == LC_SEGMENT */
906 /* size of load command including section load commands */
907 fwriteint32_t(MACHO_SEGCMD_SIZE + seg_nsects *
908 MACHO_SECTCMD_SIZE, machofp);
910 /* in an MH_OBJECT file all sections are in one unnamed (name
911 ** all zeros) segment */
912 fwritezero(16, machofp);
913 fwriteint32_t(0, machofp); /* in-memory offset */
914 fwriteint32_t(seg_vmsize, machofp); /* in-memory size */
915 fwriteint32_t(offset, machofp); /* in-file offset to data */
916 fwriteint32_t(seg_filesize, machofp); /* in-file size */
917 fwriteint32_t(VM_PROT_DEFAULT, machofp); /* maximum vm protection */
918 fwriteint32_t(VM_PROT_DEFAULT, machofp); /* initial vm protection */
919 fwriteint32_t(seg_nsects, machofp); /* number of sections */
920 fwriteint32_t(0, machofp); /* no flags */
922 /* emit section headers */
923 for (s = sects; s != NULL; s = s->next) {
924 fwrite(s->sectname, sizeof(s->sectname), 1, machofp);
925 fwrite(s->segname, sizeof(s->segname), 1, machofp);
926 fwriteint32_t(s->addr, machofp);
927 fwriteint32_t(s->size, machofp);
929 /* dummy data for zerofill sections or proper values */
930 if ((s->flags & SECTION_TYPE) != S_ZEROFILL) {
931 fwriteint32_t(offset, machofp);
932 /* Write out section alignment, as a power of two.
933 e.g. 32-bit word alignment would be 2 (2^^2 = 4). */
934 if (s->align == -1)
935 s->align = DEFAULT_SECTION_ALIGNMENT;
936 fwriteint32_t(s->align, machofp);
937 /* To be compatible with cctools as we emit
938 a zero reloff if we have no relocations. */
939 fwriteint32_t(s->nreloc ? rel_base + s_reloff : 0, machofp);
940 fwriteint32_t(s->nreloc, machofp);
942 offset += s->size;
943 s_reloff += s->nreloc * MACHO_RELINFO_SIZE;
944 } else {
945 fwriteint32_t(0, machofp);
946 fwriteint32_t(0, machofp);
947 fwriteint32_t(0, machofp);
948 fwriteint32_t(0, machofp);
951 fwriteint32_t(s->flags, machofp); /* flags */
952 fwriteint32_t(0, machofp); /* reserved */
953 fwriteint32_t(0, machofp); /* reserved */
956 rel_padcnt = rel_base - offset;
957 offset = rel_base + s_reloff;
959 return offset;
962 /* For a given chain of relocs r, write out the entire relocation
963 chain to the object file. */
965 static void macho_write_relocs (struct reloc *r)
967 while (r) {
968 uint32_t word2;
970 fwriteint32_t(r->addr, machofp); /* reloc offset */
972 word2 = r->snum;
973 word2 |= r->pcrel << 24;
974 word2 |= r->length << 25;
975 word2 |= r->ext << 27;
976 word2 |= r->type << 28;
977 fwriteint32_t(word2, machofp); /* reloc data */
979 r = r->next;
983 /* Write out the section data. */
984 static void macho_write_section (void)
986 struct section *s, *s2;
987 struct reloc *r;
988 uint8_t *p, *q, blk[4];
989 int32_t l;
991 for (s = sects; s != NULL; s = s->next) {
992 if ((s->flags & SECTION_TYPE) == S_ZEROFILL)
993 continue;
995 /* no padding needs to be done to the sections */
997 /* Like a.out Mach-O references things in the data or bss
998 * sections by addresses which are actually relative to the
999 * start of the _text_ section, in the _file_. See outaout.c
1000 * for more information. */
1001 saa_rewind(s->data);
1002 for (r = s->relocs; r != NULL; r = r->next) {
1003 saa_fread(s->data, r->addr, blk, (int32_t)r->length << 1);
1004 p = q = blk;
1005 l = *p++;
1007 /* get offset based on relocation type */
1008 if (r->length > 0) {
1009 l += ((int32_t)*p++) << 8;
1011 if (r->length == 2) {
1012 l += ((int32_t)*p++) << 16;
1013 l += ((int32_t)*p++) << 24;
1017 /* If the relocation is internal add to the current section
1018 offset. Otherwise the only value we need is the symbol
1019 offset which we already have. The linker takes care
1020 of the rest of the address. */
1021 if (!r->ext) {
1022 /* generate final address by section address and offset */
1023 s2 = get_section_by_index(r->snum);
1024 if(s2)
1025 l += s2->addr; // else what?!?
1028 /* write new offset back */
1029 if (r->length == 2)
1030 WRITELONG(q, l);
1031 else if (r->length == 1)
1032 WRITESHORT(q, l);
1033 else
1034 *q++ = l & 0xFF;
1036 saa_fwrite(s->data, r->addr, blk, (int32_t)r->length << 1);
1039 /* dump the section data to file */
1040 saa_fpwrite(s->data, machofp);
1043 /* pad last section up to reloc entries on int32_t boundary */
1044 fwritezero(rel_padcnt, machofp);
1046 /* emit relocation entries */
1047 for (s = sects; s != NULL; s = s->next)
1048 macho_write_relocs (s->relocs);
1051 /* Write out the symbol table. We should already have sorted this
1052 before now. */
1053 static void macho_write_symtab (void)
1055 struct symbol *sym;
1056 struct section *s;
1057 int32_t fi;
1058 uint32_t i;
1060 /* we don't need to pad here since MACHO_RELINFO_SIZE == 8 */
1062 for (sym = syms; sym != NULL; sym = sym->next) {
1063 if ((sym->type & N_EXT) == 0) {
1064 fwriteint32_t(sym->strx, machofp); /* string table entry number */
1065 fwrite(&sym->type, 1, 1, machofp); /* symbol type */
1066 fwrite(&sym->sect, 1, 1, machofp); /* section */
1067 fwriteint16_t(sym->desc, machofp); /* description */
1069 /* Fix up the symbol value now that we know the final section
1070 sizes. */
1071 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1072 for (s = sects, fi = 1;
1073 s != NULL && fi < sym->sect; s = s->next, ++fi)
1074 sym->value += s->size;
1077 fwriteint32_t(sym->value, machofp); /* value (i.e. offset) */
1081 for (i = 0; i < nextdefsym; i++) {
1082 sym = extdefsyms[i];
1083 fwriteint32_t(sym->strx, machofp);
1084 fwrite(&sym->type, 1, 1, machofp); /* symbol type */
1085 fwrite(&sym->sect, 1, 1, machofp); /* section */
1086 fwriteint16_t(sym->desc, machofp); /* description */
1088 /* Fix up the symbol value now that we know the final section
1089 sizes. */
1090 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1091 for (s = sects, fi = 1;
1092 s != NULL && fi < sym->sect; s = s->next, ++fi)
1093 sym->value += s->size;
1096 fwriteint32_t(sym->value, machofp); /* value (i.e. offset) */
1099 for (i = 0; i < nundefsym; i++) {
1100 sym = undefsyms[i];
1101 fwriteint32_t(sym->strx, machofp);
1102 fwrite(&sym->type, 1, 1, machofp); /* symbol type */
1103 fwrite(&sym->sect, 1, 1, machofp); /* section */
1104 fwriteint16_t(sym->desc, machofp); /* description */
1106 /* Fix up the symbol value now that we know the final section
1107 sizes. */
1108 if (((sym->type & N_TYPE) == N_SECT) && (sym->sect != NO_SECT)) {
1109 for (s = sects, fi = 1;
1110 s != NULL && fi < sym->sect; s = s->next, ++fi)
1111 sym->value += s->size;
1114 fwriteint32_t(sym->value, machofp); /* value (i.e. offset) */
1118 /* Fixup the snum in the relocation entries, we should be
1119 doing this only for externally undefined symbols. */
1120 static void macho_fixup_relocs (struct reloc *r)
1122 struct symbol *sym;
1123 uint32_t i;
1125 while (r != NULL) {
1126 if (r->ext) {
1127 for (i = 0; i < nundefsym; i++) {
1128 sym = undefsyms[i];
1129 if (sym->initial_snum == r->snum) {
1130 r->snum = sym->snum;
1131 break;
1135 r = r->next;
1139 /* Write out the object file. */
1141 static void macho_write (void)
1143 uint32_t offset = 0;
1145 /* mach-o object file structure:
1147 ** mach header
1148 ** uint32_t magic
1149 ** int cpu type
1150 ** int cpu subtype
1151 ** uint32_t mach file type
1152 ** uint32_t number of load commands
1153 ** uint32_t size of all load commands
1154 ** (includes section struct size of segment command)
1155 ** uint32_t flags
1157 ** segment command
1158 ** uint32_t command type == LC_SEGMENT
1159 ** uint32_t size of load command
1160 ** (including section load commands)
1161 ** char[16] segment name
1162 ** uint32_t in-memory offset
1163 ** uint32_t in-memory size
1164 ** uint32_t in-file offset to data area
1165 ** uint32_t in-file size
1166 ** (in-memory size excluding zerofill sections)
1167 ** int maximum vm protection
1168 ** int initial vm protection
1169 ** uint32_t number of sections
1170 ** uint32_t flags
1172 ** section commands
1173 ** char[16] section name
1174 ** char[16] segment name
1175 ** uint32_t in-memory offset
1176 ** uint32_t in-memory size
1177 ** uint32_t in-file offset
1178 ** uint32_t alignment
1179 ** (irrelevant in MH_OBJECT)
1180 ** uint32_t in-file offset of relocation entires
1181 ** uint32_t number of relocations
1182 ** uint32_t flags
1183 ** uint32_t reserved
1184 ** uint32_t reserved
1186 ** symbol table command
1187 ** uint32_t command type == LC_SYMTAB
1188 ** uint32_t size of load command
1189 ** uint32_t symbol table offset
1190 ** uint32_t number of symbol table entries
1191 ** uint32_t string table offset
1192 ** uint32_t string table size
1194 ** raw section data
1196 ** padding to int32_t boundary
1198 ** relocation data (struct reloc)
1199 ** int32_t offset
1200 ** uint data (symbolnum, pcrel, length, extern, type)
1202 ** symbol table data (struct nlist)
1203 ** int32_t string table entry number
1204 ** uint8_t type
1205 ** (extern, absolute, defined in section)
1206 ** uint8_t section
1207 ** (0 for global symbols, section number of definition (>= 1, <=
1208 ** 254) for local symbols, size of variable for common symbols
1209 ** [type == extern])
1210 ** int16_t description
1211 ** (for stab debugging format)
1212 ** uint32_t value (i.e. file offset) of symbol or stab offset
1214 ** string table data
1215 ** list of null-terminated strings
1218 /* Emit the Mach-O header. */
1219 macho_write_header();
1221 offset = MACHO_HEADER_SIZE + head_sizeofcmds;
1223 /* emit the segment load command */
1224 if (seg_nsects > 0)
1225 offset = macho_write_segment (offset);
1226 else
1227 error(ERR_WARNING, "no sections?");
1229 if (nsyms > 0) {
1230 /* write out symbol command */
1231 fwriteint32_t(LC_SYMTAB, machofp); /* cmd == LC_SYMTAB */
1232 fwriteint32_t(MACHO_SYMCMD_SIZE, machofp); /* size of load command */
1233 fwriteint32_t(offset, machofp); /* symbol table offset */
1234 fwriteint32_t(nsyms, machofp); /* number of symbol
1235 ** table entries */
1237 offset += nsyms * MACHO_NLIST_SIZE;
1238 fwriteint32_t(offset, machofp); /* string table offset */
1239 fwriteint32_t(strslen, machofp); /* string table size */
1242 /* emit section data */
1243 if (seg_nsects > 0)
1244 macho_write_section ();
1246 /* emit symbol table if we have symbols */
1247 if (nsyms > 0)
1248 macho_write_symtab ();
1250 /* we don't need to pad here since MACHO_NLIST_SIZE == 12 */
1252 /* emit string table */
1253 saa_fpwrite(strs, machofp);
1255 /* We do quite a bit here, starting with finalizing all of the data
1256 for the object file, writing, and then freeing all of the data from
1257 the file. */
1259 static void macho_cleanup(int debuginfo)
1261 struct section *s;
1262 struct reloc *r;
1263 struct symbol *sym;
1265 (void)debuginfo;
1267 /* Sort all symbols. */
1268 macho_layout_symbols (&nsyms, &strslen);
1270 /* Fixup relocation entries */
1271 for (s = sects; s != NULL; s = s->next) {
1272 macho_fixup_relocs (s->relocs);
1275 /* First calculate and finalize needed values. */
1276 macho_calculate_sizes();
1277 macho_write();
1279 /* done - yay! */
1280 fclose(machofp);
1282 /* free up everything */
1283 while (sects->next) {
1284 s = sects;
1285 sects = sects->next;
1287 saa_free(s->data);
1288 while (s->relocs != NULL) {
1289 r = s->relocs;
1290 s->relocs = s->relocs->next;
1291 nasm_free(r);
1294 nasm_free(s);
1297 saa_free(strs);
1298 raa_free(extsyms);
1300 if (syms) {
1301 while (syms->next) {
1302 sym = syms;
1303 syms = syms->next;
1305 nasm_free (sym);
1310 /* Debugging routines. */
1311 static void debug_reloc (struct reloc *r)
1313 fprintf (stdout, "reloc:\n");
1314 fprintf (stdout, "\taddr: %"PRId32"\n", r->addr);
1315 fprintf (stdout, "\tsnum: %d\n", r->snum);
1316 fprintf (stdout, "\tpcrel: %d\n", r->pcrel);
1317 fprintf (stdout, "\tlength: %d\n", r->length);
1318 fprintf (stdout, "\text: %d\n", r->ext);
1319 fprintf (stdout, "\ttype: %d\n", r->type);
1322 static void debug_section_relocs (struct section *s)
1324 struct reloc *r = s->relocs;
1326 fprintf (stdout, "relocs for section %s:\n\n", s->sectname);
1328 while (r != NULL) {
1329 debug_reloc (r);
1330 r = r->next;
1334 struct ofmt of_macho = {
1335 "NeXTstep/OpenStep/Rhapsody/Darwin/MacOS X object files",
1336 "macho",
1337 NULL,
1338 null_debug_arr,
1339 &null_debug_form,
1340 macho_stdmac,
1341 macho_init,
1342 macho_setinfo,
1343 macho_output,
1344 macho_symdef,
1345 macho_section,
1346 macho_segbase,
1347 macho_directive,
1348 macho_filename,
1349 macho_cleanup
1352 #endif
1355 * Local Variables:
1356 * mode:c
1357 * c-basic-offset:4
1358 * End:
1360 * end of file */