]> git.ipfire.org Git - thirdparty/binutils-gdb.git/blob - binutils/od-macho.c
Update copyright years
[thirdparty/binutils-gdb.git] / binutils / od-macho.c
1 /* od-macho.c -- dump information about an Mach-O object file.
2 Copyright (C) 2011-2014 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 "sysdep.h"
23 #include <stddef.h>
24 #include <time.h>
25 #include "safe-ctype.h"
26 #include "bfd.h"
27 #include "objdump.h"
28 #include "bucomm.h"
29 #include "bfdlink.h"
30 #include "libbfd.h"
31 #include "mach-o.h"
32 #include "mach-o/external.h"
33 #include "mach-o/codesign.h"
34
35 /* Index of the options in the options[] array. */
36 #define OPT_HEADER 0
37 #define OPT_SECTION 1
38 #define OPT_MAP 2
39 #define OPT_LOAD 3
40 #define OPT_DYSYMTAB 4
41 #define OPT_CODESIGN 5
42 #define OPT_SEG_SPLIT_INFO 6
43
44 /* List of actions. */
45 static struct objdump_private_option options[] =
46 {
47 { "header", 0 },
48 { "section", 0 },
49 { "map", 0 },
50 { "load", 0 },
51 { "dysymtab", 0 },
52 { "codesign", 0 },
53 { "seg_split_info", 0 },
54 { NULL, 0 }
55 };
56
57 /* Display help. */
58
59 static void
60 mach_o_help (FILE *stream)
61 {
62 fprintf (stream, _("\
63 For Mach-O files:\n\
64 header Display the file header\n\
65 section Display the segments and sections commands\n\
66 map Display the section map\n\
67 load Display the load commands\n\
68 dysymtab Display the dynamic symbol table\n\
69 codesign Display code signature\n\
70 seg_split_info Display segment split info\n\
71 "));
72 }
73
74 /* Return TRUE if ABFD is handled. */
75
76 static int
77 mach_o_filter (bfd *abfd)
78 {
79 return bfd_get_flavour (abfd) == bfd_target_mach_o_flavour;
80 }
81 \f
82 static const bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
83 {
84 { "vax", BFD_MACH_O_CPU_TYPE_VAX },
85 { "mc680x0", BFD_MACH_O_CPU_TYPE_MC680x0 },
86 { "i386", BFD_MACH_O_CPU_TYPE_I386 },
87 { "mips", BFD_MACH_O_CPU_TYPE_MIPS },
88 { "mc98000", BFD_MACH_O_CPU_TYPE_MC98000 },
89 { "hppa", BFD_MACH_O_CPU_TYPE_HPPA },
90 { "arm", BFD_MACH_O_CPU_TYPE_ARM },
91 { "mc88000", BFD_MACH_O_CPU_TYPE_MC88000 },
92 { "sparc", BFD_MACH_O_CPU_TYPE_SPARC },
93 { "i860", BFD_MACH_O_CPU_TYPE_I860 },
94 { "alpha", BFD_MACH_O_CPU_TYPE_ALPHA },
95 { "powerpc", BFD_MACH_O_CPU_TYPE_POWERPC },
96 { "powerpc_64", BFD_MACH_O_CPU_TYPE_POWERPC_64 },
97 { "x86_64", BFD_MACH_O_CPU_TYPE_X86_64 },
98 { NULL, 0}
99 };
100
101 static const bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
102 {
103 { "object", BFD_MACH_O_MH_OBJECT },
104 { "execute", BFD_MACH_O_MH_EXECUTE },
105 { "fvmlib", BFD_MACH_O_MH_FVMLIB },
106 { "core", BFD_MACH_O_MH_CORE },
107 { "preload", BFD_MACH_O_MH_PRELOAD },
108 { "dylib", BFD_MACH_O_MH_DYLIB },
109 { "dylinker", BFD_MACH_O_MH_DYLINKER },
110 { "bundle", BFD_MACH_O_MH_BUNDLE },
111 { "dylib_stub", BFD_MACH_O_MH_DYLIB_STUB },
112 { "dym", BFD_MACH_O_MH_DSYM },
113 { "kext_bundle", BFD_MACH_O_MH_KEXT_BUNDLE },
114 { NULL, 0}
115 };
116
117 static const bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
118 {
119 { "noundefs", BFD_MACH_O_MH_NOUNDEFS },
120 { "incrlink", BFD_MACH_O_MH_INCRLINK },
121 { "dyldlink", BFD_MACH_O_MH_DYLDLINK },
122 { "bindatload", BFD_MACH_O_MH_BINDATLOAD },
123 { "prebound", BFD_MACH_O_MH_PREBOUND },
124 { "split_segs", BFD_MACH_O_MH_SPLIT_SEGS },
125 { "lazy_init", BFD_MACH_O_MH_LAZY_INIT },
126 { "twolevel", BFD_MACH_O_MH_TWOLEVEL },
127 { "force_flat", BFD_MACH_O_MH_FORCE_FLAT },
128 { "nomultidefs", BFD_MACH_O_MH_NOMULTIDEFS },
129 { "nofixprebinding", BFD_MACH_O_MH_NOFIXPREBINDING },
130 { "prebindable", BFD_MACH_O_MH_PREBINDABLE },
131 { "allmodsbound", BFD_MACH_O_MH_ALLMODSBOUND },
132 { "subsections_via_symbols", BFD_MACH_O_MH_SUBSECTIONS_VIA_SYMBOLS },
133 { "canonical", BFD_MACH_O_MH_CANONICAL },
134 { "weak_defines", BFD_MACH_O_MH_WEAK_DEFINES },
135 { "binds_to_weak", BFD_MACH_O_MH_BINDS_TO_WEAK },
136 { "allow_stack_execution", BFD_MACH_O_MH_ALLOW_STACK_EXECUTION },
137 { "root_safe", BFD_MACH_O_MH_ROOT_SAFE },
138 { "setuid_safe", BFD_MACH_O_MH_SETUID_SAFE },
139 { "no_reexported_dylibs", BFD_MACH_O_MH_NO_REEXPORTED_DYLIBS },
140 { "pie", BFD_MACH_O_MH_PIE },
141 { NULL, 0}
142 };
143
144 static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
145 {
146 { "segment", BFD_MACH_O_LC_SEGMENT},
147 { "symtab", BFD_MACH_O_LC_SYMTAB},
148 { "symseg", BFD_MACH_O_LC_SYMSEG},
149 { "thread", BFD_MACH_O_LC_THREAD},
150 { "unixthread", BFD_MACH_O_LC_UNIXTHREAD},
151 { "loadfvmlib", BFD_MACH_O_LC_LOADFVMLIB},
152 { "idfvmlib", BFD_MACH_O_LC_IDFVMLIB},
153 { "ident", BFD_MACH_O_LC_IDENT},
154 { "fvmfile", BFD_MACH_O_LC_FVMFILE},
155 { "prepage", BFD_MACH_O_LC_PREPAGE},
156 { "dysymtab", BFD_MACH_O_LC_DYSYMTAB},
157 { "load_dylib", BFD_MACH_O_LC_LOAD_DYLIB},
158 { "id_dylib", BFD_MACH_O_LC_ID_DYLIB},
159 { "load_dylinker", BFD_MACH_O_LC_LOAD_DYLINKER},
160 { "id_dylinker", BFD_MACH_O_LC_ID_DYLINKER},
161 { "prebound_dylib", BFD_MACH_O_LC_PREBOUND_DYLIB},
162 { "routines", BFD_MACH_O_LC_ROUTINES},
163 { "sub_framework", BFD_MACH_O_LC_SUB_FRAMEWORK},
164 { "sub_umbrella", BFD_MACH_O_LC_SUB_UMBRELLA},
165 { "sub_client", BFD_MACH_O_LC_SUB_CLIENT},
166 { "sub_library", BFD_MACH_O_LC_SUB_LIBRARY},
167 { "twolevel_hints", BFD_MACH_O_LC_TWOLEVEL_HINTS},
168 { "prebind_cksum", BFD_MACH_O_LC_PREBIND_CKSUM},
169 { "load_weak_dylib", BFD_MACH_O_LC_LOAD_WEAK_DYLIB},
170 { "segment_64", BFD_MACH_O_LC_SEGMENT_64},
171 { "routines_64", BFD_MACH_O_LC_ROUTINES_64},
172 { "uuid", BFD_MACH_O_LC_UUID},
173 { "rpath", BFD_MACH_O_LC_RPATH},
174 { "code_signature", BFD_MACH_O_LC_CODE_SIGNATURE},
175 { "segment_split_info", BFD_MACH_O_LC_SEGMENT_SPLIT_INFO},
176 { "reexport_dylib", BFD_MACH_O_LC_REEXPORT_DYLIB},
177 { "lazy_load_dylib", BFD_MACH_O_LC_LAZY_LOAD_DYLIB},
178 { "encryption_info", BFD_MACH_O_LC_ENCRYPTION_INFO},
179 { "dyld_info", BFD_MACH_O_LC_DYLD_INFO},
180 { "load_upward_lib", BFD_MACH_O_LC_LOAD_UPWARD_DYLIB},
181 { "version_min_macosx", BFD_MACH_O_LC_VERSION_MIN_MACOSX},
182 { "version_min_iphoneos", BFD_MACH_O_LC_VERSION_MIN_IPHONEOS},
183 { "function_starts", BFD_MACH_O_LC_FUNCTION_STARTS},
184 { "dyld_environment", BFD_MACH_O_LC_DYLD_ENVIRONMENT},
185 { "main", BFD_MACH_O_LC_MAIN},
186 { "data_in_code", BFD_MACH_O_LC_DATA_IN_CODE},
187 { "source_version", BFD_MACH_O_LC_SOURCE_VERSION},
188 { "dylib_code_sign_drs", BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS},
189 { NULL, 0}
190 };
191
192 static const bfd_mach_o_xlat_name bfd_mach_o_thread_x86_name[] =
193 {
194 { "thread_state32", BFD_MACH_O_x86_THREAD_STATE32},
195 { "float_state32", BFD_MACH_O_x86_FLOAT_STATE32},
196 { "exception_state32", BFD_MACH_O_x86_EXCEPTION_STATE32},
197 { "thread_state64", BFD_MACH_O_x86_THREAD_STATE64},
198 { "float_state64", BFD_MACH_O_x86_FLOAT_STATE64},
199 { "exception_state64", BFD_MACH_O_x86_EXCEPTION_STATE64},
200 { "thread_state", BFD_MACH_O_x86_THREAD_STATE},
201 { "float_state", BFD_MACH_O_x86_FLOAT_STATE},
202 { "exception_state", BFD_MACH_O_x86_EXCEPTION_STATE},
203 { "debug_state32", BFD_MACH_O_x86_DEBUG_STATE32},
204 { "debug_state64", BFD_MACH_O_x86_DEBUG_STATE64},
205 { "debug_state", BFD_MACH_O_x86_DEBUG_STATE},
206 { "state_none", BFD_MACH_O_x86_THREAD_STATE_NONE},
207 { NULL, 0 }
208 };
209 \f
210 static void
211 bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
212 unsigned long val)
213 {
214 int first = 1;
215
216 for (; table->name; table++)
217 {
218 if (table->val & val)
219 {
220 if (!first)
221 printf ("+");
222 printf ("%s", table->name);
223 val &= ~table->val;
224 first = 0;
225 }
226 }
227 if (val)
228 {
229 if (!first)
230 printf ("+");
231 printf ("0x%lx", val);
232 return;
233 }
234 if (first)
235 printf ("-");
236 }
237
238 static const char *
239 bfd_mach_o_get_name_or_null (const bfd_mach_o_xlat_name *table,
240 unsigned long val)
241 {
242 for (; table->name; table++)
243 if (table->val == val)
244 return table->name;
245 return NULL;
246 }
247
248 static const char *
249 bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
250 {
251 const char *res = bfd_mach_o_get_name_or_null (table, val);
252
253 if (res == NULL)
254 return "*UNKNOWN*";
255 else
256 return res;
257 }
258
259 static void
260 dump_header (bfd *abfd)
261 {
262 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
263 bfd_mach_o_header *h = &mdata->header;
264
265 fputs (_("Mach-O header:\n"), stdout);
266 printf (_(" magic : %08lx\n"), h->magic);
267 printf (_(" cputype : %08lx (%s)\n"), h->cputype,
268 bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
269 printf (_(" cpusubtype: %08lx\n"), h->cpusubtype);
270 printf (_(" filetype : %08lx (%s)\n"),
271 h->filetype,
272 bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
273 printf (_(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds);
274 printf (_(" sizeofcmds: %08lx\n"), h->sizeofcmds);
275 printf (_(" flags : %08lx ("), h->flags);
276 bfd_mach_o_print_flags (bfd_mach_o_header_flags_name, h->flags);
277 fputs (_(")\n"), stdout);
278 printf (_(" reserved : %08x\n"), h->reserved);
279 }
280
281 static void
282 dump_section_map (bfd *abfd)
283 {
284 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
285 unsigned int i;
286 unsigned int sec_nbr = 0;
287
288 fputs (_("Segments and Sections:\n"), stdout);
289 fputs (_(" #: Segment name Section name Address\n"), stdout);
290
291 for (i = 0; i < mdata->header.ncmds; i++)
292 {
293 bfd_mach_o_segment_command *seg;
294 bfd_mach_o_section *sec;
295
296 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
297 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
298 continue;
299
300 seg = &mdata->commands[i].command.segment;
301
302 printf ("[Segment %-16s ", seg->segname);
303 printf_vma (seg->vmaddr);
304 putchar ('-');
305 printf_vma (seg->vmaddr + seg->vmsize - 1);
306 putchar (' ');
307 putchar (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-');
308 putchar (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
309 putchar (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
310 printf ("]\n");
311
312 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
313 {
314 printf ("%02u: %-16s %-16s ", ++sec_nbr,
315 sec->segname, sec->sectname);
316 printf_vma (sec->addr);
317 putchar (' ');
318 printf_vma (sec->size);
319 printf (" %08lx\n", sec->flags);
320 }
321 }
322 }
323
324 static void
325 dump_section (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_section *sec)
326 {
327 printf (" Section: %-16s %-16s (bfdname: %s)\n",
328 sec->sectname, sec->segname, sec->bfdsection->name);
329 printf (" addr: ");
330 printf_vma (sec->addr);
331 printf (" size: ");
332 printf_vma (sec->size);
333 printf (" offset: ");
334 printf_vma (sec->offset);
335 printf ("\n");
336 printf (" align: %ld", sec->align);
337 printf (" nreloc: %lu reloff: ", sec->nreloc);
338 printf_vma (sec->reloff);
339 printf ("\n");
340 printf (" flags: %08lx (type: %s", sec->flags,
341 bfd_mach_o_get_name (bfd_mach_o_section_type_name,
342 sec->flags & BFD_MACH_O_SECTION_TYPE_MASK));
343 printf (" attr: ");
344 bfd_mach_o_print_flags (bfd_mach_o_section_attribute_name,
345 sec->flags & BFD_MACH_O_SECTION_ATTRIBUTES_MASK);
346 printf (")\n");
347 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
348 {
349 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
350 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
351 case BFD_MACH_O_S_SYMBOL_STUBS:
352 printf (" first indirect sym: %lu", sec->reserved1);
353 printf (" (%u entries)",
354 bfd_mach_o_section_get_nbr_indirect (abfd, sec));
355 break;
356 default:
357 printf (" reserved1: 0x%lx", sec->reserved1);
358 break;
359 }
360 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
361 {
362 case BFD_MACH_O_S_SYMBOL_STUBS:
363 printf (" stub size: %lu", sec->reserved2);
364 break;
365 default:
366 printf (" reserved2: 0x%lx", sec->reserved2);
367 break;
368 }
369 printf (" reserved3: 0x%lx\n", sec->reserved3);
370 }
371
372 static void
373 dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
374 {
375 bfd_mach_o_segment_command *seg = &cmd->command.segment;
376 bfd_mach_o_section *sec;
377
378 printf (" name: %s\n", *seg->segname ? seg->segname : "*none*");
379 printf (" vmaddr: ");
380 printf_vma (seg->vmaddr);
381 printf (" vmsize: ");
382 printf_vma (seg->vmsize);
383 printf ("\n");
384 printf (" fileoff: ");
385 printf_vma (seg->fileoff);
386 printf (" filesize: ");
387 printf_vma ((bfd_vma)seg->filesize);
388 printf (" endoff: ");
389 printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
390 printf ("\n");
391 printf (" nsects: %lu ", seg->nsects);
392 printf (" flags: %lx\n", seg->flags);
393 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
394 dump_section (abfd, sec);
395 }
396
397 static void
398 dump_dysymtab (bfd *abfd, bfd_mach_o_load_command *cmd, bfd_boolean verbose)
399 {
400 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
401 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
402 unsigned int i;
403
404 printf (" local symbols: idx: %10lu num: %-8lu",
405 dysymtab->ilocalsym, dysymtab->nlocalsym);
406 printf (" (nxtidx: %lu)\n",
407 dysymtab->ilocalsym + dysymtab->nlocalsym);
408 printf (" external symbols: idx: %10lu num: %-8lu",
409 dysymtab->iextdefsym, dysymtab->nextdefsym);
410 printf (" (nxtidx: %lu)\n",
411 dysymtab->iextdefsym + dysymtab->nextdefsym);
412 printf (" undefined symbols: idx: %10lu num: %-8lu",
413 dysymtab->iundefsym, dysymtab->nundefsym);
414 printf (" (nxtidx: %lu)\n",
415 dysymtab->iundefsym + dysymtab->nundefsym);
416 printf (" table of content: off: 0x%08lx num: %-8lu",
417 dysymtab->tocoff, dysymtab->ntoc);
418 printf (" (endoff: 0x%08lx)\n",
419 dysymtab->tocoff + dysymtab->ntoc * BFD_MACH_O_TABLE_OF_CONTENT_SIZE);
420 printf (" module table: off: 0x%08lx num: %-8lu",
421 dysymtab->modtaboff, dysymtab->nmodtab);
422 printf (" (endoff: 0x%08lx)\n",
423 dysymtab->modtaboff + dysymtab->nmodtab
424 * (mdata->header.version == 2 ?
425 BFD_MACH_O_DYLIB_MODULE_64_SIZE : BFD_MACH_O_DYLIB_MODULE_SIZE));
426 printf (" external reference table: off: 0x%08lx num: %-8lu",
427 dysymtab->extrefsymoff, dysymtab->nextrefsyms);
428 printf (" (endoff: 0x%08lx)\n",
429 dysymtab->extrefsymoff
430 + dysymtab->nextrefsyms * BFD_MACH_O_REFERENCE_SIZE);
431 printf (" indirect symbol table: off: 0x%08lx num: %-8lu",
432 dysymtab->indirectsymoff, dysymtab->nindirectsyms);
433 printf (" (endoff: 0x%08lx)\n",
434 dysymtab->indirectsymoff
435 + dysymtab->nindirectsyms * BFD_MACH_O_INDIRECT_SYMBOL_SIZE);
436 printf (" external relocation table: off: 0x%08lx num: %-8lu",
437 dysymtab->extreloff, dysymtab->nextrel);
438 printf (" (endoff: 0x%08lx)\n",
439 dysymtab->extreloff + dysymtab->nextrel * BFD_MACH_O_RELENT_SIZE);
440 printf (" local relocation table: off: 0x%08lx num: %-8lu",
441 dysymtab->locreloff, dysymtab->nlocrel);
442 printf (" (endoff: 0x%08lx)\n",
443 dysymtab->locreloff + dysymtab->nlocrel * BFD_MACH_O_RELENT_SIZE);
444
445 if (!verbose)
446 return;
447
448 if (dysymtab->ntoc > 0
449 || dysymtab->nindirectsyms > 0
450 || dysymtab->nextrefsyms > 0)
451 {
452 /* Try to read the symbols to display the toc or indirect symbols. */
453 bfd_mach_o_read_symtab_symbols (abfd);
454 }
455 else if (dysymtab->nmodtab > 0)
456 {
457 /* Try to read the strtab to display modules name. */
458 bfd_mach_o_read_symtab_strtab (abfd);
459 }
460
461 for (i = 0; i < dysymtab->nmodtab; i++)
462 {
463 bfd_mach_o_dylib_module *module = &dysymtab->dylib_module[i];
464 printf (" module %u:\n", i);
465 printf (" name: %lu", module->module_name_idx);
466 if (mdata->symtab && mdata->symtab->strtab)
467 printf (": %s",
468 mdata->symtab->strtab + module->module_name_idx);
469 printf ("\n");
470 printf (" extdefsym: idx: %8lu num: %lu\n",
471 module->iextdefsym, module->nextdefsym);
472 printf (" refsym: idx: %8lu num: %lu\n",
473 module->irefsym, module->nrefsym);
474 printf (" localsym: idx: %8lu num: %lu\n",
475 module->ilocalsym, module->nlocalsym);
476 printf (" extrel: idx: %8lu num: %lu\n",
477 module->iextrel, module->nextrel);
478 printf (" init: idx: %8u num: %u\n",
479 module->iinit, module->ninit);
480 printf (" term: idx: %8u num: %u\n",
481 module->iterm, module->nterm);
482 printf (" objc_module_info: addr: ");
483 printf_vma (module->objc_module_info_addr);
484 printf (" size: %lu\n", module->objc_module_info_size);
485 }
486
487 if (dysymtab->ntoc > 0)
488 {
489 bfd_mach_o_symtab_command *symtab = mdata->symtab;
490
491 printf (" table of content: (symbol/module)\n");
492 for (i = 0; i < dysymtab->ntoc; i++)
493 {
494 bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
495
496 printf (" %4u: ", i);
497 if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
498 {
499 const char *name = symtab->symbols[toc->symbol_index].symbol.name;
500 printf ("%s (%lu)", name ? name : "*invalid*",
501 toc->symbol_index);
502 }
503 else
504 printf ("%lu", toc->symbol_index);
505
506 printf (" / ");
507 if (symtab && symtab->strtab
508 && toc->module_index < dysymtab->nmodtab)
509 {
510 bfd_mach_o_dylib_module *mod;
511 mod = &dysymtab->dylib_module[toc->module_index];
512 printf ("%s (%lu)",
513 symtab->strtab + mod->module_name_idx,
514 toc->module_index);
515 }
516 else
517 printf ("%lu", toc->module_index);
518
519 printf ("\n");
520 }
521 }
522
523 if (dysymtab->nindirectsyms != 0)
524 {
525 printf (" indirect symbols:\n");
526
527 for (i = 0; i < mdata->nsects; i++)
528 {
529 bfd_mach_o_section *sec = mdata->sections[i];
530 unsigned int j, first, last;
531 bfd_mach_o_symtab_command *symtab = mdata->symtab;
532 bfd_vma addr;
533 bfd_vma entry_size;
534
535 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
536 {
537 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
538 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
539 case BFD_MACH_O_S_SYMBOL_STUBS:
540 first = sec->reserved1;
541 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
542 addr = sec->addr;
543 entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
544 printf (" for section %s.%s:\n",
545 sec->segname, sec->sectname);
546 for (j = first; j < last; j++)
547 {
548 unsigned int isym = dysymtab->indirect_syms[j];
549
550 printf (" ");
551 printf_vma (addr);
552 printf (" %5u: 0x%08x", j, isym);
553 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_LOCAL)
554 printf (" LOCAL");
555 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_ABS)
556 printf (" ABSOLUTE");
557 if (symtab && symtab->symbols
558 && isym < symtab->nsyms
559 && symtab->symbols[isym].symbol.name)
560 printf (" %s", symtab->symbols[isym].symbol.name);
561 printf ("\n");
562 addr += entry_size;
563 }
564 break;
565 default:
566 break;
567 }
568 }
569 }
570 if (dysymtab->nextrefsyms > 0)
571 {
572 bfd_mach_o_symtab_command *symtab = mdata->symtab;
573
574 printf (" external reference table: (symbol flags)\n");
575 for (i = 0; i < dysymtab->nextrefsyms; i++)
576 {
577 bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
578
579 printf (" %4u: %5lu 0x%02lx", i, ref->isym, ref->flags);
580 if (symtab && symtab->symbols
581 && ref->isym < symtab->nsyms
582 && symtab->symbols[ref->isym].symbol.name)
583 printf (" %s", symtab->symbols[ref->isym].symbol.name);
584 printf ("\n");
585 }
586 }
587
588 }
589
590 static void
591 dump_dyld_info (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
592 {
593 bfd_mach_o_dyld_info_command *info = &cmd->command.dyld_info;
594
595 printf (" rebase: off: 0x%08x size: %-8u\n",
596 info->rebase_off, info->rebase_size);
597 printf (" bind: off: 0x%08x size: %-8u\n",
598 info->bind_off, info->bind_size);
599 printf (" weak bind: off: 0x%08x size: %-8u\n",
600 info->weak_bind_off, info->weak_bind_size);
601 printf (" lazy bind: off: 0x%08x size: %-8u\n",
602 info->lazy_bind_off, info->lazy_bind_size);
603 printf (" export: off: 0x%08x size: %-8u\n",
604 info->export_off, info->export_size);
605 }
606
607 static void
608 dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
609 {
610 bfd_mach_o_thread_command *thread = &cmd->command.thread;
611 unsigned int j;
612 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
613 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
614
615 printf (" nflavours: %lu\n", thread->nflavours);
616 for (j = 0; j < thread->nflavours; j++)
617 {
618 bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
619 const bfd_mach_o_xlat_name *name_table;
620
621 printf (" %2u: flavour: 0x%08lx", j, flavour->flavour);
622 switch (mdata->header.cputype)
623 {
624 case BFD_MACH_O_CPU_TYPE_I386:
625 case BFD_MACH_O_CPU_TYPE_X86_64:
626 name_table = bfd_mach_o_thread_x86_name;
627 break;
628 default:
629 name_table = NULL;
630 break;
631 }
632 if (name_table != NULL)
633 printf (": %s", bfd_mach_o_get_name (name_table, flavour->flavour));
634 putchar ('\n');
635
636 printf (" offset: 0x%08lx size: 0x%08lx\n",
637 flavour->offset, flavour->size);
638 if (bed->_bfd_mach_o_print_thread)
639 {
640 char *buf = xmalloc (flavour->size);
641
642 if (bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
643 && bfd_bread (buf, flavour->size, abfd) == flavour->size)
644 (*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, buf);
645
646 free (buf);
647 }
648 }
649 }
650
651 static const bfd_mach_o_xlat_name bfd_mach_o_cs_magic[] =
652 {
653 { "embedded signature", BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE },
654 { "requirement", BFD_MACH_O_CS_MAGIC_REQUIREMENT },
655 { "requirements", BFD_MACH_O_CS_MAGIC_REQUIREMENTS },
656 { "code directory", BFD_MACH_O_CS_MAGIC_CODEDIRECTORY },
657 { "embedded entitlements", BFD_MACH_O_CS_MAGIC_EMBEDDED_ENTITLEMENTS },
658 { "blob wrapper", BFD_MACH_O_CS_MAGIC_BLOB_WRAPPER },
659 { NULL, 0 }
660 };
661
662 static const bfd_mach_o_xlat_name bfd_mach_o_cs_hash_type[] =
663 {
664 { "no-hash", BFD_MACH_O_CS_NO_HASH },
665 { "sha1", BFD_MACH_O_CS_HASH_SHA1 },
666 { "sha256", BFD_MACH_O_CS_HASH_SHA256 },
667 { "skein 160", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_160x256 },
668 { "skein 256", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_256x512 },
669 { NULL, 0 }
670 };
671
672 static unsigned int
673 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len);
674
675 static void
676 dump_code_signature_superblob (bfd *abfd ATTRIBUTE_UNUSED,
677 const unsigned char *buf, unsigned int len)
678 {
679 unsigned int count;
680 unsigned int i;
681
682 if (len < 12)
683 {
684 printf (_(" [bad block length]\n"));
685 return;
686 }
687 count = bfd_getb32 (buf + 8);
688 printf (_(" %u index entries:\n"), count);
689 if (len < 12 + 8 * count)
690 {
691 printf (_(" [bad block length]\n"));
692 return;
693 }
694 for (i = 0; i < count; i++)
695 {
696 unsigned int type;
697 unsigned int off;
698
699 type = bfd_getb32 (buf + 12 + 8 * i);
700 off = bfd_getb32 (buf + 12 + 8 * i + 4);
701 printf (_(" index entry %u: type: %08x, offset: %08x\n"),
702 i, type, off);
703
704 dump_code_signature_blob (abfd, buf + off, len - off);
705 }
706 }
707
708 static void
709 swap_code_codedirectory_v1_in
710 (const struct mach_o_codesign_codedirectory_external_v1 *src,
711 struct mach_o_codesign_codedirectory_v1 *dst)
712 {
713 dst->version = bfd_getb32 (src->version);
714 dst->flags = bfd_getb32 (src->flags);
715 dst->hash_offset = bfd_getb32 (src->hash_offset);
716 dst->ident_offset = bfd_getb32 (src->ident_offset);
717 dst->nbr_special_slots = bfd_getb32 (src->nbr_special_slots);
718 dst->nbr_code_slots = bfd_getb32 (src->nbr_code_slots);
719 dst->code_limit = bfd_getb32 (src->code_limit);
720 dst->hash_size = src->hash_size[0];
721 dst->hash_type = src->hash_type[0];
722 dst->spare1 = src->spare1[0];
723 dst->page_size = src->page_size[0];
724 dst->spare2 = bfd_getb32 (src->spare2);
725 }
726
727 static void
728 hexdump (unsigned int start, unsigned int len,
729 const unsigned char *buf)
730 {
731 unsigned int i, j;
732
733 for (i = 0; i < len; i += 16)
734 {
735 printf ("%08x:", start + i);
736 for (j = 0; j < 16; j++)
737 {
738 fputc (j == 8 ? '-' : ' ', stdout);
739 if (i + j < len)
740 printf ("%02x", buf[i + j]);
741 else
742 fputs (" ", stdout);
743 }
744 fputc (' ', stdout);
745 for (j = 0; j < 16; j++)
746 {
747 if (i + j < len)
748 fputc (ISPRINT (buf[i + j]) ? buf[i + j] : '.', stdout);
749 else
750 fputc (' ', stdout);
751 }
752 fputc ('\n', stdout);
753 }
754 }
755
756 static void
757 dump_code_signature_codedirectory (bfd *abfd ATTRIBUTE_UNUSED,
758 const unsigned char *buf, unsigned int len)
759 {
760 struct mach_o_codesign_codedirectory_v1 cd;
761 const char *id;
762
763 if (len < sizeof (struct mach_o_codesign_codedirectory_external_v1))
764 {
765 printf (_(" [bad block length]\n"));
766 return;
767 }
768
769 swap_code_codedirectory_v1_in
770 ((const struct mach_o_codesign_codedirectory_external_v1 *) (buf + 8), &cd);
771
772 printf (_(" version: %08x\n"), cd.version);
773 printf (_(" flags: %08x\n"), cd.flags);
774 printf (_(" hash offset: %08x\n"), cd.hash_offset);
775 id = (const char *) buf + cd.ident_offset;
776 printf (_(" ident offset: %08x (- %08x)\n"),
777 cd.ident_offset, cd.ident_offset + (unsigned) strlen (id) + 1);
778 printf (_(" identity: %s\n"), id);
779 printf (_(" nbr special slots: %08x (at offset %08x)\n"),
780 cd.nbr_special_slots,
781 cd.hash_offset - cd.nbr_special_slots * cd.hash_size);
782 printf (_(" nbr code slots: %08x\n"), cd.nbr_code_slots);
783 printf (_(" code limit: %08x\n"), cd.code_limit);
784 printf (_(" hash size: %02x\n"), cd.hash_size);
785 printf (_(" hash type: %02x (%s)\n"),
786 cd.hash_type,
787 bfd_mach_o_get_name (bfd_mach_o_cs_hash_type, cd.hash_type));
788 printf (_(" spare1: %02x\n"), cd.spare1);
789 printf (_(" page size: %02x\n"), cd.page_size);
790 printf (_(" spare2: %08x\n"), cd.spare2);
791 if (cd.version >= 0x20100)
792 printf (_(" scatter offset: %08x\n"),
793 (unsigned) bfd_getb32 (buf + 44));
794 }
795
796 static unsigned int
797 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len)
798 {
799 unsigned int magic;
800 unsigned int length;
801
802 if (len < 8)
803 {
804 printf (_(" [truncated block]\n"));
805 return 0;
806 }
807 magic = bfd_getb32 (buf);
808 length = bfd_getb32 (buf + 4);
809 if (magic == 0 || length == 0)
810 return 0;
811
812 printf (_(" magic : %08x (%s)\n"), magic,
813 bfd_mach_o_get_name (bfd_mach_o_cs_magic, magic));
814 printf (_(" length: %08x\n"), length);
815 if (length > len)
816 {
817 printf (_(" [bad block length]\n"));
818 return 0;
819 }
820
821 switch (magic)
822 {
823 case BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE:
824 dump_code_signature_superblob (abfd, buf, length);
825 break;
826 case BFD_MACH_O_CS_MAGIC_CODEDIRECTORY:
827 dump_code_signature_codedirectory (abfd, buf, length);
828 break;
829 default:
830 hexdump (0, length - 8, buf + 8);
831 break;
832 }
833 return length;
834 }
835
836 static void
837 dump_code_signature (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
838 {
839 unsigned char *buf = xmalloc (cmd->datasize);
840 unsigned int off;
841
842 if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
843 || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
844 {
845 non_fatal (_("cannot read code signature data"));
846 free (buf);
847 return;
848 }
849 for (off = 0; off < cmd->datasize;)
850 {
851 unsigned int len;
852
853 len = dump_code_signature_blob (abfd, buf + off, cmd->datasize - off);
854
855 if (len == 0)
856 break;
857 off += len;
858 }
859 free (buf);
860 }
861
862 static void
863 dump_segment_split_info (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
864 {
865 unsigned char *buf = xmalloc (cmd->datasize);
866 unsigned char *p;
867 unsigned int len;
868 bfd_vma addr = 0;
869
870 if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
871 || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
872 {
873 non_fatal (_("cannot read segment split info"));
874 free (buf);
875 return;
876 }
877 if (buf[cmd->datasize - 1] != 0)
878 {
879 non_fatal (_("segment split info is not nul terminated"));
880 free (buf);
881 return;
882 }
883
884 switch (buf[0])
885 {
886 case 0:
887 printf (_(" 32 bit pointers:\n"));
888 break;
889 case 1:
890 printf (_(" 64 bit pointers:\n"));
891 break;
892 case 2:
893 printf (_(" PPC hi-16:\n"));
894 break;
895 default:
896 printf (_(" Unhandled location type %u\n"), buf[0]);
897 break;
898 }
899 for (p = buf + 1; *p != 0; p += len)
900 {
901 addr += read_unsigned_leb128 (abfd, p, &len);
902 fputs (" ", stdout);
903 bfd_printf_vma (abfd, addr);
904 putchar ('\n');
905 }
906 free (buf);
907 }
908
909 static void
910 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
911 bfd_boolean verbose)
912 {
913 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
914 const char *cmd_name;
915
916 cmd_name = bfd_mach_o_get_name_or_null
917 (bfd_mach_o_load_command_name, cmd->type);
918 printf ("Load command ");
919 if (cmd_name == NULL)
920 printf ("0x%02x:", cmd->type);
921 else
922 printf ("%s:", cmd_name);
923
924 switch (cmd->type)
925 {
926 case BFD_MACH_O_LC_SEGMENT:
927 case BFD_MACH_O_LC_SEGMENT_64:
928 dump_segment (abfd, cmd);
929 break;
930 case BFD_MACH_O_LC_UUID:
931 {
932 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
933 unsigned int j;
934
935 for (j = 0; j < sizeof (uuid->uuid); j ++)
936 printf (" %02x", uuid->uuid[j]);
937 putchar ('\n');
938 }
939 break;
940 case BFD_MACH_O_LC_LOAD_DYLIB:
941 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
942 case BFD_MACH_O_LC_REEXPORT_DYLIB:
943 case BFD_MACH_O_LC_ID_DYLIB:
944 case BFD_MACH_O_LC_LOAD_UPWARD_DYLIB:
945 {
946 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
947 printf (" %s\n", dylib->name_str);
948 printf (" time stamp: 0x%08lx\n",
949 dylib->timestamp);
950 printf (" current version: 0x%08lx\n",
951 dylib->current_version);
952 printf (" comptibility version: 0x%08lx\n",
953 dylib->compatibility_version);
954 }
955 break;
956 case BFD_MACH_O_LC_LOAD_DYLINKER:
957 case BFD_MACH_O_LC_ID_DYLINKER:
958 printf (" %s\n", cmd->command.dylinker.name_str);
959 break;
960 case BFD_MACH_O_LC_SYMTAB:
961 {
962 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
963 printf ("\n"
964 " symoff: 0x%08x nsyms: %8u (endoff: 0x%08x)\n",
965 symtab->symoff, symtab->nsyms,
966 symtab->symoff + symtab->nsyms
967 * (mdata->header.version == 2
968 ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE));
969 printf (" stroff: 0x%08x strsize: %8u (endoff: 0x%08x)\n",
970 symtab->stroff, symtab->strsize,
971 symtab->stroff + symtab->strsize);
972 break;
973 }
974 case BFD_MACH_O_LC_DYSYMTAB:
975 putchar ('\n');
976 dump_dysymtab (abfd, cmd, verbose);
977 break;
978 case BFD_MACH_O_LC_LOADFVMLIB:
979 case BFD_MACH_O_LC_IDFVMLIB:
980 {
981 bfd_mach_o_fvmlib_command *fvmlib = &cmd->command.fvmlib;
982 printf (" %s\n", fvmlib->name_str);
983 printf (" minor version: 0x%08x\n", fvmlib->minor_version);
984 printf (" header address: 0x%08x\n", fvmlib->header_addr);
985 }
986 break;
987 case BFD_MACH_O_LC_CODE_SIGNATURE:
988 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
989 case BFD_MACH_O_LC_FUNCTION_STARTS:
990 {
991 bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
992 printf
993 ("\n"
994 " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
995 linkedit->dataoff, linkedit->datasize,
996 linkedit->dataoff + linkedit->datasize);
997
998 if (verbose && cmd->type == BFD_MACH_O_LC_CODE_SIGNATURE)
999 dump_code_signature (abfd, linkedit);
1000 else if (verbose && cmd->type == BFD_MACH_O_LC_SEGMENT_SPLIT_INFO)
1001 dump_segment_split_info (abfd, linkedit);
1002 break;
1003 }
1004 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1005 case BFD_MACH_O_LC_SUB_UMBRELLA:
1006 case BFD_MACH_O_LC_SUB_LIBRARY:
1007 case BFD_MACH_O_LC_SUB_CLIENT:
1008 case BFD_MACH_O_LC_RPATH:
1009 {
1010 bfd_mach_o_str_command *str = &cmd->command.str;
1011 printf (" %s\n", str->str);
1012 break;
1013 }
1014 case BFD_MACH_O_LC_THREAD:
1015 case BFD_MACH_O_LC_UNIXTHREAD:
1016 dump_thread (abfd, cmd);
1017 break;
1018 case BFD_MACH_O_LC_ENCRYPTION_INFO:
1019 {
1020 bfd_mach_o_encryption_info_command *cryp =
1021 &cmd->command.encryption_info;
1022 printf
1023 ("\n"
1024 " cryptoff: 0x%08x cryptsize: 0x%08x (endoff 0x%08x)"
1025 " cryptid: %u\n",
1026 cryp->cryptoff, cryp->cryptsize,
1027 cryp->cryptoff + cryp->cryptsize,
1028 cryp->cryptid);
1029 }
1030 break;
1031 case BFD_MACH_O_LC_DYLD_INFO:
1032 putchar ('\n');
1033 dump_dyld_info (abfd, cmd);
1034 break;
1035 case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
1036 case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
1037 {
1038 bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
1039
1040 printf (" %u.%u.%u\n", ver->rel, ver->maj, ver->min);
1041 }
1042 break;
1043 case BFD_MACH_O_LC_SOURCE_VERSION:
1044 {
1045 bfd_mach_o_source_version_command *version =
1046 &cmd->command.source_version;
1047 printf ("\n"
1048 " version a.b.c.d.e: %u.%u.%u.%u.%u\n",
1049 version->a, version->b, version->c, version->d, version->e);
1050 break;
1051 }
1052 case BFD_MACH_O_LC_MAIN:
1053 {
1054 bfd_mach_o_main_command *entry = &cmd->command.main;
1055 printf ("\n"
1056 " entry offset: ");
1057 printf_vma (entry->entryoff);
1058 printf ("\n"
1059 " stack size: ");
1060 printf_vma (entry->stacksize);
1061 printf ("\n");
1062 break;
1063 }
1064 default:
1065 putchar ('\n');
1066 printf (" offset: 0x%08lx\n", (unsigned long)cmd->offset);
1067 printf (" size: 0x%08lx\n", (unsigned long)cmd->len);
1068 break;
1069 }
1070 putchar ('\n');
1071 }
1072
1073 static void
1074 dump_load_commands (bfd *abfd, unsigned int cmd32, unsigned int cmd64)
1075 {
1076 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1077 unsigned int i;
1078
1079 for (i = 0; i < mdata->header.ncmds; i++)
1080 {
1081 bfd_mach_o_load_command *cmd = &mdata->commands[i];
1082
1083 if (cmd32 == 0)
1084 dump_load_command (abfd, cmd, FALSE);
1085 else if (cmd->type == cmd32 || cmd->type == cmd64)
1086 dump_load_command (abfd, cmd, TRUE);
1087 }
1088 }
1089
1090 /* Dump ABFD (according to the options[] array). */
1091
1092 static void
1093 mach_o_dump (bfd *abfd)
1094 {
1095 if (options[OPT_HEADER].selected)
1096 dump_header (abfd);
1097 if (options[OPT_SECTION].selected)
1098 dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT, BFD_MACH_O_LC_SEGMENT_64);
1099 if (options[OPT_MAP].selected)
1100 dump_section_map (abfd);
1101 if (options[OPT_LOAD].selected)
1102 dump_load_commands (abfd, 0, 0);
1103 if (options[OPT_DYSYMTAB].selected)
1104 dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0);
1105 if (options[OPT_CODESIGN].selected)
1106 dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
1107 if (options[OPT_SEG_SPLIT_INFO].selected)
1108 dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT_SPLIT_INFO, 0);
1109 }
1110
1111 /* Vector for Mach-O. */
1112
1113 const struct objdump_private_desc objdump_private_desc_mach_o =
1114 {
1115 mach_o_help,
1116 mach_o_filter,
1117 mach_o_dump,
1118 options
1119 };