• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Mac OS X ABI Mach-O File Format
3  *
4  *  Copyright (C) 2007 Henryk Richter, built upon xdf objfmt (C) Peter Johnson
5  *
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND OTHER CONTRIBUTORS ``AS IS''
17  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR OTHER CONTRIBUTORS BE
20  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
21  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
22  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
23  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
24  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
25  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26  * POSSIBILITY OF SUCH DAMAGE.
27  */
28 /*
29   notes: This implementation is rather basic. There are several implementation
30          issues to be sorted out for full compliance and error resilience.
31          Some examples are given below (nasm syntax).
32 
33   1) section placement
34      Mach-O requires BSS sections to be placed last in object files. This
35      has to be done manually.
36      Example:
37 
38       section .text
39        mov rax,[qword foo]
40       section .data
41        dw  0
42       section .bss
43       foo dw 0
44 
45   2) addressing issues
46 
47   2.1) symbol relative relocation (i.e. mov eax,[foo wrt bar])
48        Not implemented yet.
49 
50   2.2) data referencing in 64 bit mode
51        While ELF allows 32 bit absolute relocations in 64 bit mode, Mach-O
52        does not. Therefore code like
53         lea rbx,[_foo]  ;48 8d 1c 25 00 00 00 00
54         mov rcx,[_bar]  ;48 8b 0c 25 00 00 00 00
55        with a 32 bit address field cannot be relocated into an address >= 0x100000000 (OSX actually
56        uses that).
57 
58        Actually, the only register where a 64 bit displacement is allowed in x86-64, is rax
59        as in the example 1).
60 
61        A plausible workaround is either classic PIC (like in C), which is in turn
62        not implemented in this object format. The recommended was is PC relative
63        code (called RIP-relative in x86-64). So instead of the lines above, just write:
64         lea rbx,[_foo wrt rip]
65         mov rcx,[_bar wrt rip]
66 
67   2.3) section/data alignment
68        Normally, you specify sections with a specific alignment
69        and get your data layed out as desired. Unfortunately, the
70        linker in MacOS X seems to ignore the section alignment requests.
71        The workaround is an explicit alignment at the end of the text section.
72 
73        section .text
74         movdqa xmm0,[_foo wrt rip]
75 
76         align 16
77        section .data align=16
78         _foo dw 32,32,32,32,32,32,32,32
79 
80        FIXME: perform that operation implicitly!
81 
82   2.4) cross section symbol differences unsupported in current implementation
83        [extern foo]
84        [extern bar]
85        section .data
86         dq bar-foo
87 
88        Will currently produce an error though the necessary means are provided
89        by the Mach-O specification.
90 
91 */
92 
93 #include <util.h>
94 
95 #include <libyasm.h>
96 
97 /* MACH-O DEFINES */
98 /* Mach-O in-file header structure sizes (32 BIT, see below for 64 bit defs) */
99 #define MACHO_HEADER_SIZE       28
100 #define MACHO_SEGCMD_SIZE       56
101 #define MACHO_SECTCMD_SIZE      68
102 #define MACHO_SYMCMD_SIZE       24
103 #define MACHO_NLIST_SIZE        12
104 #define MACHO_RELINFO_SIZE      8
105 
106 /* 64 bit sizes */
107 #define MACHO_HEADER64_SIZE     32
108 #define MACHO_SEGCMD64_SIZE     72
109 #define MACHO_SECTCMD64_SIZE    80
110 #define MACHO_NLIST64_SIZE      16
111 #define MACHO_RELINFO64_SIZE    8
112 
113 
114 /* Mach-O file header values */
115 #define MH_MAGIC                0xfeedface
116 #define MH_MAGIC_64             0xfeedfacf
117 
118 /* CPU machine type */
119 #define CPU_TYPE_I386           7       /* x86 platform */
120 #define CPU_TYPE_X86_64         (CPU_TYPE_I386|CPU_ARCH_ABI64)
121 #define CPU_ARCH_ABI64          0x01000000      /* 64 bit ABI */
122 
123 /* CPU machine subtype, e.g. processor */
124 #define CPU_SUBTYPE_I386_ALL    3       /* all-x86 compatible */
125 #define CPU_SUBTYPE_X86_64_ALL  CPU_SUBTYPE_I386_ALL
126 #define CPU_SUBTYPE_386         3
127 #define CPU_SUBTYPE_486         4
128 #define CPU_SUBTYPE_486SX       (4 + 128)
129 #define CPU_SUBTYPE_586         5
130 #define CPU_SUBTYPE_INTEL(f, m) ((f) + ((m) << 4))
131 #define CPU_SUBTYPE_PENT        CPU_SUBTYPE_INTEL(5, 0)
132 #define CPU_SUBTYPE_PENTPRO     CPU_SUBTYPE_INTEL(6, 1)
133 #define CPU_SUBTYPE_PENTII_M3   CPU_SUBTYPE_INTEL(6, 3)
134 #define CPU_SUBTYPE_PENTII_M5   CPU_SUBTYPE_INTEL(6, 5)
135 #define CPU_SUBTYPE_PENTIUM_4   CPU_SUBTYPE_INTEL(10, 0)
136 
137 #define CPU_SUBTYPE_INTEL_FAMILY(x)     ((x) & 15)
138 #define CPU_SUBTYPE_INTEL_FAMILY_MAX    15
139 
140 #define CPU_SUBTYPE_INTEL_MODEL(x)      ((x) >> 4)
141 #define CPU_SUBTYPE_INTEL_MODEL_ALL     0
142 
143 #define MH_OBJECT               0x1     /* object file */
144 
145 #define LC_SEGMENT              0x1     /* segment load command */
146 #define LC_SYMTAB               0x2     /* symbol table load command */
147 #define LC_SEGMENT_64           0x19    /* segment load command */
148 
149 
150 #define VM_PROT_NONE            0x00
151 #define VM_PROT_READ            0x01
152 #define VM_PROT_WRITE           0x02
153 #define VM_PROT_EXECUTE         0x04
154 
155 #define VM_PROT_DEFAULT (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
156 #define VM_PROT_ALL     (VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE)
157 
158 #define SECTION_TYPE        0x000000ff  /* section type mask */
159 #define SECTION_ATTRIBUTES  0xffffff00UL/* section attributes mask */
160 
161 #define S_REGULAR           0x0         /* standard section */
162 #define S_ZEROFILL          0x1         /* zerofill, in-memory only */
163 #define S_CSTRING_LITERALS  0x2         /* literal C strings */
164 #define S_4BYTE_LITERALS    0x3         /* only 4-byte literals */
165 #define S_8BYTE_LITERALS    0x4         /* only 8-byte literals */
166 #define S_LITERAL_POINTERS  0x5         /* only pointers to literals */
167 #define S_NON_LAZY_SYMBOL_POINTERS  0x6 /* only non-lazy symbol pointers */
168 #define S_LAZY_SYMBOL_POINTERS      0x7 /* only lazy symbol pointers */
169 #define S_SYMBOL_STUBS      0x8         /* only symbol stubs; byte size of
170                                          * stub in the reserved2 field */
171 #define S_MOD_INIT_FUNC_POINTERS    0x9 /* only function pointers for init */
172 #define S_MOD_TERM_FUNC_POINTERS    0xa /* only function pointers for term */
173 #define S_COALESCED         0xb         /* symbols that are to be coalesced */
174 #define S_GB_ZEROFILL       0xc         /* >4GB zero fill on demand section */
175 #define S_INTERPOSING       0xd         /* only pairs of function pointers for
176                                          * interposing */
177 #define S_16BYTE_LITERALS   0xe         /* only 16 byte literals */
178 
179 #define S_ATTR_DEBUG             0x02000000     /* a debug section */
180 #define SECTION_ATTRIBUTES_SYS   0x00ffff00     /* system setable attributes */
181 #define S_ATTR_SOME_INSTRUCTIONS 0x00000400     /* section contains some
182                                                  * machine instructions */
183 #define S_ATTR_EXT_RELOC         0x00000200     /* section has external
184                                                  * relocation entries */
185 #define S_ATTR_LOC_RELOC         0x00000100     /* section has local
186                                                  * relocation entries */
187 
188 #define SECTION_ATTRIBUTES_USR   0xff000000UL   /* User setable attributes */
189 #define S_ATTR_PURE_INSTRUCTIONS 0x80000000UL   /* only true machine insns */
190 #define S_ATTR_NO_TOC            0x40000000UL   /* coalesced symbols that are
191                                                  * not to be in a ranlib table
192                                                  * of contents */
193 #define S_ATTR_STRIP_STATIC_SYMS 0x20000000UL   /* ok to strip static symbols
194                                                  * in this section in files
195                                                  * with the MH_DYLDLINK flag */
196 #define S_ATTR_NO_DEAD_STRIP     0x10000000UL   /* no dead stripping */
197 #define S_ATTR_LIVE_SUPPORT      0x08000000UL   /* blocks are live if they
198                                                  * reference live blocks */
199 #define S_ATTR_SELF_MODIFYING_CODE 0x04000000UL /* Used with i386 code stubs
200                                                  * written on by dyld */
201 
202 /* macho references symbols in different ways whether they are linked at
203  * runtime (LAZY, read library functions) or at link time (NON_LAZY, mostly
204  * data)
205  *
206  * TODO: proper support for dynamically linkable modules would require the
207  * __import sections as well as the dsymtab command
208  */
209 #define REFERENCE_FLAG_UNDEFINED_NON_LAZY 0x0
210 #define REFERENCE_FLAG_UNDEFINED_LAZY     0x1
211 
212 #define align(x, y) \
213     (((x) + (y) - 1) & ~((y) - 1))      /* align x to multiple of y */
214 
215 #define align32(x) \
216     align(x, 4)                 /* align x to 32 bit boundary */
217 
218 #define macho_MAGIC     0x87654322
219 
220 /* Symbol table type field bit masks */
221 #define N_STAB  0xe0            /* mask indicating stab entry */
222 #define N_PEXT  0x10            /* private external bit */
223 #define N_TYPE  0x0e            /* mask for all the type bits */
224 #define N_EXT   0x01            /* external (global) bit */
225 
226 /* Symbol table type field values */
227 #define N_UNDF  0x00            /* undefined */
228 #define N_ABS   0x02            /* absolute address */
229 #define N_SECT  0x0e            /* symbol is defined in a section */
230 
231 #define NO_SECT 0               /* no section for symbol in nlist */
232 
233 #define REGULAR_OUTBUF_SIZE     1024
234 
235 
236 typedef struct macho_reloc {
237     yasm_reloc reloc;
238     int pcrel;
239     int length;
240     int ext;
241     enum reloc_type_x86_64 {
242         /* x86 relocations */
243         GENERIC_RELOC_VANILLA = 0,      /* generic relocation */
244         GENERIC_RELOC_PAIR = 1,         /* Only follows a GENERIC_RELOC_SECTDIFF */
245         GENERIC_RELOC_SECTDIFF = 2,
246         GENERIC_RELOC_PB_LA_PTR = 3,    /* prebound lazy pointer */
247         GENERIC_RELOC_LOCAL_SECTDIFF = 4,
248 
249         /* x86-64 relocations */
250         X86_64_RELOC_UNSIGNED = 0,      /* for absolute addresses */
251         X86_64_RELOC_SIGNED = 1,        /* for signed 32-bit displacement */
252         X86_64_RELOC_BRANCH = 2,        /* a CALL/JMP insn with 32-bit disp */
253         X86_64_RELOC_GOT_LOAD = 3,      /* a MOVQ load of a GOT entry */
254         X86_64_RELOC_GOT = 4,           /* other GOT references */
255         X86_64_RELOC_SUBTRACTOR = 5,    /* must be followed by a X86_64_RELOC_UNSIGNED */
256         X86_64_RELOC_SIGNED_1 = 6,      /* signed 32-bit disp, -1 addend */
257         X86_64_RELOC_SIGNED_2 = 7,      /* signed 32-bit disp, -2 addend */
258         X86_64_RELOC_SIGNED_4 = 8       /* signed 32-bit disp, -4 addend */
259     } type;
260 } macho_reloc;
261 
262 typedef struct macho_section_data {
263     /*@dependent@*/ yasm_symrec *sym; /* symbol created for this section */
264     long scnum;                 /* section number (0=first section) */
265     /*@only@*/ char *segname;   /* segment name in file */
266     /*@only@*/ char *sectname;  /* section name in file */
267     unsigned long flags;        /* S_* flags */
268     unsigned long size;         /* size of raw data (section data) in bytes */
269     unsigned long offset;       /* offset in raw data within file in bytes */
270     unsigned long vmoff;        /* memory offset */
271     unsigned long nreloc;       /* number of relocation entries */
272     unsigned int extreloc;      /* external relocations present (0/1) */
273 } macho_section_data;
274 
275 
276 typedef struct macho_symrec_data {
277     unsigned long index;        /* index in output order */
278     yasm_intnum *value;         /* valid after writing symtable to file */
279     unsigned long length;       /* length + 1 (plus auto underscore) */
280 } macho_symrec_data;
281 
282 
283 typedef struct yasm_objfmt_macho {
284     yasm_objfmt_base objfmt;    /* base structure */
285 
286     long parse_scnum;           /* sect numbering in parser */
287     int bits;                   /* 32 / 64 */
288 
289     yasm_symrec *gotpcrel_sym;  /* ..gotpcrel */
290 } yasm_objfmt_macho;
291 
292 
293 typedef struct macho_objfmt_output_info {
294     yasm_object *object;
295     yasm_objfmt_macho *objfmt_macho;
296     yasm_errwarns *errwarns;
297     /*@dependent@ */ FILE *f;
298     /*@only@ */ unsigned char *buf;
299     yasm_section *sect;
300     /*@dependent@ */ macho_section_data *msd;
301 
302     unsigned int is_64;         /* write object in 64 bit mode */
303 
304     /* vmsize and filesize available after traversing section count routine */
305     unsigned long vmsize;       /* raw size of all sections (including BSS) */
306     unsigned long filesize;     /* size of sections in file (excluding BSS) */
307     unsigned long offset;       /* offset within file */
308 
309     /* forward offset tracking */
310     unsigned long rel_base;     /* first relocation in file */
311     unsigned long s_reloff;     /* in-file offset to relocations */
312 
313     unsigned long indx;         /* current symbol size in bytes (name length+1) */
314     unsigned long symindex;     /* current symbol index in output order */
315     int all_syms;               /* outputting all symbols? */
316     unsigned long strlength;    /* length of all strings */
317 } macho_objfmt_output_info;
318 
319 
320 static void macho_section_data_destroy(/*@only@*/ void *d);
321 static void macho_section_data_print(void *data, FILE *f, int indent_level);
322 
323 static const yasm_assoc_data_callback macho_section_data_cb = {
324     macho_section_data_destroy,
325     macho_section_data_print
326 };
327 
328 static void macho_symrec_data_destroy(/*@only@*/ void *d);
329 static void macho_symrec_data_print(void *data, FILE *f, int indent_level);
330 
331 static const yasm_assoc_data_callback macho_symrec_data_cb = {
332     macho_symrec_data_destroy,
333     macho_symrec_data_print
334 };
335 
336 yasm_objfmt_module yasm_macho_LTX_objfmt;
337 yasm_objfmt_module yasm_macho32_LTX_objfmt;
338 yasm_objfmt_module yasm_macho64_LTX_objfmt;
339 
340 static yasm_objfmt *
macho_objfmt_create_common(yasm_object * object,yasm_objfmt_module * module,int bits_pref)341 macho_objfmt_create_common(yasm_object *object, yasm_objfmt_module *module,
342                            int bits_pref)
343 {
344     yasm_objfmt_macho *objfmt_macho = yasm_xmalloc(sizeof(yasm_objfmt_macho));
345 
346     objfmt_macho->objfmt.module = module;
347 
348     /* Only support x86 arch for now */
349     if (yasm__strcasecmp(yasm_arch_keyword(object->arch), "x86") != 0) {
350         yasm_xfree(objfmt_macho);
351         return NULL;
352     }
353 
354     /* Support x86 and amd64 machines of x86 arch */
355     if (yasm__strcasecmp(yasm_arch_get_machine(object->arch), "x86") == 0 &&
356         (bits_pref == 0 || bits_pref == 32)) {
357         objfmt_macho->bits = 32;
358         objfmt_macho->gotpcrel_sym = NULL;
359     } else if (yasm__strcasecmp(yasm_arch_get_machine(object->arch),
360                               "amd64") == 0 &&
361              (bits_pref == 0 || bits_pref == 64)) {
362         objfmt_macho->bits = 64;
363         /* FIXME: misuse of NULL bytecode */
364         objfmt_macho->gotpcrel_sym =
365             yasm_symtab_define_label(object->symtab, "..gotpcrel", NULL, 0, 0);
366     } else {
367         yasm_xfree(objfmt_macho);
368         return NULL;
369     }
370 
371     objfmt_macho->parse_scnum = 0;      /* section numbering starts at 0 */
372     return (yasm_objfmt *)objfmt_macho;
373 }
374 
375 static yasm_objfmt *
macho_objfmt_create(yasm_object * object)376 macho_objfmt_create(yasm_object *object)
377 {
378     yasm_objfmt *objfmt;
379     yasm_objfmt_macho *objfmt_macho;
380 
381     objfmt = macho_objfmt_create_common(object, &yasm_macho_LTX_objfmt, 0);
382     if (objfmt) {
383         objfmt_macho = (yasm_objfmt_macho *)objfmt;
384         /* Figure out which bitness of object format to use */
385         if (objfmt_macho->bits == 32)
386             objfmt_macho->objfmt.module = &yasm_macho32_LTX_objfmt;
387         else if (objfmt_macho->bits == 64)
388             objfmt_macho->objfmt.module = &yasm_macho64_LTX_objfmt;
389     }
390     return objfmt;
391 }
392 
393 static yasm_objfmt *
macho32_objfmt_create(yasm_object * object)394 macho32_objfmt_create(yasm_object *object)
395 {
396     return macho_objfmt_create_common(object, &yasm_macho32_LTX_objfmt, 32);
397 }
398 
399 static yasm_objfmt *
macho64_objfmt_create(yasm_object * object)400 macho64_objfmt_create(yasm_object *object)
401 {
402     return macho_objfmt_create_common(object, &yasm_macho64_LTX_objfmt, 64);
403 }
404 
405 static int
macho_objfmt_output_value(yasm_value * value,unsigned char * buf,unsigned int destsize,unsigned long offset,yasm_bytecode * bc,int warn,void * d)406 macho_objfmt_output_value(yasm_value *value, unsigned char *buf,
407                           unsigned int destsize, unsigned long offset,
408                           yasm_bytecode *bc, int warn, /*@null@*/ void *d)
409 {
410     /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
411     yasm_objfmt_macho *objfmt_macho;
412     /*@dependent@*/ /*@null@*/ yasm_intnum *intn;
413     unsigned long intn_minus = 0, intn_plus = 0;
414     int retval;
415     unsigned int valsize = value->size;
416     macho_reloc *reloc = NULL;
417 
418     assert(info != NULL);
419     objfmt_macho = info->objfmt_macho;
420 
421     if (value->abs)
422         value->abs = yasm_expr_simplify(value->abs, 1);
423 
424     /* Try to output constant and PC-relative section-local first.
425      * Note this does NOT output any value with a SEG, WRT, external,
426      * cross-section, or non-PC-relative reference (those are handled below).
427      */
428     switch (yasm_value_output_basic(value, buf, destsize, bc, warn,
429                                     info->object->arch)) {
430         case -1:
431             return 1;
432         case 0:
433             break;
434         default:
435             return 0;
436     }
437 
438     if (value->section_rel) {
439         yasm_error_set(YASM_ERROR_TOO_COMPLEX,
440             N_("macho: relocation too complex for current implementation"));
441         return 1;
442     }
443 
444     if (value->rel) {
445         yasm_sym_vis vis = yasm_symrec_get_visibility(value->rel);
446 
447         reloc = yasm_xcalloc(sizeof(macho_reloc), 1);
448         reloc->reloc.addr = yasm_intnum_create_uint(bc->offset + offset);
449         reloc->reloc.sym = value->rel;
450         switch (valsize) {
451             case 64:
452                 reloc->length = 3;
453                 break;
454             case 32:
455                 reloc->length = 2;
456                 break;
457             case 16:
458                 reloc->length = 1;
459                 break;
460             case 8:
461                 reloc->length = 0;
462                 break;
463             default:
464                 yasm_error_set(YASM_ERROR_TOO_COMPLEX,
465                                N_("macho: relocation size unsupported"));
466                 yasm_xfree(reloc);
467                 return 1;
468         }
469         reloc->pcrel = 0;
470         reloc->ext = 0;
471         reloc->type = GENERIC_RELOC_VANILLA;
472         /* R_ABS */
473 
474         if (value->rshift > 0) {
475             yasm_error_set(YASM_ERROR_TOO_COMPLEX,
476                            N_("macho: shifted relocations not supported"));
477             yasm_xfree(reloc);
478             return 1;
479         }
480 
481         if (value->seg_of) {
482             yasm_error_set(YASM_ERROR_TOO_COMPLEX,
483                            N_("macho: SEG not supported"));
484             yasm_xfree(reloc);
485             return 1;
486         }
487 
488         if (value->curpos_rel && objfmt_macho->gotpcrel_sym &&
489             value->wrt == objfmt_macho->gotpcrel_sym) {
490             reloc->type = X86_64_RELOC_GOT;
491             value->wrt = NULL;
492         } else if (value->wrt) {
493             yasm_error_set(YASM_ERROR_TOO_COMPLEX,
494                            N_("macho: invalid WRT"));
495             yasm_xfree(reloc);
496             return 1;
497         }
498 
499         if (value->curpos_rel) {
500             reloc->pcrel = 1;
501             if (!info->is_64) {
502                 /* Adjust to start of section, so subtract out the bytecode
503                  * offset.
504                  */
505                 intn_minus = bc->offset;
506             } else {
507                 /* Add in the offset plus value size to end up with 0. */
508                 intn_plus = offset+destsize;
509                 if (reloc->type == X86_64_RELOC_GOT) {
510                     /* XXX: This is a hack */
511                     if (offset >= 2 && buf[-2] == 0x8B)
512                         reloc->type = X86_64_RELOC_GOT_LOAD;
513                 } else if (value->jump_target)
514                     reloc->type = X86_64_RELOC_BRANCH;
515                 else
516                     reloc->type = X86_64_RELOC_SIGNED;
517             }
518         } else if (info->is_64) {
519             if (valsize == 32) {
520                 yasm_error_set(YASM_ERROR_NOT_CONSTANT,
521                     N_("macho: sorry, cannot apply 32 bit absolute relocations in 64 bit mode, consider \"[_symbol wrt rip]\" for mem access, \"qword\" and \"dq _foo\" for pointers."));
522                 return 1;
523             }
524             reloc->type = X86_64_RELOC_UNSIGNED;
525         }
526 
527         /* It seems that x86-64 objects need to have all extern relocs? */
528         if (info->is_64)
529             reloc->ext = 1;
530 
531         if ((vis & YASM_SYM_EXTERN) || (vis & YASM_SYM_COMMON)) {
532             reloc->ext = 1;
533             info->msd->extreloc = 1;    /* section has external relocations */
534         } else if (!info->is_64) {
535             /*@dependent@*/ /*@null@*/ yasm_bytecode *sym_precbc;
536 
537             /* Local symbols need valued to their actual address */
538             if (yasm_symrec_get_label(value->rel, &sym_precbc)) {
539                 yasm_section *sym_sect = yasm_bc_get_section(sym_precbc);
540                 /*@null@*/ macho_section_data *msd;
541                 msd = yasm_section_get_data(sym_sect, &macho_section_data_cb);
542                 assert(msd != NULL);
543                 intn_plus += msd->vmoff + yasm_bc_next_offset(sym_precbc);
544             }
545         }
546 
547         info->msd->nreloc++;
548         /*printf("reloc %s type %d ",yasm_symrec_get_name(reloc->reloc.sym),reloc->type);*/
549         yasm_section_add_reloc(info->sect, (yasm_reloc *)reloc, yasm_xfree);
550     }
551 
552     if (intn_minus <= intn_plus)
553         intn = yasm_intnum_create_uint(intn_plus-intn_minus);
554     else {
555         intn = yasm_intnum_create_uint(intn_minus-intn_plus);
556         yasm_intnum_calc(intn, YASM_EXPR_NEG, NULL);
557     }
558 
559     if (value->abs) {
560         yasm_intnum *intn2 = yasm_expr_get_intnum(&value->abs, 0);
561 
562         if (!intn2) {
563             yasm_error_set(YASM_ERROR_TOO_COMPLEX,
564                            N_("macho: relocation too complex"));
565             yasm_intnum_destroy(intn);
566             return 1;
567         }
568         yasm_intnum_calc(intn, YASM_EXPR_ADD, intn2);
569     }
570 
571     retval = yasm_arch_intnum_tobytes(info->object->arch, intn, buf, destsize,
572                                       valsize, 0, bc, warn);
573     /*printf("val %ld\n",yasm_intnum_get_int(intn));*/
574     yasm_intnum_destroy(intn);
575     return retval;
576 }
577 
578 static int
macho_objfmt_output_bytecode(yasm_bytecode * bc,void * d)579 macho_objfmt_output_bytecode(yasm_bytecode *bc, /*@null@*/ void *d)
580 {
581     /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
582     /*@null@*/ /*@only@*/ unsigned char *bigbuf;
583     unsigned long size = REGULAR_OUTBUF_SIZE;
584     int gap;
585 
586     assert(info != NULL);
587 
588     bigbuf = yasm_bc_tobytes(bc, info->buf, &size, &gap, info,
589                              macho_objfmt_output_value, NULL);
590 
591     /* Don't bother doing anything else if size ended up being 0. */
592     if (size == 0) {
593         if (bigbuf)
594             yasm_xfree(bigbuf);
595         return 0;
596     }
597 
598     /* Warn that gaps are converted to 0 and write out the 0's. */
599     if (gap) {
600         unsigned long left;
601 
602         yasm_warn_set(YASM_WARN_UNINIT_CONTENTS,
603                       N_("uninitialized space: zeroing"));
604         /* Write out in chunks */
605         memset(info->buf, 0, REGULAR_OUTBUF_SIZE);
606         left = size;
607         while (left > REGULAR_OUTBUF_SIZE) {
608             fwrite(info->buf, REGULAR_OUTBUF_SIZE, 1, info->f);
609             left -= REGULAR_OUTBUF_SIZE;
610         }
611         fwrite(info->buf, left, 1, info->f);
612     } else {
613         /* Output buf (or bigbuf if non-NULL) to file */
614         fwrite(bigbuf ? bigbuf : info->buf, (size_t) size, 1, info->f);
615     }
616 
617     /* If bigbuf was allocated, free it */
618     if (bigbuf)
619         yasm_xfree(bigbuf);
620 
621     return 0;
622 }
623 
624 static int
macho_objfmt_output_section(yasm_section * sect,void * d)625 macho_objfmt_output_section(yasm_section *sect, /*@null@ */ void *d)
626 {
627     /*@null@ */ macho_objfmt_output_info *info =
628         (macho_objfmt_output_info *) d;
629     /*@dependent@ *//*@null@ */ macho_section_data *msd;
630 
631     assert(info != NULL);
632     msd = yasm_section_get_data(sect, &macho_section_data_cb);
633     assert(msd != NULL);
634 
635     if (!(msd->flags & S_ZEROFILL)) {
636         /* Output non-BSS sections */
637         info->sect = sect;
638         info->msd = msd;
639         yasm_section_bcs_traverse(sect, info->errwarns, info,
640                                   macho_objfmt_output_bytecode);
641     }
642     return 0;
643 }
644 
645 static int
macho_objfmt_output_relocs(yasm_section * sect,void * d)646 macho_objfmt_output_relocs(yasm_section *sect, /*@null@*/ void *d)
647 {
648     /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
649     /*@dependent@*/ /*@null@*/ macho_section_data *msd;
650     macho_reloc *reloc;
651 
652     reloc = (macho_reloc *)yasm_section_relocs_first(sect);
653     while (reloc) {
654         unsigned char *localbuf = info->buf;
655         /*@null@*/ macho_symrec_data *xsymd;
656         unsigned long symnum;
657 
658         xsymd = yasm_symrec_get_data(reloc->reloc.sym, &macho_symrec_data_cb);
659         yasm_intnum_get_sized(reloc->reloc.addr, localbuf, 4, 32, 0, 0, 0);
660         localbuf += 4;          /* address of relocation */
661 
662         if (reloc->ext)
663             symnum = xsymd->index;
664         else {
665             /* find section where the symbol relates to */
666             /*@dependent@*/ /*@null@*/ yasm_section *dsect;
667             /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
668             symnum = 0; /* default to absolute */
669             if (yasm_symrec_get_label(reloc->reloc.sym, &precbc) &&
670                 (dsect = yasm_bc_get_section(precbc)) &&
671                 (msd = yasm_section_get_data(dsect, &macho_section_data_cb)))
672                 symnum = msd->scnum+1;
673         }
674         YASM_WRITE_32_L(localbuf,
675                         (symnum & 0x00ffffff) |
676                         (((unsigned long)reloc->pcrel & 1) << 24) |
677                         (((unsigned long)reloc->length & 3) << 25) |
678                         (((unsigned long)reloc->ext & 1) << 27) |
679                         (((unsigned long)reloc->type & 0xf) << 28));
680         fwrite(info->buf, 8, 1, info->f);
681         reloc = (macho_reloc *)yasm_section_reloc_next((yasm_reloc *)reloc);
682     }
683 
684     return 0;
685 }
686 
687 static int
exp2_to_bits(unsigned long val)688 exp2_to_bits(unsigned long val)
689 {
690     int ret = 0;
691 
692     while (val) {
693         val >>= 1;
694         ret++;
695     }
696     ret = (ret > 0) ? ret - 1 : 0;
697 
698     return ret;
699 }
700 
701 static int
macho_objfmt_is_section_label(yasm_symrec * sym)702 macho_objfmt_is_section_label(yasm_symrec *sym)
703 {
704     /*@dependent@*/ /*@null@*/ yasm_section *sect;
705     /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
706 
707     /* Look at symrec for value/scnum/etc. */
708     if (yasm_symrec_get_label(sym, &precbc)) {
709         if (precbc)
710             sect = yasm_bc_get_section(precbc);
711         else
712             sect = NULL;
713         /* it's a label: get value and offset.
714          * If there is not a section, leave as debugging symbol.
715          */
716         if (sect) {
717             /*@dependent@*/ /*@null@*/ macho_section_data *msd;
718 
719             msd = yasm_section_get_data(sect, &macho_section_data_cb);
720             if (msd) {
721                 if (msd->sym == sym)
722                     return 1;   /* don't store section names */
723             }
724         }
725     }
726     return 0;
727 }
728 
729 static int
macho_objfmt_output_secthead(yasm_section * sect,void * d)730 macho_objfmt_output_secthead(yasm_section *sect, /*@null@*/ void *d)
731 {
732     /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
733     yasm_objfmt_macho *objfmt_macho;
734     /*@dependent@*/ /*@null@*/ macho_section_data *msd;
735     unsigned char *localbuf;
736 
737     assert(info != NULL);
738     objfmt_macho = info->objfmt_macho;
739     msd = yasm_section_get_data(sect, &macho_section_data_cb);
740     assert(msd != NULL);
741 
742     localbuf = info->buf;
743 
744     memset(localbuf, 0, 16);
745     strncpy((char *)localbuf, msd->sectname, 16);
746     localbuf += 16;
747     memset(localbuf, 0, 16);
748     strncpy((char *)localbuf, msd->segname, 16);
749     localbuf += 16;
750     /* section address, size depend on 32/64 bit mode */
751     YASM_WRITE_32_L(localbuf, msd->vmoff);      /* address in memory */
752     if (info->is_64)
753         YASM_WRITE_32_L(localbuf, 0);   /* 64-bit mode: upper 32 bits = 0 */
754     YASM_WRITE_32_L(localbuf, msd->size);       /* size in memory */
755     if (info->is_64)
756         YASM_WRITE_32_L(localbuf, 0);   /* 64-bit mode: upper 32 bits = 0 */
757 
758     /* offset,align,reloff,nreloc,flags,reserved1,reserved2 are 32 bit */
759     if ((msd->flags & SECTION_TYPE) != S_ZEROFILL) {
760         YASM_WRITE_32_L(localbuf, msd->offset);
761         YASM_WRITE_32_L(localbuf, exp2_to_bits(yasm_section_get_align(sect)));
762         if (msd->nreloc) {
763             msd->flags |= S_ATTR_LOC_RELOC;
764             if (msd->extreloc)
765                 msd->flags |= S_ATTR_EXT_RELOC;
766             YASM_WRITE_32_L(localbuf,
767                             align32((long)(info->rel_base + info->s_reloff)));
768             YASM_WRITE_32_L(localbuf, msd->nreloc);     /* nreloc */
769         } else {
770             YASM_WRITE_32_L(localbuf, 0);
771             YASM_WRITE_32_L(localbuf, 0);
772         }
773 
774         info->s_reloff += msd->nreloc * MACHO_RELINFO_SIZE;     /* nreloc */
775     } else {
776         YASM_WRITE_32_L(localbuf, 0);   /* these are zero in BSS */
777         YASM_WRITE_32_L(localbuf, 0);
778         YASM_WRITE_32_L(localbuf, 0);
779         YASM_WRITE_32_L(localbuf, 0);
780     }
781 
782     YASM_WRITE_32_L(localbuf, msd->flags);      /* flags */
783     YASM_WRITE_32_L(localbuf, 0);       /* reserved 1 */
784     YASM_WRITE_32_L(localbuf, 0);       /* reserved 2 */
785 
786     if (info->is_64)
787         fwrite(info->buf, MACHO_SECTCMD64_SIZE, 1, info->f);
788     else
789         fwrite(info->buf, MACHO_SECTCMD_SIZE, 1, info->f);
790 
791     return 0;
792 }
793 
794 
795 static int
macho_objfmt_count_sym(yasm_symrec * sym,void * d)796 macho_objfmt_count_sym(yasm_symrec *sym, /*@null@*/ void *d)
797 {
798     /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
799     /*@only@*/ char *name;
800     yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
801 
802     assert(info != NULL);
803     if (info->all_syms ||
804         vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
805         if (0 == macho_objfmt_is_section_label(sym)) {
806             /* Save index in symrec data */
807             macho_symrec_data *sym_data =
808                 yasm_symrec_get_data(sym, &macho_symrec_data_cb);
809             if (!sym_data) {
810                 sym_data = yasm_xcalloc(sizeof(macho_symrec_data), 1);
811                 yasm_symrec_add_data(sym, &macho_symrec_data_cb, sym_data);
812             }
813             sym_data->index = info->symindex;
814             info->symindex++;
815 
816             name = yasm_symrec_get_global_name(sym, info->object);
817             /*printf("%s\n",name); */
818             /* name length + delimiter */
819             sym_data->length = (unsigned long)strlen(name) + 1;
820             info->strlength += sym_data->length;
821             info->indx++;
822             yasm_xfree(name);
823         }
824     }
825     return 0;
826 }
827 
828 
829 static int
macho_objfmt_output_symtable(yasm_symrec * sym,void * d)830 macho_objfmt_output_symtable(yasm_symrec *sym, /*@null@*/ void *d)
831 {
832     /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
833     yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
834 
835     assert(info != NULL);
836 
837     if (info->all_syms ||
838         vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
839         const yasm_expr *equ_val;
840         const yasm_intnum *intn;
841         unsigned long value = 0;
842         long scnum = -3;        /* -3 = debugging symbol */
843         /*@dependent@*/ /*@null@*/ yasm_section *sect;
844         /*@dependent@*/ /*@null@*/ yasm_bytecode *precbc;
845         unsigned char *localbuf;
846         yasm_intnum *val;
847         unsigned int long_int_bytes = (info->is_64) ? 8 : 4;
848         unsigned int n_type = 0, n_sect = 0, n_desc = 0;
849         macho_symrec_data *symd;
850 
851         val = yasm_intnum_create_uint(0);
852 
853         symd = yasm_symrec_get_data(sym, &macho_symrec_data_cb);
854 
855         /* Look at symrec for value/scnum/etc. */
856         if (yasm_symrec_get_label(sym, &precbc)) {
857             if (precbc)
858                 sect = yasm_bc_get_section(precbc);
859             else
860                 sect = NULL;
861             /* it's a label: get value and offset.
862              * If there is not a section, leave as debugging symbol.
863              */
864             if (sect) {
865                 /*@dependent@*/ /*@null@*/ macho_section_data *msd;
866 
867                 msd = yasm_section_get_data(sect, &macho_section_data_cb);
868                 if (msd) {
869                     if (msd->sym == sym) {
870                         /* don't store section names */
871                         yasm_intnum_destroy(val);
872                         return 0;
873                     }
874                     scnum = msd->scnum;
875                     n_type = N_SECT;
876                 } else
877                     yasm_internal_error(N_("didn't understand section"));
878                 if (precbc)
879                     value += yasm_bc_next_offset(precbc);
880                 /* all values are subject to correction: base offset is first
881                  * raw section, therefore add section offset
882                  */
883                 if (msd)
884                     value += msd->vmoff;
885                 yasm_intnum_set_uint(val, value);
886                 /*printf("%s offset %lx\n",name,value);*/
887             }
888         } else if ((equ_val = yasm_symrec_get_equ(sym))) {
889             yasm_expr *equ_val_copy = yasm_expr_copy(equ_val);
890 
891             intn = yasm_expr_get_intnum(&equ_val_copy, 1);
892             if (!intn) {
893                 if (vis & YASM_SYM_GLOBAL) {
894                     yasm_error_set(YASM_ERROR_NOT_CONSTANT,
895                         N_("global EQU value not an integer expression"));
896                     yasm_errwarn_propagate(info->errwarns, equ_val->line);
897                 }
898             } else
899                 value = yasm_intnum_get_uint(intn);
900             yasm_expr_destroy(equ_val_copy);
901             yasm_intnum_set_uint(val, value);
902             n_type = N_ABS;
903             scnum = -2;         /* -2 = absolute symbol */
904         }
905 
906         if (vis & YASM_SYM_EXTERN) {
907             n_type = N_EXT;
908             scnum = -1;
909             /*n_desc = REFERENCE_FLAG_UNDEFINED_LAZY;   * FIXME: see definition of REFERENCE_FLAG_* above */
910         } else if (vis & YASM_SYM_COMMON) {
911             yasm_expr **csize = yasm_symrec_get_common_size(sym);
912             n_type = N_UNDF | N_EXT;
913             if (csize) {
914                 intn = yasm_expr_get_intnum(csize, 1);
915                 if (!intn) {
916                     yasm_error_set(YASM_ERROR_NOT_CONSTANT,
917                                    N_("COMMON data size not an integer expression"));
918                     yasm_errwarn_propagate(info->errwarns, (*csize)->line);
919                 } else
920                     yasm_intnum_set_uint(val, yasm_intnum_get_uint(intn));
921             }
922             /*printf("common symbol %s val %lu\n", name, yasm_intnum_get_uint(val));*/
923         } else if (vis & YASM_SYM_GLOBAL) {
924             yasm_valparamhead *valparams =
925                 yasm_symrec_get_objext_valparams(sym);
926 
927             struct macho_global_data {
928                 unsigned long flag; /* N_PEXT */
929             } data;
930 
931             data.flag = 0;
932 
933             if (valparams) {
934                 static const yasm_dir_help help[] = {
935                     { "private_extern", 0, yasm_dir_helper_flag_set,
936                       offsetof(struct macho_global_data, flag), N_PEXT },
937                 };
938                 yasm_dir_helper(sym, yasm_vps_first(valparams),
939                                 yasm_symrec_get_decl_line(sym), help, NELEMS(help),
940                                 &data, yasm_dir_helper_valparam_warn);
941             }
942 
943             n_type |= N_EXT | data.flag;
944         }
945 
946         localbuf = info->buf;
947         YASM_WRITE_32_L(localbuf, info->indx);  /* offset in string table */
948         YASM_WRITE_8(localbuf, n_type); /* type of symbol entry */
949         n_sect = (scnum >= 0) ? scnum + 1 : NO_SECT;
950         YASM_WRITE_8(localbuf, n_sect); /* referring section where symbol is found */
951         YASM_WRITE_16_L(localbuf, n_desc);      /* extra description */
952         yasm_intnum_get_sized(val, localbuf, long_int_bytes, ((long_int_bytes) << 3), 0, 0, 0); /* value/argument */
953         localbuf += long_int_bytes;
954         if (symd)
955             symd->value = val;
956         else
957             yasm_intnum_destroy(val);
958 
959         info->indx += symd->length;
960 
961         fwrite(info->buf, 8 + long_int_bytes, 1, info->f);
962     }
963 
964     return 0;
965 }
966 
967 
968 static int
macho_objfmt_output_str(yasm_symrec * sym,void * d)969 macho_objfmt_output_str(yasm_symrec *sym, /*@null@*/ void *d)
970 {
971     /*@null@*/ macho_objfmt_output_info *info = (macho_objfmt_output_info *)d;
972     yasm_sym_vis vis = yasm_symrec_get_visibility(sym);
973     /*@null@*/ macho_symrec_data *xsymd;
974 
975 
976     assert(info != NULL);
977 
978     if (info->all_syms ||
979         vis & (YASM_SYM_GLOBAL | YASM_SYM_COMMON | YASM_SYM_EXTERN)) {
980         if (0 == macho_objfmt_is_section_label(sym)) {
981             /*@only@*/ char *name =
982                 yasm_symrec_get_global_name(sym, info->object);
983             size_t len = strlen(name);
984 
985             xsymd = yasm_symrec_get_data(sym, &macho_symrec_data_cb);
986             fwrite(name, len + 1, 1, info->f);
987             yasm_xfree(name);
988         }
989     }
990     return 0;
991 }
992 
993 static int
macho_objfmt_calc_sectsize(yasm_section * sect,void * d)994 macho_objfmt_calc_sectsize(yasm_section *sect, /*@null@ */ void *d)
995 {
996     /*@null@ */ macho_objfmt_output_info *info =
997         (macho_objfmt_output_info *) d;
998     /*@dependent@ *//*@null@ */ macho_section_data *msd;
999     unsigned long align;
1000 
1001     assert(info != NULL);
1002     msd = yasm_section_get_data(sect, &macho_section_data_cb);
1003     assert(msd != NULL);
1004 
1005     msd->size = yasm_bc_next_offset(yasm_section_bcs_last(sect));
1006     if (!(msd->flags & S_ZEROFILL)) {
1007         msd->offset = info->offset;
1008         info->offset += msd->size;
1009         info->filesize += msd->size;
1010     }
1011 
1012     /* accumulate size in memory */
1013     msd->vmoff = info->vmsize;
1014     info->vmsize += msd->size;
1015 
1016     /* align both start and end of section */
1017     align = yasm_section_get_align(sect);
1018     if (align != 0) {
1019         unsigned long delta = msd->vmoff % align;
1020         if (delta > 0) {
1021             msd->vmoff += align - delta;
1022             info->vmsize += align - delta;
1023         }
1024     }
1025 
1026     return 0;
1027 }
1028 
1029 /* write object */
1030 static void
macho_objfmt_output(yasm_object * object,FILE * f,int all_syms,yasm_errwarns * errwarns)1031 macho_objfmt_output(yasm_object *object, FILE *f, int all_syms,
1032                     yasm_errwarns *errwarns)
1033 {
1034     yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
1035     macho_objfmt_output_info info;
1036     unsigned char *localbuf;
1037     unsigned long symtab_count = 0;
1038     unsigned long headsize;
1039     unsigned int macho_segcmdsize, macho_sectcmdsize, macho_nlistsize;
1040     unsigned int macho_relinfosize, macho_segcmd;
1041     unsigned int head_ncmds, head_sizeofcmds;
1042     unsigned long fileoffset, fileoff_sections;
1043     yasm_intnum *val;
1044     unsigned long long_int_bytes;
1045     const char pad_data[3] = "\0\0\0";
1046 
1047     info.object = object;
1048     info.objfmt_macho = objfmt_macho;
1049     info.errwarns = errwarns;
1050     info.f = f;
1051     info.buf = yasm_xmalloc(REGULAR_OUTBUF_SIZE);
1052 
1053     if (objfmt_macho->parse_scnum == 0) {
1054         yasm_internal_error(N_("no sections defined"));
1055         /*@notreached@*/
1056         return;
1057     }
1058 
1059     val = yasm_intnum_create_uint(0);
1060 
1061     /*
1062      * MACH-O Header, Seg CMD, Sect CMDs, Sym Tab, Reloc Data
1063      */
1064     info.is_64 = (objfmt_macho->bits == 32) ? 0 : 1;
1065     if (info.is_64) {
1066         /* this works only when SYMBOLS and SECTIONS present */
1067         headsize =
1068             MACHO_HEADER64_SIZE + MACHO_SEGCMD64_SIZE +
1069             (MACHO_SECTCMD64_SIZE * (objfmt_macho->parse_scnum)) +
1070             MACHO_SYMCMD_SIZE;
1071         macho_segcmd = LC_SEGMENT_64;
1072         macho_segcmdsize = MACHO_SEGCMD64_SIZE;
1073         macho_sectcmdsize = MACHO_SECTCMD64_SIZE;
1074         macho_nlistsize = MACHO_NLIST64_SIZE;
1075         macho_relinfosize = MACHO_RELINFO64_SIZE;
1076         long_int_bytes = 8;
1077     } else {
1078         headsize =
1079             MACHO_HEADER_SIZE + MACHO_SEGCMD_SIZE +
1080             (MACHO_SECTCMD_SIZE * (objfmt_macho->parse_scnum)) +
1081             MACHO_SYMCMD_SIZE;
1082         macho_segcmd = LC_SEGMENT;
1083         macho_segcmdsize = MACHO_SEGCMD_SIZE;
1084         macho_sectcmdsize = MACHO_SECTCMD_SIZE;
1085         macho_nlistsize = MACHO_NLIST_SIZE;
1086         macho_relinfosize = MACHO_RELINFO_SIZE;
1087         long_int_bytes = 4;
1088     }
1089 
1090     /* Get number of symbols */
1091     info.symindex = 0;
1092     info.indx = 0;
1093     info.strlength = 1;         /* string table starts with a zero byte */
1094     info.all_syms = all_syms || info.is_64;
1095     /*info.all_syms = 1;                * force all syms into symbol table */
1096     yasm_symtab_traverse(object->symtab, &info, macho_objfmt_count_sym);
1097     symtab_count = info.indx;
1098 
1099     /* write raw section data first */
1100     if (fseek(f, (long)headsize, SEEK_SET) < 0) {
1101         yasm__fatal(N_("could not seek on output file"));
1102         /*@notreached@ */
1103         return;
1104     }
1105 
1106     /* get size of sections in memory (including BSS) and size of sections
1107      * in file (without BSS)
1108      */
1109     info.vmsize = 0;
1110     info.filesize = 0;
1111     info.offset = headsize;
1112     yasm_object_sections_traverse(object, &info, macho_objfmt_calc_sectsize);
1113 
1114     /* output sections to file */
1115     yasm_object_sections_traverse(object, &info, macho_objfmt_output_section);
1116 
1117     fileoff_sections = ftell(f);
1118 
1119     /* Write headers */
1120     if (fseek(f, 0, SEEK_SET) < 0) {
1121         yasm__fatal(N_("could not seek on output file"));
1122         /*@notreached@*/
1123         return;
1124     }
1125 
1126     localbuf = info.buf;
1127 
1128     /* header size is common to 32 bit and 64 bit variants */
1129     if (info.is_64) {
1130         YASM_WRITE_32_L(localbuf, MH_MAGIC_64); /* magic number */
1131         /* i386 64-bit ABI */
1132         YASM_WRITE_32_L(localbuf, CPU_ARCH_ABI64 | CPU_TYPE_I386);
1133     } else {
1134         YASM_WRITE_32_L(localbuf, MH_MAGIC);    /* magic number */
1135         YASM_WRITE_32_L(localbuf, CPU_TYPE_I386);       /* i386 32-bit ABI */
1136     }
1137     /* i386 all cpu subtype compatible */
1138     YASM_WRITE_32_L(localbuf, CPU_SUBTYPE_I386_ALL);
1139     YASM_WRITE_32_L(localbuf, MH_OBJECT);       /* MACH file type */
1140 
1141     /* calculate number of commands and their size, put to stream */
1142     head_ncmds = 0;
1143     head_sizeofcmds = 0;
1144     if (objfmt_macho->parse_scnum > 0) {
1145         head_ncmds++;
1146         head_sizeofcmds +=
1147             macho_segcmdsize + macho_sectcmdsize * objfmt_macho->parse_scnum;
1148     }
1149     if (symtab_count > 0) {
1150         head_ncmds++;
1151         head_sizeofcmds += MACHO_SYMCMD_SIZE;
1152     }
1153 
1154     YASM_WRITE_32_L(localbuf, head_ncmds);
1155     YASM_WRITE_32_L(localbuf, head_sizeofcmds);
1156     YASM_WRITE_32_L(localbuf, 0);       /* no flags (yet) */
1157     if (info.is_64) {
1158         YASM_WRITE_32_L(localbuf, 0);   /* reserved in 64 bit */
1159         fileoffset = MACHO_HEADER64_SIZE + head_sizeofcmds;
1160     } else {
1161         /* initial offset to first section */
1162         fileoffset = MACHO_HEADER_SIZE + head_sizeofcmds;
1163     }
1164 
1165     /* --------------- write segment header command ---------------- */
1166     YASM_WRITE_32_L(localbuf, macho_segcmd);    /* command LC_SEGMENT */
1167     /* size of load command including section load commands */
1168     YASM_WRITE_32_L(localbuf,
1169                     macho_segcmdsize +
1170                     macho_sectcmdsize * objfmt_macho->parse_scnum);
1171     /* in an MH_OBJECT file all sections are in one unnamed (name all zeros)
1172      * segment (16x0)
1173      */
1174     YASM_WRITE_32_L(localbuf, 0);
1175     YASM_WRITE_32_L(localbuf, 0);
1176     YASM_WRITE_32_L(localbuf, 0);
1177     YASM_WRITE_32_L(localbuf, 0);
1178 
1179     /* in-memory offset, in-memory size */
1180     yasm_intnum_set_uint(val, 0);       /* offset in memory (vmaddr) */
1181     yasm_intnum_get_sized(val, localbuf, long_int_bytes,
1182                           ((long_int_bytes) << 3), 0, 0, 0);
1183     localbuf += long_int_bytes;
1184     yasm_intnum_set_uint(val, info.vmsize);     /* size in memory (vmsize) */
1185     yasm_intnum_get_sized(val, localbuf, long_int_bytes,
1186                           ((long_int_bytes) << 3), 0, 0, 0);
1187     localbuf += long_int_bytes;
1188     /* offset in file to first section */
1189     yasm_intnum_set_uint(val, fileoffset);
1190     yasm_intnum_get_sized(val, localbuf, long_int_bytes,
1191                           ((long_int_bytes) << 3), 0, 0, 0);
1192     localbuf += long_int_bytes;
1193     yasm_intnum_set_uint(val, info.filesize);   /* overall size in file */
1194     yasm_intnum_get_sized(val, localbuf, long_int_bytes,
1195                           ((long_int_bytes) << 3), 0, 0, 0);
1196     localbuf += long_int_bytes;
1197 
1198     YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, maximum */
1199     YASM_WRITE_32_L(localbuf, VM_PROT_DEFAULT); /* VM protection, initial */
1200     /* number of sections */
1201     YASM_WRITE_32_L(localbuf, objfmt_macho->parse_scnum);
1202     YASM_WRITE_32_L(localbuf, 0);       /* no flags */
1203 
1204     /* write MACH-O header and segment command to outfile */
1205     fwrite(info.buf, (size_t) (localbuf - info.buf), 1, f);
1206 
1207     /* next: section headers */
1208     /* offset to relocs for first section */
1209     info.rel_base = align32((long)fileoff_sections);
1210     info.s_reloff = 0;          /* offset for relocs of following sections */
1211     yasm_object_sections_traverse(object, &info, macho_objfmt_output_secthead);
1212 
1213     localbuf = info.buf;
1214     /* write out symbol command */
1215     YASM_WRITE_32_L(localbuf, LC_SYMTAB);       /* cmd == LC_SYMTAB */
1216     YASM_WRITE_32_L(localbuf, MACHO_SYMCMD_SIZE);
1217     /* symbol table offset */
1218     YASM_WRITE_32_L(localbuf, info.rel_base + info.s_reloff);
1219     YASM_WRITE_32_L(localbuf, symtab_count);    /* number of symbols */
1220 
1221     YASM_WRITE_32_L(localbuf, macho_nlistsize * symtab_count + info.rel_base +
1222                     info.s_reloff);     /* string table offset */
1223     YASM_WRITE_32_L(localbuf, info.strlength);  /* string table size */
1224     /* write symbol command */
1225     fwrite(info.buf, (size_t)(localbuf - info.buf), 1, f);
1226 
1227     /*printf("num symbols %d, vmsize %d, filesize %d\n",symtab_count,
1228       info.vmsize, info.filesize ); */
1229 
1230     /* get back to end of raw section data */
1231     if (fseek(f, (long)fileoff_sections, SEEK_SET) < 0) {
1232         yasm__fatal(N_("could not seek on output file"));
1233         /*@notreached@*/
1234         return;
1235     }
1236 
1237     /* padding to long boundary */
1238     if ((info.rel_base - fileoff_sections) > 0) {
1239         fwrite(pad_data, info.rel_base - fileoff_sections, 1, f);
1240     }
1241 
1242     /* relocation data */
1243     yasm_object_sections_traverse(object, &info, macho_objfmt_output_relocs);
1244 
1245     /* symbol table (NLIST) */
1246     info.indx = 1;              /* restart symbol table indices */
1247     yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_symtable);
1248 
1249     /* symbol strings */
1250     fwrite(pad_data, 1, 1, f);
1251     yasm_symtab_traverse(object->symtab, &info, macho_objfmt_output_str);
1252 
1253     yasm_intnum_destroy(val);
1254     yasm_xfree(info.buf);
1255 }
1256 
1257 static void
macho_objfmt_destroy(yasm_objfmt * objfmt)1258 macho_objfmt_destroy(yasm_objfmt *objfmt)
1259 {
1260     yasm_xfree(objfmt);
1261 }
1262 
1263 static void
macho_objfmt_init_new_section(yasm_section * sect,unsigned long line)1264 macho_objfmt_init_new_section(yasm_section *sect, unsigned long line)
1265 {
1266     yasm_object *object = yasm_section_get_object(sect);
1267     const char *sectname = yasm_section_get_name(sect);
1268     yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
1269     macho_section_data *data;
1270     yasm_symrec *sym;
1271 
1272     data = yasm_xmalloc(sizeof(macho_section_data));
1273     data->scnum = objfmt_macho->parse_scnum++;
1274     data->segname = NULL;
1275     data->sectname = NULL;
1276     data->flags = S_REGULAR;
1277     data->size = 0;
1278     data->offset = 0;
1279     data->vmoff = 0;
1280     data->nreloc = 0;
1281     data->extreloc = 0;
1282     yasm_section_add_data(sect, &macho_section_data_cb, data);
1283 
1284     sym = yasm_symtab_define_label(object->symtab, sectname,
1285                                    yasm_section_bcs_first(sect), 1, line);
1286     data->sym = sym;
1287 }
1288 
1289 static yasm_section *
macho_objfmt_add_default_section(yasm_object * object)1290 macho_objfmt_add_default_section(yasm_object *object)
1291 {
1292     yasm_section *retval;
1293     macho_section_data *msd;
1294     int isnew;
1295 
1296     retval = yasm_object_get_general(object, "LC_SEGMENT.__TEXT.__text", 0, 1,
1297                                      0, &isnew, 0);
1298     if (isnew) {
1299         msd = yasm_section_get_data(retval, &macho_section_data_cb);
1300         msd->segname = yasm__xstrdup("__TEXT");
1301         msd->sectname = yasm__xstrdup("__text");
1302         msd->flags = S_ATTR_PURE_INSTRUCTIONS;
1303         yasm_section_set_align(retval, 0, 0);
1304         yasm_section_set_default(retval, 1);
1305     }
1306     return retval;
1307 }
1308 
1309 static /*@observer@*/ /*@null@*/ yasm_section *
macho_objfmt_section_switch(yasm_object * object,yasm_valparamhead * valparams,yasm_valparamhead * objext_valparams,unsigned long line)1310 macho_objfmt_section_switch(yasm_object *object, yasm_valparamhead *valparams,
1311                             /*@unused@*/ /*@null@*/
1312                             yasm_valparamhead *objext_valparams,
1313                             unsigned long line)
1314 {
1315     yasm_valparam *vp;
1316     yasm_section *retval;
1317     int isnew;
1318     /*@only@*/ char *f_sectname;
1319     unsigned long flags;
1320     unsigned long align;
1321     int flags_override = 0;
1322     const char *sectname;
1323     char *realname;
1324     int resonly = 0;
1325     macho_section_data *msd;
1326     size_t i;
1327 
1328     static const struct {
1329         const char *in;
1330         const char *seg;
1331         const char *sect;
1332         unsigned long flags;
1333         unsigned long align;
1334     } section_name_translation[] = {
1335         {".text",           "__TEXT", "__text", S_ATTR_PURE_INSTRUCTIONS, 0},
1336         {".const",          "__TEXT", "__const",        S_REGULAR, 0},
1337         {".static_const",   "__TEXT", "__static_const", S_REGULAR, 0},
1338         {".cstring",        "__TEXT", "__cstring",      S_CSTRING_LITERALS, 0},
1339         {".literal4",       "__TEXT", "__literal4",     S_4BYTE_LITERALS, 4},
1340         {".literal8",       "__TEXT", "__literal8",     S_8BYTE_LITERALS, 8},
1341         {".literal16",      "__TEXT", "__literal16",    S_16BYTE_LITERALS, 16},
1342         {".constructor",    "__TEXT", "__constructor",  S_REGULAR, 0},
1343         {".destructor",     "__TEXT", "__destructor",   S_REGULAR, 0},
1344         {".fvmlib_init0",   "__TEXT", "__fvmlib_init0", S_REGULAR, 0},
1345         {".fvmlib_init1",   "__TEXT", "__fvmlib_init1", S_REGULAR, 0},
1346         {".mod_init_func",  "__DATA", "__mod_init_func",
1347             S_MOD_INIT_FUNC_POINTERS, 4},
1348         {".mod_term_func",  "__DATA", "__mod_term_func",
1349             S_MOD_TERM_FUNC_POINTERS, 4},
1350         {".dyld",           "__DATA", "__dyld",         S_REGULAR, 0},
1351         {".data",           "__DATA", "__data",         S_REGULAR, 0},
1352         {".static_data",    "__DATA", "__static_data",  S_REGULAR, 0},
1353         {".const_data",     "__DATA", "__const",        S_REGULAR, 0},
1354         {".rodata",         "__DATA", "__const",        S_REGULAR, 0},
1355         {".bss",            "__DATA", "__bss",          S_ZEROFILL, 0},
1356         {".objc_class_names",   "__TEXT", "__cstring",  S_CSTRING_LITERALS, 0},
1357         {".objc_meth_var_types","__TEXT", "__cstring",  S_CSTRING_LITERALS, 0},
1358         {".objc_meth_var_names","__TEXT", "__cstring",  S_CSTRING_LITERALS, 0},
1359         {".objc_selector_strs", "__OBJC", "__selector_strs",
1360             S_CSTRING_LITERALS, 0},
1361         {".objc_class",         "__OBJC", "__class",
1362             S_ATTR_NO_DEAD_STRIP, 0},
1363         {".objc_meta_class",    "__OBJC", "__meta_class",
1364             S_ATTR_NO_DEAD_STRIP, 0},
1365         {".objc_string_object", "__OBJC", "__string_object",
1366             S_ATTR_NO_DEAD_STRIP, 0},
1367         {".objc_protocol",      "__OBJC", "__protocol",
1368             S_ATTR_NO_DEAD_STRIP, 0},
1369         {".objc_cat_cls_meth",  "__OBJC", "__cat_cls_meth",
1370             S_ATTR_NO_DEAD_STRIP, 0},
1371         {".objc_cat_inst_meth", "__OBJC", "__cat_inst_meth",
1372             S_ATTR_NO_DEAD_STRIP, 0},
1373         {".objc_cls_meth",      "__OBJC", "__cls_meth",
1374             S_ATTR_NO_DEAD_STRIP, 0},
1375         {".objc_inst_meth",     "__OBJC", "__inst_meth",
1376             S_ATTR_NO_DEAD_STRIP, 0},
1377         {".objc_message_refs",  "__OBJC", "__message_refs",
1378             S_LITERAL_POINTERS|S_ATTR_NO_DEAD_STRIP, 4},
1379         {".objc_cls_refs",      "__OBJC", "__cls_refs",
1380             S_LITERAL_POINTERS|S_ATTR_NO_DEAD_STRIP, 4},
1381         {".objc_module_info",   "__OBJC", "__module_info",
1382             S_ATTR_NO_DEAD_STRIP, 0},
1383         {".objc_symbols",       "__OBJC", "__symbols",
1384             S_ATTR_NO_DEAD_STRIP, 0},
1385         {".objc_category",      "__OBJC", "__category",
1386             S_ATTR_NO_DEAD_STRIP, 0},
1387         {".objc_class_vars",    "__OBJC", "__class_vars",
1388             S_ATTR_NO_DEAD_STRIP, 0},
1389         {".objc_instance_vars", "__OBJC", "__instance_vars",
1390             S_ATTR_NO_DEAD_STRIP, 0}
1391     };
1392 
1393     struct macho_section_switch_data {
1394         /*@only@*/ /*@null@*/ char *f_segname;
1395         /*@only@*/ /*@null@*/ yasm_intnum *align_intn;
1396     } data;
1397 
1398     static const yasm_dir_help help[] = {
1399         { "segname", 1, yasm_dir_helper_string,
1400           offsetof(struct macho_section_switch_data, f_segname), 0 },
1401         { "align", 1, yasm_dir_helper_intn,
1402           offsetof(struct macho_section_switch_data, align_intn), 0 }
1403     };
1404 
1405     data.f_segname = NULL;
1406     data.align_intn = NULL;
1407 
1408     vp = yasm_vps_first(valparams);
1409     sectname = yasm_vp_string(vp);
1410     if (!sectname)
1411         return NULL;
1412     vp = yasm_vps_next(vp);
1413 
1414     /* translate .text,.data,.bss to __text,__data,__bss... */
1415     for (i=0; i<NELEMS(section_name_translation); i++) {
1416         if (yasm__strcasecmp(sectname, section_name_translation[i].in) == 0)
1417             break;
1418     }
1419 
1420     if (i == NELEMS(section_name_translation)) {
1421         const char *s;
1422         if (vp && !vp->val && (s = yasm_vp_string(vp))) {
1423             /* Treat as SEGNAME, SECTNAME */
1424             if (strlen(sectname) > 16)
1425                 yasm_warn_set(YASM_WARN_GENERAL,
1426                     N_("segment name is too long, max 16 chars; truncating"));
1427             data.f_segname = yasm__xstrndup(sectname, 16);
1428             if (strlen(s) > 16)
1429                 yasm_warn_set(YASM_WARN_GENERAL,
1430                     N_("section name is too long, max 16 chars; truncating"));
1431             f_sectname = yasm__xstrndup(s, 16);
1432             flags = S_REGULAR;
1433             align = 0;
1434 
1435             sectname = s;
1436             vp = yasm_vps_next(vp);
1437         } else {
1438             data.f_segname = NULL;
1439             if (strlen(sectname) > 16)
1440                 yasm_warn_set(YASM_WARN_GENERAL,
1441                     N_("section name is too long, max 16 chars; truncating"));
1442             f_sectname = yasm__xstrndup(sectname, 16);
1443             flags = S_ATTR_SOME_INSTRUCTIONS;
1444             align = 0;
1445         }
1446     } else {
1447         data.f_segname = yasm__xstrdup(section_name_translation[i].seg);
1448         f_sectname = yasm__xstrdup(section_name_translation[i].sect);
1449         flags = section_name_translation[i].flags;
1450         align = section_name_translation[i].align;
1451     }
1452 
1453     flags_override = yasm_dir_helper(object, vp, line, help, NELEMS(help),
1454                                      &data, yasm_dir_helper_valparam_warn);
1455     if (flags_override < 0)
1456         return NULL;    /* error occurred */
1457 
1458     if (data.align_intn) {
1459         align = yasm_intnum_get_uint(data.align_intn);
1460         yasm_intnum_destroy(data.align_intn);
1461 
1462         /* Alignments must be a power of two. */
1463         if (!is_exp2(align)) {
1464             yasm_error_set(YASM_ERROR_VALUE,
1465                            N_("argument to `%s' is not a power of two"),
1466                            vp->val);
1467             return NULL;
1468         }
1469 
1470         /* Check to see if alignment is supported size */
1471         if (align > 16384) {
1472             yasm_error_set(YASM_ERROR_VALUE,
1473                 N_("macho implementation does not support alignments > 16384"));
1474             return NULL;
1475         }
1476     }
1477 
1478     if (!data.f_segname) {
1479         yasm_warn_set(YASM_WARN_GENERAL,
1480                       N_("Unknown section name, defaulting to __TEXT segment"));
1481         data.f_segname = yasm__xstrdup("__TEXT");
1482     }
1483 
1484     /* Build a unique sectname from f_segname and f_sectname. */
1485     realname = yasm_xmalloc(strlen("LC_SEGMENT") + 1 + strlen(data.f_segname) + 1 +
1486                             strlen(f_sectname) + 1);
1487     sprintf(realname, "LC_SEGMENT.%s.%s", data.f_segname, f_sectname);
1488     retval = yasm_object_get_general(object, realname, align, 1, resonly,
1489                                      &isnew, line);
1490     yasm_xfree(realname);
1491 
1492     msd = yasm_section_get_data(retval, &macho_section_data_cb);
1493 
1494     if (isnew || yasm_section_is_default(retval)) {
1495         yasm_section_set_default(retval, 0);
1496         msd->segname = data.f_segname;
1497         msd->sectname = f_sectname;
1498         msd->flags = flags;
1499         yasm_section_set_align(retval, align, line);
1500     } else if (flags_override) {
1501         /* align is the only value used from overrides. */
1502         if (yasm_section_get_align(retval) != align) {
1503             yasm_warn_set(YASM_WARN_GENERAL,
1504                           N_("section flags ignored on section redeclaration"));
1505         }
1506     }
1507     return retval;
1508 }
1509 
1510 static /*@observer@*/ /*@null@*/ yasm_symrec *
macho_objfmt_get_special_sym(yasm_object * object,const char * name,const char * parser)1511 macho_objfmt_get_special_sym(yasm_object *object, const char *name,
1512                              const char *parser)
1513 {
1514     yasm_objfmt_macho *objfmt_macho = (yasm_objfmt_macho *)object->objfmt;
1515     if (yasm__strcasecmp(name, "gotpcrel") == 0) {
1516         return objfmt_macho->gotpcrel_sym;
1517     }
1518     return NULL;
1519 }
1520 
1521 static void
macho_section_data_destroy(void * data)1522 macho_section_data_destroy(void *data)
1523 {
1524     macho_section_data *msd = (macho_section_data *) data;
1525     yasm_xfree(msd->segname);
1526     yasm_xfree(msd->sectname);
1527     yasm_xfree(data);
1528 }
1529 
1530 static void
macho_section_data_print(void * data,FILE * f,int indent_level)1531 macho_section_data_print(void *data, FILE *f, int indent_level)
1532 {
1533     macho_section_data *msd = (macho_section_data *) data;
1534 
1535     fprintf(f, "%*ssym=\n", indent_level, "");
1536     yasm_symrec_print(msd->sym, f, indent_level + 1);
1537     fprintf(f, "%*sscnum=%ld\n", indent_level, "", msd->scnum);
1538     fprintf(f, "%*sflags=0x%lx\n", indent_level, "", msd->flags);
1539     fprintf(f, "%*ssize=%lu\n", indent_level, "", msd->size);
1540     fprintf(f, "%*snreloc=%lu\n", indent_level, "", msd->nreloc);
1541     fprintf(f, "%*soffset=%lu\n", indent_level, "", msd->offset);
1542     fprintf(f, "%*sextreloc=%u\n", indent_level, "", msd->extreloc);
1543 }
1544 
1545 static void
macho_symrec_data_destroy(void * data)1546 macho_symrec_data_destroy(void *data)
1547 {
1548     yasm_xfree(data);
1549 }
1550 
1551 static void
macho_symrec_data_print(void * data,FILE * f,int indent_level)1552 macho_symrec_data_print(void *data, FILE *f, int indent_level)
1553 {
1554     macho_symrec_data *msd = (macho_symrec_data *)data;
1555 
1556     fprintf(f, "%*sindex=%ld\n", indent_level, "", msd->index);
1557     fprintf(f, "%*svalue=", indent_level, "");
1558     if (msd->value)
1559         fprintf(f, "%ld\n", yasm_intnum_get_int(msd->value));
1560     else
1561         fprintf(f, "nil\n");
1562 }
1563 
1564 
1565 /* Define valid debug formats to use with this object format */
1566 static const char *macho_objfmt_dbgfmt_keywords[] = {
1567     "null",
1568     NULL
1569 };
1570 
1571 /* Define objfmt structure -- see objfmt.h for details */
1572 yasm_objfmt_module yasm_macho_LTX_objfmt = {
1573     "Mac OS X ABI Mach-O File Format",
1574     "macho",
1575     "o",
1576     32,
1577     0,
1578     macho_objfmt_dbgfmt_keywords,
1579     "null",
1580     NULL,   /* no directives */
1581     NULL,   /* no standard macros */
1582     macho_objfmt_create,
1583     macho_objfmt_output,
1584     macho_objfmt_destroy,
1585     macho_objfmt_add_default_section,
1586     macho_objfmt_init_new_section,
1587     macho_objfmt_section_switch,
1588     macho_objfmt_get_special_sym
1589 };
1590 
1591 yasm_objfmt_module yasm_macho32_LTX_objfmt = {
1592     "Mac OS X ABI Mach-O File Format (32-bit)",
1593     "macho32",
1594     "o",
1595     32,
1596     0,
1597     macho_objfmt_dbgfmt_keywords,
1598     "null",
1599     NULL,   /* no directives */
1600     NULL,   /* no standard macros */
1601     macho32_objfmt_create,
1602     macho_objfmt_output,
1603     macho_objfmt_destroy,
1604     macho_objfmt_add_default_section,
1605     macho_objfmt_init_new_section,
1606     macho_objfmt_section_switch,
1607     macho_objfmt_get_special_sym
1608 };
1609 
1610 yasm_objfmt_module yasm_macho64_LTX_objfmt = {
1611     "Mac OS X ABI Mach-O File Format (64-bit)",
1612     "macho64",
1613     "o",
1614     64,
1615     0,
1616     macho_objfmt_dbgfmt_keywords,
1617     "null",
1618     NULL,   /* no directives */
1619     NULL,   /* no standard macros */
1620     macho64_objfmt_create,
1621     macho_objfmt_output,
1622     macho_objfmt_destroy,
1623     macho_objfmt_add_default_section,
1624     macho_objfmt_init_new_section,
1625     macho_objfmt_section_switch,
1626     macho_objfmt_get_special_sym
1627 };
1628