1/* 2 * Copyright (c) 2006 Apple Computer, 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#include <stdio.h> 24#include <stdlib.h> 25#include <string.h> 26#include <limits.h> 27#include <fcntl.h> 28#include <sys/types.h> 29#include <sys/stat.h> 30#include <sys/mman.h> 31#include "stuff/allocate.h" 32#include "stuff/errors.h" 33#include "stuff/breakout.h" 34#include "stuff/rnd.h" 35 36/* 37 * The structure that holds the -arch <arch> <file> information from the command 38 * line flags. 39 */ 40struct arch_ctf { 41 struct arch_flag arch_flag; 42 enum bool arch_found; 43 char *filename; 44 char *contents; 45 uint32_t size; 46}; 47struct arch_ctf *arch_ctfs; 48uint32_t narch_ctfs = 0; 49 50/* used by error routines as the name of the program */ 51char *progname = NULL; 52 53static void usage( 54 void); 55 56static void process( 57 struct arch *archs, 58 uint32_t narchs); 59 60static void ctf_insert( 61 struct arch *arch, 62 struct member *member, 63 struct object *object); 64 65static void add_ctf_section( 66 struct arch *arch, 67 char *arch_name, 68 uint32_t offset, 69 uint64_t addr, 70 uint32_t size); 71 72/* apple_version is created by the libstuff/Makefile */ 73extern char apple_version[]; 74char *version = apple_version; 75 76/* 77 * The ctf_insert(1) tool has the following usage: 78 * 79 * ctf_insert input -arch arch ctf_file ... -o output 80 * 81 * Where the input is a Mach-O file that is the ctf_file(s) are to be inserted 82 * into and output is the file to be created. 83 */ 84int 85main( 86int argc, 87char **argv, 88char **envp) 89{ 90 uint32_t i; 91 char *input, *output, *contents; 92 struct arch *archs; 93 uint32_t narchs; 94 struct stat stat_buf; 95 int fd; 96 97 progname = argv[0]; 98 input = NULL; 99 output = NULL; 100 archs = NULL; 101 narchs = 0; 102 for(i = 1; i < argc; i++){ 103 if(strcmp(argv[i], "-o") == 0){ 104 if(i + 1 == argc){ 105 error("missing argument to: %s option", argv[i]); 106 usage(); 107 } 108 if(output != NULL){ 109 error("more than one: %s option specified", argv[i]); 110 usage(); 111 } 112 output = argv[i+1]; 113 i++; 114 } 115 else if(strcmp(argv[i], "-arch") == 0){ 116 if(i + 2 == argc){ 117 error("missing argument(s) to: %s option", argv[i]); 118 usage(); 119 } 120 else{ 121 arch_ctfs = reallocate(arch_ctfs, 122 (narch_ctfs + 1) * sizeof(struct arch_ctf)); 123 if(get_arch_from_flag(argv[i+1], 124 &(arch_ctfs[narch_ctfs].arch_flag)) == 0){ 125 error("unknown architecture specification flag: " 126 "%s %s %s", argv[i], argv[i+1], argv[i+2]); 127 arch_usage(); 128 usage(); 129 } 130 if((fd = open(argv[i+2], O_RDONLY, 0)) == -1) 131 system_fatal("can't open file: %s", argv[i+2]); 132 if(fstat(fd, &stat_buf) == -1) 133 system_fatal("can't stat file: %s", argv[i+2]); 134 /* 135 * For some reason mapping files with zero size fails 136 * so it has to be handled specially. 137 */ 138 contents = NULL; 139 if(stat_buf.st_size != 0){ 140 contents = mmap(0, stat_buf.st_size, 141 PROT_READ|PROT_WRITE, 142 MAP_FILE|MAP_PRIVATE, fd, 0); 143 if((intptr_t)contents == -1) 144 system_error("can't map file : %s", argv[i+2]); 145 } 146 arch_ctfs[narch_ctfs].filename = argv[i+2]; 147 arch_ctfs[narch_ctfs].contents = contents; 148 arch_ctfs[narch_ctfs].size = stat_buf.st_size; 149 arch_ctfs[narch_ctfs].arch_found = FALSE; 150 narch_ctfs++; 151 i += 2; 152 } 153 } 154 else{ 155 if(input != NULL){ 156 error("more than one input file file: %s specified", 157 input); 158 usage(); 159 } 160 input = argv[i]; 161 } 162 } 163 if(input == NULL || output == NULL || narch_ctfs == 0) 164 usage(); 165 166 breakout(input, &archs, &narchs, FALSE); 167 if(errors) 168 exit(EXIT_FAILURE); 169 170 checkout(archs, narchs); 171 172 process(archs, narchs); 173 174 for(i = 0; i < narch_ctfs; i++){ 175 if(arch_ctfs[i].arch_found == FALSE) 176 fatal("input file: %s does not contain a matching architecture " 177 "for specified '-arch %s %s' option", input, 178 arch_ctfs[i].arch_flag.name, arch_ctfs[i].filename); 179 } 180 181 writeout(archs, narchs, output, 0777, TRUE, FALSE, FALSE, NULL); 182 183 if(errors) 184 return(EXIT_FAILURE); 185 else 186 return(EXIT_SUCCESS); 187} 188 189/* 190 * usage() prints the current usage message and exits indicating failure. 191 */ 192static 193void 194usage( 195void) 196{ 197 fprintf(stderr, "Usage: %s input [-arch <arch> <file>]... -o output\n", 198 progname); 199 exit(EXIT_FAILURE); 200} 201 202/* 203 * process() walks the archs and calls ctf_insert() to do the work. 204 */ 205static 206void 207process( 208struct arch *archs, 209uint32_t narchs) 210{ 211 uint32_t i; 212 213 for(i = 0; i < narchs; i++){ 214 if(archs[i].type == OFILE_Mach_O) 215 ctf_insert(archs + i, NULL, archs[i].object); 216 else 217 fatal_arch(archs + i, NULL, "file type not valid input for " 218 "this this program to process: "); 219 } 220} 221 222/* 223 * ctf_insert() does the work to add the ctf section in the specified broken 224 * out ofile for the architecure specifed with a -arch command line option. 225 */ 226static 227void 228ctf_insert( 229struct arch *arch, 230struct member *member, 231struct object *object) 232{ 233 uint32_t i, move_size; 234 cpu_type_t cputype; 235 cpu_subtype_t cpusubtype; 236 uint32_t flags, offset; 237 uint64_t addr; 238 239 if(object->mh != NULL){ 240 cputype = object->mh->cputype; 241 cpusubtype = object->mh->cpusubtype & ~CPU_SUBTYPE_MASK; 242 flags = object->mh->flags; 243 offset = object->seg_linkedit->fileoff; 244 addr = object->seg_linkedit->vmaddr; 245 } 246 else{ 247 cputype = object->mh64->cputype; 248 cpusubtype = object->mh64->cpusubtype & ~CPU_SUBTYPE_MASK; 249 flags = object->mh64->flags; 250 offset = object->seg_linkedit64->fileoff; 251 addr = object->seg_linkedit64->vmaddr; 252 } 253 254 /* 255 * Make sure this object is valid to process. Since the input should 256 * be a mach_kernel that is statically linked we should not see any 257 * dynamic symbol table info. Or a code signature at the point this 258 * program is called in the build process. 259 */ 260 if((flags & MH_DYLDLINK) == MH_DYLDLINK || 261 object->dyld_info != NULL || 262 object->split_info_cmd != NULL || 263 object->hints_cmd != NULL) 264 fatal_arch(arch, member, "file is input for the dynamic linker so " 265 "not a valid input for this program to process: "); 266 /* 267 * Allow a dynamic symbol table load command where it only has an 268 * indirect symbol table and no other tables. 269 */ 270 if(object->dyst != NULL && 271 (object->dyst->ntoc != 0 || 272 object->dyst->nmodtab != 0 || 273 object->dyst->nmodtab != 0 || 274 object->dyst->nextrefsyms != 0 || 275 object->dyst->nextrel != 0)) 276 fatal_arch(arch, member, "file is input for the dynamic linker so " 277 "not a valid input for this program to process: "); 278 if(object->mh_filetype != MH_EXECUTE) 279 fatal_arch(arch, member, "file type is not MH_EXECUTE so " 280 "not a valid input for this program to process: "); 281 if(object->seg_linkedit == NULL && object->seg_linkedit64 == NULL) 282 fatal_arch(arch, member, "file type does not have a __LINKEDIT " 283 "segment so not a valid input for this program to " 284 "process: "); 285 if(object->code_sig_cmd != NULL) 286 fatal_arch(arch, member, "file type has code signature " 287 "so not a valid input for this program to process: "); 288 289 /* 290 * Now see if one of the -arch flags matches this object. 291 */ 292 for(i = 0; i < narch_ctfs; i++){ 293 if(arch_ctfs[i].arch_flag.cputype == cputype && 294 arch_ctfs[i].arch_flag.cpusubtype == cpusubtype) 295 break; 296 } 297 /* 298 * If we didn't find a matching -arch flag it is an error. 299 */ 300 if(i >= narch_ctfs){ 301 fatal_arch(arch, member, "no matching -arch option for this slice " 302 "of file: "); 303 return; 304 } 305 arch_ctfs[i].arch_found = TRUE; 306 307 /* 308 * Add the section for the ctf data for this arch. It is placed in 309 * the file where the linkedit info was and that info will then be 310 * moved. 311 */ 312 add_ctf_section(arch, arch_ctfs[i].arch_flag.name, 313 offset, addr, arch_ctfs[i].size); 314 315 /* 316 * Now set up all the pointers and sizes of the symbol and string table. 317 */ 318 if(object->st != NULL && object->st->nsyms != 0){ 319 if(object->mh != NULL){ 320 object->output_symbols = (struct nlist *) 321 (object->object_addr + object->st->symoff); 322 if(object->object_byte_sex != get_host_byte_sex()) 323 swap_nlist(object->output_symbols, 324 object->st->nsyms, 325 get_host_byte_sex()); 326 object->output_symbols64 = NULL; 327 } 328 else{ 329 object->output_symbols64 = (struct nlist_64 *) 330 (object->object_addr + object->st->symoff); 331 if(object->object_byte_sex != get_host_byte_sex()) 332 swap_nlist_64(object->output_symbols64, 333 object->st->nsyms, 334 get_host_byte_sex()); 335 object->output_symbols = NULL; 336 } 337 object->output_nsymbols = object->st->nsyms; 338 object->output_strings = 339 object->object_addr + object->st->stroff; 340 object->output_strings_size = object->st->strsize; 341 if(object->mh != NULL){ 342 object->input_sym_info_size = 343 object->st->nsyms * sizeof(struct nlist) + 344 object->st->strsize; 345 } 346 else{ 347 object->input_sym_info_size = 348 object->st->nsyms * sizeof(struct nlist_64) + 349 object->st->strsize; 350 } 351 } 352 if(object->dyst != NULL){ 353 object->output_ilocalsym = object->dyst->ilocalsym; 354 object->output_nlocalsym = object->dyst->nlocalsym; 355 object->output_iextdefsym = object->dyst->iextdefsym; 356 object->output_nextdefsym = object->dyst->nextdefsym; 357 object->output_iundefsym = object->dyst->iundefsym; 358 object->output_nundefsym = object->dyst->nundefsym; 359 object->output_indirect_symtab = (uint32_t *) 360 (object->object_addr + object->dyst->indirectsymoff); 361 object->output_loc_relocs = (struct relocation_info *) 362 (object->object_addr + object->dyst->locreloff); 363 if(object->mh != NULL){ 364 object->input_sym_info_size += 365 object->dyst->nindirectsyms * 366 sizeof(uint32_t); 367 } 368 else{ 369 object->input_sym_info_size += 370 object->dyst->nindirectsyms * 371 sizeof(uint32_t) + 372 object->input_indirectsym_pad; 373 } 374 object->input_sym_info_size += 375 object->dyst->nlocrel * 376 sizeof(struct relocation_info); 377 } 378 if(object->func_starts_info_cmd != NULL){ 379 object->output_func_start_info_data = object->object_addr + 380 object->func_starts_info_cmd->dataoff; 381 object->output_func_start_info_data_size = 382 object->func_starts_info_cmd->datasize; 383 object->input_sym_info_size += 384 object->func_starts_info_cmd->datasize; 385 } 386 if(object->data_in_code_cmd != NULL){ 387 object->output_data_in_code_info_data = object->object_addr + 388 object->data_in_code_cmd->dataoff; 389 object->output_data_in_code_info_data_size = 390 object->data_in_code_cmd->datasize; 391 object->input_sym_info_size += 392 object->data_in_code_cmd->datasize; 393 } 394 if(object->code_sign_drs_cmd != NULL){ 395 object->output_code_sign_drs_info_data = object->object_addr + 396 object->code_sign_drs_cmd->dataoff; 397 object->output_code_sign_drs_info_data_size = 398 object->code_sign_drs_cmd->datasize; 399 object->input_sym_info_size += 400 object->code_sign_drs_cmd->datasize; 401 } 402 object->output_sym_info_size = object->input_sym_info_size; 403 404 /* 405 * Now move the link edit info by the size of the ctf for this arch 406 * rounded to the load command size for this arch. 407 */ 408 if(object->mh != NULL){ 409 move_size = rnd(arch_ctfs[i].size, sizeof(uint32_t)); 410 object->seg_linkedit->fileoff += move_size; 411 } 412 else{ 413 move_size = rnd(arch_ctfs[i].size, sizeof(uint64_t)); 414 object->seg_linkedit64->fileoff += move_size; 415 } 416 if(object->st != NULL && object->st->nsyms != 0){ 417 object->st->symoff += move_size; 418 object->st->stroff += move_size; 419 } 420 if(object->dyst != NULL){ 421 if(object->dyst->nindirectsyms != 0) 422 object->dyst->indirectsymoff += move_size; 423 if(object->dyst->nlocrel != 0) 424 object->dyst->locreloff += move_size; 425 } 426 if(object->func_starts_info_cmd != NULL) 427 object->func_starts_info_cmd->dataoff += move_size; 428 if(object->data_in_code_cmd != NULL) 429 object->data_in_code_cmd->dataoff += move_size; 430 if(object->code_sign_drs_cmd != NULL) 431 object->code_sign_drs_cmd->dataoff += move_size; 432 433 /* 434 * Record the new content for writeout() to put in to the output file. 435 */ 436 object->output_new_content = arch_ctfs[i].contents; 437 object->output_new_content_size = move_size; 438} 439 440/* 441 * add_ctf_section() sees if there is space to add an LC_SEGMENT load command 442 * and one section stucture in the padding after the headers for the specified 443 * arch and arch_name. If so it adds a segment load command and section struct 444 * filled in with the offset, size and addr fields. If it can't be added or 445 * one already exists a fatal error message is printed. 446 */ 447static 448void 449add_ctf_section( 450struct arch *arch, 451char *arch_name, 452uint32_t offset, 453uint64_t addr, 454uint32_t size) 455{ 456 uint32_t i, j, low_fileoff, mach_header_size, added_header_size; 457 uint32_t ncmds, sizeofcmds; 458 struct load_command *lc; 459 struct segment_command *sg; 460 struct segment_command_64 *sg64; 461 struct section *s; 462 struct section_64 *s64; 463 struct segment_command *sg_CTF; 464 struct section *s_ctf; 465 struct segment_command_64 *sg64_CTF; 466 struct section_64 *s64_ctf; 467 468 if(arch->object->mh != NULL){ 469 ncmds = arch->object->mh->ncmds; 470 sizeofcmds = arch->object->mh->sizeofcmds; 471 mach_header_size = sizeof(struct mach_header); 472 added_header_size = sizeof(struct segment_command) + 473 sizeof(struct section); 474 } 475 else{ 476 ncmds = arch->object->mh64->ncmds; 477 sizeofcmds = arch->object->mh64->sizeofcmds; 478 mach_header_size = sizeof(struct mach_header_64); 479 added_header_size = sizeof(struct segment_command_64) + 480 sizeof(struct section_64); 481 } 482 483 /* 484 * The size of the new load commands that includes the added segment 485 * load command and section structure is larger than the existing load 486 * commands, so see if they can be fitted in before the contents of the 487 * first section (or segment in the case of a LINKEDIT segment only 488 * file). 489 */ 490 low_fileoff = UINT_MAX; 491 lc = arch->object->load_commands; 492 for(i = 0; i < ncmds; i++){ 493 if(lc->cmd == LC_SEGMENT){ 494 sg = (struct segment_command *)lc; 495 if(strcmp(sg->segname, "__CTF") == 0) 496 fatal("can't insert __CTF segment for: %s (for " 497 "architecture %s) because it already contains " 498 "this segment", arch->file_name, arch_name); 499 s = (struct section *) 500 ((char *)sg + sizeof(struct segment_command)); 501 if(sg->nsects != 0){ 502 for(j = 0; j < sg->nsects; j++){ 503 if(s->size != 0 && 504 (s->flags & S_ZEROFILL) != S_ZEROFILL && 505 (s->flags & S_THREAD_LOCAL_ZEROFILL) != 506 S_THREAD_LOCAL_ZEROFILL && 507 s->offset < low_fileoff) 508 low_fileoff = s->offset; 509 s++; 510 } 511 } 512 else{ 513 if(sg->filesize != 0 && sg->fileoff < low_fileoff) 514 low_fileoff = sg->fileoff; 515 } 516 } 517 else if(lc->cmd == LC_SEGMENT_64){ 518 sg64 = (struct segment_command_64 *)lc; 519 if(strcmp(sg64->segname, "__CTF") == 0) 520 fatal("can't insert __CTF segment for: %s (for " 521 "architecture %s) because it already contains " 522 "this segment", arch->file_name, arch_name); 523 s64 = (struct section_64 *) 524 ((char *)sg64 + sizeof(struct segment_command_64)); 525 if(sg64->nsects != 0){ 526 for(j = 0; j < sg64->nsects; j++){ 527 if(s64->size != 0 && 528 (s64->flags & S_ZEROFILL) != S_ZEROFILL && 529 (s64->flags & S_THREAD_LOCAL_ZEROFILL) != 530 S_THREAD_LOCAL_ZEROFILL && 531 s64->offset < low_fileoff) 532 low_fileoff = s64->offset; 533 s64++; 534 } 535 } 536 else{ 537 if(sg64->filesize != 0 && sg64->fileoff < low_fileoff) 538 low_fileoff = sg64->fileoff; 539 } 540 } 541 lc = (struct load_command *)((char *)lc + lc->cmdsize); 542 } 543 if(sizeofcmds + mach_header_size + added_header_size > low_fileoff) 544{ 545printf("added_header_size = %d\n", added_header_size); 546printf("space available = %d\n", low_fileoff - (sizeofcmds + mach_header_size)); 547 fatal("can't insert (__CTF,__ctf) section for: %s (for architecture" 548 " %s) because larger updated load commands do not fit (the " 549 "program must be relinked using a larger -headerpad value)", 550 arch->file_name, arch_name); 551} 552 /* 553 * There is space for the new load command. So just use that space for 554 * the new segment and section and set the fields. 555 */ 556 if(arch->object->mh != NULL){ 557 sg_CTF = (struct segment_command *) 558 ((char *)arch->object->load_commands + sizeofcmds); 559 memset(sg_CTF, '\0', sizeof(struct segment_command)); 560 sg_CTF->cmd = LC_SEGMENT; 561 sg_CTF->cmdsize = sizeof(struct segment_command) + 562 sizeof(struct section); 563 strcpy(sg_CTF->segname, "__CTF"); 564 sg_CTF->vmaddr = addr; 565 sg_CTF->vmsize = 0; 566 sg_CTF->fileoff = offset; 567 sg_CTF->filesize = size; 568 sg_CTF->maxprot = VM_PROT_READ; 569 sg_CTF->initprot = VM_PROT_READ; 570 sg_CTF->nsects = 1; 571 sg_CTF->flags = 0; 572 s_ctf = (struct section *) 573 ((char *)sg_CTF + sizeof(struct segment_command)); 574 memset(s_ctf, '\0', sizeof(struct section)); 575 strcpy(s_ctf->sectname, "__ctf"); 576 strcpy(s_ctf->segname, "__CTF"); 577 s_ctf->addr = addr; 578 s_ctf->size = size; 579 s_ctf->offset = offset; 580 s_ctf->align = 0; 581 s_ctf->reloff = 0; 582 s_ctf->nreloc = 0; 583 s_ctf->flags = S_REGULAR; 584 s_ctf->reserved1 = 0; 585 s_ctf->reserved2 = 0; 586 arch->object->mh->sizeofcmds = sizeofcmds + 587 sizeof(struct segment_command) + 588 sizeof(struct section); 589 arch->object->mh->ncmds = ncmds + 1; 590 } 591 else{ 592 sg64_CTF = (struct segment_command_64 *) 593 ((char *)arch->object->load_commands + sizeofcmds); 594 memset(sg64_CTF, '\0', sizeof(struct segment_command_64)); 595 sg64_CTF->cmd = LC_SEGMENT_64; 596 sg64_CTF->cmdsize = sizeof(struct segment_command_64) + 597 sizeof(struct section_64); 598 strcpy(sg64_CTF->segname, "__CTF"); 599 sg64_CTF->vmaddr = addr; 600 sg64_CTF->vmsize = 0; 601 sg64_CTF->fileoff = offset; 602 sg64_CTF->filesize = size; 603 sg64_CTF->maxprot = VM_PROT_READ; 604 sg64_CTF->initprot = VM_PROT_READ; 605 sg64_CTF->nsects = 1; 606 sg64_CTF->flags = 0; 607 s64_ctf = (struct section_64 *) 608 ((char *)sg64_CTF + sizeof(struct segment_command_64)); 609 memset(s64_ctf, '\0', sizeof(struct section_64)); 610 strcpy(s64_ctf->sectname, "__ctf"); 611 strcpy(s64_ctf->segname, "__CTF"); 612 s64_ctf->addr = addr; 613 s64_ctf->size = size; 614 s64_ctf->offset = offset; 615 s64_ctf->align = 0; 616 s64_ctf->reloff = 0; 617 s64_ctf->nreloc = 0; 618 s64_ctf->flags = S_REGULAR; 619 s64_ctf->reserved1 = 0; 620 s64_ctf->reserved2 = 0; 621 arch->object->mh64->sizeofcmds = sizeofcmds + 622 sizeof(struct segment_command_64) + 623 sizeof(struct section_64); 624 arch->object->mh64->ncmds = ncmds + 1; 625 } 626} 627