xref: /netbsd-src/external/gpl3/binutils.old/dist/binutils/od-macho.c (revision e992f068c547fd6e84b3f104dc2340adcc955732)
1 /* od-macho.c -- dump information about an Mach-O object file.
2    Copyright (C) 2011-2022 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 "elfcomm.h"
30 #include "dwarf.h"
31 #include "bfdlink.h"
32 #include "mach-o.h"
33 #include "mach-o/external.h"
34 #include "mach-o/codesign.h"
35 #include "mach-o/unwind.h"
36 
37 /* Index of the options in the options[] array.  */
38 #define OPT_HEADER 0
39 #define OPT_SECTION 1
40 #define OPT_MAP 2
41 #define OPT_LOAD 3
42 #define OPT_DYSYMTAB 4
43 #define OPT_CODESIGN 5
44 #define OPT_SEG_SPLIT_INFO 6
45 #define OPT_COMPACT_UNWIND 7
46 #define OPT_FUNCTION_STARTS 8
47 #define OPT_DATA_IN_CODE 9
48 #define OPT_TWOLEVEL_HINTS 10
49 #define OPT_DYLD_INFO 11
50 
51 /* List of actions.  */
52 static struct objdump_private_option options[] =
53   {
54     { "header", 0 },
55     { "section", 0 },
56     { "map", 0 },
57     { "load", 0 },
58     { "dysymtab", 0 },
59     { "codesign", 0 },
60     { "seg_split_info", 0 },
61     { "compact_unwind", 0 },
62     { "function_starts", 0 },
63     { "data_in_code", 0 },
64     { "twolevel_hints", 0 },
65     { "dyld_info", 0 },
66     { NULL, 0 }
67   };
68 
69 /* Display help.  */
70 
71 static void
mach_o_help(FILE * stream)72 mach_o_help (FILE *stream)
73 {
74   fprintf (stream, _("\
75 For Mach-O files:\n\
76   header           Display the file header\n\
77   section          Display the segments and sections commands\n\
78   map              Display the section map\n\
79   load             Display the load commands\n\
80   dysymtab         Display the dynamic symbol table\n\
81   codesign         Display code signature\n\
82   seg_split_info   Display segment split info\n\
83   compact_unwind   Display compact unwinding info\n\
84   function_starts  Display start address of functions\n\
85   data_in_code     Display data in code entries\n\
86   twolevel_hints   Display the two-level namespace lookup hints table\n\
87   dyld_info        Display dyld information\n\
88 "));
89 }
90 
91 /* Return TRUE if ABFD is handled.  */
92 
93 static int
mach_o_filter(bfd * abfd)94 mach_o_filter (bfd *abfd)
95 {
96   return bfd_get_flavour (abfd) == bfd_target_mach_o_flavour;
97 }
98 
99 static const bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
100 {
101   { "vax", BFD_MACH_O_CPU_TYPE_VAX },
102   { "mc680x0", BFD_MACH_O_CPU_TYPE_MC680x0 },
103   { "i386", BFD_MACH_O_CPU_TYPE_I386 },
104   { "mips", BFD_MACH_O_CPU_TYPE_MIPS },
105   { "mc98000", BFD_MACH_O_CPU_TYPE_MC98000 },
106   { "hppa", BFD_MACH_O_CPU_TYPE_HPPA },
107   { "arm", BFD_MACH_O_CPU_TYPE_ARM },
108   { "mc88000", BFD_MACH_O_CPU_TYPE_MC88000 },
109   { "sparc", BFD_MACH_O_CPU_TYPE_SPARC },
110   { "alpha", BFD_MACH_O_CPU_TYPE_ALPHA },
111   { "powerpc", BFD_MACH_O_CPU_TYPE_POWERPC },
112   { "powerpc_64", BFD_MACH_O_CPU_TYPE_POWERPC_64 },
113   { "x86_64", BFD_MACH_O_CPU_TYPE_X86_64 },
114   { "arm64", BFD_MACH_O_CPU_TYPE_ARM64 },
115   { NULL, 0}
116 };
117 
118 static const bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
119 {
120   { "object", BFD_MACH_O_MH_OBJECT },
121   { "execute", BFD_MACH_O_MH_EXECUTE },
122   { "fvmlib", BFD_MACH_O_MH_FVMLIB },
123   { "core", BFD_MACH_O_MH_CORE },
124   { "preload", BFD_MACH_O_MH_PRELOAD },
125   { "dylib", BFD_MACH_O_MH_DYLIB },
126   { "dylinker", BFD_MACH_O_MH_DYLINKER },
127   { "bundle", BFD_MACH_O_MH_BUNDLE },
128   { "dylib_stub", BFD_MACH_O_MH_DYLIB_STUB },
129   { "dym", BFD_MACH_O_MH_DSYM },
130   { "kext_bundle", BFD_MACH_O_MH_KEXT_BUNDLE },
131   { NULL, 0}
132 };
133 
134 static const bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
135 {
136   { "noundefs", BFD_MACH_O_MH_NOUNDEFS },
137   { "incrlink", BFD_MACH_O_MH_INCRLINK },
138   { "dyldlink", BFD_MACH_O_MH_DYLDLINK },
139   { "bindatload", BFD_MACH_O_MH_BINDATLOAD },
140   { "prebound", BFD_MACH_O_MH_PREBOUND },
141   { "split_segs", BFD_MACH_O_MH_SPLIT_SEGS },
142   { "lazy_init", BFD_MACH_O_MH_LAZY_INIT },
143   { "twolevel", BFD_MACH_O_MH_TWOLEVEL },
144   { "force_flat", BFD_MACH_O_MH_FORCE_FLAT },
145   { "nomultidefs", BFD_MACH_O_MH_NOMULTIDEFS },
146   { "nofixprebinding", BFD_MACH_O_MH_NOFIXPREBINDING },
147   { "prebindable", BFD_MACH_O_MH_PREBINDABLE },
148   { "allmodsbound", BFD_MACH_O_MH_ALLMODSBOUND },
149   { "subsections_via_symbols", BFD_MACH_O_MH_SUBSECTIONS_VIA_SYMBOLS },
150   { "canonical", BFD_MACH_O_MH_CANONICAL },
151   { "weak_defines", BFD_MACH_O_MH_WEAK_DEFINES },
152   { "binds_to_weak", BFD_MACH_O_MH_BINDS_TO_WEAK },
153   { "allow_stack_execution", BFD_MACH_O_MH_ALLOW_STACK_EXECUTION },
154   { "root_safe", BFD_MACH_O_MH_ROOT_SAFE },
155   { "setuid_safe", BFD_MACH_O_MH_SETUID_SAFE },
156   { "no_reexported_dylibs", BFD_MACH_O_MH_NO_REEXPORTED_DYLIBS },
157   { "pie", BFD_MACH_O_MH_PIE },
158   { "dead_strippable_dylib", BFD_MACH_O_MH_DEAD_STRIPPABLE_DYLIB },
159   { "has_tlv", BFD_MACH_O_MH_HAS_TLV_DESCRIPTORS },
160   { "no_heap_execution", BFD_MACH_O_MH_NO_HEAP_EXECUTION },
161   { "app_extension_safe", BFD_MACH_O_MH_APP_EXTENSION_SAFE },
162   { NULL, 0}
163 };
164 
165 static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
166 {
167   { "segment", BFD_MACH_O_LC_SEGMENT},
168   { "symtab", BFD_MACH_O_LC_SYMTAB},
169   { "symseg", BFD_MACH_O_LC_SYMSEG},
170   { "thread", BFD_MACH_O_LC_THREAD},
171   { "unixthread", BFD_MACH_O_LC_UNIXTHREAD},
172   { "loadfvmlib", BFD_MACH_O_LC_LOADFVMLIB},
173   { "idfvmlib", BFD_MACH_O_LC_IDFVMLIB},
174   { "ident", BFD_MACH_O_LC_IDENT},
175   { "fvmfile", BFD_MACH_O_LC_FVMFILE},
176   { "prepage", BFD_MACH_O_LC_PREPAGE},
177   { "dysymtab", BFD_MACH_O_LC_DYSYMTAB},
178   { "load_dylib", BFD_MACH_O_LC_LOAD_DYLIB},
179   { "id_dylib", BFD_MACH_O_LC_ID_DYLIB},
180   { "load_dylinker", BFD_MACH_O_LC_LOAD_DYLINKER},
181   { "id_dylinker", BFD_MACH_O_LC_ID_DYLINKER},
182   { "prebound_dylib", BFD_MACH_O_LC_PREBOUND_DYLIB},
183   { "routines", BFD_MACH_O_LC_ROUTINES},
184   { "sub_framework", BFD_MACH_O_LC_SUB_FRAMEWORK},
185   { "sub_umbrella", BFD_MACH_O_LC_SUB_UMBRELLA},
186   { "sub_client", BFD_MACH_O_LC_SUB_CLIENT},
187   { "sub_library", BFD_MACH_O_LC_SUB_LIBRARY},
188   { "twolevel_hints", BFD_MACH_O_LC_TWOLEVEL_HINTS},
189   { "prebind_cksum", BFD_MACH_O_LC_PREBIND_CKSUM},
190   { "load_weak_dylib", BFD_MACH_O_LC_LOAD_WEAK_DYLIB},
191   { "segment_64", BFD_MACH_O_LC_SEGMENT_64},
192   { "routines_64", BFD_MACH_O_LC_ROUTINES_64},
193   { "uuid", BFD_MACH_O_LC_UUID},
194   { "rpath", BFD_MACH_O_LC_RPATH},
195   { "code_signature", BFD_MACH_O_LC_CODE_SIGNATURE},
196   { "segment_split_info", BFD_MACH_O_LC_SEGMENT_SPLIT_INFO},
197   { "reexport_dylib", BFD_MACH_O_LC_REEXPORT_DYLIB},
198   { "lazy_load_dylib", BFD_MACH_O_LC_LAZY_LOAD_DYLIB},
199   { "encryption_info", BFD_MACH_O_LC_ENCRYPTION_INFO},
200   { "dyld_info", BFD_MACH_O_LC_DYLD_INFO},
201   { "load_upward_lib", BFD_MACH_O_LC_LOAD_UPWARD_DYLIB},
202   { "version_min_macosx", BFD_MACH_O_LC_VERSION_MIN_MACOSX},
203   { "version_min_iphoneos", BFD_MACH_O_LC_VERSION_MIN_IPHONEOS},
204   { "function_starts", BFD_MACH_O_LC_FUNCTION_STARTS},
205   { "dyld_environment", BFD_MACH_O_LC_DYLD_ENVIRONMENT},
206   { "main", BFD_MACH_O_LC_MAIN},
207   { "data_in_code", BFD_MACH_O_LC_DATA_IN_CODE},
208   { "source_version", BFD_MACH_O_LC_SOURCE_VERSION},
209   { "dylib_code_sign_drs", BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS},
210   { "encryption_info_64", BFD_MACH_O_LC_ENCRYPTION_INFO_64},
211   { "linker_options", BFD_MACH_O_LC_LINKER_OPTIONS},
212   { "linker_optimization_hint", BFD_MACH_O_LC_LINKER_OPTIMIZATION_HINT},
213   { "version_min_tvos", BFD_MACH_O_LC_VERSION_MIN_TVOS},
214   { "version_min_watchos", BFD_MACH_O_LC_VERSION_MIN_WATCHOS},
215   { "note", BFD_MACH_O_LC_NOTE},
216   { "build_version", BFD_MACH_O_LC_BUILD_VERSION},
217   { "exports_trie", BFD_MACH_O_LC_DYLD_EXPORTS_TRIE},
218   { "chained_fixups", BFD_MACH_O_LC_DYLD_CHAINED_FIXUPS},
219   { NULL, 0}
220 };
221 
222 static const bfd_mach_o_xlat_name bfd_mach_o_thread_x86_name[] =
223 {
224   { "thread_state32", BFD_MACH_O_x86_THREAD_STATE32},
225   { "float_state32", BFD_MACH_O_x86_FLOAT_STATE32},
226   { "exception_state32", BFD_MACH_O_x86_EXCEPTION_STATE32},
227   { "thread_state64", BFD_MACH_O_x86_THREAD_STATE64},
228   { "float_state64", BFD_MACH_O_x86_FLOAT_STATE64},
229   { "exception_state64", BFD_MACH_O_x86_EXCEPTION_STATE64},
230   { "thread_state", BFD_MACH_O_x86_THREAD_STATE},
231   { "float_state", BFD_MACH_O_x86_FLOAT_STATE},
232   { "exception_state", BFD_MACH_O_x86_EXCEPTION_STATE},
233   { "debug_state32", BFD_MACH_O_x86_DEBUG_STATE32},
234   { "debug_state64", BFD_MACH_O_x86_DEBUG_STATE64},
235   { "debug_state", BFD_MACH_O_x86_DEBUG_STATE},
236   { "state_none", BFD_MACH_O_x86_THREAD_STATE_NONE},
237   { NULL, 0 }
238 };
239 
240 static const bfd_mach_o_xlat_name bfd_mach_o_platform_name[] =
241 {
242   { "macos", BFD_MACH_O_PLATFORM_MACOS},
243   { "ios", BFD_MACH_O_PLATFORM_IOS},
244   { "tvos", BFD_MACH_O_PLATFORM_TVOS},
245   { "watchos", BFD_MACH_O_PLATFORM_WATCHOS},
246   { "bridgeos", BFD_MACH_O_PLATFORM_BRIDGEOS},
247   { NULL, 0 }
248 };
249 
250 static const bfd_mach_o_xlat_name bfd_mach_o_tool_name[] =
251 {
252   { "clang", BFD_MACH_O_TOOL_CLANG},
253   { "swift", BFD_MACH_O_TOOL_SWIFT},
254   { "ld", BFD_MACH_O_TOOL_LD},
255   { NULL, 0 }
256 };
257 
258 static void
bfd_mach_o_print_flags(const bfd_mach_o_xlat_name * table,unsigned long val)259 bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
260                         unsigned long val)
261 {
262   int first = 1;
263 
264   for (; table->name; table++)
265     {
266       if (table->val & val)
267         {
268           if (!first)
269             printf ("+");
270           printf ("%s", table->name);
271           val &= ~table->val;
272           first = 0;
273         }
274     }
275   if (val)
276     {
277       if (!first)
278         printf ("+");
279       printf ("0x%lx", val);
280       return;
281     }
282   if (first)
283     printf ("-");
284 }
285 
286 static const char *
bfd_mach_o_get_name_or_null(const bfd_mach_o_xlat_name * table,unsigned long val)287 bfd_mach_o_get_name_or_null (const bfd_mach_o_xlat_name *table,
288                              unsigned long val)
289 {
290   for (; table->name; table++)
291     if (table->val == val)
292       return table->name;
293   return NULL;
294 }
295 
296 static const char *
bfd_mach_o_get_name(const bfd_mach_o_xlat_name * table,unsigned long val)297 bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
298 {
299   const char *res = bfd_mach_o_get_name_or_null (table, val);
300 
301   if (res == NULL)
302     return "*UNKNOWN*";
303   else
304     return res;
305 }
306 
307 static void
dump_header(bfd * abfd)308 dump_header (bfd *abfd)
309 {
310   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
311   bfd_mach_o_header *h = &mdata->header;
312 
313   fputs (_("Mach-O header:\n"), stdout);
314   printf (_(" magic     : %08lx\n"), h->magic);
315   printf (_(" cputype   : %08lx (%s)\n"), h->cputype,
316           bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
317   printf (_(" cpusubtype: %08lx\n"), h->cpusubtype);
318   printf (_(" filetype  : %08lx (%s)\n"),
319           h->filetype,
320           bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
321   printf (_(" ncmds     : %08lx (%lu)\n"), h->ncmds, h->ncmds);
322   printf (_(" sizeofcmds: %08lx (%lu)\n"), h->sizeofcmds, h->sizeofcmds);
323   printf (_(" flags     : %08lx ("), h->flags);
324   bfd_mach_o_print_flags (bfd_mach_o_header_flags_name, h->flags);
325   fputs (_(")\n"), stdout);
326   printf (_(" reserved  : %08x\n"), h->reserved);
327   putchar ('\n');
328 }
329 
330 static void
disp_segment_prot(unsigned int prot)331 disp_segment_prot (unsigned int prot)
332 {
333   putchar (prot & BFD_MACH_O_PROT_READ ? 'r' : '-');
334   putchar (prot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
335   putchar (prot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
336 }
337 
338 static void
dump_section_map(bfd * abfd)339 dump_section_map (bfd *abfd)
340 {
341   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
342   bfd_mach_o_load_command *cmd;
343   unsigned int sec_nbr = 0;
344 
345   fputs (_("Segments and Sections:\n"), stdout);
346   fputs (_(" #: Segment name     Section name     Address\n"), stdout);
347 
348   for (cmd = mdata->first_command; cmd != NULL; cmd = cmd->next)
349     {
350       bfd_mach_o_segment_command *seg;
351       bfd_mach_o_section *sec;
352 
353       if (cmd->type != BFD_MACH_O_LC_SEGMENT
354 	  && cmd->type != BFD_MACH_O_LC_SEGMENT_64)
355 	continue;
356 
357       seg = &cmd->command.segment;
358 
359       printf ("[Segment %-16s ", seg->segname);
360       printf_vma (seg->vmaddr);
361       putchar ('-');
362       printf_vma  (seg->vmaddr + seg->vmsize - 1);
363       putchar (' ');
364       disp_segment_prot (seg->initprot);
365       printf ("]\n");
366 
367       for (sec = seg->sect_head; sec != NULL; sec = sec->next)
368 	{
369 	  printf ("%02u: %-16s %-16s ", ++sec_nbr,
370                   sec->segname, sec->sectname);
371 	  printf_vma (sec->addr);
372 	  putchar (' ');
373 	  printf_vma  (sec->size);
374 	  printf (" %08lx\n", sec->flags);
375 	}
376     }
377 }
378 
379 static void
dump_section_header(bfd * abfd ATTRIBUTE_UNUSED,bfd_mach_o_section * sec)380 dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_section *sec)
381 {
382   printf (" Section: %-16s %-16s (bfdname: %s)\n",
383            sec->sectname, sec->segname, sec->bfdsection->name);
384   printf ("  addr: ");
385   printf_vma (sec->addr);
386   printf (" size: ");
387   printf_vma (sec->size);
388   printf (" offset: ");
389   printf_vma (sec->offset);
390   printf ("\n");
391   printf ("  align: %ld", sec->align);
392   printf ("  nreloc: %lu  reloff: ", sec->nreloc);
393   printf_vma (sec->reloff);
394   printf ("\n");
395   printf ("  flags: %08lx (type: %s", sec->flags,
396           bfd_mach_o_get_name (bfd_mach_o_section_type_name,
397                                sec->flags & BFD_MACH_O_SECTION_TYPE_MASK));
398   printf (" attr: ");
399   bfd_mach_o_print_flags (bfd_mach_o_section_attribute_name,
400                           sec->flags & BFD_MACH_O_SECTION_ATTRIBUTES_MASK);
401   printf (")\n");
402   switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
403     {
404     case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
405     case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
406     case BFD_MACH_O_S_SYMBOL_STUBS:
407       printf ("  first indirect sym: %lu", sec->reserved1);
408       printf (" (%u entries)",
409                bfd_mach_o_section_get_nbr_indirect (abfd, sec));
410       break;
411     default:
412       printf ("  reserved1: 0x%lx", sec->reserved1);
413       break;
414     }
415   switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
416     {
417     case BFD_MACH_O_S_SYMBOL_STUBS:
418       printf ("  stub size: %lu", sec->reserved2);
419       break;
420     default:
421       printf ("  reserved2: 0x%lx", sec->reserved2);
422       break;
423     }
424   printf ("  reserved3: 0x%lx\n", sec->reserved3);
425 }
426 
427 static void
dump_segment(bfd * abfd ATTRIBUTE_UNUSED,bfd_mach_o_load_command * cmd)428 dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
429 {
430   bfd_mach_o_segment_command *seg = &cmd->command.segment;
431   bfd_mach_o_section *sec;
432 
433   printf ("     name: %16s", *seg->segname ? seg->segname : "*none*");
434   printf ("  nsects: %lu", seg->nsects);
435   printf ("  flags: %lx", seg->flags);
436   printf ("  initprot: ");
437   disp_segment_prot (seg->initprot);
438   printf ("  maxprot: ");
439   disp_segment_prot (seg->maxprot);
440   printf ("\n");
441   printf ("   vmaddr: ");
442   printf_vma (seg->vmaddr);
443   printf ("   vmsize: ");
444   printf_vma  (seg->vmsize);
445   printf ("\n");
446   printf ("  fileoff: ");
447   printf_vma (seg->fileoff);
448   printf (" filesize: ");
449   printf_vma ((bfd_vma)seg->filesize);
450   printf (" endoff: ");
451   printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
452   printf ("\n");
453   for (sec = seg->sect_head; sec != NULL; sec = sec->next)
454     dump_section_header (abfd, sec);
455 }
456 
457 static void
dump_dysymtab(bfd * abfd,bfd_mach_o_load_command * cmd,bool verbose)458 dump_dysymtab (bfd *abfd, bfd_mach_o_load_command *cmd, bool verbose)
459 {
460   bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
461   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
462   unsigned int i;
463 
464   printf ("              local symbols: idx: %10lu  num: %-8lu",
465           dysymtab->ilocalsym, dysymtab->nlocalsym);
466   printf (" (nxtidx: %lu)\n",
467           dysymtab->ilocalsym + dysymtab->nlocalsym);
468   printf ("           external symbols: idx: %10lu  num: %-8lu",
469           dysymtab->iextdefsym, dysymtab->nextdefsym);
470   printf (" (nxtidx: %lu)\n",
471           dysymtab->iextdefsym + dysymtab->nextdefsym);
472   printf ("          undefined symbols: idx: %10lu  num: %-8lu",
473           dysymtab->iundefsym, dysymtab->nundefsym);
474   printf (" (nxtidx: %lu)\n",
475           dysymtab->iundefsym + dysymtab->nundefsym);
476   printf ("           table of content: off: 0x%08lx  num: %-8lu",
477           dysymtab->tocoff, dysymtab->ntoc);
478   printf (" (endoff: 0x%08lx)\n",
479           dysymtab->tocoff + dysymtab->ntoc * BFD_MACH_O_TABLE_OF_CONTENT_SIZE);
480   printf ("               module table: off: 0x%08lx  num: %-8lu",
481           dysymtab->modtaboff, dysymtab->nmodtab);
482   printf (" (endoff: 0x%08lx)\n",
483           dysymtab->modtaboff + dysymtab->nmodtab
484           * (mdata->header.version == 2 ?
485              BFD_MACH_O_DYLIB_MODULE_64_SIZE : BFD_MACH_O_DYLIB_MODULE_SIZE));
486   printf ("   external reference table: off: 0x%08lx  num: %-8lu",
487           dysymtab->extrefsymoff, dysymtab->nextrefsyms);
488   printf (" (endoff: 0x%08lx)\n",
489           dysymtab->extrefsymoff
490           + dysymtab->nextrefsyms * BFD_MACH_O_REFERENCE_SIZE);
491   printf ("      indirect symbol table: off: 0x%08lx  num: %-8lu",
492           dysymtab->indirectsymoff, dysymtab->nindirectsyms);
493   printf (" (endoff: 0x%08lx)\n",
494           dysymtab->indirectsymoff
495           + dysymtab->nindirectsyms * BFD_MACH_O_INDIRECT_SYMBOL_SIZE);
496   printf ("  external relocation table: off: 0x%08lx  num: %-8lu",
497           dysymtab->extreloff, dysymtab->nextrel);
498   printf (" (endoff: 0x%08lx)\n",
499           dysymtab->extreloff + dysymtab->nextrel * BFD_MACH_O_RELENT_SIZE);
500   printf ("     local relocation table: off: 0x%08lx  num: %-8lu",
501           dysymtab->locreloff, dysymtab->nlocrel);
502   printf (" (endoff: 0x%08lx)\n",
503           dysymtab->locreloff + dysymtab->nlocrel * BFD_MACH_O_RELENT_SIZE);
504 
505   if (!verbose)
506     return;
507 
508   if (dysymtab->ntoc > 0
509       || dysymtab->nindirectsyms > 0
510       || dysymtab->nextrefsyms > 0)
511     {
512       /* Try to read the symbols to display the toc or indirect symbols.  */
513       bfd_mach_o_read_symtab_symbols (abfd);
514     }
515   else if (dysymtab->nmodtab > 0)
516     {
517       /* Try to read the strtab to display modules name.  */
518       bfd_mach_o_read_symtab_strtab (abfd);
519     }
520 
521   for (i = 0; i < dysymtab->nmodtab; i++)
522     {
523       bfd_mach_o_dylib_module *module = &dysymtab->dylib_module[i];
524       printf ("  module %u:\n", i);
525       printf ("   name: %lu", module->module_name_idx);
526       if (mdata->symtab && mdata->symtab->strtab)
527         printf (": %s",
528                  mdata->symtab->strtab + module->module_name_idx);
529       printf ("\n");
530       printf ("   extdefsym: idx: %8lu  num: %lu\n",
531                module->iextdefsym, module->nextdefsym);
532       printf ("      refsym: idx: %8lu  num: %lu\n",
533                module->irefsym, module->nrefsym);
534       printf ("    localsym: idx: %8lu  num: %lu\n",
535                module->ilocalsym, module->nlocalsym);
536       printf ("      extrel: idx: %8lu  num: %lu\n",
537                module->iextrel, module->nextrel);
538       printf ("        init: idx: %8u  num: %u\n",
539                module->iinit, module->ninit);
540       printf ("        term: idx: %8u  num: %u\n",
541                module->iterm, module->nterm);
542       printf ("   objc_module_info: addr: ");
543       printf_vma (module->objc_module_info_addr);
544       printf ("  size: %lu\n", module->objc_module_info_size);
545     }
546 
547   if (dysymtab->ntoc > 0)
548     {
549       bfd_mach_o_symtab_command *symtab = mdata->symtab;
550 
551       printf ("  table of content: (symbol/module)\n");
552       for (i = 0; i < dysymtab->ntoc; i++)
553         {
554           bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
555 
556           printf ("   %4u: ", i);
557           if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
558             {
559               const char *name = symtab->symbols[toc->symbol_index].symbol.name;
560               printf ("%s (%lu)", name ? name : "*invalid*",
561                        toc->symbol_index);
562             }
563           else
564             printf ("%lu", toc->symbol_index);
565 
566           printf (" / ");
567           if (symtab && symtab->strtab
568               && toc->module_index < dysymtab->nmodtab)
569             {
570               bfd_mach_o_dylib_module *mod;
571               mod = &dysymtab->dylib_module[toc->module_index];
572               printf ("%s (%lu)",
573                        symtab->strtab + mod->module_name_idx,
574                        toc->module_index);
575             }
576           else
577             printf ("%lu", toc->module_index);
578 
579           printf ("\n");
580         }
581     }
582 
583   if (dysymtab->nindirectsyms != 0)
584     {
585       printf ("  indirect symbols:\n");
586 
587       for (i = 0; i < mdata->nsects; i++)
588         {
589           bfd_mach_o_section *sec = mdata->sections[i];
590           unsigned int j, first, last;
591           bfd_mach_o_symtab_command *symtab = mdata->symtab;
592           bfd_vma addr;
593           bfd_vma entry_size;
594 
595           switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
596             {
597             case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
598             case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
599             case BFD_MACH_O_S_SYMBOL_STUBS:
600               first = sec->reserved1;
601               last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
602               addr = sec->addr;
603               entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
604               printf ("  for section %s.%s:\n",
605                        sec->segname, sec->sectname);
606               for (j = first; j < last; j++)
607                 {
608                   unsigned int isym = dysymtab->indirect_syms[j];
609 
610                   printf ("   ");
611                   printf_vma (addr);
612                   printf (" %5u: 0x%08x", j, isym);
613                   if (isym & BFD_MACH_O_INDIRECT_SYMBOL_LOCAL)
614                     printf (" LOCAL");
615                   if (isym & BFD_MACH_O_INDIRECT_SYMBOL_ABS)
616                     printf (" ABSOLUTE");
617                   if (symtab && symtab->symbols
618                       && isym < symtab->nsyms
619                       && symtab->symbols[isym].symbol.name)
620                     printf (" %s", symtab->symbols[isym].symbol.name);
621                   printf ("\n");
622                   addr += entry_size;
623                 }
624               break;
625             default:
626               break;
627             }
628         }
629     }
630   if (dysymtab->nextrefsyms > 0)
631     {
632       bfd_mach_o_symtab_command *symtab = mdata->symtab;
633 
634       printf ("  external reference table: (symbol flags)\n");
635       for (i = 0; i < dysymtab->nextrefsyms; i++)
636         {
637           bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
638 
639           printf ("   %4u: %5lu 0x%02lx", i, ref->isym, ref->flags);
640           if (symtab && symtab->symbols
641               && ref->isym < symtab->nsyms
642               && symtab->symbols[ref->isym].symbol.name)
643             printf (" %s", symtab->symbols[ref->isym].symbol.name);
644           printf ("\n");
645         }
646     }
647 
648 }
649 
650 static bool
load_and_dump(bfd * abfd,ufile_ptr off,unsigned int len,void (* dump)(bfd * abfd,unsigned char * buf,unsigned int len,ufile_ptr off))651 load_and_dump (bfd *abfd, ufile_ptr off, unsigned int len,
652 	       void (*dump)(bfd *abfd, unsigned char *buf, unsigned int len,
653 			    ufile_ptr off))
654 {
655   unsigned char *buf;
656 
657   if (len == 0)
658     return true;
659 
660   buf = xmalloc (len);
661 
662   if (bfd_seek (abfd, off, SEEK_SET) == 0
663       && bfd_bread (buf, len, abfd) == len)
664     dump (abfd, buf, len, off);
665   else
666     return false;
667 
668   free (buf);
669   return true;
670 }
671 
672 static const bfd_mach_o_xlat_name bfd_mach_o_dyld_rebase_type_name[] =
673 {
674   { "pointer",      BFD_MACH_O_REBASE_TYPE_POINTER },
675   { "text_abs32",   BFD_MACH_O_REBASE_TYPE_TEXT_ABSOLUTE32 },
676   { "text_pcrel32", BFD_MACH_O_REBASE_TYPE_TEXT_PCREL32 },
677   { NULL, 0 }
678 };
679 
680 static void
dump_dyld_info_rebase(bfd * abfd,unsigned char * buf,unsigned int len,ufile_ptr off ATTRIBUTE_UNUSED)681 dump_dyld_info_rebase (bfd *abfd, unsigned char *buf, unsigned int len,
682 		       ufile_ptr off ATTRIBUTE_UNUSED)
683 {
684   unsigned int i;
685   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
686   unsigned int ptrsize = mdata->header.version == 2 ? 8 : 4;
687 
688   for (i = 0; i < len; )
689     {
690       unsigned char b = buf[i++];
691       unsigned char imm = b & BFD_MACH_O_REBASE_IMMEDIATE_MASK;
692       bfd_vma leb;
693       unsigned int leblen;
694 
695       printf ("   [0x%04x] 0x%02x: ", i, b);
696       switch (b & BFD_MACH_O_REBASE_OPCODE_MASK)
697 	{
698 	case BFD_MACH_O_REBASE_OPCODE_DONE:
699 	  printf ("done\n");
700 	  return;
701 	case BFD_MACH_O_REBASE_OPCODE_SET_TYPE_IMM:
702 	  printf ("set_type %s\n",
703 		  bfd_mach_o_get_name (bfd_mach_o_dyld_rebase_type_name, imm));
704 	  break;
705 	case BFD_MACH_O_REBASE_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
706 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
707 	  printf ("set segment: %u and offset: 0x%08x\n",
708 		  imm, (unsigned) leb);
709 	  i += leblen;
710 	  break;
711 	case BFD_MACH_O_REBASE_OPCODE_ADD_ADDR_ULEB:
712 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
713 	  printf ("add addr uleb: 0x%08x\n", (unsigned) leb);
714 	  i += leblen;
715 	  break;
716 	case BFD_MACH_O_REBASE_OPCODE_ADD_ADDR_IMM_SCALED:
717 	  printf ("add addr imm scaled: %u\n", imm * ptrsize);
718 	  break;
719 	case BFD_MACH_O_REBASE_OPCODE_DO_REBASE_IMM_TIMES:
720 	  printf ("rebase imm times: %u\n", imm);
721 	  break;
722 	case BFD_MACH_O_REBASE_OPCODE_DO_REBASE_ULEB_TIMES:
723 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
724 	  printf ("rebase uleb times: %u\n", (unsigned) leb);
725 	  i += leblen;
726 	  break;
727 	case BFD_MACH_O_REBASE_OPCODE_DO_REBASE_ADD_ADDR_ULEB:
728 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
729 	  printf ("rebase add addr uleb: %u\n", (unsigned) leb);
730 	  i += leblen;
731 	  break;
732 	case BFD_MACH_O_REBASE_OPCODE_DO_REBASE_ULEB_TIMES_SKIPPING_ULEB:
733 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
734 	  printf ("rebase uleb times (%u)", (unsigned) leb);
735 	  i += leblen;
736 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
737 	  printf (" skipping uleb (%u)\n", (unsigned) leb);
738 	  i += leblen;
739 	  break;
740 	default:
741 	  printf ("unknown\n");
742 	  return;
743 	}
744     }
745   printf ("   rebase commands without end!\n");
746 }
747 
748 static void
dump_dyld_info_bind(bfd * abfd,unsigned char * buf,unsigned int len,ufile_ptr off ATTRIBUTE_UNUSED)749 dump_dyld_info_bind (bfd *abfd, unsigned char *buf, unsigned int len,
750 		     ufile_ptr off ATTRIBUTE_UNUSED)
751 {
752   unsigned int i;
753   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
754   unsigned int ptrsize = mdata->header.version == 2 ? 8 : 4;
755 
756   for (i = 0; i < len; )
757     {
758       unsigned char b = buf[i++];
759       unsigned char imm = b & BFD_MACH_O_BIND_IMMEDIATE_MASK;
760       bfd_vma leb;
761       unsigned int leblen;
762 
763       printf ("   [0x%04x] 0x%02x: ", i, b);
764       switch (b & BFD_MACH_O_BIND_OPCODE_MASK)
765 	{
766 	case BFD_MACH_O_BIND_OPCODE_DONE:
767 	  printf ("done\n");
768 	  return;
769 	case BFD_MACH_O_BIND_OPCODE_SET_DYLIB_ORDINAL_IMM:
770 	  printf ("set dylib ordinal imm: %u\n", imm);
771 	  break;
772 	case BFD_MACH_O_BIND_OPCODE_SET_DYLIB_ORDINAL_ULEB:
773 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
774 	  printf ("set dylib ordinal uleb: %u\n", imm);
775 	  i += leblen;
776 	  break;
777 	case BFD_MACH_O_BIND_OPCODE_SET_DYLIB_SPECIAL_IMM:
778 	  imm = (imm != 0) ? imm | BFD_MACH_O_BIND_OPCODE_MASK : imm;
779 	  printf ("set dylib special imm: %d\n", imm);
780 	  break;
781 	case BFD_MACH_O_BIND_OPCODE_SET_SYMBOL_TRAILING_FLAGS_IMM:
782 	  printf ("set symbol trailing flags imm: 0x%02x, ", imm);
783 	  for (; i < len && buf[i] != 0; i++)
784 	    putchar (buf[i] >= ' ' && buf[i] < 0x7f ? buf[i] : '?');
785 	  putchar ('\n');
786 	  i++;
787 	  break;
788 	case BFD_MACH_O_BIND_OPCODE_SET_TYPE_IMM:
789 	  /* Kludge: use the same table as rebase type.  */
790 	  printf ("set_type %s\n",
791 		  bfd_mach_o_get_name (bfd_mach_o_dyld_rebase_type_name, imm));
792 	  break;
793 	case BFD_MACH_O_BIND_OPCODE_SET_ADDEND_SLEB:
794 	  {
795 	    bfd_signed_vma svma;
796 	    svma = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
797 	    printf ("set addend sleb: 0x%08x\n", (unsigned) svma);
798 	    i += leblen;
799 	  }
800 	  break;
801 	case BFD_MACH_O_BIND_OPCODE_SET_SEGMENT_AND_OFFSET_ULEB:
802 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
803 	  printf ("set segment: %u and offset: 0x%08x\n",
804 		  imm, (unsigned) leb);
805 	  i += leblen;
806 	  break;
807 	case BFD_MACH_O_BIND_OPCODE_ADD_ADDR_ULEB:
808 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
809 	  printf ("add addr uleb: 0x%08x\n", (unsigned) leb);
810 	  i += leblen;
811 	  break;
812 	case BFD_MACH_O_BIND_OPCODE_DO_BIND:
813 	  printf ("do bind\n");
814 	  break;
815 	case BFD_MACH_O_BIND_OPCODE_DO_BIND_ADD_ADDR_ULEB:
816 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
817 	  printf ("do bind add addr uleb: 0x%08x\n", (unsigned) leb);
818 	  i += leblen;
819 	  break;
820 	case BFD_MACH_O_BIND_OPCODE_DO_BIND_ADD_ADDR_IMM_SCALED:
821 	  printf ("do bind add addr imm scaled: %u\n", imm * ptrsize);
822 	  break;
823 	case BFD_MACH_O_BIND_OPCODE_DO_BIND_ULEB_TIMES_SKIPPING_ULEB:
824 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
825 	  printf ("do bind uleb times (%u)", (unsigned) leb);
826 	  i += leblen;
827 	  leb = read_leb128 (buf + i, buf + len, 0, &leblen, NULL);
828 	  printf (" skipping uleb (%u)\n", (unsigned) leb);
829 	  i += leblen;
830 	  break;
831 	default:
832 	  printf ("unknown\n");
833 	  return;
834 	}
835     }
836   printf ("   bind commands without end!\n");
837 }
838 
839 struct export_info_data
840 {
841   const unsigned char *name;
842   struct export_info_data *next;
843 };
844 
845 static void
dump_dyld_info_export_1(bfd * abfd,unsigned char * buf,unsigned int len,unsigned int off,struct export_info_data * parent,struct export_info_data * base)846 dump_dyld_info_export_1 (bfd *abfd, unsigned char *buf, unsigned int len,
847 			 unsigned int off, struct export_info_data *parent,
848 			 struct export_info_data *base)
849 {
850   bfd_vma size;
851   unsigned int leblen;
852   unsigned int child_count;
853   unsigned int i;
854 
855   size = read_leb128 (buf + off, buf + len, 0, &leblen, NULL);
856   off += leblen;
857 
858   if (size != 0)
859     {
860       bfd_vma flags;
861       struct export_info_data *d;
862 
863       flags = read_leb128 (buf + off, buf + len, 0, &leblen, NULL);
864       off += leblen;
865 
866       fputs ("   ", stdout);
867       switch (flags & BFD_MACH_O_EXPORT_SYMBOL_FLAGS_KIND_MASK)
868 	{
869 	case BFD_MACH_O_EXPORT_SYMBOL_FLAGS_KIND_REGULAR:
870 	  putchar ('-');
871 	  break;
872 	case BFD_MACH_O_EXPORT_SYMBOL_FLAGS_KIND_THREAD_LOCAL:
873 	  putchar ('T');
874 	  break;
875 	default:
876 	  putchar ('?');
877 	  break;
878 	}
879       putchar ((flags & BFD_MACH_O_EXPORT_SYMBOL_FLAGS_WEAK_DEFINITION) ?
880 	       'W' : '-');
881 
882       if (flags & BFD_MACH_O_EXPORT_SYMBOL_FLAGS_REEXPORT)
883 	{
884 	  bfd_vma lib;
885 
886 	  lib = read_leb128 (buf + off, buf + len, 0, &leblen, NULL);
887 	  off += leblen;
888 
889 	  fputs (" [reexport] ", stdout);
890 	  for (d = base; d != NULL; d = d->next)
891 	    printf ("%s", d->name);
892 
893 	  fputs (" (", stdout);
894 	  if (buf[off] != 0)
895 	    {
896 	      fputs ((const char *)buf + off, stdout);
897 	      putchar (' ');
898 	      off += strlen ((const char *)buf + off);
899 	    }
900 	  printf ("from dylib %u)\n", (unsigned) lib);
901 	  off++;
902 	}
903       else
904 	{
905 	  bfd_vma offset;
906 	  bfd_vma resolv = 0;
907 
908 	  offset = read_leb128 (buf + off, buf + len, 0, &leblen, NULL);
909 	  off += leblen;
910 
911 	  if (flags & BFD_MACH_O_EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
912 	    {
913 	      resolv = read_leb128 (buf + off, buf + len, 0, &leblen, NULL);
914 	      off += leblen;
915 	    }
916 
917 	  printf (" 0x%08x ", (unsigned) offset);
918 	  for (d = base; d != NULL; d = d->next)
919 	    printf ("%s", d->name);
920 	  if (flags & BFD_MACH_O_EXPORT_SYMBOL_FLAGS_STUB_AND_RESOLVER)
921 	    printf (" [resolv: 0x%08x]", (unsigned) resolv);
922 	  printf ("\n");
923 	}
924     }
925 
926   child_count = read_leb128 (buf + off, buf + len, 0, &leblen, NULL);
927   off += leblen;
928 
929   for (i = 0; i < child_count; i++)
930     {
931       struct export_info_data sub_data;
932       bfd_vma sub_off;
933 
934       sub_data.name = buf + off;
935       sub_data.next = NULL;
936       parent->next = &sub_data;
937 
938       off += strlen ((const char *)buf + off) + 1;
939 
940       sub_off = read_leb128 (buf + off, buf + len, 0, &leblen, NULL);
941       off += leblen;
942 
943       dump_dyld_info_export_1 (abfd, buf, len, sub_off, &sub_data, base);
944     }
945 }
946 
947 static void
dump_dyld_info_export(bfd * abfd,unsigned char * buf,unsigned int len,ufile_ptr off ATTRIBUTE_UNUSED)948 dump_dyld_info_export (bfd *abfd, unsigned char *buf, unsigned int len,
949 		       ufile_ptr off ATTRIBUTE_UNUSED)
950 {
951   struct export_info_data data;
952 
953   data.name = (const unsigned char *) "";
954   data.next = NULL;
955 
956   printf ("   fl offset     sym        (Flags: Tls Weak)\n");
957   dump_dyld_info_export_1 (abfd, buf, len, 0, &data, &data);
958 }
959 
960 static void
dump_dyld_info(bfd * abfd,bfd_mach_o_load_command * cmd,bool verbose)961 dump_dyld_info (bfd *abfd, bfd_mach_o_load_command *cmd,
962 		bool verbose)
963 {
964   bfd_mach_o_dyld_info_command *dinfo = &cmd->command.dyld_info;
965 
966   printf ("       rebase: off: 0x%08x  size: %-8u   (endoff: 0x%08x)\n",
967 	  dinfo->rebase_off, dinfo->rebase_size,
968 	  dinfo->rebase_off + dinfo->rebase_size);
969   printf ("         bind: off: 0x%08x  size: %-8u   (endoff: 0x%08x)\n",
970 	  dinfo->bind_off, dinfo->bind_size,
971 	  dinfo->bind_off + dinfo->bind_size);
972   printf ("    weak bind: off: 0x%08x  size: %-8u   (endoff: 0x%08x)\n",
973 	  dinfo->weak_bind_off, dinfo->weak_bind_size,
974 	  dinfo->weak_bind_off + dinfo->weak_bind_size);
975   printf ("    lazy bind: off: 0x%08x  size: %-8u   (endoff: 0x%08x)\n",
976 	  dinfo->lazy_bind_off, dinfo->lazy_bind_size,
977 	  dinfo->lazy_bind_off + dinfo->lazy_bind_size);
978   printf ("       export: off: 0x%08x  size: %-8u   (endoff: 0x%08x)\n",
979 	  dinfo->export_off, dinfo->export_size,
980 	  dinfo->export_off + dinfo->export_size);
981 
982   if (!verbose)
983     return;
984 
985   printf ("   rebase:\n");
986   if (!load_and_dump (abfd, dinfo->rebase_off, dinfo->rebase_size,
987 		      dump_dyld_info_rebase))
988     non_fatal (_("cannot read rebase dyld info"));
989 
990   printf ("   bind:\n");
991   if (!load_and_dump (abfd, dinfo->bind_off, dinfo->bind_size,
992 		      dump_dyld_info_bind))
993     non_fatal (_("cannot read bind dyld info"));
994 
995   printf ("   weak bind:\n");
996   if (!load_and_dump (abfd, dinfo->weak_bind_off, dinfo->weak_bind_size,
997 		      dump_dyld_info_bind))
998     non_fatal (_("cannot read weak bind dyld info"));
999 
1000   printf ("   lazy bind:\n");
1001   if (!load_and_dump (abfd, dinfo->lazy_bind_off, dinfo->lazy_bind_size,
1002 		      dump_dyld_info_bind))
1003     non_fatal (_("cannot read lazy bind dyld info"));
1004 
1005   printf ("   exported symbols:\n");
1006   if (!load_and_dump (abfd, dinfo->export_off, dinfo->export_size,
1007 		      dump_dyld_info_export))
1008     non_fatal (_("cannot read export symbols dyld info"));
1009 }
1010 
1011 static void
dump_thread(bfd * abfd,bfd_mach_o_load_command * cmd)1012 dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
1013 {
1014   bfd_mach_o_thread_command *thread = &cmd->command.thread;
1015   unsigned int j;
1016   bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
1017   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1018 
1019   printf (" nflavours: %lu\n", thread->nflavours);
1020   for (j = 0; j < thread->nflavours; j++)
1021     {
1022       bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
1023       const bfd_mach_o_xlat_name *name_table;
1024 
1025       printf ("  %2u: flavour: 0x%08lx", j, flavour->flavour);
1026       switch (mdata->header.cputype)
1027         {
1028         case BFD_MACH_O_CPU_TYPE_I386:
1029         case BFD_MACH_O_CPU_TYPE_X86_64:
1030           name_table = bfd_mach_o_thread_x86_name;
1031           break;
1032         default:
1033           name_table = NULL;
1034           break;
1035         }
1036       if (name_table != NULL)
1037         printf (": %s", bfd_mach_o_get_name (name_table, flavour->flavour));
1038       putchar ('\n');
1039 
1040       printf ("       offset: 0x%08lx  size: 0x%08lx\n",
1041               flavour->offset, flavour->size);
1042       if (bed->_bfd_mach_o_print_thread)
1043         {
1044           char *buf = xmalloc (flavour->size);
1045 
1046           if (bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
1047               && bfd_bread (buf, flavour->size, abfd) == flavour->size)
1048             (*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, buf);
1049 
1050           free (buf);
1051         }
1052     }
1053 }
1054 
1055 static const bfd_mach_o_xlat_name bfd_mach_o_cs_magic[] =
1056 {
1057   { "embedded signature", BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE },
1058   { "requirement", BFD_MACH_O_CS_MAGIC_REQUIREMENT },
1059   { "requirements", BFD_MACH_O_CS_MAGIC_REQUIREMENTS },
1060   { "code directory", BFD_MACH_O_CS_MAGIC_CODEDIRECTORY },
1061   { "embedded entitlements", BFD_MACH_O_CS_MAGIC_EMBEDDED_ENTITLEMENTS },
1062   { "blob wrapper", BFD_MACH_O_CS_MAGIC_BLOB_WRAPPER },
1063   { NULL, 0 }
1064 };
1065 
1066 static const bfd_mach_o_xlat_name bfd_mach_o_cs_hash_type[] =
1067 {
1068   { "no-hash", BFD_MACH_O_CS_NO_HASH },
1069   { "sha1", BFD_MACH_O_CS_HASH_SHA1 },
1070   { "sha256", BFD_MACH_O_CS_HASH_SHA256 },
1071   { "skein 160", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_160x256 },
1072   { "skein 256", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_256x512 },
1073   { NULL, 0 }
1074 };
1075 
1076 static unsigned int
1077 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len);
1078 
1079 static void
dump_code_signature_superblob(bfd * abfd ATTRIBUTE_UNUSED,const unsigned char * buf,unsigned int len)1080 dump_code_signature_superblob (bfd *abfd ATTRIBUTE_UNUSED,
1081                                const unsigned char *buf, unsigned int len)
1082 {
1083   unsigned int count;
1084   unsigned int i;
1085 
1086   if (len < 12)
1087     {
1088       printf (_("  [bad block length]\n"));
1089       return;
1090     }
1091   count = bfd_getb32 (buf + 8);
1092   printf (ngettext ("  %u index entry:\n",
1093 		    "  %u index entries:\n",
1094 		    count),
1095 	  count);
1096   if (len < 12 + 8 * count)
1097     {
1098       printf (_("  [bad block length]\n"));
1099       return;
1100     }
1101   for (i = 0; i < count; i++)
1102     {
1103       unsigned int type;
1104       unsigned int off;
1105 
1106       type = bfd_getb32 (buf + 12 + 8 * i);
1107       off = bfd_getb32 (buf + 12 + 8 * i + 4);
1108       printf (_("  index entry %u: type: %08x, offset: %08x\n"),
1109               i, type, off);
1110 
1111       dump_code_signature_blob (abfd, buf + off, len - off);
1112     }
1113 }
1114 
1115 static void
swap_code_codedirectory_v1_in(const struct mach_o_codesign_codedirectory_external_v1 * src,struct mach_o_codesign_codedirectory_v1 * dst)1116 swap_code_codedirectory_v1_in
1117   (const struct mach_o_codesign_codedirectory_external_v1 *src,
1118    struct mach_o_codesign_codedirectory_v1 *dst)
1119 {
1120   dst->version = bfd_getb32 (src->version);
1121   dst->flags = bfd_getb32 (src->flags);
1122   dst->hash_offset = bfd_getb32 (src->hash_offset);
1123   dst->ident_offset = bfd_getb32 (src->ident_offset);
1124   dst->nbr_special_slots = bfd_getb32 (src->nbr_special_slots);
1125   dst->nbr_code_slots = bfd_getb32 (src->nbr_code_slots);
1126   dst->code_limit = bfd_getb32 (src->code_limit);
1127   dst->hash_size = src->hash_size[0];
1128   dst->hash_type = src->hash_type[0];
1129   dst->spare1 = src->spare1[0];
1130   dst->page_size = src->page_size[0];
1131   dst->spare2 = bfd_getb32 (src->spare2);
1132 }
1133 
1134 static void
hexdump(unsigned int start,unsigned int len,const unsigned char * buf)1135 hexdump (unsigned int start, unsigned int len,
1136          const unsigned char *buf)
1137 {
1138   unsigned int i, j;
1139 
1140   for (i = 0; i < len; i += 16)
1141     {
1142       printf ("%08x:", start + i);
1143       for (j = 0; j < 16; j++)
1144         {
1145           fputc (j == 8 ? '-' : ' ', stdout);
1146           if (i + j < len)
1147             printf ("%02x", buf[i + j]);
1148           else
1149             fputs ("  ", stdout);
1150         }
1151       fputc (' ', stdout);
1152       for (j = 0; j < 16; j++)
1153         {
1154           if (i + j < len)
1155             fputc (ISPRINT (buf[i + j]) ? buf[i + j] : '.', stdout);
1156           else
1157             fputc (' ', stdout);
1158         }
1159       fputc ('\n', stdout);
1160     }
1161 }
1162 
1163 static void
dump_code_signature_codedirectory(bfd * abfd ATTRIBUTE_UNUSED,const unsigned char * buf,unsigned int len)1164 dump_code_signature_codedirectory (bfd *abfd ATTRIBUTE_UNUSED,
1165                                    const unsigned char *buf, unsigned int len)
1166 {
1167   struct mach_o_codesign_codedirectory_v1 cd;
1168   const char *id;
1169 
1170   if (len < sizeof (struct mach_o_codesign_codedirectory_external_v1))
1171     {
1172       printf (_("  [bad block length]\n"));
1173       return;
1174     }
1175 
1176   swap_code_codedirectory_v1_in
1177     ((const struct mach_o_codesign_codedirectory_external_v1 *) (buf + 8), &cd);
1178 
1179   printf (_("  version:           %08x\n"), cd.version);
1180   printf (_("  flags:             %08x\n"), cd.flags);
1181   printf (_("  hash offset:       %08x\n"), cd.hash_offset);
1182   id = (const char *) buf + cd.ident_offset;
1183   printf (_("  ident offset:      %08x (- %08x)\n"),
1184           cd.ident_offset, cd.ident_offset + (unsigned) strlen (id) + 1);
1185   printf (_("   identity: %s\n"), id);
1186   printf (_("  nbr special slots: %08x (at offset %08x)\n"),
1187           cd.nbr_special_slots,
1188           cd.hash_offset - cd.nbr_special_slots * cd.hash_size);
1189   printf (_("  nbr code slots:    %08x\n"), cd.nbr_code_slots);
1190   printf (_("  code limit:        %08x\n"), cd.code_limit);
1191   printf (_("  hash size:         %02x\n"), cd.hash_size);
1192   printf (_("  hash type:         %02x (%s)\n"),
1193           cd.hash_type,
1194           bfd_mach_o_get_name (bfd_mach_o_cs_hash_type, cd.hash_type));
1195   printf (_("  spare1:            %02x\n"), cd.spare1);
1196   printf (_("  page size:         %02x\n"), cd.page_size);
1197   printf (_("  spare2:            %08x\n"), cd.spare2);
1198   if (cd.version >= 0x20100)
1199     printf (_("  scatter offset:    %08x\n"),
1200             (unsigned) bfd_getb32 (buf + 44));
1201 }
1202 
1203 static unsigned int
dump_code_signature_blob(bfd * abfd,const unsigned char * buf,unsigned int len)1204 dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len)
1205 {
1206   unsigned int magic;
1207   unsigned int length;
1208 
1209   if (len < 8)
1210     {
1211       printf (_("  [truncated block]\n"));
1212       return 0;
1213     }
1214   magic = bfd_getb32 (buf);
1215   length = bfd_getb32 (buf + 4);
1216   if (magic == 0 || length == 0)
1217     return 0;
1218 
1219   printf (_(" magic : %08x (%s)\n"), magic,
1220           bfd_mach_o_get_name (bfd_mach_o_cs_magic, magic));
1221   printf (_(" length: %08x\n"), length);
1222   if (length > len)
1223     {
1224       printf (_("  [bad block length]\n"));
1225       return 0;
1226     }
1227 
1228   switch (magic)
1229     {
1230     case BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE:
1231       dump_code_signature_superblob (abfd, buf, length);
1232       break;
1233     case BFD_MACH_O_CS_MAGIC_CODEDIRECTORY:
1234       dump_code_signature_codedirectory (abfd, buf, length);
1235       break;
1236     default:
1237       hexdump (0, length - 8, buf + 8);
1238       break;
1239     }
1240   return length;
1241 }
1242 
1243 static void
dump_code_signature(bfd * abfd,bfd_mach_o_linkedit_command * cmd)1244 dump_code_signature (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
1245 {
1246   unsigned char *buf = xmalloc (cmd->datasize);
1247   unsigned int off;
1248 
1249   if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
1250       || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
1251     {
1252       non_fatal (_("cannot read code signature data"));
1253       free (buf);
1254       return;
1255     }
1256   for (off = 0; off < cmd->datasize;)
1257     {
1258       unsigned int len;
1259 
1260       len = dump_code_signature_blob (abfd, buf + off, cmd->datasize - off);
1261 
1262       if (len == 0)
1263         break;
1264       off += len;
1265     }
1266   free (buf);
1267 }
1268 
1269 static void
dump_segment_split_info(bfd * abfd,bfd_mach_o_linkedit_command * cmd)1270 dump_segment_split_info (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
1271 {
1272   unsigned char *buf = xmalloc (cmd->datasize);
1273   unsigned char *p;
1274   unsigned int len;
1275   bfd_vma addr = 0;
1276 
1277   if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
1278       || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
1279     {
1280       non_fatal (_("cannot read segment split info"));
1281       free (buf);
1282       return;
1283     }
1284   if (buf[cmd->datasize - 1] != 0)
1285     {
1286       non_fatal (_("segment split info is not nul terminated"));
1287       free (buf);
1288       return;
1289     }
1290 
1291   switch (buf[0])
1292     {
1293     case 0:
1294       printf (_("  32 bit pointers:\n"));
1295       break;
1296     case 1:
1297       printf (_("  64 bit pointers:\n"));
1298       break;
1299     case 2:
1300       printf (_("  PPC hi-16:\n"));
1301       break;
1302     default:
1303       printf (_("  Unhandled location type %u\n"), buf[0]);
1304       break;
1305     }
1306   for (p = buf + 1; *p != 0; p += len)
1307     {
1308       addr += read_leb128 (p, buf + cmd->datasize, 0, &len, NULL);
1309       fputs ("    ", stdout);
1310       bfd_printf_vma (abfd, addr);
1311       putchar ('\n');
1312     }
1313   free (buf);
1314 }
1315 
1316 static void
dump_function_starts(bfd * abfd,bfd_mach_o_linkedit_command * cmd)1317 dump_function_starts (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
1318 {
1319   unsigned char *buf = xmalloc (cmd->datasize);
1320   unsigned char *end_buf = buf + cmd->datasize;
1321   unsigned char *p;
1322   bfd_vma addr;
1323 
1324   if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
1325       || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
1326     {
1327       non_fatal (_("cannot read function starts"));
1328       free (buf);
1329       return;
1330     }
1331 
1332   /* Function starts are delta encoded, starting from the base address.  */
1333   addr = bfd_mach_o_get_base_address (abfd);
1334 
1335   for (p = buf; ;)
1336     {
1337       bfd_vma delta = 0;
1338       unsigned int shift = 0;
1339 
1340       if (*p == 0 || p == end_buf)
1341 	break;
1342       while (1)
1343 	{
1344 	  unsigned char b = *p++;
1345 
1346 	  delta |= (b & 0x7f) << shift;
1347 	  if ((b & 0x80) == 0)
1348 	    break;
1349 	  if (p == end_buf)
1350 	    {
1351 	      fputs ("   [truncated]\n", stdout);
1352 	      break;
1353 	    }
1354 	  shift += 7;
1355 	}
1356 
1357       addr += delta;
1358       fputs ("    ", stdout);
1359       bfd_printf_vma (abfd, addr);
1360       putchar ('\n');
1361     }
1362   free (buf);
1363 }
1364 
1365 static const bfd_mach_o_xlat_name data_in_code_kind_name[] =
1366 {
1367   { "data", BFD_MACH_O_DICE_KIND_DATA },
1368   { "1 byte jump table", BFD_MACH_O_DICE_JUMP_TABLES8 },
1369   { "2 bytes jump table", BFD_MACH_O_DICE_JUMP_TABLES16 },
1370   { "4 bytes jump table", BFD_MACH_O_DICE_JUMP_TABLES32 },
1371   { "4 bytes abs jump table", BFD_MACH_O_DICE_ABS_JUMP_TABLES32 },
1372   { NULL, 0 }
1373 };
1374 
1375 static void
dump_data_in_code(bfd * abfd,bfd_mach_o_linkedit_command * cmd)1376 dump_data_in_code (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
1377 {
1378   unsigned char *buf;
1379   unsigned char *p;
1380 
1381   if (cmd->datasize == 0)
1382     {
1383       printf ("   no data_in_code entries\n");
1384       return;
1385     }
1386 
1387   buf = xmalloc (cmd->datasize);
1388   if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
1389       || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
1390     {
1391       non_fatal (_("cannot read data_in_code"));
1392       free (buf);
1393       return;
1394     }
1395 
1396   printf ("   offset     length kind\n");
1397   for (p = buf; p < buf + cmd->datasize; )
1398     {
1399       struct mach_o_data_in_code_entry_external *dice;
1400       unsigned int offset;
1401       unsigned int length;
1402       unsigned int kind;
1403 
1404       dice = (struct mach_o_data_in_code_entry_external *) p;
1405 
1406       offset = bfd_get_32 (abfd, dice->offset);
1407       length = bfd_get_16 (abfd, dice->length);
1408       kind = bfd_get_16 (abfd, dice->kind);
1409 
1410       printf ("   0x%08x 0x%04x 0x%04x %s\n", offset, length, kind,
1411 	      bfd_mach_o_get_name (data_in_code_kind_name, kind));
1412 
1413       p += sizeof (*dice);
1414     }
1415   free (buf);
1416 }
1417 
1418 static void
dump_twolevel_hints(bfd * abfd,bfd_mach_o_twolevel_hints_command * cmd)1419 dump_twolevel_hints (bfd *abfd, bfd_mach_o_twolevel_hints_command *cmd)
1420 {
1421   size_t sz = 4 * cmd->nhints;
1422   unsigned char *buf;
1423   unsigned char *p;
1424 
1425   buf = xmalloc (sz);
1426   if (bfd_seek (abfd, cmd->offset, SEEK_SET) != 0
1427       || bfd_bread (buf, sz, abfd) != sz)
1428     {
1429       non_fatal (_("cannot read twolevel hints"));
1430       free (buf);
1431       return;
1432     }
1433 
1434   for (p = buf; p < buf + sz; p += 4)
1435     {
1436       unsigned int v;
1437       unsigned int isub_image;
1438       unsigned int itoc;
1439 
1440       v = bfd_get_32 (abfd, p);
1441       if (bfd_big_endian (abfd))
1442 	{
1443 	  isub_image = (v >> 24) & 0xff;
1444 	  itoc = v & 0xffffff;
1445 	}
1446       else
1447 	{
1448 	  isub_image = v & 0xff;
1449 	  itoc = (v >> 8) & 0xffffff;
1450 	}
1451 
1452       printf ("  %3u %8u\n", isub_image, itoc);
1453     }
1454   free (buf);
1455 }
1456 
1457 static void
printf_version(uint32_t version)1458 printf_version (uint32_t version)
1459 {
1460   uint32_t maj, min, upd;
1461 
1462   maj = (version >> 16) & 0xffff;
1463   min = (version >> 8) & 0xff;
1464   upd = version & 0xff;
1465 
1466   printf ("%u.%u.%u", maj, min, upd);
1467 }
1468 
1469 static void
dump_build_version(bfd * abfd,bfd_mach_o_load_command * cmd)1470 dump_build_version (bfd *abfd, bfd_mach_o_load_command *cmd)
1471 {
1472   const char *platform_name;
1473   size_t tools_len, tools_offset;
1474   bfd_mach_o_build_version_tool *tools, *tool;
1475   bfd_mach_o_build_version_command *ver = &cmd->command.build_version;
1476   uint32_t i;
1477 
1478   platform_name = bfd_mach_o_get_name_or_null
1479     (bfd_mach_o_platform_name, ver->platform);
1480   if (platform_name == NULL)
1481     printf ("   platform: 0x%08x\n", ver->platform);
1482   else
1483     printf ("   platform: %s\n", platform_name);
1484   printf ("   os:       ");
1485   printf_version (ver->minos);
1486   printf ("\n   sdk:      ");
1487   printf_version (ver->sdk);
1488   printf ("\n   ntools:   %u\n", ver->ntools);
1489 
1490   tools_len = sizeof (bfd_mach_o_build_version_tool) * ver->ntools;
1491   tools_offset = cmd->offset + cmd->len - tools_len;
1492 
1493   tools = xmalloc (tools_len);
1494   if (bfd_seek (abfd, tools_offset, SEEK_SET) != 0
1495       || bfd_bread (tools, tools_len, abfd) != tools_len)
1496     {
1497       non_fatal (_("cannot read build tools"));
1498       free (tools);
1499       return;
1500     }
1501 
1502   for (i = 0, tool = tools; i < ver->ntools; i++, tool++)
1503     {
1504       const char * tool_name;
1505 
1506       tool_name = bfd_mach_o_get_name_or_null
1507 	(bfd_mach_o_tool_name, tool->tool);
1508       if (tool_name == NULL)
1509 	printf ("   tool:     0x%08x\n", tool->tool);
1510       else
1511 	printf ("   tool:     %s\n", tool_name);
1512       printf ("   version:  ");
1513       printf_version (tool->version);
1514       printf ("\n");
1515     }
1516   free (tools);
1517 }
1518 
1519 static void
dump_load_command(bfd * abfd,bfd_mach_o_load_command * cmd,unsigned int idx,bool verbose)1520 dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
1521                    unsigned int idx, bool verbose)
1522 {
1523   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1524   const char *cmd_name;
1525 
1526   cmd_name = bfd_mach_o_get_name_or_null
1527     (bfd_mach_o_load_command_name, cmd->type);
1528   printf ("Load command #%-2u (size: %3u, offset: %4u): ",
1529 	  idx, cmd->len, cmd->offset);
1530   if (cmd_name == NULL)
1531     printf ("0x%02x\n", cmd->type);
1532   else
1533     printf ("%s\n", cmd_name);
1534 
1535   switch (cmd->type)
1536     {
1537     case BFD_MACH_O_LC_SEGMENT:
1538     case BFD_MACH_O_LC_SEGMENT_64:
1539       dump_segment (abfd, cmd);
1540       break;
1541     case BFD_MACH_O_LC_UUID:
1542       {
1543         bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
1544         unsigned int j;
1545 
1546 	printf ("   ");
1547         for (j = 0; j < sizeof (uuid->uuid); j ++)
1548           printf (" %02x", uuid->uuid[j]);
1549         putchar ('\n');
1550       }
1551       break;
1552     case BFD_MACH_O_LC_LOAD_DYLIB:
1553     case BFD_MACH_O_LC_LAZY_LOAD_DYLIB:
1554     case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1555     case BFD_MACH_O_LC_REEXPORT_DYLIB:
1556     case BFD_MACH_O_LC_ID_DYLIB:
1557     case BFD_MACH_O_LC_LOAD_UPWARD_DYLIB:
1558       {
1559         bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
1560         printf ("  name: %s\n", dylib->name_str);
1561         printf ("            time stamp: 0x%08lx\n",
1562                 dylib->timestamp);
1563         printf ("       current version: 0x%08lx\n",
1564                 dylib->current_version);
1565         printf ("  comptibility version: 0x%08lx\n",
1566                 dylib->compatibility_version);
1567       }
1568       break;
1569     case BFD_MACH_O_LC_LOAD_DYLINKER:
1570     case BFD_MACH_O_LC_ID_DYLINKER:
1571       printf ("    %s\n", cmd->command.dylinker.name_str);
1572       break;
1573     case BFD_MACH_O_LC_DYLD_ENVIRONMENT:
1574       printf ("    %s\n", cmd->command.dylinker.name_str);
1575       break;
1576     case BFD_MACH_O_LC_SYMTAB:
1577       {
1578         bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
1579         printf ("   symoff: 0x%08x    nsyms: %8u  (endoff: 0x%08x)\n",
1580                 symtab->symoff, symtab->nsyms,
1581                 symtab->symoff + symtab->nsyms
1582                 * (mdata->header.version == 2
1583                    ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE));
1584         printf ("   stroff: 0x%08x  strsize: %8u  (endoff: 0x%08x)\n",
1585                 symtab->stroff, symtab->strsize,
1586                 symtab->stroff + symtab->strsize);
1587         break;
1588       }
1589     case BFD_MACH_O_LC_DYSYMTAB:
1590       dump_dysymtab (abfd, cmd, verbose);
1591       break;
1592     case BFD_MACH_O_LC_LOADFVMLIB:
1593     case BFD_MACH_O_LC_IDFVMLIB:
1594       {
1595         bfd_mach_o_fvmlib_command *fvmlib = &cmd->command.fvmlib;
1596         printf ("                fvmlib: %s\n", fvmlib->name_str);
1597         printf ("         minor version: 0x%08x\n", fvmlib->minor_version);
1598         printf ("        header address: 0x%08x\n", fvmlib->header_addr);
1599       }
1600       break;
1601     case BFD_MACH_O_LC_CODE_SIGNATURE:
1602     case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
1603     case BFD_MACH_O_LC_FUNCTION_STARTS:
1604     case BFD_MACH_O_LC_DATA_IN_CODE:
1605     case BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS:
1606     case BFD_MACH_O_LC_DYLD_EXPORTS_TRIE:
1607     case BFD_MACH_O_LC_DYLD_CHAINED_FIXUPS:
1608       {
1609         bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
1610         printf
1611           ("  dataoff: 0x%08lx  datasize: 0x%08lx  (endoff: 0x%08lx)\n",
1612            linkedit->dataoff, linkedit->datasize,
1613            linkedit->dataoff + linkedit->datasize);
1614 
1615 	if (verbose)
1616 	  switch (cmd->type)
1617 	    {
1618 	    case BFD_MACH_O_LC_CODE_SIGNATURE:
1619 	      dump_code_signature (abfd, linkedit);
1620 	      break;
1621 	    case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
1622 	      dump_segment_split_info (abfd, linkedit);
1623 	      break;
1624 	    case BFD_MACH_O_LC_FUNCTION_STARTS:
1625 	      dump_function_starts (abfd, linkedit);
1626 	      break;
1627 	    case BFD_MACH_O_LC_DATA_IN_CODE:
1628 	      dump_data_in_code (abfd, linkedit);
1629 	      break;
1630 	    default:
1631 	      break;
1632 	    }
1633       }
1634       break;
1635     case BFD_MACH_O_LC_SUB_FRAMEWORK:
1636     case BFD_MACH_O_LC_SUB_UMBRELLA:
1637     case BFD_MACH_O_LC_SUB_LIBRARY:
1638     case BFD_MACH_O_LC_SUB_CLIENT:
1639     case BFD_MACH_O_LC_RPATH:
1640       {
1641         bfd_mach_o_str_command *strc = &cmd->command.str;
1642         printf ("    %s\n", strc->str);
1643         break;
1644       }
1645     case BFD_MACH_O_LC_THREAD:
1646     case BFD_MACH_O_LC_UNIXTHREAD:
1647       dump_thread (abfd, cmd);
1648       break;
1649     case BFD_MACH_O_LC_ENCRYPTION_INFO:
1650       {
1651         bfd_mach_o_encryption_info_command *cryp =
1652           &cmd->command.encryption_info;
1653         printf ("  cryptoff: 0x%08x  cryptsize: 0x%08x (endoff 0x%08x)"
1654 		" cryptid: %u\n",
1655 		cryp->cryptoff, cryp->cryptsize,
1656 		cryp->cryptoff + cryp->cryptsize,
1657 		cryp->cryptid);
1658       }
1659       break;
1660     case BFD_MACH_O_LC_DYLD_INFO:
1661       dump_dyld_info (abfd, cmd, verbose);
1662       break;
1663     case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
1664     case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
1665     case BFD_MACH_O_LC_VERSION_MIN_WATCHOS:
1666     case BFD_MACH_O_LC_VERSION_MIN_TVOS:
1667       {
1668         bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
1669 
1670         printf ("   os: ");
1671         printf_version (ver->version);
1672         printf ("\n   sdk: ");
1673         printf_version (ver->sdk);
1674         printf ("\n");
1675       }
1676       break;
1677     case BFD_MACH_O_LC_SOURCE_VERSION:
1678       {
1679         bfd_mach_o_source_version_command *version =
1680 	  &cmd->command.source_version;
1681         printf ("   version a.b.c.d.e: %u.%u.%u.%u.%u\n",
1682 		version->a, version->b, version->c, version->d, version->e);
1683         break;
1684       }
1685     case BFD_MACH_O_LC_PREBOUND_DYLIB:
1686       {
1687         bfd_mach_o_prebound_dylib_command *pbdy = &cmd->command.prebound_dylib;
1688 	unsigned char *lm = pbdy->linked_modules;
1689 	unsigned int j;
1690 	unsigned int last;
1691 
1692         printf ("      dylib: %s\n", pbdy->name_str);
1693         printf ("   nmodules: %u\n", pbdy->nmodules);
1694 	printf ("   linked modules (at %u): ",
1695 		pbdy->linked_modules_offset - cmd->offset);
1696 	last = pbdy->nmodules > 32 ? 32 : pbdy->nmodules;
1697 	for (j = 0; j < last; j++)
1698 	  printf ("%u", (lm[j >> 3] >> (j & 7)) & 1);
1699 	if (last < pbdy->nmodules)
1700 	  printf ("...");
1701 	putchar ('\n');
1702         break;
1703       }
1704     case BFD_MACH_O_LC_PREBIND_CKSUM:
1705       {
1706         bfd_mach_o_prebind_cksum_command *cksum = &cmd->command.prebind_cksum;
1707         printf ("   0x%08x\n", cksum->cksum);
1708         break;
1709       }
1710     case BFD_MACH_O_LC_TWOLEVEL_HINTS:
1711       {
1712         bfd_mach_o_twolevel_hints_command *hints =
1713 	  &cmd->command.twolevel_hints;
1714 
1715         printf ("   table offset: 0x%08x  nbr hints: %u\n",
1716 		hints->offset, hints->nhints);
1717 	if (verbose)
1718 	  dump_twolevel_hints (abfd, hints);
1719         break;
1720       }
1721     case BFD_MACH_O_LC_MAIN:
1722       {
1723 	bfd_mach_o_main_command *entry = &cmd->command.main;
1724 	printf ("   entry offset: %#016" PRIx64 "\n"
1725 		"   stack size:   %#016" PRIx64 "\n",
1726 		entry->entryoff, entry->stacksize);
1727 	break;
1728       }
1729     case BFD_MACH_O_LC_NOTE:
1730       {
1731 	bfd_mach_o_note_command *note = &cmd->command.note;
1732 	printf ("   data owner: %.16s\n"
1733 		"   offset:     %#016" PRIx64 "\n"
1734 		"   size:       %#016" PRIx64 "\n",
1735 		note->data_owner, note->offset, note->size);
1736 	break;
1737       }
1738     case BFD_MACH_O_LC_BUILD_VERSION:
1739       dump_build_version (abfd, cmd);
1740       break;
1741     default:
1742       break;
1743     }
1744   putchar ('\n');
1745 }
1746 
1747 static void
dump_load_commands(bfd * abfd,unsigned int cmd32,unsigned int cmd64)1748 dump_load_commands (bfd *abfd, unsigned int cmd32, unsigned int cmd64)
1749 {
1750   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1751   bfd_mach_o_load_command *cmd;
1752   unsigned int i;
1753 
1754   for (cmd = mdata->first_command, i = 0; cmd != NULL; cmd = cmd->next, i++)
1755     {
1756       if (cmd32 == 0)
1757         dump_load_command (abfd, cmd, i, false);
1758       else if (cmd->type == cmd32 || cmd->type == cmd64)
1759         dump_load_command (abfd, cmd, i, true);
1760     }
1761 }
1762 
1763 static const char * const unwind_x86_64_regs[] =
1764   {"", "rbx", "r12", "r13", "r14", "r15", "rbp", "???" };
1765 
1766 static const char * const unwind_x86_regs[] =
1767   {"", "ebx", "ecx", "edx", "edi", "edi", "ebp", "???" };
1768 
1769 /* Dump x86 or x86-64 compact unwind encoding.  Works for both architecture,
1770    as the encoding is the same (but not register names).  */
1771 
1772 static void
dump_unwind_encoding_x86(unsigned int encoding,unsigned int sz,const char * const regs_name[])1773 dump_unwind_encoding_x86 (unsigned int encoding, unsigned int sz,
1774 			  const char * const regs_name[])
1775 {
1776   unsigned int mode;
1777 
1778   mode = encoding & MACH_O_UNWIND_X86_64_MODE_MASK;
1779   switch (mode)
1780     {
1781     case MACH_O_UNWIND_X86_64_MODE_RBP_FRAME:
1782       {
1783 	unsigned int regs;
1784 	char pfx = sz == 8 ? 'R' : 'E';
1785 
1786 	regs = encoding & MACH_O_UNWIND_X86_64_RBP_FRAME_REGISTERS;
1787 	printf (" %cSP frame", pfx);
1788 	if (regs != 0)
1789 	  {
1790 	    unsigned int offset;
1791 	    int i;
1792 
1793 	    offset = (encoding & MACH_O_UNWIND_X86_64_RBP_FRAME_OFFSET) >> 16;
1794 	    printf (" at %cBP-%u:", pfx, offset * sz);
1795 	    for (i = 0; i < 5; i++)
1796 	      {
1797 		unsigned int reg = (regs >> (i * 3)) & 0x7;
1798 		if (reg != MACH_O_UNWIND_X86_64_REG_NONE)
1799 		  printf (" %s", regs_name[reg]);
1800 	      }
1801 	  }
1802       }
1803       break;
1804     case MACH_O_UNWIND_X86_64_MODE_STACK_IMMD:
1805     case MACH_O_UNWIND_X86_64_MODE_STACK_IND:
1806       {
1807 	unsigned int stack_size;
1808 	unsigned int reg_count;
1809 	unsigned int reg_perm;
1810 	unsigned int regs[6];
1811 	int i, j;
1812 
1813 	printf (" frameless");
1814 	stack_size =
1815 	  (encoding & MACH_O_UNWIND_X86_64_FRAMELESS_STACK_SIZE) >> 16;
1816 	reg_count =
1817 	  (encoding & MACH_O_UNWIND_X86_64_FRAMELESS_REG_COUNT) >> 10;
1818 	reg_perm = encoding & MACH_O_UNWIND_X86_64_FRAMELESS_REG_PERMUTATION;
1819 
1820 	if (mode == MACH_O_UNWIND_X86_64_MODE_STACK_IMMD)
1821 	  printf (" size: 0x%03x", stack_size * sz);
1822 	else
1823 	  {
1824 	    unsigned int stack_adj;
1825 
1826 	    stack_adj =
1827 	      (encoding & MACH_O_UNWIND_X86_64_FRAMELESS_STACK_ADJUST) >> 13;
1828 	    printf (" size at 0x%03x + 0x%02x", stack_size, stack_adj * sz);
1829 	  }
1830 	/* Registers are coded using arithmetic compression: the register
1831 	   is indexed in range 0-6, the second in range 0-5, the third in
1832 	   range 0-4, etc.  Already used registers are removed in next
1833 	   ranges.  */
1834 #define DO_PERM(R, NUM) R = reg_perm / NUM; reg_perm -= R * NUM
1835 	switch (reg_count)
1836 	  {
1837 	  case 6:
1838 	  case 5:
1839 	    DO_PERM (regs[0], 120);
1840 	    DO_PERM (regs[1], 24);
1841 	    DO_PERM (regs[2], 6);
1842 	    DO_PERM (regs[3], 2);
1843 	    DO_PERM (regs[4], 1);
1844 	    regs[5] = 0; /* Not used if reg_count = 5.  */
1845 	    break;
1846 	  case 4:
1847 	    DO_PERM (regs[0], 60);
1848 	    DO_PERM (regs[1], 12);
1849 	    DO_PERM (regs[2], 3);
1850 	    DO_PERM (regs[3], 1);
1851 	    break;
1852 	  case 3:
1853 	    DO_PERM (regs[0], 20);
1854 	    DO_PERM (regs[1], 4);
1855 	    DO_PERM (regs[2], 1);
1856 	    break;
1857 	  case 2:
1858 	    DO_PERM (regs[0], 5);
1859 	    DO_PERM (regs[1], 1);
1860 	    break;
1861 	  case 1:
1862 	    DO_PERM (regs[0], 1);
1863 	    break;
1864 	  case 0:
1865 	    break;
1866 	  default:
1867 	    printf (" [bad reg count]");
1868 	    return;
1869 	  }
1870 #undef DO_PERM
1871 	/* Renumber.  */
1872 	for (i = reg_count - 1; i >= 0; i--)
1873 	  {
1874 	    unsigned int inc = 1;
1875 	    for (j = 0; j < i; j++)
1876 	      if (regs[i] >= regs[j])
1877 		inc++;
1878 	    regs[i] += inc;
1879 	  }
1880 	/* Display.  */
1881 	for (i = 0; i < (int) reg_count; i++)
1882 	  printf (" %s", regs_name[regs[i]]);
1883       }
1884       break;
1885     case MACH_O_UNWIND_X86_64_MODE_DWARF:
1886       printf (" Dwarf offset: 0x%06x",
1887 	      encoding & MACH_O_UNWIND_X86_64_DWARF_SECTION_OFFSET);
1888       break;
1889     default:
1890       printf (" [unhandled mode]");
1891       break;
1892     }
1893 }
1894 
1895 /* Dump arm64 compact unwind entries.  */
1896 
1897 static void
dump_unwind_encoding_arm64(unsigned int encoding)1898 dump_unwind_encoding_arm64 (unsigned int encoding)
1899 {
1900   switch (encoding & MACH_O_UNWIND_ARM64_MODE_MASK)
1901     {
1902     case MACH_O_UNWIND_ARM64_MODE_FRAMELESS:
1903       printf (" frameless");
1904       break;
1905     case MACH_O_UNWIND_ARM64_MODE_DWARF:
1906       printf (" Dwarf offset: 0x%06x",
1907 	      encoding & MACH_O_UNWIND_ARM64_DWARF_SECTION_OFFSET);
1908       return;
1909     case MACH_O_UNWIND_ARM64_MODE_FRAME:
1910       printf (" frame");
1911       break;
1912     default:
1913       printf (" [unhandled mode]");
1914       return;
1915     }
1916   switch (encoding & MACH_O_UNWIND_ARM64_MODE_MASK)
1917     {
1918     case MACH_O_UNWIND_ARM64_MODE_FRAMELESS:
1919     case MACH_O_UNWIND_ARM64_MODE_FRAME:
1920       if (encoding & MACH_O_UNWIND_ARM64_FRAME_X19_X20_PAIR)
1921 	printf (" x19-x20");
1922       if (encoding & MACH_O_UNWIND_ARM64_FRAME_X21_X22_PAIR)
1923 	printf (" x21-x22");
1924       if (encoding & MACH_O_UNWIND_ARM64_FRAME_X23_X24_PAIR)
1925 	printf (" x23-x24");
1926       if (encoding & MACH_O_UNWIND_ARM64_FRAME_X25_X26_PAIR)
1927 	printf (" x25-x26");
1928       if (encoding & MACH_O_UNWIND_ARM64_FRAME_X27_X28_PAIR)
1929 	printf (" x27-x28");
1930       break;
1931     }
1932   switch (encoding & MACH_O_UNWIND_ARM64_MODE_MASK)
1933     {
1934     case MACH_O_UNWIND_ARM64_MODE_FRAME:
1935       if (encoding & MACH_O_UNWIND_ARM64_FRAME_D8_D9_PAIR)
1936 	printf (" d8-d9");
1937       if (encoding & MACH_O_UNWIND_ARM64_FRAME_D10_D11_PAIR)
1938 	printf (" d10-d11");
1939       if (encoding & MACH_O_UNWIND_ARM64_FRAME_D12_D13_PAIR)
1940 	printf (" d12-d13");
1941       if (encoding & MACH_O_UNWIND_ARM64_FRAME_D14_D15_PAIR)
1942 	printf (" d14-d15");
1943       break;
1944     case MACH_O_UNWIND_ARM64_MODE_FRAMELESS:
1945       printf (" size: %u",
1946 	      (encoding & MACH_O_UNWIND_ARM64_FRAMELESS_STACK_SIZE_MASK) >> 8);
1947       break;
1948     }
1949 }
1950 
1951 static void
dump_unwind_encoding(bfd_mach_o_data_struct * mdata,unsigned int encoding)1952 dump_unwind_encoding (bfd_mach_o_data_struct *mdata, unsigned int encoding)
1953 {
1954   printf ("0x%08x", encoding);
1955   if (encoding == 0)
1956     return;
1957 
1958   switch (mdata->header.cputype)
1959     {
1960     case BFD_MACH_O_CPU_TYPE_X86_64:
1961       dump_unwind_encoding_x86 (encoding, 8, unwind_x86_64_regs);
1962       break;
1963     case BFD_MACH_O_CPU_TYPE_I386:
1964       dump_unwind_encoding_x86 (encoding, 4, unwind_x86_regs);
1965       break;
1966     case BFD_MACH_O_CPU_TYPE_ARM64:
1967       dump_unwind_encoding_arm64 (encoding);
1968       break;
1969     default:
1970       printf (" [unhandled cpu]");
1971       break;
1972     }
1973   if (encoding & MACH_O_UNWIND_HAS_LSDA)
1974     printf (" LSDA");
1975   if (encoding & MACH_O_UNWIND_PERSONALITY_MASK)
1976     printf (" PERS(%u)",
1977 	    ((encoding & MACH_O_UNWIND_PERSONALITY_MASK)
1978 	     >> MACH_O_UNWIND_PERSONALITY_SHIFT));
1979 }
1980 
1981 static void
dump_obj_compact_unwind(bfd * abfd,const unsigned char * content,bfd_size_type size)1982 dump_obj_compact_unwind (bfd *abfd,
1983 			 const unsigned char *content, bfd_size_type size)
1984 {
1985   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1986   int is_64 = mdata->header.version == 2;
1987   const unsigned char *p;
1988 
1989   printf ("Compact unwind info:\n");
1990   printf (" start            length   personality      lsda\n");
1991 
1992   if (is_64)
1993     {
1994       struct mach_o_compact_unwind_64 *e =
1995 	(struct mach_o_compact_unwind_64 *) content;
1996 
1997       for (p = content; p < content + size; p += sizeof (*e))
1998 	{
1999 	  e = (struct mach_o_compact_unwind_64 *) p;
2000 
2001 	  printf (" %#016" PRIx64 " %#08x %#016" PRIx64 " %#016" PRIx64 "\n",
2002 		  (uint64_t) bfd_get_64 (abfd, e->start),
2003 		  (unsigned int) bfd_get_32 (abfd, e->length),
2004 		  (uint64_t) bfd_get_64 (abfd, e->personality),
2005 		  (uint64_t) bfd_get_64 (abfd, e->lsda));
2006 
2007 	  printf ("  encoding: ");
2008 	  dump_unwind_encoding (mdata, bfd_get_32 (abfd, e->encoding));
2009 	  putchar ('\n');
2010 	}
2011     }
2012   else
2013     {
2014       printf ("unhandled\n");
2015     }
2016 }
2017 
2018 static void
dump_exe_compact_unwind(bfd * abfd,const unsigned char * content,bfd_size_type size)2019 dump_exe_compact_unwind (bfd *abfd,
2020 			 const unsigned char *content, bfd_size_type size)
2021 {
2022   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
2023   struct mach_o_unwind_info_header *hdr;
2024   unsigned int version;
2025   unsigned int encodings_offset;
2026   unsigned int encodings_count;
2027   unsigned int personality_offset;
2028   unsigned int personality_count;
2029   unsigned int index_offset;
2030   unsigned int index_count;
2031   struct mach_o_unwind_index_entry *index_entry;
2032   unsigned int i;
2033 
2034   /* The header.  */
2035   printf ("Compact unwind info:\n");
2036 
2037   hdr = (struct mach_o_unwind_info_header *) content;
2038   if (size < sizeof (*hdr))
2039     {
2040       printf ("  truncated!\n");
2041       return;
2042     }
2043 
2044   version = bfd_get_32 (abfd, hdr->version);
2045   if (version != MACH_O_UNWIND_SECTION_VERSION)
2046     {
2047       printf ("  unknown version: %u\n", version);
2048       return;
2049     }
2050   encodings_offset = bfd_get_32 (abfd, hdr->encodings_array_offset);
2051   encodings_count = bfd_get_32 (abfd, hdr->encodings_array_count);
2052   personality_offset = bfd_get_32 (abfd, hdr->personality_array_offset);
2053   personality_count = bfd_get_32 (abfd, hdr->personality_array_count);
2054   index_offset = bfd_get_32 (abfd, hdr->index_offset);
2055   index_count = bfd_get_32 (abfd, hdr->index_count);
2056   printf ("   %u encodings, %u personalities, %u level-1 indexes:\n",
2057 	  encodings_count, personality_count, index_count);
2058 
2059   /* Personality.  */
2060   if (personality_count > 0)
2061     {
2062       const unsigned char *pers = content + personality_offset;
2063 
2064       printf ("   personalities\n");
2065       for (i = 0; i < personality_count; i++)
2066 	printf ("     %u: 0x%08x\n", i,
2067 		(unsigned) bfd_get_32 (abfd, pers + 4 * i));
2068     }
2069 
2070   /* Level-1 index.  */
2071   printf ("   idx function   level2 off lsda off\n");
2072 
2073   index_entry = (struct mach_o_unwind_index_entry *) (content + index_offset);
2074   for (i = 0; i < index_count; i++)
2075     {
2076       unsigned int func_offset;
2077       unsigned int level2_offset;
2078       unsigned int lsda_offset;
2079 
2080       func_offset = bfd_get_32 (abfd, index_entry->function_offset);
2081       level2_offset = bfd_get_32 (abfd, index_entry->second_level_offset);
2082       lsda_offset = bfd_get_32 (abfd, index_entry->lsda_index_offset);
2083       printf ("   %3u 0x%08x 0x%08x 0x%08x\n",
2084 	      i, func_offset, level2_offset, lsda_offset);
2085       index_entry++;
2086     }
2087 
2088   /* Level-1 index.  */
2089   index_entry = (struct mach_o_unwind_index_entry *) (content + index_offset);
2090   for (i = 0; i < index_count; i++)
2091     {
2092       unsigned int func_offset;
2093       unsigned int level2_offset;
2094       const unsigned char *level2;
2095       unsigned int kind;
2096 
2097       func_offset = bfd_get_32 (abfd, index_entry->function_offset);
2098       level2_offset = bfd_get_32 (abfd, index_entry->second_level_offset);
2099 
2100       /* No level-2 for this index (should be the last index).  */
2101       if (level2_offset == 0)
2102 	continue;
2103 
2104       level2 = content + level2_offset;
2105       kind = bfd_get_32 (abfd, level2);
2106       switch (kind)
2107 	{
2108 	case MACH_O_UNWIND_SECOND_LEVEL_COMPRESSED:
2109 	  {
2110 	    struct mach_o_unwind_compressed_second_level_page_header *l2;
2111 	    unsigned int entry_offset;
2112 	    unsigned int entry_count;
2113 	    unsigned int l2_encodings_offset;
2114 	    unsigned int l2_encodings_count;
2115 	    const unsigned char *en;
2116 	    unsigned int j;
2117 
2118 	    l2 = (struct mach_o_unwind_compressed_second_level_page_header *)
2119 	      level2;
2120 	    entry_offset = bfd_get_16 (abfd, l2->entry_page_offset);
2121 	    entry_count = bfd_get_16 (abfd, l2->entry_count);
2122 	    l2_encodings_offset = bfd_get_16 (abfd, l2->encodings_offset);
2123 	    l2_encodings_count = bfd_get_16 (abfd, l2->encodings_count);
2124 
2125 	    printf ("   index %2u: compressed second level: "
2126 		    "%u entries, %u encodings (at 0x%08x)\n",
2127 		    i, entry_count, l2_encodings_count, l2_encodings_offset);
2128 	    printf ("   #    function   eidx  encoding\n");
2129 
2130 	    en = level2 + entry_offset;
2131 	    for (j = 0; j < entry_count; j++)
2132 	      {
2133 		unsigned int entry;
2134 		unsigned int en_func;
2135 		unsigned int enc_idx;
2136 		unsigned int encoding;
2137 		const unsigned char *enc_addr;
2138 
2139 		entry = bfd_get_32 (abfd, en);
2140 		en_func =
2141 		  MACH_O_UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry);
2142 		enc_idx =
2143 		  MACH_O_UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry);
2144 		if (enc_idx < encodings_count)
2145 		  enc_addr = content + encodings_offset
2146 		    + 4 * enc_idx;
2147 		else
2148 		  enc_addr = level2 + l2_encodings_offset
2149 		    + 4 * (enc_idx - encodings_count);
2150 		encoding = bfd_get_32 (abfd, enc_addr);
2151 
2152 		printf ("   %4u 0x%08x [%3u] ", j,
2153 			func_offset + en_func, enc_idx);
2154 		dump_unwind_encoding (mdata, encoding);
2155 		putchar ('\n');
2156 
2157 		en += 4;
2158 	      }
2159 	  }
2160 	  break;
2161 
2162 	case MACH_O_UNWIND_SECOND_LEVEL_REGULAR:
2163 	  {
2164 	    struct mach_o_unwind_regular_second_level_page_header *l2;
2165 	    struct mach_o_unwind_regular_second_level_entry *en;
2166 	    unsigned int entry_offset;
2167 	    unsigned int entry_count;
2168 	    unsigned int j;
2169 
2170 	    l2 = (struct mach_o_unwind_regular_second_level_page_header *)
2171 	      level2;
2172 
2173 	    entry_offset = bfd_get_16 (abfd, l2->entry_page_offset);
2174 	    entry_count = bfd_get_16 (abfd, l2->entry_count);
2175 	    printf ("   index %2u: regular level 2 at 0x%04x, %u entries\n",
2176 		    i, entry_offset, entry_count);
2177 	    printf ("   #    function   encoding\n");
2178 
2179 	    en = (struct mach_o_unwind_regular_second_level_entry *)
2180 	      (level2 + entry_offset);
2181 	    for (j = 0; j < entry_count; j++)
2182 	      {
2183 		unsigned int en_func;
2184 		unsigned int encoding;
2185 
2186 		en_func = bfd_get_32 (abfd, en->function_offset);
2187 		encoding = bfd_get_32 (abfd, en->encoding);
2188 		printf ("   %-4u 0x%08x ", j, en_func);
2189 		dump_unwind_encoding (mdata, encoding);
2190 		putchar ('\n');
2191 		en++;
2192 	      }
2193 	  }
2194 	  break;
2195 
2196 	default:
2197 	  printf ("   index %2u: unhandled second level format (%u)\n",
2198 		  i, kind);
2199 	  break;
2200 	}
2201 
2202       {
2203 	struct mach_o_unwind_lsda_index_entry *lsda;
2204 	unsigned int lsda_offset;
2205 	unsigned int next_lsda_offset;
2206 	unsigned int nbr_lsda;
2207 	unsigned int j;
2208 
2209 	lsda_offset = bfd_get_32 (abfd, index_entry->lsda_index_offset);
2210 	next_lsda_offset = bfd_get_32 (abfd, index_entry[1].lsda_index_offset);
2211 	lsda = (struct mach_o_unwind_lsda_index_entry *)
2212 	  (content + lsda_offset);
2213 	nbr_lsda = (next_lsda_offset - lsda_offset) / sizeof (*lsda);
2214 	for (j = 0; j < nbr_lsda; j++)
2215 	  {
2216 	    printf ("   lsda %3u: function 0x%08x lsda 0x%08x\n",
2217 		    j, (unsigned int) bfd_get_32 (abfd, lsda->function_offset),
2218 		    (unsigned int) bfd_get_32 (abfd, lsda->lsda_offset));
2219 	    lsda++;
2220 	  }
2221       }
2222       index_entry++;
2223     }
2224 }
2225 
2226 static void
dump_section_content(bfd * abfd,const char * segname,const char * sectname,void (* dump)(bfd *,const unsigned char *,bfd_size_type))2227 dump_section_content (bfd *abfd,
2228 		      const char *segname, const char *sectname,
2229 		      void (*dump)(bfd*, const unsigned char*, bfd_size_type))
2230 {
2231   bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
2232   bfd_mach_o_load_command *cmd;
2233 
2234   for (cmd = mdata->first_command; cmd != NULL; cmd = cmd->next)
2235     {
2236       if (cmd->type == BFD_MACH_O_LC_SEGMENT
2237 	  || cmd->type == BFD_MACH_O_LC_SEGMENT_64)
2238 	{
2239 	  bfd_mach_o_segment_command *seg = &cmd->command.segment;
2240 	  bfd_mach_o_section *sec;
2241 	  for (sec = seg->sect_head; sec != NULL; sec = sec->next)
2242 	    if (strcmp (sec->segname, segname) == 0
2243 		&& strcmp (sec->sectname, sectname) == 0)
2244 	      {
2245 		bfd_size_type size;
2246 		asection *bfdsec = sec->bfdsection;
2247 		unsigned char *content;
2248 
2249 		size = bfd_section_size (bfdsec);
2250 		content = (unsigned char *) xmalloc (size);
2251 		bfd_get_section_contents (abfd, bfdsec, content, 0, size);
2252 
2253 		(*dump)(abfd, content, size);
2254 
2255 		free (content);
2256 	      }
2257 	}
2258     }
2259 }
2260 
2261 /* Dump ABFD (according to the options[] array).  */
2262 
2263 static void
mach_o_dump(bfd * abfd)2264 mach_o_dump (bfd *abfd)
2265 {
2266   if (options[OPT_HEADER].selected)
2267     dump_header (abfd);
2268   if (options[OPT_SECTION].selected)
2269     dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT, BFD_MACH_O_LC_SEGMENT_64);
2270   if (options[OPT_MAP].selected)
2271     dump_section_map (abfd);
2272   if (options[OPT_LOAD].selected)
2273     dump_load_commands (abfd, 0, 0);
2274   if (options[OPT_DYSYMTAB].selected)
2275     dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0);
2276   if (options[OPT_CODESIGN].selected)
2277     dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
2278   if (options[OPT_SEG_SPLIT_INFO].selected)
2279     dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT_SPLIT_INFO, 0);
2280   if (options[OPT_FUNCTION_STARTS].selected)
2281     dump_load_commands (abfd, BFD_MACH_O_LC_FUNCTION_STARTS, 0);
2282   if (options[OPT_DATA_IN_CODE].selected)
2283     dump_load_commands (abfd, BFD_MACH_O_LC_DATA_IN_CODE, 0);
2284   if (options[OPT_TWOLEVEL_HINTS].selected)
2285     dump_load_commands (abfd, BFD_MACH_O_LC_TWOLEVEL_HINTS, 0);
2286   if (options[OPT_COMPACT_UNWIND].selected)
2287     {
2288       dump_section_content (abfd, "__LD", "__compact_unwind",
2289 			    dump_obj_compact_unwind);
2290       dump_section_content (abfd, "__TEXT", "__unwind_info",
2291 			    dump_exe_compact_unwind);
2292     }
2293   if (options[OPT_DYLD_INFO].selected)
2294     dump_load_commands (abfd, BFD_MACH_O_LC_DYLD_INFO, 0);
2295 }
2296 
2297 /* Vector for Mach-O.  */
2298 
2299 const struct objdump_private_desc objdump_private_desc_mach_o =
2300 {
2301  mach_o_help,
2302  mach_o_filter,
2303  mach_o_dump,
2304  options
2305 };
2306