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