1/* 2 * Copyright (c) 2007 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. Please obtain a copy of the License at 10 * http://www.opensource.apple.com/apsl/ and read it before using this 11 * file. 12 * 13 * The Original Code and all software distributed under the License are 14 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 15 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 16 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 18 * Please see the License for the specific language governing rights and 19 * limitations under the License. 20 * 21 * @APPLE_LICENSE_HEADER_END@ 22 */ 23#define __eip eip 24#define __rip rip 25 26#include <stdio.h> 27#include <stdlib.h> 28#include <fcntl.h> 29#include <time.h> 30#include <sys/types.h> 31#include <sys/uio.h> 32#include <unistd.h> 33#include "stuff/breakout.h" 34#include "stuff/errors.h" 35#include "stuff/allocate.h" 36#include "stuff/reloc.h" 37#include "stuff/rnd.h" 38 39#include "coff/ms_dos_stub.h" 40#include "coff/filehdr.h" 41#include "coff/aouthdr.h" 42#include "coff/scnhdr.h" 43#include "coff/syment.h" 44#include "coff/bytesex.h" 45 46#include "coff/base_relocs.h" 47#include "mach-o/x86_64/reloc.h" 48 49/* used by error routines as the name of this program */ 50char *progname = NULL; 51 52/* the bytesex of our target object file and of this host machine */ 53static enum byte_sex target_byte_sex; 54static enum byte_sex host_byte_sex; 55static enum bool swapped; 56 57/* the size of the pecoff output file */ 58static uint32_t output_size = 0; 59 60/* 61 * The headers, and elements of them in the pecoff output file. 62 */ 63static struct ms_dos_stub ms_dos_stub; 64static char signature[4]; 65static struct filehdr filehdr; 66static struct aouthdr aouthdr; 67static struct aouthdr_64 aouthdr64; 68uint32_t entry = 0; /* the entry point */ 69uint32_t nscns = 0; /* the number of section headers and contents pointers */ 70static struct scnhdr *scnhdrs = NULL; /* the section headers */ 71static char **scn_contents = NULL; /* pointers to the section contents */ 72 73/* 74 * The value of the -subsystem argument to then set in the PECOFF aouthdr. 75 */ 76static uint16_t Subsystem = IMAGE_SUBSYSTEM_EFI_APPLICATION; 77 78struct subsystem_argument { 79 char *name; 80 uint16_t value; 81}; 82 83struct subsystem_argument subsystem_arguments[] = { 84 { "application", IMAGE_SUBSYSTEM_EFI_APPLICATION }, 85 { "app", IMAGE_SUBSYSTEM_EFI_APPLICATION }, 86 { "UEFI_APPLICATION", IMAGE_SUBSYSTEM_EFI_APPLICATION }, 87 { "APPLICATION", IMAGE_SUBSYSTEM_EFI_APPLICATION }, 88 89 { "boot", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 90 { "bsdrv", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 91 { "DXE_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 92 { "SEC", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 93 { "peim", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 94 { "BASE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 95 { "PEI_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 96 { "PEIM", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 97 { "DXE_SMM_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 98 { "TOOL", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 99 { "USER_DEFINED", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 100 { "UEFI_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 101 { "DXE_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 102 { "SECURITY_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 103 { "COMBINED_PEIM_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 104 { "PIC_PEIM", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 105 { "RELOCATABLE_PEIM", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 106 { "BS_DRIVER", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 107 { "SMM_CORE", IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER }, 108 109 { "runtime", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER }, 110 { "rtdrv", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER }, 111 { "DXE_RUNTIME_DRIVER", IMAGE_SUBSYSTEM_EFI_RUNTIME_DRIVER }, 112 113 { NULL, 0 } 114}; 115 116/* 117 * The value of the -section_alignment argument (or the -align argument) to 118 * layout the added PECOFF sections and set into the PECOFF aouthdr. 119 */ 120static uint32_t section_alignment = SECTIONALIGNMENT; 121 122/* 123 * The value of the -align argument to layout the PECOFF file. 124 */ 125static uint32_t file_alignment = FILEALIGNMENT; 126 127/* The maximum alignment allowed to be specified, in hex */ 128#define MAXALIGN 0x8000 129 130/* Static routine to help parse arguments */ 131static enum bool ispoweroftwo(uint32_t x); 132 133/* 134 * The string for the -d argument. 135 */ 136char *debug_filename = NULL; 137 138/* 139 * The string for the -u argument. 140 */ 141char *debug_uuid = NULL; 142 143/* 144 * Format specifier for scanf() to convert UUID to individual bytes 145 */ 146#define UUID_FORMAT_STRING "%02hhx%02hhx%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx-%02hhx%02hhx%02hhx%02hhx%02hhx%02hhx" 147 148/* 149 * The string for the entry point symbol name. 150 */ 151char *entry_point = NULL; 152 153#ifdef HACK_TO_MATCH_TEST_CASE 154/* 155 * These are are used for the HACK to get the symbol table for 32-bit files to 156 * match the one produced by objcopy. They are the pecoff section numbers of 157 * the .common and .bss sections. 158 */ 159static uint32_t common_scnum = 0; 160static uint32_t bss_scnum = 0; 161#endif 162 163/* 164 * These are for the .reloc section that contains the base relocations. 165 */ 166static struct scnhdr *reloc_scnhdr = NULL; 167static uint32_t reloc_size = 0; 168static char *reloc_contents = NULL; 169 170/* 171 * These are for the pecoff symbol table and string table. 172 */ 173static uint32_t nsyments = 0; /* number of symbols */ 174static struct syment *syments = NULL; /* pointer to symbol table elements */ 175static uint32_t syment_offset = 0; /* file offset of the symbol table */ 176static uint32_t strsize = 0; /* size of the string table */ 177static char *strings = NULL; /* pointer to the string table */ 178static uint32_t section_names_size = 0; /* size of the section names */ 179static char *section_names = NULL; /* pointer to section names */ 180static uint32_t string_offset = 0; /* file offset of the string table */ 181 182/* 183 * These are for the .debug section that contains the -d filename information. 184 */ 185static struct scnhdr *debug_scnhdr = NULL; 186static uint32_t debug_size = 0; 187static char *debug_contents = NULL; 188static struct debug_directory_entry *dde = NULL; 189static struct mtoc_debug_info *mdi = NULL; 190 191static void process_arch( 192 struct arch *archs, 193 uint32_t narchs); 194static void process_32bit_arch( 195 struct arch *arch); 196static void process_64bit_arch( 197 struct arch *arch); 198static void layout_output( 199 struct ofile *ofile); 200static void create_output( 201 struct ofile *ofile, 202 char *out); 203static void create_ms_dos_stub( 204 struct ms_dos_stub *p); 205static void usage( 206 void); 207 208static void create_32bit_symbol_table( 209 struct arch *arch); 210static void create_64bit_symbol_table( 211 struct arch *arch); 212 213/* 214 * This is the internal structure that we gather the base relocation in from 215 * the Mach-O relocation entries. 216 */ 217struct base_reloc { 218 uint64_t addr; 219 uint32_t type; 220}; 221struct base_reloc *base_relocs = NULL; 222uint32_t nbase_reloc = 0; 223 224static void create_base_reloc( 225 struct arch *arch); 226static void gather_base_reloc_info( 227 uint32_t addr, 228 struct relocation_info *relocs, 229 uint32_t nreloc, 230 cpu_type_t cpu_type, 231 uint32_t length, 232 int macho_reloc_type, 233 int base_reloc_type); 234static void add_base_reloc( 235 uint64_t addr, 236 uint32_t type); 237static void make_base_relocs( 238 void); 239static int cmp_base_relocs( 240 struct base_reloc *x1, 241 struct base_reloc *x2); 242static uint32_t checksum( 243 unsigned char *buf); 244static void string_to_uuid( 245 char *string, 246 uint8_t *uuid); 247 248static void create_debug( 249 struct arch *arch); 250static void set_debug_addrs_and_offsets( 251 void); 252 253/* apple_version is created by the libstuff/Makefile */ 254extern char apple_version[]; 255char *version = apple_version; 256 257/* 258 * The mtoc(1) tool makes a PECOFF file from a fully linked Mach-O file 259 * compiled with dynamic code gen and relocation entries saved (linked with -r). 260 * 261 * mtoc [-subsystem type] [-section_alignment hexvalue] [-align hexvalue] 262 * [-d filename] input_Mach-O output_pecoff 263 */ 264int 265main( 266int argc, 267char **argv, 268char **envp) 269{ 270 int i, j; 271 char *input, *output; 272 struct ofile *ofile; 273 struct arch *archs; 274 uint32_t narchs; 275 char *endp; 276 enum bool section_alignment_specified, align_specified; 277 278 progname = argv[0]; 279 host_byte_sex = get_host_byte_sex(); 280 281 input = NULL; 282 output = NULL; 283 284 section_alignment_specified = FALSE; 285 align_specified = FALSE; 286 287 for(i = 1; i < argc; i++){ 288 if(strcmp(argv[i], "-subsystem") == 0){ 289 if(i + 1 >= argc){ 290 warning("no argument specified for -subsystem option"); 291 usage(); 292 } 293 for(j = 0; subsystem_arguments[j].name != NULL; j++){ 294 if(strcmp(argv[i+1], subsystem_arguments[j].name) == 0){ 295 Subsystem = subsystem_arguments[j].value; 296 break; 297 } 298 } 299 if(subsystem_arguments[j].name == NULL){ 300 warning("unknown argument: %s specified for -subsystem " 301 "argument can be:", argv[i+1]); 302 for(j = 0; subsystem_arguments[j].name != NULL; j++) 303 fprintf(stderr, "%s\n", subsystem_arguments[j].name); 304 usage(); 305 } 306 i++; 307 } 308 else if(strcmp(argv[i], "-d") == 0){ 309 if(i + 1 >= argc){ 310 warning("no argument specified for -d option"); 311 usage(); 312 } 313 debug_filename = argv[i+1]; 314 i++; 315 } 316 else if(strcmp(argv[i], "-e") == 0){ 317 if(i + 1 >= argc){ 318 warning("no argument specified for -e option"); 319 usage(); 320 } 321 entry_point = argv[i+1]; 322 i++; 323 } 324 else if(strcmp(argv[i], "-u") == 0){ 325 if(i + 1 >= argc){ 326 warning("no argument specified for -u option"); 327 usage(); 328 } 329 if(debug_filename == NULL) { 330 fatal("-u option requires -d option"); 331 } 332 debug_uuid = argv[i+1]; 333 i++; 334 } 335 else if(strcmp(argv[i], "-section_alignment") == 0){ 336 if(i + 1 >= argc){ 337 warning("no argument specified for -section_alignment " 338 "option"); 339 usage(); 340 } 341 section_alignment = strtoul(argv[i+1], &endp, 16); 342 if(*endp != '\0') 343 fatal("argument for -section_alignment %s not a proper " 344 "hexadecimal number", argv[i+1]); 345 if(!ispoweroftwo(section_alignment) || section_alignment == 0) 346 fatal("argument to -section_alignment: %x (hex) must be a " 347 "non-zero power of two", section_alignment); 348 if(section_alignment > MAXALIGN) 349 fatal("argument to -section_alignment: %x (hex) must " 350 "equal to or less than %x (hex)", section_alignment, 351 (unsigned int)MAXALIGN); 352 section_alignment_specified = TRUE; 353 if(align_specified == TRUE && 354 section_alignment != file_alignment) 355 fatal("can't specifiy a -section_alignment value %x (hex) " 356 "different from the -align value %x (hex)", 357 section_alignment, file_alignment); 358 i++; 359 } 360 else if(strcmp(argv[i], "-align") == 0){ 361 if(i + 1 >= argc){ 362 warning("no argument specified for -align option"); 363 usage(); 364 } 365 file_alignment = strtoul(argv[i+1], &endp, 16); 366 if(*endp != '\0') 367 fatal("argument for -align %s not a proper hexadecimal " 368 "number", argv[i+1]); 369 if(!ispoweroftwo(file_alignment) || file_alignment == 0) 370 fatal("argument to -align: %x (hex) must be a non-zero " 371 "power of two", file_alignment); 372 if(file_alignment > MAXALIGN) 373 fatal("argument to -file_alignment: %x (hex) must " 374 "equal to or less than %x (hex)", file_alignment, 375 (unsigned int)MAXALIGN); 376 align_specified = TRUE; 377 if(section_alignment_specified == TRUE && 378 section_alignment != file_alignment) 379 fatal("can't specifiy a -section_alignment value %x (hex) " 380 "different from the -align value %x (hex)", 381 section_alignment, file_alignment); 382 section_alignment = file_alignment; 383 i++; 384 } 385 else if(input == NULL) 386 input = argv[i]; 387 else if(output == NULL) 388 output = argv[i]; 389 else 390 usage(); 391 } 392 if(input == NULL){ 393 warning("no input file specified"); 394 usage(); 395 } 396 if(output == NULL){ 397 warning("no output file specified"); 398 usage(); 399 } 400 401 /* breakout the file for processing */ 402 ofile = breakout(input, &archs, &narchs, FALSE); 403 if(errors) 404 return(EXIT_FAILURE); 405 406 /* checkout the file for symbol table replacement processing */ 407 checkout(archs, narchs); 408 409 /* process the input file */ 410 process_arch(archs, narchs); 411 if(errors){ 412 free_archs(archs, narchs); 413 ofile_unmap(ofile); 414 return(EXIT_FAILURE); 415 } 416 417 /* 418 * Layout the pecoff output file from the information gathered from 419 * the input file creating the needed headers, relocs, etc. 420 */ 421 layout_output(ofile); 422 423 create_output(ofile, output); 424 425 if(errors == 0) 426 return(EXIT_SUCCESS); 427 else 428 return(EXIT_FAILURE); 429} 430 431/* 432 * usage() prints the current usage message and exits indicating failure. 433 */ 434static 435void 436usage( 437void) 438{ 439 fprintf(stderr, "Usage: %s [-subsystem type] " 440 "[-section_alignment hexvalue] [-align hexvalue] [-d debug_filename] " 441 "[-u debug_guid] input_Mach-O output_pecoff\n", progname); 442 exit(EXIT_FAILURE); 443} 444 445/* 446 * ispoweroftwo() returns TRUE or FALSE depending if x is a power of two. 447 */ 448static 449enum 450bool 451ispoweroftwo( 452uint32_t x) 453{ 454 if(x == 0) 455 return(TRUE); 456 while((x & 0x1) != 0x1){ 457 x >>= 1; 458 } 459 if((x & ~0x1) != 0) 460 return(FALSE); 461 else 462 return(TRUE); 463} 464 465/* 466 * process_arch() is the routine that process the broken out ofile to gather 467 * the info to create the pecoff file. This routine basically counts and adds 468 * up the sizes of the elements that will be in the pecoff output file. 469 */ 470static 471void 472process_arch( 473struct arch *archs, 474uint32_t narchs) 475{ 476 /* 477 * Check to see the input file is something this program can convert to 478 * a pecoff file. 479 */ 480 if(narchs != 1) 481 fatal("input file: %s must only have one architecture", 482 archs->file_name); 483 if(archs->type != OFILE_Mach_O) 484 fatal("input file: %s must be a Mach-O file", archs->file_name); 485 if(archs->object->mh_cputype != CPU_TYPE_I386 && 486 archs->object->mh_cputype != CPU_TYPE_ARM && 487 archs->object->mh_cputype != CPU_TYPE_X86_64) 488 fatal("input file: %s must be an i386 or ARM architecture", 489 archs->file_name); 490 if(archs->object->mh != NULL){ 491 if(archs->object->mh->filetype == MH_PRELOAD || 492 (archs->object->mh->filetype == MH_EXECUTE && 493 (archs->object->mh->flags & MH_PIE) == MH_PIE)){ 494 if(entry_point != NULL) 495 fatal("entry point option, -e %s, not allowed with " 496 "MH_PRELOAD or MH_EXECUTE file types", entry_point); 497 } 498 else{ 499 fatal("input file: %s must be an MH_PRELOAD file type or " 500 "MH_EXECUTE file type with MH_PIE flag", 501 archs->file_name); 502 } 503 } 504 else{ 505 if(archs->object->mh64->filetype == MH_DYLIB || 506 (archs->object->mh64->filetype == MH_EXECUTE && 507 (archs->object->mh64->flags & MH_PIE) == MH_PIE)){ 508 if(entry_point == NULL && 509 archs->object->mh64->filetype == MH_DYLIB) 510 fatal("input file: %s is a MH_DYLIB file type, so entry " 511 "point option, -e name, must be specified", 512 archs->file_name); 513 } 514 else if(archs->object->mh64->filetype == MH_PRELOAD || 515 (archs->object->mh64->filetype == MH_EXECUTE && 516 (archs->object->mh64->flags & MH_PIE) == MH_PIE)){ 517 if(entry_point != NULL) 518 fatal("entry point option, -e %s, not allowed with " 519 "MH_PRELOAD or MH_EXECUTE file types", 520 archs->file_name); 521 } 522 else 523 fatal("input file: %s must be an MH_PRELOAD or MH_DYLIB file " 524 "type or MH_EXECUTE file type with MH_PIE flag", 525 archs->file_name); 526 } 527 528 target_byte_sex = archs->object->object_byte_sex; 529 swapped = host_byte_sex != target_byte_sex; 530 531 /* 532 * Create base relocation entries for this Mach-O file. This is done 533 * before the sections are created as this produces the contents for 534 * the .reloc section and determines it size. 535 */ 536 create_base_reloc(archs); 537 538 /* 539 * If there is a -d flag create the information that will be in .debug 540 * section for it. 541 */ 542 if(debug_filename != NULL) 543 create_debug(archs); 544 545 if(archs->object->mh != NULL) 546 process_32bit_arch(archs); 547 else 548 process_64bit_arch(archs); 549} 550 551/* 552 * process_32bit_arch() is the routine that processes a 32-bit broken out ofile 553 * to gather the info to create the pecoff file. This routine basically counts 554 * and adds up the sizes of the elements that will be in the pecoff output file. 555 */ 556static 557void 558process_32bit_arch( 559struct arch *arch) 560{ 561 uint32_t i, j, reloc_addr, debug_addr; 562 struct load_command *lc; 563 struct segment_command *sg; 564 struct thread_command *ut; 565 char *p, *state; 566 uint32_t flavor, count; 567 char *object_addr, *section_name; 568#ifdef HACK_TO_MATCH_TEST_CASE 569 uint32_t len; 570 struct section *s; 571#endif 572 573 /* 574 * Determine the number of sections in the pecoff output file. 575 * 576#ifdef HACK_TO_MATCH_TEST_CASE 577 * 578 * The hack implementation of this routine is done to match the 579 * current ld_efi(1) script that uses objcopy(1) to make the pecoff 580 * file. So for 32-bit file the contents of the Mach-O file gets 581 * placed into pecoff sections as follows: 582 * 583 * the entire __TEXT segment becomes the .text section 584 * the entire __DATA segment becomes the .data section 585 * the zero fill section (__DATA,__common) becomes .common 586 * the zero fill section (__DATA,__bss) becomes .bss 587 * the (__IMPORT,__pointers) section becomes .pointers 588 * the base relocation entries go into the .reloc section 589 * 590#else 591 * 592 * The whole Mach-O segments __TEXT, __DATA and __IMPORT are placed in 593 * the pecoff file from the Mach-O file. And then the .reloc section 594 * added for the base relocations. 595 * 596#endif 597 */ 598 nscns = 0; 599 reloc_addr = 0; 600 lc = arch->object->load_commands; 601 for(i = 0; i < arch->object->mh->ncmds; i++){ 602 if(lc->cmd == LC_SEGMENT){ 603 sg = (struct segment_command *)lc; 604 if(strcmp(sg->segname, SEG_LINKEDIT) != 0 && 605 sg->vmaddr + sg->vmsize > reloc_addr) 606 reloc_addr = sg->vmaddr + sg->vmsize; 607 if(strcmp(sg->segname, SEG_TEXT) == 0) 608 nscns++; 609 else if(strcmp(sg->segname, SEG_DATA) == 0){ 610 nscns++; 611#ifdef HACK_TO_MATCH_TEST_CASE 612 s = (struct section *) 613 ((char *)sg + sizeof(struct segment_command)); 614 for(j = 0; j < sg->nsects; j++, s++){ 615 if(strcmp(s->sectname, SECT_COMMON) == 0 || 616 strcmp(s->sectname, SECT_BSS) == 0){ 617 nscns++; 618 } 619 else if(s->size != 0 && 620 strcmp(s->sectname, SECT_DATA) != 0) 621 fatal("input file: %s contains Mach-O section " 622 "(%.16s,%.16s) unsupported for conversion " 623 "to a pecoff file", arch->file_name, 624 s->segname, s->sectname); 625 } 626#endif /* HACK_TO_MATCH_TEST_CASE */ 627 } 628 else if(strcmp(sg->segname, SEG_IMPORT) == 0){ 629#ifndef HACK_TO_MATCH_TEST_CASE 630 nscns++; 631#else 632 s = (struct section *) 633 ((char *)sg + sizeof(struct segment_command)); 634 for(j = 0; j < sg->nsects; j++, s++){ 635 if(strcmp(s->sectname, "__pointers") == 0){ 636 section_names_size += strlen(".pointers") + 1; 637 nscns++; 638 } 639 else if(s->size != 0) 640 fatal("input file: %s contains Mach-O section " 641 "(%.16s,%.16s) unsupported for conversion " 642 "to a pecoff file", arch->file_name, 643 s->segname, s->sectname); 644 } 645 646#endif /* HACK_TO_MATCH_TEST_CASE */ 647 } 648 else if((arch->object->mh->flags & MH_PIE) != MH_PIE || 649 strcmp(sg->segname, SEG_LINKEDIT) != 0){ 650 fatal("input file: %s contains Mach-O segment %.16s " 651 "unsupported for conversion to a pecoff file", 652 arch->file_name, sg->segname); 653 } 654 } 655 /* 656 * Also while processing the Mach-O file pick up the entry point. 657 */ 658 else if(lc->cmd == LC_UNIXTHREAD){ 659 ut = (struct thread_command *)lc; 660 state = (char *)ut + sizeof(struct thread_command); 661 p = (char *)ut + ut->cmdsize; 662 while(state < p){ 663 flavor = *((uint32_t *)state); 664 state += sizeof(uint32_t); 665 count = *((uint32_t *)state); 666 state += sizeof(uint32_t); 667 switch(arch->object->mh_cputype){ 668 case CPU_TYPE_I386: 669 switch((int)flavor){ 670 i386_thread_state_t *cpu; 671 case i386_THREAD_STATE: 672#if i386_THREAD_STATE == 1 673 case -1: 674#endif /* i386_THREAD_STATE == 1 */ 675/* i386 thread states on older releases */ 676#if i386_THREAD_STATE == -1 677 case 1: 678#endif /* i386_THREAD_STATE == -1 */ 679 cpu = (i386_thread_state_t *)state; 680 entry = cpu->eip; 681 state += sizeof(i386_thread_state_t); 682 break; 683 default: 684 state += count * sizeof(uint32_t); 685 break; 686 } 687 break; 688 case CPU_TYPE_ARM: 689 switch(flavor){ 690 arm_thread_state_t *cpu; 691 case ARM_THREAD_STATE: 692 cpu = (arm_thread_state_t *)state; 693 entry = cpu->__pc; 694 state += sizeof(arm_thread_state_t); 695 break; 696 default: 697 state += count * sizeof(uint32_t); 698 break; 699 } 700 break; 701 default: 702 break; 703 } 704 } 705 } 706 lc = (struct load_command *)((char *)lc + lc->cmdsize); 707 } 708 if(reloc_size != 0){ 709 /* add one for the .reloc section to contain the base relocations */ 710 nscns++; 711 } 712 713 /* 714 * If there is a -d flag add one for the .debug section to contain 715 * the information. 716 */ 717 if(debug_filename != NULL) 718 nscns++; 719 720 /* 721 * At the beginning of the COFF string table are 4 bytes that contain 722 * the total size (in bytes) of the rest of the string table. This size 723 * includes the size field itself, so that the value in this location 724 * would be 4 if no strings were present. 725 */ 726 strsize = sizeof(uint32_t); 727 728 /* 729 * Section names longer than 8 bytes are placed in the string table. 730 * So here we allocate memory to put them into, which later will be 731 * copied to the start of the string table. 732 */ 733 section_names = allocate(section_names_size); 734 section_name = section_names; 735 if(section_names_size != 0) 736 *section_name = '\0'; 737 738 /* 739 * Allocate space for the section headers and fill in everything but 740 * their file offsets. 741 * 742#ifndef HACK_TO_MATCH_TEST_CASE 743 * 744 * We use the SizeOfRawData field (s_size) as the unrounded value of 745 * the size of the initialized section contents coming from the 746 * segment's filesize. The VirtualSize field s_vsize may be bigger 747 * with the remaining space zero filled coming from the segment's 748 * vmsize. 749#else 750 * 751 * Note to match what objcopy(1) does the s_vsize is an unrounded value 752 * of the size (more like the actual size) and the s_size is a value 753 * rounded to the file_alignment. So the s_vsize can be smaller than 754 * the s_size, as in the case of pecoff sections created from Mach-O 755 * sections (and not segments). This seems to volate the spec where 756 * s_vsize can be bigger than s_size with the remaining space zero 757 * filled but does NOT allow the s_vsize to be smaller than the s_size. 758#endif 759 */ 760 scnhdrs = allocate(nscns * sizeof(struct scnhdr)); 761 memset(scnhdrs, '\0', nscns * sizeof(struct scnhdr)); 762 scn_contents = allocate(nscns * sizeof(char *)); 763 object_addr = arch->object->object_addr; 764 j = 0; 765 lc = arch->object->load_commands; 766 for(i = 0; i < arch->object->mh->ncmds; i++){ 767 if(lc->cmd == LC_SEGMENT){ 768 sg = (struct segment_command *)lc; 769 if(strcmp(sg->segname, SEG_TEXT) == 0){ 770 strcpy(scnhdrs[j].s_name, ".text"); 771#ifdef HACK_TO_MATCH_TEST_CASE 772 scnhdrs[j].s_vsize = sg->filesize; 773#else 774 scnhdrs[j].s_vsize = sg->vmsize; 775#endif 776 scnhdrs[j].s_vaddr = sg->vmaddr; 777 scnhdrs[j].s_size = rnd(sg->filesize, file_alignment); 778 scnhdrs[j].s_relptr = 0; 779 scnhdrs[j].s_lnnoptr = 0; 780 scnhdrs[j].s_nlnno = 0; 781 scnhdrs[j].s_flags = IMAGE_SCN_MEM_EXECUTE | 782 IMAGE_SCN_MEM_READ | 783 IMAGE_SCN_CNT_CODE; 784 scn_contents[j] = object_addr + sg->fileoff; 785 j++; 786 } 787 else if(strcmp(sg->segname, SEG_DATA) == 0){ 788 strcpy(scnhdrs[j].s_name, ".data"); 789#ifdef HACK_TO_MATCH_TEST_CASE 790 scnhdrs[j].s_vsize = sg->filesize; 791#else 792 scnhdrs[j].s_vsize = sg->vmsize; 793#endif 794 scnhdrs[j].s_vaddr = sg->vmaddr; 795 scnhdrs[j].s_size = rnd(sg->filesize, file_alignment); 796 scnhdrs[j].s_relptr = 0; 797 scnhdrs[j].s_lnnoptr = 0; 798 scnhdrs[j].s_nlnno = 0; 799 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 800 IMAGE_SCN_MEM_WRITE | 801 IMAGE_SCN_CNT_CODE | 802 IMAGE_SCN_CNT_INITIALIZED_DATA | 803 IMAGE_SCN_MEM_EXECUTE; 804 scn_contents[j] = object_addr + sg->fileoff; 805 j++; 806#ifdef HACK_TO_MATCH_TEST_CASE 807 s = (struct section *) 808 ((char *)sg + sizeof(struct segment_command)); 809 for(i = 0; i < sg->nsects; i++, s++){ 810 if(s->size == 0) 811 continue; 812 scnhdrs[j].s_vsize = s->size; 813 scnhdrs[j].s_vaddr = s->addr; 814 scnhdrs[j].s_size = 0; 815 scnhdrs[j].s_relptr = 0; 816 scnhdrs[j].s_lnnoptr = 0; 817 scnhdrs[j].s_nlnno = 0; 818 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 819 IMAGE_SCN_MEM_WRITE | 820 IMAGE_SCN_CNT_UNINITIALIZED_DATA; 821 if(strcmp(s->sectname, SECT_DATA) == 0){ 822 continue; 823 } 824 else if(strcmp(s->sectname, SECT_COMMON) == 0){ 825 strcpy(scnhdrs[j].s_name, ".common"); 826 common_scnum = j + 1; 827 } 828 else if(strcmp(s->sectname, SECT_BSS) == 0){ 829 strcpy(scnhdrs[j].s_name, ".bss"); 830 bss_scnum = j + 1; 831 } 832 scn_contents[j] = NULL; 833 j++; 834 } 835#endif /* HACK_TO_MATCH_TEST_CASE */ 836 } 837 else if(strcmp(sg->segname, SEG_IMPORT) == 0){ 838#ifndef HACK_TO_MATCH_TEST_CASE 839 strcpy(scnhdrs[j].s_name, ".import"); 840 scnhdrs[j].s_vsize = sg->vmsize; 841 scnhdrs[j].s_vaddr = sg->vmaddr; 842 scnhdrs[j].s_size = rnd(sg->filesize, file_alignment); 843 scnhdrs[j].s_relptr = 0; 844 scnhdrs[j].s_lnnoptr = 0; 845 scnhdrs[j].s_nlnno = 0; 846 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 847 IMAGE_SCN_MEM_WRITE | 848 IMAGE_SCN_CNT_INITIALIZED_DATA; 849 scn_contents[j] = object_addr + sg->fileoff; 850 j++; 851#else /* defined(HACK_TO_MATCH_TEST_CASE) */ 852 s = (struct section *) 853 ((char *)sg + sizeof(struct segment_command)); 854 for(i = 0; i < sg->nsects; i++, s++){ 855 if(s->size == 0) 856 continue; 857 scnhdrs[j].s_vsize = s->size; 858 scnhdrs[j].s_vaddr = s->addr; 859 scnhdrs[j].s_size = rnd(s->size, file_alignment); 860 scnhdrs[j].s_relptr = 0; 861 scnhdrs[j].s_lnnoptr = 0; 862 scnhdrs[j].s_nlnno = 0; 863 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 864 IMAGE_SCN_MEM_WRITE | 865 IMAGE_SCN_CNT_INITIALIZED_DATA; 866 if(strcmp(s->sectname, "__pointers") == 0){ 867 sprintf(scnhdrs[j].s_name, "/%d", strsize); 868 strcat(section_name, ".pointers"); 869 len = strlen(section_name) + 1; 870 strsize += len; 871 } 872 scn_contents[j] = object_addr + s->offset; 873 j++; 874 } 875#endif /* HACK_TO_MATCH_TEST_CASE */ 876 } 877 } 878 lc = (struct load_command *)((char *)lc + lc->cmdsize); 879 } 880 if(reloc_size != 0){ 881 strcpy(scnhdrs[j].s_name, ".reloc"); 882 scnhdrs[j].s_vsize = reloc_size; 883 reloc_addr = rnd(reloc_addr, section_alignment); 884 scnhdrs[j].s_vaddr = reloc_addr; 885 scnhdrs[j].s_size = rnd(reloc_size, file_alignment); 886 scnhdrs[j].s_relptr = 0; 887 scnhdrs[j].s_lnnoptr = 0; 888 scnhdrs[j].s_nlnno = 0; 889 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 890 IMAGE_SCN_CNT_INITIALIZED_DATA | 891 IMAGE_SCN_MEM_DISCARDABLE; 892 reloc_scnhdr = scnhdrs + j; 893 scn_contents[j] = reloc_contents; 894 j++; 895 debug_addr = reloc_addr + reloc_scnhdr->s_size; 896 } 897 else{ 898 debug_addr = rnd(reloc_addr, section_alignment); 899 } 900 901 if(debug_filename != NULL){ 902 strcpy(scnhdrs[j].s_name, ".debug"); 903 scnhdrs[j].s_vsize = debug_size; 904 scnhdrs[j].s_vaddr = debug_addr; 905 scnhdrs[j].s_size = rnd(debug_size, file_alignment); 906 scnhdrs[j].s_relptr = 0; 907 scnhdrs[j].s_lnnoptr = 0; 908 scnhdrs[j].s_nlnno = 0; 909 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 910 IMAGE_SCN_CNT_INITIALIZED_DATA | 911 IMAGE_SCN_MEM_DISCARDABLE; 912 debug_scnhdr = scnhdrs + j; 913 scn_contents[j] = debug_contents; 914 j++; 915 } 916 917 /* 918 * Create the pecoff symbol and string table from this Mach-O file. 919 */ 920 create_32bit_symbol_table(arch); 921} 922 923/* 924 * process_64bit_arch() is the routine that processes a 64-bit broken out ofile 925 * to gather the info to create the pecoff file. This routine basically counts 926 * and adds up the sizes of the elements that will be in the pecoff output file. 927 */ 928static 929void 930process_64bit_arch( 931struct arch *arch) 932{ 933 uint32_t i, j; 934 uint64_t reloc_addr, debug_addr; 935 struct load_command *lc; 936 struct segment_command_64 *sg64; 937 struct thread_command *ut; 938 char *p, *state; 939 uint32_t flavor, count; 940 char *object_addr, *section_name; 941#ifdef HACK_TO_MATCH_TEST_CASE 942 struct section_64 *s64; 943 uint32_t len; 944#endif 945 946 /* 947 * Determine the number of sections in the pecoff output file. 948 * 949#ifdef HACK_TO_MATCH_TEST_CASE 950 * 951 * The hack implementation of this routine is done to match the 952 * current ld_efi(1) script that uses objcopy(1) to make the pecoff 953 * file. So for 64-bit files the contents of the Mach-O sections get 954 * placed into pecoff sections with a section name made up of the 955 * strings "LC_SEGMENT" the segment and section names separated with 956 * a dot, '.', character. So the Mach-O (__TEXT,__text) section becomes 957 * a pecoff section with the name "LC_SEGMENT.__TEXT.__text". The base 958 * relocation entries go into a ".reloc" section. 959 * 960#else 961 * 962 * The whole Mach-O __TEXT and __DATA segments are placed in the 963 * pecoff file from the Mach-O file. And then the .reloc section added 964 * for the base relocations. 965 * 966#endif 967 */ 968 nscns = 0; 969 reloc_addr = 0; 970 lc = arch->object->load_commands; 971 for(i = 0; i < arch->object->mh64->ncmds; i++){ 972 if(lc->cmd == LC_SEGMENT_64){ 973 sg64 = (struct segment_command_64 *)lc; 974#ifndef HACK_TO_MATCH_TEST_CASE 975 if(strcmp(sg64->segname, SEG_LINKEDIT) != 0 && 976 sg64->vmaddr + sg64->vmsize > reloc_addr) 977 reloc_addr = sg64->vmaddr + sg64->vmsize; 978 if(strcmp(sg64->segname, SEG_TEXT) == 0) 979 nscns++; 980 else if(strcmp(sg64->segname, SEG_DATA) == 0) 981 nscns++; 982 else if(strcmp(sg64->segname, SEG_LINKEDIT) != 0){ 983 fatal("input file: %s contains Mach-O segment %.16s " 984 "unsupported for conversion to a pecoff file", 985 arch->file_name, sg64->segname); 986 } 987#else /* defined(HACK_TO_MATCH_TEST_CASE) */ 988 s64 = (struct section_64 *) 989 ((char *)sg64 + sizeof(struct segment_command_64)); 990 for(i = 0; i < sg64->nsects; i++, s64++){ 991 if(s64->addr + s64->size > reloc_addr) 992 reloc_addr = s64->addr + s64->size; 993 section_names_size += strlen("LC_SEGMENT.") + 994 strlen(s64->segname) + 1 + 995 strlen(s64->sectname) + 1; 996 nscns++; 997 } 998#endif /* HACK_TO_MATCH_TEST_CASE */ 999 } 1000 /* 1001 * Also while process the Mach-O file pick up the entry point. 1002 */ 1003 else if(lc->cmd == LC_UNIXTHREAD){ 1004 ut = (struct thread_command *)lc; 1005 state = (char *)ut + sizeof(struct thread_command); 1006 p = (char *)ut + ut->cmdsize; 1007 while(state < p){ 1008 flavor = *((uint32_t *)state); 1009 state += sizeof(uint32_t); 1010 count = *((uint32_t *)state); 1011 state += sizeof(uint32_t); 1012 switch(arch->object->mh_cputype){ 1013#ifdef x86_THREAD_STATE64 1014 case CPU_TYPE_X86_64: 1015 switch(flavor){ 1016 x86_thread_state64_t *cpu64; 1017 case x86_THREAD_STATE64: 1018 cpu64 = (x86_thread_state64_t *)state; 1019 entry = cpu64->rip; 1020 state += sizeof(x86_thread_state64_t); 1021 break; 1022 default: 1023 state += count * sizeof(uint32_t); 1024 break; 1025 } 1026 break; 1027#endif /* x86_THREAD_STATE64 */ 1028 } 1029 } 1030 } 1031 lc = (struct load_command *)((char *)lc + lc->cmdsize); 1032 } 1033 if(reloc_size != 0){ 1034 /* add one for the .reloc section to contain the base relocations */ 1035 nscns++; 1036 } 1037 1038 /* 1039 * If there is a -d flag add one for the .debug section to contain 1040 * the information. 1041 */ 1042 if(debug_filename != NULL) 1043 nscns++; 1044 1045 /* 1046 * At the beginning of the COFF string table are 4 bytes that contain 1047 * the total size (in bytes) of the rest of the string table. This size 1048 * includes the size field itself, so that the value in this location 1049 * would be 4 if no strings were present. 1050 */ 1051 strsize = sizeof(uint32_t); 1052 1053 /* 1054 * Section names longer than 8 bytes are placed in the string table. 1055 * So here we allocate memory to put them into, which later will be 1056 * copied to the start of the string table. 1057 */ 1058 section_names = allocate(section_names_size) + 1; 1059 section_name = section_names; 1060 if(section_names_size != 0) 1061 *section_name = '\0'; 1062 1063 /* 1064 * Allocate space for the section headers and fill in everything but 1065 * their file offsets. 1066 * 1067#ifndef HACK_TO_MATCH_TEST_CASE 1068 * 1069 * We use the SizeOfRawData field (s_size) as the unrounded value of 1070 * the size of the initialized section contents coming from the 1071 * segment's filesize. The VirtualSize field s_vsize may be bigger 1072 * with the remaining space zero filled coming from the segment's 1073 * vmsize. 1074#else 1075 * 1076 * Note to match what objcopy(1) does the s_vsize is an unrounded value 1077 * of the size (more like the actual size) and the s_size is a value 1078 * rounded to the file_alignment. So the s_vsize can be smaller than 1079 * the s_size, as in the case of pecoff sections created from Mach-O 1080 * sections (and not segments). This seems to volate the spec where 1081 * s_vsize can be bigger than s_size with the remaining space zero 1082 * filled but does NOT allow the s_vsize to be smaller than the s_size. 1083#endif 1084 */ 1085 scnhdrs = allocate(nscns * sizeof(struct scnhdr)); 1086 memset(scnhdrs, '\0', nscns * sizeof(struct scnhdr)); 1087 scn_contents = allocate(nscns * sizeof(char *)); 1088 object_addr = arch->object->object_addr; 1089 j = 0; 1090 lc = arch->object->load_commands; 1091 for(i = 0; i < arch->object->mh64->ncmds; i++){ 1092 if(lc->cmd == LC_SEGMENT_64){ 1093 sg64 = (struct segment_command_64 *)lc; 1094#ifndef HACK_TO_MATCH_TEST_CASE 1095 if(strcmp(sg64->segname, SEG_TEXT) == 0){ 1096 strcpy(scnhdrs[j].s_name, ".text"); 1097 scnhdrs[j].s_vsize = sg64->vmsize; 1098 scnhdrs[j].s_vaddr = sg64->vmaddr; 1099 scnhdrs[j].s_size = rnd(sg64->filesize, file_alignment); 1100 scnhdrs[j].s_relptr = 0; 1101 scnhdrs[j].s_lnnoptr = 0; 1102 scnhdrs[j].s_nlnno = 0; 1103 scnhdrs[j].s_flags = IMAGE_SCN_MEM_EXECUTE | 1104 IMAGE_SCN_MEM_READ | 1105 IMAGE_SCN_CNT_CODE; 1106 scn_contents[j] = object_addr + sg64->fileoff; 1107 j++; 1108 } 1109 else if(strcmp(sg64->segname, SEG_DATA) == 0){ 1110 strcpy(scnhdrs[j].s_name, ".data"); 1111 scnhdrs[j].s_vsize = sg64->vmsize; 1112 scnhdrs[j].s_vaddr = sg64->vmaddr; 1113 scnhdrs[j].s_size = rnd(sg64->filesize, file_alignment); 1114 scnhdrs[j].s_relptr = 0; 1115 scnhdrs[j].s_lnnoptr = 0; 1116 scnhdrs[j].s_nlnno = 0; 1117 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 1118 IMAGE_SCN_MEM_WRITE | 1119 IMAGE_SCN_CNT_CODE | 1120 IMAGE_SCN_CNT_INITIALIZED_DATA | 1121 IMAGE_SCN_MEM_EXECUTE; 1122 scn_contents[j] = object_addr + sg64->fileoff; 1123 j++; 1124 } 1125#else /* defined(HACK_TO_MATCH_TEST_CASE) */ 1126 s64 = (struct section_64 *) 1127 ((char *)sg64 + sizeof(struct segment_command_64)); 1128 for(i = 0; i < sg64->nsects; i++, s64++){ 1129 sprintf(scnhdrs[j].s_name, "/%d", strsize); 1130 strcat(section_name, "LC_SEGMENT."); 1131 strcat(section_name, s64->segname); 1132 strcat(section_name, "."); 1133 strcat(section_name, s64->sectname); 1134 len = strlen(section_name); 1135 strsize += len + 1; 1136 section_name += len + 1; 1137 *section_name = '\0'; /* start of next section name */ 1138 1139 /* NOTE zerofill sections are not handled */ 1140 scnhdrs[j].s_vsize = s64->size; 1141 scnhdrs[j].s_vaddr = s64->addr; 1142 scnhdrs[j].s_size = rnd(s64->size, file_alignment); 1143 scnhdrs[j].s_relptr = 0; 1144 scnhdrs[j].s_lnnoptr = 0; 1145 scnhdrs[j].s_nlnno = 0; 1146 scnhdrs[j].s_flags = IMAGE_SCN_MEM_EXECUTE | 1147 IMAGE_SCN_CNT_CODE | 1148 IMAGE_SCN_MEM_WRITE; 1149 if(sg64->initprot & VM_PROT_READ) 1150 scnhdrs[j].s_flags |= IMAGE_SCN_MEM_READ; 1151 scn_contents[j] = object_addr + s64->offset; 1152 j++; 1153 } 1154#endif /* HACK_TO_MATCH_TEST_CASE */ 1155 } 1156 lc = (struct load_command *)((char *)lc + lc->cmdsize); 1157 } 1158 if(reloc_size != 0){ 1159 strcpy(scnhdrs[j].s_name, ".reloc"); 1160 scnhdrs[j].s_vsize = reloc_size; 1161 reloc_addr = rnd(reloc_addr, section_alignment); 1162 scnhdrs[j].s_vaddr = reloc_addr; 1163 scnhdrs[j].s_size = rnd(reloc_size, file_alignment); 1164 scnhdrs[j].s_relptr = 0; 1165 scnhdrs[j].s_lnnoptr = 0; 1166 scnhdrs[j].s_nlnno = 0; 1167 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 1168 IMAGE_SCN_CNT_INITIALIZED_DATA | 1169 IMAGE_SCN_MEM_DISCARDABLE | 1170 IMAGE_SCN_CNT_CODE | 1171 IMAGE_SCN_MEM_EXECUTE; 1172 reloc_scnhdr = scnhdrs + j; 1173 scn_contents[j] = reloc_contents; 1174 j++; 1175 debug_addr = reloc_addr + reloc_scnhdr->s_size; 1176 } 1177 else{ 1178 debug_addr = rnd(reloc_addr, section_alignment); 1179 } 1180 1181 if(debug_filename != NULL){ 1182 strcpy(scnhdrs[j].s_name, ".debug"); 1183 scnhdrs[j].s_vsize = debug_size; 1184 scnhdrs[j].s_vaddr = debug_addr; 1185 scnhdrs[j].s_size = rnd(debug_size, file_alignment); 1186 scnhdrs[j].s_relptr = 0; 1187 scnhdrs[j].s_lnnoptr = 0; 1188 scnhdrs[j].s_nlnno = 0; 1189 scnhdrs[j].s_flags = IMAGE_SCN_MEM_READ | 1190 IMAGE_SCN_CNT_INITIALIZED_DATA | 1191 IMAGE_SCN_MEM_DISCARDABLE | 1192 IMAGE_SCN_CNT_CODE | 1193 IMAGE_SCN_MEM_EXECUTE; 1194 debug_scnhdr = scnhdrs + j; 1195 scn_contents[j] = debug_contents; 1196 j++; 1197 } 1198 1199 /* 1200 * Create the pecoff symbol and string table from this Mach-O file. 1201 */ 1202 create_64bit_symbol_table(arch); 1203} 1204 1205/* 1206 * layout_output() takes the info gathered from the input Mach-O file and 1207 * layouts the pecoff output file and creates and fills in the elements of 1208 * the coff file. This routine basically sets of the offsets of the elements 1209 * of the output file from the previously determined sizes. 1210 */ 1211static 1212void 1213layout_output( 1214struct ofile *ofile) 1215{ 1216 uint32_t i, header_size, offset, least_vaddr; 1217 1218 /* 1219 * Determine the size of the output file and where each element will be 1220 * in the output file. 1221 */ 1222 header_size = sizeof(struct ms_dos_stub) + 1223 sizeof(signature) + 1224 sizeof(struct filehdr) + 1225 nscns * sizeof(struct scnhdr); 1226 if(ofile->mh != NULL) 1227 header_size += sizeof(struct aouthdr); 1228 else 1229 header_size += sizeof(struct aouthdr_64); 1230 header_size = rnd(header_size, file_alignment); 1231#ifdef HACK_TO_MATCH_TEST_CASE 1232 /* for some unknown reason the header size is 0x488 not 0x400 */ 1233 if(ofile->mh64 != NULL) 1234 header_size += 0x88; 1235#endif 1236 /* 1237 * If the lowest section virtual address is greater than the header 1238 * size, pad the header up to the virtual address. This modification 1239 * will make the file offset and virtual address equal, and fixes 1240 * problems with XIP rebasing in the EFI tools. 1241 */ 1242 least_vaddr = 0xffffffff; 1243 for(i = 0; i < nscns; i++){ 1244 if(scnhdrs[i].s_vaddr < least_vaddr) 1245 least_vaddr = scnhdrs[i].s_vaddr; 1246 } 1247 if(least_vaddr > header_size) 1248 header_size = least_vaddr; 1249 1250 offset = header_size; 1251 for(i = 0; i < nscns; i++){ 1252 if((scnhdrs[i].s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0){ 1253 /* 1254 * We need to check that the headers can be mapped starting at 1255 * the ImageBase, fixed at zero in this program, and fit before 1256 * the Virtual Address of the first section (really any section) 1257 * and if it doesn't then we need the Mach-O file relinked. 1258 */ 1259 if(scnhdrs[i].s_vaddr < header_size) 1260 fatal("input file: %s must be relinked so PECOFF headers " 1261 "can be mapped before its sections (use a -seg1addr " 1262 "0x%x or greater)", ofile->file_name, header_size); 1263 /* 1264 * The s_scnptr is set to the offset and then the offset is 1265 * incremented by the SizeOfRawData field (s_vsize). 1266 */ 1267 scnhdrs[i].s_scnptr = offset; 1268#ifndef HACK_TO_MATCH_TEST_CASE 1269 offset += scnhdrs[i].s_vsize; 1270#else 1271 /* for some unknown reason the offset after the __dyld section 1272 is changed from 0x10 bytes to 0x20 bytes */ 1273 if(ofile->mh64 != NULL && scnhdrs[i].s_vsize < 0x20) 1274 offset += 0x20; 1275 /* for some unknown reason the offset after the __data section 1276 is changed from 0x380 bytes to 0x3e0 bytes */ 1277 else if(ofile->mh64 != NULL && scnhdrs[i].s_vsize == 0x380) 1278 offset += scnhdrs[i].s_vsize + 0x60; 1279 else 1280 /* 1281 * Note to match what objcopy(1) does the offset is 1282 * incremented by the VirtualSize field (s_vsize) not the 1283 * SizeOfRawData field (s_size) field as that is what was 1284 * previously set up. 1285 */ 1286 offset += scnhdrs[i].s_vsize; 1287#endif 1288#ifdef HACK_TO_MATCH_TEST_CASE 1289 if(ofile->mh != NULL) 1290#endif 1291 offset = rnd(offset, file_alignment); 1292#ifdef HACK_TO_MATCH_TEST_CASE 1293 else{ 1294 /* for some unknown reason the next offset is moved up 1295 0x200 then rounded to 8 bytes */ 1296 offset += 0x200; 1297 offset = rnd(offset, 8); 1298 } 1299#endif 1300 } 1301 } 1302#ifdef HACK_TO_MATCH_TEST_CASE 1303 /* for some unknown reason the offset of the symbol is moved back 0x58 1304 bytes */ 1305 if(ofile->mh64 != NULL) 1306 offset -= 0x58; 1307#endif 1308 syment_offset = offset; 1309 offset += nsyments * sizeof(struct syment); 1310 string_offset = offset; 1311 offset += strsize; 1312 1313 output_size = offset; 1314 1315 /* 1316 * Now with all the sizes and placement of things know fill in headers 1317 * of the pecoff file for this Mach-O file. 1318 */ 1319 1320 /* first in the pecoff file is the MS-DOS stub */ 1321 create_ms_dos_stub(&ms_dos_stub); 1322 1323 /* 1324 * Second in the pecoff file is the PE format image file signature. 1325 * This signature is PE\0\0 (the letters P and E followed by two null 1326 * bytes). 1327 */ 1328 signature[0] = 'P'; 1329 signature[1] = 'E'; 1330 signature[2] = '\0'; 1331 signature[3] = '\0'; 1332 1333 /* next is the filehdr */ 1334 if(ofile->mh != NULL){ 1335 if(ofile->mh->cputype == CPU_TYPE_I386) 1336 filehdr.f_magic = IMAGE_FILE_MACHINE_I386; 1337 else 1338 filehdr.f_magic = IMAGE_FILE_MACHINE_ARM; 1339 } 1340 else{ 1341 if(ofile->mh64->cputype == CPU_TYPE_X86_64) 1342 filehdr.f_magic = IMAGE_FILE_MACHINE_AMD64; 1343 } 1344 filehdr.f_nscns = nscns; 1345#ifdef HACK_TO_MATCH_TEST_CASE 1346 if(ofile->mh != NULL){ 1347 filehdr.f_timdat = 0x46cb5980; 1348 } 1349 else 1350 filehdr.f_timdat = 0x47671e62; 1351#else 1352 filehdr.f_timdat = time(NULL); 1353#endif 1354 filehdr.f_symptr = syment_offset; 1355 filehdr.f_nsyms = nsyments; 1356 if(ofile->mh != NULL) 1357 filehdr.f_opthdr = sizeof(struct aouthdr); 1358 else 1359 filehdr.f_opthdr = sizeof(struct aouthdr_64); 1360 filehdr.f_flags = IMAGE_FILE_EXECUTABLE_IMAGE | 1361 IMAGE_FILE_LINE_NUMS_STRIPPED | 1362 IMAGE_FILE_32BIT_MACHINE | 1363 IMAGE_FILE_DEBUG_STRIPPED; 1364 if(ofile->mh64 != NULL) 1365 filehdr.f_flags |= IMAGE_FILE_LOCAL_SYMS_STRIPPED; 1366 1367 /* next is the aouthdr */ 1368 if(ofile->mh != NULL){ 1369 aouthdr.magic = PE32MAGIC; 1370 aouthdr.vstamp = VSTAMP; 1371 1372 /* 1373 * EFI does not use t, d, or b size. 1374 * EFI uses SizeOfImage to errorcheck vaddrs in the image 1375 */ 1376 aouthdr.tsize = 0; 1377 aouthdr.dsize = 0; 1378 aouthdr.bsize = 0; 1379 aouthdr.SizeOfImage = rnd(header_size, section_alignment); 1380 for(i = 0; i < nscns; i++){ 1381 aouthdr.SizeOfImage += rnd(scnhdrs[i].s_vsize, section_alignment); 1382 } 1383 1384 aouthdr.entry = entry; 1385 1386 aouthdr.text_start = 0; 1387 aouthdr.data_start = 0; 1388 for(i = 0; i < nscns; i++){ 1389 if((scnhdrs[i].s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==0){ 1390 if((scnhdrs[i].s_flags & IMAGE_SCN_MEM_WRITE) == 0){ 1391 if(aouthdr.text_start == 0) 1392 aouthdr.text_start = scnhdrs[i].s_vaddr; 1393 } 1394 else{ 1395 if(aouthdr.data_start == 0) 1396 aouthdr.data_start = scnhdrs[i].s_vaddr; 1397 } 1398 } 1399 } 1400 1401 aouthdr.ImageBase = 0; 1402 aouthdr.SectionAlignment = section_alignment; 1403 aouthdr.FileAlignment = file_alignment; 1404 aouthdr.MajorOperatingSystemVersion = 0; 1405 aouthdr.MinorOperatingSystemVersion = 0; 1406 aouthdr.MajorImageVersion = 0; 1407 aouthdr.MinorImageVersion = 0; 1408 aouthdr.MajorSubsystemVersion = 0; 1409 aouthdr.MinorSubsystemVersion = 0; 1410 aouthdr.Win32VersionValue = 0; 1411 1412 1413 aouthdr.SizeOfHeaders = header_size; 1414 aouthdr.CheckSum = 0; 1415 aouthdr.Subsystem = Subsystem; 1416 aouthdr.DllCharacteristics = 0; 1417 aouthdr.SizeOfStackReserve = 0; 1418 aouthdr.SizeOfStackCommit = 0; 1419 aouthdr.SizeOfHeapReserve = 0; 1420 aouthdr.SizeOfHeapCommit = 0; 1421 aouthdr.LoaderFlags = 0; 1422 aouthdr.NumberOfRvaAndSizes = 16; 1423 /* Entry 5, Base Relocation Directory [.reloc] address & size */ 1424 if(reloc_size != 0){ 1425 aouthdr.DataDirectory[5][0] = reloc_scnhdr->s_vaddr; 1426 aouthdr.DataDirectory[5][1] = reloc_scnhdr->s_vsize; 1427 } 1428 /* Entry 6, Debug Directory [.debug] address & size */ 1429 if(debug_filename != NULL){ 1430 aouthdr.DataDirectory[6][0] = debug_scnhdr->s_vaddr; 1431 aouthdr.DataDirectory[6][1] = debug_scnhdr->s_vsize; 1432 } 1433 } 1434 else{ 1435 aouthdr64.magic = PE32PMAGIC; 1436 aouthdr64.vstamp = VSTAMP; 1437 1438 /* 1439 * EFI does not use t, d, or b size. 1440 * EFI uses SizeOfImage to errorcheck vaddrs in the image 1441 */ 1442 aouthdr64.tsize = 0; 1443 aouthdr64.dsize = 0; 1444 aouthdr64.bsize = 0; 1445 1446 aouthdr64.SizeOfImage = rnd(header_size, section_alignment); 1447 for(i = 0; i < nscns; i++){ 1448 aouthdr64.SizeOfImage += rnd(scnhdrs[i].s_vsize, section_alignment); 1449 } 1450#ifdef HACK_TO_MATCH_TEST_CASE 1451 /* with the IMAGE_SCN_CNT_CODE flag set on all sections this is 1452 just a quick hack to match the PECOFF file */ 1453 aouthdr64.dsize = 0x200; 1454#endif 1455 1456 aouthdr64.entry = entry; 1457#ifdef HACK_TO_MATCH_TEST_CASE 1458 aouthdr64.entry = 0x4a2; 1459#endif 1460 aouthdr64.text_start = 0; 1461 for(i = 0; i < nscns; i++){ 1462 if((scnhdrs[i].s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) ==0){ 1463 if((scnhdrs[i].s_flags & IMAGE_SCN_MEM_WRITE) == 0){ 1464 if(aouthdr64.text_start == 0) 1465 aouthdr64.text_start = scnhdrs[i].s_vaddr; 1466 } 1467 } 1468 } 1469#ifdef HACK_TO_MATCH_TEST_CASE 1470 /* this is a hack as the start of the text for 64-bit Mach-O files 1471 built with -dylib does not have the text section starting at 0 */ 1472 aouthdr64.text_start = 0; 1473#endif 1474 1475 aouthdr64.ImageBase = 0; 1476 aouthdr64.SectionAlignment = section_alignment; 1477 aouthdr64.FileAlignment = file_alignment; 1478 aouthdr64.MajorOperatingSystemVersion = 0; 1479 aouthdr64.MinorOperatingSystemVersion = 0; 1480 aouthdr64.MajorImageVersion = 0; 1481 aouthdr64.MinorImageVersion = 0; 1482 aouthdr64.MajorSubsystemVersion = 0; 1483 aouthdr64.MinorSubsystemVersion = 0; 1484 aouthdr64.Win32VersionValue = 0; 1485 1486 1487#ifdef HACK_TO_MATCH_TEST_CASE 1488 /* this is a hack as it seams that the minimum size is 0x10000 */ 1489 if(aouthdr64.SizeOfImage < 0x10000) 1490 aouthdr64.SizeOfImage = 0x10000; 1491#endif 1492 aouthdr64.SizeOfHeaders = header_size; 1493 aouthdr64.CheckSum = 0; 1494 aouthdr64.Subsystem = Subsystem; 1495#ifdef HACK_TO_MATCH_TEST_CASE 1496 aouthdr64.Subsystem = IMAGE_SUBSYSTEM_EFI_BOOT_SERVICE_DRIVER; 1497#endif 1498 aouthdr64.DllCharacteristics = 0; 1499 aouthdr64.SizeOfStackReserve = 0; 1500 aouthdr64.SizeOfStackCommit = 0; 1501 aouthdr64.SizeOfHeapReserve = 0; 1502 aouthdr64.SizeOfHeapCommit = 0; 1503 aouthdr64.LoaderFlags = 0; 1504 aouthdr64.NumberOfRvaAndSizes = 16; 1505 /* Entry 5, Base Relocation Directory [.reloc] address & size */ 1506 if(reloc_size != 0){ 1507 aouthdr64.DataDirectory[5][0] = reloc_scnhdr->s_vaddr; 1508 aouthdr64.DataDirectory[5][1] = reloc_scnhdr->s_vsize; 1509 } 1510 /* Entry 6, Debug Directory [.debug] address & size */ 1511 if(debug_filename != NULL){ 1512 aouthdr64.DataDirectory[6][0] = debug_scnhdr->s_vaddr; 1513 aouthdr64.DataDirectory[6][1] = debug_scnhdr->s_vsize; 1514 } 1515 } 1516 1517 /* 1518 * If there is a debug directory entry set the address and offsets in 1519 * it now that the values are known. 1520 */ 1521 if(debug_filename != NULL) 1522 set_debug_addrs_and_offsets(); 1523} 1524 1525/* 1526 * create_output() takes the info gathered from the input Mach-O file and 1527 * creates the pecoff output file. 1528 */ 1529static 1530void 1531create_output( 1532struct ofile *ofile, 1533char *out) 1534{ 1535 int i, f; 1536 unsigned char *buf, *p, *p_aouthdr; 1537 1538 /* 1539 * Allocate the buffer to place the pecoff file in. 1540 */ 1541 buf = calloc(1, output_size); 1542 if(buf == NULL) 1543 fatal("Can't allocate buffer for output file (size = %u)", 1544 output_size); 1545 1546 /* 1547 * Copy the parts of the pecoff file into the buffer. 1548 */ 1549 p = buf; 1550 1551 memcpy(p, &ms_dos_stub, sizeof(struct ms_dos_stub)); 1552 if(swapped) 1553 swap_ms_dos_stub((struct ms_dos_stub *)p, target_byte_sex); 1554 p += sizeof(struct ms_dos_stub); 1555 1556 memcpy(p, signature, sizeof(signature)); 1557 p += sizeof(signature); 1558 1559 memcpy(p, &filehdr, sizeof(struct filehdr)); 1560 if(swapped) 1561 swap_filehdr((struct filehdr *)p, target_byte_sex); 1562 p += sizeof(struct filehdr); 1563 1564 p_aouthdr = p; 1565 if(ofile->mh != NULL){ 1566 memcpy(p, &aouthdr, sizeof(struct aouthdr)); 1567 if(swapped) 1568 swap_aouthdr((struct aouthdr *)p, target_byte_sex); 1569 p += sizeof(struct aouthdr); 1570 } 1571 else{ 1572 memcpy(p, &aouthdr64, sizeof(struct aouthdr_64)); 1573 if(swapped) 1574 swap_aouthdr_64((struct aouthdr_64 *)p, target_byte_sex); 1575 p += sizeof(struct aouthdr_64); 1576 } 1577 1578 /* 1579 * Now copy in the section contents. Note the base relocations 1580 * (the contents of the .reloc section) has already been swapped if 1581 * that was needed. 1582 */ 1583 for(i = 0; i < nscns; i++){ 1584 if((scnhdrs[i].s_flags & IMAGE_SCN_CNT_UNINITIALIZED_DATA) == 0){ 1585 memcpy(buf + scnhdrs[i].s_scnptr, 1586 scn_contents[i], 1587#ifndef HACK_TO_MATCH_TEST_CASE 1588 scnhdrs[i].s_size); 1589#else 1590 scnhdrs[i].s_vsize); 1591#endif 1592 1593#ifdef HACK_TO_MATCH_TEST_CASE 1594 /* this is a hack as this is zero in 64-bit file */ 1595 if(ofile->mh64 != NULL) 1596 scnhdrs[i].s_vsize = 0; 1597#endif 1598 } 1599 } 1600 1601 memcpy(p, scnhdrs, nscns * sizeof(struct scnhdr)); 1602 if(swapped) 1603 swap_scnhdr((struct scnhdr *)p, nscns, target_byte_sex); 1604 p += nscns * sizeof(struct scnhdr); 1605 1606 /* 1607 * Note the base relocations (the contents of the reloc section), 1608 * the symbol table and string table all have already been swapped if 1609 * that was needed. 1610 */ 1611 memcpy(buf + syment_offset, syments, nsyments * sizeof(struct syment)); 1612 memcpy(buf + string_offset, strings, strsize); 1613 1614 /* 1615 * Now with the file contents complete compute the CheckSum in the 1616 * optional header and update that in the output buffer. 1617 */ 1618 if(ofile->mh != NULL){ 1619 aouthdr.CheckSum = checksum(buf) + output_size; 1620 memcpy(p_aouthdr, &aouthdr, sizeof(struct aouthdr)); 1621 if(swapped) 1622 swap_aouthdr((struct aouthdr *)p_aouthdr, target_byte_sex); 1623 } 1624 else{ 1625 aouthdr64.CheckSum = checksum(buf) + output_size; 1626 memcpy(p_aouthdr, &aouthdr64, sizeof(struct aouthdr_64)); 1627 if(swapped) 1628 swap_aouthdr_64((struct aouthdr_64 *)p_aouthdr,target_byte_sex); 1629 } 1630 1631 /* 1632 * Create the pecoff file and write the buffer to the file. 1633 */ 1634 f = open(out, O_WRONLY|O_CREAT|O_TRUNC, 0644); 1635 if(f == -1) 1636 system_fatal("Can't create output file: %s", out); 1637 1638 if(write(f, buf, output_size) != output_size) 1639 system_fatal("Can't write output file: %s", out); 1640 1641 if(close(f) == -1) 1642 system_fatal("Can't close output file: %s", out); 1643} 1644 1645/* 1646 * create_ms_dos_stub() is pass a pointer to the buffer where to fill in the 1647 * MS-DOS stub. 1648 */ 1649static 1650void 1651create_ms_dos_stub( 1652struct ms_dos_stub *p) 1653{ 1654 int i; 1655 1656 p->e_magic = DOSMAGIC; 1657 p->e_cblp = 0x90; 1658 p->e_cp = 0x3; 1659 p->e_crlc = 0x0; 1660 p->e_cparhdr = 0x4; 1661 p->e_minalloc = 0x0; 1662 p->e_maxalloc = 0xffff; 1663 p->e_ss = 0x0; 1664 p->e_sp = 0xb8; 1665 p->e_csum = 0x0; 1666 p->e_ip = 0x0; 1667 p->e_cs = 0x0; 1668 p->e_lfarlc = 0x40; 1669 p->e_ovno = 0x0; 1670 1671 for(i = 0; i < 4; i++) 1672 p->e_res[i] = 0x0; 1673 1674 p->e_oemid = 0x0; 1675 p->e_oeminfo = 0x0; 1676 1677 for(i = 0; i < 10; i++) 1678 p->e_res2[i] = 0x0; 1679 1680 p->e_lfanew = 0x80; 1681 1682 /* 1683 * The sub dos program that prints "This program cannot be run in DOS 1684 * mode". 1685 */ 1686 p->dos_program[0] = 0x0e; 1687 p->dos_program[1] = 0x1f; 1688 p->dos_program[2] = 0xba; 1689 p->dos_program[3] = 0x0e; 1690 p->dos_program[4] = 0x00; 1691 p->dos_program[5] = 0xb4; 1692 p->dos_program[6] = 0x09; 1693 p->dos_program[7] = 0xcd; 1694 p->dos_program[8] = 0x21; 1695 p->dos_program[9] = 0xb8; 1696 p->dos_program[10] = 0x01; 1697 p->dos_program[11] = 0x4c; 1698 p->dos_program[12] = 0xcd; 1699 p->dos_program[13] = 0x21; 1700 p->dos_program[14] = 0x54; 1701 p->dos_program[15] = 0x68; 1702 p->dos_program[16] = 0x69; 1703 p->dos_program[17] = 0x73; 1704 p->dos_program[18] = 0x20; 1705 p->dos_program[19] = 0x70; 1706 p->dos_program[20] = 0x72; 1707 p->dos_program[21] = 0x6f; 1708 p->dos_program[22] = 0x67; 1709 p->dos_program[23] = 0x72; 1710 p->dos_program[24] = 0x61; 1711 p->dos_program[25] = 0x6d; 1712 p->dos_program[26] = 0x20; 1713 p->dos_program[27] = 0x63; 1714 p->dos_program[28] = 0x61; 1715 p->dos_program[29] = 0x6e; 1716 p->dos_program[30] = 0x6e; 1717 p->dos_program[31] = 0x6f; 1718 p->dos_program[32] = 0x74; 1719 p->dos_program[33] = 0x20; 1720 p->dos_program[34] = 0x62; 1721 p->dos_program[35] = 0x65; 1722 p->dos_program[36] = 0x20; 1723 p->dos_program[37] = 0x72; 1724 p->dos_program[38] = 0x75; 1725 p->dos_program[39] = 0x6e; 1726 p->dos_program[40] = 0x20; 1727 p->dos_program[41] = 0x69; 1728 p->dos_program[42] = 0x6e; 1729 p->dos_program[43] = 0x20; 1730 p->dos_program[44] = 0x44; 1731 p->dos_program[45] = 0x4f; 1732 p->dos_program[46] = 0x53; 1733 p->dos_program[47] = 0x20; 1734 p->dos_program[48] = 0x6d; 1735 p->dos_program[49] = 0x6f; 1736 p->dos_program[50] = 0x64; 1737 p->dos_program[51] = 0x65; 1738 p->dos_program[52] = 0x2e; 1739 p->dos_program[53] = 0x0d; 1740 p->dos_program[54] = 0x0d; 1741 p->dos_program[55] = 0x0a; 1742 p->dos_program[56] = 0x24; 1743 p->dos_program[57] = 0x0; 1744 p->dos_program[58] = 0x0; 1745 p->dos_program[59] = 0x0; 1746 p->dos_program[60] = 0x0; 1747 p->dos_program[61] = 0x0; 1748 p->dos_program[62] = 0x0; 1749 p->dos_program[63] = 0x0; 1750} 1751 1752 1753/* 1754 * create_32bit_symbol_table() is called to process the input Mach-O file and 1755 * create the pecoff symbol and string table. 1756 */ 1757static 1758void 1759create_32bit_symbol_table( 1760struct arch *arch) 1761{ 1762 char *object_addr; 1763 struct symtab_command *st; 1764 struct nlist *syms; 1765 char *strs; 1766 enum bool found_undef; 1767#ifdef HACK_TO_MATCH_TEST_CASE 1768 uint32_t j, n_sect, bss_n_sect, common_n_sect, 1769 bss_addr, common_addr, size; 1770 struct load_command *lc; 1771 struct segment_command *sg; 1772 struct section *s; 1773#endif /* HACK_TO_MATCH_TEST_CASE */ 1774 uint32_t i; 1775 char *p; 1776 1777 /* 1778 * No symbols are actually needed in the pecoff file from the Mach-O 1779 * file so create an empty symbol table. 1780 */ 1781 nsyments = 0; 1782 1783 /* 1784 * Make sure the Mach-O file does not have any undefined symbols. 1785 */ 1786 st = arch->object->st; 1787 object_addr = arch->object->object_addr; 1788 syms = (struct nlist *)(object_addr + st->symoff); 1789 strs = object_addr + st->stroff; 1790 if(swapped) 1791 swap_nlist(syms, st->nsyms, host_byte_sex); 1792 found_undef = FALSE; 1793 for(i = 0; i < st->nsyms; i++){ 1794 if((syms[i].n_type & N_STAB) != 0) 1795 continue; 1796 if((syms[i].n_type & N_TYPE) == N_UNDF){ 1797 if(found_undef == FALSE){ 1798 error("input file: %s contains undefined symbols:", 1799 arch->file_name); 1800 } 1801 found_undef = TRUE; 1802 if(syms[i].n_un.n_strx != 0) 1803 printf("%s\n", strs + syms[i].n_un.n_strx); 1804 else 1805 printf("symbol at index %u is undefined but has NULL " 1806 "name (like a malformed Mach-O file)\n", i); 1807 } 1808 } 1809 if(found_undef == TRUE) 1810 fatal("undefined symbols are unsupported for conversion to a " 1811 "pecoff file"); 1812 1813#ifdef HACK_TO_MATCH_TEST_CASE 1814 /* 1815 * The hack implementation of this routine exist only in order to 1816 * match the current ld_efi(1) script that uses objcopy(1) to make the 1817 * pecoff file. So for that only the common symbols and bss symbols 1818 * make it into the output pecoff file. 1819 * 1820 */ 1821 1822 /* 1823 * First figure out the section number of the common and bss sections 1824 * and address of those sections. 1825 */ 1826 n_sect = 1; 1827 bss_n_sect = 0; 1828 bss_addr = 0; 1829 common_n_sect = 0; 1830 common_addr = 0; 1831 lc = arch->object->load_commands; 1832 for(i = 0; i < arch->object->mh->ncmds; i++){ 1833 if(lc->cmd == LC_SEGMENT){ 1834 sg = (struct segment_command *)lc; 1835 if(strcmp(sg->segname, SEG_DATA) == 0){ 1836 s = (struct section *) 1837 ((char *)sg + sizeof(struct segment_command)); 1838 for(j = 0; j < sg->nsects; j++){ 1839 if(strcmp(s->sectname, SECT_BSS) == 0){ 1840 bss_n_sect = n_sect; 1841 bss_addr = s->addr; 1842 } 1843 else if(strcmp(s->sectname, SECT_COMMON) == 0){ 1844 common_n_sect = n_sect; 1845 common_addr = s->addr; 1846 } 1847 s++; 1848 n_sect++; 1849 } 1850 } 1851 else{ 1852 n_sect += sg->nsects; 1853 } 1854 } 1855 lc = (struct load_command *)((char *)lc + lc->cmdsize); 1856 } 1857 1858 /* 1859 * Count the number of the common and bss sections symbols and add up 1860 * the size of their strings. Note the size of long section names is 1861 * already accounted for in strsize by the code in process_32bit_arch(). 1862 */ 1863 for(i = 0; i < st->nsyms; i++){ 1864 if((syms[i].n_type & N_STAB) == 0 && 1865 (syms[i].n_type & N_TYPE) == N_SECT && 1866 (syms[i].n_sect == bss_n_sect || 1867 syms[i].n_sect == common_n_sect)){ 1868 nsyments++; 1869 if(syms[i].n_un.n_strx != 0){ 1870 size = strlen(strs + syms[i].n_un.n_strx); 1871 if(size > E_SYMNMLEN) 1872 strsize += strlen(strs + syms[i].n_un.n_strx) + 1; 1873 } 1874 } 1875 } 1876#endif /* HACK_TO_MATCH_TEST_CASE */ 1877 1878 /* 1879 * Allocate space for the pecoff symbol table and string table. 1880 */ 1881 syments = allocate(nsyments * sizeof(struct syment)); 1882 memset(syments, '\0', nsyments * sizeof(struct syment)); 1883 strings = allocate(strsize); 1884 1885 /* 1886 * Put the size of the string table in the string table first. Then 1887 * the strings for the long section names right after the size. 1888 */ 1889 p = strings; 1890 1891 i = strsize; 1892 if(swapped) 1893 i = SWAP_INT(i); 1894 memcpy(p, &i, sizeof(uint32_t)); 1895 p += sizeof(uint32_t); 1896 1897 memcpy(p, section_names, section_names_size); 1898 p += section_names_size; 1899 1900#ifdef HACK_TO_MATCH_TEST_CASE 1901 /* 1902 * First put in the bss symbols, again to match what is done by 1903 * objcopy. 1904 */ 1905 j = 0; 1906 for(i = 0; i < st->nsyms; i++){ 1907 if((syms[i].n_type & N_STAB) == 0 && 1908 (syms[i].n_type & N_TYPE) == N_SECT && 1909 syms[i].n_sect == bss_n_sect){ 1910 if(syms[i].n_un.n_strx != 0){ 1911 size = strlen(strs + syms[i].n_un.n_strx); 1912 if(size > E_SYMNMLEN){ 1913 syments[j].e.e.e_zeroes = 0; 1914 syments[j].e.e.e_offset = p - strings; 1915 strcpy(p, strs + syms[i].n_un.n_strx); 1916 p += strlen(strs + syms[i].n_un.n_strx) + 1; 1917 } 1918 else{ 1919 strncpy(syments[j].e.e_name, 1920 strs + syms[i].n_un.n_strx, E_SYMNMLEN); 1921 } 1922 } 1923 syments[j].e_value = syms[i].n_value - bss_addr; 1924 syments[j].e_scnum = bss_scnum; 1925 syments[j].e_type = 0; 1926 syments[j].e_sclass = IMAGE_SYM_CLASS_EXTERNAL; 1927 syments[j].e_numaux = 0; 1928 j++; 1929 } 1930 } 1931 /* 1932 * Next put in the common symbols, again to match what is done by 1933 * objcopy. 1934 */ 1935 for(i = 0; i < st->nsyms; i++){ 1936 if((syms[i].n_type & N_STAB) == 0 && 1937 (syms[i].n_type & N_TYPE) == N_SECT && 1938 syms[i].n_sect == common_n_sect){ 1939 if(syms[i].n_un.n_strx != 0){ 1940 size = strlen(strs + syms[i].n_un.n_strx); 1941 if(size > E_SYMNMLEN){ 1942 syments[j].e.e.e_zeroes = 0; 1943 syments[j].e.e.e_offset = p - strings; 1944 strcpy(p, strs + syms[i].n_un.n_strx); 1945 p += strlen(strs + syms[i].n_un.n_strx) + 1; 1946 } 1947 else{ 1948 strncpy(syments[j].e.e_name, 1949 strs + syms[i].n_un.n_strx, E_SYMNMLEN); 1950 } 1951 } 1952 syments[j].e_value = syms[i].n_value - common_addr; 1953 syments[j].e_scnum = common_scnum; 1954 syments[j].e_type = 0; 1955 syments[j].e_sclass = IMAGE_SYM_CLASS_EXTERNAL; 1956 syments[j].e_numaux = 0; 1957 j++; 1958 } 1959 } 1960 1961 if(swapped) 1962 swap_syment(syments, nsyments, target_byte_sex); 1963 1964#endif /* HACK_TO_MATCH_TEST_CASE */ 1965} 1966 1967/* 1968 * create_64bit_symbol_table() is called to process the input Mach-O file and 1969 * create the pecoff symbol and string table. 1970 */ 1971static 1972void 1973create_64bit_symbol_table( 1974struct arch *arch) 1975{ 1976 char *p; 1977 uint32_t i; 1978 char *object_addr; 1979 struct symtab_command *st; 1980 struct nlist_64 *syms64; 1981 char *strs; 1982 enum bool found_undef; 1983 1984 st = arch->object->st; 1985 object_addr = arch->object->object_addr; 1986 syms64 = (struct nlist_64 *)(object_addr + st->symoff); 1987 strs = object_addr + st->stroff; 1988 if(swapped) 1989 swap_nlist_64(syms64, st->nsyms, host_byte_sex); 1990 /* 1991 * If the entry point option was specified then look for that symbol 1992 * and set the entry point value. 1993 */ 1994 if(entry_point != NULL){ 1995 for(i = 0; i < st->nsyms; i++){ 1996 if((syms64[i].n_type & N_STAB) == 0 && 1997 syms64[i].n_un.n_strx != 0 && 1998 strcmp(strs + syms64[i].n_un.n_strx, entry_point) == 0){ 1999 entry = syms64[i].n_value; 2000 break; 2001 } 2002 } 2003 if(i == st->nsyms) 2004 fatal("can't find symbol for -e %s in input file: %s", 2005 entry_point, arch->file_name); 2006 } 2007 2008 /* 2009 * Make sure the Mach-O file does not have any undefined symbols. 2010 */ 2011 found_undef = FALSE; 2012 for(i = 0; i < st->nsyms; i++){ 2013 if((syms64[i].n_type & N_STAB) != 0) 2014 continue; 2015 if((syms64[i].n_type & N_TYPE) == N_UNDF){ 2016 if(found_undef == FALSE){ 2017 error("input file: %s contains undefined symbols:", 2018 arch->file_name); 2019 } 2020 found_undef = TRUE; 2021 if(syms64[i].n_un.n_strx != 0) 2022 printf("%s\n", strs + syms64[i].n_un.n_strx); 2023 else 2024 printf("symbol at index %u is undefined but has NULL " 2025 "name (like a malformed Mach-O file)\n", i); 2026 } 2027 } 2028 if(found_undef == TRUE) 2029 fatal("undefined symbols are unsupported for conversion to a " 2030 "pecoff file"); 2031 2032 /* 2033 * No symbols are actually needed in the pecoff file from the Mach-O 2034 * file so create an empty symbol table. 2035 * 2036 * Set the number of symbols to zero and allocate the string table. 2037 * Note the size of long section names is already accounted for in 2038 * strsize by the code in process_64bit_arch(). 2039 */ 2040 nsyments = 0; 2041 strings = allocate(strsize); 2042 2043 /* 2044 * Put the size of the string table in the string table first. Then 2045 * the strings for the long section names right after the size. 2046 */ 2047 p = strings; 2048 2049 i = strsize; 2050 if(swapped) 2051 i = SWAP_INT(i); 2052 memcpy(p, &i, sizeof(uint32_t)); 2053 p += sizeof(uint32_t); 2054 2055 memcpy(p, section_names, section_names_size); 2056} 2057 2058/* 2059 * create_base_reloc() is called to process the input Mach-O file and gather 2060 * the info needed and then to create the base relocation entries. 2061 */ 2062static 2063void 2064create_base_reloc( 2065struct arch *arch) 2066{ 2067 uint32_t ncmds, i, j; 2068 uint64_t addr, first_addr; 2069 struct load_command *lc; 2070 struct segment_command *sg; 2071 struct segment_command_64 *sg64; 2072 struct section *s; 2073 struct section_64 *s64; 2074 struct relocation_info *relocs; 2075 2076 char *object_addr; 2077 struct dysymtab_command *dyst; 2078 2079 if(arch->object->mh != NULL) 2080 ncmds = arch->object->mh->ncmds; 2081 else 2082 ncmds = arch->object->mh64->ncmds; 2083 dyst = arch->object->dyst; 2084 object_addr = arch->object->object_addr; 2085 2086 first_addr = 0; 2087 lc = arch->object->load_commands; 2088 for(i = 0; i < ncmds; i++){ 2089 if(lc->cmd == LC_SEGMENT){ 2090 sg = (struct segment_command *)lc; 2091 if(first_addr == 0) 2092 first_addr = sg->vmaddr; 2093 s = (struct section *) 2094 ((char *)sg + sizeof(struct segment_command)); 2095 for(j = 0; j < sg->nsects; j++){ 2096 relocs = (struct relocation_info *)(object_addr + 2097 s[j].reloff); 2098 if(swapped) 2099 swap_relocation_info(relocs, s[j].nreloc, 2100 host_byte_sex); 2101 if(arch->object->mh_cputype == CPU_TYPE_I386) 2102 gather_base_reloc_info(s[j].addr, relocs, s[j].nreloc, 2103 CPU_TYPE_I386, 2, GENERIC_RELOC_VANILLA, 2104 IMAGE_REL_BASED_HIGHLOW); 2105 else if(arch->object->mh_cputype == CPU_TYPE_ARM) 2106 gather_base_reloc_info(s[j].addr, relocs, s[j].nreloc, 2107 CPU_TYPE_ARM, 2, GENERIC_RELOC_VANILLA, 2108 IMAGE_REL_BASED_HIGHLOW); 2109 if((s[j].flags & SECTION_TYPE) == 2110 S_NON_LAZY_SYMBOL_POINTERS){ 2111 for(addr = s[j].addr; 2112 addr < s[j].addr + s[j].size; 2113 addr += 4) { 2114 add_base_reloc(addr, IMAGE_REL_BASED_HIGHLOW); 2115 } 2116 } 2117 } 2118 } 2119 else if(lc->cmd == LC_SEGMENT_64){ 2120 sg64 = (struct segment_command_64 *)lc; 2121 if(arch->object->mh_cputype == CPU_TYPE_X86_64) { 2122 /* 2123 * X86_64 relocations are relative to the first writable 2124 * segment. 2125 */ 2126 if((first_addr == 0) && 2127 ((sg64->initprot & VM_PROT_WRITE) != 0)) { 2128 first_addr = sg64->vmaddr; 2129 } 2130 } else { 2131 if(first_addr == 0) 2132 first_addr = sg64->vmaddr; 2133 } 2134 s64 = (struct section_64 *) 2135 ((char *)sg64 + sizeof(struct segment_command_64)); 2136 for(j = 0; j < sg64->nsects; j++){ 2137 relocs = (struct relocation_info *)(object_addr + 2138 s64[j].reloff); 2139 if(swapped) 2140 swap_relocation_info(relocs, s64[j].nreloc, 2141 host_byte_sex); 2142 if(arch->object->mh_cputype == CPU_TYPE_X86_64) 2143 gather_base_reloc_info(s64[j].addr, relocs, 2144 s64[j].nreloc, CPU_TYPE_X86_64, 3, 2145 X86_64_RELOC_UNSIGNED, IMAGE_REL_BASED_DIR64); 2146 if((s64[j].flags & SECTION_TYPE) == 2147 S_NON_LAZY_SYMBOL_POINTERS){ 2148 for(addr = s64[j].addr; 2149 addr < s64[j].addr + s64[j].size; 2150 addr += 8) { 2151 add_base_reloc(addr, IMAGE_REL_BASED_DIR64); 2152 } 2153 } 2154 } 2155 } 2156 lc = (struct load_command *)((char *)lc + lc->cmdsize); 2157 } 2158 if(dyst != NULL && dyst->nlocrel != 0){ 2159 relocs = (struct relocation_info *)(object_addr + 2160 dyst->locreloff); 2161 if(swapped) 2162 swap_relocation_info(relocs, dyst->nlocrel, host_byte_sex); 2163 if(arch->object->mh_cputype == CPU_TYPE_I386) 2164 gather_base_reloc_info(first_addr, relocs, dyst->nlocrel, 2165 CPU_TYPE_I386, 2, GENERIC_RELOC_VANILLA, 2166 IMAGE_REL_BASED_HIGHLOW); 2167 else if(arch->object->mh_cputype == CPU_TYPE_ARM) 2168 gather_base_reloc_info(first_addr, relocs, dyst->nlocrel, 2169 CPU_TYPE_ARM, 2, GENERIC_RELOC_VANILLA, 2170 IMAGE_REL_BASED_HIGHLOW); 2171 else if(arch->object->mh_cputype == CPU_TYPE_X86_64) 2172 gather_base_reloc_info(first_addr, relocs, dyst->nlocrel, 2173 CPU_TYPE_X86_64, 3, X86_64_RELOC_UNSIGNED, 2174 IMAGE_REL_BASED_DIR64); 2175 } 2176 /* 2177 if(dyst != NULL && dyst->nextrel != 0) 2178 ; TODO error if there are external relocation entries */ 2179 2180 /* 2181 * Now with all the info gathered make the base relocation entries. 2182 */ 2183 make_base_relocs(); 2184} 2185 2186/* 2187 * gather_base_reloc_info() is passed the base address for the set of Mach-O 2188 * relocation entries. And is passed the cpu_type, length and macho_reloc_type 2189 * to look for and the base_reloc_type to create if found. 2190 */ 2191static 2192void 2193gather_base_reloc_info( 2194uint32_t addr, 2195struct relocation_info *relocs, 2196uint32_t nreloc, 2197cpu_type_t cpu_type, 2198uint32_t length, 2199int macho_reloc_type, 2200int base_reloc_type) 2201{ 2202 uint32_t i, r_address, r_pcrel, r_length, r_extern, r_type; 2203 struct scattered_relocation_info *sreloc; 2204 2205 for(i = 0; i < nreloc; i++){ 2206 if((relocs[i].r_address & R_SCATTERED) != 0){ 2207 sreloc = (struct scattered_relocation_info *)(relocs + i); 2208 r_address = sreloc->r_address; 2209 r_pcrel = sreloc->r_pcrel; 2210 r_length = sreloc->r_length; 2211 r_type = (enum reloc_type_generic)sreloc->r_type; 2212 r_extern = 0; 2213 } 2214 else{ 2215 r_address = relocs[i].r_address; 2216 r_pcrel = relocs[i].r_pcrel; 2217 r_length = relocs[i].r_length; 2218 r_extern = relocs[i].r_extern; 2219 r_type = (enum reloc_type_generic)relocs[i].r_type; 2220 } 2221 2222 if(r_extern == 0 && r_pcrel == 0 && 2223 r_length == length && r_type == macho_reloc_type) 2224 add_base_reloc(addr + r_address, base_reloc_type); 2225 else 2226 ; /* TODO add checking and error messages here */ 2227 2228 if((relocs[i].r_address & R_SCATTERED) == 0){ 2229 if(reloc_has_pair(cpu_type, relocs[i].r_type)) 2230 i++; 2231 } 2232 else{ 2233 sreloc = (struct scattered_relocation_info *)relocs + i; 2234 if(reloc_has_pair(cpu_type, sreloc->r_type)) 2235 i++; 2236 } 2237 } 2238} 2239 2240/* 2241 * add_base_reloc() is passed a addr and a type for a base relocation entry to 2242 * add to the list. 2243 */ 2244static 2245void 2246add_base_reloc( 2247uint64_t addr, 2248uint32_t type) 2249{ 2250 static int max = 0; 2251 struct base_reloc *new_base_relocs; 2252 2253 if(!max){ 2254 max = 128; 2255 base_relocs = (struct base_reloc *) 2256 malloc(max * sizeof(struct base_reloc)); 2257 } 2258 if(nbase_reloc >= max){ 2259 new_base_relocs = malloc(2 * max * sizeof(struct base_reloc)); 2260 memcpy(new_base_relocs, base_relocs, 2261 max * sizeof(struct base_reloc)); 2262 max *= 2; 2263 free(base_relocs); 2264 base_relocs = new_base_relocs; 2265 } 2266 base_relocs[nbase_reloc].addr = addr; 2267 base_relocs[nbase_reloc].type = type; 2268 nbase_reloc++; 2269} 2270 2271/* 2272 * The base relocation table in a PECOFF file is divided into blocks. Each 2273 * block represents the base relocations for a 4K page. Each block must start 2274 * on a 32-bit boundary. Which is why one "nop" base relocation entry may be 2275 * be added as padding in a block. 2276 */ 2277#define MAX_BLOCK_OFFSET 0x1000 2278#define BLOCK_MASK (MAX_BLOCK_OFFSET-1) 2279 2280/* 2281 * make_base_relocs() takes the info for the base relocation entries gathered 2282 * and creates the fixup blocks as they would be in a PECOFF file and sets the 2283 * static variables reloc_contents and reloc_size to the pointer to contents 2284 * and the size of that contents. 2285 */ 2286static 2287void 2288make_base_relocs( 2289void) 2290{ 2291 int blockcnt; 2292 int i, entries; 2293 uint64_t base; 2294 int size; 2295 char *fb; 2296 struct base_relocation_block_header *h; 2297 struct base_relocation_entry *b; 2298 uint32_t offset; 2299 2300 blockcnt = 0; 2301 2302 /* 2303 * After we create each base relocation block we will allocate space 2304 * for it in the .reloc section contents buffer and copy it into the 2305 * buffer. 2306 */ 2307 reloc_size = 0; 2308 reloc_contents = NULL; 2309 2310 /* 2311 * If there are no base relocation entries return so we don't create a 2312 * base relocation block with 0 entries. 2313 */ 2314 if(nbase_reloc == 0) 2315 return; 2316 2317 qsort(base_relocs, nbase_reloc, sizeof(struct base_reloc), 2318 (int (*)(const void *, const void *))cmp_base_relocs); 2319 2320 /* 2321 * The size of the base relocation tables must be a multiple of 4 bytes. 2322 * so we may need to add one relocation entry as padding. We make this 2323 * fixup block large enought to hold all the base relocation entries. 2324 * But it will be broken up for the base relocation entries for each 2325 * each group that refers to the same 4K page. 2326 */ 2327 size = sizeof(struct base_relocation_block_header) + 2328 (nbase_reloc + 1) * sizeof(struct base_relocation_entry); 2329 fb = malloc(size); 2330 2331 2332 entries = 0; 2333 base = base_relocs[0].addr & ~BLOCK_MASK; 2334 h = (struct base_relocation_block_header *)fb; 2335 b = (struct base_relocation_entry *) 2336 (fb + sizeof(struct base_relocation_block_header)); 2337 for(i = 0; i < nbase_reloc; i++){ 2338 offset = base_relocs[i].addr - base; 2339 if(offset >= MAX_BLOCK_OFFSET) { 2340 /* add padding if needed */ 2341 if((entries % 2) != 0){ 2342 b[entries].type = IMAGE_REL_BASED_ABSOLUTE; 2343 b[entries].offset = 0; 2344 entries++; 2345 } 2346 h->page_rva = base; 2347 size = sizeof(struct base_relocation_block_header) + 2348 entries * sizeof(struct base_relocation_entry); 2349 h->block_size = size; 2350 if(swapped){ 2351 swap_base_relocation_block_header(h, 2352 target_byte_sex); 2353 swap_base_relocation_entry(b, entries, 2354 target_byte_sex); 2355 } 2356 /* copy this finished block into the .reloc contents buffer */ 2357 reloc_contents = reallocate(reloc_contents, reloc_size + size); 2358 memcpy(reloc_contents + reloc_size, fb, size); 2359 reloc_size += size; 2360 2361 entries = 0; 2362 blockcnt++; 2363 base = base_relocs[i].addr & ~BLOCK_MASK; 2364 offset = base_relocs[i].addr - base; 2365 } 2366 b[entries].type = base_relocs[i].type; 2367 b[entries].offset = offset; 2368 entries++; 2369 } 2370 2371 /* add padding if needed */ 2372 if((entries % 2) != 0){ 2373 b[entries].type = IMAGE_REL_BASED_ABSOLUTE; 2374 b[entries].offset = 0; 2375 entries++; 2376 } 2377 h->page_rva = base; 2378 size = sizeof(struct base_relocation_block_header) + 2379 entries * sizeof(struct base_relocation_entry); 2380 h->block_size = size; 2381 if(swapped){ 2382 swap_base_relocation_block_header(h, target_byte_sex); 2383 swap_base_relocation_entry(b, entries, target_byte_sex); 2384 } 2385 2386 /* copy this last block into the .reloc contents buffer */ 2387 reloc_contents = reallocate(reloc_contents, reloc_size + size); 2388 memcpy(reloc_contents + reloc_size, fb, size); 2389 reloc_size += size; 2390 2391 blockcnt++; 2392 free(fb); 2393} 2394 2395static 2396int 2397cmp_base_relocs( 2398struct base_reloc *x1, 2399struct base_reloc *x2) 2400{ 2401 if(x1->addr < x2->addr) 2402 return(-1); 2403 if(x1->addr == x2->addr) 2404 return(0); 2405 /* x1->addr > x2->addr */ 2406 return(1); 2407} 2408 2409/* 2410 * create_debug() is called to create the .debug section contents from 2411 * the -d filename argument. 2412 */ 2413static 2414void 2415create_debug( 2416struct arch *arch) 2417{ 2418 char *p; 2419 uint32_t i, ncmds; 2420 struct load_command *lc; 2421 struct uuid_command *uuid; 2422 2423 /* 2424 * Allocate space for everything that will be in the .debug section: 2425 * the debug_directory_entry struct 2426 * the mtoc_debug_info struct 2427 * the name of the -d filename argument null terminated. 2428 */ 2429 debug_size = sizeof(struct debug_directory_entry) + 2430 sizeof(struct mtoc_debug_info) + 2431 strlen(debug_filename) + 1; 2432 debug_contents = allocate(debug_size); 2433 memset(debug_contents, '\0', debug_size); 2434 /* 2435 * Set up pointers to all the parts to be filled in. 2436 */ 2437 p = debug_contents; 2438 dde = (struct debug_directory_entry *)p; 2439 p += sizeof(struct debug_directory_entry); 2440 mdi = (struct mtoc_debug_info *)p; 2441 p += sizeof(struct mtoc_debug_info); 2442 2443 dde->Characteristics = 0; 2444 dde->TimeDateStamp = time(NULL); 2445 dde->MajorVersion = 0; 2446 dde->MinorVersion = 0; 2447 dde->Type = IMAGE_DEBUG_TYPE_CODEVIEW; 2448 dde->SizeOfData = sizeof(struct mtoc_debug_info) + 2449 strlen(debug_filename) + 1; 2450 /* 2451 * These two will be filled in later when address and offsets 2452 * are known. 2453 */ 2454 dde->AddressOfRawData = 0; 2455 dde->PointerToRawData = 0; 2456 2457 mdi->Signature = MTOC_SIGNATURE; 2458 if(arch->object->mh != NULL) 2459 ncmds = arch->object->mh->ncmds; 2460 else 2461 ncmds = arch->object->mh64->ncmds; 2462 lc = arch->object->load_commands; 2463 for(i = 0; i < ncmds; i++){ 2464 if(lc->cmd == LC_UUID){ 2465 uuid = (struct uuid_command *)lc; 2466 if (debug_uuid != NULL) { 2467 string_to_uuid (debug_uuid, uuid->uuid); 2468 } 2469 mdi->uuid[0] = uuid->uuid[0]; 2470 mdi->uuid[1] = uuid->uuid[1]; 2471 mdi->uuid[2] = uuid->uuid[2]; 2472 mdi->uuid[3] = uuid->uuid[3]; 2473 mdi->uuid[4] = uuid->uuid[4]; 2474 mdi->uuid[5] = uuid->uuid[5]; 2475 mdi->uuid[6] = uuid->uuid[6]; 2476 mdi->uuid[7] = uuid->uuid[7]; 2477 mdi->uuid[8] = uuid->uuid[8]; 2478 mdi->uuid[9] = uuid->uuid[9]; 2479 mdi->uuid[10] = uuid->uuid[10]; 2480 mdi->uuid[11] = uuid->uuid[11]; 2481 mdi->uuid[12] = uuid->uuid[12]; 2482 mdi->uuid[13] = uuid->uuid[13]; 2483 mdi->uuid[14] = uuid->uuid[14]; 2484 mdi->uuid[15] = uuid->uuid[15]; 2485 break; 2486 } 2487 lc = (struct load_command *)((char *)lc + lc->cmdsize); 2488 } 2489 2490 strcpy(p, debug_filename); 2491} 2492 2493/* 2494 * set_debug_addrs_and_offsets() is called after the .debug section's address 2495 * and offset has been set and this routine sets the other needed addresses 2496 * and offsets in the section contents. And swaps the section contents if 2497 * needed for output. 2498 */ 2499static 2500void 2501set_debug_addrs_and_offsets( 2502void) 2503{ 2504 dde->AddressOfRawData = debug_scnhdr->s_vaddr + 2505 sizeof(struct debug_directory_entry); 2506 dde->PointerToRawData = debug_scnhdr->s_scnptr + 2507 sizeof(struct debug_directory_entry); 2508 if(swapped){ 2509 swap_debug_directory_entry(dde, target_byte_sex); 2510 swap_mtoc_debug_info(mdi, target_byte_sex); 2511 } 2512} 2513 2514/* 2515 * checksum() calculates the value for the CheckSum field in the optional 2516 * header from the bytes in the output buffer passed to it which has the 2517 * size output_size. 2518 */ 2519static 2520uint32_t 2521checksum( 2522unsigned char *buf) 2523{ 2524 uint32_t i, v, t; 2525 2526 t = 0; 2527 for(i = 0; i < output_size; i += 2){ 2528 if(output_size - i == 1) 2529 v = buf[i]; 2530 else 2531 v = buf[i] + (buf[i+1] << 8); 2532 t += v; 2533 t = 0xffff & (t + (t >> 0x10)); 2534 } 2535 return(0xffff & (t + (t >> 0x10))); 2536} 2537 2538/* 2539 * string_to_uuid() creates a 128-bit uuid from a well-formatted UUID string 2540 * (i.e. aabbccdd-eeff-gghh-iijj-kkllmmnnoopp) 2541 */ 2542static 2543void 2544string_to_uuid( 2545char *string, 2546uint8_t *uuid) 2547{ 2548 uint8_t count; 2549 2550 /* 2551 * scanned bytewise to ensure correct endianness of fields 2552 */ 2553 count = sscanf (string, UUID_FORMAT_STRING, 2554 &uuid[3], &uuid[2], &uuid[1], &uuid[0], 2555 &uuid[5], &uuid[4], 2556 &uuid[7], &uuid[6], 2557 &uuid[8], &uuid[9], &uuid[10], &uuid[11], 2558 &uuid[12], &uuid[13], &uuid[14], &uuid[15]); 2559 2560 if (count != 16) { 2561 fatal ("invalid UUID specified for -u option"); 2562 } 2563} 2564