This fixes a compile time error triggered by -Werror=format-security because
[deliverable/binutils-gdb.git] / binutils / od-macho.c
CommitLineData
12fa714f 1/* od-macho.c -- dump information about an Mach-O object file.
4b95cf5c 2 Copyright (C) 2011-2014 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"
29#include "bfdlink.h"
2128eb39 30#include "libbfd.h"
12fa714f
TG
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
12fa714f
TG
46
47/* List of actions. */
48static struct objdump_private_option options[] =
49 {
50 { "header", 0 },
51 { "section", 0 },
52 { "map", 0 },
53 { "load", 0 },
54 { "dysymtab", 0 },
2634e8c8 55 { "codesign", 0 },
2128eb39 56 { "seg_split_info", 0 },
167e1c1f 57 { "compact_unwind", 0 },
3cc27770 58 { "function_starts", 0 },
12fa714f
TG
59 { NULL, 0 }
60 };
61
62/* Display help. */
63
64static void
65mach_o_help (FILE *stream)
66{
67 fprintf (stream, _("\
68For Mach-O files:\n\
3cc27770
TG
69 header Display the file header\n\
70 section Display the segments and sections commands\n\
71 map Display the section map\n\
72 load Display the load commands\n\
73 dysymtab Display the dynamic symbol table\n\
74 codesign Display code signature\n\
75 seg_split_info Display segment split info\n\
76 compact_unwind Display compact unwinding info\n\
77 function_starts Display start address of functions\n\
12fa714f
TG
78"));
79}
80
81/* Return TRUE if ABFD is handled. */
82
83static int
84mach_o_filter (bfd *abfd)
85{
86 return bfd_get_flavour (abfd) == bfd_target_mach_o_flavour;
87}
88\f
89static const bfd_mach_o_xlat_name bfd_mach_o_cpu_name[] =
90{
91 { "vax", BFD_MACH_O_CPU_TYPE_VAX },
92 { "mc680x0", BFD_MACH_O_CPU_TYPE_MC680x0 },
93 { "i386", BFD_MACH_O_CPU_TYPE_I386 },
94 { "mips", BFD_MACH_O_CPU_TYPE_MIPS },
95 { "mc98000", BFD_MACH_O_CPU_TYPE_MC98000 },
96 { "hppa", BFD_MACH_O_CPU_TYPE_HPPA },
97 { "arm", BFD_MACH_O_CPU_TYPE_ARM },
98 { "mc88000", BFD_MACH_O_CPU_TYPE_MC88000 },
99 { "sparc", BFD_MACH_O_CPU_TYPE_SPARC },
100 { "i860", BFD_MACH_O_CPU_TYPE_I860 },
101 { "alpha", BFD_MACH_O_CPU_TYPE_ALPHA },
102 { "powerpc", BFD_MACH_O_CPU_TYPE_POWERPC },
103 { "powerpc_64", BFD_MACH_O_CPU_TYPE_POWERPC_64 },
104 { "x86_64", BFD_MACH_O_CPU_TYPE_X86_64 },
d8028530 105 { "arm64", BFD_MACH_O_CPU_TYPE_ARM64 },
12fa714f
TG
106 { NULL, 0}
107};
108
109static const bfd_mach_o_xlat_name bfd_mach_o_filetype_name[] =
110{
111 { "object", BFD_MACH_O_MH_OBJECT },
112 { "execute", BFD_MACH_O_MH_EXECUTE },
113 { "fvmlib", BFD_MACH_O_MH_FVMLIB },
114 { "core", BFD_MACH_O_MH_CORE },
115 { "preload", BFD_MACH_O_MH_PRELOAD },
116 { "dylib", BFD_MACH_O_MH_DYLIB },
117 { "dylinker", BFD_MACH_O_MH_DYLINKER },
118 { "bundle", BFD_MACH_O_MH_BUNDLE },
119 { "dylib_stub", BFD_MACH_O_MH_DYLIB_STUB },
120 { "dym", BFD_MACH_O_MH_DSYM },
121 { "kext_bundle", BFD_MACH_O_MH_KEXT_BUNDLE },
122 { NULL, 0}
123};
124
125static const bfd_mach_o_xlat_name bfd_mach_o_header_flags_name[] =
126{
127 { "noundefs", BFD_MACH_O_MH_NOUNDEFS },
128 { "incrlink", BFD_MACH_O_MH_INCRLINK },
129 { "dyldlink", BFD_MACH_O_MH_DYLDLINK },
130 { "bindatload", BFD_MACH_O_MH_BINDATLOAD },
131 { "prebound", BFD_MACH_O_MH_PREBOUND },
132 { "split_segs", BFD_MACH_O_MH_SPLIT_SEGS },
133 { "lazy_init", BFD_MACH_O_MH_LAZY_INIT },
134 { "twolevel", BFD_MACH_O_MH_TWOLEVEL },
135 { "force_flat", BFD_MACH_O_MH_FORCE_FLAT },
136 { "nomultidefs", BFD_MACH_O_MH_NOMULTIDEFS },
137 { "nofixprebinding", BFD_MACH_O_MH_NOFIXPREBINDING },
138 { "prebindable", BFD_MACH_O_MH_PREBINDABLE },
139 { "allmodsbound", BFD_MACH_O_MH_ALLMODSBOUND },
140 { "subsections_via_symbols", BFD_MACH_O_MH_SUBSECTIONS_VIA_SYMBOLS },
141 { "canonical", BFD_MACH_O_MH_CANONICAL },
142 { "weak_defines", BFD_MACH_O_MH_WEAK_DEFINES },
143 { "binds_to_weak", BFD_MACH_O_MH_BINDS_TO_WEAK },
144 { "allow_stack_execution", BFD_MACH_O_MH_ALLOW_STACK_EXECUTION },
145 { "root_safe", BFD_MACH_O_MH_ROOT_SAFE },
146 { "setuid_safe", BFD_MACH_O_MH_SETUID_SAFE },
147 { "no_reexported_dylibs", BFD_MACH_O_MH_NO_REEXPORTED_DYLIBS },
148 { "pie", BFD_MACH_O_MH_PIE },
149 { NULL, 0}
150};
151
152static const bfd_mach_o_xlat_name bfd_mach_o_load_command_name[] =
153{
154 { "segment", BFD_MACH_O_LC_SEGMENT},
155 { "symtab", BFD_MACH_O_LC_SYMTAB},
156 { "symseg", BFD_MACH_O_LC_SYMSEG},
157 { "thread", BFD_MACH_O_LC_THREAD},
158 { "unixthread", BFD_MACH_O_LC_UNIXTHREAD},
159 { "loadfvmlib", BFD_MACH_O_LC_LOADFVMLIB},
160 { "idfvmlib", BFD_MACH_O_LC_IDFVMLIB},
161 { "ident", BFD_MACH_O_LC_IDENT},
162 { "fvmfile", BFD_MACH_O_LC_FVMFILE},
163 { "prepage", BFD_MACH_O_LC_PREPAGE},
164 { "dysymtab", BFD_MACH_O_LC_DYSYMTAB},
165 { "load_dylib", BFD_MACH_O_LC_LOAD_DYLIB},
166 { "id_dylib", BFD_MACH_O_LC_ID_DYLIB},
167 { "load_dylinker", BFD_MACH_O_LC_LOAD_DYLINKER},
168 { "id_dylinker", BFD_MACH_O_LC_ID_DYLINKER},
169 { "prebound_dylib", BFD_MACH_O_LC_PREBOUND_DYLIB},
170 { "routines", BFD_MACH_O_LC_ROUTINES},
171 { "sub_framework", BFD_MACH_O_LC_SUB_FRAMEWORK},
172 { "sub_umbrella", BFD_MACH_O_LC_SUB_UMBRELLA},
173 { "sub_client", BFD_MACH_O_LC_SUB_CLIENT},
174 { "sub_library", BFD_MACH_O_LC_SUB_LIBRARY},
175 { "twolevel_hints", BFD_MACH_O_LC_TWOLEVEL_HINTS},
176 { "prebind_cksum", BFD_MACH_O_LC_PREBIND_CKSUM},
177 { "load_weak_dylib", BFD_MACH_O_LC_LOAD_WEAK_DYLIB},
178 { "segment_64", BFD_MACH_O_LC_SEGMENT_64},
179 { "routines_64", BFD_MACH_O_LC_ROUTINES_64},
180 { "uuid", BFD_MACH_O_LC_UUID},
181 { "rpath", BFD_MACH_O_LC_RPATH},
182 { "code_signature", BFD_MACH_O_LC_CODE_SIGNATURE},
183 { "segment_split_info", BFD_MACH_O_LC_SEGMENT_SPLIT_INFO},
184 { "reexport_dylib", BFD_MACH_O_LC_REEXPORT_DYLIB},
185 { "lazy_load_dylib", BFD_MACH_O_LC_LAZY_LOAD_DYLIB},
186 { "encryption_info", BFD_MACH_O_LC_ENCRYPTION_INFO},
187 { "dyld_info", BFD_MACH_O_LC_DYLD_INFO},
188 { "load_upward_lib", BFD_MACH_O_LC_LOAD_UPWARD_DYLIB},
189 { "version_min_macosx", BFD_MACH_O_LC_VERSION_MIN_MACOSX},
190 { "version_min_iphoneos", BFD_MACH_O_LC_VERSION_MIN_IPHONEOS},
191 { "function_starts", BFD_MACH_O_LC_FUNCTION_STARTS},
192 { "dyld_environment", BFD_MACH_O_LC_DYLD_ENVIRONMENT},
1778ad74
TG
193 { "main", BFD_MACH_O_LC_MAIN},
194 { "data_in_code", BFD_MACH_O_LC_DATA_IN_CODE},
195 { "source_version", BFD_MACH_O_LC_SOURCE_VERSION},
196 { "dylib_code_sign_drs", BFD_MACH_O_LC_DYLIB_CODE_SIGN_DRS},
12fa714f
TG
197 { NULL, 0}
198};
199
200static const bfd_mach_o_xlat_name bfd_mach_o_thread_x86_name[] =
201{
202 { "thread_state32", BFD_MACH_O_x86_THREAD_STATE32},
203 { "float_state32", BFD_MACH_O_x86_FLOAT_STATE32},
204 { "exception_state32", BFD_MACH_O_x86_EXCEPTION_STATE32},
205 { "thread_state64", BFD_MACH_O_x86_THREAD_STATE64},
206 { "float_state64", BFD_MACH_O_x86_FLOAT_STATE64},
207 { "exception_state64", BFD_MACH_O_x86_EXCEPTION_STATE64},
208 { "thread_state", BFD_MACH_O_x86_THREAD_STATE},
209 { "float_state", BFD_MACH_O_x86_FLOAT_STATE},
210 { "exception_state", BFD_MACH_O_x86_EXCEPTION_STATE},
211 { "debug_state32", BFD_MACH_O_x86_DEBUG_STATE32},
212 { "debug_state64", BFD_MACH_O_x86_DEBUG_STATE64},
213 { "debug_state", BFD_MACH_O_x86_DEBUG_STATE},
214 { "state_none", BFD_MACH_O_x86_THREAD_STATE_NONE},
215 { NULL, 0 }
216};
217\f
218static void
219bfd_mach_o_print_flags (const bfd_mach_o_xlat_name *table,
220 unsigned long val)
221{
222 int first = 1;
223
224 for (; table->name; table++)
225 {
226 if (table->val & val)
227 {
228 if (!first)
229 printf ("+");
230 printf ("%s", table->name);
231 val &= ~table->val;
232 first = 0;
233 }
234 }
235 if (val)
236 {
237 if (!first)
238 printf ("+");
239 printf ("0x%lx", val);
240 return;
241 }
242 if (first)
243 printf ("-");
244}
245
246static const char *
247bfd_mach_o_get_name_or_null (const bfd_mach_o_xlat_name *table,
248 unsigned long val)
249{
250 for (; table->name; table++)
251 if (table->val == val)
252 return table->name;
253 return NULL;
254}
255
256static const char *
257bfd_mach_o_get_name (const bfd_mach_o_xlat_name *table, unsigned long val)
258{
259 const char *res = bfd_mach_o_get_name_or_null (table, val);
260
261 if (res == NULL)
262 return "*UNKNOWN*";
263 else
264 return res;
265}
266
267static void
268dump_header (bfd *abfd)
269{
270 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
271 bfd_mach_o_header *h = &mdata->header;
272
273 fputs (_("Mach-O header:\n"), stdout);
274 printf (_(" magic : %08lx\n"), h->magic);
275 printf (_(" cputype : %08lx (%s)\n"), h->cputype,
2634e8c8 276 bfd_mach_o_get_name (bfd_mach_o_cpu_name, h->cputype));
12fa714f
TG
277 printf (_(" cpusubtype: %08lx\n"), h->cpusubtype);
278 printf (_(" filetype : %08lx (%s)\n"),
2634e8c8
TG
279 h->filetype,
280 bfd_mach_o_get_name (bfd_mach_o_filetype_name, h->filetype));
12fa714f
TG
281 printf (_(" ncmds : %08lx (%lu)\n"), h->ncmds, h->ncmds);
282 printf (_(" sizeofcmds: %08lx\n"), h->sizeofcmds);
283 printf (_(" flags : %08lx ("), h->flags);
284 bfd_mach_o_print_flags (bfd_mach_o_header_flags_name, h->flags);
285 fputs (_(")\n"), stdout);
286 printf (_(" reserved : %08x\n"), h->reserved);
287}
288
3cc27770
TG
289static void
290disp_segment_prot (unsigned int prot)
291{
292 putchar (prot & BFD_MACH_O_PROT_READ ? 'r' : '-');
293 putchar (prot & BFD_MACH_O_PROT_WRITE ? 'w' : '-');
294 putchar (prot & BFD_MACH_O_PROT_EXECUTE ? 'x' : '-');
295}
296
12fa714f
TG
297static void
298dump_section_map (bfd *abfd)
299{
300 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
301 unsigned int i;
302 unsigned int sec_nbr = 0;
303
304 fputs (_("Segments and Sections:\n"), stdout);
305 fputs (_(" #: Segment name Section name Address\n"), stdout);
306
307 for (i = 0; i < mdata->header.ncmds; i++)
308 {
309 bfd_mach_o_segment_command *seg;
310 bfd_mach_o_section *sec;
311
312 if (mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT
313 && mdata->commands[i].type != BFD_MACH_O_LC_SEGMENT_64)
314 continue;
315
316 seg = &mdata->commands[i].command.segment;
317
318 printf ("[Segment %-16s ", seg->segname);
319 printf_vma (seg->vmaddr);
320 putchar ('-');
321 printf_vma (seg->vmaddr + seg->vmsize - 1);
322 putchar (' ');
3cc27770 323 disp_segment_prot (seg->initprot);
12fa714f
TG
324 printf ("]\n");
325
326 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
327 {
328 printf ("%02u: %-16s %-16s ", ++sec_nbr,
329 sec->segname, sec->sectname);
330 printf_vma (sec->addr);
331 putchar (' ');
332 printf_vma (sec->size);
333 printf (" %08lx\n", sec->flags);
334 }
335 }
336}
337
338static void
167e1c1f 339dump_section_header (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_section *sec)
12fa714f
TG
340{
341 printf (" Section: %-16s %-16s (bfdname: %s)\n",
342 sec->sectname, sec->segname, sec->bfdsection->name);
343 printf (" addr: ");
344 printf_vma (sec->addr);
345 printf (" size: ");
346 printf_vma (sec->size);
347 printf (" offset: ");
348 printf_vma (sec->offset);
349 printf ("\n");
350 printf (" align: %ld", sec->align);
351 printf (" nreloc: %lu reloff: ", sec->nreloc);
352 printf_vma (sec->reloff);
353 printf ("\n");
354 printf (" flags: %08lx (type: %s", sec->flags,
355 bfd_mach_o_get_name (bfd_mach_o_section_type_name,
356 sec->flags & BFD_MACH_O_SECTION_TYPE_MASK));
357 printf (" attr: ");
358 bfd_mach_o_print_flags (bfd_mach_o_section_attribute_name,
359 sec->flags & BFD_MACH_O_SECTION_ATTRIBUTES_MASK);
360 printf (")\n");
361 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
362 {
363 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
364 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
365 case BFD_MACH_O_S_SYMBOL_STUBS:
366 printf (" first indirect sym: %lu", sec->reserved1);
367 printf (" (%u entries)",
368 bfd_mach_o_section_get_nbr_indirect (abfd, sec));
369 break;
370 default:
371 printf (" reserved1: 0x%lx", sec->reserved1);
372 break;
373 }
374 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
375 {
376 case BFD_MACH_O_S_SYMBOL_STUBS:
377 printf (" stub size: %lu", sec->reserved2);
378 break;
379 default:
380 printf (" reserved2: 0x%lx", sec->reserved2);
381 break;
382 }
383 printf (" reserved3: 0x%lx\n", sec->reserved3);
384}
385
386static void
387dump_segment (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
388{
389 bfd_mach_o_segment_command *seg = &cmd->command.segment;
390 bfd_mach_o_section *sec;
391
392 printf (" name: %s\n", *seg->segname ? seg->segname : "*none*");
393 printf (" vmaddr: ");
394 printf_vma (seg->vmaddr);
395 printf (" vmsize: ");
396 printf_vma (seg->vmsize);
397 printf ("\n");
398 printf (" fileoff: ");
399 printf_vma (seg->fileoff);
400 printf (" filesize: ");
401 printf_vma ((bfd_vma)seg->filesize);
402 printf (" endoff: ");
403 printf_vma ((bfd_vma)(seg->fileoff + seg->filesize));
404 printf ("\n");
3cc27770
TG
405 printf (" nsects: %lu", seg->nsects);
406 printf (" flags: %lx", seg->flags);
407 printf (" initprot: ");
408 disp_segment_prot (seg->initprot);
409 printf (" maxprot: ");
410 disp_segment_prot (seg->maxprot);
411 printf ("\n");
12fa714f 412 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
167e1c1f 413 dump_section_header (abfd, sec);
12fa714f
TG
414}
415
416static void
417dump_dysymtab (bfd *abfd, bfd_mach_o_load_command *cmd, bfd_boolean verbose)
418{
419 bfd_mach_o_dysymtab_command *dysymtab = &cmd->command.dysymtab;
420 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
421 unsigned int i;
422
423 printf (" local symbols: idx: %10lu num: %-8lu",
424 dysymtab->ilocalsym, dysymtab->nlocalsym);
425 printf (" (nxtidx: %lu)\n",
426 dysymtab->ilocalsym + dysymtab->nlocalsym);
427 printf (" external symbols: idx: %10lu num: %-8lu",
428 dysymtab->iextdefsym, dysymtab->nextdefsym);
429 printf (" (nxtidx: %lu)\n",
430 dysymtab->iextdefsym + dysymtab->nextdefsym);
431 printf (" undefined symbols: idx: %10lu num: %-8lu",
432 dysymtab->iundefsym, dysymtab->nundefsym);
433 printf (" (nxtidx: %lu)\n",
434 dysymtab->iundefsym + dysymtab->nundefsym);
435 printf (" table of content: off: 0x%08lx num: %-8lu",
436 dysymtab->tocoff, dysymtab->ntoc);
437 printf (" (endoff: 0x%08lx)\n",
438 dysymtab->tocoff + dysymtab->ntoc * BFD_MACH_O_TABLE_OF_CONTENT_SIZE);
439 printf (" module table: off: 0x%08lx num: %-8lu",
440 dysymtab->modtaboff, dysymtab->nmodtab);
441 printf (" (endoff: 0x%08lx)\n",
442 dysymtab->modtaboff + dysymtab->nmodtab
443 * (mdata->header.version == 2 ?
444 BFD_MACH_O_DYLIB_MODULE_64_SIZE : BFD_MACH_O_DYLIB_MODULE_SIZE));
445 printf (" external reference table: off: 0x%08lx num: %-8lu",
446 dysymtab->extrefsymoff, dysymtab->nextrefsyms);
447 printf (" (endoff: 0x%08lx)\n",
448 dysymtab->extrefsymoff
449 + dysymtab->nextrefsyms * BFD_MACH_O_REFERENCE_SIZE);
450 printf (" indirect symbol table: off: 0x%08lx num: %-8lu",
451 dysymtab->indirectsymoff, dysymtab->nindirectsyms);
452 printf (" (endoff: 0x%08lx)\n",
453 dysymtab->indirectsymoff
454 + dysymtab->nindirectsyms * BFD_MACH_O_INDIRECT_SYMBOL_SIZE);
455 printf (" external relocation table: off: 0x%08lx num: %-8lu",
456 dysymtab->extreloff, dysymtab->nextrel);
457 printf (" (endoff: 0x%08lx)\n",
458 dysymtab->extreloff + dysymtab->nextrel * BFD_MACH_O_RELENT_SIZE);
459 printf (" local relocation table: off: 0x%08lx num: %-8lu",
460 dysymtab->locreloff, dysymtab->nlocrel);
461 printf (" (endoff: 0x%08lx)\n",
462 dysymtab->locreloff + dysymtab->nlocrel * BFD_MACH_O_RELENT_SIZE);
463
464 if (!verbose)
465 return;
466
467 if (dysymtab->ntoc > 0
468 || dysymtab->nindirectsyms > 0
469 || dysymtab->nextrefsyms > 0)
470 {
471 /* Try to read the symbols to display the toc or indirect symbols. */
472 bfd_mach_o_read_symtab_symbols (abfd);
473 }
474 else if (dysymtab->nmodtab > 0)
475 {
476 /* Try to read the strtab to display modules name. */
477 bfd_mach_o_read_symtab_strtab (abfd);
478 }
479
480 for (i = 0; i < dysymtab->nmodtab; i++)
481 {
482 bfd_mach_o_dylib_module *module = &dysymtab->dylib_module[i];
483 printf (" module %u:\n", i);
484 printf (" name: %lu", module->module_name_idx);
485 if (mdata->symtab && mdata->symtab->strtab)
486 printf (": %s",
487 mdata->symtab->strtab + module->module_name_idx);
488 printf ("\n");
489 printf (" extdefsym: idx: %8lu num: %lu\n",
490 module->iextdefsym, module->nextdefsym);
491 printf (" refsym: idx: %8lu num: %lu\n",
492 module->irefsym, module->nrefsym);
493 printf (" localsym: idx: %8lu num: %lu\n",
494 module->ilocalsym, module->nlocalsym);
495 printf (" extrel: idx: %8lu num: %lu\n",
496 module->iextrel, module->nextrel);
497 printf (" init: idx: %8u num: %u\n",
498 module->iinit, module->ninit);
499 printf (" term: idx: %8u num: %u\n",
500 module->iterm, module->nterm);
501 printf (" objc_module_info: addr: ");
502 printf_vma (module->objc_module_info_addr);
503 printf (" size: %lu\n", module->objc_module_info_size);
504 }
505
506 if (dysymtab->ntoc > 0)
507 {
508 bfd_mach_o_symtab_command *symtab = mdata->symtab;
509
510 printf (" table of content: (symbol/module)\n");
511 for (i = 0; i < dysymtab->ntoc; i++)
512 {
513 bfd_mach_o_dylib_table_of_content *toc = &dysymtab->dylib_toc[i];
514
515 printf (" %4u: ", i);
516 if (symtab && symtab->symbols && toc->symbol_index < symtab->nsyms)
517 {
518 const char *name = symtab->symbols[toc->symbol_index].symbol.name;
519 printf ("%s (%lu)", name ? name : "*invalid*",
520 toc->symbol_index);
521 }
522 else
523 printf ("%lu", toc->symbol_index);
524
525 printf (" / ");
526 if (symtab && symtab->strtab
527 && toc->module_index < dysymtab->nmodtab)
528 {
529 bfd_mach_o_dylib_module *mod;
530 mod = &dysymtab->dylib_module[toc->module_index];
531 printf ("%s (%lu)",
532 symtab->strtab + mod->module_name_idx,
533 toc->module_index);
534 }
535 else
536 printf ("%lu", toc->module_index);
537
538 printf ("\n");
539 }
540 }
541
542 if (dysymtab->nindirectsyms != 0)
543 {
544 printf (" indirect symbols:\n");
545
546 for (i = 0; i < mdata->nsects; i++)
547 {
548 bfd_mach_o_section *sec = mdata->sections[i];
549 unsigned int j, first, last;
550 bfd_mach_o_symtab_command *symtab = mdata->symtab;
551 bfd_vma addr;
552 bfd_vma entry_size;
553
554 switch (sec->flags & BFD_MACH_O_SECTION_TYPE_MASK)
555 {
556 case BFD_MACH_O_S_NON_LAZY_SYMBOL_POINTERS:
557 case BFD_MACH_O_S_LAZY_SYMBOL_POINTERS:
558 case BFD_MACH_O_S_SYMBOL_STUBS:
559 first = sec->reserved1;
560 last = first + bfd_mach_o_section_get_nbr_indirect (abfd, sec);
561 addr = sec->addr;
562 entry_size = bfd_mach_o_section_get_entry_size (abfd, sec);
563 printf (" for section %s.%s:\n",
564 sec->segname, sec->sectname);
565 for (j = first; j < last; j++)
566 {
567 unsigned int isym = dysymtab->indirect_syms[j];
568
569 printf (" ");
570 printf_vma (addr);
571 printf (" %5u: 0x%08x", j, isym);
572 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_LOCAL)
573 printf (" LOCAL");
574 if (isym & BFD_MACH_O_INDIRECT_SYMBOL_ABS)
575 printf (" ABSOLUTE");
576 if (symtab && symtab->symbols
577 && isym < symtab->nsyms
578 && symtab->symbols[isym].symbol.name)
579 printf (" %s", symtab->symbols[isym].symbol.name);
580 printf ("\n");
581 addr += entry_size;
582 }
583 break;
584 default:
585 break;
586 }
587 }
588 }
589 if (dysymtab->nextrefsyms > 0)
590 {
591 bfd_mach_o_symtab_command *symtab = mdata->symtab;
592
593 printf (" external reference table: (symbol flags)\n");
594 for (i = 0; i < dysymtab->nextrefsyms; i++)
595 {
596 bfd_mach_o_dylib_reference *ref = &dysymtab->ext_refs[i];
597
598 printf (" %4u: %5lu 0x%02lx", i, ref->isym, ref->flags);
599 if (symtab && symtab->symbols
600 && ref->isym < symtab->nsyms
601 && symtab->symbols[ref->isym].symbol.name)
602 printf (" %s", symtab->symbols[ref->isym].symbol.name);
603 printf ("\n");
604 }
605 }
606
607}
608
609static void
610dump_dyld_info (bfd *abfd ATTRIBUTE_UNUSED, bfd_mach_o_load_command *cmd)
611{
612 bfd_mach_o_dyld_info_command *info = &cmd->command.dyld_info;
613
614 printf (" rebase: off: 0x%08x size: %-8u\n",
615 info->rebase_off, info->rebase_size);
616 printf (" bind: off: 0x%08x size: %-8u\n",
617 info->bind_off, info->bind_size);
618 printf (" weak bind: off: 0x%08x size: %-8u\n",
619 info->weak_bind_off, info->weak_bind_size);
620 printf (" lazy bind: off: 0x%08x size: %-8u\n",
621 info->lazy_bind_off, info->lazy_bind_size);
622 printf (" export: off: 0x%08x size: %-8u\n",
623 info->export_off, info->export_size);
624}
625
626static void
627dump_thread (bfd *abfd, bfd_mach_o_load_command *cmd)
628{
629 bfd_mach_o_thread_command *thread = &cmd->command.thread;
630 unsigned int j;
631 bfd_mach_o_backend_data *bed = bfd_mach_o_get_backend_data (abfd);
632 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
633
634 printf (" nflavours: %lu\n", thread->nflavours);
635 for (j = 0; j < thread->nflavours; j++)
636 {
637 bfd_mach_o_thread_flavour *flavour = &thread->flavours[j];
638 const bfd_mach_o_xlat_name *name_table;
639
640 printf (" %2u: flavour: 0x%08lx", j, flavour->flavour);
641 switch (mdata->header.cputype)
642 {
643 case BFD_MACH_O_CPU_TYPE_I386:
644 case BFD_MACH_O_CPU_TYPE_X86_64:
645 name_table = bfd_mach_o_thread_x86_name;
646 break;
647 default:
648 name_table = NULL;
649 break;
650 }
651 if (name_table != NULL)
652 printf (": %s", bfd_mach_o_get_name (name_table, flavour->flavour));
653 putchar ('\n');
654
655 printf (" offset: 0x%08lx size: 0x%08lx\n",
656 flavour->offset, flavour->size);
657 if (bed->_bfd_mach_o_print_thread)
658 {
659 char *buf = xmalloc (flavour->size);
660
2634e8c8
TG
661 if (bfd_seek (abfd, flavour->offset, SEEK_SET) == 0
662 && bfd_bread (buf, flavour->size, abfd) == flavour->size)
12fa714f 663 (*bed->_bfd_mach_o_print_thread)(abfd, flavour, stdout, buf);
2634e8c8 664
12fa714f
TG
665 free (buf);
666 }
667 }
668}
669
2634e8c8
TG
670static const bfd_mach_o_xlat_name bfd_mach_o_cs_magic[] =
671{
672 { "embedded signature", BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE },
673 { "requirement", BFD_MACH_O_CS_MAGIC_REQUIREMENT },
674 { "requirements", BFD_MACH_O_CS_MAGIC_REQUIREMENTS },
675 { "code directory", BFD_MACH_O_CS_MAGIC_CODEDIRECTORY },
676 { "embedded entitlements", BFD_MACH_O_CS_MAGIC_EMBEDDED_ENTITLEMENTS },
677 { "blob wrapper", BFD_MACH_O_CS_MAGIC_BLOB_WRAPPER },
678 { NULL, 0 }
679};
680
681static const bfd_mach_o_xlat_name bfd_mach_o_cs_hash_type[] =
682{
683 { "no-hash", BFD_MACH_O_CS_NO_HASH },
684 { "sha1", BFD_MACH_O_CS_HASH_SHA1 },
685 { "sha256", BFD_MACH_O_CS_HASH_SHA256 },
686 { "skein 160", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_160x256 },
687 { "skein 256", BFD_MACH_O_CS_HASH_PRESTANDARD_SKEIN_256x512 },
688 { NULL, 0 }
689};
690
691static unsigned int
692dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len);
693
694static void
695dump_code_signature_superblob (bfd *abfd ATTRIBUTE_UNUSED,
696 const unsigned char *buf, unsigned int len)
697{
698 unsigned int count;
699 unsigned int i;
700
701 if (len < 12)
702 {
703 printf (_(" [bad block length]\n"));
704 return;
705 }
706 count = bfd_getb32 (buf + 8);
707 printf (_(" %u index entries:\n"), count);
708 if (len < 12 + 8 * count)
709 {
710 printf (_(" [bad block length]\n"));
711 return;
712 }
713 for (i = 0; i < count; i++)
714 {
715 unsigned int type;
716 unsigned int off;
717
718 type = bfd_getb32 (buf + 12 + 8 * i);
719 off = bfd_getb32 (buf + 12 + 8 * i + 4);
720 printf (_(" index entry %u: type: %08x, offset: %08x\n"),
721 i, type, off);
722
723 dump_code_signature_blob (abfd, buf + off, len - off);
724 }
725}
726
727static void
728swap_code_codedirectory_v1_in
729 (const struct mach_o_codesign_codedirectory_external_v1 *src,
730 struct mach_o_codesign_codedirectory_v1 *dst)
731{
732 dst->version = bfd_getb32 (src->version);
733 dst->flags = bfd_getb32 (src->flags);
734 dst->hash_offset = bfd_getb32 (src->hash_offset);
735 dst->ident_offset = bfd_getb32 (src->ident_offset);
736 dst->nbr_special_slots = bfd_getb32 (src->nbr_special_slots);
737 dst->nbr_code_slots = bfd_getb32 (src->nbr_code_slots);
738 dst->code_limit = bfd_getb32 (src->code_limit);
739 dst->hash_size = src->hash_size[0];
740 dst->hash_type = src->hash_type[0];
741 dst->spare1 = src->spare1[0];
742 dst->page_size = src->page_size[0];
743 dst->spare2 = bfd_getb32 (src->spare2);
744}
745
746static void
747hexdump (unsigned int start, unsigned int len,
748 const unsigned char *buf)
749{
750 unsigned int i, j;
751
752 for (i = 0; i < len; i += 16)
753 {
754 printf ("%08x:", start + i);
755 for (j = 0; j < 16; j++)
756 {
757 fputc (j == 8 ? '-' : ' ', stdout);
758 if (i + j < len)
759 printf ("%02x", buf[i + j]);
760 else
761 fputs (" ", stdout);
762 }
763 fputc (' ', stdout);
764 for (j = 0; j < 16; j++)
765 {
766 if (i + j < len)
767 fputc (ISPRINT (buf[i + j]) ? buf[i + j] : '.', stdout);
768 else
769 fputc (' ', stdout);
770 }
771 fputc ('\n', stdout);
772 }
773}
774
775static void
776dump_code_signature_codedirectory (bfd *abfd ATTRIBUTE_UNUSED,
777 const unsigned char *buf, unsigned int len)
778{
779 struct mach_o_codesign_codedirectory_v1 cd;
780 const char *id;
781
782 if (len < sizeof (struct mach_o_codesign_codedirectory_external_v1))
783 {
784 printf (_(" [bad block length]\n"));
785 return;
786 }
787
788 swap_code_codedirectory_v1_in
789 ((const struct mach_o_codesign_codedirectory_external_v1 *) (buf + 8), &cd);
790
791 printf (_(" version: %08x\n"), cd.version);
792 printf (_(" flags: %08x\n"), cd.flags);
793 printf (_(" hash offset: %08x\n"), cd.hash_offset);
794 id = (const char *) buf + cd.ident_offset;
795 printf (_(" ident offset: %08x (- %08x)\n"),
796 cd.ident_offset, cd.ident_offset + (unsigned) strlen (id) + 1);
797 printf (_(" identity: %s\n"), id);
798 printf (_(" nbr special slots: %08x (at offset %08x)\n"),
799 cd.nbr_special_slots,
800 cd.hash_offset - cd.nbr_special_slots * cd.hash_size);
801 printf (_(" nbr code slots: %08x\n"), cd.nbr_code_slots);
802 printf (_(" code limit: %08x\n"), cd.code_limit);
803 printf (_(" hash size: %02x\n"), cd.hash_size);
804 printf (_(" hash type: %02x (%s)\n"),
805 cd.hash_type,
806 bfd_mach_o_get_name (bfd_mach_o_cs_hash_type, cd.hash_type));
807 printf (_(" spare1: %02x\n"), cd.spare1);
808 printf (_(" page size: %02x\n"), cd.page_size);
809 printf (_(" spare2: %08x\n"), cd.spare2);
810 if (cd.version >= 0x20100)
811 printf (_(" scatter offset: %08x\n"),
812 (unsigned) bfd_getb32 (buf + 44));
813}
814
815static unsigned int
816dump_code_signature_blob (bfd *abfd, const unsigned char *buf, unsigned int len)
817{
818 unsigned int magic;
819 unsigned int length;
820
821 if (len < 8)
822 {
823 printf (_(" [truncated block]\n"));
824 return 0;
825 }
826 magic = bfd_getb32 (buf);
827 length = bfd_getb32 (buf + 4);
828 if (magic == 0 || length == 0)
829 return 0;
830
831 printf (_(" magic : %08x (%s)\n"), magic,
832 bfd_mach_o_get_name (bfd_mach_o_cs_magic, magic));
833 printf (_(" length: %08x\n"), length);
834 if (length > len)
835 {
836 printf (_(" [bad block length]\n"));
837 return 0;
838 }
839
840 switch (magic)
841 {
842 case BFD_MACH_O_CS_MAGIC_EMBEDDED_SIGNATURE:
843 dump_code_signature_superblob (abfd, buf, length);
844 break;
845 case BFD_MACH_O_CS_MAGIC_CODEDIRECTORY:
846 dump_code_signature_codedirectory (abfd, buf, length);
847 break;
848 default:
849 hexdump (0, length - 8, buf + 8);
850 break;
851 }
852 return length;
853}
854
855static void
856dump_code_signature (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
857{
858 unsigned char *buf = xmalloc (cmd->datasize);
859 unsigned int off;
860
861 if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
862 || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
863 {
864 non_fatal (_("cannot read code signature data"));
865 free (buf);
866 return;
867 }
868 for (off = 0; off < cmd->datasize;)
869 {
870 unsigned int len;
871
872 len = dump_code_signature_blob (abfd, buf + off, cmd->datasize - off);
873
874 if (len == 0)
875 break;
876 off += len;
877 }
878 free (buf);
879}
880
2128eb39
TG
881static void
882dump_segment_split_info (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
883{
884 unsigned char *buf = xmalloc (cmd->datasize);
885 unsigned char *p;
886 unsigned int len;
887 bfd_vma addr = 0;
888
889 if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
890 || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
891 {
892 non_fatal (_("cannot read segment split info"));
893 free (buf);
894 return;
895 }
896 if (buf[cmd->datasize - 1] != 0)
897 {
898 non_fatal (_("segment split info is not nul terminated"));
899 free (buf);
900 return;
901 }
902
903 switch (buf[0])
904 {
905 case 0:
906 printf (_(" 32 bit pointers:\n"));
907 break;
908 case 1:
909 printf (_(" 64 bit pointers:\n"));
910 break;
911 case 2:
912 printf (_(" PPC hi-16:\n"));
913 break;
914 default:
915 printf (_(" Unhandled location type %u\n"), buf[0]);
916 break;
917 }
918 for (p = buf + 1; *p != 0; p += len)
919 {
920 addr += read_unsigned_leb128 (abfd, p, &len);
921 fputs (" ", stdout);
922 bfd_printf_vma (abfd, addr);
923 putchar ('\n');
924 }
925 free (buf);
926}
927
3cc27770
TG
928static void
929dump_function_starts (bfd *abfd, bfd_mach_o_linkedit_command *cmd)
930{
931 unsigned char *buf = xmalloc (cmd->datasize);
932 unsigned char *end_buf = buf + cmd->datasize;
933 unsigned char *p;
934 bfd_vma addr;
935
936 if (bfd_seek (abfd, cmd->dataoff, SEEK_SET) != 0
937 || bfd_bread (buf, cmd->datasize, abfd) != cmd->datasize)
938 {
939 non_fatal (_("cannot read function starts"));
940 free (buf);
941 return;
942 }
943
944 /* Function starts are delta encoded, starting from the base address. */
945 addr = bfd_mach_o_get_base_address (abfd);
946
947 for (p = buf; ;)
948 {
949 bfd_vma delta = 0;
950 unsigned int shift = 0;
951
952 if (*p == 0 || p == end_buf)
953 break;
954 while (1)
955 {
956 unsigned char b = *p++;
957
958 delta |= (b & 0x7f) << shift;
959 if ((b & 0x80) == 0)
960 break;
961 if (p == end_buf)
962 {
963 fputs (" [truncated]\n", stdout);
964 break;
965 }
966 shift += 7;
967 }
968
969 addr += delta;
970 fputs (" ", stdout);
971 bfd_printf_vma (abfd, addr);
972 putchar ('\n');
973 }
974 free (buf);
975}
976
12fa714f
TG
977static void
978dump_load_command (bfd *abfd, bfd_mach_o_load_command *cmd,
979 bfd_boolean verbose)
980{
981 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
982 const char *cmd_name;
983
984 cmd_name = bfd_mach_o_get_name_or_null
985 (bfd_mach_o_load_command_name, cmd->type);
986 printf ("Load command ");
987 if (cmd_name == NULL)
988 printf ("0x%02x:", cmd->type);
989 else
990 printf ("%s:", cmd_name);
991
992 switch (cmd->type)
993 {
994 case BFD_MACH_O_LC_SEGMENT:
995 case BFD_MACH_O_LC_SEGMENT_64:
996 dump_segment (abfd, cmd);
997 break;
998 case BFD_MACH_O_LC_UUID:
999 {
1000 bfd_mach_o_uuid_command *uuid = &cmd->command.uuid;
1001 unsigned int j;
1002
1003 for (j = 0; j < sizeof (uuid->uuid); j ++)
1004 printf (" %02x", uuid->uuid[j]);
1005 putchar ('\n');
1006 }
1007 break;
1008 case BFD_MACH_O_LC_LOAD_DYLIB:
fbe383b9 1009 case BFD_MACH_O_LC_LAZY_LOAD_DYLIB:
12fa714f
TG
1010 case BFD_MACH_O_LC_LOAD_WEAK_DYLIB:
1011 case BFD_MACH_O_LC_REEXPORT_DYLIB:
1012 case BFD_MACH_O_LC_ID_DYLIB:
1013 case BFD_MACH_O_LC_LOAD_UPWARD_DYLIB:
1014 {
1015 bfd_mach_o_dylib_command *dylib = &cmd->command.dylib;
1016 printf (" %s\n", dylib->name_str);
1017 printf (" time stamp: 0x%08lx\n",
1018 dylib->timestamp);
1019 printf (" current version: 0x%08lx\n",
1020 dylib->current_version);
1021 printf (" comptibility version: 0x%08lx\n",
1022 dylib->compatibility_version);
12fa714f 1023 }
9f4a5bd1 1024 break;
12fa714f
TG
1025 case BFD_MACH_O_LC_LOAD_DYLINKER:
1026 case BFD_MACH_O_LC_ID_DYLINKER:
1027 printf (" %s\n", cmd->command.dylinker.name_str);
1028 break;
1029 case BFD_MACH_O_LC_SYMTAB:
1030 {
1031 bfd_mach_o_symtab_command *symtab = &cmd->command.symtab;
1032 printf ("\n"
1033 " symoff: 0x%08x nsyms: %8u (endoff: 0x%08x)\n",
1034 symtab->symoff, symtab->nsyms,
1035 symtab->symoff + symtab->nsyms
1036 * (mdata->header.version == 2
1037 ? BFD_MACH_O_NLIST_64_SIZE : BFD_MACH_O_NLIST_SIZE));
1038 printf (" stroff: 0x%08x strsize: %8u (endoff: 0x%08x)\n",
1039 symtab->stroff, symtab->strsize,
1040 symtab->stroff + symtab->strsize);
1041 break;
1042 }
1043 case BFD_MACH_O_LC_DYSYMTAB:
1044 putchar ('\n');
1045 dump_dysymtab (abfd, cmd, verbose);
1046 break;
9f4a5bd1
TG
1047 case BFD_MACH_O_LC_LOADFVMLIB:
1048 case BFD_MACH_O_LC_IDFVMLIB:
1049 {
1050 bfd_mach_o_fvmlib_command *fvmlib = &cmd->command.fvmlib;
1051 printf (" %s\n", fvmlib->name_str);
1052 printf (" minor version: 0x%08x\n", fvmlib->minor_version);
1053 printf (" header address: 0x%08x\n", fvmlib->header_addr);
1054 }
1055 break;
12fa714f
TG
1056 case BFD_MACH_O_LC_CODE_SIGNATURE:
1057 case BFD_MACH_O_LC_SEGMENT_SPLIT_INFO:
1058 case BFD_MACH_O_LC_FUNCTION_STARTS:
1059 {
1060 bfd_mach_o_linkedit_command *linkedit = &cmd->command.linkedit;
1061 printf
1062 ("\n"
1063 " dataoff: 0x%08lx datasize: 0x%08lx (endoff: 0x%08lx)\n",
1064 linkedit->dataoff, linkedit->datasize,
1065 linkedit->dataoff + linkedit->datasize);
2634e8c8
TG
1066
1067 if (verbose && cmd->type == BFD_MACH_O_LC_CODE_SIGNATURE)
1068 dump_code_signature (abfd, linkedit);
2128eb39
TG
1069 else if (verbose && cmd->type == BFD_MACH_O_LC_SEGMENT_SPLIT_INFO)
1070 dump_segment_split_info (abfd, linkedit);
3cc27770
TG
1071 else if (verbose && cmd->type == BFD_MACH_O_LC_FUNCTION_STARTS)
1072 dump_function_starts (abfd, linkedit);
12fa714f
TG
1073 break;
1074 }
1075 case BFD_MACH_O_LC_SUB_FRAMEWORK:
1076 case BFD_MACH_O_LC_SUB_UMBRELLA:
1077 case BFD_MACH_O_LC_SUB_LIBRARY:
1078 case BFD_MACH_O_LC_SUB_CLIENT:
1079 case BFD_MACH_O_LC_RPATH:
1080 {
1081 bfd_mach_o_str_command *str = &cmd->command.str;
1082 printf (" %s\n", str->str);
1083 break;
1084 }
1085 case BFD_MACH_O_LC_THREAD:
1086 case BFD_MACH_O_LC_UNIXTHREAD:
1087 dump_thread (abfd, cmd);
1088 break;
fc55a902
TG
1089 case BFD_MACH_O_LC_ENCRYPTION_INFO:
1090 {
1091 bfd_mach_o_encryption_info_command *cryp =
1092 &cmd->command.encryption_info;
1093 printf
1094 ("\n"
1095 " cryptoff: 0x%08x cryptsize: 0x%08x (endoff 0x%08x)"
1096 " cryptid: %u\n",
1097 cryp->cryptoff, cryp->cryptsize,
1098 cryp->cryptoff + cryp->cryptsize,
1099 cryp->cryptid);
1100 }
1101 break;
12fa714f
TG
1102 case BFD_MACH_O_LC_DYLD_INFO:
1103 putchar ('\n');
1104 dump_dyld_info (abfd, cmd);
1105 break;
1106 case BFD_MACH_O_LC_VERSION_MIN_MACOSX:
1107 case BFD_MACH_O_LC_VERSION_MIN_IPHONEOS:
1108 {
1109 bfd_mach_o_version_min_command *ver = &cmd->command.version_min;
1110
1111 printf (" %u.%u.%u\n", ver->rel, ver->maj, ver->min);
1112 }
1113 break;
1778ad74
TG
1114 case BFD_MACH_O_LC_SOURCE_VERSION:
1115 {
1116 bfd_mach_o_source_version_command *version =
1117 &cmd->command.source_version;
1118 printf ("\n"
1119 " version a.b.c.d.e: %u.%u.%u.%u.%u\n",
1120 version->a, version->b, version->c, version->d, version->e);
1121 break;
1122 }
1123 case BFD_MACH_O_LC_MAIN:
1124 {
1125 bfd_mach_o_main_command *entry = &cmd->command.main;
1126 printf ("\n"
1127 " entry offset: ");
1128 printf_vma (entry->entryoff);
1129 printf ("\n"
1130 " stack size: ");
1131 printf_vma (entry->stacksize);
1132 printf ("\n");
1133 break;
1134 }
12fa714f
TG
1135 default:
1136 putchar ('\n');
1137 printf (" offset: 0x%08lx\n", (unsigned long)cmd->offset);
1138 printf (" size: 0x%08lx\n", (unsigned long)cmd->len);
1139 break;
1140 }
1141 putchar ('\n');
1142}
1143
1144static void
1145dump_load_commands (bfd *abfd, unsigned int cmd32, unsigned int cmd64)
1146{
1147 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1148 unsigned int i;
1149
1150 for (i = 0; i < mdata->header.ncmds; i++)
1151 {
1152 bfd_mach_o_load_command *cmd = &mdata->commands[i];
1153
1154 if (cmd32 == 0)
1155 dump_load_command (abfd, cmd, FALSE);
1156 else if (cmd->type == cmd32 || cmd->type == cmd64)
1157 dump_load_command (abfd, cmd, TRUE);
1158 }
1159}
1160
167e1c1f
TG
1161static const char * const unwind_x86_64_regs[] =
1162 {"", "rbx", "r12", "r13", "r14", "r15", "rbp", "???" };
1163
1164static const char * const unwind_x86_regs[] =
1165 {"", "ebx", "ecx", "edx", "edi", "edi", "ebp", "???" };
1166
1167/* Dump x86 or x86-64 compact unwind encoding. Works for both architecture,
1168 as the encoding is the same (but not register names). */
1169
1170static void
1171dump_unwind_encoding_x86 (unsigned int encoding, unsigned int sz,
1172 const char * const regs_name[])
1173{
1174 unsigned int mode;
1175
1176 mode = encoding & MACH_O_UNWIND_X86_64_MODE_MASK;
1177 switch (mode)
1178 {
1179 case MACH_O_UNWIND_X86_64_MODE_RBP_FRAME:
1180 {
1181 unsigned int regs;
1182 char pfx = sz == 8 ? 'R' : 'E';
1183
1184 regs = encoding & MACH_O_UNWIND_X86_64_RBP_FRAME_REGSITERS;
1185 printf (" %cSP frame", pfx);
1186 if (regs != 0)
1187 {
1188 unsigned int offset;
1189 int i;
1190
1191 offset = (encoding & MACH_O_UNWIND_X86_64_RBP_FRAME_OFFSET) >> 16;
1192 printf (" at %cBP-%u:", pfx, offset * sz);
1193 for (i = 0; i < 5; i++)
1194 {
1195 unsigned int reg = (regs >> (i * 3)) & 0x7;
1196 if (reg != MACH_O_UNWIND_X86_64_REG_NONE)
1197 printf (" %s", regs_name[reg]);
1198 }
1199 }
1200 }
1201 break;
1202 case MACH_O_UNWIND_X86_64_MODE_STACK_IMMD:
1203 case MACH_O_UNWIND_X86_64_MODE_STACK_IND:
1204 {
1205 unsigned int stack_size;
1206 unsigned int reg_count;
1207 unsigned int reg_perm;
1208 unsigned int regs[6];
1209 int i, j;
1210
1211 printf (" frameless");
1212 stack_size =
1213 (encoding & MACH_O_UNWIND_X86_64_FRAMELESS_STACK_SIZE) >> 16;
1214 reg_count =
1215 (encoding & MACH_O_UNWIND_X86_64_FRAMELESS_REG_COUNT) >> 10;
1216 reg_perm = encoding & MACH_O_UNWIND_X86_64_FRAMELESS_REG_PERMUTATION;
1217
1218 if (mode == MACH_O_UNWIND_X86_64_MODE_STACK_IMMD)
1219 printf (" size: 0x%03x", stack_size * sz);
1220 else
1221 {
1222 unsigned int stack_adj;
1223
1224 stack_adj =
1225 (encoding & MACH_O_UNWIND_X86_64_FRAMELESS_STACK_ADJUST) >> 13;
aa9fa1e2 1226 printf (" size at 0x%03x + 0x%02x", stack_size, stack_adj * sz);
167e1c1f
TG
1227 }
1228 /* Registers are coded using arithmetic compression: the register
1229 is indexed in range 0-6, the second in range 0-5, the third in
1230 range 0-4, etc. Already used registers are removed in next
1231 ranges. */
1232#define DO_PERM(R, NUM) R = reg_perm / NUM; reg_perm -= R * NUM
1233 switch (reg_count)
1234 {
1235 case 6:
1236 case 5:
1237 DO_PERM (regs[0], 120);
1238 DO_PERM (regs[1], 24);
1239 DO_PERM (regs[2], 6);
1240 DO_PERM (regs[3], 2);
1241 DO_PERM (regs[4], 1);
1242 regs[5] = 0; /* Not used if reg_count = 5. */
1243 break;
1244 case 4:
1245 DO_PERM (regs[0], 60);
1246 DO_PERM (regs[1], 12);
1247 DO_PERM (regs[2], 3);
1248 DO_PERM (regs[3], 1);
1249 break;
1250 case 3:
1251 DO_PERM (regs[0], 20);
1252 DO_PERM (regs[1], 4);
1253 DO_PERM (regs[2], 1);
1254 break;
1255 case 2:
1256 DO_PERM (regs[0], 5);
1257 DO_PERM (regs[1], 1);
1258 break;
1259 case 1:
1260 DO_PERM (regs[0], 1);
1261 break;
1262 case 0:
1263 break;
1264 default:
1265 printf (" [bad reg count]");
1266 return;
1267 }
1268#undef DO_PERM
1269 /* Renumber. */
1270 for (i = reg_count - 1; i >= 0; i--)
1271 {
1272 unsigned int inc = 1;
1273 for (j = 0; j < i; j++)
1274 if (regs[i] >= regs[j])
1275 inc++;
1276 regs[i] += inc;
1277 }
1278 /* Display. */
1279 for (i = 0; i < (int) reg_count; i++)
1280 printf (" %s", regs_name[regs[i]]);
1281 }
1282 break;
1283 case MACH_O_UNWIND_X86_64_MODE_DWARF:
1284 printf (" Dwarf offset: 0x%06x",
1285 encoding & MACH_O_UNWIND_X86_64_DWARF_SECTION_OFFSET);
1286 break;
1287 default:
1288 printf (" [unhandled mode]");
1289 break;
1290 }
1291}
1292
1293static void
1294dump_unwind_encoding (bfd_mach_o_data_struct *mdata, unsigned int encoding)
1295{
1296 printf ("0x%08x", encoding);
1297 if (encoding == 0)
1298 return;
1299
1300 switch (mdata->header.cputype)
1301 {
1302 case BFD_MACH_O_CPU_TYPE_X86_64:
1303 dump_unwind_encoding_x86 (encoding, 8, unwind_x86_64_regs);
1304 break;
1305 case BFD_MACH_O_CPU_TYPE_I386:
1306 dump_unwind_encoding_x86 (encoding, 4, unwind_x86_regs);
1307 break;
1308 default:
1309 printf (" [unhandled cpu]");
1310 break;
1311 }
1312 if (encoding & MACH_O_UNWIND_HAS_LSDA)
1313 printf (" LSDA");
1314 if (encoding & MACH_O_UNWIND_PERSONALITY_MASK)
1315 printf (" PERS(%u)",
1316 ((encoding & MACH_O_UNWIND_PERSONALITY_MASK)
1317 >> MACH_O_UNWIND_PERSONALITY_SHIFT));
1318}
1319
1320static void
1321dump_obj_compact_unwind (bfd *abfd,
1322 const unsigned char *content, bfd_size_type size)
1323{
1324 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1325 int is_64 = mdata->header.version == 2;
1326 const unsigned char *p;
1327
3cc27770 1328 printf ("Compact unwind info:\n");
167e1c1f
TG
1329 printf (" start length personality lsda\n");
1330
1331 if (is_64)
1332 {
1333 struct mach_o_compact_unwind_64 *e =
1334 (struct mach_o_compact_unwind_64 *) content;
1335
1336 for (p = content; p < content + size; p += sizeof (*e))
1337 {
1338 e = (struct mach_o_compact_unwind_64 *) p;
1339
1340 putchar (' ');
1341 fprintf_vma (stdout, bfd_get_64 (abfd, e->start));
1342 printf (" %08lx", bfd_get_32 (abfd, e->length));
1343 putchar (' ');
1344 fprintf_vma (stdout, bfd_get_64 (abfd, e->personnality));
1345 putchar (' ');
1346 fprintf_vma (stdout, bfd_get_64 (abfd, e->lsda));
1347 putchar ('\n');
1348
1349 printf (" encoding: ");
1350 dump_unwind_encoding (mdata, bfd_get_32 (abfd, e->encoding));
1351 putchar ('\n');
1352 }
1353 }
1354 else
1355 {
1356 printf ("unhandled\n");
1357 }
1358}
1359
1360static void
1361dump_exe_compact_unwind (bfd *abfd,
1362 const unsigned char *content, bfd_size_type size)
1363{
1364 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1365 struct mach_o_unwind_info_header *hdr;
1366 unsigned int version;
1367 unsigned int encodings_offset;
1368 unsigned int encodings_count;
1369 unsigned int personality_offset;
1370 unsigned int personality_count;
1371 unsigned int index_offset;
1372 unsigned int index_count;
1373 struct mach_o_unwind_index_entry *index_entry;
1374 unsigned int i;
1375
1376 /* The header. */
3cc27770 1377 printf ("Compact unwind info:\n");
167e1c1f
TG
1378
1379 hdr = (struct mach_o_unwind_info_header *) content;
1380 if (size < sizeof (*hdr))
1381 {
1382 printf (" truncated!\n");
1383 return;
1384 }
1385
1386 version = bfd_get_32 (abfd, hdr->version);
1387 if (version != MACH_O_UNWIND_SECTION_VERSION)
1388 {
1389 printf (" unknown version: %u\n", version);
1390 return;
1391 }
1392 encodings_offset = bfd_get_32 (abfd, hdr->encodings_array_offset);
1393 encodings_count = bfd_get_32 (abfd, hdr->encodings_array_count);
1394 personality_offset = bfd_get_32 (abfd, hdr->personality_array_offset);
1395 personality_count = bfd_get_32 (abfd, hdr->personality_array_count);
1396 index_offset = bfd_get_32 (abfd, hdr->index_offset);
1397 index_count = bfd_get_32 (abfd, hdr->index_count);
1398 printf (" %u encodings, %u personalities, %u level-1 indexes:\n",
1399 encodings_count, personality_count, index_count);
1400
1401 /* Level-1 index. */
1402 printf (" idx function level2 off lsda off\n");
1403
1404 index_entry = (struct mach_o_unwind_index_entry *) (content + index_offset);
1405 for (i = 0; i < index_count; i++)
1406 {
1407 unsigned int func_offset;
1408 unsigned int level2_offset;
1409 unsigned int lsda_offset;
1410
1411 func_offset = bfd_get_32 (abfd, index_entry->function_offset);
1412 level2_offset = bfd_get_32 (abfd, index_entry->second_level_offset);
1413 lsda_offset = bfd_get_32 (abfd, index_entry->lsda_index_offset);
1414 printf (" %3u 0x%08x 0x%08x 0x%08x\n",
1415 i, func_offset, level2_offset, lsda_offset);
1416 index_entry++;
1417 }
1418
1419 /* Level-1 index. */
1420 index_entry = (struct mach_o_unwind_index_entry *) (content + index_offset);
1421 for (i = 0; i < index_count; i++)
1422 {
1423 unsigned int func_offset;
1424 unsigned int level2_offset;
1425 const unsigned char *level2;
1426 unsigned int kind;
1427
167e1c1f
TG
1428 func_offset = bfd_get_32 (abfd, index_entry->function_offset);
1429 level2_offset = bfd_get_32 (abfd, index_entry->second_level_offset);
1430
aa9fa1e2
TG
1431 /* No level-2 for this index (should be the last index). */
1432 if (level2_offset == 0)
1433 continue;
1434
167e1c1f
TG
1435 level2 = content + level2_offset;
1436 kind = bfd_get_32 (abfd, level2);
1437 switch (kind)
1438 {
1439 case MACH_O_UNWIND_SECOND_LEVEL_COMPRESSED:
1440 {
1441 struct mach_o_unwind_compressed_second_level_page_header *l2;
1442 unsigned int entry_offset;
1443 unsigned int entry_count;
1444 unsigned int l2_encodings_offset;
1445 unsigned int l2_encodings_count;
1446 const unsigned char *en;
1447 unsigned int j;
1448
1449 l2 = (struct mach_o_unwind_compressed_second_level_page_header *)
1450 level2;
1451 entry_offset = bfd_get_16 (abfd, l2->entry_page_offset);
1452 entry_count = bfd_get_16 (abfd, l2->entry_count);
1453 l2_encodings_offset = bfd_get_16 (abfd, l2->encodings_offset);
1454 l2_encodings_count = bfd_get_16 (abfd, l2->encodings_count);
1455
1456 printf (" index %2u: compressed second level: "
1457 "%u entries, %u encodings (at 0x%08x)\n",
1458 i, entry_count, l2_encodings_count, l2_encodings_offset);
1459 printf (" # function eidx encoding\n");
1460
1461 en = level2 + entry_offset;
1462 for (j = 0; j < entry_count; j++)
1463 {
1464 unsigned int entry;
1465 unsigned int en_func;
1466 unsigned int enc_idx;
1467 unsigned int encoding;
1468 const unsigned char *enc_addr;
1469
1470 entry = bfd_get_32 (abfd, en);
1471 en_func =
1472 MACH_O_UNWIND_INFO_COMPRESSED_ENTRY_FUNC_OFFSET (entry);
1473 enc_idx =
1474 MACH_O_UNWIND_INFO_COMPRESSED_ENTRY_ENCODING_INDEX (entry);
1475 if (enc_idx < encodings_count)
1476 enc_addr = content + encodings_offset
1477 + 4 * enc_idx;
1478 else
1479 enc_addr = level2 + l2_encodings_offset
1480 + 4 * (enc_idx - encodings_count);
1481 encoding = bfd_get_32 (abfd, enc_addr);
1482
1483 printf (" %-4u 0x%08x [%3u] ", j,
1484 func_offset + en_func, enc_idx);
1485 dump_unwind_encoding (mdata, encoding);
1486 putchar ('\n');
1487
1488 en += 4;
1489 }
1490 }
1491 break;
1492
1493 case MACH_O_UNWIND_SECOND_LEVEL_REGULAR:
1494 {
1495 struct mach_o_unwind_regular_second_level_page_header *l2;
1496 struct mach_o_unwind_regular_second_level_entry *en;
1497 unsigned int entry_offset;
1498 unsigned int entry_count;
1499 unsigned int j;
1500
1501 l2 = (struct mach_o_unwind_regular_second_level_page_header *)
1502 level2;
1503
1504 entry_offset = bfd_get_16 (abfd, l2->entry_page_offset);
1505 entry_count = bfd_get_16 (abfd, l2->entry_count);
1506 printf (" index %2u: regular level 2 at 0x%04x, %u entries\n",
1507 i, entry_offset, entry_count);
1508 printf (" # function encoding\n");
1509
1510 en = (struct mach_o_unwind_regular_second_level_entry *)
1511 (level2 + entry_offset);
1512 for (j = 0; j < entry_count; j++)
1513 {
1514 unsigned int en_func;
1515 unsigned int encoding;
1516
1517 en_func = bfd_get_32 (abfd, en->function_offset);
1518 encoding = bfd_get_32 (abfd, en->encoding);
1519 printf (" %-4u 0x%08x ", j, en_func);
1520 dump_unwind_encoding (mdata, encoding);
1521 putchar ('\n');
1522 en++;
1523 }
1524 }
1525 break;
1526
1527 default:
1528 printf (" index %2u: unhandled second level format (%u)\n",
1529 i, kind);
1530 break;
1531 }
1532
1533 {
1534 struct mach_o_unwind_lsda_index_entry *lsda;
1535 unsigned int lsda_offset;
1536 unsigned int next_lsda_offset;
1537 unsigned int nbr_lsda;
1538 unsigned int j;
1539
1540 lsda_offset = bfd_get_32 (abfd, index_entry->lsda_index_offset);
1541 next_lsda_offset = bfd_get_32 (abfd, index_entry[1].lsda_index_offset);
1542 lsda = (struct mach_o_unwind_lsda_index_entry *)
1543 (content + lsda_offset);
1544 nbr_lsda = (next_lsda_offset - lsda_offset) / sizeof (*lsda);
1545 for (j = 0; j < nbr_lsda; j++)
1546 {
aa9fa1e2 1547 printf (" lsda %3u: function 0x%08x lsda 0x%08x\n",
167e1c1f
TG
1548 j, (unsigned int) bfd_get_32 (abfd, lsda->function_offset),
1549 (unsigned int) bfd_get_32 (abfd, lsda->lsda_offset));
1550 lsda++;
1551 }
1552 }
1553 index_entry++;
1554 }
1555}
1556
1557static void
1558dump_section_content (bfd *abfd,
1559 const char *segname, const char *sectname,
1560 void (*dump)(bfd*, const unsigned char*, bfd_size_type))
1561{
1562 bfd_mach_o_data_struct *mdata = bfd_mach_o_get_data (abfd);
1563 unsigned int i;
1564
1565 for (i = 0; i < mdata->header.ncmds; i++)
1566 {
1567 bfd_mach_o_load_command *cmd = &mdata->commands[i];
1568 if (cmd->type == BFD_MACH_O_LC_SEGMENT
1569 || cmd->type == BFD_MACH_O_LC_SEGMENT_64)
1570 {
1571 bfd_mach_o_segment_command *seg = &cmd->command.segment;
1572 bfd_mach_o_section *sec;
1573 for (sec = seg->sect_head; sec != NULL; sec = sec->next)
1574 if (strcmp (sec->segname, segname) == 0
1575 && strcmp (sec->sectname, sectname) == 0)
1576 {
1577 bfd_size_type size;
1578 asection *bfdsec = sec->bfdsection;
1579 unsigned char *content;
1580
1581 size = bfd_get_section_size (bfdsec);
1582 content = (unsigned char *) xmalloc (size);
1583 bfd_get_section_contents (abfd, bfdsec, content, 0, size);
1584
1585 (*dump)(abfd, content, size);
1586
1587 free (content);
1588 }
1589 }
1590 }
1591}
1592
12fa714f
TG
1593/* Dump ABFD (according to the options[] array). */
1594
1595static void
1596mach_o_dump (bfd *abfd)
1597{
1598 if (options[OPT_HEADER].selected)
1599 dump_header (abfd);
1600 if (options[OPT_SECTION].selected)
1601 dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT, BFD_MACH_O_LC_SEGMENT_64);
1602 if (options[OPT_MAP].selected)
1603 dump_section_map (abfd);
1604 if (options[OPT_LOAD].selected)
1605 dump_load_commands (abfd, 0, 0);
1606 if (options[OPT_DYSYMTAB].selected)
1607 dump_load_commands (abfd, BFD_MACH_O_LC_DYSYMTAB, 0);
2634e8c8
TG
1608 if (options[OPT_CODESIGN].selected)
1609 dump_load_commands (abfd, BFD_MACH_O_LC_CODE_SIGNATURE, 0);
2128eb39
TG
1610 if (options[OPT_SEG_SPLIT_INFO].selected)
1611 dump_load_commands (abfd, BFD_MACH_O_LC_SEGMENT_SPLIT_INFO, 0);
3cc27770
TG
1612 if (options[OPT_FUNCTION_STARTS].selected)
1613 dump_load_commands (abfd, BFD_MACH_O_LC_FUNCTION_STARTS, 0);
167e1c1f
TG
1614 if (options[OPT_COMPACT_UNWIND].selected)
1615 {
1616 dump_section_content (abfd, "__LD", "__compact_unwind",
1617 dump_obj_compact_unwind);
1618 dump_section_content (abfd, "__TEXT", "__unwind_info",
1619 dump_exe_compact_unwind);
1620 }
12fa714f
TG
1621}
1622
1623/* Vector for Mach-O. */
1624
1625const struct objdump_private_desc objdump_private_desc_mach_o =
1626 {
1627 mach_o_help,
1628 mach_o_filter,
1629 mach_o_dump,
1630 options
1631 };
This page took 0.217665 seconds and 4 git commands to generate.