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