Home | History | Annotate | Download | only in macho
      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 *
    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 *
    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 *
    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 *
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   1258 macho_objfmt_destroy(yasm_objfmt *objfmt)
   1259 {
   1260     yasm_xfree(objfmt);
   1261 }
   1262 
   1263 static void
   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 *
   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 *
   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 *
   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
   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
   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
   1546 macho_symrec_data_destroy(void *data)
   1547 {
   1548     yasm_xfree(data);
   1549 }
   1550 
   1551 static void
   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