* readelf.c (get_symbol_type): Add ELFOSABI_FREEBSD to the
[binutils-gdb.git] / binutils / od-macho.c
1 /* od-macho.c -- dump information about an Mach-O object file.
2 Copyright 2011 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
33 /* Index of the options in the options[] array. */
34 #define OPT_HEADER 0
35 #define OPT_SECTION 1
36 #define OPT_MAP 2
37 #define OPT_LOAD 3
38 #define OPT_DYSYMTAB 4
39
40 /* List of actions. */
41 static struct objdump_private_option options[] =
42 {
43 { "header", 0 },
44 { "section", 0 },
45 { "map", 0 },
46 { "load", 0 },
47 { "dysymtab", 0 },
48 { NULL, 0 }
49 };
50
51 /* Display help. */
52
53 static void
54 mach_o_help (FILE *stream)
55 {
56 fprintf (stream, _("\
57 For Mach-O files:\n\
58 header Display the file header\n\
59 section Display the segments and sections commands\n\
60 map Display the section map\n\
61 load Display the load commands\n\
62 dysymtab Display the dynamic symbol table\n\
63 "));
64 }
65
66 /* Return TRUE if ABFD is handled. */
67
68 static int
69 mach_o_filter (bfd *abfd)
70 {
71 return bfd_get_flavour (abfd) == bfd_target_mach_o_flavour;
72 }
73 \f
74 static const bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
75 {
76 { "vax", BFD_MACH_O_CPU_TYPE_VAX },
77 { "mc680x0", BFD_MACH_O_CPU_TYPE_MC680x0 },
78 { "i386", BFD_MACH_O_CPU_TYPE_I386 },
79 { "mips", BFD_MACH_O_CPU_TYPE_MIPS },
80 { "mc98000", BFD_MACH_O_CPU_TYPE_MC98000 },
81 { "hppa", BFD_MACH_O_CPU_TYPE_HPPA },
82 { "arm", BFD_MACH_O_CPU_TYPE_ARM },
83 { "mc88000", BFD_MACH_O_CPU_TYPE_MC88000 },
84 { "sparc", BFD_MACH_O_CPU_TYPE_SPARC },
85 { "i860", BFD_MACH_O_CPU_TYPE_I860 },
86 { "alpha", BFD_MACH_O_CPU_TYPE_ALPHA },
87 { "powerpc", BFD_MACH_O_CPU_TYPE_POWERPC },
88 { "powerpc_64", BFD_MACH_O_CPU_TYPE_POWERPC_64 },
89 { "x86_64", BFD_MACH_O_CPU_TYPE_X86_64 },
90 { NULL, 0}
91 };
92
93 static const bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
94 {
95 { "object", BFD_MACH_O_MH_OBJECT },
96 { "execute", BFD_MACH_O_MH_EXECUTE },
97 { "fvmlib", BFD_MACH_O_MH_FVMLIB },
98 { "core", BFD_MACH_O_MH_CORE },
99 { "preload", BFD_MACH_O_MH_PRELOAD },
100 { "dylib", BFD_MACH_O_MH_DYLIB },
101 { "dylinker", BFD_MACH_O_MH_DYLINKER },
102 { "bundle", BFD_MACH_O_MH_BUNDLE },
103 { "dylib_stub", BFD_MACH_O_MH_DYLIB_STUB },
104 { "dym", BFD_MACH_O_MH_DSYM },
105 { "kext_bundle", BFD_MACH_O_MH_KEXT_BUNDLE },
106 { NULL, 0}
107 };
108
109 static const bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
110 {
111 { "noundefs", BFD_MACH_O_MH_NOUNDEFS },
112 { "incrlink", BFD_MACH_O_MH_INCRLINK },
113 { "dyldlink", BFD_MACH_O_MH_DYLDLINK },
114 { "bindatload", BFD_MACH_O_MH_BINDATLOAD },
115 { "prebound", BFD_MACH_O_MH_PREBOUND },
116 { "split_segs", BFD_MACH_O_MH_SPLIT_SEGS },
117 { "lazy_init", BFD_MACH_O_MH_LAZY_INIT },
118 { "twolevel", BFD_MACH_O_MH_TWOLEVEL },
119 { "force_flat", BFD_MACH_O_MH_FORCE_FLAT },
120 { "nomultidefs", BFD_MACH_O_MH_NOMULTIDEFS },
121 { "nofixprebinding", BFD_MACH_O_MH_NOFIXPREBINDING },
122 { "prebindable", BFD_MACH_O_MH_PREBINDABLE },
123 { "allmodsbound", BFD_MACH_O_MH_ALLMODSBOUND },
124 { "subsections_via_symbols", BFD_MACH_O_MH_SUBSECTIONS_VIA_SYMBOLS },
125 { "canonical", BFD_MACH_O_MH_CANONICAL },
126 { "weak_defines", BFD_MACH_O_MH_WEAK_DEFINES },
127 { "binds_to_weak", BFD_MACH_O_MH_BINDS_TO_WEAK },
128 { "allow_stack_execution", BFD_MACH_O_MH_ALLOW_STACK_EXECUTION },
129 { "root_safe", BFD_MACH_O_MH_ROOT_SAFE },
130 { "setuid_safe", BFD_MACH_O_MH_SETUID_SAFE },
131 { "no_reexported_dylibs", BFD_MACH_O_MH_NO_REEXPORTED_DYLIBS },
132 { "pie", BFD_MACH_O_MH_PIE },
133 { NULL, 0}
134 };
135
136 static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
137 {
138 { "segment", BFD_MACH_O_LC_SEGMENT},
139 { "symtab", BFD_MACH_O_LC_SYMTAB},
140 { "symseg", BFD_MACH_O_LC_SYMSEG},
141 { "thread", BFD_MACH_O_LC_THREAD},
142 { "unixthread", BFD_MACH_O_LC_UNIXTHREAD},
143 { "loadfvmlib", BFD_MACH_O_LC_LOADFVMLIB},
144 { "idfvmlib", BFD_MACH_O_LC_IDFVMLIB},
145 { "ident", BFD_MACH_O_LC_IDENT},
146 { "fvmfile", BFD_MACH_O_LC_FVMFILE},
147 { "prepage", BFD_MACH_O_LC_PREPAGE},
148 { "dysymtab", BFD_MACH_O_LC_DYSYMTAB},
149 { "load_dylib", BFD_MACH_O_LC_LOAD_DYLIB},
150 { "id_dylib", BFD_MACH_O_LC_ID_DYLIB},
151 { "load_dylinker", BFD_MACH_O_LC_LOAD_DYLINKER},
152 { "id_dylinker", BFD_MACH_O_LC_ID_DYLINKER},
153 { "prebound_dylib", BFD_MACH_O_LC_PREBOUND_DYLIB},
154 { "routines", BFD_MACH_O_LC_ROUTINES},
155 { "sub_framework", BFD_MACH_O_LC_SUB_FRAMEWORK},
156 { "sub_umbrella", BFD_MACH_O_LC_SUB_UMBRELLA},
157 { "sub_client", BFD_MACH_O_LC_SUB_CLIENT},
158 { "sub_library", BFD_MACH_O_LC_SUB_LIBRARY},
159 { "twolevel_hints", BFD_MACH_O_LC_TWOLEVEL_HINTS},
160 { "prebind_cksum", BFD_MACH_O_LC_PREBIND_CKSUM},
161 { "load_weak_dylib", BFD_MACH_O_LC_LOAD_WEAK_DYLIB},
162 { "segment_64", BFD_MACH_O_LC_SEGMENT_64},
163 { "routines_64", BFD_MACH_O_LC_ROUTINES_64},
164 { "uuid", BFD_MACH_O_LC_UUID},
165 { "rpath", BFD_MACH_O_LC_RPATH},
166 { "code_signature", BFD_MACH_O_LC_CODE_SIGNATURE},
167 { "segment_split_info", BFD_MACH_O_LC_SEGMENT_SPLIT_INFO},
168 { "reexport_dylib", BFD_MACH_O_LC_REEXPORT_DYLIB},
169 { "lazy_load_dylib", BFD_MACH_O_LC_LAZY_LOAD_DYLIB},
170 { "encryption_info", BFD_MACH_O_LC_ENCRYPTION_INFO},
171 { "dyld_info", BFD_MACH_O_LC_DYLD_INFO},
172 { "load_upward_lib", BFD_MACH_O_LC_LOAD_UPWARD_DYLIB},
173 { "version_min_macosx", BFD_MACH_O_LC_VERSION_MIN_MACOSX},
174 { "version_min_iphoneos", BFD_MACH_O_LC_VERSION_MIN_IPHONEOS},
175 { "function_starts", BFD_MACH_O_LC_FUNCTION_STARTS},
176 { "dyld_environment", BFD_MACH_O_LC_DYLD_ENVIRONMENT},
177 { NULL, 0}
178 };
179
180 static const bfd_mach_o_xlat_name bfd_mach_o_thread_x86_name[] =
181 {
182 { "thread_state32", BFD_MACH_O_x86_THREAD_STATE32},
183 { "float_state32", BFD_MACH_O_x86_FLOAT_STATE32},
184 { "exception_state32", BFD_MACH_O_x86_EXCEPTION_STATE32},
185 { "thread_state64", BFD_MACH_O_x86_THREAD_STATE64},
186 { "float_state64", BFD_MACH_O_x86_FLOAT_STATE64},
187 { "exception_state64", BFD_MACH_O_x86_EXCEPTION_STATE64},
188 { "thread_state", BFD_MACH_O_x86_THREAD_STATE},
189 { "float_state", BFD_MACH_O_x86_FLOAT_STATE},
190 { "exception_state", BFD_MACH_O_x86_EXCEPTION_STATE},
191 { "debug_state32", BFD_MACH_O_x86_DEBUG_STATE32},
192 { "debug_state64", BFD_MACH_O_x86_DEBUG_STATE64},
193 { "debug_state", BFD_MACH_O_x86_DEBUG_STATE},
194 { "state_none", BFD_MACH_O_x86_THREAD_STATE_NONE},
195 { NULL, 0 }
196 };
197 \f
198 static void
199 bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
200 unsigned long val)
201 {
202 int first = 1;
203
204 for (; table->name; table++)
205 {
206 if (table->val & val)
207 {
208 if (!first)
209 printf ("+");
210 printf ("%s", table->name);
211 val &= ~table->val;
212 first = 0;
213 }
214 }
215 if (val)
216 {
217 if (!first)
218 printf ("+");
219 printf ("0x%lx", val);
220 return;
221 }
222 if (first)
223 printf ("-");
224 }
225
226 static const char *
227 bfd_mach_o_get_name_or_null (const bfd_mach_o_xlat_name *table,
228 unsigned long val)
229 {
230 for (; table->name; table++)
231 if (table->val == val)
232 return table->name;
233 return NULL;
234 }
235
236 static const char *
237 bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
238 {
239 const char *res = bfd_mach_o_get_name_or_null (table, val);
240
241 if (res == NULL)
242 return "*UNKNOWN*";
243 else
244 return res;
245 }
246
247 static void
248 dump_header (bfd *abfd)
249 {
250 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
251 bfd_mach_o_header *h = &mdata->header;
252
253 fputs (_("Mach-O header:\n"), stdout);
254 printf (_(" magic : %08lx\n"), h->magic);
255 printf (_(" cputype : %08lx (%s)\n"), h->cputype,
256 bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
257 printf (_(" cpusubtype: %08lx\n"), h->cpusubtype);
258 printf (_(" filetype : %08lx (%s)\n"),
259 h->filetype,
260 bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
261 printf (_(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds);
262 printf (_(" sizeofcmds: %08lx\n"), h->sizeofcmds);
263 printf (_(" flags : %08lx ("), h->flags);
264 bfd_mach_o_print_flags (bfd_mach_o_header_flags_name, h->flags);
265 fputs (_(")\n"), stdout);
266 printf (_(" reserved : %08x\n"), h->reserved);
267 }
268
269 static void
270 dump_section_map (bfd *abfd)
271 {
272 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
273 unsigned int i;
274 unsigned int sec_nbr = 0;
275
276 fputs (_("Segments and Sections:\n"), stdout);
277 fputs (_(" #: Segment name Section name Address\n"), stdout);
278
279 for (i = 0; i < mdata->header.ncmds; i++)
280 {
281 bfd_mach_o_segment_command *seg;
282 bfd_mach_o_section *sec;
283
284 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
285 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
286 continue;
287
288 seg = &mdata->commands[i].command.segment;
289
290 printf ("[Segment %-16s ", seg->segname);
291 printf_vma (seg->vmaddr);
292 putchar ('-');
293 printf_vma (seg->vmaddr + seg->vmsize - 1);
294 putchar (' ');
295 putchar (seg->initprot & BFD_MACH_O_PROT_READ ? 'r' : '-');
296 putchar (seg->initprot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
297 putchar (seg->initprot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
298 printf ("]\n");
299
300 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
301 {
302 printf ("%02u: %-16s %-16s ", ++sec_nbr,
303 sec->segname, sec->sectname);
304 printf_vma (sec->addr);
305 putchar (' ');
306 printf_vma (sec->size);
307 printf (" %08lx\n", sec->flags);
308 }
309 }
310 }
311
312 static void
313 dump_section (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_section *sec)
314 {
315 printf (" Section: %-16s %-16s (bfdname: %s)\n",
316 sec->sectname, sec->segname, sec->bfdsection->name);
317 printf (" addr: ");
318 printf_vma (sec->addr);
319 printf (" size: ");
320 printf_vma (sec->size);
321 printf (" offset: ");
322 printf_vma (sec->offset);
323 printf ("\n");
324 printf (" align: %ld", sec->align);
325 printf (" nreloc: %lu reloff: ", sec->nreloc);
326 printf_vma (sec->reloff);
327 printf ("\n");
328 printf (" flags: %08lx (type: %s", sec->flags,
329 bfd_mach_o_get_name (bfd_mach_o_section_type_name,
330 sec->flags & BFD_MACH_O_SECTION_TYPE_MASK));
331 printf (" attr: ");
332 bfd_mach_o_print_flags (bfd_mach_o_section_attribute_name,
333 sec->flags & BFD_MACH_O_SECTION_ATTRIBUTES_MASK);
334 printf (")\n");
335 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
336 {
337 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
338 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
339 case BFD_MACH_O_S_SYMBOL_STUBS:
340 printf (" first indirect sym: %lu", sec->reserved1);
341 printf (" (%u entries)",
342 bfd_mach_o_section_get_nbr_indirect (abfd, sec));
343 break;
344 default:
345 printf (" reserved1: 0x%lx", sec->reserved1);
346 break;
347 }
348 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
349 {
350 case BFD_MACH_O_S_SYMBOL_STUBS:
351 printf (" stub size: %lu", sec->reserved2);
352 break;
353 default:
354 printf (" reserved2: 0x%lx", sec->reserved2);
355 break;
356 }
357 printf (" reserved3: 0x%lx\n", sec->reserved3);
358 }
359
360 static void
361 dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
362 {
363 bfd_mach_o_segment_command *seg = &cmd->command.segment;
364 bfd_mach_o_section *sec;
365
366 printf (" name: %s\n", *seg->segname ? seg->segname : "*none*");
367 printf (" vmaddr: ");
368 printf_vma (seg->vmaddr);
369 printf (" vmsize: ");
370 printf_vma (seg->vmsize);
371 printf ("\n");
372 printf (" fileoff: ");
373 printf_vma (seg->fileoff);
374 printf (" filesize: ");
375 printf_vma ((bfd_vma)seg->filesize);
376 printf (" endoff: ");
377 printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
378 printf ("\n");
379 printf (" nsects: %lu ", seg->nsects);
380 printf (" flags: %lx\n", seg->flags);
381 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
382 dump_section (abfd, sec);
383 }
384
385 static void
386 dump_dysymtab (bfd *abfd, bfd_mach_o_load_command *cmd, bfd_boolean verbose)
387 {
388 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
389 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
390 unsigned int i;
391
392 printf (" local symbols: idx: %10lu num: %-8lu",
393 dysymtab->ilocalsym, dysymtab->nlocalsym);
394 printf (" (nxtidx: %lu)\n",
395 dysymtab->ilocalsym + dysymtab->nlocalsym);
396 printf (" external symbols: idx: %10lu num: %-8lu",
397 dysymtab->iextdefsym, dysymtab->nextdefsym);
398 printf (" (nxtidx: %lu)\n",
399 dysymtab->iextdefsym + dysymtab->nextdefsym);
400 printf (" undefined symbols: idx: %10lu num: %-8lu",
401 dysymtab->iundefsym, dysymtab->nundefsym);
402 printf (" (nxtidx: %lu)\n",
403 dysymtab->iundefsym + dysymtab->nundefsym);
404 printf (" table of content: off: 0x%08lx num: %-8lu",
405 dysymtab->tocoff, dysymtab->ntoc);
406 printf (" (endoff: 0x%08lx)\n",
407 dysymtab->tocoff + dysymtab->ntoc * BFD_MACH_O_TABLE_OF_CONTENT_SIZE);
408 printf (" module table: off: 0x%08lx num: %-8lu",
409 dysymtab->modtaboff, dysymtab->nmodtab);
410 printf (" (endoff: 0x%08lx)\n",
411 dysymtab->modtaboff + dysymtab->nmodtab
412 * (mdata->header.version == 2 ?
413 BFD_MACH_O_DYLIB_MODULE_64_SIZE : BFD_MACH_O_DYLIB_MODULE_SIZE));
414 printf (" external reference table: off: 0x%08lx num: %-8lu",
415 dysymtab->extrefsymoff, dysymtab->nextrefsyms);
416 printf (" (endoff: 0x%08lx)\n",
417 dysymtab->extrefsymoff
418 + dysymtab->nextrefsyms * BFD_MACH_O_REFERENCE_SIZE);
419 printf (" indirect symbol table: off: 0x%08lx num: %-8lu",
420 dysymtab->indirectsymoff, dysymtab->nindirectsyms);
421 printf (" (endoff: 0x%08lx)\n",
422 dysymtab->indirectsymoff
423 + dysymtab->nindirectsyms * BFD_MACH_O_INDIRECT_SYMBOL_SIZE);
424 printf (" external relocation table: off: 0x%08lx num: %-8lu",
425 dysymtab->extreloff, dysymtab->nextrel);
426 printf (" (endoff: 0x%08lx)\n",
427 dysymtab->extreloff + dysymtab->nextrel * BFD_MACH_O_RELENT_SIZE);
428 printf (" local relocation table: off: 0x%08lx num: %-8lu",
429 dysymtab->locreloff, dysymtab->nlocrel);
430 printf (" (endoff: 0x%08lx)\n",
431 dysymtab->locreloff + dysymtab->nlocrel * BFD_MACH_O_RELENT_SIZE);
432
433 if (!verbose)
434 return;
435
436 if (dysymtab->ntoc > 0
437 || dysymtab->nindirectsyms > 0
438 || dysymtab->nextrefsyms > 0)
439 {
440 /* Try to read the symbols to display the toc or indirect symbols. */
441 bfd_mach_o_read_symtab_symbols (abfd);
442 }
443 else if (dysymtab->nmodtab > 0)
444 {
445 /* Try to read the strtab to display modules name. */
446 bfd_mach_o_read_symtab_strtab (abfd);
447 }
448
449 for (i = 0; i < dysymtab->nmodtab; i++)
450 {
451 bfd_mach_o_dylib_module *module = &dysymtab->dylib_module[i];
452 printf (" module %u:\n", i);
453 printf (" name: %lu", module->module_name_idx);
454 if (mdata->symtab && mdata->symtab->strtab)
455 printf (": %s",
456 mdata->symtab->strtab + module->module_name_idx);
457 printf ("\n");
458 printf (" extdefsym: idx: %8lu num: %lu\n",
459 module->iextdefsym, module->nextdefsym);
460 printf (" refsym: idx: %8lu num: %lu\n",
461 module->irefsym, module->nrefsym);
462 printf (" localsym: idx: %8lu num: %lu\n",
463 module->ilocalsym, module->nlocalsym);
464 printf (" extrel: idx: %8lu num: %lu\n",
465 module->iextrel, module->nextrel);
466 printf (" init: idx: %8u num: %u\n",
467 module->iinit, module->ninit);
468 printf (" term: idx: %8u num: %u\n",
469 module->iterm, module->nterm);
470 printf (" objc_module_info: addr: ");
471 printf_vma (module->objc_module_info_addr);
472 printf (" size: %lu\n", module->objc_module_info_size);
473 }
474
475 if (dysymtab->ntoc > 0)
476 {
477 bfd_mach_o_symtab_command *symtab = mdata->symtab;
478
479 printf (" table of content: (symbol/module)\n");
480 for (i = 0; i < dysymtab->ntoc; i++)
481 {
482 bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
483
484 printf (" %4u: ", i);
485 if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
486 {
487 const char *name = symtab->symbols[toc->symbol_index].symbol.name;
488 printf ("%s (%lu)", name ? name : "*invalid*",
489 toc->symbol_index);
490 }
491 else
492 printf ("%lu", toc->symbol_index);
493
494 printf (" / ");
495 if (symtab && symtab->strtab
496 && toc->module_index < dysymtab->nmodtab)
497 {
498 bfd_mach_o_dylib_module *mod;
499 mod = &dysymtab->dylib_module[toc->module_index];
500 printf ("%s (%lu)",
501 symtab->strtab + mod->module_name_idx,
502 toc->module_index);
503 }
504 else
505 printf ("%lu", toc->module_index);
506
507 printf ("\n");
508 }
509 }
510
511 if (dysymtab->nindirectsyms != 0)
512 {
513 printf (" indirect symbols:\n");
514
515 for (i = 0; i < mdata->nsects; i++)
516 {
517 bfd_mach_o_section *sec = mdata->sections[i];
518 unsigned int j, first, last;
519 bfd_mach_o_symtab_command *symtab = mdata->symtab;
520 bfd_vma addr;
521 bfd_vma entry_size;
522
523 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
524 {
525 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
526 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
527 case BFD_MACH_O_S_SYMBOL_STUBS:
528 first = sec->reserved1;
529 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
530 addr = sec->addr;
531 entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
532 printf (" for section %s.%s:\n",
533 sec->segname, sec->sectname);
534 for (j = first; j < last; j++)
535 {
536 unsigned int isym = dysymtab->indirect_syms[j];
537
538 printf (" ");
539 printf_vma (addr);
540 printf (" %5u: 0x%08x", j, isym);
541 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_LOCAL)
542 printf (" LOCAL");
543 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_ABS)
544 printf (" ABSOLUTE");
545 if (symtab && symtab->symbols
546 && isym < symtab->nsyms
547 && symtab->symbols[isym].symbol.name)
548 printf (" %s", symtab->symbols[isym].symbol.name);
549 printf ("\n");
550 addr += entry_size;
551 }
552 break;
553 default:
554 break;
555 }
556 }
557 }
558 if (dysymtab->nextrefsyms > 0)
559 {
560 bfd_mach_o_symtab_command *symtab = mdata->symtab;
561
562 printf (" external reference table: (symbol flags)\n");
563 for (i = 0; i < dysymtab->nextrefsyms; i++)
564 {
565 bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
566
567 printf (" %4u: %5lu 0x%02lx", i, ref->isym, ref->flags);
568 if (symtab && symtab->symbols
569 && ref->isym < symtab->nsyms
570 && symtab->symbols[ref->isym].symbol.name)
571 printf (" %s", symtab->symbols[ref->isym].symbol.name);
572 printf ("\n");
573 }
574 }
575
576 }
577
578 static void
579 dump_dyld_info (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
580 {
581 bfd_mach_o_dyld_info_command *info = &cmd->command.dyld_info;
582
583 printf (" rebase: off: 0x%08x size: %-8u\n",
584 info->rebase_off, info->rebase_size);
585 printf (" bind: off: 0x%08x size: %-8u\n",
586 info->bind_off, info->bind_size);
587 printf (" weak bind: off: 0x%08x size: %-8u\n",
588 info->weak_bind_off, info->weak_bind_size);
589 printf (" lazy bind: off: 0x%08x size: %-8u\n",
590 info->lazy_bind_off, info->lazy_bind_size);
591 printf (" export: off: 0x%08x size: %-8u\n",
592 info->export_off, info->export_size);
593 }
594
595 static void
596 dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
597 {
598 bfd_mach_o_thread_command *thread = &cmd->command.thread;
599 unsigned int j;
600 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
601 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
602
603 printf (" nflavours: %lu\n", thread->nflavours);
604 for (j = 0; j < thread->nflavours; j++)
605 {
606 bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
607 const bfd_mach_o_xlat_name *name_table;
608
609 printf (" %2u: flavour: 0x%08lx", j, flavour->flavour);
610 switch (mdata->header.cputype)
611 {
612 case BFD_MACH_O_CPU_TYPE_I386:
613 case BFD_MACH_O_CPU_TYPE_X86_64:
614 name_table = bfd_mach_o_thread_x86_name;
615 break;
616 default:
617 name_table = NULL;
618 break;
619 }
620 if (name_table != NULL)
621 printf (": %s", bfd_mach_o_get_name (name_table, flavour->flavour));
622 putchar ('\n');
623
624 printf (" offset: 0x%08lx size: 0x%08lx\n",
625 flavour->offset, flavour->size);
626 if (bed->_bfd_mach_o_print_thread)
627 {
628 char *buf = xmalloc (flavour->size);
629
630 if (buf
631 && bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
632 && (bfd_bread (buf, flavour->size, abfd)
633 == flavour->size))
634 (*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, buf);
635 free (buf);
636 }
637 }
638 }
639
640 static void
641 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
642 bfd_boolean verbose)
643 {
644 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
645 const char *cmd_name;
646
647 cmd_name = bfd_mach_o_get_name_or_null
648 (bfd_mach_o_load_command_name, cmd->type);
649 printf ("Load command ");
650 if (cmd_name == NULL)
651 printf ("0x%02x:", cmd->type);
652 else
653 printf ("%s:", cmd_name);
654
655 switch (cmd->type)
656 {
657 case BFD_MACH_O_LC_SEGMENT:
658 case BFD_MACH_O_LC_SEGMENT_64:
659 dump_segment (abfd, cmd);
660 break;
661 case BFD_MACH_O_LC_UUID:
662 {
663 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
664 unsigned int j;
665
666 for (j = 0; j < sizeof (uuid->uuid); j ++)
667 printf (" %02x", uuid->uuid[j]);
668 putchar ('\n');
669 }
670 break;
671 case BFD_MACH_O_LC_LOAD_DYLIB:
672 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
673 case BFD_MACH_O_LC_REEXPORT_DYLIB:
674 case BFD_MACH_O_LC_ID_DYLIB:
675 case BFD_MACH_O_LC_LOAD_UPWARD_DYLIB:
676 {
677 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
678 printf (" %s\n", dylib->name_str);
679 printf (" time stamp: 0x%08lx\n",
680 dylib->timestamp);
681 printf (" current version: 0x%08lx\n",
682 dylib->current_version);
683 printf (" comptibility version: 0x%08lx\n",
684 dylib->compatibility_version);
685 break;
686 }
687 case BFD_MACH_O_LC_LOAD_DYLINKER:
688 case BFD_MACH_O_LC_ID_DYLINKER:
689 printf (" %s\n", cmd->command.dylinker.name_str);
690 break;
691 case BFD_MACH_O_LC_SYMTAB:
692 {
693 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
694 printf ("\n"
695 " symoff: 0x%08x nsyms: %8u (endoff: 0x%08x)\n",
696 symtab->symoff, symtab->nsyms,
697 symtab->symoff + symtab->nsyms
698 * (mdata->header.version == 2
699 ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE));
700 printf (" stroff: 0x%08x strsize: %8u (endoff: 0x%08x)\n",
701 symtab->stroff, symtab->strsize,
702 symtab->stroff + symtab->strsize);
703 break;
704 }
705 case BFD_MACH_O_LC_DYSYMTAB:
706 putchar ('\n');
707 dump_dysymtab (abfd, cmd, verbose);
708 break;
709 case BFD_MACH_O_LC_CODE_SIGNATURE:
710 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
711 case BFD_MACH_O_LC_FUNCTION_STARTS:
712 {
713 bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
714 printf
715 ("\n"
716 " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
717 linkedit->dataoff, linkedit->datasize,
718 linkedit->dataoff + linkedit->datasize);
719 break;
720 }
721 case BFD_MACH_O_LC_SUB_FRAMEWORK:
722 case BFD_MACH_O_LC_SUB_UMBRELLA:
723 case BFD_MACH_O_LC_SUB_LIBRARY:
724 case BFD_MACH_O_LC_SUB_CLIENT:
725 case BFD_MACH_O_LC_RPATH:
726 {
727 bfd_mach_o_str_command *str = &cmd->command.str;
728 printf (" %s\n", str->str);
729 break;
730 }
731 case BFD_MACH_O_LC_THREAD:
732 case BFD_MACH_O_LC_UNIXTHREAD:
733 dump_thread (abfd, cmd);
734 break;
735 case BFD_MACH_O_LC_DYLD_INFO:
736 putchar ('\n');
737 dump_dyld_info (abfd, cmd);
738 break;
739 case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
740 case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
741 {
742 bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
743
744 printf (" %u.%u.%u\n", ver->rel, ver->maj, ver->min);
745 }
746 break;
747 default:
748 putchar ('\n');
749 printf (" offset: 0x%08lx\n", (unsigned long)cmd->offset);
750 printf (" size: 0x%08lx\n", (unsigned long)cmd->len);
751 break;
752 }
753 putchar ('\n');
754 }
755
756 static void
757 dump_load_commands (bfd *abfd, unsigned int cmd32, unsigned int cmd64)
758 {
759 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
760 unsigned int i;
761
762 for (i = 0; i < mdata->header.ncmds; i++)
763 {
764 bfd_mach_o_load_command *cmd = &mdata->commands[i];
765
766 if (cmd32 == 0)
767 dump_load_command (abfd, cmd, FALSE);
768 else if (cmd->type == cmd32 || cmd->type == cmd64)
769 dump_load_command (abfd, cmd, TRUE);
770 }
771 }
772
773 /* Dump ABFD (according to the options[] array). */
774
775 static void
776 mach_o_dump (bfd *abfd)
777 {
778 if (options[OPT_HEADER].selected)
779 dump_header (abfd);
780 if (options[OPT_SECTION].selected)
781 dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT, BFD_MACH_O_LC_SEGMENT_64);
782 if (options[OPT_MAP].selected)
783 dump_section_map (abfd);
784 if (options[OPT_LOAD].selected)
785 dump_load_commands (abfd, 0, 0);
786 if (options[OPT_DYSYMTAB].selected)
787 dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0);
788 }
789
790 /* Vector for Mach-O. */
791
792 const struct objdump_private_desc objdump_private_desc_mach_o =
793 {
794 mach_o_help,
795 mach_o_filter,
796 mach_o_dump,
797 options
798 };