bfd/
[binutils.git] / binutils / od-macho.c
blob91e080e9bccce5dc5ca056b5f3a813796a93edc3
1 /* od-macho.c -- dump information about an Mach-O object file.
2 Copyright 2011, 2012 Free Software Foundation, Inc.
3 Written by Tristan Gingold, Adacore.
5 This file is part of GNU Binutils.
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3, or (at your option)
10 any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, 51 Franklin Street - Fifth Floor, Boston,
20 MA 02110-1301, USA. */
22 #include <stddef.h>
23 #include <time.h>
24 #include "sysdep.h"
25 #include "safe-ctype.h"
26 #include "bfd.h"
27 #include "objdump.h"
28 #include "bucomm.h"
29 #include "bfdlink.h"
30 #include "mach-o.h"
31 #include "mach-o/external.h"
32 #include "mach-o/codesign.h"
34 /* Index of the options in the options[] array. */
35 #define OPT_HEADER 0
36 #define OPT_SECTION 1
37 #define OPT_MAP 2
38 #define OPT_LOAD 3
39 #define OPT_DYSYMTAB 4
40 #define OPT_CODESIGN 5
42 /* List of actions. */
43 static struct objdump_private_option options[] =
45 { "header", 0 },
46 { "section", 0 },
47 { "map", 0 },
48 { "load", 0 },
49 { "dysymtab", 0 },
50 { "codesign", 0 },
51 { NULL, 0 }
54 /* Display help. */
56 static void
57 mach_o_help (FILE *stream)
59 fprintf (stream, _("\
60 For Mach-O files:\n\
61 header Display the file header\n\
62 section Display the segments and sections commands\n\
63 map Display the section map\n\
64 load Display the load commands\n\
65 dysymtab Display the dynamic symbol table\n\
66 codesign Display code signature section\n\
67 "));
70 /* Return TRUE if ABFD is handled. */
72 static int
73 mach_o_filter (bfd *abfd)
75 return bfd_get_flavour (abfd) == bfd_target_mach_o_flavour;
78 static const bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
80 { "vax", BFD_MACH_O_CPU_TYPE_VAX },
81 { "mc680x0", BFD_MACH_O_CPU_TYPE_MC680x0 },
82 { "i386", BFD_MACH_O_CPU_TYPE_I386 },
83 { "mips", BFD_MACH_O_CPU_TYPE_MIPS },
84 { "mc98000", BFD_MACH_O_CPU_TYPE_MC98000 },
85 { "hppa", BFD_MACH_O_CPU_TYPE_HPPA },
86 { "arm", BFD_MACH_O_CPU_TYPE_ARM },
87 { "mc88000", BFD_MACH_O_CPU_TYPE_MC88000 },
88 { "sparc", BFD_MACH_O_CPU_TYPE_SPARC },
89 { "i860", BFD_MACH_O_CPU_TYPE_I860 },
90 { "alpha", BFD_MACH_O_CPU_TYPE_ALPHA },
91 { "powerpc", BFD_MACH_O_CPU_TYPE_POWERPC },
92 { "powerpc_64", BFD_MACH_O_CPU_TYPE_POWERPC_64 },
93 { "x86_64", BFD_MACH_O_CPU_TYPE_X86_64 },
94 { NULL, 0}
97 static const bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
99 { "object", BFD_MACH_O_MH_OBJECT },
100 { "execute", BFD_MACH_O_MH_EXECUTE },
101 { "fvmlib", BFD_MACH_O_MH_FVMLIB },
102 { "core", BFD_MACH_O_MH_CORE },
103 { "preload", BFD_MACH_O_MH_PRELOAD },
104 { "dylib", BFD_MACH_O_MH_DYLIB },
105 { "dylinker", BFD_MACH_O_MH_DYLINKER },
106 { "bundle", BFD_MACH_O_MH_BUNDLE },
107 { "dylib_stub", BFD_MACH_O_MH_DYLIB_STUB },
108 { "dym", BFD_MACH_O_MH_DSYM },
109 { "kext_bundle", BFD_MACH_O_MH_KEXT_BUNDLE },
110 { NULL, 0}
113 static const bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
115 { "noundefs", BFD_MACH_O_MH_NOUNDEFS },
116 { "incrlink", BFD_MACH_O_MH_INCRLINK },
117 { "dyldlink", BFD_MACH_O_MH_DYLDLINK },
118 { "bindatload", BFD_MACH_O_MH_BINDATLOAD },
119 { "prebound", BFD_MACH_O_MH_PREBOUND },
120 { "split_segs", BFD_MACH_O_MH_SPLIT_SEGS },
121 { "lazy_init", BFD_MACH_O_MH_LAZY_INIT },
122 { "twolevel", BFD_MACH_O_MH_TWOLEVEL },
123 { "force_flat", BFD_MACH_O_MH_FORCE_FLAT },
124 { "nomultidefs", BFD_MACH_O_MH_NOMULTIDEFS },
125 { "nofixprebinding", BFD_MACH_O_MH_NOFIXPREBINDING },
126 { "prebindable", BFD_MACH_O_MH_PREBINDABLE },
127 { "allmodsbound", BFD_MACH_O_MH_ALLMODSBOUND },
128 { "subsections_via_symbols", BFD_MACH_O_MH_SUBSECTIONS_VIA_SYMBOLS },
129 { "canonical", BFD_MACH_O_MH_CANONICAL },
130 { "weak_defines", BFD_MACH_O_MH_WEAK_DEFINES },
131 { "binds_to_weak", BFD_MACH_O_MH_BINDS_TO_WEAK },
132 { "allow_stack_execution", BFD_MACH_O_MH_ALLOW_STACK_EXECUTION },
133 { "root_safe", BFD_MACH_O_MH_ROOT_SAFE },
134 { "setuid_safe", BFD_MACH_O_MH_SETUID_SAFE },
135 { "no_reexported_dylibs", BFD_MACH_O_MH_NO_REEXPORTED_DYLIBS },
136 { "pie", BFD_MACH_O_MH_PIE },
137 { NULL, 0}
140 static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
142 { "segment", BFD_MACH_O_LC_SEGMENT},
143 { "symtab", BFD_MACH_O_LC_SYMTAB},
144 { "symseg", BFD_MACH_O_LC_SYMSEG},
145 { "thread", BFD_MACH_O_LC_THREAD},
146 { "unixthread", BFD_MACH_O_LC_UNIXTHREAD},
147 { "loadfvmlib", BFD_MACH_O_LC_LOADFVMLIB},
148 { "idfvmlib", BFD_MACH_O_LC_IDFVMLIB},
149 { "ident", BFD_MACH_O_LC_IDENT},
150 { "fvmfile", BFD_MACH_O_LC_FVMFILE},
151 { "prepage", BFD_MACH_O_LC_PREPAGE},
152 { "dysymtab", BFD_MACH_O_LC_DYSYMTAB},
153 { "load_dylib", BFD_MACH_O_LC_LOAD_DYLIB},
154 { "id_dylib", BFD_MACH_O_LC_ID_DYLIB},
155 { "load_dylinker", BFD_MACH_O_LC_LOAD_DYLINKER},
156 { "id_dylinker", BFD_MACH_O_LC_ID_DYLINKER},
157 { "prebound_dylib", BFD_MACH_O_LC_PREBOUND_DYLIB},
158 { "routines", BFD_MACH_O_LC_ROUTINES},
159 { "sub_framework", BFD_MACH_O_LC_SUB_FRAMEWORK},
160 { "sub_umbrella", BFD_MACH_O_LC_SUB_UMBRELLA},
161 { "sub_client", BFD_MACH_O_LC_SUB_CLIENT},
162 { "sub_library", BFD_MACH_O_LC_SUB_LIBRARY},
163 { "twolevel_hints", BFD_MACH_O_LC_TWOLEVEL_HINTS},
164 { "prebind_cksum", BFD_MACH_O_LC_PREBIND_CKSUM},
165 { "load_weak_dylib", BFD_MACH_O_LC_LOAD_WEAK_DYLIB},
166 { "segment_64", BFD_MACH_O_LC_SEGMENT_64},
167 { "routines_64", BFD_MACH_O_LC_ROUTINES_64},
168 { "uuid", BFD_MACH_O_LC_UUID},
169 { "rpath", BFD_MACH_O_LC_RPATH},
170 { "code_signature", BFD_MACH_O_LC_CODE_SIGNATURE},
171 { "segment_split_info", BFD_MACH_O_LC_SEGMENT_SPLIT_INFO},
172 { "reexport_dylib", BFD_MACH_O_LC_REEXPORT_DYLIB},
173 { "lazy_load_dylib", BFD_MACH_O_LC_LAZY_LOAD_DYLIB},
174 { "encryption_info", BFD_MACH_O_LC_ENCRYPTION_INFO},
175 { "dyld_info", BFD_MACH_O_LC_DYLD_INFO},
176 { "load_upward_lib", BFD_MACH_O_LC_LOAD_UPWARD_DYLIB},
177 { "version_min_macosx", BFD_MACH_O_LC_VERSION_MIN_MACOSX},
178 { "version_min_iphoneos", BFD_MACH_O_LC_VERSION_MIN_IPHONEOS},
179 { "function_starts", BFD_MACH_O_LC_FUNCTION_STARTS},
180 { "dyld_environment", BFD_MACH_O_LC_DYLD_ENVIRONMENT},
181 { NULL, 0}
184 static const bfd_mach_o_xlat_name bfd_mach_o_thread_x86_name[] =
186 { "thread_state32", BFD_MACH_O_x86_THREAD_STATE32},
187 { "float_state32", BFD_MACH_O_x86_FLOAT_STATE32},
188 { "exception_state32", BFD_MACH_O_x86_EXCEPTION_STATE32},
189 { "thread_state64", BFD_MACH_O_x86_THREAD_STATE64},
190 { "float_state64", BFD_MACH_O_x86_FLOAT_STATE64},
191 { "exception_state64", BFD_MACH_O_x86_EXCEPTION_STATE64},
192 { "thread_state", BFD_MACH_O_x86_THREAD_STATE},
193 { "float_state", BFD_MACH_O_x86_FLOAT_STATE},
194 { "exception_state", BFD_MACH_O_x86_EXCEPTION_STATE},
195 { "debug_state32", BFD_MACH_O_x86_DEBUG_STATE32},
196 { "debug_state64", BFD_MACH_O_x86_DEBUG_STATE64},
197 { "debug_state", BFD_MACH_O_x86_DEBUG_STATE},
198 { "state_none", BFD_MACH_O_x86_THREAD_STATE_NONE},
199 { NULL, 0 }
202 static void
203 bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
204 unsigned long val)
206 int first = 1;
208 for (; table->name; table++)
210 if (table->val & val)
212 if (!first)
213 printf ("+");
214 printf ("%s", table->name);
215 val &= ~table->val;
216 first = 0;
219 if (val)
221 if (!first)
222 printf ("+");
223 printf ("0x%lx", val);
224 return;
226 if (first)
227 printf ("-");
230 static const char *
231 bfd_mach_o_get_name_or_null (const bfd_mach_o_xlat_name *table,
232 unsigned long val)
234 for (; table->name; table++)
235 if (table->val == val)
236 return table->name;
237 return NULL;
240 static const char *
241 bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
243 const char *res = bfd_mach_o_get_name_or_null (table, val);
245 if (res == NULL)
246 return "*UNKNOWN*";
247 else
248 return res;
251 static void
252 dump_header (bfd *abfd)
254 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
255 bfd_mach_o_header *h = &mdata->header;
257 fputs (_("Mach-O header:\n"), stdout);
258 printf (_(" magic : %08lx\n"), h->magic);
259 printf (_(" cputype : %08lx (%s)\n"), h->cputype,
260 bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
261 printf (_(" cpusubtype: %08lx\n"), h->cpusubtype);
262 printf (_(" filetype : %08lx (%s)\n"),
263 h->filetype,
264 bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
265 printf (_(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds);
266 printf (_(" sizeofcmds: %08lx\n"), h->sizeofcmds);
267 printf (_(" flags : %08lx ("), h->flags);
268 bfd_mach_o_print_flags (bfd_mach_o_header_flags_name, h->flags);
269 fputs (_(")\n"), stdout);
270 printf (_(" reserved : %08x\n"), h->reserved);
273 static void
274 dump_section_map (bfd *abfd)
276 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
277 unsigned int i;
278 unsigned int sec_nbr = 0;
280 fputs (_("Segments and Sections:\n"), stdout);
281 fputs (_(" #: Segment name Section name Address\n"), stdout);
283 for (i = 0; i < mdata->header.ncmds; i++)
285 bfd_mach_o_segment_command *seg;
286 bfd_mach_o_section *sec;
288 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
289 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
290 continue;
292 seg = &mdata->commands[i].command.segment;
294 printf ("[Segment %-16s ", seg->segname);
295 printf_vma (seg->vmaddr);
296 putchar ('-');
297 printf_vma (seg->vmaddr + seg->vmsize - 1);
298 putchar (' ');
299 putchar (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-');
300 putchar (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
301 putchar (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
302 printf ("]\n");
304 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
306 printf ("%02u: %-16s %-16s ", ++sec_nbr,
307 sec->segname, sec->sectname);
308 printf_vma (sec->addr);
309 putchar (' ');
310 printf_vma (sec->size);
311 printf (" %08lx\n", sec->flags);
316 static void
317 dump_section (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_section *sec)
319 printf (" Section: %-16s %-16s (bfdname: %s)\n",
320 sec->sectname, sec->segname, sec->bfdsection->name);
321 printf (" addr: ");
322 printf_vma (sec->addr);
323 printf (" size: ");
324 printf_vma (sec->size);
325 printf (" offset: ");
326 printf_vma (sec->offset);
327 printf ("\n");
328 printf (" align: %ld", sec->align);
329 printf (" nreloc: %lu reloff: ", sec->nreloc);
330 printf_vma (sec->reloff);
331 printf ("\n");
332 printf (" flags: %08lx (type: %s", sec->flags,
333 bfd_mach_o_get_name (bfd_mach_o_section_type_name,
334 sec->flags & BFD_MACH_O_SECTION_TYPE_MASK));
335 printf (" attr: ");
336 bfd_mach_o_print_flags (bfd_mach_o_section_attribute_name,
337 sec->flags & BFD_MACH_O_SECTION_ATTRIBUTES_MASK);
338 printf (")\n");
339 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
341 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
342 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
343 case BFD_MACH_O_S_SYMBOL_STUBS:
344 printf (" first indirect sym: %lu", sec->reserved1);
345 printf (" (%u entries)",
346 bfd_mach_o_section_get_nbr_indirect (abfd, sec));
347 break;
348 default:
349 printf (" reserved1: 0x%lx", sec->reserved1);
350 break;
352 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
354 case BFD_MACH_O_S_SYMBOL_STUBS:
355 printf (" stub size: %lu", sec->reserved2);
356 break;
357 default:
358 printf (" reserved2: 0x%lx", sec->reserved2);
359 break;
361 printf (" reserved3: 0x%lx\n", sec->reserved3);
364 static void
365 dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
367 bfd_mach_o_segment_command *seg = &cmd->command.segment;
368 bfd_mach_o_section *sec;
370 printf (" name: %s\n", *seg->segname ? seg->segname : "*none*");
371 printf (" vmaddr: ");
372 printf_vma (seg->vmaddr);
373 printf (" vmsize: ");
374 printf_vma (seg->vmsize);
375 printf ("\n");
376 printf (" fileoff: ");
377 printf_vma (seg->fileoff);
378 printf (" filesize: ");
379 printf_vma ((bfd_vma)seg->filesize);
380 printf (" endoff: ");
381 printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
382 printf ("\n");
383 printf (" nsects: %lu ", seg->nsects);
384 printf (" flags: %lx\n", seg->flags);
385 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
386 dump_section (abfd, sec);
389 static void
390 dump_dysymtab (bfd *abfd, bfd_mach_o_load_command *cmd, bfd_boolean verbose)
392 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
393 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
394 unsigned int i;
396 printf (" local symbols: idx: %10lu num: %-8lu",
397 dysymtab->ilocalsym, dysymtab->nlocalsym);
398 printf (" (nxtidx: %lu)\n",
399 dysymtab->ilocalsym + dysymtab->nlocalsym);
400 printf (" external symbols: idx: %10lu num: %-8lu",
401 dysymtab->iextdefsym, dysymtab->nextdefsym);
402 printf (" (nxtidx: %lu)\n",
403 dysymtab->iextdefsym + dysymtab->nextdefsym);
404 printf (" undefined symbols: idx: %10lu num: %-8lu",
405 dysymtab->iundefsym, dysymtab->nundefsym);
406 printf (" (nxtidx: %lu)\n",
407 dysymtab->iundefsym + dysymtab->nundefsym);
408 printf (" table of content: off: 0x%08lx num: %-8lu",
409 dysymtab->tocoff, dysymtab->ntoc);
410 printf (" (endoff: 0x%08lx)\n",
411 dysymtab->tocoff + dysymtab->ntoc * BFD_MACH_O_TABLE_OF_CONTENT_SIZE);
412 printf (" module table: off: 0x%08lx num: %-8lu",
413 dysymtab->modtaboff, dysymtab->nmodtab);
414 printf (" (endoff: 0x%08lx)\n",
415 dysymtab->modtaboff + dysymtab->nmodtab
416 * (mdata->header.version == 2 ?
417 BFD_MACH_O_DYLIB_MODULE_64_SIZE : BFD_MACH_O_DYLIB_MODULE_SIZE));
418 printf (" external reference table: off: 0x%08lx num: %-8lu",
419 dysymtab->extrefsymoff, dysymtab->nextrefsyms);
420 printf (" (endoff: 0x%08lx)\n",
421 dysymtab->extrefsymoff
422 + dysymtab->nextrefsyms * BFD_MACH_O_REFERENCE_SIZE);
423 printf (" indirect symbol table: off: 0x%08lx num: %-8lu",
424 dysymtab->indirectsymoff, dysymtab->nindirectsyms);
425 printf (" (endoff: 0x%08lx)\n",
426 dysymtab->indirectsymoff
427 + dysymtab->nindirectsyms * BFD_MACH_O_INDIRECT_SYMBOL_SIZE);
428 printf (" external relocation table: off: 0x%08lx num: %-8lu",
429 dysymtab->extreloff, dysymtab->nextrel);
430 printf (" (endoff: 0x%08lx)\n",
431 dysymtab->extreloff + dysymtab->nextrel * BFD_MACH_O_RELENT_SIZE);
432 printf (" local relocation table: off: 0x%08lx num: %-8lu",
433 dysymtab->locreloff, dysymtab->nlocrel);
434 printf (" (endoff: 0x%08lx)\n",
435 dysymtab->locreloff + dysymtab->nlocrel * BFD_MACH_O_RELENT_SIZE);
437 if (!verbose)
438 return;
440 if (dysymtab->ntoc > 0
441 || dysymtab->nindirectsyms > 0
442 || dysymtab->nextrefsyms > 0)
444 /* Try to read the symbols to display the toc or indirect symbols. */
445 bfd_mach_o_read_symtab_symbols (abfd);
447 else if (dysymtab->nmodtab > 0)
449 /* Try to read the strtab to display modules name. */
450 bfd_mach_o_read_symtab_strtab (abfd);
453 for (i = 0; i < dysymtab->nmodtab; i++)
455 bfd_mach_o_dylib_module *module = &dysymtab->dylib_module[i];
456 printf (" module %u:\n", i);
457 printf (" name: %lu", module->module_name_idx);
458 if (mdata->symtab && mdata->symtab->strtab)
459 printf (": %s",
460 mdata->symtab->strtab + module->module_name_idx);
461 printf ("\n");
462 printf (" extdefsym: idx: %8lu num: %lu\n",
463 module->iextdefsym, module->nextdefsym);
464 printf (" refsym: idx: %8lu num: %lu\n",
465 module->irefsym, module->nrefsym);
466 printf (" localsym: idx: %8lu num: %lu\n",
467 module->ilocalsym, module->nlocalsym);
468 printf (" extrel: idx: %8lu num: %lu\n",
469 module->iextrel, module->nextrel);
470 printf (" init: idx: %8u num: %u\n",
471 module->iinit, module->ninit);
472 printf (" term: idx: %8u num: %u\n",
473 module->iterm, module->nterm);
474 printf (" objc_module_info: addr: ");
475 printf_vma (module->objc_module_info_addr);
476 printf (" size: %lu\n", module->objc_module_info_size);
479 if (dysymtab->ntoc > 0)
481 bfd_mach_o_symtab_command *symtab = mdata->symtab;
483 printf (" table of content: (symbol/module)\n");
484 for (i = 0; i < dysymtab->ntoc; i++)
486 bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
488 printf (" %4u: ", i);
489 if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
491 const char *name = symtab->symbols[toc->symbol_index].symbol.name;
492 printf ("%s (%lu)", name ? name : "*invalid*",
493 toc->symbol_index);
495 else
496 printf ("%lu", toc->symbol_index);
498 printf (" / ");
499 if (symtab && symtab->strtab
500 && toc->module_index < dysymtab->nmodtab)
502 bfd_mach_o_dylib_module *mod;
503 mod = &dysymtab->dylib_module[toc->module_index];
504 printf ("%s (%lu)",
505 symtab->strtab + mod->module_name_idx,
506 toc->module_index);
508 else
509 printf ("%lu", toc->module_index);
511 printf ("\n");
515 if (dysymtab->nindirectsyms != 0)
517 printf (" indirect symbols:\n");
519 for (i = 0; i < mdata->nsects; i++)
521 bfd_mach_o_section *sec = mdata->sections[i];
522 unsigned int j, first, last;
523 bfd_mach_o_symtab_command *symtab = mdata->symtab;
524 bfd_vma addr;
525 bfd_vma entry_size;
527 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
529 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
530 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
531 case BFD_MACH_O_S_SYMBOL_STUBS:
532 first = sec->reserved1;
533 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
534 addr = sec->addr;
535 entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
536 printf (" for section %s.%s:\n",
537 sec->segname, sec->sectname);
538 for (j = first; j < last; j++)
540 unsigned int isym = dysymtab->indirect_syms[j];
542 printf (" ");
543 printf_vma (addr);
544 printf (" %5u: 0x%08x", j, isym);
545 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_LOCAL)
546 printf (" LOCAL");
547 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_ABS)
548 printf (" ABSOLUTE");
549 if (symtab && symtab->symbols
550 && isym < symtab->nsyms
551 && symtab->symbols[isym].symbol.name)
552 printf (" %s", symtab->symbols[isym].symbol.name);
553 printf ("\n");
554 addr += entry_size;
556 break;
557 default:
558 break;
562 if (dysymtab->nextrefsyms > 0)
564 bfd_mach_o_symtab_command *symtab = mdata->symtab;
566 printf (" external reference table: (symbol flags)\n");
567 for (i = 0; i < dysymtab->nextrefsyms; i++)
569 bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
571 printf (" %4u: %5lu 0x%02lx", i, ref->isym, ref->flags);
572 if (symtab && symtab->symbols
573 && ref->isym < symtab->nsyms
574 && symtab->symbols[ref->isym].symbol.name)
575 printf (" %s", symtab->symbols[ref->isym].symbol.name);
576 printf ("\n");
582 static void
583 dump_dyld_info (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
585 bfd_mach_o_dyld_info_command *info = &cmd->command.dyld_info;
587 printf (" rebase: off: 0x%08x size: %-8u\n",
588 info->rebase_off, info->rebase_size);
589 printf (" bind: off: 0x%08x size: %-8u\n",
590 info->bind_off, info->bind_size);
591 printf (" weak bind: off: 0x%08x size: %-8u\n",
592 info->weak_bind_off, info->weak_bind_size);
593 printf (" lazy bind: off: 0x%08x size: %-8u\n",
594 info->lazy_bind_off, info->lazy_bind_size);
595 printf (" export: off: 0x%08x size: %-8u\n",
596 info->export_off, info->export_size);
599 static void
600 dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
602 bfd_mach_o_thread_command *thread = &cmd->command.thread;
603 unsigned int j;
604 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
605 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
607 printf (" nflavours: %lu\n", thread->nflavours);
608 for (j = 0; j < thread->nflavours; j++)
610 bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
611 const bfd_mach_o_xlat_name *name_table;
613 printf (" %2u: flavour: 0x%08lx", j, flavour->flavour);
614 switch (mdata->header.cputype)
616 case BFD_MACH_O_CPU_TYPE_I386:
617 case BFD_MACH_O_CPU_TYPE_X86_64:
618 name_table = bfd_mach_o_thread_x86_name;
619 break;
620 default:
621 name_table = NULL;
622 break;
624 if (name_table != NULL)
625 printf (": %s", bfd_mach_o_get_name (name_table, flavour->flavour));
626 putchar ('\n');
628 printf (" offset: 0x%08lx size: 0x%08lx\n",
629 flavour->offset, flavour->size);
630 if (bed->_bfd_mach_o_print_thread)
632 char *buf = xmalloc (flavour->size);
634 if (bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
635 && bfd_bread (buf, flavour->size, abfd) == flavour->size)
636 (*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, buf);
638 free (buf);
643 static const bfd_mach_o_xlat_name bfd_mach_o_cs_magic[] =
645 { "embedded signature", BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE },
646 { "requirement", BFD_MACH_O_CS_MAGIC_REQUIREMENT },
647 { "requirements", BFD_MACH_O_CS_MAGIC_REQUIREMENTS },
648 { "code directory", BFD_MACH_O_CS_MAGIC_CODEDIRECTORY },
649 { "embedded entitlements", BFD_MACH_O_CS_MAGIC_EMBEDDED_ENTITLEMENTS },
650 { "blob wrapper", BFD_MACH_O_CS_MAGIC_BLOB_WRAPPER },
651 { NULL, 0 }
654 static const bfd_mach_o_xlat_name bfd_mach_o_cs_hash_type[] =
656 { "no-hash", BFD_MACH_O_CS_NO_HASH },
657 { "sha1", BFD_MACH_O_CS_HASH_SHA1 },
658 { "sha256", BFD_MACH_O_CS_HASH_SHA256 },
659 { "skein 160", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_160x256 },
660 { "skein 256", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_256x512 },
661 { NULL, 0 }
664 static unsigned int
665 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len);
667 static void
668 dump_code_signature_superblob (bfd *abfd ATTRIBUTE_UNUSED,
669 const unsigned char *buf, unsigned int len)
671 unsigned int count;
672 unsigned int i;
674 if (len < 12)
676 printf (_(" [bad block length]\n"));
677 return;
679 count = bfd_getb32 (buf + 8);
680 printf (_(" %u index entries:\n"), count);
681 if (len < 12 + 8 * count)
683 printf (_(" [bad block length]\n"));
684 return;
686 for (i = 0; i < count; i++)
688 unsigned int type;
689 unsigned int off;
691 type = bfd_getb32 (buf + 12 + 8 * i);
692 off = bfd_getb32 (buf + 12 + 8 * i + 4);
693 printf (_(" index entry %u: type: %08x, offset: %08x\n"),
694 i, type, off);
696 dump_code_signature_blob (abfd, buf + off, len - off);
700 static void
701 swap_code_codedirectory_v1_in
702 (const struct mach_o_codesign_codedirectory_external_v1 *src,
703 struct mach_o_codesign_codedirectory_v1 *dst)
705 dst->version = bfd_getb32 (src->version);
706 dst->flags = bfd_getb32 (src->flags);
707 dst->hash_offset = bfd_getb32 (src->hash_offset);
708 dst->ident_offset = bfd_getb32 (src->ident_offset);
709 dst->nbr_special_slots = bfd_getb32 (src->nbr_special_slots);
710 dst->nbr_code_slots = bfd_getb32 (src->nbr_code_slots);
711 dst->code_limit = bfd_getb32 (src->code_limit);
712 dst->hash_size = src->hash_size[0];
713 dst->hash_type = src->hash_type[0];
714 dst->spare1 = src->spare1[0];
715 dst->page_size = src->page_size[0];
716 dst->spare2 = bfd_getb32 (src->spare2);
719 static void
720 hexdump (unsigned int start, unsigned int len,
721 const unsigned char *buf)
723 unsigned int i, j;
725 for (i = 0; i < len; i += 16)
727 printf ("%08x:", start + i);
728 for (j = 0; j < 16; j++)
730 fputc (j == 8 ? '-' : ' ', stdout);
731 if (i + j < len)
732 printf ("%02x", buf[i + j]);
733 else
734 fputs (" ", stdout);
736 fputc (' ', stdout);
737 for (j = 0; j < 16; j++)
739 if (i + j < len)
740 fputc (ISPRINT (buf[i + j]) ? buf[i + j] : '.', stdout);
741 else
742 fputc (' ', stdout);
744 fputc ('\n', stdout);
748 static void
749 dump_code_signature_codedirectory (bfd *abfd ATTRIBUTE_UNUSED,
750 const unsigned char *buf, unsigned int len)
752 struct mach_o_codesign_codedirectory_v1 cd;
753 const char *id;
755 if (len < sizeof (struct mach_o_codesign_codedirectory_external_v1))
757 printf (_(" [bad block length]\n"));
758 return;
761 swap_code_codedirectory_v1_in
762 ((const struct mach_o_codesign_codedirectory_external_v1 *) (buf + 8), &cd);
764 printf (_(" version: %08x\n"), cd.version);
765 printf (_(" flags: %08x\n"), cd.flags);
766 printf (_(" hash offset: %08x\n"), cd.hash_offset);
767 id = (const char *) buf + cd.ident_offset;
768 printf (_(" ident offset: %08x (- %08x)\n"),
769 cd.ident_offset, cd.ident_offset + (unsigned) strlen (id) + 1);
770 printf (_(" identity: %s\n"), id);
771 printf (_(" nbr special slots: %08x (at offset %08x)\n"),
772 cd.nbr_special_slots,
773 cd.hash_offset - cd.nbr_special_slots * cd.hash_size);
774 printf (_(" nbr code slots: %08x\n"), cd.nbr_code_slots);
775 printf (_(" code limit: %08x\n"), cd.code_limit);
776 printf (_(" hash size: %02x\n"), cd.hash_size);
777 printf (_(" hash type: %02x (%s)\n"),
778 cd.hash_type,
779 bfd_mach_o_get_name (bfd_mach_o_cs_hash_type, cd.hash_type));
780 printf (_(" spare1: %02x\n"), cd.spare1);
781 printf (_(" page size: %02x\n"), cd.page_size);
782 printf (_(" spare2: %08x\n"), cd.spare2);
783 if (cd.version >= 0x20100)
784 printf (_(" scatter offset: %08x\n"),
785 (unsigned) bfd_getb32 (buf + 44));
788 static unsigned int
789 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len)
791 unsigned int magic;
792 unsigned int length;
794 if (len < 8)
796 printf (_(" [truncated block]\n"));
797 return 0;
799 magic = bfd_getb32 (buf);
800 length = bfd_getb32 (buf + 4);
801 if (magic == 0 || length == 0)
802 return 0;
804 printf (_(" magic : %08x (%s)\n"), magic,
805 bfd_mach_o_get_name (bfd_mach_o_cs_magic, magic));
806 printf (_(" length: %08x\n"), length);
807 if (length > len)
809 printf (_(" [bad block length]\n"));
810 return 0;
813 switch (magic)
815 case BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE:
816 dump_code_signature_superblob (abfd, buf, length);
817 break;
818 case BFD_MACH_O_CS_MAGIC_CODEDIRECTORY:
819 dump_code_signature_codedirectory (abfd, buf, length);
820 break;
821 default:
822 hexdump (0, length - 8, buf + 8);
823 break;
825 return length;
828 static void
829 dump_code_signature (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
831 unsigned char *buf = xmalloc (cmd->datasize);
832 unsigned int off;
834 if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
835 || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
837 non_fatal (_("cannot read code signature data"));
838 free (buf);
839 return;
841 for (off = 0; off < cmd->datasize;)
843 unsigned int len;
845 len = dump_code_signature_blob (abfd, buf + off, cmd->datasize - off);
847 if (len == 0)
848 break;
849 off += len;
851 free (buf);
854 static void
855 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
856 bfd_boolean verbose)
858 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
859 const char *cmd_name;
861 cmd_name = bfd_mach_o_get_name_or_null
862 (bfd_mach_o_load_command_name, cmd->type);
863 printf ("Load command ");
864 if (cmd_name == NULL)
865 printf ("0x%02x:", cmd->type);
866 else
867 printf ("%s:", cmd_name);
869 switch (cmd->type)
871 case BFD_MACH_O_LC_SEGMENT:
872 case BFD_MACH_O_LC_SEGMENT_64:
873 dump_segment (abfd, cmd);
874 break;
875 case BFD_MACH_O_LC_UUID:
877 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
878 unsigned int j;
880 for (j = 0; j < sizeof (uuid->uuid); j ++)
881 printf (" %02x", uuid->uuid[j]);
882 putchar ('\n');
884 break;
885 case BFD_MACH_O_LC_LOAD_DYLIB:
886 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
887 case BFD_MACH_O_LC_REEXPORT_DYLIB:
888 case BFD_MACH_O_LC_ID_DYLIB:
889 case BFD_MACH_O_LC_LOAD_UPWARD_DYLIB:
891 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
892 printf (" %s\n", dylib->name_str);
893 printf (" time stamp: 0x%08lx\n",
894 dylib->timestamp);
895 printf (" current version: 0x%08lx\n",
896 dylib->current_version);
897 printf (" comptibility version: 0x%08lx\n",
898 dylib->compatibility_version);
900 break;
901 case BFD_MACH_O_LC_LOAD_DYLINKER:
902 case BFD_MACH_O_LC_ID_DYLINKER:
903 printf (" %s\n", cmd->command.dylinker.name_str);
904 break;
905 case BFD_MACH_O_LC_SYMTAB:
907 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
908 printf ("\n"
909 " symoff: 0x%08x nsyms: %8u (endoff: 0x%08x)\n",
910 symtab->symoff, symtab->nsyms,
911 symtab->symoff + symtab->nsyms
912 * (mdata->header.version == 2
913 ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE));
914 printf (" stroff: 0x%08x strsize: %8u (endoff: 0x%08x)\n",
915 symtab->stroff, symtab->strsize,
916 symtab->stroff + symtab->strsize);
917 break;
919 case BFD_MACH_O_LC_DYSYMTAB:
920 putchar ('\n');
921 dump_dysymtab (abfd, cmd, verbose);
922 break;
923 case BFD_MACH_O_LC_LOADFVMLIB:
924 case BFD_MACH_O_LC_IDFVMLIB:
926 bfd_mach_o_fvmlib_command *fvmlib = &cmd->command.fvmlib;
927 printf (" %s\n", fvmlib->name_str);
928 printf (" minor version: 0x%08x\n", fvmlib->minor_version);
929 printf (" header address: 0x%08x\n", fvmlib->header_addr);
931 break;
932 case BFD_MACH_O_LC_CODE_SIGNATURE:
933 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
934 case BFD_MACH_O_LC_FUNCTION_STARTS:
936 bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
937 printf
938 ("\n"
939 " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
940 linkedit->dataoff, linkedit->datasize,
941 linkedit->dataoff + linkedit->datasize);
943 if (verbose && cmd->type == BFD_MACH_O_LC_CODE_SIGNATURE)
944 dump_code_signature (abfd, linkedit);
945 break;
947 case BFD_MACH_O_LC_SUB_FRAMEWORK:
948 case BFD_MACH_O_LC_SUB_UMBRELLA:
949 case BFD_MACH_O_LC_SUB_LIBRARY:
950 case BFD_MACH_O_LC_SUB_CLIENT:
951 case BFD_MACH_O_LC_RPATH:
953 bfd_mach_o_str_command *str = &cmd->command.str;
954 printf (" %s\n", str->str);
955 break;
957 case BFD_MACH_O_LC_THREAD:
958 case BFD_MACH_O_LC_UNIXTHREAD:
959 dump_thread (abfd, cmd);
960 break;
961 case BFD_MACH_O_LC_ENCRYPTION_INFO:
963 bfd_mach_o_encryption_info_command *cryp =
964 &cmd->command.encryption_info;
965 printf
966 ("\n"
967 " cryptoff: 0x%08x cryptsize: 0x%08x (endoff 0x%08x)"
968 " cryptid: %u\n",
969 cryp->cryptoff, cryp->cryptsize,
970 cryp->cryptoff + cryp->cryptsize,
971 cryp->cryptid);
973 break;
974 case BFD_MACH_O_LC_DYLD_INFO:
975 putchar ('\n');
976 dump_dyld_info (abfd, cmd);
977 break;
978 case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
979 case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
981 bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
983 printf (" %u.%u.%u\n", ver->rel, ver->maj, ver->min);
985 break;
986 default:
987 putchar ('\n');
988 printf (" offset: 0x%08lx\n", (unsigned long)cmd->offset);
989 printf (" size: 0x%08lx\n", (unsigned long)cmd->len);
990 break;
992 putchar ('\n');
995 static void
996 dump_load_commands (bfd *abfd, unsigned int cmd32, unsigned int cmd64)
998 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
999 unsigned int i;
1001 for (i = 0; i < mdata->header.ncmds; i++)
1003 bfd_mach_o_load_command *cmd = &mdata->commands[i];
1005 if (cmd32 == 0)
1006 dump_load_command (abfd, cmd, FALSE);
1007 else if (cmd->type == cmd32 || cmd->type == cmd64)
1008 dump_load_command (abfd, cmd, TRUE);
1012 /* Dump ABFD (according to the options[] array). */
1014 static void
1015 mach_o_dump (bfd *abfd)
1017 if (options[OPT_HEADER].selected)
1018 dump_header (abfd);
1019 if (options[OPT_SECTION].selected)
1020 dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT, BFD_MACH_O_LC_SEGMENT_64);
1021 if (options[OPT_MAP].selected)
1022 dump_section_map (abfd);
1023 if (options[OPT_LOAD].selected)
1024 dump_load_commands (abfd, 0, 0);
1025 if (options[OPT_DYSYMTAB].selected)
1026 dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0);
1027 if (options[OPT_CODESIGN].selected)
1028 dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
1031 /* Vector for Mach-O. */
1033 const struct objdump_private_desc objdump_private_desc_mach_o =
1035 mach_o_help,
1036 mach_o_filter,
1037 mach_o_dump,
1038 options