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