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