bfd/
[deliverable/binutils-gdb.git] / binutils / od-macho.c
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.
4
5 This file is part of GNU Binutils.
6
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.
11
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.
16
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. */
21
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"
33
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
41
42 /* List of actions. */
43 static struct objdump_private_option options[] =
44 {
45 { "header", 0 },
46 { "section", 0 },
47 { "map", 0 },
48 { "load", 0 },
49 { "dysymtab", 0 },
50 { "codesign", 0 },
51 { NULL, 0 }
52 };
53
54 /* Display help. */
55
56 static void
57 mach_o_help (FILE *stream)
58 {
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 "));
68 }
69
70 /* Return TRUE if ABFD is handled. */
71
72 static int
73 mach_o_filter (bfd *abfd)
74 {
75 return bfd_get_flavour (abfd) == bfd_target_mach_o_flavour;
76 }
77 \f
78 static const bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
79 {
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}
95 };
96
97 static const bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
98 {
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}
111 };
112
113 static const bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
114 {
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}
138 };
139
140 static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
141 {
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}
182 };
183
184 static const bfd_mach_o_xlat_name bfd_mach_o_thread_x86_name[] =
185 {
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 }
200 };
201 \f
202 static void
203 bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
204 unsigned long val)
205 {
206 int first = 1;
207
208 for (; table->name; table++)
209 {
210 if (table->val & val)
211 {
212 if (!first)
213 printf ("+");
214 printf ("%s", table->name);
215 val &= ~table->val;
216 first = 0;
217 }
218 }
219 if (val)
220 {
221 if (!first)
222 printf ("+");
223 printf ("0x%lx", val);
224 return;
225 }
226 if (first)
227 printf ("-");
228 }
229
230 static const char *
231 bfd_mach_o_get_name_or_null (const bfd_mach_o_xlat_name *table,
232 unsigned long val)
233 {
234 for (; table->name; table++)
235 if (table->val == val)
236 return table->name;
237 return NULL;
238 }
239
240 static const char *
241 bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
242 {
243 const char *res = bfd_mach_o_get_name_or_null (table, val);
244
245 if (res == NULL)
246 return "*UNKNOWN*";
247 else
248 return res;
249 }
250
251 static void
252 dump_header (bfd *abfd)
253 {
254 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
255 bfd_mach_o_header *h = &mdata->header;
256
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);
271 }
272
273 static void
274 dump_section_map (bfd *abfd)
275 {
276 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
277 unsigned int i;
278 unsigned int sec_nbr = 0;
279
280 fputs (_("Segments and Sections:\n"), stdout);
281 fputs (_(" #: Segment name Section name Address\n"), stdout);
282
283 for (i = 0; i < mdata->header.ncmds; i++)
284 {
285 bfd_mach_o_segment_command *seg;
286 bfd_mach_o_section *sec;
287
288 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
289 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
290 continue;
291
292 seg = &mdata->commands[i].command.segment;
293
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");
303
304 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
305 {
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);
312 }
313 }
314 }
315
316 static void
317 dump_section (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_section *sec)
318 {
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)
340 {
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;
351 }
352 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
353 {
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;
360 }
361 printf (" reserved3: 0x%lx\n", sec->reserved3);
362 }
363
364 static void
365 dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
366 {
367 bfd_mach_o_segment_command *seg = &cmd->command.segment;
368 bfd_mach_o_section *sec;
369
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);
387 }
388
389 static void
390 dump_dysymtab (bfd *abfd, bfd_mach_o_load_command *cmd, bfd_boolean verbose)
391 {
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;
395
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);
436
437 if (!verbose)
438 return;
439
440 if (dysymtab->ntoc > 0
441 || dysymtab->nindirectsyms > 0
442 || dysymtab->nextrefsyms > 0)
443 {
444 /* Try to read the symbols to display the toc or indirect symbols. */
445 bfd_mach_o_read_symtab_symbols (abfd);
446 }
447 else if (dysymtab->nmodtab > 0)
448 {
449 /* Try to read the strtab to display modules name. */
450 bfd_mach_o_read_symtab_strtab (abfd);
451 }
452
453 for (i = 0; i < dysymtab->nmodtab; i++)
454 {
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);
477 }
478
479 if (dysymtab->ntoc > 0)
480 {
481 bfd_mach_o_symtab_command *symtab = mdata->symtab;
482
483 printf (" table of content: (symbol/module)\n");
484 for (i = 0; i < dysymtab->ntoc; i++)
485 {
486 bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
487
488 printf (" %4u: ", i);
489 if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
490 {
491 const char *name = symtab->symbols[toc->symbol_index].symbol.name;
492 printf ("%s (%lu)", name ? name : "*invalid*",
493 toc->symbol_index);
494 }
495 else
496 printf ("%lu", toc->symbol_index);
497
498 printf (" / ");
499 if (symtab && symtab->strtab
500 && toc->module_index < dysymtab->nmodtab)
501 {
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);
507 }
508 else
509 printf ("%lu", toc->module_index);
510
511 printf ("\n");
512 }
513 }
514
515 if (dysymtab->nindirectsyms != 0)
516 {
517 printf (" indirect symbols:\n");
518
519 for (i = 0; i < mdata->nsects; i++)
520 {
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;
526
527 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
528 {
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++)
539 {
540 unsigned int isym = dysymtab->indirect_syms[j];
541
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;
555 }
556 break;
557 default:
558 break;
559 }
560 }
561 }
562 if (dysymtab->nextrefsyms > 0)
563 {
564 bfd_mach_o_symtab_command *symtab = mdata->symtab;
565
566 printf (" external reference table: (symbol flags)\n");
567 for (i = 0; i < dysymtab->nextrefsyms; i++)
568 {
569 bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
570
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");
577 }
578 }
579
580 }
581
582 static void
583 dump_dyld_info (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
584 {
585 bfd_mach_o_dyld_info_command *info = &cmd->command.dyld_info;
586
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);
597 }
598
599 static void
600 dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
601 {
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);
606
607 printf (" nflavours: %lu\n", thread->nflavours);
608 for (j = 0; j < thread->nflavours; j++)
609 {
610 bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
611 const bfd_mach_o_xlat_name *name_table;
612
613 printf (" %2u: flavour: 0x%08lx", j, flavour->flavour);
614 switch (mdata->header.cputype)
615 {
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;
623 }
624 if (name_table != NULL)
625 printf (": %s", bfd_mach_o_get_name (name_table, flavour->flavour));
626 putchar ('\n');
627
628 printf (" offset: 0x%08lx size: 0x%08lx\n",
629 flavour->offset, flavour->size);
630 if (bed->_bfd_mach_o_print_thread)
631 {
632 char *buf = xmalloc (flavour->size);
633
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);
637
638 free (buf);
639 }
640 }
641 }
642
643 static const bfd_mach_o_xlat_name bfd_mach_o_cs_magic[] =
644 {
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 }
652 };
653
654 static const bfd_mach_o_xlat_name bfd_mach_o_cs_hash_type[] =
655 {
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 }
662 };
663
664 static unsigned int
665 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len);
666
667 static void
668 dump_code_signature_superblob (bfd *abfd ATTRIBUTE_UNUSED,
669 const unsigned char *buf, unsigned int len)
670 {
671 unsigned int count;
672 unsigned int i;
673
674 if (len < 12)
675 {
676 printf (_(" [bad block length]\n"));
677 return;
678 }
679 count = bfd_getb32 (buf + 8);
680 printf (_(" %u index entries:\n"), count);
681 if (len < 12 + 8 * count)
682 {
683 printf (_(" [bad block length]\n"));
684 return;
685 }
686 for (i = 0; i < count; i++)
687 {
688 unsigned int type;
689 unsigned int off;
690
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);
695
696 dump_code_signature_blob (abfd, buf + off, len - off);
697 }
698 }
699
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)
704 {
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);
717 }
718
719 static void
720 hexdump (unsigned int start, unsigned int len,
721 const unsigned char *buf)
722 {
723 unsigned int i, j;
724
725 for (i = 0; i < len; i += 16)
726 {
727 printf ("%08x:", start + i);
728 for (j = 0; j < 16; j++)
729 {
730 fputc (j == 8 ? '-' : ' ', stdout);
731 if (i + j < len)
732 printf ("%02x", buf[i + j]);
733 else
734 fputs (" ", stdout);
735 }
736 fputc (' ', stdout);
737 for (j = 0; j < 16; j++)
738 {
739 if (i + j < len)
740 fputc (ISPRINT (buf[i + j]) ? buf[i + j] : '.', stdout);
741 else
742 fputc (' ', stdout);
743 }
744 fputc ('\n', stdout);
745 }
746 }
747
748 static void
749 dump_code_signature_codedirectory (bfd *abfd ATTRIBUTE_UNUSED,
750 const unsigned char *buf, unsigned int len)
751 {
752 struct mach_o_codesign_codedirectory_v1 cd;
753 const char *id;
754
755 if (len < sizeof (struct mach_o_codesign_codedirectory_external_v1))
756 {
757 printf (_(" [bad block length]\n"));
758 return;
759 }
760
761 swap_code_codedirectory_v1_in
762 ((const struct mach_o_codesign_codedirectory_external_v1 *) (buf + 8), &cd);
763
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));
786 }
787
788 static unsigned int
789 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len)
790 {
791 unsigned int magic;
792 unsigned int length;
793
794 if (len < 8)
795 {
796 printf (_(" [truncated block]\n"));
797 return 0;
798 }
799 magic = bfd_getb32 (buf);
800 length = bfd_getb32 (buf + 4);
801 if (magic == 0 || length == 0)
802 return 0;
803
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)
808 {
809 printf (_(" [bad block length]\n"));
810 return 0;
811 }
812
813 switch (magic)
814 {
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;
824 }
825 return length;
826 }
827
828 static void
829 dump_code_signature (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
830 {
831 unsigned char *buf = xmalloc (cmd->datasize);
832 unsigned int off;
833
834 if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
835 || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
836 {
837 non_fatal (_("cannot read code signature data"));
838 free (buf);
839 return;
840 }
841 for (off = 0; off < cmd->datasize;)
842 {
843 unsigned int len;
844
845 len = dump_code_signature_blob (abfd, buf + off, cmd->datasize - off);
846
847 if (len == 0)
848 break;
849 off += len;
850 }
851 free (buf);
852 }
853
854 static void
855 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
856 bfd_boolean verbose)
857 {
858 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
859 const char *cmd_name;
860
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);
868
869 switch (cmd->type)
870 {
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:
876 {
877 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
878 unsigned int j;
879
880 for (j = 0; j < sizeof (uuid->uuid); j ++)
881 printf (" %02x", uuid->uuid[j]);
882 putchar ('\n');
883 }
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:
890 {
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);
899 break;
900 }
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:
906 {
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;
918 }
919 case BFD_MACH_O_LC_DYSYMTAB:
920 putchar ('\n');
921 dump_dysymtab (abfd, cmd, verbose);
922 break;
923 case BFD_MACH_O_LC_CODE_SIGNATURE:
924 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
925 case BFD_MACH_O_LC_FUNCTION_STARTS:
926 {
927 bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
928 printf
929 ("\n"
930 " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
931 linkedit->dataoff, linkedit->datasize,
932 linkedit->dataoff + linkedit->datasize);
933
934 if (verbose && cmd->type == BFD_MACH_O_LC_CODE_SIGNATURE)
935 dump_code_signature (abfd, linkedit);
936 break;
937 }
938 case BFD_MACH_O_LC_SUB_FRAMEWORK:
939 case BFD_MACH_O_LC_SUB_UMBRELLA:
940 case BFD_MACH_O_LC_SUB_LIBRARY:
941 case BFD_MACH_O_LC_SUB_CLIENT:
942 case BFD_MACH_O_LC_RPATH:
943 {
944 bfd_mach_o_str_command *str = &cmd->command.str;
945 printf (" %s\n", str->str);
946 break;
947 }
948 case BFD_MACH_O_LC_THREAD:
949 case BFD_MACH_O_LC_UNIXTHREAD:
950 dump_thread (abfd, cmd);
951 break;
952 case BFD_MACH_O_LC_ENCRYPTION_INFO:
953 {
954 bfd_mach_o_encryption_info_command *cryp =
955 &cmd->command.encryption_info;
956 printf
957 ("\n"
958 " cryptoff: 0x%08x cryptsize: 0x%08x (endoff 0x%08x)"
959 " cryptid: %u\n",
960 cryp->cryptoff, cryp->cryptsize,
961 cryp->cryptoff + cryp->cryptsize,
962 cryp->cryptid);
963 }
964 break;
965 case BFD_MACH_O_LC_DYLD_INFO:
966 putchar ('\n');
967 dump_dyld_info (abfd, cmd);
968 break;
969 case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
970 case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
971 {
972 bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
973
974 printf (" %u.%u.%u\n", ver->rel, ver->maj, ver->min);
975 }
976 break;
977 default:
978 putchar ('\n');
979 printf (" offset: 0x%08lx\n", (unsigned long)cmd->offset);
980 printf (" size: 0x%08lx\n", (unsigned long)cmd->len);
981 break;
982 }
983 putchar ('\n');
984 }
985
986 static void
987 dump_load_commands (bfd *abfd, unsigned int cmd32, unsigned int cmd64)
988 {
989 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
990 unsigned int i;
991
992 for (i = 0; i < mdata->header.ncmds; i++)
993 {
994 bfd_mach_o_load_command *cmd = &mdata->commands[i];
995
996 if (cmd32 == 0)
997 dump_load_command (abfd, cmd, FALSE);
998 else if (cmd->type == cmd32 || cmd->type == cmd64)
999 dump_load_command (abfd, cmd, TRUE);
1000 }
1001 }
1002
1003 /* Dump ABFD (according to the options[] array). */
1004
1005 static void
1006 mach_o_dump (bfd *abfd)
1007 {
1008 if (options[OPT_HEADER].selected)
1009 dump_header (abfd);
1010 if (options[OPT_SECTION].selected)
1011 dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT, BFD_MACH_O_LC_SEGMENT_64);
1012 if (options[OPT_MAP].selected)
1013 dump_section_map (abfd);
1014 if (options[OPT_LOAD].selected)
1015 dump_load_commands (abfd, 0, 0);
1016 if (options[OPT_DYSYMTAB].selected)
1017 dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0);
1018 if (options[OPT_CODESIGN].selected)
1019 dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
1020 }
1021
1022 /* Vector for Mach-O. */
1023
1024 const struct objdump_private_desc objdump_private_desc_mach_o =
1025 {
1026 mach_o_help,
1027 mach_o_filter,
1028 mach_o_dump,
1029 options
1030 };
This page took 0.086048 seconds and 5 git commands to generate.