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