1/* 2 * Copyright © 2009 Apple Inc. All rights reserved. 3 * 4 * @APPLE_LICENSE_HEADER_START@ 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are met: 8 * 9 * 1. Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * 3. Neither the name of Apple Inc. ("Apple") nor the names of its 15 * contributors may be used to endorse or promote products derived from this 16 * software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY APPLE AND ITS CONTRIBUTORS "AS IS" AND ANY 19 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 20 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 21 * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY 22 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 23 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 24 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND 25 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 26 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 27 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 28 * 29 * @APPLE_LICENSE_HEADER_END@ 30 */ 31#include <stdio.h> 32#include <stdlib.h> 33#include <string.h> 34#include <limits.h> 35#include <ar.h> 36#include <mach-o/ranlib.h> 37#include <libc.h> 38#include "stuff/bool.h" 39#include "stuff/ofile.h" 40#include "stuff/errors.h" 41#include "stuff/allocate.h" 42#include "stuff/symbol.h" 43#include "stuff/symbol.h" 44#include "stuff/llvm.h" 45#include "otool.h" 46#include "ofile_print.h" 47#include "m68k_disasm.h" 48#include "i860_disasm.h" 49#include "i386_disasm.h" 50#include "m88k_disasm.h" 51#include "ppc_disasm.h" 52#include "hppa_disasm.h" 53#include "sparc_disasm.h" 54#include "arm_disasm.h" 55#include "llvm-c/Disassembler.h" 56 57/* Name of this program for error messages (argv[0]) */ 58char *progname = NULL; 59 60/* 61 * The flags to indicate the actions to perform. 62 */ 63enum bool fflag = FALSE; /* print the fat headers */ 64enum bool aflag = FALSE; /* print the archive header */ 65enum bool hflag = FALSE; /* print the exec or mach header */ 66enum bool lflag = FALSE; /* print the load commands */ 67enum bool Lflag = FALSE; /* print the shared library names */ 68enum bool Dflag = FALSE; /* print the shared library id name */ 69enum bool tflag = FALSE; /* print the text */ 70enum bool dflag = FALSE; /* print the data */ 71enum bool oflag = FALSE; /* print the objctive-C info */ 72enum bool Oflag = FALSE; /* print the objctive-C selector strings only */ 73enum bool rflag = FALSE; /* print the relocation entries */ 74enum bool Tflag = FALSE; /* print the dylib table of contents */ 75enum bool Mflag = FALSE; /* print the dylib module table */ 76enum bool Rflag = FALSE; /* print the dylib reference table */ 77enum bool Iflag = FALSE; /* print the indirect symbol table entries */ 78enum bool Hflag = FALSE; /* print the two-level hints table */ 79enum bool Gflag = FALSE; /* print the data in code table */ 80enum bool gflag = FALSE; /* group the disassembly */ 81enum bool eflag = FALSE; /* print enhanced disassembly */ 82enum bool Sflag = FALSE; /* print the contents of the __.SYMDEF file */ 83enum bool vflag = FALSE; /* print verbosely (symbolically) when possible */ 84enum bool Vflag = FALSE; /* print dissassembled operands verbosely */ 85enum bool cflag = FALSE; /* print the argument and environ strings of a core */ 86enum bool iflag = FALSE; /* print the shared library initialization table */ 87enum bool Wflag = FALSE; /* print the mod time of an archive as a number */ 88enum bool Xflag = FALSE; /* don't print leading address in disassembly */ 89enum bool Zflag = FALSE; /* don't use simplified ppc mnemonics in disassembly */ 90enum bool Bflag = FALSE; /* force Thumb disassembly (ARM objects only) */ 91enum bool Qflag = FALSE; /* use otool's disassembler */ 92enum bool qflag = FALSE; /* use 'C' Public llvm-mc disassembler */ 93enum bool jflag = FALSE; /* print opcode bytes */ 94enum bool nflag = FALSE; /* use intel disassembly syntax */ 95char *pflag = NULL; /* procedure name to start disassembling from */ 96char *segname = NULL; /* name of the section to print the contents of */ 97char *sectname = NULL; 98enum bool llvm_mc = FALSE; /* disassemble as llvm-mc will assemble */ 99char *mcpu = ""; /* the arg of the -mcpu=arg flag */ 100 101/* this is set when any of the flags that process object files is set */ 102enum bool object_processing = FALSE; 103 104static void usage( 105 void); 106 107static void processor( 108 struct ofile *ofile, 109 char *arch_name, 110 void *cookie); 111 112static void get_symbol_table_info( 113 struct load_command *load_commands, 114 uint32_t ncmds, 115 uint32_t sizeofcmds, 116 cpu_type_t cputype, 117 enum byte_sex load_commands_byte_sex, 118 char *object_addr, 119 uint32_t object_size, 120 struct nlist **symbols, 121 struct nlist_64 **symbols64, 122 uint32_t *nsymbols, 123 char **strings, 124 uint32_t *strings_size); 125 126static void get_toc_info( 127 struct load_command *load_commands, 128 uint32_t ncmds, 129 uint32_t sizeofcmds, 130 enum byte_sex load_commands_byte_sex, 131 char *object_addr, 132 uint32_t object_size, 133 struct dylib_table_of_contents **tocs, 134 uint32_t *ntocs); 135 136static void get_module_table_info( 137 struct load_command *load_commands, 138 uint32_t ncmds, 139 uint32_t sizeofcmds, 140 cpu_type_t cputype, 141 enum byte_sex load_commands_byte_sex, 142 char *object_addr, 143 uint32_t object_size, 144 struct dylib_module **mods, 145 struct dylib_module_64 **mods64, 146 uint32_t *nmods); 147 148static void get_ref_info( 149 struct load_command *load_commands, 150 uint32_t ncmds, 151 uint32_t sizeofcmds, 152 enum byte_sex load_commands_byte_sex, 153 char *object_addr, 154 uint32_t object_size, 155 struct dylib_reference **refs, 156 uint32_t *nrefs); 157 158static void get_indirect_symbol_table_info( 159 struct load_command *load_commands, 160 uint32_t ncmds, 161 uint32_t sizeofcmds, 162 enum byte_sex load_commands_byte_sex, 163 char *object_addr, 164 uint32_t object_size, 165 uint32_t **indirect_symbols, 166 uint32_t *nindirect_symbols); 167 168static enum bool get_dyst( 169 struct load_command *load_commands, 170 uint32_t ncmds, 171 uint32_t sizeofcmds, 172 enum byte_sex load_commands_byte_sex, 173 struct dysymtab_command *dyst); 174 175static void get_hints_table_info( 176 struct load_command *load_commands, 177 uint32_t ncmds, 178 uint32_t sizeofcmds, 179 enum byte_sex load_commands_byte_sex, 180 char *object_addr, 181 uint32_t object_size, 182 struct twolevel_hint **hints, 183 uint32_t *nhints); 184 185static enum bool get_hints_cmd( 186 struct load_command *load_commands, 187 uint32_t ncmds, 188 uint32_t sizeofcmds, 189 enum byte_sex load_commands_byte_sex, 190 struct twolevel_hints_command *hints_cmd); 191 192static void get_data_in_code_info( 193 struct load_command *load_commands, 194 uint32_t ncmds, 195 uint32_t sizeofcmds, 196 enum byte_sex load_commands_byte_sex, 197 char *object_addr, 198 uint32_t object_size, 199 struct data_in_code_entry **dices, 200 uint32_t *ndices); 201 202static enum bool get_dices_cmd( 203 struct load_command *load_commands, 204 uint32_t ncmds, 205 uint32_t sizeofcmds, 206 enum byte_sex load_commands_byte_sex, 207 struct linkedit_data_command *dices_cmd); 208 209static int sym_compare( 210 struct symbol *sym1, 211 struct symbol *sym2); 212 213static int rel_compare( 214 struct relocation_info *rel1, 215 struct relocation_info *rel2); 216 217static void get_linked_reloc_info( 218 struct load_command *load_commands, 219 uint32_t ncmds, 220 uint32_t sizeofcmds, 221 enum byte_sex load_commands_byte_sex, 222 char *object_addr, 223 uint32_t object_size, 224 struct relocation_info **ext_relocs, 225 uint32_t *next_relocs, 226 struct relocation_info **loc_relocs, 227 uint32_t *nloc_relocs); 228 229static void print_text( 230 cpu_type_t cputype, 231 enum byte_sex object_byte_sex, 232 char *sect, 233 uint32_t size, 234 uint64_t addr, 235 uint32_t sect_flags, 236 struct symbol *sorted_symbols, 237 uint32_t nsorted_symbols, 238 struct nlist *symbols, 239 struct nlist_64 *symbols64, 240 uint32_t nsymbols, 241 char *strings, 242 uint32_t strings_size, 243 struct relocation_info *relocs, 244 uint32_t nrelocs, 245 uint32_t *indirect_symbols, 246 uint32_t nindirect_symbols, 247 struct load_command *load_commands, 248 uint32_t ncmds, 249 uint32_t sizeofcmds, 250 enum bool disassemble, 251 enum bool verbose, 252 cpu_subtype_t cpusubtype, 253 char *object_addr, 254 uint32_t object_size, 255 struct data_in_code_entry *dices, 256 uint32_t ndices, 257 uint64_t seg_addr, 258 uint32_t filetype); 259 260static void print_argstrings( 261 uint32_t magic, 262 struct load_command *load_commands, 263 uint32_t ncmds, 264 uint32_t sizeofcmds, 265 cpu_type_t cputype, 266 cpu_subtype_t cpusubtype, 267 enum byte_sex load_commands_byte_sex, 268 char *object_addr, 269 uint32_t object_size); 270 271/* apple_version is created by the libstuff/Makefile */ 272extern char apple_version[]; 273char *version = apple_version; 274 275int 276main( 277int argc, 278char **argv, 279char **envp) 280{ 281 int i; 282 uint32_t j, nfiles; 283 struct arch_flag *arch_flags; 284 uint32_t narch_flags; 285 enum bool all_archs, use_member_syntax; 286 char **files; 287 288 progname = argv[0]; 289 arch_flags = NULL; 290 narch_flags = 0; 291 all_archs = FALSE; 292 use_member_syntax = TRUE; 293 llvm_mc = FALSE; 294 295 if(argc <= 1) 296 usage(); 297 298 /* 299 * Parse the arguments. 300 */ 301 nfiles = 0; 302 files = allocate(sizeof(char *) * argc); 303 for(i = 1; i < argc; i++){ 304 if(argv[i][0] == '-' && argv[i][1] == '\0'){ 305 for(i += 1 ; i < argc; i++) 306 files[nfiles++] = argv[i]; 307 break; 308 } 309 if(argv[i][0] != '-'){ 310 files[nfiles++] = argv[i]; 311 continue; 312 } 313 if(strcmp(argv[i], "-arch") == 0){ 314 if(i + 1 == argc){ 315 error("missing argument(s) to %s option", argv[i]); 316 usage(); 317 } 318 if(strcmp("all", argv[i+1]) == 0){ 319 all_archs = TRUE; 320 } 321 else{ 322 arch_flags = reallocate(arch_flags, 323 (narch_flags + 1) * sizeof(struct arch_flag)); 324 if(get_arch_from_flag(argv[i+1], 325 arch_flags + narch_flags) == 0){ 326 error("unknown architecture specification flag: " 327 "%s %s", argv[i], argv[i+1]); 328 arch_usage(); 329 usage(); 330 } 331 narch_flags++; 332 } 333 i++; 334 continue; 335 } 336 if(strcmp(argv[i], "-llvm-mc") == 0){ 337 llvm_mc = TRUE; 338 continue; 339 } 340 if(strncmp(argv[i], "-mcpu=", sizeof("-mcpu=")-1) == 0){ 341 mcpu = argv[i] + sizeof("-mcpu=")-1; 342 if(*mcpu == '\0'){ 343 error("missing argument to -mcpu="); 344 usage(); 345 } 346 continue; 347 } 348 if(argv[i][1] == 'p'){ 349 if(argc <= i + 1){ 350 error("-p requires an argument (a text symbol name)"); 351 usage(); 352 } 353 if(pflag) 354 error("only one -p flag can be specified"); 355 pflag = argv[i + 1]; 356 i++; 357 continue; 358 } 359 if(argv[i][1] == 's'){ 360 if(argc <= i + 2){ 361 error("-s requires two arguments (a segment name and a " 362 "section name)"); 363 usage(); 364 } 365 if(sectname != NULL){ 366 error("only one -s flag can be specified"); 367 usage(); 368 } 369 segname = argv[i + 1]; 370 sectname = argv[i + 2]; 371 i += 2; 372 object_processing = TRUE; 373 continue; 374 } 375 for(j = 1; argv[i][j] != '\0'; j++){ 376 switch(argv[i][j]){ 377 case 'V': 378 Vflag = TRUE; 379 case 'v': 380 vflag = TRUE; 381 break; 382 case 'f': 383 fflag = TRUE; 384 break; 385 case 'a': 386 aflag = TRUE; 387 break; 388 case 'g': 389 gflag = TRUE; 390 break; 391 case 'e': 392 eflag = TRUE; 393 break; 394 case 'n': 395 nflag = TRUE; 396 break; 397 case 'h': 398 hflag = TRUE; 399 object_processing = TRUE; 400 break; 401 case 'l': 402 lflag = TRUE; 403 object_processing = TRUE; 404 break; 405 case 'L': 406 Lflag = TRUE; 407 object_processing = TRUE; 408 break; 409 case 'D': 410 Dflag = TRUE; 411 object_processing = TRUE; 412 break; 413 case 't': 414 tflag = TRUE; 415 object_processing = TRUE; 416 break; 417 case 'd': 418 dflag = TRUE; 419 object_processing = TRUE; 420 break; 421 case 'o': 422 oflag = TRUE; 423 object_processing = TRUE; 424 break; 425 case 'O': 426 Oflag = TRUE; 427 object_processing = TRUE; 428 break; 429 case 'r': 430 rflag = TRUE; 431 object_processing = TRUE; 432 break; 433 case 'T': 434 Tflag = TRUE; 435 object_processing = TRUE; 436 break; 437 case 'M': 438 Mflag = TRUE; 439 object_processing = TRUE; 440 break; 441 case 'R': 442 Rflag = TRUE; 443 object_processing = TRUE; 444 break; 445 case 'I': 446 Iflag = TRUE; 447 object_processing = TRUE; 448 break; 449 case 'H': 450 Hflag = TRUE; 451 object_processing = TRUE; 452 break; 453 case 'G': 454 Gflag = TRUE; 455 object_processing = TRUE; 456 break; 457 case 'S': 458 Sflag = TRUE; 459 break; 460 case 'c': 461 cflag = TRUE; 462 object_processing = TRUE; 463 break; 464 case 'i': 465 iflag = TRUE; 466 object_processing = TRUE; 467 break; 468 case 'W': 469 Wflag = TRUE; 470 break; 471 case 'X': 472 Xflag = TRUE; 473 break; 474 case 'Z': 475 Zflag = TRUE; 476 break; 477 case 'm': 478 use_member_syntax = FALSE; 479 break; 480 case 'B': 481 Bflag = TRUE; 482 break; 483 case 'Q': 484 Qflag = TRUE; 485 break; 486 case 'q': 487 qflag = TRUE; 488 break; 489 case 'j': 490 jflag = TRUE; 491 break; 492 default: 493 error("unknown char `%c' in flag %s\n", argv[i][j],argv[i]); 494 usage(); 495 } 496 } 497 } 498 499 /* 500 * Check for correctness of arguments. 501 */ 502 if(!fflag && !aflag && !hflag && !lflag && !Lflag && !tflag && !dflag && 503 !oflag && !Oflag && !rflag && !Tflag && !Mflag && !Rflag && !Iflag && 504 !Hflag && !Gflag && !Sflag && !cflag && !iflag && !Dflag &&!segname){ 505 error("one of -fahlLtdoOrTMRIHGScis must be specified"); 506 usage(); 507 } 508 if(qflag && Qflag){ 509 error("can't specify both -q and -Q"); 510 usage(); 511 } 512 /* 513 * The default, without the -Q flag, is to use the llvm dissembler 514 * instead of otool's internal disassemblers. 515 */ 516 if(!Qflag) 517 qflag = TRUE; 518 if(nfiles == 0){ 519 error("at least one file must be specified"); 520 usage(); 521 } 522 if(segname != NULL && sectname != NULL){ 523 /* treat "-s __TEXT __text" the same as -t */ 524 if(strcmp(segname, SEG_TEXT) == 0 && 525 strcmp(sectname, SECT_TEXT) == 0){ 526 tflag = TRUE; 527 segname = NULL; 528 sectname = NULL; 529 } 530 /* treat "-s __TEXT __fvmlib0" the same as -i */ 531 else if(strcmp(segname, SEG_TEXT) == 0 && 532 strcmp(sectname, SECT_FVMLIB_INIT0) == 0){ 533 iflag = TRUE; 534 segname = NULL; 535 sectname = NULL; 536 } 537 } 538 539 for(j = 0; j < nfiles; j++){ 540 ofile_process(files[j], arch_flags, narch_flags, all_archs, TRUE, 541 TRUE, use_member_syntax, processor, NULL); 542 } 543 544 if(errors) 545 return(EXIT_FAILURE); 546 else 547 return(EXIT_SUCCESS); 548} 549 550/* 551 * Print the current usage message. 552 */ 553static 554void 555usage( 556void) 557{ 558 fprintf(stderr, 559 "Usage: %s [-arch arch_type] [-fahlLDtdorSTMRIHGvVcXmqQ] " 560 "[-mcpu=arg] <object file> ...\n", progname); 561 562 fprintf(stderr, "\t-f print the fat headers\n"); 563 fprintf(stderr, "\t-a print the archive header\n"); 564 fprintf(stderr, "\t-h print the mach header\n"); 565 fprintf(stderr, "\t-l print the load commands\n"); 566 fprintf(stderr, "\t-L print shared libraries used\n"); 567 fprintf(stderr, "\t-D print shared library id name\n"); 568 fprintf(stderr, "\t-t print the text section (disassemble with -v)\n"); 569 fprintf(stderr, "\t-p <routine name> start dissassemble from routine " 570 "name\n"); 571 fprintf(stderr, "\t-s <segname> <sectname> print contents of " 572 "section\n"); 573 fprintf(stderr, "\t-d print the data section\n"); 574 fprintf(stderr, "\t-o print the Objective-C segment\n"); 575 fprintf(stderr, "\t-r print the relocation entries\n"); 576 fprintf(stderr, "\t-S print the table of contents of a library\n"); 577 fprintf(stderr, "\t-T print the table of contents of a dynamic " 578 "shared library\n"); 579 fprintf(stderr, "\t-M print the module table of a dynamic shared " 580 "library\n"); 581 fprintf(stderr, "\t-R print the reference table of a dynamic shared " 582 "library\n"); 583 fprintf(stderr, "\t-I print the indirect symbol table\n"); 584 fprintf(stderr, "\t-H print the two-level hints table\n"); 585 fprintf(stderr, "\t-G print the data in code table\n"); 586 fprintf(stderr, "\t-v print verbosely (symbolically) when possible\n"); 587 fprintf(stderr, "\t-V print disassembled operands symbolically\n"); 588 fprintf(stderr, "\t-c print argument strings of a core file\n"); 589 fprintf(stderr, "\t-X print no leading addresses or headers\n"); 590 fprintf(stderr, "\t-m don't use archive(member) syntax\n"); 591 fprintf(stderr, "\t-B force Thumb disassembly (ARM objects only)\n"); 592 fprintf(stderr, "\t-q use llvm's disassembler (the default)\n"); 593 fprintf(stderr, "\t-Q use otool(1)'s disassembler\n"); 594 fprintf(stderr, "\t-mcpu=arg use `arg' as the cpu for disassembly\n"); 595 exit(EXIT_FAILURE); 596} 597 598static 599void 600processor( 601struct ofile *ofile, 602char *arch_name, 603void *cookie) /* cookie is not used */ 604{ 605 char *addr; 606 uint32_t i, magic; 607 uint64_t size; 608 struct mach_header mh; 609 struct mach_header_64 mh64; 610 cpu_type_t mh_cputype; 611 cpu_subtype_t mh_cpusubtype; 612 uint32_t mh_magic, mh_filetype, mh_ncmds, mh_sizeofcmds, sizeof_mach_header; 613 struct load_command *load_commands; 614 uint32_t nsymbols, nsorted_symbols, strings_size, len; 615 struct nlist *symbols, *allocated_symbols; 616 struct nlist_64 *symbols64, *allocated_symbols64; 617 struct symbol *sorted_symbols; 618 char *strings, *p; 619 uint32_t n_strx; 620 uint8_t n_type; 621 uint16_t n_desc; 622 uint64_t n_value; 623 char *sect; 624 uint32_t sect_nrelocs, sect_flags, nrelocs, next_relocs, nloc_relocs; 625 uint64_t sect_addr, sect_size; 626 struct relocation_info *sect_relocs, *relocs, *ext_relocs, *loc_relocs; 627 uint32_t *indirect_symbols, *allocated_indirect_symbols; 628 uint32_t nindirect_symbols; 629 struct dylib_module *mods, *allocated_mods; 630 struct dylib_module_64 *mods64, *allocated_mods64; 631 struct dylib_table_of_contents *tocs, *allocated_tocs; 632 struct dylib_reference *refs, *allocated_refs; 633 uint32_t nmods, ntocs, nrefs; 634 struct twolevel_hint *hints, *allocated_hints; 635 struct data_in_code_entry *dices, *allocated_dices; 636 uint32_t nhints, ndices; 637 uint64_t seg_addr; 638 639 sorted_symbols = NULL; 640 nsorted_symbols = 0; 641 indirect_symbols = NULL; 642 nindirect_symbols = 0; 643 hints = NULL; 644 nhints = 0; 645 dices = NULL; 646 ndices = 0; 647 symbols = NULL; 648 symbols64 = NULL; 649 nsymbols = 0; 650 strings = NULL; 651 nmods = 0; 652 mods64 = NULL; 653 mods = NULL; 654 /* 655 * These may or may not be allocated. If allocated they will not be 656 * NULL and then free'ed before returning. 657 */ 658 load_commands = NULL; 659 allocated_symbols = NULL; 660 allocated_symbols64 = NULL; 661 sorted_symbols = NULL; 662 allocated_indirect_symbols = NULL; 663 allocated_tocs = NULL; 664 allocated_mods = NULL; 665 allocated_refs = NULL; 666 allocated_hints = NULL; 667 allocated_dices = NULL; 668 669 /* 670 * The fat headers are printed in ofile_map() in ofile.c #ifdef'ed 671 * OTOOL. 672 */ 673 674 /* 675 * Archive headers. 676 */ 677 if(aflag && ofile->member_ar_hdr != NULL){ 678 uint32_t member_offset; 679 680 member_offset = ofile->member_offset - sizeof(struct ar_hdr); 681 if(strncmp(ofile->member_ar_hdr->ar_name, AR_EFMT1, 682 sizeof(AR_EFMT1) - 1) == 0) 683 member_offset -= ofile->member_name_size; 684 685 print_ar_hdr(ofile->member_ar_hdr, ofile->member_name, 686 ofile->member_name_size, member_offset, vflag, Vflag); 687 } 688 689 /* 690 * Archive table of contents. 691 */ 692 if(ofile->member_ar_hdr != NULL && 693 strncmp(ofile->member_name, SYMDEF, sizeof(SYMDEF)-1) == 0){ 694 if(Sflag == FALSE) 695 return; 696 if(ofile->file_type == OFILE_FAT){ 697 addr = ofile->file_addr + ofile->fat_archs[ofile->narch].offset; 698 size = ofile->fat_archs[ofile->narch].size; 699 } 700 else{ 701 addr = ofile->file_addr; 702 size = ofile->file_size; 703 } 704 if(addr + size > ofile->file_addr + ofile->file_size) 705 size = (ofile->file_addr + ofile->file_size) - addr; 706 print_library_toc(ofile->member_ar_hdr, /* toc_ar_hdr */ 707 ofile->member_name, /* toc_name */ 708 ofile->member_name_size, /* toc_name_size */ 709 ofile->member_addr, /* toc_addr */ 710 ofile->member_size, /* toc_size */ 711 get_toc_byte_sex(addr, size), 712 ofile->file_name, /* library_name */ 713 addr, /* library_addr */ 714 size, /* library_size */ 715 arch_name, 716 vflag); 717 return; 718 } 719 720 if(object_processing == FALSE) 721 return; 722 723 /* 724 * Print header for the object name if in an archive or an architecture 725 * name is passed in. 726 */ 727 if(Xflag == FALSE){ 728 printf("%s", ofile->file_name); 729 if(ofile->member_ar_hdr != NULL){ 730 printf("(%.*s)", (int)ofile->member_name_size, 731 ofile->member_name); 732 } 733 if(arch_name != NULL) 734 printf(" (architecture %s):", arch_name); 735 else 736 printf(":"); 737 /* 738 * If the mach_header pointer is NULL the file is not an object 739 * file. Truncated object file (where the file size is less 740 * than sizeof(struct mach_header) also does not have it's 741 * mach_header set. So deal with both cases here and then 742 * return as the rest of this routine deals only with things 743 * in object files. 744 */ 745 if(ofile->mh == NULL && ofile->mh64 == NULL){ 746 if(ofile->file_type == OFILE_FAT){ 747 /* 748 * This routine is not called on fat files where the 749 * offset is past end of file. An error message is 750 * printed in ofile_specific_arch() in ofile.c. 751 */ 752 if(ofile->arch_type == OFILE_ARCHIVE){ 753 addr = ofile->member_addr; 754 size = ofile->member_size; 755 } 756 else{ 757 addr = ofile->file_addr + 758 ofile->fat_archs[ofile->narch].offset; 759 size = ofile->fat_archs[ofile->narch].size; 760 } 761 if(addr + size > ofile->file_addr + ofile->file_size) 762 size = (ofile->file_addr + ofile->file_size) - addr; 763 } 764 else if(ofile->file_type == OFILE_ARCHIVE){ 765 addr = ofile->member_addr; 766 size = ofile->member_size; 767 } 768 else{ /* ofile->file_type == OFILE_UNKNOWN */ 769 addr = ofile->file_addr; 770 size = ofile->file_size; 771 } 772 if(size > sizeof(int32_t)){ 773 memcpy(&magic, addr, sizeof(uint32_t)); 774 if(magic == MH_MAGIC || 775 magic == SWAP_INT(MH_MAGIC)){ 776 printf(" is a truncated object file\n"); 777 memset(&mh, '\0', sizeof(struct mach_header)); 778 if(size > sizeof(struct mach_header)) 779 size = sizeof(struct mach_header); 780 memcpy(&mh, addr, size); 781 if(magic == SWAP_INT(MH_MAGIC)) 782 swap_mach_header(&mh, get_host_byte_sex()); 783 if(hflag) 784 print_mach_header(mh.magic, mh.cputype, 785 mh.cpusubtype, mh.filetype, mh.ncmds, 786 mh.sizeofcmds, mh.flags, vflag); 787 return; 788 } 789 else if(magic == MH_MAGIC_64 || 790 magic == SWAP_INT(MH_MAGIC_64)){ 791 printf(" is a truncated object file\n"); 792 memset(&mh64, '\0', sizeof(struct mach_header_64)); 793 if(size > sizeof(struct mach_header_64)) 794 size = sizeof(struct mach_header_64); 795 memcpy(&mh64, addr, size); 796 if(magic == SWAP_INT(MH_MAGIC_64)) 797 swap_mach_header_64(&mh64, get_host_byte_sex()); 798 if(hflag) 799 print_mach_header(mh64.magic, mh64.cputype, 800 mh64.cpusubtype, mh64.filetype, mh64.ncmds, 801 mh64.sizeofcmds, mh64.flags, vflag); 802 return; 803 } 804 } 805#ifdef LTO_SUPPORT 806 if(ofile->lto != NULL){ 807 printf(" is an LLVM bit-code file\n"); 808 return; 809 } 810#endif /* LTO_SUPPORT */ 811 printf(" is not an object file\n"); 812 return; 813 } 814 } 815 if(ofile->mh != NULL){ 816 if((intptr_t)(ofile->mh) % sizeof(uint32_t)){ 817 if(Xflag == FALSE) 818 printf("(object file offset is not a multiple of sizeof(" 819 "uint32_t))"); 820 memcpy(&mh, ofile->mh, sizeof(struct mach_header)); 821 if(mh.magic == SWAP_INT(MH_MAGIC)) 822 swap_mach_header(&mh, get_host_byte_sex()); 823 ofile->mh = &mh; 824 } 825 else if(ofile->mh->magic == SWAP_INT(MH_MAGIC)){ 826 mh = *(ofile->mh); 827 swap_mach_header(&mh, get_host_byte_sex()); 828 ofile->mh = &mh; 829 } 830 } 831 else if(ofile->mh64 != NULL){ 832 if((intptr_t)(ofile->mh64) % sizeof(uint32_t)){ 833 if(Xflag == FALSE) 834 printf("(object file offset is not a multiple of sizeof(" 835 "uint32_t))"); 836 memcpy(&mh64, ofile->mh64, sizeof(struct mach_header)); 837 if(mh64.magic == SWAP_INT(MH_MAGIC_64)) 838 swap_mach_header_64(&mh64, get_host_byte_sex()); 839 ofile->mh64 = &mh64; 840 } 841 else if(ofile->mh64->magic == SWAP_INT(MH_MAGIC_64)){ 842 mh64 = *(ofile->mh64); 843 swap_mach_header_64(&mh64, get_host_byte_sex()); 844 ofile->mh64 = &mh64; 845 } 846 } 847 if(Xflag == FALSE) 848 printf("\n"); 849 850 /* 851 * If this is not an object file then just return. 852 */ 853 if(ofile->mh == NULL && ofile->mh64 == NULL) 854 return; 855 856 /* 857 * Calculate the true number of bytes of the of the object file that 858 * is in memory (in case this file is truncated). 859 */ 860 addr = ofile->object_addr; 861 size = ofile->object_size; 862 if(addr + size > ofile->file_addr + ofile->file_size) 863 size = (ofile->file_addr + ofile->file_size) - addr; 864 865 /* 866 * Assign some local variables to the values in the mach_header for this 867 * ofile to make passing arguments to the print routines easier. 868 */ 869 if(ofile->mh != NULL){ 870 mh_magic = ofile->mh->magic; 871 mh_cputype = ofile->mh->cputype; 872 mh_cpusubtype = ofile->mh->cpusubtype; 873 mh_filetype = ofile->mh->filetype; 874 mh_ncmds = ofile->mh->ncmds; 875 mh_sizeofcmds = ofile->mh->sizeofcmds; 876 sizeof_mach_header = sizeof(struct mach_header); 877 } 878 else{ 879 mh_magic = ofile->mh64->magic; 880 mh_cputype = ofile->mh64->cputype; 881 mh_cpusubtype = ofile->mh64->cpusubtype; 882 mh_filetype = ofile->mh64->filetype; 883 mh_ncmds = ofile->mh64->ncmds; 884 mh_sizeofcmds = ofile->mh64->sizeofcmds; 885 sizeof_mach_header = sizeof(struct mach_header_64); 886 } 887 888 /* 889 * Mach header. 890 */ 891 if(hflag){ 892 if(ofile->mh != NULL) 893 print_mach_header(ofile->mh->magic, ofile->mh->cputype, 894 ofile->mh->cpusubtype, ofile->mh->filetype, 895 ofile->mh->ncmds, ofile->mh->sizeofcmds, 896 ofile->mh->flags, vflag); 897 else 898 print_mach_header(ofile->mh64->magic, ofile->mh64->cputype, 899 ofile->mh64->cpusubtype,ofile->mh64->filetype, 900 ofile->mh64->ncmds, ofile->mh64->sizeofcmds, 901 ofile->mh64->flags, vflag); 902 } 903 904 /* 905 * Load commands. 906 */ 907 if(mh_sizeofcmds + sizeof_mach_header > size){ 908 load_commands = allocate(mh_sizeofcmds); 909 memset(load_commands, '\0', mh_sizeofcmds); 910 memcpy(load_commands, ofile->load_commands, 911 size - sizeof_mach_header); 912 ofile->load_commands = load_commands; 913 } 914 if(lflag) 915 print_loadcmds(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 916 mh_cputype, mh_filetype, ofile->object_byte_sex, 917 size, vflag, Vflag); 918 919 if(Lflag || Dflag) 920 print_libraries(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 921 ofile->object_byte_sex, (Dflag && !Lflag), vflag); 922 923 /* 924 * If the indicated operation needs the symbol table get it. 925 */ 926 sect_flags = 0; 927 if(segname != NULL && sectname != NULL){ 928 (void)get_sect_info(segname, sectname, ofile->load_commands, 929 mh_ncmds, mh_sizeofcmds, mh_filetype, 930 ofile->object_byte_sex, 931 addr, size, §, §_size, §_addr, 932 §_relocs, §_nrelocs, §_flags, &seg_addr); 933 /* 934 * The MH_DYLIB_STUB format has all section sizes set to zero 935 * except sections with indirect symbol table entries (so that the 936 * indirect symbol table table entries can be printed, which are 937 * based on the section size). So if we are being asked to print 938 * the section contents of one of these sections in a MH_DYLIB_STUB 939 * we assume it has been stripped and set the section size to zero. 940 */ 941 if(mh_filetype == MH_DYLIB_STUB && 942 ((sect_flags & SECTION_TYPE) == S_NON_LAZY_SYMBOL_POINTERS || 943 (sect_flags & SECTION_TYPE) == S_LAZY_SYMBOL_POINTERS || 944 (sect_flags & SECTION_TYPE) == S_LAZY_DYLIB_SYMBOL_POINTERS || 945 (sect_flags & SECTION_TYPE) == S_SYMBOL_STUBS)) 946 sect_size = 0; 947 } 948 if(Rflag || Mflag) 949 get_symbol_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 950 mh_cputype, ofile->object_byte_sex, addr, size, &symbols, 951 &symbols64, &nsymbols, &strings, &strings_size); 952 if(vflag && (rflag || Tflag || Mflag || Rflag || Iflag || Hflag || tflag 953 || iflag || oflag || 954 (sect_flags & SECTION_TYPE) == S_LITERAL_POINTERS || 955 (sect_flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS || 956 (sect_flags & SECTION_TYPE) == S_MOD_TERM_FUNC_POINTERS || 957 (sect_flags & S_ATTR_PURE_INSTRUCTIONS) == 958 S_ATTR_PURE_INSTRUCTIONS || 959 (sect_flags & S_ATTR_SOME_INSTRUCTIONS) == 960 S_ATTR_SOME_INSTRUCTIONS || 961 segname != NULL)){ 962 get_symbol_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 963 mh_cputype, ofile->object_byte_sex, addr, size, &symbols, 964 &symbols64, &nsymbols, &strings, &strings_size); 965 966 if(symbols != NULL){ 967 if((uintptr_t)symbols % sizeof(uint32_t) || 968 ofile->object_byte_sex != get_host_byte_sex()){ 969 allocated_symbols = 970 allocate(nsymbols * sizeof(struct nlist)); 971 memcpy(allocated_symbols, symbols, 972 nsymbols * sizeof(struct nlist)); 973 symbols = allocated_symbols; 974 } 975 if(ofile->object_byte_sex != get_host_byte_sex()) 976 swap_nlist(symbols, nsymbols, get_host_byte_sex()); 977 } 978 else{ 979 if((uintptr_t)symbols64 % sizeof(uint32_t) || 980 ofile->object_byte_sex != get_host_byte_sex()){ 981 allocated_symbols64 = 982 allocate(nsymbols * sizeof(struct nlist_64)); 983 memcpy(allocated_symbols64, symbols64, 984 nsymbols * sizeof(struct nlist_64)); 985 symbols64 = allocated_symbols64; 986 } 987 if(ofile->object_byte_sex != get_host_byte_sex()) 988 swap_nlist_64(symbols64, nsymbols, get_host_byte_sex()); 989 } 990 991 /* 992 * If the operation needs a sorted symbol table create it. 993 */ 994 if(tflag || iflag || oflag || 995 (((sect_flags & SECTION_TYPE) == S_MOD_INIT_FUNC_POINTERS || 996 (sect_flags & SECTION_TYPE) == S_MOD_TERM_FUNC_POINTERS) && 997 Vflag) || 998 (sect_flags & S_ATTR_PURE_INSTRUCTIONS) == 999 S_ATTR_PURE_INSTRUCTIONS || 1000 (sect_flags & S_ATTR_SOME_INSTRUCTIONS) == 1001 S_ATTR_SOME_INSTRUCTIONS){ 1002 sorted_symbols = allocate(nsymbols * sizeof(struct symbol)); 1003 nsorted_symbols = 0; 1004 for(i = 0; i < nsymbols; i++){ 1005 if(symbols != NULL){ 1006 n_strx = symbols[i].n_un.n_strx; 1007 n_type = symbols[i].n_type; 1008 n_desc = symbols[i].n_desc; 1009 n_value = symbols[i].n_value; 1010 } 1011 else{ 1012 n_strx = symbols64[i].n_un.n_strx; 1013 n_type = symbols64[i].n_type; 1014 n_desc = symbols64[i].n_desc; 1015 n_value = symbols64[i].n_value; 1016 } 1017 if(n_strx > 0 && n_strx < strings_size) 1018 p = strings + n_strx; 1019 else 1020 p = "symbol with bad string index"; 1021 if(n_type & ~(N_TYPE|N_EXT|N_PEXT)) 1022 continue; 1023 n_type = n_type & N_TYPE; 1024 if(n_type == N_ABS || n_type == N_SECT){ 1025 len = strlen(p); 1026 if(len > sizeof(".o") - 1 && 1027 strcmp(p + (len - (sizeof(".o") - 1)), ".o") == 0) 1028 continue; 1029 if(strcmp(p, "gcc_compiled.") == 0) 1030 continue; 1031 if(strcmp(p, "ltmp0") == 0) 1032 continue; 1033 if(n_type == N_ABS && n_value == 0 && *p == '.') 1034 continue; 1035 sorted_symbols[nsorted_symbols].n_value = n_value; 1036 sorted_symbols[nsorted_symbols].name = p; 1037 sorted_symbols[nsorted_symbols].is_thumb = 1038 n_desc & N_ARM_THUMB_DEF; 1039 nsorted_symbols++; 1040 } 1041 } 1042 qsort(sorted_symbols, nsorted_symbols, sizeof(struct symbol), 1043 (int (*)(const void *, const void *))sym_compare); 1044 } 1045 } 1046 1047 if(Mflag || Tflag || Rflag){ 1048 get_module_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1049 mh_cputype, ofile->object_byte_sex, addr, size, &mods, &mods64, 1050 &nmods); 1051 if(mods != NULL){ 1052 if((intptr_t)mods % sizeof(uint32_t) || 1053 ofile->object_byte_sex != get_host_byte_sex()){ 1054 allocated_mods = allocate(nmods * 1055 sizeof(struct dylib_module)); 1056 memcpy(allocated_mods, mods, 1057 nmods * sizeof(struct dylib_module)); 1058 mods = allocated_mods; 1059 } 1060 if(ofile->object_byte_sex != get_host_byte_sex()) 1061 swap_dylib_module(mods, nmods, get_host_byte_sex()); 1062 } 1063 if(mods64 != NULL){ 1064 if((intptr_t)mods64 % sizeof(uint64_t) || 1065 ofile->object_byte_sex != get_host_byte_sex()){ 1066 allocated_mods64 = allocate(nmods * 1067 sizeof(struct dylib_module_64)); 1068 memcpy(allocated_mods64, mods64, 1069 nmods * sizeof(struct dylib_module_64)); 1070 mods64 = allocated_mods64; 1071 } 1072 if(ofile->object_byte_sex != get_host_byte_sex()) 1073 swap_dylib_module_64(mods64, nmods, get_host_byte_sex()); 1074 } 1075 } 1076 1077 if(Tflag){ 1078 get_toc_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1079 ofile->object_byte_sex, addr, size, &tocs, &ntocs); 1080 if((intptr_t)tocs % sizeof(uint32_t) || 1081 ofile->object_byte_sex != get_host_byte_sex()){ 1082 allocated_tocs = allocate(ntocs * 1083 sizeof(struct dylib_table_of_contents)); 1084 memcpy(allocated_tocs, tocs, 1085 ntocs * sizeof(struct dylib_table_of_contents)); 1086 tocs = allocated_tocs; 1087 } 1088 if(ofile->object_byte_sex != get_host_byte_sex()) 1089 swap_dylib_table_of_contents(tocs, ntocs, get_host_byte_sex()); 1090 print_toc(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1091 ofile->object_byte_sex, addr, size, tocs, ntocs, mods, mods64, 1092 nmods, symbols, symbols64, nsymbols, strings, strings_size, 1093 vflag); 1094 } 1095 1096 if(Mflag){ 1097 if(mods != NULL) 1098 print_module_table(mods, nmods, strings, strings_size, vflag); 1099 else 1100 print_module_table_64(mods64, nmods, strings, strings_size, 1101 vflag); 1102 } 1103 1104 if(Rflag){ 1105 get_ref_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1106 ofile->object_byte_sex, addr, size, &refs, &nrefs); 1107 if((intptr_t)refs % sizeof(uint32_t) || 1108 ofile->object_byte_sex != get_host_byte_sex()){ 1109 allocated_refs = allocate(nrefs * 1110 sizeof(struct dylib_reference)); 1111 memcpy(allocated_refs, refs, 1112 nrefs * sizeof(struct dylib_reference)); 1113 refs = allocated_refs; 1114 } 1115 if(ofile->object_byte_sex != get_host_byte_sex()) 1116 swap_dylib_reference(refs, nrefs, get_host_byte_sex()); 1117 print_refs(refs, nrefs, mods, mods64, nmods, symbols, symbols64, 1118 nsymbols, strings, strings_size, vflag); 1119 } 1120 1121 if(Iflag || (tflag && vflag)){ 1122 get_indirect_symbol_table_info(ofile->load_commands, mh_ncmds, 1123 mh_sizeofcmds, ofile->object_byte_sex, addr, size, 1124 &indirect_symbols, &nindirect_symbols); 1125 if((intptr_t)indirect_symbols % sizeof(uint32_t) || 1126 ofile->object_byte_sex != get_host_byte_sex()){ 1127 allocated_indirect_symbols = allocate(nindirect_symbols * 1128 sizeof(uint32_t)); 1129 memcpy(allocated_indirect_symbols, indirect_symbols, 1130 nindirect_symbols * sizeof(uint32_t)); 1131 indirect_symbols = allocated_indirect_symbols; 1132 } 1133 if(ofile->object_byte_sex != get_host_byte_sex()) 1134 swap_indirect_symbols(indirect_symbols, nindirect_symbols, 1135 get_host_byte_sex()); 1136 } 1137 if(Hflag){ 1138 get_hints_table_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1139 ofile->object_byte_sex, addr, size, &hints, &nhints); 1140 if((intptr_t)hints % sizeof(uint32_t) || 1141 ofile->object_byte_sex != get_host_byte_sex()){ 1142 allocated_hints = allocate(nhints * 1143 sizeof(struct twolevel_hint)); 1144 memcpy(allocated_hints, hints, 1145 nhints * sizeof(struct twolevel_hint)); 1146 hints = allocated_hints; 1147 } 1148 if(ofile->object_byte_sex != get_host_byte_sex()) 1149 swap_twolevel_hint(hints, nhints, get_host_byte_sex()); 1150 print_hints(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1151 ofile->object_byte_sex, hints, nhints, symbols, symbols64, 1152 nsymbols, strings, strings_size, vflag); 1153 } 1154 if(Gflag || (tflag && vflag)){ 1155 get_data_in_code_info(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1156 ofile->object_byte_sex, addr, size, &dices, &ndices); 1157 if((intptr_t)dices % sizeof(uint32_t) || 1158 ofile->object_byte_sex != get_host_byte_sex()){ 1159 allocated_dices = allocate(ndices * 1160 sizeof(struct data_in_code_entry)); 1161 memcpy(allocated_dices, dices, 1162 ndices * sizeof(struct data_in_code_entry)); 1163 dices = allocated_dices; 1164 } 1165 if(ofile->object_byte_sex != get_host_byte_sex()) 1166 swap_data_in_code_entry(dices, ndices, get_host_byte_sex()); 1167 if(Gflag) 1168 print_dices(dices, ndices, vflag); 1169 } 1170 if(Iflag) 1171 print_indirect_symbols(ofile->load_commands, mh_ncmds,mh_sizeofcmds, 1172 mh_cputype, ofile->object_byte_sex, indirect_symbols, 1173 nindirect_symbols, symbols, symbols64, nsymbols, strings, 1174 strings_size, vflag); 1175 1176 if(rflag) 1177 print_reloc(ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1178 mh_cputype, ofile->object_byte_sex, addr, size, symbols, 1179 symbols64, nsymbols, strings, strings_size, vflag); 1180 1181 if(tflag || 1182 (sect_flags & S_ATTR_PURE_INSTRUCTIONS) == 1183 S_ATTR_PURE_INSTRUCTIONS || 1184 (sect_flags & S_ATTR_SOME_INSTRUCTIONS) == 1185 S_ATTR_SOME_INSTRUCTIONS){ 1186 if(tflag) 1187 (void)get_sect_info(SEG_TEXT, SECT_TEXT, ofile->load_commands, 1188 mh_ncmds, mh_sizeofcmds, mh_filetype, 1189 ofile->object_byte_sex, 1190 addr, size, §, §_size, §_addr, 1191 §_relocs, §_nrelocs, §_flags, &seg_addr); 1192 1193 /* create aligned relocations entries as needed */ 1194 relocs = NULL; 1195 nrelocs = 0; 1196 if(Vflag){ 1197 if(mh_filetype != MH_KEXT_BUNDLE){ 1198 if((intptr_t)sect_relocs % sizeof(int32_t) != 0 || 1199 ofile->object_byte_sex != get_host_byte_sex()){ 1200 nrelocs = sect_nrelocs; 1201 relocs = allocate(nrelocs * 1202 sizeof(struct relocation_info)); 1203 memcpy(relocs, sect_relocs, nrelocs * 1204 sizeof(struct relocation_info)); 1205 } 1206 else{ 1207 nrelocs = sect_nrelocs; 1208 relocs = sect_relocs; 1209 } 1210 } 1211 else{ 1212 get_linked_reloc_info(ofile->load_commands, mh_ncmds, 1213 mh_sizeofcmds, ofile->object_byte_sex, 1214 ofile->object_addr, ofile->object_size, &ext_relocs, 1215 &next_relocs, &loc_relocs, &nloc_relocs); 1216 if((intptr_t)ext_relocs % sizeof(int32_t) != 0 || 1217 ofile->object_byte_sex != get_host_byte_sex()){ 1218 nrelocs = next_relocs; 1219 relocs = allocate(next_relocs * 1220 sizeof(struct relocation_info)); 1221 memcpy(relocs, ext_relocs, next_relocs * 1222 sizeof(struct relocation_info)); 1223 } 1224 else{ 1225 nrelocs = next_relocs; 1226 relocs = ext_relocs; 1227 } 1228 } 1229 if(ofile->object_byte_sex != get_host_byte_sex()) 1230 swap_relocation_info(relocs, nrelocs, 1231 get_host_byte_sex()); 1232 } 1233 if(Xflag == FALSE){ 1234 if(tflag) 1235 printf("(%s,%s) section\n", SEG_TEXT, SECT_TEXT); 1236 else 1237 printf("Contents of (%.16s,%.16s) section\n", segname, 1238 sectname); 1239 } 1240 print_text(mh_cputype, ofile->object_byte_sex, sect, sect_size, 1241 sect_addr, sect_flags, sorted_symbols, 1242 nsorted_symbols, symbols, symbols64, nsymbols, strings, 1243 strings_size, relocs, nrelocs, indirect_symbols, 1244 nindirect_symbols, ofile->load_commands, mh_ncmds, 1245 mh_sizeofcmds, vflag, Vflag, mh_cpusubtype, 1246 ofile->object_addr, ofile->object_size, dices, ndices, 1247 seg_addr, mh_filetype); 1248 1249 if(mh_filetype != MH_KEXT_BUNDLE){ 1250 if(relocs != NULL && relocs != sect_relocs) 1251 free(relocs); 1252 } else { 1253 if(relocs != NULL && relocs != ext_relocs) 1254 free(relocs); 1255 } 1256 } 1257 1258 if(iflag){ 1259 if(get_sect_info(SEG_TEXT, SECT_FVMLIB_INIT0, ofile->load_commands, 1260 mh_ncmds, mh_sizeofcmds, mh_filetype, ofile->object_byte_sex, 1261 addr, size, §, §_size, §_addr, 1262 §_relocs, §_nrelocs, §_flags, &seg_addr) == TRUE){ 1263 1264 /* create aligned, sorted relocations entries */ 1265 nrelocs = sect_nrelocs; 1266 relocs = allocate(nrelocs * sizeof(struct relocation_info)); 1267 memcpy(relocs, sect_relocs, nrelocs * 1268 sizeof(struct relocation_info)); 1269 if(ofile->object_byte_sex != get_host_byte_sex()) 1270 swap_relocation_info(relocs, nrelocs, get_host_byte_sex()); 1271 qsort(relocs, nrelocs, sizeof(struct relocation_info), 1272 (int (*)(const void *, const void *))rel_compare); 1273 1274 if(Xflag == FALSE) 1275 printf("Shared library initialization (%s,%s) section\n", 1276 SEG_TEXT, SECT_FVMLIB_INIT0); 1277 print_shlib_init(ofile->object_byte_sex, sect, sect_size, 1278 sect_addr, sorted_symbols, nsorted_symbols, symbols, 1279 symbols64, nsymbols, strings, strings_size, relocs, 1280 nrelocs, vflag); 1281 free(relocs); 1282 } 1283 } 1284 1285 if(dflag){ 1286 if(get_sect_info(SEG_DATA, SECT_DATA, ofile->load_commands, 1287 mh_ncmds, mh_sizeofcmds, mh_filetype, ofile->object_byte_sex, 1288 addr, size, §, §_size, §_addr, 1289 §_relocs, §_nrelocs, §_flags, &seg_addr) == TRUE){ 1290 1291 if(Xflag == FALSE) 1292 printf("(%s,%s) section\n", SEG_DATA, SECT_DATA); 1293 print_sect(mh_cputype, ofile->object_byte_sex, sect, sect_size, 1294 sect_addr); 1295 } 1296 } 1297 1298 if(segname != NULL && sectname != NULL && 1299 (sect_flags & S_ATTR_PURE_INSTRUCTIONS) != 1300 S_ATTR_PURE_INSTRUCTIONS && 1301 (sect_flags & S_ATTR_SOME_INSTRUCTIONS) != 1302 S_ATTR_SOME_INSTRUCTIONS){ 1303 if(strcmp(segname, SEG_OBJC) == 0 && 1304 strcmp(sectname, "__protocol") == 0 && vflag == TRUE){ 1305 print_objc_protocol_section(ofile->load_commands, mh_ncmds, 1306 mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, 1307 ofile->object_size, vflag); 1308 } 1309 else if(strcmp(segname, SEG_OBJC) == 0 && 1310 (strcmp(sectname, "__string_object") == 0 || 1311 strcmp(sectname, "__cstring_object") == 0) && 1312 vflag == TRUE){ 1313 if(mh_cputype & CPU_ARCH_ABI64) 1314 print_objc_string_object_section_64(sectname, 1315 ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1316 ofile->object_byte_sex, ofile->object_addr, 1317 ofile->object_size, mh_cputype, symbols64, nsymbols, 1318 strings, strings_size, sorted_symbols, nsorted_symbols, 1319 vflag); 1320 else 1321 print_objc_string_object_section(sectname, 1322 ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1323 ofile->object_byte_sex, ofile->object_addr, 1324 ofile->object_size, vflag); 1325 } 1326 else if(strcmp(segname, SEG_OBJC) == 0 && 1327 strcmp(sectname, "__runtime_setup") == 0 && vflag == TRUE){ 1328 print_objc_runtime_setup_section(ofile->load_commands, mh_ncmds, 1329 mh_sizeofcmds, ofile->object_byte_sex, ofile->object_addr, 1330 ofile->object_size, vflag); 1331 } 1332#ifdef EFI_SUPPORT 1333 else if(strcmp(segname, "__RELOC") == 0 && 1334 strcmp(sectname, "__reloc") == 0 && vflag == TRUE){ 1335 print_coff_reloc_section(ofile->load_commands, mh_ncmds, 1336 mh_sizeofcmds, mh_filetype, ofile->object_byte_sex, 1337 ofile->object_addr, ofile->object_size, vflag); 1338 } 1339#endif 1340 else if(get_sect_info(segname, sectname, ofile->load_commands, 1341 mh_ncmds, mh_sizeofcmds, mh_filetype, ofile->object_byte_sex, 1342 addr, size, §, §_size, §_addr, 1343 §_relocs, §_nrelocs, §_flags, &seg_addr) == TRUE){ 1344 1345 if(Xflag == FALSE) 1346 printf("Contents of (%.16s,%.16s) section\n", segname, 1347 sectname); 1348 1349 if(vflag){ 1350 switch((sect_flags & SECTION_TYPE)){ 1351 case 0: 1352 print_sect(mh_cputype, ofile->object_byte_sex, 1353 sect, sect_size, sect_addr); 1354 break; 1355 case S_ZEROFILL: 1356 printf("zerofill section and has no contents in the " 1357 "file\n"); 1358 break; 1359 case S_CSTRING_LITERALS: 1360 print_cstring_section(mh_cputype, sect, sect_size, 1361 sect_addr, 1362 Xflag == TRUE ? FALSE : TRUE); 1363 break; 1364 case S_4BYTE_LITERALS: 1365 print_literal4_section(sect, sect_size, sect_addr, 1366 ofile->object_byte_sex, 1367 Xflag == TRUE ? FALSE : TRUE); 1368 break; 1369 case S_8BYTE_LITERALS: 1370 print_literal8_section(sect, sect_size, sect_addr, 1371 ofile->object_byte_sex, 1372 Xflag == TRUE ? FALSE : TRUE); 1373 break; 1374 case S_16BYTE_LITERALS: 1375 print_literal16_section(sect, sect_size, sect_addr, 1376 ofile->object_byte_sex, 1377 Xflag == TRUE ? FALSE : TRUE); 1378 break; 1379 case S_LITERAL_POINTERS: 1380 /* create aligned, sorted relocations entries */ 1381 nrelocs = sect_nrelocs; 1382 relocs = allocate(nrelocs * 1383 sizeof(struct relocation_info)); 1384 memcpy(relocs, sect_relocs, nrelocs * 1385 sizeof(struct relocation_info)); 1386 if(ofile->object_byte_sex != get_host_byte_sex()) 1387 swap_relocation_info(relocs, nrelocs, 1388 get_host_byte_sex()); 1389 qsort(relocs, nrelocs, sizeof(struct relocation_info), 1390 (int (*)(const void *, const void *))rel_compare); 1391 print_literal_pointer_section(mh_cputype, 1392 ofile->load_commands, mh_ncmds, mh_sizeofcmds, 1393 ofile->object_byte_sex, addr, size, sect, 1394 sect_size, sect_addr, symbols, symbols64, 1395 nsymbols, strings, strings_size, relocs, 1396 nrelocs, Xflag == TRUE ? FALSE : TRUE); 1397 free(relocs); 1398 1399 break; 1400 1401 case S_MOD_INIT_FUNC_POINTERS: 1402 case S_MOD_TERM_FUNC_POINTERS: 1403 print_init_term_pointer_section(mh_cputype, sect, 1404 sect_size, sect_addr, ofile->object_byte_sex, 1405 sorted_symbols, nsorted_symbols, Vflag); 1406 break; 1407 1408 default: 1409 printf("Unknown section type (0x%x)\n", 1410 (unsigned int)(sect_flags & SECTION_TYPE)); 1411 print_sect(mh_cputype, ofile->object_byte_sex, sect, 1412 sect_size, sect_addr); 1413 break; 1414 } 1415 } 1416 else{ 1417 if((sect_flags & SECTION_TYPE) == S_ZEROFILL) 1418 printf("zerofill section and has no contents in the " 1419 "file\n"); 1420 else 1421 print_sect(mh_cputype, ofile->object_byte_sex, sect, 1422 sect_size, sect_addr); 1423 } 1424 } 1425 } 1426 1427 if(cflag) 1428 print_argstrings(mh_magic, ofile->load_commands, mh_ncmds, 1429 mh_sizeofcmds, mh_cputype, mh_cpusubtype, 1430 ofile->object_byte_sex, ofile->object_addr, 1431 ofile->object_size); 1432 1433 if(oflag){ 1434 if(mh_cputype & CPU_ARCH_ABI64){ 1435 get_linked_reloc_info(ofile->load_commands, mh_ncmds, 1436 mh_sizeofcmds, ofile->object_byte_sex, 1437 ofile->object_addr, ofile->object_size, &ext_relocs, 1438 &next_relocs, &loc_relocs, &nloc_relocs); 1439 /* create aligned relocations entries as needed */ 1440 relocs = NULL; 1441 nrelocs = 0; 1442 if((intptr_t)ext_relocs % sizeof(int32_t) != 0 || 1443 ofile->object_byte_sex != get_host_byte_sex()){ 1444 relocs = allocate(next_relocs * 1445 sizeof(struct relocation_info)); 1446 memcpy(relocs, ext_relocs, next_relocs * 1447 sizeof(struct relocation_info)); 1448 ext_relocs = relocs; 1449 } 1450 if((intptr_t)loc_relocs % sizeof(int32_t) != 0 || 1451 ofile->object_byte_sex != get_host_byte_sex()){ 1452 relocs = allocate(nloc_relocs * 1453 sizeof(struct relocation_info)); 1454 memcpy(relocs, loc_relocs, nloc_relocs * 1455 sizeof(struct relocation_info)); 1456 loc_relocs = relocs; 1457 } 1458 if(ofile->object_byte_sex != get_host_byte_sex()){ 1459 swap_relocation_info(ext_relocs, next_relocs, 1460 get_host_byte_sex()); 1461 swap_relocation_info(loc_relocs, nloc_relocs, 1462 get_host_byte_sex()); 1463 } 1464 print_objc2_64bit(mh_cputype, ofile->load_commands, mh_ncmds, 1465 mh_sizeofcmds, ofile->object_byte_sex, 1466 ofile->object_addr, ofile->object_size, symbols64, 1467 nsymbols, strings, strings_size, sorted_symbols, 1468 nsorted_symbols, ext_relocs, next_relocs, 1469 loc_relocs, nloc_relocs, vflag, Vflag); 1470 } 1471 else if(mh_cputype == CPU_TYPE_ARM){ 1472 get_linked_reloc_info(ofile->load_commands, mh_ncmds, 1473 mh_sizeofcmds, ofile->object_byte_sex, 1474 ofile->object_addr, ofile->object_size, &ext_relocs, 1475 &next_relocs, &loc_relocs, &nloc_relocs); 1476 /* create aligned relocations entries as needed */ 1477 relocs = NULL; 1478 nrelocs = 0; 1479 if((intptr_t)ext_relocs % sizeof(int32_t) != 0 || 1480 ofile->object_byte_sex != get_host_byte_sex()){ 1481 relocs = allocate(next_relocs * 1482 sizeof(struct relocation_info)); 1483 memcpy(relocs, ext_relocs, next_relocs * 1484 sizeof(struct relocation_info)); 1485 ext_relocs = relocs; 1486 } 1487 if((intptr_t)loc_relocs % sizeof(int32_t) != 0 || 1488 ofile->object_byte_sex != get_host_byte_sex()){ 1489 relocs = allocate(nloc_relocs * 1490 sizeof(struct relocation_info)); 1491 memcpy(relocs, loc_relocs, nloc_relocs * 1492 sizeof(struct relocation_info)); 1493 loc_relocs = relocs; 1494 } 1495 if(ofile->object_byte_sex != get_host_byte_sex()){ 1496 swap_relocation_info(ext_relocs, next_relocs, 1497 get_host_byte_sex()); 1498 swap_relocation_info(loc_relocs, nloc_relocs, 1499 get_host_byte_sex()); 1500 } 1501 print_objc2_32bit(mh_cputype, ofile->load_commands, mh_ncmds, 1502 mh_sizeofcmds, ofile->object_byte_sex, 1503 ofile->object_addr, ofile->object_size, symbols, 1504 nsymbols, strings, strings_size, sorted_symbols, 1505 nsorted_symbols, ext_relocs, next_relocs, 1506 loc_relocs, nloc_relocs, vflag); 1507 } 1508 else{ 1509 /* 1510 * This is the 32-bit non-arm cputype case. Which is normally 1511 * the first Objective-C ABI. But it may be the case of a 1512 * binary for the iOS simulator which is the second Objective-C 1513 * ABI. In that case print_objc_segment() will determine that 1514 * and return FALSE. 1515 */ 1516 if(print_objc_segment(mh_cputype, ofile->load_commands, 1517 mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, 1518 ofile->object_addr, ofile->object_size, sorted_symbols, 1519 nsorted_symbols, vflag) == FALSE){ 1520 get_linked_reloc_info(ofile->load_commands, mh_ncmds, 1521 mh_sizeofcmds, ofile->object_byte_sex, 1522 ofile->object_addr, ofile->object_size, &ext_relocs, 1523 &next_relocs, &loc_relocs, &nloc_relocs); 1524 /* create aligned relocations entries as needed */ 1525 relocs = NULL; 1526 nrelocs = 0; 1527 if((intptr_t)ext_relocs % sizeof(int32_t) != 0 || 1528 ofile->object_byte_sex != get_host_byte_sex()){ 1529 relocs = allocate(next_relocs * 1530 sizeof(struct relocation_info)); 1531 memcpy(relocs, ext_relocs, next_relocs * 1532 sizeof(struct relocation_info)); 1533 ext_relocs = relocs; 1534 } 1535 if((intptr_t)loc_relocs % sizeof(int32_t) != 0 || 1536 ofile->object_byte_sex != get_host_byte_sex()){ 1537 relocs = allocate(nloc_relocs * 1538 sizeof(struct relocation_info)); 1539 memcpy(relocs, loc_relocs, nloc_relocs * 1540 sizeof(struct relocation_info)); 1541 loc_relocs = relocs; 1542 } 1543 if(ofile->object_byte_sex != get_host_byte_sex()){ 1544 swap_relocation_info(ext_relocs, next_relocs, 1545 get_host_byte_sex()); 1546 swap_relocation_info(loc_relocs, nloc_relocs, 1547 get_host_byte_sex()); 1548 } 1549 print_objc2_32bit(mh_cputype, ofile->load_commands, 1550 mh_ncmds, mh_sizeofcmds, ofile->object_byte_sex, 1551 ofile->object_addr, ofile->object_size, symbols, 1552 nsymbols, strings, strings_size, sorted_symbols, 1553 nsorted_symbols, ext_relocs, next_relocs, 1554 loc_relocs, nloc_relocs, vflag); 1555 } 1556 } 1557 } 1558 1559 if(load_commands != NULL) 1560 free(load_commands); 1561 if(allocated_symbols != NULL) 1562 free(allocated_symbols); 1563 if(sorted_symbols != NULL) 1564 free(sorted_symbols); 1565 if(allocated_indirect_symbols != NULL) 1566 free(allocated_indirect_symbols); 1567 if(allocated_hints != NULL) 1568 free(allocated_hints); 1569 if(allocated_dices != NULL) 1570 free(allocated_dices); 1571 if(allocated_tocs != NULL) 1572 free(allocated_tocs); 1573 if(allocated_mods != NULL) 1574 free(allocated_mods); 1575 if(allocated_refs != NULL) 1576 free(allocated_refs); 1577} 1578 1579/* 1580 * get_symbol_table_info() returns pointers to the symbol table and string 1581 * table as well as the number of symbols and size of the string table. 1582 * This routine handles the problems related to the file being truncated and 1583 * only returns valid pointers and sizes that can be used. This routine will 1584 * return pointers that are misaligned and it is up to the caller to deal with 1585 * alignment issues. It is also up to the caller to deal with byte sex of the 1586 * the symbol table. 1587 */ 1588static 1589void 1590get_symbol_table_info( 1591struct load_command *load_commands, /* input */ 1592uint32_t ncmds, 1593uint32_t sizeofcmds, 1594cpu_type_t cputype, 1595enum byte_sex load_commands_byte_sex, 1596char *object_addr, 1597uint32_t object_size, 1598struct nlist **symbols, /* output */ 1599struct nlist_64 **symbols64, 1600uint32_t *nsymbols, 1601char **strings, 1602uint32_t *strings_size) 1603{ 1604 enum byte_sex host_byte_sex; 1605 enum bool swapped; 1606 uint32_t i, left, size, st_cmd; 1607 struct load_command *lc, l; 1608 struct symtab_command st; 1609 uint64_t bigsize; 1610 1611 *symbols = NULL; 1612 *symbols64 = NULL; 1613 *nsymbols = 0; 1614 *strings = NULL; 1615 *strings_size = 0; 1616 1617 host_byte_sex = get_host_byte_sex(); 1618 swapped = host_byte_sex != load_commands_byte_sex; 1619 1620 st_cmd = UINT_MAX; 1621 lc = load_commands; 1622 memset((char *)&st, '\0', sizeof(struct symtab_command)); 1623 for(i = 0 ; i < ncmds; i++){ 1624 memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); 1625 if(swapped) 1626 swap_load_command(&l, host_byte_sex); 1627 if(l.cmdsize % sizeof(int32_t) != 0) 1628 printf("load command %u size not a multiple of " 1629 "sizeof(int32_t)\n", i); 1630 if((char *)lc + l.cmdsize > 1631 (char *)load_commands + sizeofcmds) 1632 printf("load command %u extends past end of load " 1633 "commands\n", i); 1634 left = sizeofcmds - ((char *)lc - (char *)load_commands); 1635 1636 switch(l.cmd){ 1637 case LC_SYMTAB: 1638 if(st_cmd != UINT_MAX){ 1639 printf("more than one LC_SYMTAB command (using command %u)" 1640 "\n", st_cmd); 1641 break; 1642 } 1643 size = left < sizeof(struct symtab_command) ? 1644 left : sizeof(struct symtab_command); 1645 memcpy((char *)&st, (char *)lc, size); 1646 if(swapped) 1647 swap_symtab_command(&st, host_byte_sex); 1648 st_cmd = i; 1649 } 1650 if(l.cmdsize == 0){ 1651 printf("load command %u size zero (can't advance to other " 1652 "load commands)\n", i); 1653 break; 1654 } 1655 lc = (struct load_command *)((char *)lc + l.cmdsize); 1656 if((char *)lc > (char *)load_commands + sizeofcmds) 1657 break; 1658 } 1659 if((char *)load_commands + sizeofcmds != (char *)lc) 1660 printf("Inconsistent sizeofcmds\n"); 1661 1662 if(st_cmd == UINT_MAX){ 1663 return; 1664 } 1665 1666 if(st.symoff >= object_size){ 1667 printf("symbol table offset is past end of file\n"); 1668 } 1669 else{ 1670 if(cputype & CPU_ARCH_ABI64){ 1671 *symbols64 = (struct nlist_64 *)(object_addr + st.symoff); 1672 bigsize = st.nsyms; 1673 bigsize *= sizeof(struct nlist_64); 1674 bigsize += st.symoff; 1675 if(bigsize > object_size){ 1676 printf("symbol table extends past end of file\n"); 1677 *nsymbols = (object_size - st.symoff) / 1678 sizeof(struct nlist_64); 1679 } 1680 else 1681 *nsymbols = st.nsyms; 1682 } 1683 else{ 1684 *symbols = (struct nlist *)(object_addr + st.symoff); 1685 bigsize = st.nsyms; 1686 bigsize *= sizeof(struct nlist); 1687 bigsize += st.symoff; 1688 if(bigsize > object_size){ 1689 printf("symbol table extends past end of file\n"); 1690 *nsymbols = (object_size - st.symoff) / 1691 sizeof(struct nlist); 1692 } 1693 else 1694 *nsymbols = st.nsyms; 1695 } 1696 } 1697 1698 if(st.stroff >= object_size){ 1699 printf("string table offset is past end of file\n"); 1700 } 1701 else{ 1702 *strings = object_addr + st.stroff; 1703 if(st.stroff + st.strsize > object_size){ 1704 printf("string table extends past end of file\n"); 1705 *strings_size = object_size - st.symoff; 1706 } 1707 else 1708 *strings_size = st.strsize; 1709 } 1710} 1711 1712/* 1713 * get_toc_info() returns a pointer and the size of the table of contents. 1714 * This routine handles the problems related to the file being truncated and 1715 * only returns valid pointers and sizes that can be used. This routine will 1716 * return pointers that are misaligned and it is up to the caller to deal with 1717 * alignment issues. It is also up to the caller to deal with byte sex of the 1718 * table. 1719 */ 1720static 1721void 1722get_toc_info( 1723struct load_command *load_commands, 1724uint32_t ncmds, 1725uint32_t sizeofcmds, 1726enum byte_sex load_commands_byte_sex, 1727char *object_addr, 1728uint32_t object_size, 1729struct dylib_table_of_contents **tocs, /* output */ 1730uint32_t *ntocs) 1731{ 1732 struct dysymtab_command dyst; 1733 uint64_t bigsize; 1734 1735 *tocs = NULL; 1736 *ntocs = 0; 1737 1738 if(get_dyst(load_commands, ncmds, sizeofcmds, load_commands_byte_sex, 1739 &dyst) == FALSE) 1740 return; 1741 1742 if(dyst.tocoff >= object_size){ 1743 printf("table of contents offset is past end of file\n"); 1744 } 1745 else{ 1746 *tocs = (struct dylib_table_of_contents *)(object_addr + 1747 dyst.tocoff); 1748 bigsize = dyst.ntoc; 1749 bigsize *= sizeof(struct dylib_table_of_contents); 1750 bigsize += dyst.tocoff; 1751 if(bigsize > object_size){ 1752 printf("table of contents extends past end of file\n"); 1753 *ntocs = (object_size - dyst.tocoff) / 1754 sizeof(struct dylib_table_of_contents); 1755 } 1756 else 1757 *ntocs = dyst.ntoc; 1758 } 1759} 1760 1761/* 1762 * get_module_table_info() returns a pointer and the size of the 1763 * module table. This routine handles the problems related to the file being 1764 * truncated and only returns valid pointers and sizes that can be used. This 1765 * routine will return pointers that are misaligned and it is up to the caller 1766 * to deal with alignment issues. It is also up to the caller to deal with 1767 * byte sex of the table. 1768 */ 1769static 1770void 1771get_module_table_info( 1772struct load_command *load_commands, 1773uint32_t ncmds, 1774uint32_t sizeofcmds, 1775cpu_type_t cputype, 1776enum byte_sex load_commands_byte_sex, 1777char *object_addr, 1778uint32_t object_size, 1779struct dylib_module **mods, /* output */ 1780struct dylib_module_64 **mods64, 1781uint32_t *nmods) 1782{ 1783 struct dysymtab_command dyst; 1784 uint64_t bigsize; 1785 1786 *mods = NULL; 1787 *mods64 = NULL; 1788 *nmods = 0; 1789 1790 if(get_dyst(load_commands, ncmds, sizeofcmds, load_commands_byte_sex, 1791 &dyst) == FALSE) 1792 return; 1793 1794 if(dyst.modtaboff >= object_size){ 1795 printf("module table offset is past end of file\n"); 1796 } 1797 else{ 1798 if(cputype & CPU_ARCH_ABI64){ 1799 *mods64 = (struct dylib_module_64 *)(object_addr + 1800 dyst.modtaboff); 1801 bigsize = dyst.nmodtab; 1802 bigsize *= sizeof(struct dylib_module_64); 1803 bigsize += dyst.modtaboff; 1804 if(bigsize > object_size){ 1805 printf("module table extends past end of file\n"); 1806 *nmods = (object_size - dyst.modtaboff) / 1807 sizeof(struct dylib_module_64); 1808 } 1809 else 1810 *nmods = dyst.nmodtab; 1811 } 1812 else{ 1813 *mods = (struct dylib_module *)(object_addr + dyst.modtaboff); 1814 if(dyst.modtaboff + 1815 dyst.nmodtab * sizeof(struct dylib_module) > object_size){ 1816 printf("module table extends past end of file\n"); 1817 *nmods = (object_size - dyst.modtaboff) / 1818 sizeof(struct dylib_module); 1819 } 1820 else 1821 *nmods = dyst.nmodtab; 1822 } 1823 } 1824} 1825 1826/* 1827 * get_ref_info() returns a pointer and the size of the reference table. 1828 * This routine handles the problems related to the file being truncated and 1829 * only returns valid pointers and sizes that can be used. This routine will 1830 * return pointers that are misaligned and it is up to the caller to deal with 1831 * alignment issues. It is also up to the caller to deal with byte sex of the 1832 * table. 1833 */ 1834static 1835void 1836get_ref_info( 1837struct load_command *load_commands, 1838uint32_t ncmds, 1839uint32_t sizeofcmds, 1840enum byte_sex load_commands_byte_sex, 1841char *object_addr, 1842uint32_t object_size, 1843struct dylib_reference **refs, /* output */ 1844uint32_t *nrefs) 1845{ 1846 struct dysymtab_command dyst; 1847 uint64_t bigsize; 1848 1849 *refs = NULL; 1850 *nrefs = 0; 1851 1852 if(get_dyst(load_commands, ncmds, sizeofcmds, load_commands_byte_sex, 1853 &dyst) == FALSE) 1854 return; 1855 1856 if(dyst.extrefsymoff >= object_size){ 1857 printf("reference table offset is past end of file\n"); 1858 } 1859 else{ 1860 *refs = (struct dylib_reference *)(object_addr + dyst.extrefsymoff); 1861 bigsize = dyst.nextrefsyms; 1862 bigsize *= sizeof(struct dylib_reference); 1863 bigsize += dyst.extrefsymoff; 1864 if(bigsize > object_size){ 1865 printf("reference table extends past end of file\n"); 1866 *nrefs = (object_size - dyst.extrefsymoff) / 1867 sizeof(struct dylib_reference); 1868 } 1869 else 1870 *nrefs = dyst.nextrefsyms; 1871 } 1872} 1873 1874/* 1875 * get_indirect_symbol_table_info() returns a pointer and the size of the 1876 * indirect symbol table. This routine handles the problems related to the 1877 * file being truncated and only returns valid pointers and sizes that can be 1878 * used. This routine will return pointers that are misaligned and it is up to 1879 * the caller to deal with alignment issues. It is also up to the caller to 1880 * deal with byte sex of the table. 1881 */ 1882static 1883void 1884get_indirect_symbol_table_info( 1885struct load_command *load_commands, 1886uint32_t ncmds, 1887uint32_t sizeofcmds, 1888enum byte_sex load_commands_byte_sex, 1889char *object_addr, 1890uint32_t object_size, 1891uint32_t **indirect_symbols, /* output */ 1892uint32_t *nindirect_symbols) 1893{ 1894 struct dysymtab_command dyst; 1895 uint64_t bigsize; 1896 1897 *indirect_symbols = NULL; 1898 *nindirect_symbols = 0; 1899 1900 if(get_dyst(load_commands, ncmds, sizeofcmds, load_commands_byte_sex, 1901 &dyst) == FALSE) 1902 return; 1903 1904 if(dyst.indirectsymoff >= object_size){ 1905 printf("indirect symbol table offset is past end of file\n"); 1906 } 1907 else{ 1908 *indirect_symbols = (uint32_t *)(object_addr + dyst.indirectsymoff); 1909 bigsize = dyst.nindirectsyms; 1910 bigsize *= sizeof(uint32_t); 1911 bigsize += dyst.indirectsymoff; 1912 if(bigsize > object_size){ 1913 printf("indirect symbol table extends past end of file\n"); 1914 *nindirect_symbols = (object_size - dyst.indirectsymoff) / 1915 sizeof(uint32_t); 1916 } 1917 else 1918 *nindirect_symbols = dyst.nindirectsyms; 1919 } 1920} 1921 1922/* 1923 * get_dyst() gets the dysymtab_command from the mach header and load commands 1924 * passed to it and copys it into dyst. It if doesn't find one it returns FALSE 1925 * else it returns TRUE. 1926 */ 1927static 1928enum bool 1929get_dyst( 1930struct load_command *load_commands, 1931uint32_t ncmds, 1932uint32_t sizeofcmds, 1933enum byte_sex load_commands_byte_sex, 1934struct dysymtab_command *dyst) 1935{ 1936 enum byte_sex host_byte_sex; 1937 enum bool swapped; 1938 uint32_t i, left, size, dyst_cmd; 1939 struct load_command *lc, l; 1940 1941 host_byte_sex = get_host_byte_sex(); 1942 swapped = host_byte_sex != load_commands_byte_sex; 1943 1944 dyst_cmd = UINT_MAX; 1945 lc = load_commands; 1946 for(i = 0 ; i < ncmds; i++){ 1947 memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); 1948 if(swapped) 1949 swap_load_command(&l, host_byte_sex); 1950 if(l.cmdsize % sizeof(int32_t) != 0) 1951 printf("load command %u size not a multiple of " 1952 "sizeof(int32_t)\n", i); 1953 if((char *)lc + l.cmdsize > 1954 (char *)load_commands + sizeofcmds) 1955 printf("load command %u extends past end of load " 1956 "commands\n", i); 1957 left = sizeofcmds - ((char *)lc - (char *)load_commands); 1958 1959 switch(l.cmd){ 1960 case LC_DYSYMTAB: 1961 if(dyst_cmd != UINT_MAX){ 1962 printf("more than one LC_DYSYMTAB command (using command " 1963 "%u)\n", dyst_cmd); 1964 break; 1965 } 1966 memset((char *)dyst, '\0', sizeof(struct dysymtab_command)); 1967 size = left < sizeof(struct dysymtab_command) ? 1968 left : sizeof(struct dysymtab_command); 1969 memcpy((char *)dyst, (char *)lc, size); 1970 if(swapped) 1971 swap_dysymtab_command(dyst, host_byte_sex); 1972 dyst_cmd = i; 1973 } 1974 if(l.cmdsize == 0){ 1975 printf("load command %u size zero (can't advance to other " 1976 "load commands)\n", i); 1977 break; 1978 } 1979 lc = (struct load_command *)((char *)lc + l.cmdsize); 1980 if((char *)lc > (char *)load_commands + sizeofcmds) 1981 break; 1982 } 1983 if((char *)load_commands + sizeofcmds != (char *)lc) 1984 printf("Inconsistent sizeofcmds\n"); 1985 1986 if(dyst_cmd == UINT_MAX){ 1987 return(FALSE); 1988 } 1989 return(TRUE); 1990} 1991 1992/* 1993 * get_hints_table_info() returns a pointer and the size of the two-level hints 1994 * table. This routine handles the problems related to the file being truncated 1995 * and only returns valid pointers and sizes that can be used. This routine 1996 * will return pointers that are misaligned and it is up to the caller to deal 1997 * with alignment issues. It is also up to the caller to deal with byte sex of 1998 * the table. 1999 */ 2000static 2001void 2002get_hints_table_info( 2003struct load_command *load_commands, 2004uint32_t ncmds, 2005uint32_t sizeofcmds, 2006enum byte_sex load_commands_byte_sex, 2007char *object_addr, 2008uint32_t object_size, 2009struct twolevel_hint **hints, /* output */ 2010uint32_t *nhints) 2011{ 2012 struct twolevel_hints_command hints_cmd; 2013 uint64_t bigsize; 2014 2015 *hints = NULL; 2016 *nhints = 0; 2017 2018 memset(&hints_cmd, '\0', sizeof(struct twolevel_hints_command)); 2019 if(get_hints_cmd(load_commands, ncmds, sizeofcmds, 2020 load_commands_byte_sex, &hints_cmd) == FALSE) 2021 return; 2022 2023 if(hints_cmd.offset >= object_size){ 2024 printf("two-level hints offset is past end of file\n"); 2025 } 2026 else{ 2027 *hints = (struct twolevel_hint *)(object_addr + hints_cmd.offset); 2028 bigsize = hints_cmd.nhints; 2029 bigsize *= sizeof(struct twolevel_hint); 2030 bigsize += hints_cmd.offset; 2031 if(bigsize > object_size){ 2032 printf("two-level hints table extends past end of file\n"); 2033 *nhints = (object_size - hints_cmd.offset) / 2034 sizeof(struct twolevel_hint); 2035 } 2036 else 2037 *nhints = hints_cmd.nhints; 2038 } 2039} 2040 2041/* 2042 * get_hints_cmd() gets the twolevel_hints_command from the mach header and 2043 * load commands passed to it and copys it into hints_cmd. It if doesn't find 2044 * one it returns FALSE else it returns TRUE. 2045 */ 2046static 2047enum bool 2048get_hints_cmd( 2049struct load_command *load_commands, 2050uint32_t ncmds, 2051uint32_t sizeofcmds, 2052enum byte_sex load_commands_byte_sex, 2053struct twolevel_hints_command *hints_cmd) 2054{ 2055 enum byte_sex host_byte_sex; 2056 enum bool swapped; 2057 uint32_t i, left, size, cmd; 2058 struct load_command *lc, l; 2059 2060 host_byte_sex = get_host_byte_sex(); 2061 swapped = host_byte_sex != load_commands_byte_sex; 2062 2063 cmd = UINT_MAX; 2064 lc = load_commands; 2065 for(i = 0 ; i < ncmds; i++){ 2066 memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); 2067 if(swapped) 2068 swap_load_command(&l, host_byte_sex); 2069 if(l.cmdsize % sizeof(int32_t) != 0) 2070 printf("load command %u size not a multiple of " 2071 "sizeof(int32_t)\n", i); 2072 if((char *)lc + l.cmdsize > 2073 (char *)load_commands + sizeofcmds) 2074 printf("load command %u extends past end of load " 2075 "commands\n", i); 2076 left = sizeofcmds - ((char *)lc - (char *)load_commands); 2077 2078 switch(l.cmd){ 2079 case LC_TWOLEVEL_HINTS: 2080 if(cmd != UINT_MAX){ 2081 printf("more than one LC_TWOLEVEL_HINTS command (using " 2082 "command %u)\n", cmd); 2083 break; 2084 } 2085 memset((char *)hints_cmd, '\0', 2086 sizeof(struct twolevel_hints_command)); 2087 size = left < sizeof(struct twolevel_hints_command) ? 2088 left : sizeof(struct twolevel_hints_command); 2089 memcpy((char *)hints_cmd, (char *)lc, size); 2090 if(swapped) 2091 swap_twolevel_hints_command(hints_cmd, host_byte_sex); 2092 cmd = i; 2093 } 2094 if(l.cmdsize == 0){ 2095 printf("load command %u size zero (can't advance to other " 2096 "load commands)\n", i); 2097 break; 2098 } 2099 lc = (struct load_command *)((char *)lc + l.cmdsize); 2100 if((char *)lc > (char *)load_commands + sizeofcmds) 2101 break; 2102 } 2103 if((char *)load_commands + sizeofcmds != (char *)lc) 2104 printf("Inconsistent sizeofcmds\n"); 2105 2106 if(cmd == UINT_MAX){ 2107 return(FALSE); 2108 } 2109 return(TRUE); 2110} 2111 2112/* 2113 * get_data_in_code_info() returns a pointer and the size of the data in code 2114 * table. This routine handles the problems related to the file being truncated 2115 * and only returns valid pointers and sizes that can be used. This routine 2116 * will return pointers that are misaligned and it is up to the caller to deal 2117 * with alignment issues. It is also up to the caller to deal with byte sex of 2118 * the table. 2119 */ 2120static 2121void 2122get_data_in_code_info( 2123struct load_command *load_commands, 2124uint32_t ncmds, 2125uint32_t sizeofcmds, 2126enum byte_sex load_commands_byte_sex, 2127char *object_addr, 2128uint32_t object_size, 2129struct data_in_code_entry **dices, /* output */ 2130uint32_t *ndices) 2131{ 2132 struct linkedit_data_command dices_cmd; 2133 uint64_t bigsize; 2134 2135 *dices = NULL; 2136 *ndices = 0; 2137 2138 memset(&dices_cmd, '\0', sizeof(struct linkedit_data_command)); 2139 if(get_dices_cmd(load_commands, ncmds, sizeofcmds, 2140 load_commands_byte_sex, &dices_cmd) == FALSE) 2141 return; 2142 2143 if(dices_cmd.dataoff >= object_size){ 2144 printf("data in code offset is past end of file\n"); 2145 } 2146 else{ 2147 *dices = (struct data_in_code_entry *) 2148 (object_addr + dices_cmd.dataoff); 2149 bigsize = dices_cmd.datasize; 2150 bigsize += dices_cmd.dataoff; 2151 if(bigsize > object_size){ 2152 printf("data in code table extends past end of file\n"); 2153 *ndices = (object_size - dices_cmd.dataoff) / 2154 sizeof(struct data_in_code_entry); 2155 } 2156 else 2157 *ndices = dices_cmd.datasize / 2158 sizeof(struct data_in_code_entry); 2159 } 2160} 2161 2162/* 2163 * get_dices_cmd() gets the linkedit_data_command for the data in code from the 2164 * mach header and load commands passed to it and copys it into dices_cmd. It 2165 * if doesn't find one it returns FALSE else it returns TRUE. 2166 */ 2167static 2168enum bool 2169get_dices_cmd( 2170struct load_command *load_commands, 2171uint32_t ncmds, 2172uint32_t sizeofcmds, 2173enum byte_sex load_commands_byte_sex, 2174struct linkedit_data_command *dices_cmd) 2175{ 2176 enum byte_sex host_byte_sex; 2177 enum bool swapped; 2178 uint32_t i, left, size, cmd; 2179 struct load_command *lc, l; 2180 2181 host_byte_sex = get_host_byte_sex(); 2182 swapped = host_byte_sex != load_commands_byte_sex; 2183 2184 cmd = UINT_MAX; 2185 lc = load_commands; 2186 for(i = 0 ; i < ncmds; i++){ 2187 memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); 2188 if(swapped) 2189 swap_load_command(&l, host_byte_sex); 2190 if(l.cmdsize % sizeof(int32_t) != 0) 2191 printf("load command %u size not a multiple of " 2192 "sizeof(int32_t)\n", i); 2193 if((char *)lc + l.cmdsize > 2194 (char *)load_commands + sizeofcmds) 2195 printf("load command %u extends past end of load " 2196 "commands\n", i); 2197 left = sizeofcmds - ((char *)lc - (char *)load_commands); 2198 2199 switch(l.cmd){ 2200 case LC_DATA_IN_CODE: 2201 if(cmd != UINT_MAX){ 2202 printf("more than one LC_DATA_IN_CODE command (using " 2203 "command %u)\n", cmd); 2204 break; 2205 } 2206 memset((char *)dices_cmd, '\0', 2207 sizeof(struct linkedit_data_command)); 2208 size = left < sizeof(struct linkedit_data_command) ? 2209 left : sizeof(struct linkedit_data_command); 2210 memcpy((char *)dices_cmd, (char *)lc, size); 2211 if(swapped) 2212 swap_linkedit_data_command(dices_cmd, host_byte_sex); 2213 cmd = i; 2214 } 2215 if(l.cmdsize == 0){ 2216 printf("load command %u size zero (can't advance to other " 2217 "load commands)\n", i); 2218 break; 2219 } 2220 lc = (struct load_command *)((char *)lc + l.cmdsize); 2221 if((char *)lc > (char *)load_commands + sizeofcmds) 2222 break; 2223 } 2224 if((char *)load_commands + sizeofcmds != (char *)lc) 2225 printf("Inconsistent sizeofcmds\n"); 2226 2227 if(cmd == UINT_MAX){ 2228 return(FALSE); 2229 } 2230 return(TRUE); 2231} 2232 2233/* 2234 * Function for qsort for comparing symbols. 2235 */ 2236static 2237int 2238sym_compare( 2239struct symbol *sym1, 2240struct symbol *sym2) 2241{ 2242 if(sym1->n_value == sym2->n_value) 2243 return(0); 2244 if(sym1->n_value < sym2->n_value) 2245 return(-1); 2246 else 2247 return(1); 2248} 2249 2250/* 2251 * Function for qsort for comparing relocation entries. 2252 */ 2253static 2254int 2255rel_compare( 2256struct relocation_info *rel1, 2257struct relocation_info *rel2) 2258{ 2259 struct scattered_relocation_info *srel; 2260 uint32_t r_address1, r_address2; 2261 2262 if((rel1->r_address & R_SCATTERED) != 0){ 2263 srel = (struct scattered_relocation_info *)rel1; 2264 r_address1 = srel->r_address; 2265 } 2266 else 2267 r_address1 = rel1->r_address; 2268 if((rel2->r_address & R_SCATTERED) != 0){ 2269 srel = (struct scattered_relocation_info *)rel2; 2270 r_address2 = srel->r_address; 2271 } 2272 else 2273 r_address2 = rel2->r_address; 2274 2275 if(r_address1 == r_address2) 2276 return(0); 2277 if(r_address1 < r_address2) 2278 return(-1); 2279 else 2280 return(1); 2281} 2282 2283enum bool 2284get_sect_info( 2285char *segname, /* input */ 2286char *sectname, 2287struct load_command *load_commands, 2288uint32_t ncmds, 2289uint32_t sizeofcmds, 2290uint32_t filetype, 2291enum byte_sex load_commands_byte_sex, 2292char *object_addr, 2293uint32_t object_size, 2294char **sect_pointer, /* output */ 2295uint64_t *sect_size, 2296uint64_t *sect_addr, 2297struct relocation_info **sect_relocs, 2298uint32_t *sect_nrelocs, 2299uint32_t *sect_flags, 2300uint64_t *seg_addr) 2301{ 2302 enum byte_sex host_byte_sex; 2303 enum bool found, swapped; 2304 uint32_t i, j, left, size; 2305 struct load_command *lc, l; 2306 uint32_t cmd; 2307 struct segment_command sg; 2308 struct segment_command_64 sg64; 2309 struct section s; 2310 struct section_64 s64; 2311 char *p; 2312 2313 *sect_pointer = NULL; 2314 *sect_size = 0; 2315 *sect_addr = 0; 2316 *sect_relocs = NULL; 2317 *sect_nrelocs = 0; 2318 *sect_flags = 0; 2319 2320 found = FALSE; 2321 cmd = 0; 2322 host_byte_sex = get_host_byte_sex(); 2323 swapped = host_byte_sex != load_commands_byte_sex; 2324 2325 lc = load_commands; 2326 for(i = 0 ; found == FALSE && i < ncmds; i++){ 2327 memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); 2328 if(swapped) 2329 swap_load_command(&l, host_byte_sex); 2330 if(l.cmdsize % sizeof(int32_t) != 0) 2331 printf("load command %u size not a multiple of " 2332 "sizeof(int32_t)\n", i); 2333 if((char *)lc + l.cmdsize > 2334 (char *)load_commands + sizeofcmds) 2335 printf("load command %u extends past end of load " 2336 "commands\n", i); 2337 left = sizeofcmds - ((char *)lc - (char *)load_commands); 2338 2339 switch(l.cmd){ 2340 case LC_SEGMENT: 2341 memset((char *)&sg, '\0', sizeof(struct segment_command)); 2342 size = left < sizeof(struct segment_command) ? 2343 left : sizeof(struct segment_command); 2344 memcpy((char *)&sg, (char *)lc, size); 2345 if(swapped) 2346 swap_segment_command(&sg, host_byte_sex); 2347 2348 if((filetype == MH_OBJECT && sg.segname[0] == '\0') || 2349 strncmp(sg.segname, segname, sizeof(sg.segname)) == 0){ 2350 *seg_addr = sg.vmaddr; 2351 p = (char *)lc + sizeof(struct segment_command); 2352 for(j = 0 ; found == FALSE && j < sg.nsects ; j++){ 2353 if(p + sizeof(struct section) > 2354 (char *)load_commands + sizeofcmds){ 2355 printf("section structure command extends past " 2356 "end of load commands\n"); 2357 } 2358 left = sizeofcmds - (p - (char *)load_commands); 2359 memset((char *)&s, '\0', sizeof(struct section)); 2360 size = left < sizeof(struct section) ? 2361 left : sizeof(struct section); 2362 memcpy((char *)&s, p, size); 2363 if(swapped) 2364 swap_section(&s, 1, host_byte_sex); 2365 2366 if(strncmp(s.sectname, sectname, 2367 sizeof(s.sectname)) == 0 && 2368 strncmp(s.segname, segname, 2369 sizeof(s.segname)) == 0){ 2370 found = TRUE; 2371 cmd = LC_SEGMENT; 2372 break; 2373 } 2374 2375 if(p + sizeof(struct section) > 2376 (char *)load_commands + sizeofcmds) 2377 return(FALSE); 2378 p += size; 2379 } 2380 } 2381 break; 2382 case LC_SEGMENT_64: 2383 memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); 2384 size = left < sizeof(struct segment_command_64) ? 2385 left : sizeof(struct segment_command_64); 2386 memcpy((char *)&sg64, (char *)lc, size); 2387 if(swapped) 2388 swap_segment_command_64(&sg64, host_byte_sex); 2389 2390 if((filetype == MH_OBJECT && sg64.segname[0] == '\0') || 2391 strncmp(sg64.segname, segname, sizeof(sg64.segname)) == 0){ 2392 *seg_addr = sg.vmaddr; 2393 p = (char *)lc + sizeof(struct segment_command_64); 2394 for(j = 0 ; found == FALSE && j < sg64.nsects ; j++){ 2395 if(p + sizeof(struct section_64) > 2396 (char *)load_commands + sizeofcmds){ 2397 printf("section structure command extends past " 2398 "end of load commands\n"); 2399 } 2400 left = sizeofcmds - (p - (char *)load_commands); 2401 memset((char *)&s64, '\0', sizeof(struct section_64)); 2402 size = left < sizeof(struct section_64) ? 2403 left : sizeof(struct section_64); 2404 memcpy((char *)&s64, p, size); 2405 if(swapped) 2406 swap_section_64(&s64, 1, host_byte_sex); 2407 2408 if(strncmp(s64.sectname, sectname, 2409 sizeof(s64.sectname)) == 0 && 2410 strncmp(s64.segname, segname, 2411 sizeof(s64.segname)) == 0){ 2412 found = TRUE; 2413 cmd = LC_SEGMENT_64; 2414 break; 2415 } 2416 2417 if(p + sizeof(struct section_64) > 2418 (char *)load_commands + sizeofcmds) 2419 return(FALSE); 2420 p += size; 2421 } 2422 } 2423 break; 2424 } 2425 if(l.cmdsize == 0){ 2426 printf("load command %u size zero (can't advance to other " 2427 "load commands)\n", i); 2428 break; 2429 } 2430 lc = (struct load_command *)((char *)lc + l.cmdsize); 2431 if((char *)lc > (char *)load_commands + sizeofcmds) 2432 break; 2433 } 2434 if(found == FALSE) 2435 return(FALSE); 2436 2437 if(cmd == LC_SEGMENT){ 2438 if((s.flags & SECTION_TYPE) == S_ZEROFILL){ 2439 *sect_pointer = NULL; 2440 *sect_size = s.size; 2441 } 2442 else{ 2443 if(s.offset > object_size){ 2444 printf("section offset for section (%.16s,%.16s) is past " 2445 "end of file\n", s.segname, s.sectname); 2446 } 2447 else{ 2448 *sect_pointer = object_addr + s.offset; 2449 if(s.offset + s.size > object_size){ 2450 printf("section (%.16s,%.16s) extends past end of " 2451 "file\n", s.segname, s.sectname); 2452 *sect_size = object_size - s.offset; 2453 } 2454 else 2455 *sect_size = s.size; 2456 } 2457 } 2458 if(s.reloff >= object_size){ 2459 printf("relocation entries offset for (%.16s,%.16s): is past " 2460 "end of file\n", s.segname, s.sectname); 2461 } 2462 else{ 2463 *sect_relocs = (struct relocation_info *)(object_addr + 2464 s.reloff); 2465 if(s.reloff + s.nreloc * sizeof(struct relocation_info) > 2466 object_size){ 2467 printf("relocation entries for section (%.16s,%.16s) " 2468 "extends past end of file\n", s.segname, s.sectname); 2469 *sect_nrelocs = (object_size - s.reloff) / 2470 sizeof(struct relocation_info); 2471 } 2472 else 2473 *sect_nrelocs = s.nreloc; 2474 } 2475 *sect_addr = s.addr; 2476 *sect_flags = s.flags; 2477 } 2478 else{ 2479 if((s64.flags & SECTION_TYPE) == S_ZEROFILL){ 2480 *sect_pointer = NULL; 2481 *sect_size = s64.size; 2482 } 2483 else{ 2484 if(s64.offset > object_size){ 2485 printf("section offset for section (%.16s,%.16s) is past " 2486 "end of file\n", s64.segname, s64.sectname); 2487 } 2488 else{ 2489 *sect_pointer = object_addr + s64.offset; 2490 if(s64.offset + s64.size > object_size){ 2491 printf("section (%.16s,%.16s) extends past end of " 2492 "file\n", s64.segname, s64.sectname); 2493 *sect_size = object_size - s64.offset; 2494 } 2495 else 2496 *sect_size = s64.size; 2497 } 2498 } 2499 if(s64.reloff >= object_size){ 2500 printf("relocation entries offset for (%.16s,%.16s): is past " 2501 "end of file\n", s64.segname, s64.sectname); 2502 } 2503 else{ 2504 *sect_relocs = (struct relocation_info *)(object_addr + 2505 s64.reloff); 2506 if(s64.reloff + s64.nreloc * sizeof(struct relocation_info) > 2507 object_size){ 2508 printf("relocation entries for section (%.16s,%.16s) " 2509 "extends past end of file\n", s64.segname, 2510 s64.sectname); 2511 *sect_nrelocs = (object_size - s64.reloff) / 2512 sizeof(struct relocation_info); 2513 } 2514 else 2515 *sect_nrelocs = s64.nreloc; 2516 } 2517 *sect_addr = s64.addr; 2518 *sect_flags = s64.flags; 2519 } 2520 return(TRUE); 2521} 2522 2523static 2524void 2525get_linked_reloc_info( 2526struct load_command *load_commands, /* input */ 2527uint32_t ncmds, 2528uint32_t sizeofcmds, 2529enum byte_sex load_commands_byte_sex, 2530char *object_addr, 2531uint32_t object_size, 2532struct relocation_info **ext_relocs, /* output */ 2533uint32_t *next_relocs, 2534struct relocation_info **loc_relocs, 2535uint32_t *nloc_relocs) 2536{ 2537 struct dysymtab_command dyst; 2538 uint64_t bigsize; 2539 2540 *ext_relocs = NULL; 2541 *next_relocs = 0; 2542 *loc_relocs = NULL; 2543 *nloc_relocs = 0; 2544 2545 if(get_dyst(load_commands, ncmds, sizeofcmds, load_commands_byte_sex, 2546 &dyst) == FALSE) 2547 return; 2548 2549 if(dyst.extreloff >= object_size){ 2550 printf("external relocation entries offset is past end of file\n"); 2551 } 2552 else{ 2553 *ext_relocs = (struct relocation_info *)(object_addr + 2554 dyst.extreloff); 2555 bigsize = dyst.nextrel; 2556 bigsize *= sizeof(struct relocation_info); 2557 bigsize += dyst.extreloff; 2558 if(bigsize > object_size){ 2559 printf("external relocation entries extend past end of file\n"); 2560 *next_relocs = (object_size - dyst.extreloff) / 2561 sizeof(struct relocation_info); 2562 } 2563 else 2564 *next_relocs = dyst.nextrel; 2565 } 2566 if(dyst.locreloff >= object_size){ 2567 printf("local relocation entries offset is past end of file\n"); 2568 } 2569 else{ 2570 *loc_relocs = (struct relocation_info *)(object_addr + 2571 dyst.locreloff); 2572 bigsize = dyst.nlocrel; 2573 bigsize *= sizeof(struct relocation_info); 2574 bigsize += dyst.locreloff; 2575 if(bigsize > object_size){ 2576 printf("local relocation entries extend past end of file\n"); 2577 *nloc_relocs = (object_size - dyst.locreloff) / 2578 sizeof(struct relocation_info); 2579 } 2580 else 2581 *nloc_relocs = dyst.nlocrel; 2582 } 2583} 2584 2585static 2586void 2587print_text( 2588cpu_type_t cputype, 2589enum byte_sex object_byte_sex, 2590char *sect, 2591uint32_t size, 2592uint64_t addr, 2593uint32_t sect_flags, 2594struct symbol *sorted_symbols, 2595uint32_t nsorted_symbols, 2596struct nlist *symbols, 2597struct nlist_64 *symbols64, 2598uint32_t nsymbols, 2599char *strings, 2600uint32_t strings_size, 2601struct relocation_info *relocs, 2602uint32_t nrelocs, 2603uint32_t *indirect_symbols, 2604uint32_t nindirect_symbols, 2605struct load_command *load_commands, 2606uint32_t ncmds, 2607uint32_t sizeofcmds, 2608enum bool disassemble, 2609enum bool verbose, 2610cpu_subtype_t cpusubtype, 2611char *object_addr, 2612uint32_t object_size, 2613struct data_in_code_entry *dices, 2614uint32_t ndices, 2615uint64_t seg_addr, 2616uint32_t filetype) 2617{ 2618 enum byte_sex host_byte_sex; 2619 enum bool swapped; 2620 uint32_t i, j, offset, long_word; 2621 uint64_t cur_addr; 2622 unsigned short short_word; 2623 unsigned char byte_word; 2624 LLVMDisasmContextRef arm_dc, thumb_dc, i386_dc, x86_64_dc; 2625 uint32_t n, ninsts; 2626 struct inst *insts; 2627 char *sect_start; 2628 2629 host_byte_sex = get_host_byte_sex(); 2630 swapped = host_byte_sex != object_byte_sex; 2631 arm_dc = NULL; 2632 thumb_dc = NULL; 2633 i386_dc = NULL; 2634 x86_64_dc = NULL; 2635 n = 0; 2636 ninsts = 0; 2637 insts = NULL; 2638 2639 if(disassemble == TRUE){ 2640 if(pflag){ 2641 for(i = 0; i < nsorted_symbols; i++){ 2642 if(strcmp(sorted_symbols[i].name, pflag) == 0) 2643 break; 2644 } 2645 if(i == nsorted_symbols){ 2646 printf("Can't find -p symbol: %s\n", pflag); 2647 return; 2648 } 2649 if(sorted_symbols[i].n_value < addr || 2650 sorted_symbols[i].n_value >= addr + size){ 2651 printf("-p symbol: %s not in text section\n", pflag); 2652 return; 2653 } 2654 offset = sorted_symbols[i].n_value - addr; 2655 sect += offset; 2656 cur_addr = sorted_symbols[i].n_value; 2657 sect_start = sect; 2658 } 2659 else{ 2660 offset = 0; 2661 cur_addr = addr; 2662 sect_start = sect; 2663 } 2664 if(cputype == CPU_TYPE_ARM && 2665 (cpusubtype == CPU_SUBTYPE_ARM_V7 || 2666 cpusubtype == CPU_SUBTYPE_ARM_V7F || 2667 cpusubtype == CPU_SUBTYPE_ARM_V7S || 2668 cpusubtype == CPU_SUBTYPE_ARM_V7K)){ 2669 if(sect_flags & S_SYMBOL_STUBS) 2670 in_thumb = FALSE; 2671 else 2672 in_thumb = TRUE; 2673 } 2674 else 2675 in_thumb = FALSE; 2676 if((qflag || gflag) && cputype == CPU_TYPE_ARM){ 2677 arm_dc = create_arm_llvm_disassembler(cpusubtype); 2678 if(arm_dc == NULL){ 2679 printf("can't create arm llvm disassembler\n"); 2680 return; 2681 } 2682 thumb_dc = create_thumb_llvm_disassembler(cpusubtype); 2683 if(thumb_dc == NULL){ 2684 printf("can't create thumb llvm disassembler\n"); 2685 return; 2686 } 2687 llvm_disasm_set_options(arm_dc, 2688 LLVMDisassembler_Option_PrintImmHex); 2689 llvm_disasm_set_options(thumb_dc, 2690 LLVMDisassembler_Option_PrintImmHex); 2691 if(eflag){ 2692 llvm_disasm_set_options(arm_dc, 2693 LLVMDisassembler_Option_UseMarkup); 2694 llvm_disasm_set_options(thumb_dc, 2695 LLVMDisassembler_Option_UseMarkup); 2696 } 2697 } 2698 if((qflag || gflag) && cputype == CPU_TYPE_I386){ 2699 i386_dc = create_i386_llvm_disassembler(); 2700 if(i386_dc == NULL){ 2701 printf("can't create i386 llvm disassembler\n"); 2702 return; 2703 } 2704 llvm_disasm_set_options(i386_dc, 2705 LLVMDisassembler_Option_PrintImmHex); 2706 if(nflag) 2707 llvm_disasm_set_options(i386_dc, 2708 LLVMDisassembler_Option_AsmPrinterVariant); 2709 if(eflag) 2710 llvm_disasm_set_options(i386_dc, 2711 LLVMDisassembler_Option_UseMarkup); 2712 } 2713 if((qflag || gflag) && cputype == CPU_TYPE_X86_64){ 2714 x86_64_dc = create_x86_64_llvm_disassembler(); 2715 if(x86_64_dc == NULL){ 2716 printf("can't create x86_64 llvm disassembler\n"); 2717 return; 2718 } 2719 llvm_disasm_set_options(x86_64_dc, 2720 LLVMDisassembler_Option_PrintImmHex); 2721 if(nflag) 2722 llvm_disasm_set_options(x86_64_dc, 2723 LLVMDisassembler_Option_AsmPrinterVariant); 2724 if(eflag) 2725 llvm_disasm_set_options(x86_64_dc, 2726 LLVMDisassembler_Option_UseMarkup); 2727 } 2728 if(gflag){ 2729 ninsts = 100; 2730 insts = allocate(sizeof(struct inst) * ninsts); 2731 } 2732 for(i = offset ; i < size ; ){ 2733 if(gflag && 2734 (cputype == CPU_TYPE_X86_64 || 2735 cputype == CPU_TYPE_I386 || 2736 cputype == CPU_TYPE_ARM)){ 2737 if(n > ninsts){ 2738 ninsts += ninsts; 2739 insts = reallocate(insts, sizeof(struct inst) * ninsts); 2740 } 2741 memset(&(insts[n]), '\0', sizeof(struct inst)); 2742 insts[n].address = cur_addr; 2743 insts[n].label = get_label(cur_addr, sorted_symbols, 2744 nsorted_symbols);; 2745 } 2746 else{ 2747 print_label(cur_addr, TRUE, sorted_symbols,nsorted_symbols); 2748 if(Xflag == FALSE){ 2749 if(cputype & CPU_ARCH_ABI64) 2750 printf("%016llx", cur_addr); 2751 else 2752 printf("%08x", (uint32_t)cur_addr); 2753 if(qflag == FALSE) 2754 printf("\t"); 2755 } 2756 } 2757 if(cputype == CPU_TYPE_POWERPC64) 2758 j = ppc_disassemble(sect, size - i, cur_addr, addr, 2759 object_byte_sex, relocs, nrelocs, symbols, 2760 symbols64, nsymbols, sorted_symbols, 2761 nsorted_symbols, strings, strings_size, 2762 indirect_symbols, nindirect_symbols, 2763 load_commands, ncmds, sizeofcmds, verbose); 2764 else if(cputype == CPU_TYPE_X86_64) 2765 j = i386_disassemble(sect, size - i, cur_addr, addr, 2766 object_byte_sex, relocs, nrelocs, NULL, 2767 symbols64, nsymbols, sorted_symbols, 2768 nsorted_symbols, strings, strings_size, 2769 indirect_symbols, nindirect_symbols, cputype, 2770 load_commands, ncmds, sizeofcmds, verbose, 2771 llvm_mc, i386_dc, x86_64_dc , object_addr, 2772 object_size, &(insts[n]), NULL, 0, 2773 filetype); 2774 else if(cputype == CPU_TYPE_MC680x0) 2775 j = m68k_disassemble(sect, size - i, cur_addr, addr, 2776 object_byte_sex, relocs, nrelocs, symbols, 2777 nsymbols, sorted_symbols, nsorted_symbols, 2778 strings, strings_size, indirect_symbols, 2779 nindirect_symbols, load_commands, ncmds, 2780 sizeofcmds, verbose); 2781 else if(cputype == CPU_TYPE_I860) 2782 j = i860_disassemble(sect, size - i, cur_addr, addr, 2783 object_byte_sex, relocs, nrelocs, symbols, 2784 nsymbols, sorted_symbols, nsorted_symbols, 2785 strings, strings_size, verbose); 2786 else if(cputype == CPU_TYPE_I386) 2787 j = i386_disassemble(sect, size - i, cur_addr, addr, 2788 object_byte_sex, relocs, nrelocs, symbols, NULL, 2789 nsymbols, sorted_symbols, nsorted_symbols, 2790 strings, strings_size, indirect_symbols, 2791 nindirect_symbols, cputype, load_commands, 2792 ncmds, sizeofcmds, verbose, llvm_mc, i386_dc, 2793 x86_64_dc, object_addr, object_size, 2794 &(insts[n]), NULL, 0, filetype); 2795 else if(cputype == CPU_TYPE_MC88000) 2796 j = m88k_disassemble(sect, size - i, cur_addr, addr, 2797 object_byte_sex, relocs, nrelocs, symbols, 2798 nsymbols, sorted_symbols, nsorted_symbols, 2799 strings, strings_size, verbose); 2800 else if(cputype == CPU_TYPE_POWERPC || 2801 cputype == CPU_TYPE_VEO) 2802 j = ppc_disassemble(sect, size - i, cur_addr, addr, 2803 object_byte_sex, relocs, nrelocs, symbols, 2804 symbols64, nsymbols, sorted_symbols, 2805 nsorted_symbols, strings, strings_size, 2806 indirect_symbols, nindirect_symbols, 2807 load_commands, ncmds, sizeofcmds, verbose); 2808 else if(cputype == CPU_TYPE_HPPA) 2809 j = hppa_disassemble(sect, size - i, cur_addr, addr, 2810 object_byte_sex, relocs, nrelocs, symbols, 2811 nsymbols, sorted_symbols, nsorted_symbols, 2812 strings, strings_size, verbose); 2813 else if(cputype == CPU_TYPE_SPARC) 2814 j = sparc_disassemble(sect, size - i, cur_addr, addr, 2815 object_byte_sex, relocs, nrelocs, symbols, 2816 nsymbols, sorted_symbols, nsorted_symbols, 2817 strings, strings_size, indirect_symbols, 2818 nindirect_symbols, load_commands, ncmds, 2819 sizeofcmds, verbose); 2820 else if(cputype == CPU_TYPE_ARM) 2821 j = arm_disassemble(sect, size - i, cur_addr, addr, 2822 object_byte_sex, relocs, nrelocs, symbols, 2823 nsymbols, sorted_symbols, nsorted_symbols, 2824 strings, strings_size, indirect_symbols, 2825 nindirect_symbols, load_commands, ncmds, 2826 sizeofcmds, cpusubtype, verbose, arm_dc, 2827 thumb_dc, object_addr, object_size, dices, 2828 ndices, seg_addr, &(insts[n]), NULL, 0); 2829 else{ 2830 printf("Can't disassemble unknown cputype %d\n", cputype); 2831 return; 2832 } 2833 sect += j; 2834 cur_addr += j; 2835 i += j; 2836 if(gflag) 2837 n++; 2838 } 2839 if(gflag && 2840 (cputype == CPU_TYPE_X86_64 || 2841 cputype == CPU_TYPE_I386 || 2842 cputype == CPU_TYPE_ARM)){ 2843 char dst[4096]; 2844 dst[4095] = '\0'; 2845 2846 /* Look for inits that need tmp labels. */ 2847 for(i = 0 ; i < n ; i++){ 2848 if(insts[i].has_raw_target_address){ 2849 for(j = 0; j < n; j++){ 2850 if(insts[i].raw_target_address == insts[j].address) 2851 insts[j].needs_tmp_label = TRUE; 2852 } 2853 } 2854 } 2855 2856 /* Create the needed tmp labels. */ 2857 j = 1; 2858 for(i = 0 ; i < n ; i++){ 2859 if(insts[i].needs_tmp_label == TRUE){ 2860 insts[i].tmp_label = allocate(20); 2861 sprintf(insts[i].tmp_label, "L%d", j++); 2862 } 2863 } 2864 2865 /* Now finally print the inits. */ 2866 for(i = 0 ; i < n ; i++){ 2867 if(insts[i].label != NULL) 2868 printf("%s:\n", insts[i].label); 2869 else if(insts[i].tmp_label != NULL) 2870 printf("%s:", insts[i].tmp_label); 2871 insts[i].print = TRUE; 2872 cur_addr = insts[i].address; 2873 offset = cur_addr - addr; 2874 sect = sect_start + offset; 2875 if(cputype == CPU_TYPE_X86_64 || cputype == CPU_TYPE_I386) 2876 j = i386_disassemble(sect, size - offset, cur_addr, addr, 2877 object_byte_sex, relocs, nrelocs, symbols, NULL, 2878 nsymbols, sorted_symbols, nsorted_symbols, 2879 strings, strings_size, indirect_symbols, 2880 nindirect_symbols, cputype, load_commands, 2881 ncmds, sizeofcmds, verbose, llvm_mc, i386_dc, 2882 x86_64_dc, object_addr, object_size, 2883 &(insts[i]), insts, n, filetype); 2884 else if(cputype == CPU_TYPE_ARM) 2885 j = arm_disassemble(sect, size - offset, cur_addr, addr, 2886 object_byte_sex, relocs, nrelocs, symbols, 2887 nsymbols, sorted_symbols, nsorted_symbols, 2888 strings, strings_size, indirect_symbols, 2889 nindirect_symbols, load_commands, ncmds, 2890 sizeofcmds, cpusubtype, verbose, arm_dc, 2891 thumb_dc, object_addr, object_size, dices, 2892 ndices, seg_addr, &(insts[i]), insts, n); 2893 } 2894 2895 /* Free up allocated space */ 2896 for(i = 0 ; i < n ; i++){ 2897 if(insts[i].tmp_label != NULL) 2898 free(insts[i].tmp_label); 2899 } 2900 free(insts); 2901 } 2902 if(i386_dc != NULL) 2903 delete_arm_llvm_disassembler(i386_dc); 2904 if(x86_64_dc != NULL) 2905 delete_arm_llvm_disassembler(x86_64_dc); 2906 if(arm_dc != NULL) 2907 delete_arm_llvm_disassembler(arm_dc); 2908 if(thumb_dc != NULL) 2909 delete_arm_llvm_disassembler(thumb_dc); 2910 } 2911 else{ 2912 if(cputype == CPU_TYPE_I386 || cputype == CPU_TYPE_X86_64){ 2913 for(i = 0 ; i < size ; i += j , addr += j){ 2914 if(cputype & CPU_ARCH_ABI64) 2915 printf("%016llx ", addr); 2916 else 2917 printf("%08x ", (uint32_t)addr); 2918 for(j = 0; 2919 j < 16 * sizeof(char) && i + j < size; 2920 j += sizeof(char)){ 2921 byte_word = *(sect + i + j); 2922 printf("%02x ", (unsigned int)byte_word); 2923 } 2924 printf("\n"); 2925 } 2926 } 2927 else if(cputype == CPU_TYPE_MC680x0){ 2928 for(i = 0 ; i < size ; i += j , addr += j){ 2929 printf("%08x ", (unsigned int)addr); 2930 for(j = 0; 2931 j < 8 * sizeof(short) && i + j < size; 2932 j += sizeof(short)){ 2933 memcpy(&short_word, sect + i + j, sizeof(short)); 2934 if(swapped) 2935 short_word = SWAP_SHORT(short_word); 2936 printf("%04x ", (unsigned int)short_word); 2937 } 2938 printf("\n"); 2939 } 2940 } 2941 else{ 2942 for(i = 0 ; i < size ; i += j , addr += j){ 2943 if(cputype & CPU_ARCH_ABI64) 2944 printf("%016llx ", addr); 2945 else 2946 printf("%08x ", (uint32_t)addr); 2947 for(j = 0; 2948 j < 4 * sizeof(int32_t) && i + j < size; 2949 j += sizeof(int32_t)){ 2950 memcpy(&long_word, sect + i + j, sizeof(int32_t)); 2951 if(swapped) 2952 long_word = SWAP_INT(long_word); 2953 printf("%08x ", (unsigned int)long_word); 2954 } 2955 printf("\n"); 2956 } 2957 } 2958 } 2959} 2960 2961static 2962void 2963print_argstrings( 2964uint32_t magic, 2965struct load_command *load_commands, 2966uint32_t ncmds, 2967uint32_t sizeofcmds, 2968cpu_type_t cputype, 2969cpu_subtype_t cpusubtype, 2970enum byte_sex load_commands_byte_sex, 2971char *object_addr, 2972uint32_t object_size) 2973{ 2974 enum byte_sex host_byte_sex; 2975 enum bool swapped; 2976 uint32_t i, len, left, size, arg; 2977 uint64_t usrstack; 2978 struct load_command *lc, l; 2979 struct segment_command sg; 2980 struct segment_command_64 sg64; 2981 char *stack, *stack_top, *p, *q, *argv; 2982 struct arch_flag arch_flags; 2983 2984 host_byte_sex = get_host_byte_sex(); 2985 swapped = host_byte_sex != load_commands_byte_sex; 2986 2987 arch_flags.cputype = cputype; 2988 if(magic == MH_MAGIC_64) 2989 arch_flags.cputype |= CPU_ARCH_ABI64; 2990 arch_flags.cpusubtype = cpusubtype; 2991 usrstack = get_stack_addr_from_flag(&arch_flags); 2992 if(usrstack == 0){ 2993 printf("Don't know the value of USRSTACK for unknown cputype " 2994 "(%d)\n", cputype); 2995 return; 2996 } 2997 printf("Argument strings on the stack at: "); 2998 if(cputype & CPU_ARCH_ABI64 || magic == MH_MAGIC_64) 2999 printf("%016llx\n", usrstack); 3000 else 3001 printf("%08x\n", (uint32_t)usrstack); 3002 lc = load_commands; 3003 for(i = 0 ; i < ncmds; i++){ 3004 memcpy((char *)&l, (char *)lc, sizeof(struct load_command)); 3005 if(swapped) 3006 swap_load_command(&l, host_byte_sex); 3007 if(cputype & CPU_ARCH_ABI64 || magic == MH_MAGIC_64){ 3008 if(l.cmdsize % 8 != 0) 3009 printf("load command %u size not a multiple of 8\n", i); 3010 } 3011 else{ 3012 if(l.cmdsize % 4 != 0) 3013 printf("load command %u size not a multiple of 4\n", i); 3014 } 3015 if((char *)lc + l.cmdsize > 3016 (char *)load_commands + sizeofcmds) 3017 printf("load command %u extends past end of load " 3018 "commands\n", i); 3019 left = sizeofcmds - ((char *)lc - (char *)load_commands); 3020 3021 switch(l.cmd){ 3022 case LC_SEGMENT: 3023 memset((char *)&sg, '\0', sizeof(struct segment_command)); 3024 size = left < sizeof(struct segment_command) ? 3025 left : sizeof(struct segment_command); 3026 memcpy((char *)&sg, (char *)lc, size); 3027 if(swapped) 3028 swap_segment_command(&sg, host_byte_sex); 3029 3030 if(cputype == CPU_TYPE_HPPA){ 3031 if(sg.vmaddr == usrstack && 3032 sg.fileoff + sg.filesize <= object_size){ 3033 stack = object_addr + sg.fileoff; 3034 stack_top = stack + sg.filesize; 3035 /* 3036 * There appears to be some pointer then argc at the 3037 * bottom of the stack first before argv[]. 3038 */ 3039 argv = stack + 2 * sizeof(uint32_t); 3040 memcpy(&arg, argv, sizeof(uint32_t)); 3041 if(swapped) 3042 arg = SWAP_INT(arg); 3043 while(argv < stack_top && 3044 arg != 0 && 3045 arg >= usrstack && arg < usrstack + sg.filesize){ 3046 p = stack + (arg - usrstack); 3047 printf("\t"); 3048 while(p < stack_top && *p != '\0'){ 3049 printf("%c", *p); 3050 p++; 3051 } 3052 printf("\n"); 3053 argv += sizeof(uint32_t); 3054 memcpy(&arg, argv, sizeof(uint32_t)); 3055 if(swapped) 3056 arg = SWAP_INT(arg); 3057 } 3058 /* after argv[] then there is envp[] */ 3059 argv += sizeof(uint32_t); 3060 memcpy(&arg, argv, sizeof(uint32_t)); 3061 if(swapped) 3062 arg = SWAP_INT(arg); 3063 while(argv < stack_top && 3064 arg != 0 && 3065 arg >= usrstack && arg < usrstack + sg.filesize){ 3066 p = stack + (arg - usrstack); 3067 printf("\t"); 3068 while(p < stack_top && *p != '\0'){ 3069 printf("%c", *p); 3070 p++; 3071 } 3072 printf("\n"); 3073 argv += sizeof(uint32_t); 3074 memcpy(&arg, argv, sizeof(uint32_t)); 3075 if(swapped) 3076 arg = SWAP_INT(arg); 3077 } 3078 } 3079 } 3080 else{ 3081 if(sg.vmaddr + sg.vmsize == usrstack && 3082 sg.fileoff + sg.filesize <= object_size){ 3083 stack = object_addr + sg.fileoff; 3084 stack_top = stack + sg.filesize; 3085 3086 /* the first thing on the stack is a long 0 */ 3087 stack_top -= 4; 3088 p = (char *)stack_top; 3089 3090 /* find the first non-null character before the long 0*/ 3091 while(p > stack && *p == '\0') 3092 p--; 3093 if(p != (char *)stack_top) 3094 p++; 3095 3096 q = p; 3097 /* Stop when we find another long 0 */ 3098 while(p > stack && (*p != '\0' || *(p-1) != '\0' || 3099 *(p-2) != '\0' || *(p-3) != '\0')){ 3100 p--; 3101 /* step back over the string to its start */ 3102 while(p > stack && *p != '\0') 3103 p--; 3104 } 3105 3106 p++; /* step forward to the start of the first string */ 3107 while(p < q){ 3108 printf("\t"); 3109 len = 0; 3110 while(p + len < q && p[len] != '\0'){ 3111 printf("%c", p[len]); 3112 len++; 3113 } 3114 printf("\n"); 3115 p += len + 1; 3116 } 3117 return; 3118 } 3119 } 3120 break; 3121 case LC_SEGMENT_64: 3122 memset((char *)&sg64, '\0', sizeof(struct segment_command_64)); 3123 size = left < sizeof(struct segment_command_64) ? 3124 left : sizeof(struct segment_command_64); 3125 memcpy((char *)&sg64, (char *)lc, size); 3126 if(swapped) 3127 swap_segment_command_64(&sg64, host_byte_sex); 3128 if(sg64.vmaddr + sg64.vmsize == usrstack && 3129 sg64.fileoff + sg64.filesize <= object_size){ 3130 stack = object_addr + sg64.fileoff; 3131 stack_top = stack + sg64.filesize; 3132 3133 /* the first thing on the stack is a uint64_t 0 */ 3134 stack_top -= 8; 3135 p = (char *)stack_top; 3136 3137 /* find the first non-null character before the uint64_t 0*/ 3138 while(p > stack && *p == '\0') 3139 p--; 3140 if(p != (char *)stack_top) 3141 p++; 3142 3143 q = p; 3144 /* Stop when we find another uint64_t 0 */ 3145 while(p > stack && (*p != '\0' || *(p-1) != '\0' || 3146 *(p-2) != '\0' || *(p-3) != '\0' || *(p-4) != '\0' || 3147 *(p-5) != '\0' || *(p-6) != '\0' || *(p-7) != '\0')){ 3148 p--; 3149 /* step back over the string to its start */ 3150 while(p > stack && *p != '\0') 3151 p--; 3152 } 3153 3154 p++; /* step forward to the start of the first string */ 3155 while(p < q){ 3156 printf("\t"); 3157 len = 0; 3158 while(p + len < q && p[len] != '\0'){ 3159 printf("%c", p[len]); 3160 len++; 3161 } 3162 printf("\n"); 3163 p += len + 1; 3164 } 3165 return; 3166 } 3167 break; 3168 } 3169 3170 if(l.cmdsize == 0){ 3171 printf("load command %u size zero (can't advance to other " 3172 "load commands)\n", i); 3173 break; 3174 } 3175 lc = (struct load_command *)((char *)lc + l.cmdsize); 3176 if((char *)lc > (char *)load_commands + sizeofcmds) 3177 break; 3178 } 3179} 3180 3181#ifndef __DYNAMIC__ 3182/* 3183 * To avoid linking in libm. These variables are defined as they are used in 3184 * pthread_init() to put in place a fast sqrt(). 3185 */ 3186size_t hw_sqrt_len = 0; 3187 3188double 3189sqrt(double x) 3190{ 3191 return(0.0); 3192} 3193double 3194hw_sqrt(double x) 3195{ 3196 return(0.0); 3197} 3198 3199/* 3200 * More stubs to avoid linking in libm. This works as along as we don't use 3201 * long doubles. 3202 */ 3203int32_t 3204__fpclassifyd(double x) 3205{ 3206 return(0); 3207} 3208int32_t 3209__fpclassify(long double x) 3210{ 3211 return(0); 3212} 3213#endif /* !defined(__DYNAMIC__) */ 3214