2 * Copyright © 2009 Apple Inc. All rights reserved.
4 * @APPLE_LICENSE_HEADER_START@
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
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.
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.
29 * @APPLE_LICENSE_HEADER_END@
36 #include <mach-o/ranlib.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 "stuff/guess_short_name.h"
46 #include "stuff/execute.h"
48 #include "dyld_bind_info.h"
49 #include "ofile_print.h"
50 #include "m68k_disasm.h"
51 #include "i860_disasm.h"
52 #include "i386_disasm.h"
53 #include "m88k_disasm.h"
54 #include "ppc_disasm.h"
55 #include "hppa_disasm.h"
56 #include "sparc_disasm.h"
57 #include "arm_disasm.h"
58 #include "arm64_disasm.h"
59 #include "llvm-c/Disassembler.h"
61 /* Name of this program for error messages (argv[0]) */
62 char *progname
= NULL
;
65 * The flags to indicate the actions to perform.
67 enum bool fflag
= FALSE
; /* print the fat headers */
68 enum bool aflag
= FALSE
; /* print the archive header */
69 enum bool hflag
= FALSE
; /* print the exec or mach header */
70 enum bool lflag
= FALSE
; /* print the load commands */
71 enum bool Lflag
= FALSE
; /* print the shared library names */
72 enum bool Dflag
= FALSE
; /* print the shared library id name */
73 enum bool tflag
= FALSE
; /* print the text */
74 enum bool Uflag
= FALSE
; /* print the text symbol by symbol,
75 for llvm-objdump testing must be used with -t */
76 enum bool no_show_raw_insn
= FALSE
; /* no raw inst, for llvm-objdump testing
79 enum bool show_objdump_command
= FALSE
; /* print the objdump command */
80 #endif /* LLVM_OTOOL */
81 enum bool dflag
= FALSE
; /* print the data */
82 enum bool oflag
= FALSE
; /* print the objctive-C info */
83 enum bool Oflag
= FALSE
; /* print the objctive-C selector strings only */
84 enum bool rflag
= FALSE
; /* print the relocation entries */
85 enum bool Tflag
= FALSE
; /* print the dylib table of contents */
86 enum bool Mflag
= FALSE
; /* print the dylib module table */
87 enum bool Rflag
= FALSE
; /* print the dylib reference table */
88 enum bool Iflag
= FALSE
; /* print the indirect symbol table entries */
89 enum bool Hflag
= FALSE
; /* print the two-level hints table */
90 enum bool Cflag
= FALSE
; /* print the linker optimization hints */
91 enum bool Gflag
= FALSE
; /* print the data in code table */
92 enum bool gflag
= FALSE
; /* group the disassembly */
93 enum bool eflag
= FALSE
; /* print enhanced disassembly */
94 enum bool Sflag
= FALSE
; /* print the contents of the __.SYMDEF file */
95 enum bool vflag
= FALSE
; /* print verbosely (symbolically) when possible */
96 enum bool Vflag
= FALSE
; /* print dissassembled operands verbosely */
97 enum bool cflag
= FALSE
; /* print the argument and environ strings of a core */
98 enum bool iflag
= FALSE
; /* print the shared library initialization table */
99 enum bool Wflag
= FALSE
; /* print the mod time of an archive as a number */
100 enum bool Xflag
= FALSE
; /* don't print leading address in disassembly */
101 enum bool Zflag
= FALSE
; /* don't use simplified ppc mnemonics in disassembly */
102 enum bool Bflag
= FALSE
; /* force Thumb disassembly (ARM objects only) */
103 enum bool Qflag
= FALSE
; /* use otool's disassembler */
104 enum bool qflag
= FALSE
; /* use 'C' Public llvm-mc disassembler */
105 enum bool jflag
= FALSE
; /* print opcode bytes */
106 enum bool Pflag
= FALSE
; /* print (__TEXT,__info_plist) section as strings */
107 char *pflag
= NULL
; /* procedure name to start disassembling from */
108 char *segname
= NULL
; /* name of the section to print the contents of */
109 char *sectname
= NULL
;
110 enum bool llvm_mc
= FALSE
; /* disassemble as llvm-mc will assemble */
111 char *mcpu
= ""; /* the arg of the -mcpu=arg flag */
112 /* Print function offsets when disassembling when TRUE. */
113 enum bool function_offsets
= FALSE
;
114 enum bool print_bind_info
= FALSE
; /* print dyld bind information */
116 /* this is set when any of the flags that process object files is set */
117 enum bool object_processing
= FALSE
;
124 static void processor(
129 static void get_symbol_table_info(
130 struct load_command
*load_commands
,
134 enum byte_sex load_commands_byte_sex
,
136 uint32_t object_size
,
137 struct nlist
**symbols
,
138 struct nlist_64
**symbols64
,
141 uint32_t *strings_size
);
143 static void get_toc_info(
144 struct load_command
*load_commands
,
147 enum byte_sex load_commands_byte_sex
,
149 uint32_t object_size
,
150 struct dylib_table_of_contents
**tocs
,
153 static void get_module_table_info(
154 struct load_command
*load_commands
,
158 enum byte_sex load_commands_byte_sex
,
160 uint32_t object_size
,
161 struct dylib_module
**mods
,
162 struct dylib_module_64
**mods64
,
165 static void get_ref_info(
166 struct load_command
*load_commands
,
169 enum byte_sex load_commands_byte_sex
,
171 uint32_t object_size
,
172 struct dylib_reference
**refs
,
175 static void get_indirect_symbol_table_info(
176 struct load_command
*load_commands
,
179 enum byte_sex load_commands_byte_sex
,
181 uint32_t object_size
,
182 uint32_t **indirect_symbols
,
183 uint32_t *nindirect_symbols
);
185 static enum bool get_dyst(
186 struct load_command
*load_commands
,
189 enum byte_sex load_commands_byte_sex
,
190 struct dysymtab_command
*dyst
);
192 static void get_hints_table_info(
193 struct load_command
*load_commands
,
196 enum byte_sex load_commands_byte_sex
,
198 uint32_t object_size
,
199 struct twolevel_hint
**hints
,
202 static enum bool get_hints_cmd(
203 struct load_command
*load_commands
,
206 enum byte_sex load_commands_byte_sex
,
207 struct twolevel_hints_command
*hints_cmd
);
209 static void get_link_opt_hints(
210 struct load_command
*load_commands
,
213 enum byte_sex load_commands_byte_sex
,
215 uint32_t object_size
,
219 static enum bool get_link_opt_hint_cmd(
220 struct load_command
*load_commands
,
223 enum byte_sex load_commands_byte_sex
,
224 struct linkedit_data_command
*loh_cmd
);
226 static void get_data_in_code_info(
227 struct load_command
*load_commands
,
230 enum byte_sex load_commands_byte_sex
,
232 uint32_t object_size
,
233 struct data_in_code_entry
**dices
,
236 static enum bool get_dices_cmd(
237 struct load_command
*load_commands
,
240 enum byte_sex load_commands_byte_sex
,
241 struct linkedit_data_command
*dices_cmd
);
243 static int sym_compare(
245 struct symbol
*sym2
);
247 static int rel_compare(
248 struct relocation_info
*rel1
,
249 struct relocation_info
*rel2
);
251 static void get_linked_reloc_info(
252 struct load_command
*load_commands
,
255 enum byte_sex load_commands_byte_sex
,
257 uint32_t object_size
,
258 struct relocation_info
**ext_relocs
,
259 uint32_t *next_relocs
,
260 struct relocation_info
**loc_relocs
,
261 uint32_t *nloc_relocs
);
263 static void setup_dyld_bind_info(
264 struct load_command
*load_commands
, /* input */
267 enum byte_sex load_commands_byte_sex
,
269 uint32_t object_size
,
270 struct dyld_bind_info
**dbi
, /* output */
273 static void print_text_by_symbols(
275 enum byte_sex object_byte_sex
,
280 struct symbol
*sorted_symbols
,
281 uint32_t nsorted_symbols
,
282 struct nlist
*symbols
,
283 struct nlist_64
*symbols64
,
286 uint32_t strings_size
,
287 struct relocation_info
*relocs
,
289 struct relocation_info
*ext_relocs
,
290 uint32_t next_relocs
,
291 struct relocation_info
*loc_relocs
,
292 uint32_t nloc_relocs
,
293 struct dyld_bind_info
*dbi
,
295 uint32_t *indirect_symbols
,
296 uint32_t nindirect_symbols
,
297 struct load_command
*load_commands
,
300 enum bool disassemble
,
302 cpu_subtype_t cpusubtype
,
304 uint32_t object_size
,
305 struct data_in_code_entry
*dices
,
309 static void print_text(
311 enum byte_sex object_byte_sex
,
316 struct symbol
*sorted_symbols
,
317 uint32_t nsorted_symbols
,
318 struct nlist
*symbols
,
319 struct nlist_64
*symbols64
,
322 uint32_t strings_size
,
323 struct relocation_info
*relocs
,
325 struct relocation_info
*ext_relocs
,
326 uint32_t next_relocs
,
327 struct relocation_info
*loc_relocs
,
328 uint32_t nloc_relocs
,
329 struct dyld_bind_info
*dbi
,
331 uint32_t *indirect_symbols
,
332 uint32_t nindirect_symbols
,
333 struct load_command
*load_commands
,
336 enum bool disassemble
,
338 cpu_subtype_t cpusubtype
,
340 uint32_t object_size
,
341 struct data_in_code_entry
*dices
,
345 static void print_argstrings(
347 struct load_command
*load_commands
,
351 cpu_subtype_t cpusubtype
,
352 enum byte_sex load_commands_byte_sex
,
354 uint32_t object_size
);
356 #else /* defined(LLVM_OTOOL) */
358 static void llvm_otool(
361 struct arch_flag
*arch_flags
,
362 uint32_t narch_flags
,
366 #endif /* LLVM_OTOOL */
368 /* apple_version is created by the libstuff/Makefile */
369 extern char apple_version
[];
370 char *version
= apple_version
;
371 /* likewise lto_suport */
372 extern char lto_support
[];
382 struct arch_flag
*arch_flags
;
383 uint32_t narch_flags
;
384 enum bool all_archs
, use_member_syntax
, version
;
387 const char *disssembler_version
;
388 #endif /* !defined(LLVM_OTOOL) */
394 use_member_syntax
= TRUE
;
403 * Parse the arguments.
406 files
= allocate(sizeof(char *) * argc
);
407 for(i
= 1; i
< argc
; i
++){
408 if(argv
[i
][0] == '-' && argv
[i
][1] == '\0'){
409 for(i
+= 1 ; i
< argc
; i
++)
410 files
[nfiles
++] = argv
[i
];
413 if(argv
[i
][0] != '-'){
414 files
[nfiles
++] = argv
[i
];
417 if(strcmp(argv
[i
], "--version") == 0){
421 #else /* defined(LLVM_OTOOL) */
423 #endif /* LLVM_OTOOL */
424 " Apple Inc. version %s\n", apple_version
);
426 disssembler_version
= llvm_disasm_version_string();
427 if(disssembler_version
!= NULL
)
428 fprintf(stderr
, "disassmbler: %s\n", disssembler_version
);
429 #endif /* !defined(LLVM_OTOOL) */
433 if(strcmp(argv
[i
], "-arch") == 0){
435 error("missing argument(s) to %s option", argv
[i
]);
438 if(strcmp("all", argv
[i
+1]) == 0){
442 arch_flags
= reallocate(arch_flags
,
443 (narch_flags
+ 1) * sizeof(struct arch_flag
));
444 if(get_arch_from_flag(argv
[i
+1],
445 arch_flags
+ narch_flags
) == 0){
446 error("unknown architecture specification flag: "
447 "%s %s", argv
[i
], argv
[i
+1]);
456 if(strcmp(argv
[i
], "-llvm-mc") == 0){
460 if(strcmp(argv
[i
], "-function_offsets") == 0){
461 function_offsets
= TRUE
;
464 if(strcmp(argv
[i
], "-bind_info") == 0){
465 print_bind_info
= TRUE
;
466 object_processing
= TRUE
;
469 if(strncmp(argv
[i
], "-mcpu=", sizeof("-mcpu=")-1) == 0){
470 mcpu
= argv
[i
] + sizeof("-mcpu=")-1;
472 error("missing argument to -mcpu=");
477 if(strcmp(argv
[i
], "-no-show-raw-insn") == 0){
478 no_show_raw_insn
= TRUE
;
481 if(argv
[i
][1] == 'p'){
483 error("-p requires an argument (a text symbol name)");
487 error("only one -p flag can be specified");
493 if(strcmp(argv
[i
], "-show-objdump-command") == 0){
494 show_objdump_command
= TRUE
;
497 #endif /* LLVM_OTOOL */
498 if(argv
[i
][1] == 's'){
500 error("-s requires two arguments (a segment name and a "
504 if(sectname
!= NULL
){
505 error("only one -s flag can be specified");
508 segname
= argv
[i
+ 1];
509 sectname
= argv
[i
+ 2];
511 object_processing
= TRUE
;
514 for(j
= 1; argv
[i
][j
] != '\0'; j
++){
535 object_processing
= TRUE
;
539 object_processing
= TRUE
;
543 object_processing
= TRUE
;
547 object_processing
= TRUE
;
551 object_processing
= TRUE
;
558 object_processing
= TRUE
;
562 object_processing
= TRUE
;
566 object_processing
= TRUE
;
570 object_processing
= TRUE
;
574 object_processing
= TRUE
;
578 object_processing
= TRUE
;
582 object_processing
= TRUE
;
586 object_processing
= TRUE
;
590 object_processing
= TRUE
;
594 object_processing
= TRUE
;
598 object_processing
= TRUE
;
605 object_processing
= TRUE
;
609 object_processing
= TRUE
;
621 use_member_syntax
= FALSE
;
637 object_processing
= TRUE
;
640 error("unknown char `%c' in flag %s\n", argv
[i
][j
],argv
[i
]);
647 * Check for correctness of arguments.
649 if(!fflag
&& !aflag
&& !hflag
&& !lflag
&& !Lflag
&& !tflag
&& !dflag
&&
650 !oflag
&& !Oflag
&& !rflag
&& !Tflag
&& !Mflag
&& !Rflag
&& !Iflag
&&
651 !Cflag
&& !print_bind_info
&& !version
&& !Pflag
&&
652 !Hflag
&& !Gflag
&& !Sflag
&& !cflag
&& !iflag
&& !Dflag
&&!segname
){
653 error("one of -fahlLtdoOrTMRIHCGScisP or --version must be "
658 error("can't specify both -q and -Q");
662 * The default, without the -Q flag, is to use the llvm dissembler
663 * instead of otool's internal disassemblers.
667 if(nfiles
== 0 && version
== FALSE
){
668 error("at least one file must be specified");
671 if(segname
!= NULL
&& sectname
!= NULL
){
672 /* treat "-s __TEXT __text" the same as -t */
673 if(strcmp(segname
, SEG_TEXT
) == 0 &&
674 strcmp(sectname
, SECT_TEXT
) == 0){
679 /* treat "-s __TEXT __fvmlib0" the same as -i */
680 else if(strcmp(segname
, SEG_TEXT
) == 0 &&
681 strcmp(sectname
, SECT_FVMLIB_INIT0
) == 0){
686 /* treat "-v -s __TEXT __info_plist" the same as -P */
687 else if(vflag
== TRUE
&& strcmp(segname
, SEG_TEXT
) == 0 &&
688 strcmp(sectname
, "__info_plist") == 0){
696 for(j
= 0; j
< nfiles
; j
++){
697 ofile_process(files
[j
], arch_flags
, narch_flags
, all_archs
, TRUE
,
698 TRUE
, use_member_syntax
, processor
, NULL
);
700 #else /* defined(LLVM_OTOOL) */
701 llvm_otool(files
, nfiles
, arch_flags
, narch_flags
, all_archs
, version
);
702 #endif /* LLVM_OTOOL */
705 return(EXIT_FAILURE
);
707 return(EXIT_SUCCESS
);
711 * Print the current usage message.
719 "Usage: %s [-arch arch_type] [-fahlLDtdorSTMRIHGvVcXmqQjCP] "
720 "[-mcpu=arg] [--version] <object file> ...\n", progname
);
722 fprintf(stderr
, "\t-f print the fat headers\n");
723 fprintf(stderr
, "\t-a print the archive header\n");
724 fprintf(stderr
, "\t-h print the mach header\n");
725 fprintf(stderr
, "\t-l print the load commands\n");
726 fprintf(stderr
, "\t-L print shared libraries used\n");
727 fprintf(stderr
, "\t-D print shared library id name\n");
728 fprintf(stderr
, "\t-t print the text section (disassemble with -v)\n");
729 fprintf(stderr
, "\t-p <routine name> start dissassemble from routine "
731 fprintf(stderr
, "\t-s <segname> <sectname> print contents of "
733 fprintf(stderr
, "\t-d print the data section\n");
734 fprintf(stderr
, "\t-o print the Objective-C segment\n");
735 fprintf(stderr
, "\t-r print the relocation entries\n");
736 fprintf(stderr
, "\t-S print the table of contents of a library\n");
737 fprintf(stderr
, "\t-T print the table of contents of a dynamic "
739 fprintf(stderr
, "\t-M print the module table of a dynamic shared "
741 fprintf(stderr
, "\t-R print the reference table of a dynamic shared "
743 fprintf(stderr
, "\t-I print the indirect symbol table\n");
744 fprintf(stderr
, "\t-H print the two-level hints table\n");
745 fprintf(stderr
, "\t-G print the data in code table\n");
746 fprintf(stderr
, "\t-v print verbosely (symbolically) when possible\n");
747 fprintf(stderr
, "\t-V print disassembled operands symbolically\n");
748 fprintf(stderr
, "\t-c print argument strings of a core file\n");
749 fprintf(stderr
, "\t-X print no leading addresses or headers\n");
750 fprintf(stderr
, "\t-m don't use archive(member) syntax\n");
751 fprintf(stderr
, "\t-B force Thumb disassembly (ARM objects only)\n");
752 fprintf(stderr
, "\t-q use llvm's disassembler (the default)\n");
753 fprintf(stderr
, "\t-Q use otool(1)'s disassembler\n");
754 fprintf(stderr
, "\t-mcpu=arg use `arg' as the cpu for disassembly\n");
755 fprintf(stderr
, "\t-j print opcode bytes\n");
756 fprintf(stderr
, "\t-P print the info plist section as strings\n");
757 fprintf(stderr
, "\t-C print linker optimization hints\n");
758 fprintf(stderr
, "\t--version print the version of %s\n", progname
);
764 static void llvm_otool(
767 struct arch_flag
*arch_flags
,
768 uint32_t narch_flags
,
773 struct stat stat_buf
;
776 objdump
= cmd_with_prefix("objdump");
777 if(stat(objdump
, &stat_buf
) == -1)
778 objdump
= cmd_with_prefix("llvm-objdump");
780 reset_execute_list();
781 add_execute_list(objdump
);
782 add_execute_list("-macho");
785 add_execute_list("-universal-headers");
787 add_execute_list("-archive-headers");
789 add_execute_list("-archive-member-offsets");
792 add_execute_list("-private-header");
794 add_execute_list("-private-headers");
797 add_execute_list("-disassemble");
799 add_execute_list("-section");
800 add_execute_list("__TEXT,__text");
803 if(tflag
|| segname
!= NULL
){
804 add_execute_list("-full-leading-addr");
805 add_execute_list("-print-imm-hex");
808 add_execute_list("-dis-symname");
809 add_execute_list(pflag
);
812 add_execute_list(makestr("-mcpu=", mcpu
, NULL
));
814 add_execute_list("-indirect-symbols");
816 add_execute_list("-data-in-code");
818 add_execute_list("-link-opt-hints");
820 add_execute_list("-info-plist");
821 if(segname
!= NULL
&& sectname
!= NULL
){
822 add_execute_list("-section");
823 add_execute_list(makestr(segname
, ",", sectname
, NULL
));
826 add_execute_list("-section");
827 add_execute_list("__DATA,__data");
830 add_execute_list("-r");
832 error("for -S functionality, use llvm-nm with -print-armap");
834 add_execute_list("-version");
836 add_execute_list("-bind");
838 add_execute_list("-dylibs-used");
840 add_execute_list("-dylib-id");
842 add_execute_list("-objc-meta-data");
845 add_execute_list("-non-verbose");
846 if(!Vflag
&& (tflag
|| segname
!= NULL
))
847 add_execute_list("-no-symbolic-operands");
848 if((!jflag
&& (tflag
|| segname
!= NULL
)) || no_show_raw_insn
)
849 add_execute_list("-no-show-raw-insn");
851 add_execute_list("-no-leading-addr");
854 add_execute_list("-arch");
855 add_execute_list("all");
857 for(i
= 0; i
< narch_flags
; i
++){
858 add_execute_list("-arch");
859 add_execute_list(arch_flags
[i
].name
);
863 warning("-B functionality not implemented in objdump(1)");
865 warning("-c functionality not implemented in objdump(1)");
867 warning("-W functionality not implemented in objdump(1)");
869 warning("-function-offsets functionality not implemented in "
872 warning("-O functionality obsolete");
874 warning("-T functionality obsolete");
876 warning("-M functionality obsolete");
878 warning("-R functionality obsolete");
880 warning("-i functionality obsolete");
882 warning("-Q functionality obsolete");
884 for(i
= 0; i
< nfiles
; i
++)
885 add_execute_list(files
[i
]);
887 if(execute_list(show_objdump_command
) == 0)
888 fatal("internal objdump command failed");
891 #else /* !defined(LLVM_OTOOL) */
898 void *cookie
) /* cookie is not used */
903 struct mach_header mh
;
904 struct mach_header_64 mh64
;
905 cpu_type_t mh_cputype
;
906 cpu_subtype_t mh_cpusubtype
;
907 uint32_t mh_magic
, mh_filetype
, mh_ncmds
, mh_sizeofcmds
, sizeof_mach_header
;
908 struct load_command
*load_commands
;
909 uint32_t nsymbols
, nsorted_symbols
, strings_size
, len
;
910 struct nlist
*symbols
, *allocated_symbols
;
911 struct nlist_64
*symbols64
, *allocated_symbols64
;
912 struct symbol
*sorted_symbols
;
919 uint32_t sect_nrelocs
, sect_flags
, nrelocs
, next_relocs
, nloc_relocs
;
920 uint64_t sect_addr
, sect_size
;
921 struct relocation_info
*sect_relocs
, *relocs
, *ext_relocs
, *loc_relocs
;
922 uint32_t *indirect_symbols
, *allocated_indirect_symbols
;
923 uint32_t nindirect_symbols
;
924 struct dylib_module
*mods
, *allocated_mods
;
925 struct dylib_module_64
*mods64
, *allocated_mods64
;
926 struct dylib_table_of_contents
*tocs
, *allocated_tocs
;
927 struct dylib_reference
*refs
, *allocated_refs
;
928 uint32_t nmods
, ntocs
, nrefs
;
929 struct twolevel_hint
*hints
, *allocated_hints
;
930 struct data_in_code_entry
*dices
, *allocated_dices
;
931 uint32_t nhints
, ndices
;
935 struct dyld_bind_info
*dbi
;
939 sorted_symbols
= NULL
;
941 indirect_symbols
= NULL
;
942 nindirect_symbols
= 0;
955 * These may or may not be allocated. If allocated they will not be
956 * NULL and then free'ed before returning.
958 load_commands
= NULL
;
959 allocated_symbols
= NULL
;
960 allocated_symbols64
= NULL
;
961 sorted_symbols
= NULL
;
962 allocated_indirect_symbols
= NULL
;
963 allocated_tocs
= NULL
;
964 allocated_mods
= NULL
;
965 allocated_refs
= NULL
;
966 allocated_hints
= NULL
;
967 allocated_dices
= NULL
;
972 * The fat headers are printed in ofile_map() in ofile.c #ifdef'ed
979 if(aflag
&& ofile
->member_ar_hdr
!= NULL
){
980 uint64_t member_offset
;
982 member_offset
= ofile
->member_offset
- sizeof(struct ar_hdr
);
983 if(strncmp(ofile
->member_ar_hdr
->ar_name
, AR_EFMT1
,
984 sizeof(AR_EFMT1
) - 1) == 0)
985 member_offset
-= ofile
->member_name_size
;
987 print_ar_hdr(ofile
->member_ar_hdr
, ofile
->member_name
,
988 ofile
->member_name_size
, member_offset
, vflag
, Vflag
);
992 * Archive table of contents.
994 if(ofile
->member_ar_hdr
!= NULL
&&
995 (strncmp(ofile
->member_name
, SYMDEF
, sizeof(SYMDEF
)-1) == 0 ||
996 strncmp(ofile
->member_name
, "/ ", sizeof("/ ")-1) == 0)){
999 if(ofile
->file_type
== OFILE_FAT
){
1000 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1001 addr
= ofile
->file_addr
+
1002 ofile
->fat_archs64
[ofile
->narch
].offset
;
1003 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
1006 addr
= ofile
->file_addr
+
1007 ofile
->fat_archs
[ofile
->narch
].offset
;
1008 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1012 addr
= ofile
->file_addr
;
1013 size
= ofile
->file_size
;
1015 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1016 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1017 if(strncmp(ofile
->member_name
, SYMDEF
, sizeof(SYMDEF
)-1) == 0)
1018 print_library_toc(ofile
->member_ar_hdr
, /* toc_ar_hdr */
1019 ofile
->member_name
, /* toc_name */
1020 ofile
->member_name_size
, /* toc_name_size */
1021 ofile
->member_addr
, /* toc_addr */
1022 ofile
->member_size
, /* toc_size */
1023 get_toc_byte_sex(addr
, size
),
1024 ofile
->file_name
, /* library_name */
1025 addr
, /* library_addr */
1026 size
, /* library_size */
1030 print_sysv_library_toc(ofile
->member_ar_hdr
, /* toc_ar_hdr */
1031 ofile
->member_name
, /* toc_name */
1032 ofile
->member_name_size
,
1034 ofile
->member_addr
, /* toc_addr */
1035 ofile
->member_size
, /* toc_size */
1036 get_toc_byte_sex(addr
, size
),
1037 ofile
->file_name
, /* library_name */
1038 addr
, /* library_addr */
1039 size
, /* library_size */
1045 * Quietly skip the System V archive string table member name which has
1046 * the name "//", just as we skip the table of contents above.
1048 if(ofile
->member_ar_hdr
!= NULL
&&
1049 strncmp(ofile
->member_name
, "// ", sizeof("// ")-1) == 0)
1052 if(object_processing
== FALSE
)
1056 * Print header for the object name if in an archive or an architecture
1057 * name is passed in.
1060 printf("%s", ofile
->file_name
);
1061 if(ofile
->member_ar_hdr
!= NULL
){
1062 printf("(%.*s)", (int)ofile
->member_name_size
,
1063 ofile
->member_name
);
1065 if(arch_name
!= NULL
)
1066 printf(" (architecture %s):", arch_name
);
1070 * If the mach_header pointer is NULL the file is not an object
1071 * file. Truncated object file (where the file size is less
1072 * than sizeof(struct mach_header) also does not have it's
1073 * mach_header set. So deal with both cases here and then
1074 * return as the rest of this routine deals only with things
1077 if(ofile
->mh
== NULL
&& ofile
->mh64
== NULL
){
1078 if(ofile
->file_type
== OFILE_FAT
){
1080 * This routine is not called on fat files where the
1081 * offset is past end of file. An error message is
1082 * printed in ofile_specific_arch() in ofile.c.
1084 if(ofile
->arch_type
== OFILE_ARCHIVE
){
1085 addr
= ofile
->member_addr
;
1086 size
= ofile
->member_size
;
1089 if(ofile
->fat_header
->magic
== FAT_MAGIC_64
){
1090 addr
= ofile
->file_addr
+
1091 ofile
->fat_archs64
[ofile
->narch
].offset
;
1092 size
= ofile
->fat_archs64
[ofile
->narch
].size
;
1095 addr
= ofile
->file_addr
+
1096 ofile
->fat_archs
[ofile
->narch
].offset
;
1097 size
= ofile
->fat_archs
[ofile
->narch
].size
;
1100 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1101 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1103 else if(ofile
->file_type
== OFILE_ARCHIVE
){
1104 addr
= ofile
->member_addr
;
1105 size
= ofile
->member_size
;
1107 else{ /* ofile->file_type == OFILE_UNKNOWN */
1108 addr
= ofile
->file_addr
;
1109 size
= ofile
->file_size
;
1111 if(size
> sizeof(int32_t)){
1112 memcpy(&magic
, addr
, sizeof(uint32_t));
1113 if(magic
== MH_MAGIC
||
1114 magic
== SWAP_INT(MH_MAGIC
)){
1115 printf(" is a truncated object file\n");
1116 memset(&mh
, '\0', sizeof(struct mach_header
));
1117 if(size
> sizeof(struct mach_header
))
1118 size
= sizeof(struct mach_header
);
1119 memcpy(&mh
, addr
, size
);
1120 if(magic
== SWAP_INT(MH_MAGIC
))
1121 swap_mach_header(&mh
, get_host_byte_sex());
1123 print_mach_header(mh
.magic
, mh
.cputype
,
1124 mh
.cpusubtype
, mh
.filetype
, mh
.ncmds
,
1125 mh
.sizeofcmds
, mh
.flags
, vflag
);
1128 else if(magic
== MH_MAGIC_64
||
1129 magic
== SWAP_INT(MH_MAGIC_64
)){
1130 printf(" is a truncated object file\n");
1131 memset(&mh64
, '\0', sizeof(struct mach_header_64
));
1132 if(size
> sizeof(struct mach_header_64
))
1133 size
= sizeof(struct mach_header_64
);
1134 memcpy(&mh64
, addr
, size
);
1135 if(magic
== SWAP_INT(MH_MAGIC_64
))
1136 swap_mach_header_64(&mh64
, get_host_byte_sex());
1138 print_mach_header(mh64
.magic
, mh64
.cputype
,
1139 mh64
.cpusubtype
, mh64
.filetype
, mh64
.ncmds
,
1140 mh64
.sizeofcmds
, mh64
.flags
, vflag
);
1145 if(ofile
->lto
!= NULL
){
1146 printf(" is an LLVM bit-code file\n");
1149 #endif /* LTO_SUPPORT */
1150 printf(" is not an object file\n");
1154 if(ofile
->mh
!= NULL
){
1155 if((intptr_t)(ofile
->mh
) % sizeof(uint32_t)){
1157 printf("(object file offset is not a multiple of sizeof("
1159 memcpy(&mh
, ofile
->mh
, sizeof(struct mach_header
));
1160 if(mh
.magic
== SWAP_INT(MH_MAGIC
))
1161 swap_mach_header(&mh
, get_host_byte_sex());
1164 else if(ofile
->mh
->magic
== SWAP_INT(MH_MAGIC
)){
1166 swap_mach_header(&mh
, get_host_byte_sex());
1170 else if(ofile
->mh64
!= NULL
){
1171 if((intptr_t)(ofile
->mh64
) % sizeof(uint32_t)){
1173 printf("(object file offset is not a multiple of sizeof("
1175 memcpy(&mh64
, ofile
->mh64
, sizeof(struct mach_header
));
1176 if(mh64
.magic
== SWAP_INT(MH_MAGIC_64
))
1177 swap_mach_header_64(&mh64
, get_host_byte_sex());
1178 ofile
->mh64
= &mh64
;
1180 else if(ofile
->mh64
->magic
== SWAP_INT(MH_MAGIC_64
)){
1181 mh64
= *(ofile
->mh64
);
1182 swap_mach_header_64(&mh64
, get_host_byte_sex());
1183 ofile
->mh64
= &mh64
;
1190 * If this is not an object file then just return.
1192 if(ofile
->mh
== NULL
&& ofile
->mh64
== NULL
)
1196 * Calculate the true number of bytes of the of the object file that
1197 * is in memory (in case this file is truncated).
1199 addr
= ofile
->object_addr
;
1200 size
= ofile
->object_size
;
1201 if(addr
+ size
> ofile
->file_addr
+ ofile
->file_size
)
1202 size
= (ofile
->file_addr
+ ofile
->file_size
) - addr
;
1205 * Assign some local variables to the values in the mach_header for this
1206 * ofile to make passing arguments to the print routines easier.
1208 if(ofile
->mh
!= NULL
){
1209 mh_magic
= ofile
->mh
->magic
;
1210 mh_cputype
= ofile
->mh
->cputype
;
1211 mh_cpusubtype
= ofile
->mh
->cpusubtype
;
1212 mh_filetype
= ofile
->mh
->filetype
;
1213 mh_ncmds
= ofile
->mh
->ncmds
;
1214 mh_sizeofcmds
= ofile
->mh
->sizeofcmds
;
1215 sizeof_mach_header
= sizeof(struct mach_header
);
1218 mh_magic
= ofile
->mh64
->magic
;
1219 mh_cputype
= ofile
->mh64
->cputype
;
1220 mh_cpusubtype
= ofile
->mh64
->cpusubtype
;
1221 mh_filetype
= ofile
->mh64
->filetype
;
1222 mh_ncmds
= ofile
->mh64
->ncmds
;
1223 mh_sizeofcmds
= ofile
->mh64
->sizeofcmds
;
1224 sizeof_mach_header
= sizeof(struct mach_header_64
);
1231 if(ofile
->mh
!= NULL
)
1232 print_mach_header(ofile
->mh
->magic
, ofile
->mh
->cputype
,
1233 ofile
->mh
->cpusubtype
, ofile
->mh
->filetype
,
1234 ofile
->mh
->ncmds
, ofile
->mh
->sizeofcmds
,
1235 ofile
->mh
->flags
, vflag
);
1237 print_mach_header(ofile
->mh64
->magic
, ofile
->mh64
->cputype
,
1238 ofile
->mh64
->cpusubtype
,ofile
->mh64
->filetype
,
1239 ofile
->mh64
->ncmds
, ofile
->mh64
->sizeofcmds
,
1240 ofile
->mh64
->flags
, vflag
);
1246 big_size
= mh_sizeofcmds
;
1247 big_size
+= sizeof_mach_header
;
1248 if(big_size
> size
){
1250 * For malformed binaries trim the mh_sizeofcmds to be no bigger
1251 * than the size of the file after the mach_header. This will
1252 * limit the printing of the unknown load commands so it does not
1253 * appear to be in an infinite loop printing the zero's we created
1254 * with the memset().
1256 if(size
> sizeof_mach_header
)
1257 mh_sizeofcmds
= size
- sizeof_mach_header
;
1259 mh_sizeofcmds
= sizeof(struct load_command
);
1260 load_commands
= allocate(mh_sizeofcmds
);
1261 memset(load_commands
, '\0', mh_sizeofcmds
);
1262 if(size
> sizeof_mach_header
)
1263 memcpy(load_commands
, ofile
->load_commands
, mh_sizeofcmds
);
1264 ofile
->load_commands
= load_commands
;
1267 print_loadcmds(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1268 mh_cputype
, mh_filetype
, ofile
->object_byte_sex
,
1269 size
, vflag
, Vflag
);
1272 print_libraries(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1273 ofile
->object_byte_sex
, (Dflag
&& !Lflag
), vflag
);
1276 * If the indicated operation needs the symbol table get it.
1279 if(segname
!= NULL
&& sectname
!= NULL
){
1280 (void)get_sect_info(segname
, sectname
, ofile
->load_commands
,
1281 mh_ncmds
, mh_sizeofcmds
, mh_filetype
,
1282 ofile
->object_byte_sex
,
1283 addr
, size
, §
, §_size
, §_addr
,
1284 §_relocs
, §_nrelocs
, §_flags
, &seg_addr
);
1286 * The MH_DYLIB_STUB format has all section sizes set to zero
1287 * except sections with indirect symbol table entries (so that the
1288 * indirect symbol table table entries can be printed, which are
1289 * based on the section size). So if we are being asked to print
1290 * the section contents of one of these sections in a MH_DYLIB_STUB
1291 * we assume it has been stripped and set the section size to zero.
1293 if(mh_filetype
== MH_DYLIB_STUB
&&
1294 ((sect_flags
& SECTION_TYPE
) == S_NON_LAZY_SYMBOL_POINTERS
||
1295 (sect_flags
& SECTION_TYPE
) == S_LAZY_SYMBOL_POINTERS
||
1296 (sect_flags
& SECTION_TYPE
) == S_LAZY_DYLIB_SYMBOL_POINTERS
||
1297 (sect_flags
& SECTION_TYPE
) == S_SYMBOL_STUBS
))
1301 get_symbol_table_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1302 mh_cputype
, ofile
->object_byte_sex
, addr
, size
, &symbols
,
1303 &symbols64
, &nsymbols
, &strings
, &strings_size
);
1304 if(vflag
&& (rflag
|| Tflag
|| Mflag
|| Rflag
|| Iflag
|| Hflag
|| tflag
1305 || iflag
|| oflag
||
1306 (sect_flags
& SECTION_TYPE
) == S_LITERAL_POINTERS
||
1307 (sect_flags
& SECTION_TYPE
) == S_MOD_INIT_FUNC_POINTERS
||
1308 (sect_flags
& SECTION_TYPE
) == S_MOD_TERM_FUNC_POINTERS
||
1309 (sect_flags
& S_ATTR_PURE_INSTRUCTIONS
) ==
1310 S_ATTR_PURE_INSTRUCTIONS
||
1311 (sect_flags
& S_ATTR_SOME_INSTRUCTIONS
) ==
1312 S_ATTR_SOME_INSTRUCTIONS
||
1314 get_symbol_table_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1315 mh_cputype
, ofile
->object_byte_sex
, addr
, size
, &symbols
,
1316 &symbols64
, &nsymbols
, &strings
, &strings_size
);
1318 if(symbols
!= NULL
){
1319 if((uintptr_t)symbols
% sizeof(uint32_t) ||
1320 ofile
->object_byte_sex
!= get_host_byte_sex()){
1322 allocate(nsymbols
* sizeof(struct nlist
));
1323 memcpy(allocated_symbols
, symbols
,
1324 nsymbols
* sizeof(struct nlist
));
1325 symbols
= allocated_symbols
;
1327 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1328 swap_nlist(symbols
, nsymbols
, get_host_byte_sex());
1331 if((uintptr_t)symbols64
% sizeof(uint32_t) ||
1332 ofile
->object_byte_sex
!= get_host_byte_sex()){
1333 allocated_symbols64
=
1334 allocate(nsymbols
* sizeof(struct nlist_64
));
1335 memcpy(allocated_symbols64
, symbols64
,
1336 nsymbols
* sizeof(struct nlist_64
));
1337 symbols64
= allocated_symbols64
;
1339 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1340 swap_nlist_64(symbols64
, nsymbols
, get_host_byte_sex());
1344 * If the operation needs a sorted symbol table create it.
1346 if(tflag
|| iflag
|| oflag
||
1347 (((sect_flags
& SECTION_TYPE
) == S_MOD_INIT_FUNC_POINTERS
||
1348 (sect_flags
& SECTION_TYPE
) == S_MOD_TERM_FUNC_POINTERS
) &&
1350 (sect_flags
& S_ATTR_PURE_INSTRUCTIONS
) ==
1351 S_ATTR_PURE_INSTRUCTIONS
||
1352 (sect_flags
& S_ATTR_SOME_INSTRUCTIONS
) ==
1353 S_ATTR_SOME_INSTRUCTIONS
){
1354 sorted_symbols
= allocate(nsymbols
* sizeof(struct symbol
));
1355 nsorted_symbols
= 0;
1356 for(i
= 0; i
< nsymbols
; i
++){
1357 if(symbols
!= NULL
){
1358 n_strx
= symbols
[i
].n_un
.n_strx
;
1359 n_type
= symbols
[i
].n_type
;
1360 n_desc
= symbols
[i
].n_desc
;
1361 n_value
= symbols
[i
].n_value
;
1364 n_strx
= symbols64
[i
].n_un
.n_strx
;
1365 n_type
= symbols64
[i
].n_type
;
1366 n_desc
= symbols64
[i
].n_desc
;
1367 n_value
= symbols64
[i
].n_value
;
1369 if(n_strx
> 0 && n_strx
< strings_size
)
1370 p
= strings
+ n_strx
;
1372 p
= "symbol with bad string index";
1373 if(n_type
& ~(N_TYPE
|N_EXT
|N_PEXT
))
1375 n_type
= n_type
& N_TYPE
;
1376 if(n_type
== N_ABS
|| n_type
== N_SECT
){
1378 if(len
> sizeof(".o") - 1 &&
1379 strcmp(p
+ (len
- (sizeof(".o") - 1)), ".o") == 0)
1381 if(strcmp(p
, "gcc_compiled.") == 0)
1383 if(strncmp(p
, "ltmp", sizeof("ltmp") - 1) == 0)
1385 if(n_type
== N_ABS
&& n_value
== 0 && *p
== '.')
1387 sorted_symbols
[nsorted_symbols
].n_value
= n_value
;
1388 sorted_symbols
[nsorted_symbols
].name
= p
;
1389 sorted_symbols
[nsorted_symbols
].is_thumb
=
1390 n_desc
& N_ARM_THUMB_DEF
;
1394 qsort(sorted_symbols
, nsorted_symbols
, sizeof(struct symbol
),
1395 (int (*)(const void *, const void *))sym_compare
);
1399 if(Mflag
|| Tflag
|| Rflag
){
1400 get_module_table_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1401 mh_cputype
, ofile
->object_byte_sex
, addr
, size
, &mods
, &mods64
,
1404 if((intptr_t)mods
% sizeof(uint32_t) ||
1405 ofile
->object_byte_sex
!= get_host_byte_sex()){
1406 allocated_mods
= allocate(nmods
*
1407 sizeof(struct dylib_module
));
1408 memcpy(allocated_mods
, mods
,
1409 nmods
* sizeof(struct dylib_module
));
1410 mods
= allocated_mods
;
1412 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1413 swap_dylib_module(mods
, nmods
, get_host_byte_sex());
1416 if((intptr_t)mods64
% sizeof(uint64_t) ||
1417 ofile
->object_byte_sex
!= get_host_byte_sex()){
1418 allocated_mods64
= allocate(nmods
*
1419 sizeof(struct dylib_module_64
));
1420 memcpy(allocated_mods64
, mods64
,
1421 nmods
* sizeof(struct dylib_module_64
));
1422 mods64
= allocated_mods64
;
1424 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1425 swap_dylib_module_64(mods64
, nmods
, get_host_byte_sex());
1430 get_toc_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1431 ofile
->object_byte_sex
, addr
, size
, &tocs
, &ntocs
);
1432 if((intptr_t)tocs
% sizeof(uint32_t) ||
1433 ofile
->object_byte_sex
!= get_host_byte_sex()){
1434 allocated_tocs
= allocate(ntocs
*
1435 sizeof(struct dylib_table_of_contents
));
1436 memcpy(allocated_tocs
, tocs
,
1437 ntocs
* sizeof(struct dylib_table_of_contents
));
1438 tocs
= allocated_tocs
;
1440 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1441 swap_dylib_table_of_contents(tocs
, ntocs
, get_host_byte_sex());
1442 print_toc(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1443 ofile
->object_byte_sex
, addr
, size
, tocs
, ntocs
, mods
, mods64
,
1444 nmods
, symbols
, symbols64
, nsymbols
, strings
, strings_size
,
1450 print_module_table(mods
, nmods
, strings
, strings_size
, vflag
);
1452 print_module_table_64(mods64
, nmods
, strings
, strings_size
,
1457 get_ref_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1458 ofile
->object_byte_sex
, addr
, size
, &refs
, &nrefs
);
1459 if((intptr_t)refs
% sizeof(uint32_t) ||
1460 ofile
->object_byte_sex
!= get_host_byte_sex()){
1461 allocated_refs
= allocate(nrefs
*
1462 sizeof(struct dylib_reference
));
1463 memcpy(allocated_refs
, refs
,
1464 nrefs
* sizeof(struct dylib_reference
));
1465 refs
= allocated_refs
;
1467 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1468 swap_dylib_reference(refs
, nrefs
, get_host_byte_sex());
1469 print_refs(refs
, nrefs
, mods
, mods64
, nmods
, symbols
, symbols64
,
1470 nsymbols
, strings
, strings_size
, vflag
);
1473 if(Iflag
|| (tflag
&& vflag
)){
1474 get_indirect_symbol_table_info(ofile
->load_commands
, mh_ncmds
,
1475 mh_sizeofcmds
, ofile
->object_byte_sex
, addr
, size
,
1476 &indirect_symbols
, &nindirect_symbols
);
1477 if((intptr_t)indirect_symbols
% sizeof(uint32_t) ||
1478 ofile
->object_byte_sex
!= get_host_byte_sex()){
1479 allocated_indirect_symbols
= allocate(nindirect_symbols
*
1481 memcpy(allocated_indirect_symbols
, indirect_symbols
,
1482 nindirect_symbols
* sizeof(uint32_t));
1483 indirect_symbols
= allocated_indirect_symbols
;
1485 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1486 swap_indirect_symbols(indirect_symbols
, nindirect_symbols
,
1487 get_host_byte_sex());
1490 get_hints_table_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1491 ofile
->object_byte_sex
, addr
, size
, &hints
, &nhints
);
1492 if((intptr_t)hints
% sizeof(uint32_t) ||
1493 ofile
->object_byte_sex
!= get_host_byte_sex()){
1494 allocated_hints
= allocate(nhints
*
1495 sizeof(struct twolevel_hint
));
1496 memcpy(allocated_hints
, hints
,
1497 nhints
* sizeof(struct twolevel_hint
));
1498 hints
= allocated_hints
;
1500 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1501 swap_twolevel_hint(hints
, nhints
, get_host_byte_sex());
1502 print_hints(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1503 ofile
->object_byte_sex
, hints
, nhints
, symbols
, symbols64
,
1504 nsymbols
, strings
, strings_size
, vflag
);
1507 get_link_opt_hints(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1508 ofile
->object_byte_sex
, addr
, size
, &loh
, &nloh
);
1509 print_link_opt_hints(loh
, nloh
);
1511 if(Gflag
|| (tflag
&& vflag
)){
1512 get_data_in_code_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1513 ofile
->object_byte_sex
, addr
, size
, &dices
, &ndices
);
1514 if((intptr_t)dices
% sizeof(uint32_t) ||
1515 ofile
->object_byte_sex
!= get_host_byte_sex()){
1516 allocated_dices
= allocate(ndices
*
1517 sizeof(struct data_in_code_entry
));
1518 memcpy(allocated_dices
, dices
,
1519 ndices
* sizeof(struct data_in_code_entry
));
1520 dices
= allocated_dices
;
1522 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1523 swap_data_in_code_entry(dices
, ndices
, get_host_byte_sex());
1525 print_dices(dices
, ndices
, vflag
);
1528 print_indirect_symbols(ofile
->load_commands
, mh_ncmds
,mh_sizeofcmds
,
1529 mh_cputype
, ofile
->object_byte_sex
, indirect_symbols
,
1530 nindirect_symbols
, symbols
, symbols64
, nsymbols
, strings
,
1531 strings_size
, vflag
);
1534 print_reloc(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1535 mh_cputype
, ofile
->object_byte_sex
, addr
, size
, symbols
,
1536 symbols64
, nsymbols
, strings
, strings_size
, vflag
);
1537 if(print_bind_info
){
1538 setup_dyld_bind_info(ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1539 ofile
->object_byte_sex
, ofile
->object_addr
, ofile
->object_size
,
1541 print_dyld_bind_info(dbi
, ndbi
);
1545 (sect_flags
& S_ATTR_PURE_INSTRUCTIONS
) ==
1546 S_ATTR_PURE_INSTRUCTIONS
||
1547 (sect_flags
& S_ATTR_SOME_INSTRUCTIONS
) ==
1548 S_ATTR_SOME_INSTRUCTIONS
){
1550 (void)get_sect_info(SEG_TEXT
, SECT_TEXT
, ofile
->load_commands
,
1551 mh_ncmds
, mh_sizeofcmds
, mh_filetype
,
1552 ofile
->object_byte_sex
,
1553 addr
, size
, §
, §_size
, §_addr
,
1554 §_relocs
, §_nrelocs
, §_flags
, &seg_addr
);
1556 /* create aligned relocations entries as needed */
1564 if(mh_filetype
== MH_KEXT_BUNDLE
){
1565 get_linked_reloc_info(ofile
->load_commands
, mh_ncmds
,
1566 mh_sizeofcmds
, ofile
->object_byte_sex
,
1567 ofile
->object_addr
, ofile
->object_size
, &ext_relocs
,
1568 &next_relocs
, &loc_relocs
, &nloc_relocs
);
1569 /* create aligned relocations entries as needed */
1570 if((intptr_t)ext_relocs
% sizeof(int32_t) != 0 ||
1571 ofile
->object_byte_sex
!= get_host_byte_sex()){
1572 relocs
= allocate(next_relocs
*
1573 sizeof(struct relocation_info
));
1574 memcpy(relocs
, ext_relocs
, next_relocs
*
1575 sizeof(struct relocation_info
));
1576 ext_relocs
= relocs
;
1578 if((intptr_t)loc_relocs
% sizeof(int32_t) != 0 ||
1579 ofile
->object_byte_sex
!= get_host_byte_sex()){
1580 relocs
= allocate(nloc_relocs
*
1581 sizeof(struct relocation_info
));
1582 memcpy(relocs
, loc_relocs
, nloc_relocs
*
1583 sizeof(struct relocation_info
));
1584 loc_relocs
= relocs
;
1586 if(ofile
->object_byte_sex
!= get_host_byte_sex()){
1587 swap_relocation_info(ext_relocs
, next_relocs
,
1588 get_host_byte_sex());
1589 swap_relocation_info(loc_relocs
, nloc_relocs
,
1590 get_host_byte_sex());
1594 if((intptr_t)sect_relocs
% sizeof(int32_t) != 0 ||
1595 ofile
->object_byte_sex
!= get_host_byte_sex()){
1596 nrelocs
= sect_nrelocs
;
1597 relocs
= allocate(nrelocs
*
1598 sizeof(struct relocation_info
));
1599 memcpy(relocs
, sect_relocs
, nrelocs
*
1600 sizeof(struct relocation_info
));
1603 nrelocs
= sect_nrelocs
;
1604 relocs
= sect_relocs
;
1606 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1607 swap_relocation_info(relocs
, nrelocs
,
1608 get_host_byte_sex());
1609 setup_dyld_bind_info(ofile
->load_commands
, mh_ncmds
,
1610 mh_sizeofcmds
, ofile
->object_byte_sex
,
1611 ofile
->object_addr
, ofile
->object_size
,
1616 printf("(%s,%s) section\n", SEG_TEXT
, SECT_TEXT
);
1618 printf("Contents of (%.16s,%.16s) section\n", segname
,
1622 print_text_by_symbols(mh_cputype
, ofile
->object_byte_sex
, sect
,
1623 sect_size
, sect_addr
, sect_flags
, sorted_symbols
,
1624 nsorted_symbols
, symbols
, symbols64
, nsymbols
, strings
,
1625 strings_size
, relocs
, nrelocs
, ext_relocs
, next_relocs
,
1626 loc_relocs
, nloc_relocs
, dbi
, ndbi
, indirect_symbols
,
1627 nindirect_symbols
, ofile
->load_commands
, mh_ncmds
,
1628 mh_sizeofcmds
, vflag
, Vflag
, mh_cpusubtype
,
1629 ofile
->object_addr
, ofile
->object_size
, dices
, ndices
,
1632 print_text(mh_cputype
, ofile
->object_byte_sex
, sect
, sect_size
,
1633 sect_addr
, sect_flags
, sorted_symbols
,
1634 nsorted_symbols
, symbols
, symbols64
, nsymbols
, strings
,
1635 strings_size
, relocs
, nrelocs
, ext_relocs
, next_relocs
,
1636 loc_relocs
, nloc_relocs
, dbi
, ndbi
, indirect_symbols
,
1637 nindirect_symbols
, ofile
->load_commands
, mh_ncmds
,
1638 mh_sizeofcmds
, vflag
, Vflag
, mh_cpusubtype
,
1639 ofile
->object_addr
, ofile
->object_size
, dices
, ndices
,
1642 if(relocs
!= NULL
&& relocs
!= sect_relocs
)
1647 if(get_sect_info(SEG_TEXT
, SECT_FVMLIB_INIT0
, ofile
->load_commands
,
1648 mh_ncmds
, mh_sizeofcmds
, mh_filetype
, ofile
->object_byte_sex
,
1649 addr
, size
, §
, §_size
, §_addr
,
1650 §_relocs
, §_nrelocs
, §_flags
, &seg_addr
) == TRUE
){
1652 /* create aligned, sorted relocations entries */
1653 nrelocs
= sect_nrelocs
;
1654 relocs
= allocate(nrelocs
* sizeof(struct relocation_info
));
1655 memcpy(relocs
, sect_relocs
, nrelocs
*
1656 sizeof(struct relocation_info
));
1657 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1658 swap_relocation_info(relocs
, nrelocs
, get_host_byte_sex());
1659 qsort(relocs
, nrelocs
, sizeof(struct relocation_info
),
1660 (int (*)(const void *, const void *))rel_compare
);
1663 printf("Shared library initialization (%s,%s) section\n",
1664 SEG_TEXT
, SECT_FVMLIB_INIT0
);
1665 print_shlib_init(ofile
->object_byte_sex
, sect
, sect_size
,
1666 sect_addr
, sorted_symbols
, nsorted_symbols
, symbols
,
1667 symbols64
, nsymbols
, strings
, strings_size
, relocs
,
1674 if(get_sect_info(SEG_DATA
, SECT_DATA
, ofile
->load_commands
,
1675 mh_ncmds
, mh_sizeofcmds
, mh_filetype
, ofile
->object_byte_sex
,
1676 addr
, size
, §
, §_size
, §_addr
,
1677 §_relocs
, §_nrelocs
, §_flags
, &seg_addr
) == TRUE
){
1680 printf("(%s,%s) section\n", SEG_DATA
, SECT_DATA
);
1682 print_sect(mh_cputype
, ofile
->object_byte_sex
, sect
, sect_size
,
1688 if(get_sect_info(SEG_TEXT
, "__info_plist", ofile
->load_commands
,
1689 mh_ncmds
, mh_sizeofcmds
, mh_filetype
, ofile
->object_byte_sex
,
1690 addr
, size
, §
, §_size
, §_addr
,
1691 §_relocs
, §_nrelocs
, §_flags
, &seg_addr
) == TRUE
){
1694 printf("(%s,%s) section\n", SEG_TEXT
, "__info_plist");
1695 printf("%.*s\n", (int)sect_size
, sect
);
1699 if(segname
!= NULL
&& sectname
!= NULL
&&
1700 (sect_flags
& S_ATTR_PURE_INSTRUCTIONS
) !=
1701 S_ATTR_PURE_INSTRUCTIONS
&&
1702 (sect_flags
& S_ATTR_SOME_INSTRUCTIONS
) !=
1703 S_ATTR_SOME_INSTRUCTIONS
){
1704 if(strcmp(segname
, SEG_OBJC
) == 0 &&
1705 strcmp(sectname
, "__protocol") == 0 && vflag
== TRUE
){
1706 print_objc_protocol_section(ofile
->load_commands
, mh_ncmds
,
1707 mh_sizeofcmds
, ofile
->object_byte_sex
, ofile
->object_addr
,
1708 ofile
->object_size
, vflag
);
1710 else if(strcmp(segname
, SEG_OBJC
) == 0 &&
1711 (strcmp(sectname
, "__string_object") == 0 ||
1712 strcmp(sectname
, "__cstring_object") == 0) &&
1714 if(mh_cputype
& CPU_ARCH_ABI64
)
1715 print_objc_string_object_section_64(sectname
,
1716 ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1717 ofile
->object_byte_sex
, ofile
->object_addr
,
1718 ofile
->object_size
, mh_cputype
, symbols64
, nsymbols
,
1719 strings
, strings_size
, sorted_symbols
, nsorted_symbols
,
1722 print_objc_string_object_section(sectname
,
1723 ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1724 ofile
->object_byte_sex
, ofile
->object_addr
,
1725 ofile
->object_size
, vflag
);
1727 else if(strcmp(segname
, SEG_OBJC
) == 0 &&
1728 strcmp(sectname
, "__runtime_setup") == 0 && vflag
== TRUE
){
1729 print_objc_runtime_setup_section(ofile
->load_commands
, mh_ncmds
,
1730 mh_sizeofcmds
, ofile
->object_byte_sex
, ofile
->object_addr
,
1731 ofile
->object_size
, vflag
);
1733 else if(strcmp(segname
, "__LLVM") == 0 &&
1734 strcmp(sectname
, "__bundle") == 0 &&
1735 (vflag
== TRUE
|| Vflag
== TRUE
) &&
1736 get_sect_info(segname
, sectname
, ofile
->load_commands
,
1737 mh_ncmds
, mh_sizeofcmds
, mh_filetype
, ofile
->object_byte_sex
,
1738 addr
, size
, §
, §_size
, §_addr
, §_relocs
,
1739 §_nrelocs
, §_flags
, &seg_addr
) == TRUE
){
1740 print_bitcode_section(sect
, sect_size
, vflag
, Vflag
, aflag
,
1744 else if(strcmp(segname
, "__RELOC") == 0 &&
1745 strcmp(sectname
, "__reloc") == 0 && vflag
== TRUE
){
1746 print_coff_reloc_section(ofile
->load_commands
, mh_ncmds
,
1747 mh_sizeofcmds
, mh_filetype
, ofile
->object_byte_sex
,
1748 ofile
->object_addr
, ofile
->object_size
, vflag
);
1751 else if(get_sect_info(segname
, sectname
, ofile
->load_commands
,
1752 mh_ncmds
, mh_sizeofcmds
, mh_filetype
, ofile
->object_byte_sex
,
1753 addr
, size
, §
, §_size
, §_addr
,
1754 §_relocs
, §_nrelocs
, §_flags
, &seg_addr
) == TRUE
){
1757 printf("Contents of (%.16s,%.16s) section\n", segname
,
1761 switch((sect_flags
& SECTION_TYPE
)){
1763 print_sect(mh_cputype
, ofile
->object_byte_sex
,
1764 sect
, sect_size
, sect_addr
);
1767 printf("zerofill section and has no contents in the "
1770 case S_CSTRING_LITERALS
:
1771 print_cstring_section(mh_cputype
, sect
, sect_size
,
1773 Xflag
== TRUE
? FALSE
: TRUE
);
1775 case S_4BYTE_LITERALS
:
1776 print_literal4_section(mh_cputype
, sect
, sect_size
,
1778 ofile
->object_byte_sex
,
1779 Xflag
== TRUE
? FALSE
: TRUE
);
1781 case S_8BYTE_LITERALS
:
1782 print_literal8_section(mh_cputype
, sect
, sect_size
,
1784 ofile
->object_byte_sex
,
1785 Xflag
== TRUE
? FALSE
: TRUE
);
1787 case S_16BYTE_LITERALS
:
1788 print_literal16_section(mh_cputype
, sect
, sect_size
,
1790 ofile
->object_byte_sex
,
1791 Xflag
== TRUE
? FALSE
: TRUE
);
1793 case S_LITERAL_POINTERS
:
1794 /* create aligned, sorted relocations entries */
1795 nrelocs
= sect_nrelocs
;
1796 relocs
= allocate(nrelocs
*
1797 sizeof(struct relocation_info
));
1798 memcpy(relocs
, sect_relocs
, nrelocs
*
1799 sizeof(struct relocation_info
));
1800 if(ofile
->object_byte_sex
!= get_host_byte_sex())
1801 swap_relocation_info(relocs
, nrelocs
,
1802 get_host_byte_sex());
1803 qsort(relocs
, nrelocs
, sizeof(struct relocation_info
),
1804 (int (*)(const void *, const void *))rel_compare
);
1805 print_literal_pointer_section(mh_cputype
,
1806 ofile
->load_commands
, mh_ncmds
, mh_sizeofcmds
,
1807 ofile
->object_byte_sex
, addr
, size
, sect
,
1808 sect_size
, sect_addr
, symbols
, symbols64
,
1809 nsymbols
, strings
, strings_size
, relocs
,
1810 nrelocs
, Xflag
== TRUE
? FALSE
: TRUE
);
1815 case S_MOD_INIT_FUNC_POINTERS
:
1816 case S_MOD_TERM_FUNC_POINTERS
:
1817 print_init_term_pointer_section(mh_cputype
, sect
,
1818 sect_size
, sect_addr
, ofile
->object_byte_sex
,
1819 sorted_symbols
, nsorted_symbols
, Vflag
);
1823 printf("Unknown section type (0x%x)\n",
1824 (unsigned int)(sect_flags
& SECTION_TYPE
));
1825 print_sect(mh_cputype
, ofile
->object_byte_sex
, sect
,
1826 sect_size
, sect_addr
);
1831 if((sect_flags
& SECTION_TYPE
) == S_ZEROFILL
)
1832 printf("zerofill section and has no contents in the "
1835 print_sect(mh_cputype
, ofile
->object_byte_sex
, sect
,
1836 sect_size
, sect_addr
);
1842 print_argstrings(mh_magic
, ofile
->load_commands
, mh_ncmds
,
1843 mh_sizeofcmds
, mh_cputype
, mh_cpusubtype
,
1844 ofile
->object_byte_sex
, ofile
->object_addr
,
1845 ofile
->object_size
);
1848 if(mh_cputype
& CPU_ARCH_ABI64
){
1849 get_linked_reloc_info(ofile
->load_commands
, mh_ncmds
,
1850 mh_sizeofcmds
, ofile
->object_byte_sex
,
1851 ofile
->object_addr
, ofile
->object_size
, &ext_relocs
,
1852 &next_relocs
, &loc_relocs
, &nloc_relocs
);
1853 /* create aligned relocations entries as needed */
1856 if((intptr_t)ext_relocs
% sizeof(int32_t) != 0 ||
1857 ofile
->object_byte_sex
!= get_host_byte_sex()){
1858 relocs
= allocate(next_relocs
*
1859 sizeof(struct relocation_info
));
1860 memcpy(relocs
, ext_relocs
, next_relocs
*
1861 sizeof(struct relocation_info
));
1862 ext_relocs
= relocs
;
1864 if((intptr_t)loc_relocs
% sizeof(int32_t) != 0 ||
1865 ofile
->object_byte_sex
!= get_host_byte_sex()){
1866 relocs
= allocate(nloc_relocs
*
1867 sizeof(struct relocation_info
));
1868 memcpy(relocs
, loc_relocs
, nloc_relocs
*
1869 sizeof(struct relocation_info
));
1870 loc_relocs
= relocs
;
1872 if(ofile
->object_byte_sex
!= get_host_byte_sex()){
1873 swap_relocation_info(ext_relocs
, next_relocs
,
1874 get_host_byte_sex());
1875 swap_relocation_info(loc_relocs
, nloc_relocs
,
1876 get_host_byte_sex());
1878 setup_dyld_bind_info(ofile
->load_commands
, mh_ncmds
,
1879 mh_sizeofcmds
, ofile
->object_byte_sex
,
1880 ofile
->object_addr
, ofile
->object_size
,
1882 print_objc2_64bit(mh_cputype
, ofile
->load_commands
, mh_ncmds
,
1883 mh_sizeofcmds
, ofile
->object_byte_sex
,
1884 ofile
->object_addr
, ofile
->object_size
, symbols64
,
1885 nsymbols
, strings
, strings_size
, sorted_symbols
,
1886 nsorted_symbols
, ext_relocs
, next_relocs
,
1887 loc_relocs
, nloc_relocs
, dbi
, ndbi
, vflag
, Vflag
);
1889 else if(mh_cputype
== CPU_TYPE_ARM
){
1890 get_linked_reloc_info(ofile
->load_commands
, mh_ncmds
,
1891 mh_sizeofcmds
, ofile
->object_byte_sex
,
1892 ofile
->object_addr
, ofile
->object_size
, &ext_relocs
,
1893 &next_relocs
, &loc_relocs
, &nloc_relocs
);
1894 /* create aligned relocations entries as needed */
1897 if((intptr_t)ext_relocs
% sizeof(int32_t) != 0 ||
1898 ofile
->object_byte_sex
!= get_host_byte_sex()){
1899 relocs
= allocate(next_relocs
*
1900 sizeof(struct relocation_info
));
1901 memcpy(relocs
, ext_relocs
, next_relocs
*
1902 sizeof(struct relocation_info
));
1903 ext_relocs
= relocs
;
1905 if((intptr_t)loc_relocs
% sizeof(int32_t) != 0 ||
1906 ofile
->object_byte_sex
!= get_host_byte_sex()){
1907 relocs
= allocate(nloc_relocs
*
1908 sizeof(struct relocation_info
));
1909 memcpy(relocs
, loc_relocs
, nloc_relocs
*
1910 sizeof(struct relocation_info
));
1911 loc_relocs
= relocs
;
1913 if(ofile
->object_byte_sex
!= get_host_byte_sex()){
1914 swap_relocation_info(ext_relocs
, next_relocs
,
1915 get_host_byte_sex());
1916 swap_relocation_info(loc_relocs
, nloc_relocs
,
1917 get_host_byte_sex());
1919 print_objc2_32bit(mh_cputype
, ofile
->load_commands
, mh_ncmds
,
1920 mh_sizeofcmds
, ofile
->object_byte_sex
,
1921 ofile
->object_addr
, ofile
->object_size
, symbols
,
1922 nsymbols
, strings
, strings_size
, sorted_symbols
,
1923 nsorted_symbols
, ext_relocs
, next_relocs
,
1924 loc_relocs
, nloc_relocs
, vflag
);
1928 * This is the 32-bit non-arm cputype case. Which is normally
1929 * the first Objective-C ABI. But it may be the case of a
1930 * binary for the iOS simulator which is the second Objective-C
1931 * ABI. In that case print_objc_segment() will determine that
1934 if(print_objc_segment(mh_cputype
, ofile
->load_commands
,
1935 mh_ncmds
, mh_sizeofcmds
, ofile
->object_byte_sex
,
1936 ofile
->object_addr
, ofile
->object_size
, sorted_symbols
,
1937 nsorted_symbols
, vflag
) == FALSE
){
1938 get_linked_reloc_info(ofile
->load_commands
, mh_ncmds
,
1939 mh_sizeofcmds
, ofile
->object_byte_sex
,
1940 ofile
->object_addr
, ofile
->object_size
, &ext_relocs
,
1941 &next_relocs
, &loc_relocs
, &nloc_relocs
);
1942 /* create aligned relocations entries as needed */
1945 if((intptr_t)ext_relocs
% sizeof(int32_t) != 0 ||
1946 ofile
->object_byte_sex
!= get_host_byte_sex()){
1947 relocs
= allocate(next_relocs
*
1948 sizeof(struct relocation_info
));
1949 memcpy(relocs
, ext_relocs
, next_relocs
*
1950 sizeof(struct relocation_info
));
1951 ext_relocs
= relocs
;
1953 if((intptr_t)loc_relocs
% sizeof(int32_t) != 0 ||
1954 ofile
->object_byte_sex
!= get_host_byte_sex()){
1955 relocs
= allocate(nloc_relocs
*
1956 sizeof(struct relocation_info
));
1957 memcpy(relocs
, loc_relocs
, nloc_relocs
*
1958 sizeof(struct relocation_info
));
1959 loc_relocs
= relocs
;
1961 if(ofile
->object_byte_sex
!= get_host_byte_sex()){
1962 swap_relocation_info(ext_relocs
, next_relocs
,
1963 get_host_byte_sex());
1964 swap_relocation_info(loc_relocs
, nloc_relocs
,
1965 get_host_byte_sex());
1967 print_objc2_32bit(mh_cputype
, ofile
->load_commands
,
1968 mh_ncmds
, mh_sizeofcmds
, ofile
->object_byte_sex
,
1969 ofile
->object_addr
, ofile
->object_size
, symbols
,
1970 nsymbols
, strings
, strings_size
, sorted_symbols
,
1971 nsorted_symbols
, ext_relocs
, next_relocs
,
1972 loc_relocs
, nloc_relocs
, vflag
);
1977 if(load_commands
!= NULL
)
1978 free(load_commands
);
1979 if(allocated_symbols
!= NULL
)
1980 free(allocated_symbols
);
1981 if(sorted_symbols
!= NULL
)
1982 free(sorted_symbols
);
1983 if(allocated_indirect_symbols
!= NULL
)
1984 free(allocated_indirect_symbols
);
1985 if(allocated_hints
!= NULL
)
1986 free(allocated_hints
);
1987 if(allocated_dices
!= NULL
)
1988 free(allocated_dices
);
1989 if(allocated_tocs
!= NULL
)
1990 free(allocated_tocs
);
1991 if(allocated_mods
!= NULL
)
1992 free(allocated_mods
);
1993 if(allocated_refs
!= NULL
)
1994 free(allocated_refs
);
2000 * get_symbol_table_info() returns pointers to the symbol table and string
2001 * table as well as the number of symbols and size of the string table.
2002 * This routine handles the problems related to the file being truncated and
2003 * only returns valid pointers and sizes that can be used. This routine will
2004 * return pointers that are misaligned and it is up to the caller to deal with
2005 * alignment issues. It is also up to the caller to deal with byte sex of the
2010 get_symbol_table_info(
2011 struct load_command
*load_commands
, /* input */
2013 uint32_t sizeofcmds
,
2015 enum byte_sex load_commands_byte_sex
,
2017 uint32_t object_size
,
2018 struct nlist
**symbols
, /* output */
2019 struct nlist_64
**symbols64
,
2022 uint32_t *strings_size
)
2024 enum byte_sex host_byte_sex
;
2026 uint32_t i
, left
, size
, st_cmd
;
2027 struct load_command
*lc
, l
;
2028 struct symtab_command st
;
2037 host_byte_sex
= get_host_byte_sex();
2038 swapped
= host_byte_sex
!= load_commands_byte_sex
;
2042 memset((char *)&st
, '\0', sizeof(struct symtab_command
));
2043 for(i
= 0 ; i
< ncmds
; i
++){
2044 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
2046 swap_load_command(&l
, host_byte_sex
);
2047 if(l
.cmdsize
% sizeof(int32_t) != 0)
2048 printf("load command %u size not a multiple of "
2049 "sizeof(int32_t)\n", i
);
2050 if((char *)lc
+ l
.cmdsize
>
2051 (char *)load_commands
+ sizeofcmds
)
2052 printf("load command %u extends past end of load "
2054 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
2058 if(st_cmd
!= UINT_MAX
){
2059 printf("more than one LC_SYMTAB command (using command %u)"
2063 size
= left
< sizeof(struct symtab_command
) ?
2064 left
: sizeof(struct symtab_command
);
2065 memcpy((char *)&st
, (char *)lc
, size
);
2067 swap_symtab_command(&st
, host_byte_sex
);
2071 printf("load command %u size zero (can't advance to other "
2072 "load commands)\n", i
);
2075 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
2076 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2079 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
)
2080 printf("Inconsistent sizeofcmds\n");
2082 if(st_cmd
== UINT_MAX
){
2086 if(st
.symoff
>= object_size
){
2087 printf("symbol table offset is past end of file\n");
2090 if(cputype
& CPU_ARCH_ABI64
){
2091 *symbols64
= (struct nlist_64
*)(object_addr
+ st
.symoff
);
2093 bigsize
*= sizeof(struct nlist_64
);
2094 bigsize
+= st
.symoff
;
2095 if(bigsize
> object_size
){
2096 printf("symbol table extends past end of file\n");
2097 *nsymbols
= (object_size
- st
.symoff
) /
2098 sizeof(struct nlist_64
);
2101 *nsymbols
= st
.nsyms
;
2104 *symbols
= (struct nlist
*)(object_addr
+ st
.symoff
);
2106 bigsize
*= sizeof(struct nlist
);
2107 bigsize
+= st
.symoff
;
2108 if(bigsize
> object_size
){
2109 printf("symbol table extends past end of file\n");
2110 *nsymbols
= (object_size
- st
.symoff
) /
2111 sizeof(struct nlist
);
2114 *nsymbols
= st
.nsyms
;
2118 if(st
.stroff
>= object_size
){
2119 printf("string table offset is past end of file\n");
2122 *strings
= object_addr
+ st
.stroff
;
2123 bigsize
= st
.stroff
;
2124 bigsize
+= st
.strsize
;
2125 if(bigsize
> object_size
){
2126 printf("string table extends past end of file\n");
2129 *strings_size
= st
.strsize
;
2134 * get_toc_info() returns a pointer and the size of the table of contents.
2135 * This routine handles the problems related to the file being truncated and
2136 * only returns valid pointers and sizes that can be used. This routine will
2137 * return pointers that are misaligned and it is up to the caller to deal with
2138 * alignment issues. It is also up to the caller to deal with byte sex of the
2144 struct load_command
*load_commands
,
2146 uint32_t sizeofcmds
,
2147 enum byte_sex load_commands_byte_sex
,
2149 uint32_t object_size
,
2150 struct dylib_table_of_contents
**tocs
, /* output */
2153 struct dysymtab_command dyst
;
2159 if(get_dyst(load_commands
, ncmds
, sizeofcmds
, load_commands_byte_sex
,
2163 if(dyst
.tocoff
>= object_size
){
2164 printf("table of contents offset is past end of file\n");
2167 *tocs
= (struct dylib_table_of_contents
*)(object_addr
+
2169 bigsize
= dyst
.ntoc
;
2170 bigsize
*= sizeof(struct dylib_table_of_contents
);
2171 bigsize
+= dyst
.tocoff
;
2172 if(bigsize
> object_size
){
2173 printf("table of contents extends past end of file\n");
2174 *ntocs
= (object_size
- dyst
.tocoff
) /
2175 sizeof(struct dylib_table_of_contents
);
2183 * get_module_table_info() returns a pointer and the size of the
2184 * module table. This routine handles the problems related to the file being
2185 * truncated and only returns valid pointers and sizes that can be used. This
2186 * routine will return pointers that are misaligned and it is up to the caller
2187 * to deal with alignment issues. It is also up to the caller to deal with
2188 * byte sex of the table.
2192 get_module_table_info(
2193 struct load_command
*load_commands
,
2195 uint32_t sizeofcmds
,
2197 enum byte_sex load_commands_byte_sex
,
2199 uint32_t object_size
,
2200 struct dylib_module
**mods
, /* output */
2201 struct dylib_module_64
**mods64
,
2204 struct dysymtab_command dyst
;
2211 if(get_dyst(load_commands
, ncmds
, sizeofcmds
, load_commands_byte_sex
,
2215 if(dyst
.modtaboff
>= object_size
){
2216 printf("module table offset is past end of file\n");
2219 if(cputype
& CPU_ARCH_ABI64
){
2220 *mods64
= (struct dylib_module_64
*)(object_addr
+
2222 bigsize
= dyst
.nmodtab
;
2223 bigsize
*= sizeof(struct dylib_module_64
);
2224 bigsize
+= dyst
.modtaboff
;
2225 if(bigsize
> object_size
){
2226 printf("module table extends past end of file\n");
2227 *nmods
= (object_size
- dyst
.modtaboff
) /
2228 sizeof(struct dylib_module_64
);
2231 *nmods
= dyst
.nmodtab
;
2234 *mods
= (struct dylib_module
*)(object_addr
+ dyst
.modtaboff
);
2236 dyst
.nmodtab
* sizeof(struct dylib_module
) > object_size
){
2237 printf("module table extends past end of file\n");
2238 *nmods
= (object_size
- dyst
.modtaboff
) /
2239 sizeof(struct dylib_module
);
2242 *nmods
= dyst
.nmodtab
;
2248 * get_ref_info() returns a pointer and the size of the reference table.
2249 * This routine handles the problems related to the file being truncated and
2250 * only returns valid pointers and sizes that can be used. This routine will
2251 * return pointers that are misaligned and it is up to the caller to deal with
2252 * alignment issues. It is also up to the caller to deal with byte sex of the
2258 struct load_command
*load_commands
,
2260 uint32_t sizeofcmds
,
2261 enum byte_sex load_commands_byte_sex
,
2263 uint32_t object_size
,
2264 struct dylib_reference
**refs
, /* output */
2267 struct dysymtab_command dyst
;
2273 if(get_dyst(load_commands
, ncmds
, sizeofcmds
, load_commands_byte_sex
,
2277 if(dyst
.extrefsymoff
>= object_size
){
2278 printf("reference table offset is past end of file\n");
2281 *refs
= (struct dylib_reference
*)(object_addr
+ dyst
.extrefsymoff
);
2282 bigsize
= dyst
.nextrefsyms
;
2283 bigsize
*= sizeof(struct dylib_reference
);
2284 bigsize
+= dyst
.extrefsymoff
;
2285 if(bigsize
> object_size
){
2286 printf("reference table extends past end of file\n");
2287 *nrefs
= (object_size
- dyst
.extrefsymoff
) /
2288 sizeof(struct dylib_reference
);
2291 *nrefs
= dyst
.nextrefsyms
;
2296 * get_indirect_symbol_table_info() returns a pointer and the size of the
2297 * indirect symbol table. This routine handles the problems related to the
2298 * file being truncated and only returns valid pointers and sizes that can be
2299 * used. This routine will return pointers that are misaligned and it is up to
2300 * the caller to deal with alignment issues. It is also up to the caller to
2301 * deal with byte sex of the table.
2305 get_indirect_symbol_table_info(
2306 struct load_command
*load_commands
,
2308 uint32_t sizeofcmds
,
2309 enum byte_sex load_commands_byte_sex
,
2311 uint32_t object_size
,
2312 uint32_t **indirect_symbols
, /* output */
2313 uint32_t *nindirect_symbols
)
2315 struct dysymtab_command dyst
;
2318 *indirect_symbols
= NULL
;
2319 *nindirect_symbols
= 0;
2321 if(get_dyst(load_commands
, ncmds
, sizeofcmds
, load_commands_byte_sex
,
2325 if(dyst
.indirectsymoff
>= object_size
){
2326 printf("indirect symbol table offset is past end of file\n");
2329 *indirect_symbols
= (uint32_t *)(object_addr
+ dyst
.indirectsymoff
);
2330 bigsize
= dyst
.nindirectsyms
;
2331 bigsize
*= sizeof(uint32_t);
2332 bigsize
+= dyst
.indirectsymoff
;
2333 if(bigsize
> object_size
){
2334 printf("indirect symbol table extends past end of file\n");
2335 *nindirect_symbols
= (object_size
- dyst
.indirectsymoff
) /
2339 *nindirect_symbols
= dyst
.nindirectsyms
;
2344 * get_dyst() gets the dysymtab_command from the mach header and load commands
2345 * passed to it and copys it into dyst. It if doesn't find one it returns FALSE
2346 * else it returns TRUE.
2351 struct load_command
*load_commands
,
2353 uint32_t sizeofcmds
,
2354 enum byte_sex load_commands_byte_sex
,
2355 struct dysymtab_command
*dyst
)
2357 enum byte_sex host_byte_sex
;
2359 uint32_t i
, left
, size
, dyst_cmd
;
2360 struct load_command
*lc
, l
;
2362 host_byte_sex
= get_host_byte_sex();
2363 swapped
= host_byte_sex
!= load_commands_byte_sex
;
2365 dyst_cmd
= UINT_MAX
;
2367 for(i
= 0 ; i
< ncmds
; i
++){
2368 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
2370 swap_load_command(&l
, host_byte_sex
);
2371 if(l
.cmdsize
% sizeof(int32_t) != 0)
2372 printf("load command %u size not a multiple of "
2373 "sizeof(int32_t)\n", i
);
2374 if((char *)lc
+ l
.cmdsize
>
2375 (char *)load_commands
+ sizeofcmds
)
2376 printf("load command %u extends past end of load "
2378 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
2382 if(dyst_cmd
!= UINT_MAX
){
2383 printf("more than one LC_DYSYMTAB command (using command "
2387 memset((char *)dyst
, '\0', sizeof(struct dysymtab_command
));
2388 size
= left
< sizeof(struct dysymtab_command
) ?
2389 left
: sizeof(struct dysymtab_command
);
2390 memcpy((char *)dyst
, (char *)lc
, size
);
2392 swap_dysymtab_command(dyst
, host_byte_sex
);
2396 printf("load command %u size zero (can't advance to other "
2397 "load commands)\n", i
);
2400 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
2401 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2404 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
)
2405 printf("Inconsistent sizeofcmds\n");
2407 if(dyst_cmd
== UINT_MAX
){
2414 * get_hints_table_info() returns a pointer and the size of the two-level hints
2415 * table. This routine handles the problems related to the file being truncated
2416 * and only returns valid pointers and sizes that can be used. This routine
2417 * will return pointers that are misaligned and it is up to the caller to deal
2418 * with alignment issues. It is also up to the caller to deal with byte sex of
2423 get_hints_table_info(
2424 struct load_command
*load_commands
,
2426 uint32_t sizeofcmds
,
2427 enum byte_sex load_commands_byte_sex
,
2429 uint32_t object_size
,
2430 struct twolevel_hint
**hints
, /* output */
2433 struct twolevel_hints_command hints_cmd
;
2439 memset(&hints_cmd
, '\0', sizeof(struct twolevel_hints_command
));
2440 if(get_hints_cmd(load_commands
, ncmds
, sizeofcmds
,
2441 load_commands_byte_sex
, &hints_cmd
) == FALSE
)
2444 if(hints_cmd
.offset
>= object_size
){
2445 printf("two-level hints offset is past end of file\n");
2448 *hints
= (struct twolevel_hint
*)(object_addr
+ hints_cmd
.offset
);
2449 bigsize
= hints_cmd
.nhints
;
2450 bigsize
*= sizeof(struct twolevel_hint
);
2451 bigsize
+= hints_cmd
.offset
;
2452 if(bigsize
> object_size
){
2453 printf("two-level hints table extends past end of file\n");
2454 *nhints
= (object_size
- hints_cmd
.offset
) /
2455 sizeof(struct twolevel_hint
);
2458 *nhints
= hints_cmd
.nhints
;
2463 * get_hints_cmd() gets the twolevel_hints_command from the mach header and
2464 * load commands passed to it and copys it into hints_cmd. It if doesn't find
2465 * one it returns FALSE else it returns TRUE.
2470 struct load_command
*load_commands
,
2472 uint32_t sizeofcmds
,
2473 enum byte_sex load_commands_byte_sex
,
2474 struct twolevel_hints_command
*hints_cmd
)
2476 enum byte_sex host_byte_sex
;
2478 uint32_t i
, left
, size
, cmd
;
2479 struct load_command
*lc
, l
;
2481 host_byte_sex
= get_host_byte_sex();
2482 swapped
= host_byte_sex
!= load_commands_byte_sex
;
2486 for(i
= 0 ; i
< ncmds
; i
++){
2487 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
2489 swap_load_command(&l
, host_byte_sex
);
2490 if(l
.cmdsize
% sizeof(int32_t) != 0)
2491 printf("load command %u size not a multiple of "
2492 "sizeof(int32_t)\n", i
);
2493 if((char *)lc
+ l
.cmdsize
>
2494 (char *)load_commands
+ sizeofcmds
)
2495 printf("load command %u extends past end of load "
2497 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
2500 case LC_TWOLEVEL_HINTS
:
2501 if(cmd
!= UINT_MAX
){
2502 printf("more than one LC_TWOLEVEL_HINTS command (using "
2503 "command %u)\n", cmd
);
2506 memset((char *)hints_cmd
, '\0',
2507 sizeof(struct twolevel_hints_command
));
2508 size
= left
< sizeof(struct twolevel_hints_command
) ?
2509 left
: sizeof(struct twolevel_hints_command
);
2510 memcpy((char *)hints_cmd
, (char *)lc
, size
);
2512 swap_twolevel_hints_command(hints_cmd
, host_byte_sex
);
2516 printf("load command %u size zero (can't advance to other "
2517 "load commands)\n", i
);
2520 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
2521 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2524 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
)
2525 printf("Inconsistent sizeofcmds\n");
2527 if(cmd
== UINT_MAX
){
2534 * get_link_opt_hints() returns a pointer and the size of the linker
2535 * optimization hints table. This routine handles the problems related to the
2536 * file being truncated and only returns valid pointers and sizes that can be
2542 struct load_command
*load_commands
,
2544 uint32_t sizeofcmds
,
2545 enum byte_sex load_commands_byte_sex
,
2547 uint32_t object_size
,
2551 struct linkedit_data_command loh_cmd
;
2557 memset(&loh_cmd
, '\0', sizeof(struct linkedit_data_command
));
2558 if(get_link_opt_hint_cmd(load_commands
, ncmds
, sizeofcmds
,
2559 load_commands_byte_sex
, &loh_cmd
) == FALSE
)
2562 if(loh_cmd
.dataoff
>= object_size
){
2563 printf("linker optimization hints offset is past end of file\n");
2566 *loh
= object_addr
+ loh_cmd
.dataoff
;
2567 bigsize
= loh_cmd
.dataoff
;
2568 bigsize
+= loh_cmd
.datasize
;
2569 if(bigsize
> object_size
){
2570 printf("linker optimization hints extends past end of file\n");
2571 *nloh
= object_size
- loh_cmd
.dataoff
;
2574 *nloh
= loh_cmd
.datasize
;
2579 * get_link_opt_hint_cmd() gets the linker optimization hint command from the
2580 * mach header and load commands passed to it and copys it into loh_cmd. It if
2581 * doesn't find one it returns FALSE else it returns TRUE.
2585 get_link_opt_hint_cmd(
2586 struct load_command
*load_commands
,
2588 uint32_t sizeofcmds
,
2589 enum byte_sex load_commands_byte_sex
,
2590 struct linkedit_data_command
*loh_cmd
)
2592 enum byte_sex host_byte_sex
;
2594 uint32_t i
, left
, size
, cmd
;
2595 struct load_command
*lc
, l
;
2597 host_byte_sex
= get_host_byte_sex();
2598 swapped
= host_byte_sex
!= load_commands_byte_sex
;
2602 for(i
= 0 ; i
< ncmds
; i
++){
2603 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
2605 swap_load_command(&l
, host_byte_sex
);
2606 if(l
.cmdsize
% sizeof(int32_t) != 0)
2607 printf("load command %u size not a multiple of "
2608 "sizeof(int32_t)\n", i
);
2609 if((char *)lc
+ l
.cmdsize
>
2610 (char *)load_commands
+ sizeofcmds
)
2611 printf("load command %u extends past end of load "
2613 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
2616 case LC_LINKER_OPTIMIZATION_HINT
:
2617 if(cmd
!= UINT_MAX
){
2618 printf("more than one LC_LINKER_OPTIMIZATION_HINT command "
2619 "(using command %u)\n", cmd
);
2622 memset((char *)loh_cmd
, '\0',
2623 sizeof(struct linkedit_data_command
));
2624 size
= left
< sizeof(struct linkedit_data_command
) ?
2625 left
: sizeof(struct linkedit_data_command
);
2626 memcpy((char *)loh_cmd
, (char *)lc
, size
);
2628 swap_linkedit_data_command(loh_cmd
, host_byte_sex
);
2632 printf("load command %u size zero (can't advance to other "
2633 "load commands)\n", i
);
2636 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
2637 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2640 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
)
2641 printf("Inconsistent sizeofcmds\n");
2643 if(cmd
== UINT_MAX
){
2650 * get_data_in_code_info() returns a pointer and the size of the data in code
2651 * table. This routine handles the problems related to the file being truncated
2652 * and only returns valid pointers and sizes that can be used. This routine
2653 * will return pointers that are misaligned and it is up to the caller to deal
2654 * with alignment issues. It is also up to the caller to deal with byte sex of
2659 get_data_in_code_info(
2660 struct load_command
*load_commands
,
2662 uint32_t sizeofcmds
,
2663 enum byte_sex load_commands_byte_sex
,
2665 uint32_t object_size
,
2666 struct data_in_code_entry
**dices
, /* output */
2669 struct linkedit_data_command dices_cmd
;
2675 memset(&dices_cmd
, '\0', sizeof(struct linkedit_data_command
));
2676 if(get_dices_cmd(load_commands
, ncmds
, sizeofcmds
,
2677 load_commands_byte_sex
, &dices_cmd
) == FALSE
)
2680 if(dices_cmd
.dataoff
>= object_size
){
2681 printf("data in code offset is past end of file\n");
2684 *dices
= (struct data_in_code_entry
*)
2685 (object_addr
+ dices_cmd
.dataoff
);
2686 bigsize
= dices_cmd
.datasize
;
2687 bigsize
+= dices_cmd
.dataoff
;
2688 if(bigsize
> object_size
){
2689 printf("data in code table extends past end of file\n");
2690 *ndices
= (object_size
- dices_cmd
.dataoff
) /
2691 sizeof(struct data_in_code_entry
);
2694 *ndices
= dices_cmd
.datasize
/
2695 sizeof(struct data_in_code_entry
);
2700 * get_dices_cmd() gets the linkedit_data_command for the data in code from the
2701 * mach header and load commands passed to it and copys it into dices_cmd. It
2702 * if doesn't find one it returns FALSE else it returns TRUE.
2707 struct load_command
*load_commands
,
2709 uint32_t sizeofcmds
,
2710 enum byte_sex load_commands_byte_sex
,
2711 struct linkedit_data_command
*dices_cmd
)
2713 enum byte_sex host_byte_sex
;
2715 uint32_t i
, left
, size
, cmd
;
2716 struct load_command
*lc
, l
;
2718 host_byte_sex
= get_host_byte_sex();
2719 swapped
= host_byte_sex
!= load_commands_byte_sex
;
2723 for(i
= 0 ; i
< ncmds
; i
++){
2724 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
2726 swap_load_command(&l
, host_byte_sex
);
2727 if(l
.cmdsize
% sizeof(int32_t) != 0)
2728 printf("load command %u size not a multiple of "
2729 "sizeof(int32_t)\n", i
);
2730 if((char *)lc
+ l
.cmdsize
>
2731 (char *)load_commands
+ sizeofcmds
)
2732 printf("load command %u extends past end of load "
2734 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
2737 case LC_DATA_IN_CODE
:
2738 if(cmd
!= UINT_MAX
){
2739 printf("more than one LC_DATA_IN_CODE command (using "
2740 "command %u)\n", cmd
);
2743 memset((char *)dices_cmd
, '\0',
2744 sizeof(struct linkedit_data_command
));
2745 size
= left
< sizeof(struct linkedit_data_command
) ?
2746 left
: sizeof(struct linkedit_data_command
);
2747 memcpy((char *)dices_cmd
, (char *)lc
, size
);
2749 swap_linkedit_data_command(dices_cmd
, host_byte_sex
);
2753 printf("load command %u size zero (can't advance to other "
2754 "load commands)\n", i
);
2757 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
2758 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2761 if((char *)load_commands
+ sizeofcmds
!= (char *)lc
)
2762 printf("Inconsistent sizeofcmds\n");
2764 if(cmd
== UINT_MAX
){
2771 * Function for qsort for comparing symbols.
2776 struct symbol
*sym1
,
2777 struct symbol
*sym2
)
2779 if(sym1
->n_value
== sym2
->n_value
)
2781 if(sym1
->n_value
< sym2
->n_value
)
2788 * Function for qsort for comparing relocation entries.
2793 struct relocation_info
*rel1
,
2794 struct relocation_info
*rel2
)
2796 struct scattered_relocation_info
*srel
;
2797 uint32_t r_address1
, r_address2
;
2799 if((rel1
->r_address
& R_SCATTERED
) != 0){
2800 srel
= (struct scattered_relocation_info
*)rel1
;
2801 r_address1
= srel
->r_address
;
2804 r_address1
= rel1
->r_address
;
2805 if((rel2
->r_address
& R_SCATTERED
) != 0){
2806 srel
= (struct scattered_relocation_info
*)rel2
;
2807 r_address2
= srel
->r_address
;
2810 r_address2
= rel2
->r_address
;
2812 if(r_address1
== r_address2
)
2814 if(r_address1
< r_address2
)
2822 char *segname
, /* input */
2824 struct load_command
*load_commands
,
2826 uint32_t sizeofcmds
,
2828 enum byte_sex load_commands_byte_sex
,
2830 uint32_t object_size
,
2831 char **sect_pointer
, /* output */
2832 uint64_t *sect_size
,
2833 uint64_t *sect_addr
,
2834 struct relocation_info
**sect_relocs
,
2835 uint32_t *sect_nrelocs
,
2836 uint32_t *sect_flags
,
2839 enum byte_sex host_byte_sex
;
2840 enum bool found
, swapped
;
2841 uint32_t i
, j
, left
, size
;
2842 struct load_command
*lc
, l
;
2844 struct segment_command sg
;
2845 struct segment_command_64 sg64
;
2847 struct section_64 s64
;
2850 *sect_pointer
= NULL
;
2853 *sect_relocs
= NULL
;
2859 host_byte_sex
= get_host_byte_sex();
2860 swapped
= host_byte_sex
!= load_commands_byte_sex
;
2863 for(i
= 0 ; found
== FALSE
&& i
< ncmds
; i
++){
2864 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
2866 swap_load_command(&l
, host_byte_sex
);
2867 if(l
.cmdsize
% sizeof(int32_t) != 0)
2868 printf("load command %u size not a multiple of "
2869 "sizeof(int32_t)\n", i
);
2870 if((char *)lc
+ l
.cmdsize
>
2871 (char *)load_commands
+ sizeofcmds
)
2872 printf("load command %u extends past end of load "
2874 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
2878 memset((char *)&sg
, '\0', sizeof(struct segment_command
));
2879 size
= left
< sizeof(struct segment_command
) ?
2880 left
: sizeof(struct segment_command
);
2881 memcpy((char *)&sg
, (char *)lc
, size
);
2883 swap_segment_command(&sg
, host_byte_sex
);
2885 if((filetype
== MH_OBJECT
&& sg
.segname
[0] == '\0') ||
2886 strncmp(sg
.segname
, segname
, sizeof(sg
.segname
)) == 0){
2887 *seg_addr
= sg
.vmaddr
;
2888 p
= (char *)lc
+ sizeof(struct segment_command
);
2889 for(j
= 0 ; found
== FALSE
&& j
< sg
.nsects
; j
++){
2890 if(p
+ sizeof(struct section
) >
2891 (char *)load_commands
+ sizeofcmds
){
2892 printf("section structure command extends past "
2893 "end of load commands\n");
2895 left
= sizeofcmds
- (p
- (char *)load_commands
);
2896 memset((char *)&s
, '\0', sizeof(struct section
));
2897 size
= left
< sizeof(struct section
) ?
2898 left
: sizeof(struct section
);
2899 memcpy((char *)&s
, p
, size
);
2901 swap_section(&s
, 1, host_byte_sex
);
2903 if(strncmp(s
.sectname
, sectname
,
2904 sizeof(s
.sectname
)) == 0 &&
2905 strncmp(s
.segname
, segname
,
2906 sizeof(s
.segname
)) == 0){
2912 if(p
+ sizeof(struct section
) >
2913 (char *)load_commands
+ sizeofcmds
)
2920 memset((char *)&sg64
, '\0', sizeof(struct segment_command_64
));
2921 size
= left
< sizeof(struct segment_command_64
) ?
2922 left
: sizeof(struct segment_command_64
);
2923 memcpy((char *)&sg64
, (char *)lc
, size
);
2925 swap_segment_command_64(&sg64
, host_byte_sex
);
2927 if((filetype
== MH_OBJECT
&& sg64
.segname
[0] == '\0') ||
2928 strncmp(sg64
.segname
, segname
, sizeof(sg64
.segname
)) == 0){
2929 *seg_addr
= sg
.vmaddr
;
2930 p
= (char *)lc
+ sizeof(struct segment_command_64
);
2931 for(j
= 0 ; found
== FALSE
&& j
< sg64
.nsects
; j
++){
2932 if(p
+ sizeof(struct section_64
) >
2933 (char *)load_commands
+ sizeofcmds
){
2934 printf("section structure command extends past "
2935 "end of load commands\n");
2937 left
= sizeofcmds
- (p
- (char *)load_commands
);
2938 memset((char *)&s64
, '\0', sizeof(struct section_64
));
2939 size
= left
< sizeof(struct section_64
) ?
2940 left
: sizeof(struct section_64
);
2941 memcpy((char *)&s64
, p
, size
);
2943 swap_section_64(&s64
, 1, host_byte_sex
);
2945 if(strncmp(s64
.sectname
, sectname
,
2946 sizeof(s64
.sectname
)) == 0 &&
2947 strncmp(s64
.segname
, segname
,
2948 sizeof(s64
.segname
)) == 0){
2950 cmd
= LC_SEGMENT_64
;
2954 if(p
+ sizeof(struct section_64
) >
2955 (char *)load_commands
+ sizeofcmds
)
2963 printf("load command %u size zero (can't advance to other "
2964 "load commands)\n", i
);
2967 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
2968 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
2974 if(cmd
== LC_SEGMENT
){
2975 if((s
.flags
& SECTION_TYPE
) == S_ZEROFILL
){
2976 *sect_pointer
= NULL
;
2977 *sect_size
= s
.size
;
2980 if(s
.offset
> object_size
){
2981 printf("section offset for section (%.16s,%.16s) is past "
2982 "end of file\n", s
.segname
, s
.sectname
);
2985 *sect_pointer
= object_addr
+ s
.offset
;
2986 if(s
.size
> object_size
||
2987 s
.offset
+ s
.size
> object_size
){
2988 printf("section (%.16s,%.16s) extends past end of "
2989 "file\n", s
.segname
, s
.sectname
);
2990 *sect_size
= object_size
- s
.offset
;
2993 *sect_size
= s
.size
;
2996 if(s
.reloff
>= object_size
){
2997 printf("relocation entries offset for (%.16s,%.16s): is past "
2998 "end of file\n", s
.segname
, s
.sectname
);
3001 *sect_relocs
= (struct relocation_info
*)(object_addr
+
3003 if(s
.reloff
+ s
.nreloc
* sizeof(struct relocation_info
) >
3005 printf("relocation entries for section (%.16s,%.16s) "
3006 "extends past end of file\n", s
.segname
, s
.sectname
);
3007 *sect_nrelocs
= (object_size
- s
.reloff
) /
3008 sizeof(struct relocation_info
);
3011 *sect_nrelocs
= s
.nreloc
;
3013 *sect_addr
= s
.addr
;
3014 *sect_flags
= s
.flags
;
3017 if((s64
.flags
& SECTION_TYPE
) == S_ZEROFILL
){
3018 *sect_pointer
= NULL
;
3019 *sect_size
= s64
.size
;
3022 if(s64
.offset
> object_size
){
3023 printf("section offset for section (%.16s,%.16s) is past "
3024 "end of file\n", s64
.segname
, s64
.sectname
);
3027 *sect_pointer
= object_addr
+ s64
.offset
;
3028 if(s64
.size
> object_size
||
3029 s64
.offset
+ s64
.size
> object_size
){
3030 printf("section (%.16s,%.16s) extends past end of "
3031 "file\n", s64
.segname
, s64
.sectname
);
3034 *sect_size
= s64
.size
;
3037 if(s64
.reloff
>= object_size
){
3038 printf("relocation entries offset for (%.16s,%.16s): is past "
3039 "end of file\n", s64
.segname
, s64
.sectname
);
3042 *sect_relocs
= (struct relocation_info
*)(object_addr
+
3044 if(s64
.reloff
+ s64
.nreloc
* sizeof(struct relocation_info
) >
3046 printf("relocation entries for section (%.16s,%.16s) "
3047 "extends past end of file\n", s64
.segname
,
3049 *sect_nrelocs
= (object_size
- s64
.reloff
) /
3050 sizeof(struct relocation_info
);
3053 *sect_nrelocs
= s64
.nreloc
;
3055 *sect_addr
= s64
.addr
;
3056 *sect_flags
= s64
.flags
;
3063 get_linked_reloc_info(
3064 struct load_command
*load_commands
, /* input */
3066 uint32_t sizeofcmds
,
3067 enum byte_sex load_commands_byte_sex
,
3069 uint32_t object_size
,
3070 struct relocation_info
**ext_relocs
, /* output */
3071 uint32_t *next_relocs
,
3072 struct relocation_info
**loc_relocs
,
3073 uint32_t *nloc_relocs
)
3075 struct dysymtab_command dyst
;
3083 if(get_dyst(load_commands
, ncmds
, sizeofcmds
, load_commands_byte_sex
,
3087 if(dyst
.extreloff
>= object_size
){
3088 printf("external relocation entries offset is past end of file\n");
3091 *ext_relocs
= (struct relocation_info
*)(object_addr
+
3093 bigsize
= dyst
.nextrel
;
3094 bigsize
*= sizeof(struct relocation_info
);
3095 bigsize
+= dyst
.extreloff
;
3096 if(bigsize
> object_size
){
3097 printf("external relocation entries extend past end of file\n");
3098 *next_relocs
= (object_size
- dyst
.extreloff
) /
3099 sizeof(struct relocation_info
);
3102 *next_relocs
= dyst
.nextrel
;
3104 if(dyst
.locreloff
>= object_size
){
3105 printf("local relocation entries offset is past end of file\n");
3108 *loc_relocs
= (struct relocation_info
*)(object_addr
+
3110 bigsize
= dyst
.nlocrel
;
3111 bigsize
*= sizeof(struct relocation_info
);
3112 bigsize
+= dyst
.locreloff
;
3113 if(bigsize
> object_size
){
3114 printf("local relocation entries extend past end of file\n");
3115 *nloc_relocs
= (object_size
- dyst
.locreloff
) /
3116 sizeof(struct relocation_info
);
3119 *nloc_relocs
= dyst
.nlocrel
;
3124 * setup_dyld_bind_info() looks for a LC_DYLD_INFO load command and if it has
3125 * bind info unpacks it and returns it in dbi and ndbi values for the internal
3130 setup_dyld_bind_info(
3131 struct load_command
*load_commands
, /* input */
3133 uint32_t sizeofcmds
,
3134 enum byte_sex load_commands_byte_sex
,
3136 uint32_t object_size
,
3137 struct dyld_bind_info
**dbi
, /* output */
3140 enum byte_sex host_byte_sex
;
3141 enum bool swapped
, found_bind
;
3142 uint32_t pass
, i
, j
, left
, size
, nsegs
, nsegs64
, ndylibs
;
3144 struct load_command
*lc
, l
;
3145 struct dyld_info_command dyld_info
;
3146 struct dylib_command dl
;
3147 struct segment_command sg
, **segs
;
3148 struct segment_command_64 sg64
, **segs64
;
3150 struct section_64 s64
;
3151 char *short_name
, *has_suffix
;
3152 enum bool is_framework
;
3154 uint8_t *start
, *end
;
3155 const char **dylibs
;
3157 /* If already setup just return. */
3165 host_byte_sex
= get_host_byte_sex();
3166 swapped
= host_byte_sex
!= load_commands_byte_sex
;
3176 * Make two passes over the load commands. On the first pass count the
3177 * number of load commands for dylibs and segments and look for an
3178 * LC_DYLD_INFO load commands If we find the bind info allocate space
3179 * arrays of pointers to dylibs and segments and fill them in on the
3182 for(pass
= 1; pass
<= 2; pass
++){
3187 for(i
= 0 ; i
< ncmds
; i
++){
3188 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
3190 swap_load_command(&l
, host_byte_sex
);
3191 if(l
.cmdsize
% sizeof(int32_t) != 0)
3192 printf("load command %u size not a multiple of "
3193 "sizeof(int32_t)\n", i
);
3194 if((char *)lc
+ l
.cmdsize
>
3195 (char *)load_commands
+ sizeofcmds
)
3196 printf("load command %u extends past end of load "
3198 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
3203 case LC_DYLD_INFO_ONLY
:
3205 memset((char *)&dyld_info
, '\0',
3206 sizeof(struct dyld_info_command
));
3207 size
= left
< sizeof(struct dyld_info_command
) ?
3208 left
: sizeof(struct dyld_info_command
);
3209 memcpy((char *)&dyld_info
, (char *)lc
, size
);
3211 swap_dyld_info_command(&dyld_info
, host_byte_sex
);
3212 if(dyld_info
.bind_off
> object_size
){
3213 printf("bind_off in LC_DYLD_INFO load command %u "
3214 "past end of file\n", i
);
3217 big_size
= dyld_info
.bind_off
;
3218 big_size
+= dyld_info
.bind_size
;
3219 if(big_size
> object_size
){
3220 printf("bind_off plus bind_size in LC_DYLD_INFO "
3221 "load command %u past end of file\n", i
);
3224 if(found_bind
== TRUE
){
3225 printf("more than one LC_DYLD_INFO load command\n");
3233 case LC_LOAD_WEAK_DYLIB
:
3234 case LC_REEXPORT_DYLIB
:
3235 case LC_LOAD_UPWARD_DYLIB
:
3236 case LC_LAZY_LOAD_DYLIB
:
3241 memset((char *)&dl
, '\0', sizeof(struct dylib_command
));
3242 size
= left
< sizeof(struct dylib_command
) ?
3243 left
: sizeof(struct dylib_command
);
3244 memcpy((char *)&dl
, (char *)lc
, size
);
3246 swap_dylib_command(&dl
, host_byte_sex
);
3248 if(dl
.dylib
.name
.offset
< dl
.cmdsize
&&
3249 dl
.dylib
.name
.offset
< left
){
3250 p
= (char *)lc
+ dl
.dylib
.name
.offset
;
3251 short_name
= guess_short_name(p
,
3252 &is_framework
, &has_suffix
);
3255 p
= "(bad offset for dylib.name.offset)";
3256 if(short_name
!= NULL
)
3257 dylibs
[ndylibs
++] = short_name
;
3259 dylibs
[ndylibs
++] = p
;
3264 memset((char *)&sg
, '\0', sizeof(struct segment_command
));
3265 size
= left
< sizeof(struct segment_command
) ?
3266 left
: sizeof(struct segment_command
);
3267 memcpy((char *)&sg
, (char *)lc
, size
);
3269 swap_segment_command(&sg
, host_byte_sex
);
3271 a
= allocate(sizeof(struct segment_command
) +
3272 sg
.nsects
* sizeof(struct section
));
3273 memcpy(a
, (char *)&sg
,
3274 sizeof(struct segment_command
));
3276 (struct segment_command
*)a
;
3277 a
+= sizeof(struct segment_command
);
3280 p
= (char *)lc
+ sizeof(struct segment_command
);
3281 for(j
= 0 ; j
< sg
.nsects
; j
++){
3282 if(p
+ sizeof(struct section
) >
3283 (char *)load_commands
+ sizeofcmds
){
3284 printf("section structure command extends past "
3285 "end of load commands\n");
3288 left
= sizeofcmds
- (p
- (char *)load_commands
);
3289 memset((char *)&s
, '\0', sizeof(struct section
));
3290 size
= left
< sizeof(struct section
) ?
3291 left
: sizeof(struct section
);
3292 memcpy((char *)&s
, p
, size
);
3294 swap_section(&s
, 1, host_byte_sex
);
3296 memcpy(a
, (char *)&s
, sizeof(struct section
));
3297 a
+= sizeof(struct section
);
3299 if(p
+ sizeof(struct section
) >
3300 (char *)load_commands
+ sizeofcmds
)
3308 memset((char *)&sg64
, '\0',
3309 sizeof(struct segment_command_64
));
3310 size
= left
< sizeof(struct segment_command_64
) ?
3311 left
: sizeof(struct segment_command_64
);
3312 memcpy((char *)&sg64
, (char *)lc
, size
);
3314 swap_segment_command_64(&sg64
, host_byte_sex
);
3316 a
= allocate(sizeof(struct segment_command_64
) +
3317 sg64
.nsects
* sizeof(struct section_64
));
3318 memcpy(a
, (char *)&sg64
,
3319 sizeof(struct segment_command_64
));
3321 (struct segment_command_64
*)a
;
3322 a
+= sizeof(struct segment_command_64
);
3325 p
= (char *)lc
+ sizeof(struct segment_command_64
);
3326 for(j
= 0 ; j
< sg64
.nsects
; j
++){
3327 if(p
+ sizeof(struct section_64
) >
3328 (char *)load_commands
+ sizeofcmds
){
3329 printf("section structure command extends past "
3330 "end of load commands\n");
3332 left
= sizeofcmds
- (p
- (char *)load_commands
);
3333 memset((char *)&s64
, '\0', sizeof(struct section_64
));
3334 size
= left
< sizeof(struct section_64
) ?
3335 left
: sizeof(struct section_64
);
3336 memcpy((char *)&s64
, p
, size
);
3338 swap_section_64(&s64
, 1, host_byte_sex
);
3340 memcpy(a
, (char *)&s64
, sizeof(struct section_64
));
3341 a
+= sizeof(struct section_64
);
3343 if(p
+ sizeof(struct section_64
) >
3344 (char *)load_commands
+ sizeofcmds
)
3353 printf("load command %u size zero (can't advance to other "
3354 "load commands)\n", i
);
3357 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
3358 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
3361 if(found_bind
== FALSE
)
3364 dylibs
= (const char **)allocate(ndylibs
* sizeof(char *));
3365 segs
= (struct segment_command
**)allocate(
3366 nsegs
* sizeof(struct segment_command
*));
3367 segs64
= (struct segment_command_64
**)allocate(
3368 nsegs64
* sizeof(struct segment_command_64
*));
3372 start
= (uint8_t *)(object_addr
+ dyld_info
.bind_off
);
3373 end
= start
+ dyld_info
.bind_size
;
3374 get_dyld_bind_info(start
, end
, dylibs
, ndylibs
, segs
, nsegs
,
3375 segs64
, nsegs64
, dbi
, ndbi
);
3380 for(i
= 0; i
< nsegs
; i
++)
3385 for(i
= 0; i
< nsegs64
; i
++)
3393 print_text_by_symbols(
3395 enum byte_sex object_byte_sex
,
3399 uint32_t sect_flags
,
3400 struct symbol
*sorted_symbols
,
3401 uint32_t nsorted_symbols
,
3402 struct nlist
*symbols
,
3403 struct nlist_64
*symbols64
,
3406 uint32_t strings_size
,
3407 struct relocation_info
*relocs
,
3409 struct relocation_info
*ext_relocs
,
3410 uint32_t next_relocs
,
3411 struct relocation_info
*loc_relocs
,
3412 uint32_t nloc_relocs
,
3413 struct dyld_bind_info
*dbi
,
3415 uint32_t *indirect_symbols
,
3416 uint32_t nindirect_symbols
,
3417 struct load_command
*load_commands
,
3419 uint32_t sizeofcmds
,
3420 enum bool disassemble
,
3422 cpu_subtype_t cpusubtype
,
3424 uint32_t object_size
,
3425 struct data_in_code_entry
*dices
,
3429 uint32_t i
, symbol_size
;
3430 uint64_t symbol_addr
, symbol_offset
;
3432 for(i
= 0; i
< nsorted_symbols
; i
++){
3433 symbol_addr
= sorted_symbols
[i
].n_value
;
3434 if(symbol_addr
< addr
|| symbol_addr
>= addr
+ size
)
3436 symbol_offset
= symbol_addr
- addr
;
3437 if(i
+1 < nsorted_symbols
&&
3438 sorted_symbols
[i
+1].n_value
< addr
+ size
)
3439 symbol_size
= sorted_symbols
[i
+1].n_value
- symbol_addr
;
3441 symbol_size
= (addr
+ size
) - symbol_addr
;
3442 print_text(cputype
, object_byte_sex
, sect
+ symbol_offset
,
3443 symbol_size
, symbol_addr
, sect_flags
, sorted_symbols
,
3444 nsorted_symbols
, symbols
, symbols64
, nsymbols
, strings
,
3445 strings_size
, relocs
, nrelocs
, ext_relocs
, next_relocs
,
3446 loc_relocs
, nloc_relocs
, dbi
, ndbi
, indirect_symbols
,
3447 nindirect_symbols
, load_commands
, ncmds
, sizeofcmds
,
3448 disassemble
, verbose
, cpusubtype
, object_addr
,
3449 object_size
, dices
, ndices
, seg_addr
);
3457 enum byte_sex object_byte_sex
,
3461 uint32_t sect_flags
,
3462 struct symbol
*sorted_symbols
,
3463 uint32_t nsorted_symbols
,
3464 struct nlist
*symbols
,
3465 struct nlist_64
*symbols64
,
3468 uint32_t strings_size
,
3469 struct relocation_info
*relocs
,
3471 struct relocation_info
*ext_relocs
,
3472 uint32_t next_relocs
,
3473 struct relocation_info
*loc_relocs
,
3474 uint32_t nloc_relocs
,
3475 struct dyld_bind_info
*dbi
,
3477 uint32_t *indirect_symbols
,
3478 uint32_t nindirect_symbols
,
3479 struct load_command
*load_commands
,
3481 uint32_t sizeofcmds
,
3482 enum bool disassemble
,
3484 cpu_subtype_t cpusubtype
,
3486 uint32_t object_size
,
3487 struct data_in_code_entry
*dices
,
3491 enum byte_sex host_byte_sex
;
3493 uint32_t i
, j
, offset
, long_word
, label_offset
;
3495 unsigned short short_word
;
3496 unsigned char byte_word
;
3497 LLVMDisasmContextRef arm64_dc
;
3498 LLVMDisasmContextRef arm_dc
, thumb_dc
, i386_dc
, x86_64_dc
;
3503 host_byte_sex
= get_host_byte_sex();
3504 swapped
= host_byte_sex
!= object_byte_sex
;
3515 * If the section has a type of S_ZEROFILL then its section contents
3516 * pointer is NULL, so in this case just do nothing.
3521 if(disassemble
== TRUE
){
3523 for(i
= 0; i
< nsorted_symbols
; i
++){
3524 if(strcmp(sorted_symbols
[i
].name
, pflag
) == 0)
3527 if(i
== nsorted_symbols
){
3528 printf("Can't find -p symbol: %s\n", pflag
);
3531 if(sorted_symbols
[i
].n_value
< addr
||
3532 sorted_symbols
[i
].n_value
>= addr
+ size
){
3533 printf("-p symbol: %s not in text section\n", pflag
);
3536 offset
= sorted_symbols
[i
].n_value
- addr
;
3538 cur_addr
= sorted_symbols
[i
].n_value
;
3546 if(cputype
== CPU_TYPE_ARM
&&
3547 (cpusubtype
== CPU_SUBTYPE_ARM_V7
||
3548 cpusubtype
== CPU_SUBTYPE_ARM_V7F
||
3549 cpusubtype
== CPU_SUBTYPE_ARM_V7S
||
3550 cpusubtype
== CPU_SUBTYPE_ARM_V7K
)){
3551 if(sect_flags
& S_SYMBOL_STUBS
)
3558 if((qflag
|| gflag
) && cputype
== CPU_TYPE_ARM
){
3559 arm_dc
= create_arm_llvm_disassembler(cpusubtype
);
3561 printf("can't create arm llvm disassembler\n");
3564 thumb_dc
= create_thumb_llvm_disassembler(cpusubtype
);
3565 if(thumb_dc
== NULL
){
3566 printf("can't create thumb llvm disassembler\n");
3569 llvm_disasm_set_options(arm_dc
,
3570 LLVMDisassembler_Option_PrintImmHex
);
3571 llvm_disasm_set_options(thumb_dc
,
3572 LLVMDisassembler_Option_PrintImmHex
);
3574 llvm_disasm_set_options(arm_dc
,
3575 LLVMDisassembler_Option_UseMarkup
);
3576 llvm_disasm_set_options(thumb_dc
,
3577 LLVMDisassembler_Option_UseMarkup
);
3580 if((qflag
|| gflag
) && cputype
== CPU_TYPE_I386
){
3581 i386_dc
= create_i386_llvm_disassembler();
3582 if(i386_dc
== NULL
){
3583 printf("can't create i386 llvm disassembler\n");
3586 llvm_disasm_set_options(i386_dc
,
3587 LLVMDisassembler_Option_PrintImmHex
);
3588 llvm_disasm_set_options(i386_dc
,
3589 LLVMDisassembler_Option_SetInstrComments
);
3591 llvm_disasm_set_options(i386_dc
,
3592 LLVMDisassembler_Option_UseMarkup
);
3594 if((qflag
|| gflag
) && cputype
== CPU_TYPE_X86_64
){
3595 x86_64_dc
= create_x86_64_llvm_disassembler();
3596 if(x86_64_dc
== NULL
){
3597 printf("can't create x86_64 llvm disassembler\n");
3600 llvm_disasm_set_options(x86_64_dc
,
3601 LLVMDisassembler_Option_PrintImmHex
);
3602 llvm_disasm_set_options(x86_64_dc
,
3603 LLVMDisassembler_Option_SetInstrComments
);
3605 llvm_disasm_set_options(x86_64_dc
,
3606 LLVMDisassembler_Option_UseMarkup
);
3608 if(cputype
== CPU_TYPE_ARM64
){
3609 arm64_dc
= create_arm64_llvm_disassembler(cpusubtype
);
3610 if(arm64_dc
== NULL
){
3611 printf("can't create arm64 llvm disassembler\n");
3614 llvm_disasm_set_options(arm64_dc
,
3615 LLVMDisassembler_Option_PrintImmHex
);
3619 insts
= allocate(sizeof(struct inst
) * ninsts
);
3622 for(i
= offset
; i
< size
; ){
3624 (cputype
== CPU_TYPE_X86_64
||
3625 cputype
== CPU_TYPE_I386
||
3626 cputype
== CPU_TYPE_ARM
)){
3629 insts
= reallocate(insts
, sizeof(struct inst
) * ninsts
);
3631 memset(&(insts
[n
]), '\0', sizeof(struct inst
));
3632 insts
[n
].address
= cur_addr
;
3633 insts
[n
].label
= get_label(cur_addr
, sorted_symbols
,
3637 if(print_label(cur_addr
, TRUE
, sorted_symbols
,
3638 nsorted_symbols
) == TRUE
)
3640 if(function_offsets
)
3641 printf("%+6d ", (int)(i
- label_offset
));
3643 if(cputype
& CPU_ARCH_ABI64
)
3644 printf("%016llx", cur_addr
);
3646 printf("%08x", (uint32_t)cur_addr
);
3647 if((qflag
== FALSE
||
3648 (cputype
== CPU_TYPE_POWERPC
||
3649 cputype
== CPU_TYPE_POWERPC64
)) &&
3650 cputype
!= CPU_TYPE_ARM64
)
3654 if(cputype
== CPU_TYPE_POWERPC64
)
3655 j
= ppc_disassemble(sect
, size
- i
, cur_addr
, addr
,
3656 object_byte_sex
, relocs
, nrelocs
, symbols
,
3657 symbols64
, nsymbols
, sorted_symbols
,
3658 nsorted_symbols
, strings
, strings_size
,
3659 indirect_symbols
, nindirect_symbols
,
3660 load_commands
, ncmds
, sizeofcmds
, verbose
);
3661 else if(cputype
== CPU_TYPE_X86_64
)
3662 j
= i386_disassemble(sect
, size
- i
, cur_addr
, addr
,
3663 object_byte_sex
, relocs
, nrelocs
, ext_relocs
,
3664 next_relocs
, loc_relocs
, nloc_relocs
, dbi
, ndbi
,
3665 NULL
, symbols64
, nsymbols
, sorted_symbols
,
3666 nsorted_symbols
, strings
, strings_size
,
3667 indirect_symbols
, nindirect_symbols
, cputype
,
3668 load_commands
, ncmds
, sizeofcmds
, verbose
,
3669 llvm_mc
, i386_dc
, x86_64_dc
, object_addr
,
3670 object_size
, &(insts
[n
]), NULL
, 0);
3671 else if(cputype
== CPU_TYPE_MC680x0
)
3672 j
= m68k_disassemble(sect
, size
- i
, cur_addr
, addr
,
3673 object_byte_sex
, relocs
, nrelocs
, symbols
,
3674 nsymbols
, sorted_symbols
, nsorted_symbols
,
3675 strings
, strings_size
, indirect_symbols
,
3676 nindirect_symbols
, load_commands
, ncmds
,
3677 sizeofcmds
, verbose
);
3678 else if(cputype
== CPU_TYPE_I860
)
3679 j
= i860_disassemble(sect
, size
- i
, cur_addr
, addr
,
3680 object_byte_sex
, relocs
, nrelocs
, symbols
,
3681 nsymbols
, sorted_symbols
, nsorted_symbols
,
3682 strings
, strings_size
, verbose
);
3683 else if(cputype
== CPU_TYPE_I386
)
3684 j
= i386_disassemble(sect
, size
- i
, cur_addr
, addr
,
3685 object_byte_sex
, relocs
, nrelocs
, ext_relocs
,
3686 next_relocs
, loc_relocs
, nloc_relocs
, dbi
, ndbi
,
3687 symbols
, NULL
, nsymbols
, sorted_symbols
,
3688 nsorted_symbols
, strings
, strings_size
,
3689 indirect_symbols
, nindirect_symbols
, cputype
,
3690 load_commands
, ncmds
, sizeofcmds
, verbose
,
3691 llvm_mc
, i386_dc
, x86_64_dc
, object_addr
,
3692 object_size
, &(insts
[n
]), NULL
, 0);
3693 else if(cputype
== CPU_TYPE_MC88000
)
3694 j
= m88k_disassemble(sect
, size
- i
, cur_addr
, addr
,
3695 object_byte_sex
, relocs
, nrelocs
, symbols
,
3696 nsymbols
, sorted_symbols
, nsorted_symbols
,
3697 strings
, strings_size
, verbose
);
3698 else if(cputype
== CPU_TYPE_POWERPC
||
3699 cputype
== CPU_TYPE_VEO
)
3700 j
= ppc_disassemble(sect
, size
- i
, cur_addr
, addr
,
3701 object_byte_sex
, relocs
, nrelocs
, symbols
,
3702 symbols64
, nsymbols
, sorted_symbols
,
3703 nsorted_symbols
, strings
, strings_size
,
3704 indirect_symbols
, nindirect_symbols
,
3705 load_commands
, ncmds
, sizeofcmds
, verbose
);
3706 else if(cputype
== CPU_TYPE_HPPA
)
3707 j
= hppa_disassemble(sect
, size
- i
, cur_addr
, addr
,
3708 object_byte_sex
, relocs
, nrelocs
, symbols
,
3709 nsymbols
, sorted_symbols
, nsorted_symbols
,
3710 strings
, strings_size
, verbose
);
3711 else if(cputype
== CPU_TYPE_SPARC
)
3712 j
= sparc_disassemble(sect
, size
- i
, cur_addr
, addr
,
3713 object_byte_sex
, relocs
, nrelocs
, symbols
,
3714 nsymbols
, sorted_symbols
, nsorted_symbols
,
3715 strings
, strings_size
, indirect_symbols
,
3716 nindirect_symbols
, load_commands
, ncmds
,
3717 sizeofcmds
, verbose
);
3718 else if(cputype
== CPU_TYPE_ARM
)
3719 j
= arm_disassemble(sect
, size
- i
, cur_addr
, addr
,
3720 object_byte_sex
, relocs
, nrelocs
, symbols
,
3721 nsymbols
, sorted_symbols
, nsorted_symbols
,
3722 strings
, strings_size
, indirect_symbols
,
3723 nindirect_symbols
, load_commands
, ncmds
,
3724 sizeofcmds
, cpusubtype
, verbose
, arm_dc
,
3725 thumb_dc
, object_addr
, object_size
, dices
,
3726 ndices
, seg_addr
, &(insts
[n
]), NULL
, 0);
3727 else if(cputype
== CPU_TYPE_ARM64
)
3728 j
= arm64_disassemble(sect
, size
- i
, cur_addr
, addr
,
3729 object_byte_sex
, relocs
, nrelocs
, ext_relocs
,
3730 next_relocs
, loc_relocs
, nloc_relocs
, dbi
, ndbi
,
3731 symbols64
, nsymbols
, sorted_symbols
,
3732 nsorted_symbols
, strings
, strings_size
,
3733 indirect_symbols
, nindirect_symbols
,
3734 load_commands
, ncmds
, sizeofcmds
, object_addr
,
3735 object_size
, verbose
, arm64_dc
);
3738 printf("Can't disassemble unknown cputype %d\n", cputype
);
3748 (cputype
== CPU_TYPE_X86_64
||
3749 cputype
== CPU_TYPE_I386
||
3750 cputype
== CPU_TYPE_ARM
)){
3754 /* Look for inits that need tmp labels. */
3755 for(i
= 0 ; i
< n
; i
++){
3756 if(insts
[i
].has_raw_target_address
){
3757 for(j
= 0; j
< n
; j
++){
3758 if(insts
[i
].raw_target_address
== insts
[j
].address
)
3759 insts
[j
].needs_tmp_label
= TRUE
;
3764 /* Create the needed tmp labels. */
3766 for(i
= 0 ; i
< n
; i
++){
3767 if(insts
[i
].needs_tmp_label
== TRUE
){
3768 insts
[i
].tmp_label
= allocate(20);
3769 sprintf(insts
[i
].tmp_label
, "L%d", j
++);
3773 /* Now finally print the inits. */
3774 for(i
= 0 ; i
< n
; i
++){
3775 if(insts
[i
].label
!= NULL
)
3776 printf("%s:\n", insts
[i
].label
);
3777 else if(insts
[i
].tmp_label
!= NULL
)
3778 printf("%s:", insts
[i
].tmp_label
);
3779 insts
[i
].print
= TRUE
;
3780 cur_addr
= insts
[i
].address
;
3781 offset
= cur_addr
- addr
;
3782 sect
= sect_start
+ offset
;
3783 if(cputype
== CPU_TYPE_X86_64
|| cputype
== CPU_TYPE_I386
)
3784 j
= i386_disassemble(sect
, size
- offset
, cur_addr
,
3785 addr
, object_byte_sex
, relocs
, nrelocs
,
3786 ext_relocs
, next_relocs
, loc_relocs
,
3787 nloc_relocs
, dbi
, ndbi
, symbols
, NULL
,
3788 nsymbols
, sorted_symbols
, nsorted_symbols
,
3789 strings
, strings_size
, indirect_symbols
,
3790 nindirect_symbols
, cputype
, load_commands
,
3791 ncmds
, sizeofcmds
, verbose
, llvm_mc
, i386_dc
,
3792 x86_64_dc
, object_addr
, object_size
,
3793 &(insts
[i
]), insts
, n
);
3794 else if(cputype
== CPU_TYPE_ARM
)
3795 j
= arm_disassemble(sect
, size
- offset
, cur_addr
, addr
,
3796 object_byte_sex
, relocs
, nrelocs
, symbols
,
3797 nsymbols
, sorted_symbols
, nsorted_symbols
,
3798 strings
, strings_size
, indirect_symbols
,
3799 nindirect_symbols
, load_commands
, ncmds
,
3800 sizeofcmds
, cpusubtype
, verbose
, arm_dc
,
3801 thumb_dc
, object_addr
, object_size
, dices
,
3802 ndices
, seg_addr
, &(insts
[i
]), insts
, n
);
3805 /* Free up allocated space */
3806 for(i
= 0 ; i
< n
; i
++){
3807 if(insts
[i
].tmp_label
!= NULL
)
3808 free(insts
[i
].tmp_label
);
3813 delete_arm_llvm_disassembler(i386_dc
);
3814 if(x86_64_dc
!= NULL
)
3815 delete_arm_llvm_disassembler(x86_64_dc
);
3817 delete_arm_llvm_disassembler(arm_dc
);
3818 if(thumb_dc
!= NULL
)
3819 delete_arm_llvm_disassembler(thumb_dc
);
3820 if(arm64_dc
!= NULL
)
3821 delete_arm64_llvm_disassembler(arm64_dc
);
3824 if(cputype
== CPU_TYPE_I386
|| cputype
== CPU_TYPE_X86_64
){
3825 for(i
= 0 ; i
< size
; i
+= j
, addr
+= j
){
3826 if(cputype
& CPU_ARCH_ABI64
)
3827 printf("%016llx ", addr
);
3829 printf("%08x ", (uint32_t)addr
);
3831 j
< 16 * sizeof(char) && i
+ j
< size
;
3833 byte_word
= *(sect
+ i
+ j
);
3834 printf("%02x ", (unsigned int)byte_word
);
3839 else if(cputype
== CPU_TYPE_MC680x0
){
3840 for(i
= 0 ; i
< size
; i
+= j
, addr
+= j
){
3841 printf("%08x ", (unsigned int)addr
);
3843 j
< 8 * sizeof(short) && i
+ j
< size
;
3844 j
+= sizeof(short)){
3845 memcpy(&short_word
, sect
+ i
+ j
, sizeof(short));
3847 short_word
= SWAP_SHORT(short_word
);
3848 printf("%04x ", (unsigned int)short_word
);
3854 for(i
= 0 ; i
< size
; i
+= j
, addr
+= j
){
3855 if(cputype
& CPU_ARCH_ABI64
)
3856 printf("%016llx ", addr
);
3858 printf("%08x ", (uint32_t)addr
);
3860 j
< 4 * sizeof(int32_t) && i
+ j
< size
;
3861 j
+= sizeof(int32_t)){
3862 memcpy(&long_word
, sect
+ i
+ j
, sizeof(int32_t));
3864 long_word
= SWAP_INT(long_word
);
3865 printf("%08x ", (unsigned int)long_word
);
3877 struct load_command
*load_commands
,
3879 uint32_t sizeofcmds
,
3881 cpu_subtype_t cpusubtype
,
3882 enum byte_sex load_commands_byte_sex
,
3884 uint32_t object_size
)
3886 enum byte_sex host_byte_sex
;
3888 uint32_t i
, len
, left
, size
, arg
;
3890 struct load_command
*lc
, l
;
3891 struct segment_command sg
;
3892 struct segment_command_64 sg64
;
3893 char *stack
, *stack_top
, *p
, *q
, *argv
;
3894 struct arch_flag arch_flags
;
3896 host_byte_sex
= get_host_byte_sex();
3897 swapped
= host_byte_sex
!= load_commands_byte_sex
;
3899 arch_flags
.cputype
= cputype
;
3900 if(magic
== MH_MAGIC_64
)
3901 arch_flags
.cputype
|= CPU_ARCH_ABI64
;
3902 arch_flags
.cpusubtype
= cpusubtype
;
3903 usrstack
= get_stack_addr_from_flag(&arch_flags
);
3905 printf("Don't know the value of USRSTACK for unknown cputype "
3909 printf("Argument strings on the stack at: ");
3910 if(cputype
& CPU_ARCH_ABI64
|| magic
== MH_MAGIC_64
)
3911 printf("%016llx\n", usrstack
);
3913 printf("%08x\n", (uint32_t)usrstack
);
3915 for(i
= 0 ; i
< ncmds
; i
++){
3916 memcpy((char *)&l
, (char *)lc
, sizeof(struct load_command
));
3918 swap_load_command(&l
, host_byte_sex
);
3919 if(cputype
& CPU_ARCH_ABI64
|| magic
== MH_MAGIC_64
){
3920 if(l
.cmdsize
% 8 != 0)
3921 printf("load command %u size not a multiple of 8\n", i
);
3924 if(l
.cmdsize
% 4 != 0)
3925 printf("load command %u size not a multiple of 4\n", i
);
3927 if((char *)lc
+ l
.cmdsize
>
3928 (char *)load_commands
+ sizeofcmds
)
3929 printf("load command %u extends past end of load "
3931 left
= sizeofcmds
- ((char *)lc
- (char *)load_commands
);
3935 memset((char *)&sg
, '\0', sizeof(struct segment_command
));
3936 size
= left
< sizeof(struct segment_command
) ?
3937 left
: sizeof(struct segment_command
);
3938 memcpy((char *)&sg
, (char *)lc
, size
);
3940 swap_segment_command(&sg
, host_byte_sex
);
3942 if(cputype
== CPU_TYPE_HPPA
){
3943 if(sg
.vmaddr
== usrstack
&&
3944 sg
.fileoff
+ sg
.filesize
<= object_size
){
3945 stack
= object_addr
+ sg
.fileoff
;
3946 stack_top
= stack
+ sg
.filesize
;
3948 * There appears to be some pointer then argc at the
3949 * bottom of the stack first before argv[].
3951 argv
= stack
+ 2 * sizeof(uint32_t);
3952 memcpy(&arg
, argv
, sizeof(uint32_t));
3954 arg
= SWAP_INT(arg
);
3955 while(argv
< stack_top
&&
3957 arg
>= usrstack
&& arg
< usrstack
+ sg
.filesize
){
3958 p
= stack
+ (arg
- usrstack
);
3960 while(p
< stack_top
&& *p
!= '\0'){
3965 argv
+= sizeof(uint32_t);
3966 memcpy(&arg
, argv
, sizeof(uint32_t));
3968 arg
= SWAP_INT(arg
);
3970 /* after argv[] then there is envp[] */
3971 argv
+= sizeof(uint32_t);
3972 memcpy(&arg
, argv
, sizeof(uint32_t));
3974 arg
= SWAP_INT(arg
);
3975 while(argv
< stack_top
&&
3977 arg
>= usrstack
&& arg
< usrstack
+ sg
.filesize
){
3978 p
= stack
+ (arg
- usrstack
);
3980 while(p
< stack_top
&& *p
!= '\0'){
3985 argv
+= sizeof(uint32_t);
3986 memcpy(&arg
, argv
, sizeof(uint32_t));
3988 arg
= SWAP_INT(arg
);
3993 if(sg
.vmaddr
+ sg
.vmsize
== usrstack
&&
3994 sg
.fileoff
+ sg
.filesize
<= object_size
){
3995 stack
= object_addr
+ sg
.fileoff
;
3996 stack_top
= stack
+ sg
.filesize
;
3998 /* the first thing on the stack is a long 0 */
4000 p
= (char *)stack_top
;
4002 /* find the first non-null character before the long 0*/
4003 while(p
> stack
&& *p
== '\0')
4005 if(p
!= (char *)stack_top
)
4009 /* Stop when we find another long 0 */
4010 while(p
> stack
&& (*p
!= '\0' || *(p
-1) != '\0' ||
4011 *(p
-2) != '\0' || *(p
-3) != '\0')){
4013 /* step back over the string to its start */
4014 while(p
> stack
&& *p
!= '\0')
4018 p
++; /* step forward to the start of the first string */
4022 while(p
+ len
< q
&& p
[len
] != '\0'){
4023 printf("%c", p
[len
]);
4034 memset((char *)&sg64
, '\0', sizeof(struct segment_command_64
));
4035 size
= left
< sizeof(struct segment_command_64
) ?
4036 left
: sizeof(struct segment_command_64
);
4037 memcpy((char *)&sg64
, (char *)lc
, size
);
4039 swap_segment_command_64(&sg64
, host_byte_sex
);
4040 if(sg64
.vmaddr
+ sg64
.vmsize
== usrstack
&&
4041 sg64
.fileoff
+ sg64
.filesize
<= object_size
){
4042 stack
= object_addr
+ sg64
.fileoff
;
4043 stack_top
= stack
+ sg64
.filesize
;
4045 /* the first thing on the stack is a uint64_t 0 */
4047 p
= (char *)stack_top
;
4049 /* find the first non-null character before the uint64_t 0*/
4050 while(p
> stack
&& *p
== '\0')
4052 if(p
!= (char *)stack_top
)
4056 /* Stop when we find another uint64_t 0 */
4057 while(p
> stack
&& (*p
!= '\0' || *(p
-1) != '\0' ||
4058 *(p
-2) != '\0' || *(p
-3) != '\0' || *(p
-4) != '\0' ||
4059 *(p
-5) != '\0' || *(p
-6) != '\0' || *(p
-7) != '\0')){
4061 /* step back over the string to its start */
4062 while(p
> stack
&& *p
!= '\0')
4066 p
++; /* step forward to the start of the first string */
4070 while(p
+ len
< q
&& p
[len
] != '\0'){
4071 printf("%c", p
[len
]);
4083 printf("load command %u size zero (can't advance to other "
4084 "load commands)\n", i
);
4087 lc
= (struct load_command
*)((char *)lc
+ l
.cmdsize
);
4088 if((char *)lc
> (char *)load_commands
+ sizeofcmds
)
4095 * To avoid linking in libm. These variables are defined as they are used in
4096 * pthread_init() to put in place a fast sqrt().
4098 size_t hw_sqrt_len
= 0;
4112 * More stubs to avoid linking in libm. This works as along as we don't use
4116 __fpclassifyd(double x
)
4121 __fpclassify(long double x
)
4125 #endif /* !defined(__DYNAMIC__) */
4127 #endif /* !defined(LLVM_OTOOL) */